adding autoFocus to stateful components. getting global keys working

master
Dustin Swan 3 weeks ago
parent 244126ee9e
commit 30234875fe
Signed by: dustinswan
GPG Key ID: 30D46587E2100467

@ -84,6 +84,7 @@ findCursorPos = text clickX scrollOffset inputPadding \
textInput = config \ ui.stateful { textInput = config \ ui.stateful {
key = config.key, key = config.key,
focusable = True, focusable = True,
autoFocus = config.initialFocus,
# init : State # init : State
init = { init = {
@ -95,7 +96,7 @@ textInput = config \ ui.stateful {
# update : State \ Event \ State # update : State \ Event \ State
update = state event \ event update = state event \ event
| Key { key = c, printable = True } \ | Key { key = c, printable = True, meta = False, ctrl = False } \
newText = insertChar state.text state.cursorPos c; newText = insertChar state.text state.cursorPos c;
newCursorPos = state.cursorPos + 1; newCursorPos = state.cursorPos + 1;
newScroll = calcScrollOffset newText newCursorPos state.scrollOffset config.w; newScroll = calcScrollOffset newText newCursorPos state.scrollOffset config.w;

@ -67,11 +67,14 @@ export function runAppCompiled(app: App, canvas: HTMLCanvasElement, rt: any) {
} }
} }
function expandStateful(ui: UIValue, path: number[]): UIValue { function expandStateful(ui: UIValue, path: number[], renderedKeys: Set<string>): UIValue {
switch (ui.kind) { switch (ui.kind) {
case 'stateful': { case 'stateful': {
const fullKey = [...path, ui.key].join('.'); const fullKey = [...path, ui.key].join('.');
renderedKeys.add(fullKey);
let instance = componentInstances.get(fullKey); let instance = componentInstances.get(fullKey);
const isNew = !instance;
if (!instance) { if (!instance) {
instance = { instance = {
@ -86,6 +89,10 @@ export function runAppCompiled(app: App, canvas: HTMLCanvasElement, rt: any) {
instance.view = ui.view; instance.view = ui.view;
} }
if (ui.autoFocus && isNew) {
setFocus(fullKey);
}
const viewResult = instance.view(instance.state); const viewResult = instance.view(instance.state);
let viewUI = valueToUI(viewResult); let viewUI = valueToUI(viewResult);
@ -96,7 +103,7 @@ export function runAppCompiled(app: App, canvas: HTMLCanvasElement, rt: any) {
event: { _tag: 'FocusAndClick', _0: fullKey } event: { _tag: 'FocusAndClick', _0: fullKey }
}; };
} }
return expandStateful(viewUI, path); return expandStateful(viewUI, path, renderedKeys);
} }
case 'stack': case 'stack':
@ -105,7 +112,7 @@ export function runAppCompiled(app: App, canvas: HTMLCanvasElement, rt: any) {
return { return {
...ui, ...ui,
children: ui.children.map((child: UIValue, i: number) => children: ui.children.map((child: UIValue, i: number) =>
expandStateful(child, [...path, i]) expandStateful(child, [...path, i], renderedKeys)
) )
} }
} }
@ -117,7 +124,7 @@ export function runAppCompiled(app: App, canvas: HTMLCanvasElement, rt: any) {
case 'clip': { case 'clip': {
return { return {
...ui, ...ui,
child: expandStateful((ui as any).child, [...path, 0]) child: expandStateful((ui as any).child, [...path, 0], renderedKeys)
}; };
} }
@ -130,11 +137,17 @@ export function runAppCompiled(app: App, canvas: HTMLCanvasElement, rt: any) {
function rerender() { function rerender() {
const viewport = { width: window.innerWidth, height: window.innerHeight }; const viewport = { width: window.innerWidth, height: window.innerHeight };
const renderedKeys = new Set<string>();
try { try {
const uiValue = app.view(state)(viewport); const uiValue = app.view(state)(viewport);
const ui = valueToUI(uiValue); const ui = valueToUI(uiValue);
const expandedUI = expandStateful(ui, []); const expandedUI = expandStateful(ui, [], renderedKeys);
if (focusedComponentKey && !renderedKeys.has(focusedComponentKey)) {
focusedComponentKey = null;
}
render(expandedUI, canvas); render(expandedUI, canvas);
} catch (error) { } catch (error) {
console.error('Render error:', error); console.error('Render error:', error);

@ -85,6 +85,7 @@ export function valueToUI(value: any): any {
kind: 'stateful', kind: 'stateful',
key: value.key, key: value.key,
focusable: value.focusable, focusable: value.focusable,
autoFocus: value.autoFocus,
init: value.init, init: value.init,
update: value.update, update: value.update,
view: value.view, view: value.view,

Loading…
Cancel
Save