verstak
Version:
Verstak - Front-End Library
128 lines (127 loc) • 5.31 kB
JavaScript
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;
}