Trying to make a text input. this shit is hard

master
Dustin Swan 3 days ago
parent fadf59c6aa
commit a9e10b3123
Signed by: dustinswan
GPG Key ID: 30D46587E2100467

@ -25,6 +25,7 @@ console.log(ast);
const env: Env = new Map(Object.entries(builtins));
const appRecord = evaluate(ast, env);
console.log("appRecord", appRecord);
if (appRecord.kind !== 'record')
throw new Error('Expected record');

@ -1,78 +1,48 @@
# Helpers
insertChar = text pos char \
before = slice text 0 pos;
after = slice text pos (len text);
before & char & after;
deleteChar = text pos \
(pos == 0
| True \ text
routeKeyToFocused = state event \
(state.focusedInput == "email"
| True \
newInputState = textInput2.update state.email event;
state.{ email = newInputState }
| False \
(before = slice text 0 (pos - 1);
after = slice text pos (len text);
before & after));
# test app
newInputState = textInput2.update state.password event;
state.{ password = newInputState });
init = {
text = "hello world",
cursorPos = 5
focusedInput = "email",
email = textInput2.init "",
password = textInput2.init ""
};
update = state event \ event
| ArrowLeft \ state.{ cursorPos = max 0 (state.cursorPos - 1) }
| ArrowRight \ state.{ cursorPos = min (len state.text) (state.cursorPos + 1) }
| Backspace \ {
text = deleteChar state.text state.cursorPos,
cursorPos = max 0 (state.cursorPos - 1)
}
| Char c \ {
text = insertChar state.text state.cursorPos c,
cursorPos = state.cursorPos + 1
}
| FocusEmail \ state.{ focusedInput = "email" }
| FocusPassword \ state.{ focusedInput = "password" }
| ArrowLeft \ routeKeyToFocused state ArrowLeft
| ArrowRight \ routeKeyToFocused state ArrowRight
| Backspace \ routeKeyToFocused state Backspace
| Char c \ routeKeyToFocused state (Char c)
| _ \ state;
view = state viewport \
# charWidth = 9.65;
# cursorX = state.cursorPos * charWidth;
textBeforeCursor = slice state.text 0 state.cursorPos;
cursorX = measureText textBeforeCursor;
Column {
gap = 20,
children = [
Text {
content = "Text: " & state.text & " | Cursor: " & str(state.cursorPos),
x = 0,
y = 20
},
# Text Input Component
Stack {
children = [
Rect { w = 300, h = 40, color = "white", radius = 4 },
# Text content
Positioned {
x = 8,
y = 8,
child = Text { content = state.text, x = 0, y = 17 }
},
# Cursor
Positioned {
x = 8 + cursorX,
y = 8,
child = Rect {
w = 2,
h = 24,
color = "black"
}
}
]
}
]
};
Positioned {
x = 30,
y = 30,
child = Column {
gap = 10,
children = [
(textInput2.view state.email) {
focused = state.focusedInput == "email",
onFocus = FocusEmail,
w = 300,
h = 40
},
(textInput2.view state.password) {
focused = state.focusedInput == "password",
onFocus = FocusPassword,
w = 300,
h = 40
}
]
}
};
{ init = init, update = update, view = view }

@ -9,3 +9,90 @@ button = config \
]
}
};
insertChar = text pos char \
before = slice text 0 pos;
after = slice text pos (len text);
before & char & after;
deleteChar = text pos \
(pos == 0
| True \ text
| False \
(before = slice text 0 (pos - 1);
after = slice text pos (len text);
before & after));
calcScrollOffset = text cursorPos scrollOffset inputWidth \
textBeforeCursor = slice text 0 cursorPos;
cursorX = measureText textBeforeCursor;
(cursorX < scrollOffset
| True \ max 0 (cursorX - 20)
| False \
(cursorX > (scrollOffset + inputWidth)
| True \ cursorX - inputWidth + 20
| False \ scrollOffset));
textInput2 = {
# init : String \ State
init = text \ { text = text, cursorPos = 0, scrollOffset = 0 },
# update : State \ Event \ State
update = state event \ event
| ArrowLeft \ (
newCursorPos = max 0 (state.cursorPos - 1);
newScroll = calcScrollOffset state.text newCursorPos state.scrollOffset 284;
{ text = state.text, cursorPos = newCursorPos, scrollOffset = newScroll }
)
| ArrowRight \ (
newCursorPos = min (len state.text) (state.cursorPos + 1);
newScroll = calcScrollOffset state.text newCursorPos state.scrollOffset 284;
{ text = state.text, cursorPos = newCursorPos, scrollOffset = newScroll }
)
| Backspace \ (
newText = deleteChar state.text state.cursorPos;
newCursorPos = max 0 (state.cursorPos - 1);
newScroll = calcScrollOffset newText newCursorPos state.scrollOffset 284;
{ text = newText, cursorPos = newCursorPos, scrollOffset = newScroll }
)
| Char c \ (
newText = insertChar state.text state.cursorPos c;
newCursorPos = state.cursorPos + 1;
newScroll = calcScrollOffset newText newCursorPos state.scrollOffset 284;
{ text = newText, cursorPos = newCursorPos, scrollOffset = newScroll }
)
| _ \ state,
view = state config \
textBeforeCursor = slice state.text 0 state.cursorPos;
cursorX = measureText textBeforeCursor;
padding = 8;
Clickable {
event = config.onFocus,
child =
Stack {
children = [
Rect { w = config.w, h = config.h, color = "rgba(240,240,240,0.9)", radius = 4 },
Positioned {
x = 8 - state.scrollOffset,
y = 8,
child = Text { content = state.text, x = 0, y = 17 }
},
(config.focused
| True \ Positioned {
x = 8 + cursorX - state.scrollOffset,
y = 8,
child = Rect { w = 2, h = 24, color = "black" }
}
| _ \ Rect { w = 0, h = 0, color = "transparent" })
]
}
}
};

Loading…
Cancel
Save