UNPKG

verstak

Version:
128 lines (127 loc) 5.31 kB
import { Mode, setBasis } from "reactronic"; import { Block, OnFocus, rowBreak, Fragment, KeyboardModifiers, H, V } from "verstak"; import { rxModel } from "./common/Utils.js"; import { Theme } from "./Theme.js"; import { Icon } from "./Icon.v.js"; export function Input(declaration) { return (Block(setBasis(declaration, { preparation() { var _a; (_a = this.model) !== null && _a !== void 0 ? _a : (this.model = composeInputModel()); this.native.dataForSensor.focus = this.model; }, body() { const m = this.model; const theme = Theme.current.input; this.useStylingPreset(theme.main); if (m.icon) Icon(m.icon, { body(el, base) { base(); this.useStylingPreset(theme.icon); }, }); InputField(m, theme); InputPopup(m, theme); }, }))); } export function composeInputModel(props) { var _a, _b, _c, _d, _e, _f, _g, _h; return rxModel({ icon: props === null || props === void 0 ? void 0 : props.icon, text: (_a = props === null || props === void 0 ? void 0 : props.text) !== null && _a !== void 0 ? _a : "", options: (_b = props === null || props === void 0 ? void 0 : props.options) !== null && _b !== void 0 ? _b : [], selected: props === null || props === void 0 ? void 0 : props.selected, multiSelected: (_c = props === null || props === void 0 ? void 0 : props.multiSelected) !== null && _c !== void 0 ? _c : new Set(), position: (_d = props === null || props === void 0 ? void 0 : props.position) !== null && _d !== void 0 ? _d : 0, isMultiLineText: (_e = props === null || props === void 0 ? void 0 : props.isMultiLineText) !== null && _e !== void 0 ? _e : false, isEditMode: (_f = props === null || props === void 0 ? void 0 : props.isEditMode) !== null && _f !== void 0 ? _f : false, isHotText: (_g = props === null || props === void 0 ? void 0 : props.isHotText) !== null && _g !== void 0 ? _g : false, inputStyle: (_h = props === null || props === void 0 ? void 0 : props.inputStyle) !== null && _h !== void 0 ? _h : "", }); } function InputField(model, styling) { return (Block({ key: InputField.name, mode: Mode.primitive, preparation(el, base) { const e = this.native; this.useStylingPreset(styling.field); this.selfAlignmentHorizontal = H.stretch; this.selfAlignmentVertical = V.stretch; this.textIsEditable = true; e.tabIndex = 0; e.dataForSensor.focus = model; base(); }, body() { const e = this.native; if (!model.isEditMode) this.text = model.text; Fragment(() => { const keyboard = e.sensors.keyboard; if (keyboard.down) { if (isApplyKey(model, keyboard)) selectAllAndPreventDefault(e, keyboard); } if (keyboard.up) { if (isApplyKey(model, keyboard)) { selectAllAndPreventDefault(e, keyboard); model.text = e.innerText; } else if (model.isHotText) model.text = e.innerText; } }); OnFocus(e, model); }, })); } function InputPopup(model, styling) { return (Block({ key: InputPopup.name, mode: Mode.primitive, body() { this.useStylingPreset(styling.popup); Fragment(() => model.position = this.native.sensors.scroll.y); const visible = this.overlayVisible = model.isEditMode; if (visible) { const options = model.options; if (options.length > 0) { for (const x of model.options) { rowBreak(); Block({ key: x, mode: Mode.primitive, preparation() { this.text = x; this.contentWrapping = false; }, }); } } else Block({ key: "(nothing)", mode: Mode.primitive, body() { this.text = "(nothing)"; }, }); } }, })); } function isApplyKey(m, keyboard) { const modifiers = keyboard.modifiers; return keyboard.down === "Enter" && (!m.isMultiLineText || (modifiers & KeyboardModifiers.ctrlShiftMeta) > 0); } function selectAllAndPreventDefault(e, keyboard) { const range = document.createRange(); range.selectNodeContents(e); const sel = window.getSelection(); sel === null || sel === void 0 ? void 0 : sel.removeAllRanges(); sel === null || sel === void 0 ? void 0 : sel.addRange(range); keyboard.preventDefault = true; }