@vortexm/vjt 0.1.8 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js
CHANGED
|
@@ -4366,6 +4366,8 @@ var ReferenceRuntime = class {
|
|
|
4366
4366
|
return state.isHidden ?? true;
|
|
4367
4367
|
case "url":
|
|
4368
4368
|
return state.url ?? "";
|
|
4369
|
+
case "base64":
|
|
4370
|
+
return state.base64 ?? "";
|
|
4369
4371
|
case "elements":
|
|
4370
4372
|
if (state.widget === "list") {
|
|
4371
4373
|
return (state.elements ?? []).map((descriptor, index) => ({
|
|
@@ -4453,6 +4455,9 @@ var ReferenceRuntime = class {
|
|
|
4453
4455
|
case "url":
|
|
4454
4456
|
state.url = stringifyReferenceValue(inputValue);
|
|
4455
4457
|
break;
|
|
4458
|
+
case "base64":
|
|
4459
|
+
state.base64 = stringifyReferenceValue(inputValue);
|
|
4460
|
+
break;
|
|
4456
4461
|
case "condition":
|
|
4457
4462
|
state.condition = Boolean(inputValue);
|
|
4458
4463
|
break;
|
|
@@ -4645,9 +4650,11 @@ var ActionRuntime = class {
|
|
|
4645
4650
|
assignReference;
|
|
4646
4651
|
resolveMappedValue;
|
|
4647
4652
|
setWidgetEnabled;
|
|
4653
|
+
setWidgetVisible;
|
|
4648
4654
|
clearWidget;
|
|
4649
4655
|
clearListElementState;
|
|
4650
4656
|
focusWidget;
|
|
4657
|
+
moveCursorToEnd;
|
|
4651
4658
|
scrollWidgetToTop;
|
|
4652
4659
|
scrollWidgetToBottom;
|
|
4653
4660
|
scrollWidgetToElementByIndex;
|
|
@@ -4685,9 +4692,11 @@ var ActionRuntime = class {
|
|
|
4685
4692
|
this.assignReference = options.assignReference;
|
|
4686
4693
|
this.resolveMappedValue = options.resolveMappedValue;
|
|
4687
4694
|
this.setWidgetEnabled = options.setWidgetEnabled;
|
|
4695
|
+
this.setWidgetVisible = options.setWidgetVisible;
|
|
4688
4696
|
this.clearWidget = options.clearWidget;
|
|
4689
4697
|
this.clearListElementState = options.clearListElementState;
|
|
4690
4698
|
this.focusWidget = options.focusWidget;
|
|
4699
|
+
this.moveCursorToEnd = options.moveCursorToEnd;
|
|
4691
4700
|
this.scrollWidgetToTop = options.scrollWidgetToTop;
|
|
4692
4701
|
this.scrollWidgetToBottom = options.scrollWidgetToBottom;
|
|
4693
4702
|
this.scrollWidgetToElementByIndex = options.scrollWidgetToElementByIndex;
|
|
@@ -4883,6 +4892,14 @@ var ActionRuntime = class {
|
|
|
4883
4892
|
this.setWidgetEnabled(name.slice(8), false);
|
|
4884
4893
|
return null;
|
|
4885
4894
|
}
|
|
4895
|
+
if (name.startsWith("makeVisible ")) {
|
|
4896
|
+
this.setWidgetVisible(name.slice(12), true);
|
|
4897
|
+
return null;
|
|
4898
|
+
}
|
|
4899
|
+
if (name.startsWith("makeInvisible ")) {
|
|
4900
|
+
this.setWidgetVisible(name.slice(14), false);
|
|
4901
|
+
return null;
|
|
4902
|
+
}
|
|
4886
4903
|
if (name.startsWith("clear ")) {
|
|
4887
4904
|
this.clearWidget(name.slice(6));
|
|
4888
4905
|
return null;
|
|
@@ -4891,6 +4908,10 @@ var ActionRuntime = class {
|
|
|
4891
4908
|
this.focusWidget(name.slice(9));
|
|
4892
4909
|
return null;
|
|
4893
4910
|
}
|
|
4911
|
+
if (name.startsWith("moveCursorToEnd ")) {
|
|
4912
|
+
this.moveCursorToEnd(name.slice(16));
|
|
4913
|
+
return null;
|
|
4914
|
+
}
|
|
4894
4915
|
if (name.startsWith("scrollToTop ")) {
|
|
4895
4916
|
this.scrollWidgetToTop(name.slice(12));
|
|
4896
4917
|
return inputValue;
|
|
@@ -5065,7 +5086,7 @@ var ActionRuntime = class {
|
|
|
5065
5086
|
if (Array.isArray(inputValue)) {
|
|
5066
5087
|
return inputValue.map((entry) => this.resolveMappedValue(action.args, entry, context.responseValue));
|
|
5067
5088
|
}
|
|
5068
|
-
return this.resolveMappedValue(action.args,
|
|
5089
|
+
return this.resolveMappedValue(action.args, inputValue, context.responseValue);
|
|
5069
5090
|
}
|
|
5070
5091
|
if (name === "ifelse") {
|
|
5071
5092
|
const branches = isIfElseArgs(action.args) ? action.args : null;
|
|
@@ -6409,7 +6430,10 @@ var renderCheckbox = (env, node, state, key) => {
|
|
|
6409
6430
|
|
|
6410
6431
|
// src/lib/widgets/image.ts
|
|
6411
6432
|
var renderImage = (env, node, state, key) => {
|
|
6412
|
-
const
|
|
6433
|
+
const rawBase64 = typeof state.base64 === "string" ? state.base64 : typeof node.base64 === "string" ? node.base64 : "";
|
|
6434
|
+
const rawUrl = sanitizeUrl(state.url ?? node.url ?? "", { allowRelative: true }) ?? "";
|
|
6435
|
+
const imageSource = rawBase64 ? rawBase64.startsWith("data:") ? rawBase64 : `data:image/png;base64,${rawBase64}` : rawUrl;
|
|
6436
|
+
const url = env.escapeHtml(imageSource);
|
|
6413
6437
|
const styleParts = [
|
|
6414
6438
|
"box-sizing:border-box",
|
|
6415
6439
|
"width:100%",
|
|
@@ -6613,6 +6637,32 @@ function renderConfirmModalOverlay(env, modal) {
|
|
|
6613
6637
|
}
|
|
6614
6638
|
|
|
6615
6639
|
// src/lib/widgets/bindings.ts
|
|
6640
|
+
function readBlobAsDataUrl(blob) {
|
|
6641
|
+
return new Promise((resolve, reject) => {
|
|
6642
|
+
const reader = new FileReader();
|
|
6643
|
+
reader.onload = () => resolve(typeof reader.result === "string" ? reader.result : "");
|
|
6644
|
+
reader.onerror = () => reject(reader.error ?? new Error("Failed to read clipboard blob"));
|
|
6645
|
+
reader.readAsDataURL(blob);
|
|
6646
|
+
});
|
|
6647
|
+
}
|
|
6648
|
+
async function getPasteInputValue(event) {
|
|
6649
|
+
const clipboardData = event.clipboardData;
|
|
6650
|
+
if (!clipboardData) {
|
|
6651
|
+
return "";
|
|
6652
|
+
}
|
|
6653
|
+
for (const item of Array.from(clipboardData.items)) {
|
|
6654
|
+
if (!item.type.startsWith("image/")) {
|
|
6655
|
+
continue;
|
|
6656
|
+
}
|
|
6657
|
+
const file = item.getAsFile();
|
|
6658
|
+
if (!file) {
|
|
6659
|
+
continue;
|
|
6660
|
+
}
|
|
6661
|
+
const dataUrl = await readBlobAsDataUrl(file);
|
|
6662
|
+
return dataUrl;
|
|
6663
|
+
}
|
|
6664
|
+
return clipboardData.getData("text/plain");
|
|
6665
|
+
}
|
|
6616
6666
|
function bindKeyboardSubmitEvents(element, node, key, env) {
|
|
6617
6667
|
const hasKeyboardEvents = Boolean(
|
|
6618
6668
|
node.events?.onEnter?.length || node.events?.onShiftEnter?.length || node.events?.onControlEnter?.length
|
|
@@ -6635,6 +6685,10 @@ function bindKeyboardSubmitEvents(element, node, key, env) {
|
|
|
6635
6685
|
if (!eventName || !node.events?.[eventName]?.length) {
|
|
6636
6686
|
return;
|
|
6637
6687
|
}
|
|
6688
|
+
if (eventName !== "onShiftEnter") {
|
|
6689
|
+
event.preventDefault();
|
|
6690
|
+
event.stopPropagation();
|
|
6691
|
+
}
|
|
6638
6692
|
void env.dispatchWidgetEvent(node, eventName, key, env.getActionInputValueForElement(element, node), null);
|
|
6639
6693
|
});
|
|
6640
6694
|
}
|
|
@@ -6706,6 +6760,11 @@ function bindWidgetEvents(root, env) {
|
|
|
6706
6760
|
}
|
|
6707
6761
|
if (element instanceof HTMLInputElement && element.dataset.widget === "edit") {
|
|
6708
6762
|
bindKeyboardSubmitEvents(element, node, key, env);
|
|
6763
|
+
if (node.events?.onPaste?.length) {
|
|
6764
|
+
element.addEventListener("paste", (event) => {
|
|
6765
|
+
void getPasteInputValue(event).then((inputValue) => env.dispatchWidgetEvent(node, "onPaste", key, inputValue, null));
|
|
6766
|
+
});
|
|
6767
|
+
}
|
|
6709
6768
|
element.addEventListener("input", () => {
|
|
6710
6769
|
const state = env.stateByKey.get(key);
|
|
6711
6770
|
if (state) {
|
|
@@ -6724,6 +6783,11 @@ function bindWidgetEvents(root, env) {
|
|
|
6724
6783
|
}
|
|
6725
6784
|
if (element instanceof HTMLTextAreaElement && element.dataset.widget === "textarea") {
|
|
6726
6785
|
bindKeyboardSubmitEvents(element, node, key, env);
|
|
6786
|
+
if (node.events?.onPaste?.length) {
|
|
6787
|
+
element.addEventListener("paste", (event) => {
|
|
6788
|
+
void getPasteInputValue(event).then((inputValue) => env.dispatchWidgetEvent(node, "onPaste", key, inputValue, null));
|
|
6789
|
+
});
|
|
6790
|
+
}
|
|
6727
6791
|
element.addEventListener("input", () => {
|
|
6728
6792
|
const state = env.stateByKey.get(key);
|
|
6729
6793
|
if (state) {
|
|
@@ -7225,6 +7289,8 @@ var RuntimeRenderer = class {
|
|
|
7225
7289
|
pendingScrollAction = null;
|
|
7226
7290
|
pendingScrollFrameId = null;
|
|
7227
7291
|
activeScrollAnimationFrameId = null;
|
|
7292
|
+
pendingCursorReference = null;
|
|
7293
|
+
pendingCursorFrameId = null;
|
|
7228
7294
|
constructor(description, options = {}) {
|
|
7229
7295
|
this.description = deepClone(description);
|
|
7230
7296
|
this.resourceManager = options.resourceManager ?? null;
|
|
@@ -7260,6 +7326,8 @@ var RuntimeRenderer = class {
|
|
|
7260
7326
|
return this.language;
|
|
7261
7327
|
case "theme":
|
|
7262
7328
|
return this.theme;
|
|
7329
|
+
case "isMobile":
|
|
7330
|
+
return typeof window === "undefined" ? false : isMobileViewport();
|
|
7263
7331
|
case "urlPath":
|
|
7264
7332
|
return typeof window === "undefined" ? "" : window.location.pathname;
|
|
7265
7333
|
default:
|
|
@@ -7324,9 +7392,11 @@ var RuntimeRenderer = class {
|
|
|
7324
7392
|
assignReference: (reference, inputValue, currentValue, options2) => this.referenceRuntime.assignReference(reference, inputValue, currentValue, options2),
|
|
7325
7393
|
resolveMappedValue: (template, currentValue, responseValue) => this.referenceRuntime.resolveMappedValue(template, currentValue, responseValue),
|
|
7326
7394
|
setWidgetEnabled: (widgetId, enabled) => this.setWidgetEnabled(widgetId, enabled),
|
|
7395
|
+
setWidgetVisible: (widgetId, visible) => this.setWidgetVisible(widgetId, visible),
|
|
7327
7396
|
clearWidget: (widgetId) => this.clearWidget(widgetId),
|
|
7328
7397
|
clearListElementState: (listKey) => this.clearListElementState(listKey),
|
|
7329
7398
|
focusWidget: (reference) => this.focusWidget(reference),
|
|
7399
|
+
moveCursorToEnd: (reference) => this.moveCursorToEnd(reference),
|
|
7330
7400
|
scrollWidgetToTop: (reference) => this.scrollWidgetToTop(reference),
|
|
7331
7401
|
scrollWidgetToBottom: (reference) => this.scrollWidgetToBottom(reference),
|
|
7332
7402
|
scrollWidgetToElementByIndex: (reference, index) => this.scrollWidgetToElementByIndex(reference, index),
|
|
@@ -7466,6 +7536,7 @@ var RuntimeRenderer = class {
|
|
|
7466
7536
|
this.attachWidgetEvents(this.root);
|
|
7467
7537
|
restoreElementState(this.root, preservedState, this.stateByKey);
|
|
7468
7538
|
this.applyPendingScrollAction();
|
|
7539
|
+
this.applyPendingCursorAction();
|
|
7469
7540
|
this.activeContextMenu = adjustContextMenuPosition(this.root, this.activeContextMenu);
|
|
7470
7541
|
this.pendingResetModalIds.clear();
|
|
7471
7542
|
if (typeof this.onRuntimeSnapshot === "function") {
|
|
@@ -7986,6 +8057,9 @@ var RuntimeRenderer = class {
|
|
|
7986
8057
|
existing.id = stateId2;
|
|
7987
8058
|
this.stateById.set(stateId2, existing);
|
|
7988
8059
|
}
|
|
8060
|
+
if (existing.visible === void 0) {
|
|
8061
|
+
existing.visible = normalizeBoolean(node.visible, true);
|
|
8062
|
+
}
|
|
7989
8063
|
this.syncStateDefinition(existing, node);
|
|
7990
8064
|
return existing;
|
|
7991
8065
|
}
|
|
@@ -8036,7 +8110,8 @@ var RuntimeRenderer = class {
|
|
|
8036
8110
|
id: stateId,
|
|
8037
8111
|
name: node.name,
|
|
8038
8112
|
text: typeof node.text === "string" ? node.text : void 0,
|
|
8039
|
-
url: "url" in node ? typeof node.url === "string" ? node.url : "" : void 0
|
|
8113
|
+
url: "url" in node ? typeof node.url === "string" ? node.url : "" : void 0,
|
|
8114
|
+
base64: "base64" in node ? typeof node.base64 === "string" ? node.base64 : "" : void 0
|
|
8040
8115
|
};
|
|
8041
8116
|
break;
|
|
8042
8117
|
case "conditional-container":
|
|
@@ -8273,6 +8348,9 @@ var RuntimeRenderer = class {
|
|
|
8273
8348
|
const key = itemContext ? this.resolveItemNodeKey(node, itemContext.listId, itemContext.index, path) : this.resolveNodeKey(node, path);
|
|
8274
8349
|
this.nodeByKey.set(key, node);
|
|
8275
8350
|
const state = this.ensureWidgetState(node, key);
|
|
8351
|
+
if ((state.visible ?? normalizeBoolean(node.visible, true)) === false) {
|
|
8352
|
+
return "";
|
|
8353
|
+
}
|
|
8276
8354
|
switch (node.widget) {
|
|
8277
8355
|
case "adaptive-layout":
|
|
8278
8356
|
return renderAdaptiveLayout(env, node, state, key, path, itemContext);
|
|
@@ -8762,6 +8840,13 @@ var RuntimeRenderer = class {
|
|
|
8762
8840
|
}
|
|
8763
8841
|
state.enabled = enabled;
|
|
8764
8842
|
}
|
|
8843
|
+
setWidgetVisible(widgetId, visible) {
|
|
8844
|
+
const state = this.stateById.get(widgetId);
|
|
8845
|
+
if (!state) {
|
|
8846
|
+
return;
|
|
8847
|
+
}
|
|
8848
|
+
state.visible = visible;
|
|
8849
|
+
}
|
|
8765
8850
|
clearListElementState(listKey) {
|
|
8766
8851
|
this.referenceRuntime.clearListElementState(listKey);
|
|
8767
8852
|
}
|
|
@@ -8787,6 +8872,16 @@ var RuntimeRenderer = class {
|
|
|
8787
8872
|
nestedTarget.focus({ preventScroll: true });
|
|
8788
8873
|
}
|
|
8789
8874
|
}
|
|
8875
|
+
moveCursorToEnd(reference) {
|
|
8876
|
+
this.pendingCursorReference = reference;
|
|
8877
|
+
if (typeof window === "undefined" || this.pendingCursorFrameId !== null) {
|
|
8878
|
+
return;
|
|
8879
|
+
}
|
|
8880
|
+
this.pendingCursorFrameId = window.requestAnimationFrame(() => {
|
|
8881
|
+
this.pendingCursorFrameId = null;
|
|
8882
|
+
this.applyPendingCursorAction();
|
|
8883
|
+
});
|
|
8884
|
+
}
|
|
8790
8885
|
scrollWidgetToTop(reference) {
|
|
8791
8886
|
this.pendingScrollAction = { kind: "top", reference };
|
|
8792
8887
|
this.schedulePendingScrollAction();
|
|
@@ -8813,17 +8908,17 @@ var RuntimeRenderer = class {
|
|
|
8813
8908
|
return;
|
|
8814
8909
|
}
|
|
8815
8910
|
const pending = this.pendingScrollAction;
|
|
8816
|
-
const element = this.findScrollableWidgetElement(pending.reference);
|
|
8817
|
-
if (!element) {
|
|
8818
|
-
return;
|
|
8819
|
-
}
|
|
8820
8911
|
if (pending.kind === "top") {
|
|
8821
|
-
this.animateScrollTop(
|
|
8912
|
+
this.animateScrollTop(pending.reference, 0);
|
|
8822
8913
|
this.pendingScrollAction = null;
|
|
8823
8914
|
return;
|
|
8824
8915
|
}
|
|
8825
8916
|
if (pending.kind === "bottom") {
|
|
8826
|
-
this.
|
|
8917
|
+
const element = this.findScrollableWidgetElement(pending.reference);
|
|
8918
|
+
if (!element) {
|
|
8919
|
+
return;
|
|
8920
|
+
}
|
|
8921
|
+
this.animateScrollTop(pending.reference, element.scrollHeight);
|
|
8827
8922
|
this.pendingScrollAction = null;
|
|
8828
8923
|
return;
|
|
8829
8924
|
}
|
|
@@ -8832,17 +8927,21 @@ var RuntimeRenderer = class {
|
|
|
8832
8927
|
this.pendingScrollAction = null;
|
|
8833
8928
|
return;
|
|
8834
8929
|
}
|
|
8835
|
-
this.performScrollToElementByIndex(
|
|
8930
|
+
this.performScrollToElementByIndex(pending.reference, index);
|
|
8836
8931
|
this.pendingScrollAction = null;
|
|
8837
8932
|
}
|
|
8838
|
-
performScrollToElementByIndex(
|
|
8933
|
+
performScrollToElementByIndex(reference, index) {
|
|
8934
|
+
const element = this.findScrollableWidgetElement(reference);
|
|
8935
|
+
if (!element) {
|
|
8936
|
+
return;
|
|
8937
|
+
}
|
|
8839
8938
|
if (element instanceof HTMLSelectElement) {
|
|
8840
8939
|
const option = element.options.item(index);
|
|
8841
8940
|
if (!option) {
|
|
8842
8941
|
return;
|
|
8843
8942
|
}
|
|
8844
8943
|
const maxScrollTop = Math.max(0, element.scrollHeight - element.clientHeight);
|
|
8845
|
-
this.animateScrollTop(
|
|
8944
|
+
this.animateScrollTop(reference, Math.max(0, Math.min(option.offsetTop, maxScrollTop)));
|
|
8846
8945
|
return;
|
|
8847
8946
|
}
|
|
8848
8947
|
const listElement = element.querySelector(`.vjt-list-element[data-list-index="${index}"], .vjt-grid-cell[data-list-index="${index}"]`);
|
|
@@ -8853,41 +8952,88 @@ var RuntimeRenderer = class {
|
|
|
8853
8952
|
const targetTop = element.scrollTop + (itemRect.top - containerRect.top);
|
|
8854
8953
|
const remainingContentHeight = element.scrollHeight - targetTop;
|
|
8855
8954
|
const nextScrollTop = remainingContentHeight > element.clientHeight ? Math.max(0, Math.min(targetTop, maxScrollTop)) : maxScrollTop;
|
|
8856
|
-
this.animateScrollTop(
|
|
8955
|
+
this.animateScrollTop(reference, nextScrollTop);
|
|
8857
8956
|
}
|
|
8858
8957
|
}
|
|
8859
|
-
animateScrollTop(
|
|
8958
|
+
animateScrollTop(reference, targetTop) {
|
|
8959
|
+
const resolveLiveElement = () => {
|
|
8960
|
+
const resolved = this.findScrollableWidgetElement(reference);
|
|
8961
|
+
return resolved instanceof HTMLElement ? resolved : null;
|
|
8962
|
+
};
|
|
8963
|
+
const getMaxScrollTop = (element) => Math.max(
|
|
8964
|
+
0,
|
|
8965
|
+
element.scrollHeight - element.clientHeight
|
|
8966
|
+
);
|
|
8967
|
+
const initialElement = resolveLiveElement();
|
|
8968
|
+
if (!initialElement) {
|
|
8969
|
+
return;
|
|
8970
|
+
}
|
|
8860
8971
|
if (typeof window === "undefined") {
|
|
8861
|
-
|
|
8972
|
+
initialElement.scrollTop = Math.max(0, Math.min(targetTop, getMaxScrollTop(initialElement)));
|
|
8862
8973
|
return;
|
|
8863
8974
|
}
|
|
8864
8975
|
if (this.activeScrollAnimationFrameId !== null) {
|
|
8865
8976
|
window.cancelAnimationFrame(this.activeScrollAnimationFrameId);
|
|
8866
8977
|
this.activeScrollAnimationFrameId = null;
|
|
8867
8978
|
}
|
|
8868
|
-
const startTop =
|
|
8869
|
-
const clampedTargetTop = Math.max(0, targetTop);
|
|
8979
|
+
const startTop = initialElement.scrollTop;
|
|
8980
|
+
const clampedTargetTop = Math.max(0, Math.min(targetTop, getMaxScrollTop(initialElement)));
|
|
8870
8981
|
const delta = clampedTargetTop - startTop;
|
|
8871
8982
|
if (Math.abs(delta) < 1) {
|
|
8872
|
-
|
|
8983
|
+
initialElement.scrollTop = clampedTargetTop;
|
|
8873
8984
|
return;
|
|
8874
8985
|
}
|
|
8875
8986
|
const durationMs = 300;
|
|
8876
8987
|
const startTime = window.performance.now();
|
|
8877
8988
|
const easeInOutCubic = (t) => t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;
|
|
8878
8989
|
const tick = (now) => {
|
|
8990
|
+
const liveElement = resolveLiveElement();
|
|
8991
|
+
if (!liveElement) {
|
|
8992
|
+
this.activeScrollAnimationFrameId = null;
|
|
8993
|
+
return;
|
|
8994
|
+
}
|
|
8879
8995
|
const elapsed = now - startTime;
|
|
8880
8996
|
const progress = Math.min(1, elapsed / durationMs);
|
|
8881
|
-
|
|
8997
|
+
const liveTargetTop = Math.max(0, Math.min(clampedTargetTop, getMaxScrollTop(liveElement)));
|
|
8998
|
+
liveElement.scrollTop = startTop + (liveTargetTop - startTop) * easeInOutCubic(progress);
|
|
8882
8999
|
if (progress < 1) {
|
|
8883
9000
|
this.activeScrollAnimationFrameId = window.requestAnimationFrame(tick);
|
|
8884
9001
|
} else {
|
|
8885
|
-
|
|
9002
|
+
liveElement.scrollTop = liveTargetTop;
|
|
8886
9003
|
this.activeScrollAnimationFrameId = null;
|
|
8887
9004
|
}
|
|
8888
9005
|
};
|
|
8889
9006
|
this.activeScrollAnimationFrameId = window.requestAnimationFrame(tick);
|
|
8890
9007
|
}
|
|
9008
|
+
applyPendingCursorAction() {
|
|
9009
|
+
if (!(this.root instanceof HTMLElement) || !this.pendingCursorReference) {
|
|
9010
|
+
return;
|
|
9011
|
+
}
|
|
9012
|
+
const reference = this.pendingCursorReference;
|
|
9013
|
+
const widgetId = reference.split(".")[0]?.trim();
|
|
9014
|
+
if (!widgetId) {
|
|
9015
|
+
this.pendingCursorReference = null;
|
|
9016
|
+
return;
|
|
9017
|
+
}
|
|
9018
|
+
const directTarget = this.root.querySelector(`#${CSS.escape(widgetId)}`);
|
|
9019
|
+
const widgetRoot = directTarget ?? this.root.querySelector(`[data-widget-id="${CSS.escape(widgetId)}"]`);
|
|
9020
|
+
if (!widgetRoot) {
|
|
9021
|
+
return;
|
|
9022
|
+
}
|
|
9023
|
+
const inputTarget = widgetRoot instanceof HTMLInputElement || widgetRoot instanceof HTMLTextAreaElement ? widgetRoot : widgetRoot.querySelector("input, textarea");
|
|
9024
|
+
if (!inputTarget || inputTarget.disabled) {
|
|
9025
|
+
this.pendingCursorReference = null;
|
|
9026
|
+
return;
|
|
9027
|
+
}
|
|
9028
|
+
if (typeof inputTarget.focus === "function") {
|
|
9029
|
+
inputTarget.focus({ preventScroll: true });
|
|
9030
|
+
}
|
|
9031
|
+
if (typeof inputTarget.setSelectionRange === "function") {
|
|
9032
|
+
const end = inputTarget.value.length;
|
|
9033
|
+
inputTarget.setSelectionRange(end, end);
|
|
9034
|
+
}
|
|
9035
|
+
this.pendingCursorReference = null;
|
|
9036
|
+
}
|
|
8891
9037
|
findScrollableWidgetElement(reference) {
|
|
8892
9038
|
if (!(this.root instanceof HTMLElement)) {
|
|
8893
9039
|
return null;
|
|
@@ -29,9 +29,11 @@ type ActionRuntimeOptions = {
|
|
|
29
29
|
}) => void;
|
|
30
30
|
resolveMappedValue: (template: unknown, currentValue: unknown, responseValue: unknown) => unknown;
|
|
31
31
|
setWidgetEnabled: (widgetId: string, enabled: boolean) => void;
|
|
32
|
+
setWidgetVisible: (widgetId: string, visible: boolean) => void;
|
|
32
33
|
clearWidget: (widgetId: string) => void;
|
|
33
34
|
clearListElementState: (listKey: string) => void;
|
|
34
35
|
focusWidget: (reference: string) => void;
|
|
36
|
+
moveCursorToEnd: (reference: string) => void;
|
|
35
37
|
scrollWidgetToTop: (reference: string) => void;
|
|
36
38
|
scrollWidgetToBottom: (reference: string) => void;
|
|
37
39
|
scrollWidgetToElementByIndex: (reference: string, index: unknown) => void;
|
|
@@ -82,9 +84,11 @@ export declare class ActionRuntime {
|
|
|
82
84
|
private readonly assignReference;
|
|
83
85
|
private readonly resolveMappedValue;
|
|
84
86
|
private readonly setWidgetEnabled;
|
|
87
|
+
private readonly setWidgetVisible;
|
|
85
88
|
private readonly clearWidget;
|
|
86
89
|
private readonly clearListElementState;
|
|
87
90
|
private readonly focusWidget;
|
|
91
|
+
private readonly moveCursorToEnd;
|
|
88
92
|
private readonly scrollWidgetToTop;
|
|
89
93
|
private readonly scrollWidgetToBottom;
|
|
90
94
|
private readonly scrollWidgetToElementByIndex;
|
package/dist/lib/types.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ export type LayoutType = 'vertical' | 'horizontal' | 'grid';
|
|
|
3
3
|
export type TextAlign = 'left' | 'center' | 'right';
|
|
4
4
|
export type VerticalAlign = 'top' | 'center' | 'bottom';
|
|
5
5
|
export type HeadingTag = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
|
|
6
|
-
export type WidgetEventName = 'onClick' | 'onUserValueChange' | 'onRefresh' | 'onEnter' | 'onShiftEnter' | 'onControlEnter';
|
|
6
|
+
export type WidgetEventName = 'onClick' | 'onUserValueChange' | 'onRefresh' | 'onEnter' | 'onShiftEnter' | 'onControlEnter' | 'onPaste';
|
|
7
7
|
export type SystemEventName = 'onBeforeRender' | 'onAfterRender' | 'onBeforeNavigate' | 'onAfterNavigate' | 'onSpeechDetected' | 'onRecordingStarted' | 'onRecordingStopped' | 'onRecordingError' | 'onListeningError' | 'onListeringError' | 'onPlayFinished' | 'onPlayingStopped';
|
|
8
8
|
export type PrimitiveRequestType = 'int' | 'float' | 'boolean' | 'string';
|
|
9
9
|
export type RouteDefinition = {
|
|
@@ -58,6 +58,7 @@ export type BaseNode = {
|
|
|
58
58
|
name?: string;
|
|
59
59
|
style?: string | string[];
|
|
60
60
|
css?: string;
|
|
61
|
+
visible?: boolean | string;
|
|
61
62
|
enabled?: boolean | string;
|
|
62
63
|
events?: WidgetEvents;
|
|
63
64
|
[key: string]: unknown;
|
|
@@ -103,8 +104,10 @@ export type WidgetState = {
|
|
|
103
104
|
currentRef?: string;
|
|
104
105
|
text?: string;
|
|
105
106
|
url?: string;
|
|
107
|
+
base64?: string;
|
|
106
108
|
placeholder?: string;
|
|
107
109
|
enabled?: boolean;
|
|
110
|
+
visible?: boolean;
|
|
108
111
|
editable?: boolean;
|
|
109
112
|
checked?: boolean;
|
|
110
113
|
condition?: boolean;
|
|
@@ -12,7 +12,7 @@ type BindingEnvironment = {
|
|
|
12
12
|
}) => void;
|
|
13
13
|
updatePointerFromEvent: (event: MouseEvent) => void;
|
|
14
14
|
updateOwningListElementDescriptor: (element: HTMLElement, mutate: (descriptor: DescriptionNode) => void) => void;
|
|
15
|
-
dispatchWidgetEvent: (node: DescriptionNode, eventName: 'onClick' | 'onUserValueChange' | 'onEnter' | 'onShiftEnter' | 'onControlEnter', key: string, inputValue?: unknown, pointer?: {
|
|
15
|
+
dispatchWidgetEvent: (node: DescriptionNode, eventName: 'onClick' | 'onUserValueChange' | 'onEnter' | 'onShiftEnter' | 'onControlEnter' | 'onPaste', key: string, inputValue?: unknown, pointer?: {
|
|
16
16
|
x: number;
|
|
17
17
|
y: number;
|
|
18
18
|
} | null) => Promise<void>;
|