@vortexm/vjt 0.1.6 → 0.1.8
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.d.ts +1 -1
- package/dist/index.js +549 -53
- package/dist/lib/action-runtime.d.ts +10 -1
- package/dist/lib/references.d.ts +6 -2
- package/dist/lib/resource-manager.d.ts +4 -1
- package/dist/lib/types.d.ts +8 -0
- package/dist/lib/voice-runtime.d.ts +1 -1
- package/dist/lib/widgets/context.d.ts +1 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { renderApp, renderJson } from './lib/render.js';
|
|
2
2
|
export { ResourceManager } from './lib/resource-manager.js';
|
|
3
3
|
export { DEFAULT_STYLE_MAP } from './lib/default-styles.js';
|
|
4
|
-
export type { ActionDefinition, ActionMap, AdaptiveLayoutNode, BaseNode, ButtonNode, CheckboxNode, ComboboxNode, ConditionExpression, ConditionalContainerNode, ContextMenuNode, ContainerCell, ContainerLayoutNode, CellConstraints, DescriptionNode, GridViewNode, HeadingTag, I18nMap, ImageNode, LayoutType, LinkNode, ListElementContext, ListNode, ListboxNode, MdTextNode, ModalWindowNode, MountJsonOptions, OverlayContainerNode, OverlayLayer, PanelNode, PrimitiveRequestType, RadioGroupNode, RequestDefinition, RequestMap, RequestSchema, RenderJsonOptions, RuntimeSnapshot, SseConfig, SseConfigInput, SseEventDefinition, SpoilerNode, SplitterNode, StaticTextNode, StyleMap, SystemEventName, TabsNode, TextAlign, TextareaNode, UiReferenceNode, Theme, VerticalAlign, WidgetEventName, WidgetState } from './lib/types.js';
|
|
4
|
+
export type { ActionDefinition, ActionMap, AdaptiveLayoutNode, BaseNode, ButtonNode, CheckboxNode, ComboboxNode, ConditionExpression, ConditionalContainerNode, ContextMenuNode, ContainerCell, ContainerLayoutNode, CellConstraints, DescriptionNode, GridViewNode, HeadingTag, I18nMap, ImageNode, LayoutType, LinkNode, ListElementContext, ListNode, ListboxNode, MdTextNode, ModalWindowNode, MountJsonOptions, OverlayContainerNode, OverlayLayer, PanelNode, PrimitiveRequestType, RadioGroupNode, RouteDefinition, RoutesConfigInput, RequestDefinition, RequestMap, RequestSchema, RenderJsonOptions, RuntimeSnapshot, SseConfig, SseConfigInput, SseEventDefinition, SpoilerNode, SplitterNode, StaticTextNode, StyleMap, SystemEventName, TabsNode, TextAlign, TextareaNode, UiReferenceNode, Theme, VerticalAlign, WidgetEventName, WidgetState } from './lib/types.js';
|
package/dist/index.js
CHANGED
|
@@ -4154,6 +4154,32 @@ function readPath(target, path) {
|
|
|
4154
4154
|
}
|
|
4155
4155
|
return current;
|
|
4156
4156
|
}
|
|
4157
|
+
function writePath(target, path, value) {
|
|
4158
|
+
if (!isPlainObject2(target) || path.length === 0) {
|
|
4159
|
+
return false;
|
|
4160
|
+
}
|
|
4161
|
+
let current = target;
|
|
4162
|
+
for (let index = 0; index < path.length - 1; index += 1) {
|
|
4163
|
+
const segment = path[index];
|
|
4164
|
+
if (isBlockedObjectKey(segment)) {
|
|
4165
|
+
return false;
|
|
4166
|
+
}
|
|
4167
|
+
const next = current[segment];
|
|
4168
|
+
if (isPlainObject2(next)) {
|
|
4169
|
+
current = next;
|
|
4170
|
+
continue;
|
|
4171
|
+
}
|
|
4172
|
+
const created = {};
|
|
4173
|
+
current[segment] = created;
|
|
4174
|
+
current = created;
|
|
4175
|
+
}
|
|
4176
|
+
const leaf = path[path.length - 1];
|
|
4177
|
+
if (isBlockedObjectKey(leaf)) {
|
|
4178
|
+
return false;
|
|
4179
|
+
}
|
|
4180
|
+
current[leaf] = value;
|
|
4181
|
+
return true;
|
|
4182
|
+
}
|
|
4157
4183
|
function sanitizeIdFragment(value) {
|
|
4158
4184
|
return value.replace(/[^A-Za-z0-9_-]/g, "");
|
|
4159
4185
|
}
|
|
@@ -4273,8 +4299,9 @@ var ReferenceRuntime = class {
|
|
|
4273
4299
|
}
|
|
4274
4300
|
resolveCurrentReference(reference, currentValue) {
|
|
4275
4301
|
if (this.isListElementContext(currentValue)) {
|
|
4302
|
+
const resolvedDescriptor = this.resolveListDescriptorNode(currentValue.descriptor, currentValue);
|
|
4276
4303
|
const firstPart = reference.split(".")[0];
|
|
4277
|
-
const namedNode = this.findNamedWidget(
|
|
4304
|
+
const namedNode = this.findNamedWidget(resolvedDescriptor, firstPart, currentValue);
|
|
4278
4305
|
if (namedNode) {
|
|
4279
4306
|
const widgetKey = this.host.resolveItemNodeKey(namedNode, currentValue.listId, currentValue.index, `named.${firstPart}`);
|
|
4280
4307
|
const state = this.host.ensureWidgetState(namedNode, widgetKey);
|
|
@@ -4285,12 +4312,16 @@ var ReferenceRuntime = class {
|
|
|
4285
4312
|
if (directDescriptorValue !== void 0) {
|
|
4286
4313
|
return directDescriptorValue;
|
|
4287
4314
|
}
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
|
|
4315
|
+
const resolvedDescriptorValue = resolvedDescriptor !== currentValue.descriptor ? readPath(resolvedDescriptor, reference.split(".")) : void 0;
|
|
4316
|
+
if (resolvedDescriptorValue !== void 0) {
|
|
4317
|
+
return resolvedDescriptorValue;
|
|
4318
|
+
}
|
|
4319
|
+
if (typeof resolvedDescriptor.widget === "string") {
|
|
4320
|
+
const descriptorKey = this.host.resolveItemNodeKey(resolvedDescriptor, currentValue.listId, currentValue.index, "item");
|
|
4321
|
+
const descriptorState = this.host.ensureWidgetState(resolvedDescriptor, descriptorKey);
|
|
4291
4322
|
return this.readWidgetField(descriptorState, reference);
|
|
4292
4323
|
}
|
|
4293
|
-
return readPath(
|
|
4324
|
+
return readPath(resolvedDescriptor, reference.split("."));
|
|
4294
4325
|
}
|
|
4295
4326
|
if (isPlainObject2(currentValue) || Array.isArray(currentValue)) {
|
|
4296
4327
|
return readPath(currentValue, reference.split("."));
|
|
@@ -4374,8 +4405,12 @@ var ReferenceRuntime = class {
|
|
|
4374
4405
|
return readPath(state, field.split("."));
|
|
4375
4406
|
}
|
|
4376
4407
|
}
|
|
4377
|
-
assignReference(reference, inputValue,
|
|
4378
|
-
if (
|
|
4408
|
+
assignReference(reference, inputValue, currentValue, options) {
|
|
4409
|
+
if (hasBlockedReferenceSegment(reference)) {
|
|
4410
|
+
return;
|
|
4411
|
+
}
|
|
4412
|
+
if (reference.startsWith("current.")) {
|
|
4413
|
+
this.assignCurrentReference(reference.slice(8), inputValue, currentValue);
|
|
4379
4414
|
return;
|
|
4380
4415
|
}
|
|
4381
4416
|
if (reference.startsWith("cookies.")) {
|
|
@@ -4443,6 +4478,19 @@ var ReferenceRuntime = class {
|
|
|
4443
4478
|
break;
|
|
4444
4479
|
}
|
|
4445
4480
|
}
|
|
4481
|
+
assignCurrentReference(reference, inputValue, currentValue) {
|
|
4482
|
+
const path = reference.split(".").filter(Boolean);
|
|
4483
|
+
if (path.length === 0) {
|
|
4484
|
+
return;
|
|
4485
|
+
}
|
|
4486
|
+
if (this.isListElementContext(currentValue)) {
|
|
4487
|
+
writePath(currentValue.descriptor, path, inputValue);
|
|
4488
|
+
return;
|
|
4489
|
+
}
|
|
4490
|
+
if (isPlainObject2(currentValue)) {
|
|
4491
|
+
writePath(currentValue, path, inputValue);
|
|
4492
|
+
}
|
|
4493
|
+
}
|
|
4446
4494
|
clearListElementState(listKey) {
|
|
4447
4495
|
const generatedPrefix = `${sanitizeIdFragment(listKey)}Element`;
|
|
4448
4496
|
for (const key of Array.from(this.host.stateByKey.keys())) {
|
|
@@ -4493,7 +4541,7 @@ var ReferenceRuntime = class {
|
|
|
4493
4541
|
isListElementContext(value) {
|
|
4494
4542
|
return isPlainObject2(value) && value.kind === "list-element" && typeof value.listId === "string" && typeof value.index === "number" && isPlainObject2(value.descriptor) && typeof value.descriptor.widget === "string";
|
|
4495
4543
|
}
|
|
4496
|
-
findNamedWidget(node, name) {
|
|
4544
|
+
findNamedWidget(node, name, currentValue) {
|
|
4497
4545
|
if (!node) {
|
|
4498
4546
|
return null;
|
|
4499
4547
|
}
|
|
@@ -4502,12 +4550,12 @@ var ReferenceRuntime = class {
|
|
|
4502
4550
|
}
|
|
4503
4551
|
switch (node.widget) {
|
|
4504
4552
|
case "adaptive-layout":
|
|
4505
|
-
return this.findNamedWidget(node.desktop, name) ?? this.findNamedWidget(node.mobile, name);
|
|
4553
|
+
return this.findNamedWidget(node.desktop, name, currentValue) ?? this.findNamedWidget(node.mobile, name, currentValue);
|
|
4506
4554
|
case "container-layout":
|
|
4507
4555
|
if (node.type === "grid") {
|
|
4508
4556
|
for (const row of node.grid?.rows ?? []) {
|
|
4509
4557
|
for (const column of row.columns ?? []) {
|
|
4510
|
-
const match = this.findNamedWidget(column.child, name);
|
|
4558
|
+
const match = this.findNamedWidget(column.child, name, currentValue);
|
|
4511
4559
|
if (match) {
|
|
4512
4560
|
return match;
|
|
4513
4561
|
}
|
|
@@ -4516,20 +4564,20 @@ var ReferenceRuntime = class {
|
|
|
4516
4564
|
return null;
|
|
4517
4565
|
}
|
|
4518
4566
|
for (const cell of node.children ?? []) {
|
|
4519
|
-
const match = this.findNamedWidget(cell.child, name);
|
|
4567
|
+
const match = this.findNamedWidget(cell.child, name, currentValue);
|
|
4520
4568
|
if (match) {
|
|
4521
4569
|
return match;
|
|
4522
4570
|
}
|
|
4523
4571
|
}
|
|
4524
4572
|
return null;
|
|
4525
4573
|
case "panel":
|
|
4526
|
-
return this.findNamedWidget(node.child, name);
|
|
4574
|
+
return this.findNamedWidget(node.child, name, currentValue);
|
|
4527
4575
|
case "conditional-container":
|
|
4528
|
-
return this.findNamedWidget(node.default, name) ?? this.findNamedWidget(node.alternative, name);
|
|
4576
|
+
return this.findNamedWidget(node.default, name, currentValue) ?? this.findNamedWidget(node.alternative, name, currentValue);
|
|
4529
4577
|
case "list":
|
|
4530
4578
|
case "grid-view":
|
|
4531
4579
|
for (const element of node.elements ?? []) {
|
|
4532
|
-
const match = this.findNamedWidget(element, name);
|
|
4580
|
+
const match = this.findNamedWidget(element, name, currentValue);
|
|
4533
4581
|
if (match) {
|
|
4534
4582
|
return match;
|
|
4535
4583
|
}
|
|
@@ -4537,7 +4585,7 @@ var ReferenceRuntime = class {
|
|
|
4537
4585
|
return null;
|
|
4538
4586
|
case "overlay-container":
|
|
4539
4587
|
for (const layer of node.layers ?? []) {
|
|
4540
|
-
const match = this.findNamedWidget(layer.child, name);
|
|
4588
|
+
const match = this.findNamedWidget(layer.child, name, currentValue);
|
|
4541
4589
|
if (match) {
|
|
4542
4590
|
return match;
|
|
4543
4591
|
}
|
|
@@ -4545,20 +4593,40 @@ var ReferenceRuntime = class {
|
|
|
4545
4593
|
return null;
|
|
4546
4594
|
case "tabs":
|
|
4547
4595
|
for (const tab of node.tabs ?? []) {
|
|
4548
|
-
const match = this.findNamedWidget(tab.content, name);
|
|
4596
|
+
const match = this.findNamedWidget(tab.content, name, currentValue);
|
|
4549
4597
|
if (match) {
|
|
4550
4598
|
return match;
|
|
4551
4599
|
}
|
|
4552
4600
|
}
|
|
4553
4601
|
return null;
|
|
4554
4602
|
case "spoiler":
|
|
4555
|
-
return typeof node.content === "string" ? null : this.findNamedWidget(node.content, name);
|
|
4603
|
+
return typeof node.content === "string" ? null : this.findNamedWidget(node.content, name, currentValue);
|
|
4604
|
+
case "ui-reference": {
|
|
4605
|
+
const referenced = currentValue ? this.resolveUiReferenceNode(node, currentValue) : null;
|
|
4606
|
+
return referenced ? this.findNamedWidget(referenced, name, currentValue) : null;
|
|
4607
|
+
}
|
|
4556
4608
|
case "modal-window":
|
|
4557
|
-
return this.findNamedWidget(node.child, name);
|
|
4609
|
+
return this.findNamedWidget(node.child, name, currentValue);
|
|
4558
4610
|
default:
|
|
4559
4611
|
return null;
|
|
4560
4612
|
}
|
|
4561
4613
|
}
|
|
4614
|
+
resolveListDescriptorNode(node, currentValue) {
|
|
4615
|
+
if (node.widget !== "ui-reference") {
|
|
4616
|
+
return node;
|
|
4617
|
+
}
|
|
4618
|
+
return this.resolveUiReferenceNode(node, currentValue) ?? node;
|
|
4619
|
+
}
|
|
4620
|
+
resolveUiReferenceNode(node, currentValue) {
|
|
4621
|
+
if (node.widget !== "ui-reference") {
|
|
4622
|
+
return null;
|
|
4623
|
+
}
|
|
4624
|
+
const resolvedValue = typeof node.ref === "string" && node.ref.startsWith("$ref:") ? this.resolveReference(node.ref.slice(5), currentValue, null) : node.ref;
|
|
4625
|
+
if (typeof resolvedValue !== "string" || resolvedValue.length === 0) {
|
|
4626
|
+
return null;
|
|
4627
|
+
}
|
|
4628
|
+
return this.host.getUiResource(resolvedValue);
|
|
4629
|
+
}
|
|
4562
4630
|
};
|
|
4563
4631
|
|
|
4564
4632
|
// src/lib/action-runtime.ts
|
|
@@ -4580,6 +4648,9 @@ var ActionRuntime = class {
|
|
|
4580
4648
|
clearWidget;
|
|
4581
4649
|
clearListElementState;
|
|
4582
4650
|
focusWidget;
|
|
4651
|
+
scrollWidgetToTop;
|
|
4652
|
+
scrollWidgetToBottom;
|
|
4653
|
+
scrollWidgetToElementByIndex;
|
|
4583
4654
|
playAudio;
|
|
4584
4655
|
stopPlaying;
|
|
4585
4656
|
copyToClipboard;
|
|
@@ -4617,6 +4688,9 @@ var ActionRuntime = class {
|
|
|
4617
4688
|
this.clearWidget = options.clearWidget;
|
|
4618
4689
|
this.clearListElementState = options.clearListElementState;
|
|
4619
4690
|
this.focusWidget = options.focusWidget;
|
|
4691
|
+
this.scrollWidgetToTop = options.scrollWidgetToTop;
|
|
4692
|
+
this.scrollWidgetToBottom = options.scrollWidgetToBottom;
|
|
4693
|
+
this.scrollWidgetToElementByIndex = options.scrollWidgetToElementByIndex;
|
|
4620
4694
|
this.playAudio = options.playAudio;
|
|
4621
4695
|
this.stopPlaying = options.stopPlaying;
|
|
4622
4696
|
this.copyToClipboard = options.copyToClipboard;
|
|
@@ -4670,16 +4744,22 @@ var ActionRuntime = class {
|
|
|
4670
4744
|
async runSingleAction(action, inputValue, context) {
|
|
4671
4745
|
const actionName = action.action.trim();
|
|
4672
4746
|
try {
|
|
4673
|
-
|
|
4747
|
+
const rawOutput = await this.executeAction(action, inputValue, context);
|
|
4748
|
+
logRuntimeDebug(this.debugLogging, "action-output", {
|
|
4749
|
+
action: actionName,
|
|
4750
|
+
output: rawOutput
|
|
4751
|
+
});
|
|
4752
|
+
let output = rawOutput;
|
|
4674
4753
|
if (action.andThen?.length) {
|
|
4675
4754
|
if (output !== null && output !== void 0) {
|
|
4676
|
-
output = await this.runActions(action.andThen, output,
|
|
4755
|
+
output = await this.runActions(action.andThen, output, context);
|
|
4677
4756
|
} else {
|
|
4678
4757
|
output = null;
|
|
4679
4758
|
}
|
|
4680
4759
|
}
|
|
4681
4760
|
logRuntimeDebug(this.debugLogging, "action-result", {
|
|
4682
4761
|
action: actionName,
|
|
4762
|
+
rawOutput,
|
|
4683
4763
|
output
|
|
4684
4764
|
});
|
|
4685
4765
|
return output;
|
|
@@ -4697,7 +4777,7 @@ var ActionRuntime = class {
|
|
|
4697
4777
|
}
|
|
4698
4778
|
async executeAction(action, inputValue, context) {
|
|
4699
4779
|
const name = action.action.trim();
|
|
4700
|
-
logRuntimeDebug(this.debugLogging, "action", {
|
|
4780
|
+
logRuntimeDebug(this.debugLogging, "action-start", {
|
|
4701
4781
|
action: name,
|
|
4702
4782
|
args: action.args,
|
|
4703
4783
|
inputValue,
|
|
@@ -4759,7 +4839,7 @@ var ActionRuntime = class {
|
|
|
4759
4839
|
return null;
|
|
4760
4840
|
}
|
|
4761
4841
|
if (name === "startListening") {
|
|
4762
|
-
await this.startListening();
|
|
4842
|
+
await this.startListening(action.args);
|
|
4763
4843
|
return null;
|
|
4764
4844
|
}
|
|
4765
4845
|
if (name === "stopListening") {
|
|
@@ -4811,6 +4891,18 @@ var ActionRuntime = class {
|
|
|
4811
4891
|
this.focusWidget(name.slice(9));
|
|
4812
4892
|
return null;
|
|
4813
4893
|
}
|
|
4894
|
+
if (name.startsWith("scrollToTop ")) {
|
|
4895
|
+
this.scrollWidgetToTop(name.slice(12));
|
|
4896
|
+
return inputValue;
|
|
4897
|
+
}
|
|
4898
|
+
if (name.startsWith("scrollToBottom ")) {
|
|
4899
|
+
this.scrollWidgetToBottom(name.slice(15));
|
|
4900
|
+
return inputValue;
|
|
4901
|
+
}
|
|
4902
|
+
if (name.startsWith("scrollToElementByIndex ")) {
|
|
4903
|
+
this.scrollWidgetToElementByIndex(name.slice(23), inputValue);
|
|
4904
|
+
return inputValue;
|
|
4905
|
+
}
|
|
4814
4906
|
if (name.startsWith("setUi ")) {
|
|
4815
4907
|
const widgetId = name.slice(6);
|
|
4816
4908
|
const resourceRef = typeof inputValue === "string" ? inputValue : "";
|
|
@@ -4821,14 +4913,62 @@ var ActionRuntime = class {
|
|
|
4821
4913
|
}
|
|
4822
4914
|
if (name.startsWith("get ")) {
|
|
4823
4915
|
const reference = name.slice(4);
|
|
4824
|
-
if (Array.isArray(
|
|
4825
|
-
return
|
|
4916
|
+
if (Array.isArray(inputValue) && this.isCurrentScopedReference(reference)) {
|
|
4917
|
+
return inputValue.map((entry) => this.resolveReference(reference, entry, context.responseValue)).filter((entry) => entry !== null && entry !== void 0);
|
|
4826
4918
|
}
|
|
4827
4919
|
return this.resolveReference(reference, context.currentValue, context.responseValue);
|
|
4828
4920
|
}
|
|
4921
|
+
if (name.startsWith("count ")) {
|
|
4922
|
+
return this.countValue(this.resolveReference(name.slice(6), context.currentValue, context.responseValue));
|
|
4923
|
+
}
|
|
4924
|
+
if (name === "indexOf") {
|
|
4925
|
+
if (isListElementLike(context.currentValue)) {
|
|
4926
|
+
return context.currentValue.index;
|
|
4927
|
+
}
|
|
4928
|
+
if (typeof context.currentIndex === "number") {
|
|
4929
|
+
return context.currentIndex;
|
|
4930
|
+
}
|
|
4931
|
+
return null;
|
|
4932
|
+
}
|
|
4933
|
+
if (name === "foreach") {
|
|
4934
|
+
if (Array.isArray(inputValue) && action.andThen?.length) {
|
|
4935
|
+
const currentList = inputValue;
|
|
4936
|
+
for (let index = 0; index < currentList.length; index += 1) {
|
|
4937
|
+
const entry = currentList[index];
|
|
4938
|
+
await this.runActions(action.andThen, entry, {
|
|
4939
|
+
...context,
|
|
4940
|
+
currentValue: entry,
|
|
4941
|
+
currentList,
|
|
4942
|
+
currentIndex: index
|
|
4943
|
+
});
|
|
4944
|
+
}
|
|
4945
|
+
}
|
|
4946
|
+
return inputValue;
|
|
4947
|
+
}
|
|
4948
|
+
if (name === "inc") {
|
|
4949
|
+
return this.toNumber(inputValue) + 1;
|
|
4950
|
+
}
|
|
4951
|
+
if (name === "dec") {
|
|
4952
|
+
return this.toNumber(inputValue) - 1;
|
|
4953
|
+
}
|
|
4829
4954
|
if (name.startsWith("equals ")) {
|
|
4830
4955
|
return this.resolveReference(name.slice(7), context.currentValue, context.responseValue) === action.args;
|
|
4831
4956
|
}
|
|
4957
|
+
if (name.startsWith("greaterThan ")) {
|
|
4958
|
+
return this.toNumber(inputValue) > this.toNumber(this.resolveReference(name.slice(12), context.currentValue, context.responseValue));
|
|
4959
|
+
}
|
|
4960
|
+
if (name.startsWith("greaterThanOrEquals ")) {
|
|
4961
|
+
return this.toNumber(inputValue) >= this.toNumber(this.resolveReference(name.slice(20), context.currentValue, context.responseValue));
|
|
4962
|
+
}
|
|
4963
|
+
if (name.startsWith("lessThan ")) {
|
|
4964
|
+
return this.toNumber(inputValue) < this.toNumber(this.resolveReference(name.slice(9), context.currentValue, context.responseValue));
|
|
4965
|
+
}
|
|
4966
|
+
if (name.startsWith("lessThanOrEquals ")) {
|
|
4967
|
+
return this.toNumber(inputValue) <= this.toNumber(this.resolveReference(name.slice(17), context.currentValue, context.responseValue));
|
|
4968
|
+
}
|
|
4969
|
+
if (name.startsWith("and ")) {
|
|
4970
|
+
return Boolean(inputValue) && Boolean(this.resolveReference(name.slice(4), context.currentValue, context.responseValue));
|
|
4971
|
+
}
|
|
4832
4972
|
if (name.startsWith("isEmpty ")) {
|
|
4833
4973
|
return this.isEmptyReference(name.slice(8), context.currentValue, context.responseValue);
|
|
4834
4974
|
}
|
|
@@ -4846,8 +4986,8 @@ var ActionRuntime = class {
|
|
|
4846
4986
|
}
|
|
4847
4987
|
if (name.startsWith("filter ")) {
|
|
4848
4988
|
const reference = name.slice(7);
|
|
4849
|
-
if (Array.isArray(
|
|
4850
|
-
return
|
|
4989
|
+
if (Array.isArray(inputValue) && this.isCurrentScopedReference(reference)) {
|
|
4990
|
+
return inputValue.filter((entry) => this.resolveReference(reference, entry, context.responseValue));
|
|
4851
4991
|
}
|
|
4852
4992
|
const value = this.resolveReference(reference, context.currentValue, context.responseValue);
|
|
4853
4993
|
return value ? inputValue : null;
|
|
@@ -4872,6 +5012,12 @@ var ActionRuntime = class {
|
|
|
4872
5012
|
this.clearListElementState(listState.key);
|
|
4873
5013
|
return listState.elements;
|
|
4874
5014
|
}
|
|
5015
|
+
const inputListState = this.asListWidgetState(inputValue);
|
|
5016
|
+
if (inputListState && Array.isArray(inputListState.elements)) {
|
|
5017
|
+
inputListState.elements.push(valueToAdd);
|
|
5018
|
+
this.clearListElementState(inputListState.key);
|
|
5019
|
+
return inputListState.elements;
|
|
5020
|
+
}
|
|
4875
5021
|
if (context.currentList && typeof context.currentIndex === "number") {
|
|
4876
5022
|
return context.currentIndex === context.currentList.length - 1 ? [this.unwrapListValue(inputValue), valueToAdd] : this.unwrapListValue(inputValue);
|
|
4877
5023
|
}
|
|
@@ -4896,6 +5042,12 @@ var ActionRuntime = class {
|
|
|
4896
5042
|
return listState.elements;
|
|
4897
5043
|
}
|
|
4898
5044
|
}
|
|
5045
|
+
const inputListState = this.asListWidgetState(inputValue);
|
|
5046
|
+
if (inputListState && Array.isArray(inputListState.elements)) {
|
|
5047
|
+
inputListState.elements.push(valueToInsert);
|
|
5048
|
+
this.clearListElementState(inputListState.key);
|
|
5049
|
+
return inputListState.elements;
|
|
5050
|
+
}
|
|
4899
5051
|
if (context.currentList && typeof context.currentIndex === "number") {
|
|
4900
5052
|
return [this.unwrapListValue(inputValue), valueToInsert];
|
|
4901
5053
|
}
|
|
@@ -4910,8 +5062,8 @@ var ActionRuntime = class {
|
|
|
4910
5062
|
return inputValue;
|
|
4911
5063
|
}
|
|
4912
5064
|
if (name === "map") {
|
|
4913
|
-
if (Array.isArray(
|
|
4914
|
-
return
|
|
5065
|
+
if (Array.isArray(inputValue)) {
|
|
5066
|
+
return inputValue.map((entry) => this.resolveMappedValue(action.args, entry, context.responseValue));
|
|
4915
5067
|
}
|
|
4916
5068
|
return this.resolveMappedValue(action.args, context.currentValue, context.responseValue);
|
|
4917
5069
|
}
|
|
@@ -4958,6 +5110,46 @@ var ActionRuntime = class {
|
|
|
4958
5110
|
isCurrentScopedReference(reference) {
|
|
4959
5111
|
return reference === "current" || reference.startsWith("current.") || reference.startsWith("this.") || reference === "this";
|
|
4960
5112
|
}
|
|
5113
|
+
countValue(value) {
|
|
5114
|
+
if (Array.isArray(value) || typeof value === "string") {
|
|
5115
|
+
return value.length;
|
|
5116
|
+
}
|
|
5117
|
+
if (value && typeof value === "object") {
|
|
5118
|
+
const widgetState = value;
|
|
5119
|
+
if (widgetState.widget === "list" || widgetState.widget === "grid-view") {
|
|
5120
|
+
return Array.isArray(widgetState.elements) ? widgetState.elements.length : 0;
|
|
5121
|
+
}
|
|
5122
|
+
if (widgetState.widget === "listbox") {
|
|
5123
|
+
return Array.isArray(widgetState.listboxElements) ? widgetState.listboxElements.length : 0;
|
|
5124
|
+
}
|
|
5125
|
+
if (widgetState.widget === "combobox") {
|
|
5126
|
+
return Array.isArray(widgetState.comboboxElements) ? widgetState.comboboxElements.length : 0;
|
|
5127
|
+
}
|
|
5128
|
+
if ("length" in widgetState && typeof widgetState.length === "number") {
|
|
5129
|
+
return widgetState.length;
|
|
5130
|
+
}
|
|
5131
|
+
}
|
|
5132
|
+
return 0;
|
|
5133
|
+
}
|
|
5134
|
+
toNumber(value) {
|
|
5135
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
5136
|
+
return value;
|
|
5137
|
+
}
|
|
5138
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
5139
|
+
const parsed = Number.parseFloat(value);
|
|
5140
|
+
if (Number.isFinite(parsed)) {
|
|
5141
|
+
return parsed;
|
|
5142
|
+
}
|
|
5143
|
+
}
|
|
5144
|
+
return 0;
|
|
5145
|
+
}
|
|
5146
|
+
asListWidgetState(value) {
|
|
5147
|
+
if (!value || typeof value !== "object") {
|
|
5148
|
+
return null;
|
|
5149
|
+
}
|
|
5150
|
+
const state = value;
|
|
5151
|
+
return state.widget === "list" || state.widget === "grid-view" ? state : null;
|
|
5152
|
+
}
|
|
4961
5153
|
};
|
|
4962
5154
|
function isIfElseArgs(value) {
|
|
4963
5155
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -5387,7 +5579,7 @@ var MAX_CONCURRENT_PLAYERS = 5;
|
|
|
5387
5579
|
var MAX_RECORDING_MS = 10 * 60 * 1e3;
|
|
5388
5580
|
var MAX_LISTENING_SILENCE_MS = 60 * 60 * 1e3;
|
|
5389
5581
|
var SILENCE_STOP_MS = 2e3;
|
|
5390
|
-
var
|
|
5582
|
+
var DEFAULT_SPEECH_THRESHOLD = 0.035;
|
|
5391
5583
|
var RECORDING_MIME_CANDIDATES = [
|
|
5392
5584
|
"audio/webm;codecs=opus",
|
|
5393
5585
|
"audio/webm",
|
|
@@ -5440,6 +5632,21 @@ function blobToBase64(blob) {
|
|
|
5440
5632
|
reader.readAsDataURL(blob);
|
|
5441
5633
|
});
|
|
5442
5634
|
}
|
|
5635
|
+
function normalizeSpeechThreshold(value) {
|
|
5636
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
5637
|
+
return Math.max(0, Math.min(1, value));
|
|
5638
|
+
}
|
|
5639
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
5640
|
+
const parsed = Number.parseFloat(value);
|
|
5641
|
+
if (Number.isFinite(parsed)) {
|
|
5642
|
+
return Math.max(0, Math.min(1, parsed));
|
|
5643
|
+
}
|
|
5644
|
+
}
|
|
5645
|
+
return DEFAULT_SPEECH_THRESHOLD;
|
|
5646
|
+
}
|
|
5647
|
+
function isStartListeningArgs(value) {
|
|
5648
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5649
|
+
}
|
|
5443
5650
|
var VoiceRuntime = class {
|
|
5444
5651
|
debugLogging;
|
|
5445
5652
|
triggerSystemEvent;
|
|
@@ -5536,11 +5743,12 @@ var VoiceRuntime = class {
|
|
|
5536
5743
|
this.clearRecordingTimeout();
|
|
5537
5744
|
this.mediaRecorder.stop();
|
|
5538
5745
|
}
|
|
5539
|
-
async startListening() {
|
|
5746
|
+
async startListening(args) {
|
|
5540
5747
|
if (this.listening) {
|
|
5541
5748
|
return;
|
|
5542
5749
|
}
|
|
5543
5750
|
try {
|
|
5751
|
+
const silenceThreshold = isStartListeningArgs(args) ? normalizeSpeechThreshold(args.silenceThreshold) : DEFAULT_SPEECH_THRESHOLD;
|
|
5544
5752
|
const stream = await this.ensureInputStream();
|
|
5545
5753
|
const context = new AudioContext();
|
|
5546
5754
|
const analyser = context.createAnalyser();
|
|
@@ -5567,7 +5775,7 @@ var VoiceRuntime = class {
|
|
|
5567
5775
|
}
|
|
5568
5776
|
const rms = Math.sqrt(squareSum / sampleBuffer.length);
|
|
5569
5777
|
const now = performance.now();
|
|
5570
|
-
if (rms >=
|
|
5778
|
+
if (rms >= silenceThreshold) {
|
|
5571
5779
|
this.lastSpeechAt = now;
|
|
5572
5780
|
this.listeningStartedAt = now;
|
|
5573
5781
|
if (!this.speechEventTriggered) {
|
|
@@ -5589,6 +5797,9 @@ var VoiceRuntime = class {
|
|
|
5589
5797
|
void step();
|
|
5590
5798
|
});
|
|
5591
5799
|
};
|
|
5800
|
+
logRuntimeDebug(this.debugLogging, "voice-listening-started", {
|
|
5801
|
+
silenceThreshold
|
|
5802
|
+
});
|
|
5592
5803
|
void step();
|
|
5593
5804
|
} catch (error) {
|
|
5594
5805
|
await this.handleListeningError(error);
|
|
@@ -6004,7 +6215,7 @@ var renderGridView = (env, node, state, key) => {
|
|
|
6004
6215
|
index: realIndex,
|
|
6005
6216
|
descriptor: element
|
|
6006
6217
|
};
|
|
6007
|
-
return `<div class="vjt-grid-cell">${env.renderNode(element, `${key}.elements.${realIndex}`, context)}</div>`;
|
|
6218
|
+
return `<div class="vjt-grid-cell" data-list-id="${env.escapeHtml(key)}" data-list-index="${realIndex}">${env.renderNode(element, `${key}.elements.${realIndex}`, context)}</div>`;
|
|
6008
6219
|
}).join("");
|
|
6009
6220
|
rows.push(`<div class="vjt-grid-row">${rowMarkup}</div>`);
|
|
6010
6221
|
}
|
|
@@ -6050,13 +6261,13 @@ var renderCombobox = (env, node, state, key) => {
|
|
|
6050
6261
|
var HEADING_TAGS = /* @__PURE__ */ new Set(["h1", "h2", "h3", "h4", "h5", "h6"]);
|
|
6051
6262
|
var TEXT_ALIGN_MAP = { left: "left", center: "center", right: "right" };
|
|
6052
6263
|
var VERTICAL_ALIGN_MAP = { top: "flex-start", center: "center", bottom: "flex-end" };
|
|
6053
|
-
var renderStaticText = (env, node, state, key) => {
|
|
6264
|
+
var renderStaticText = (env, node, state, key, _path, itemContext) => {
|
|
6054
6265
|
const resolvedHeading = node.heading && HEADING_TAGS.has(node.heading) ? node.heading : null;
|
|
6055
6266
|
const tag = resolvedHeading ?? "div";
|
|
6056
6267
|
const align = TEXT_ALIGN_MAP[node["horiz-align"] ?? "left"];
|
|
6057
6268
|
const verticalAlign = VERTICAL_ALIGN_MAP[node["vert-align"] ?? "center"];
|
|
6058
6269
|
const common = state.id ? ` id="${env.escapeHtml(state.id)}"` : "";
|
|
6059
|
-
const text = env.escapeHtml(env.
|
|
6270
|
+
const text = env.escapeHtml(env.resolveTextValue(state.text ?? node.text, itemContext));
|
|
6060
6271
|
const inlineStyle = [
|
|
6061
6272
|
"display:flex",
|
|
6062
6273
|
`align-items:${verticalAlign}`,
|
|
@@ -6087,11 +6298,11 @@ var markdownConverter = new import_showdown.default.Converter({
|
|
|
6087
6298
|
strikethrough: false,
|
|
6088
6299
|
tasklists: false
|
|
6089
6300
|
});
|
|
6090
|
-
var renderMdText = (env, node, state, key) => {
|
|
6301
|
+
var renderMdText = (env, node, state, key, _path, itemContext) => {
|
|
6091
6302
|
const align = TEXT_ALIGN_MAP2[node["horiz-align"] ?? "left"];
|
|
6092
6303
|
const verticalAlign = VERTICAL_ALIGN_MAP2[node["vert-align"] ?? "center"];
|
|
6093
6304
|
const common = state.id ? ` id="${env.escapeHtml(state.id)}"` : "";
|
|
6094
|
-
const markdown = env.
|
|
6305
|
+
const markdown = env.resolveTextValue(state.text ?? node.text, itemContext);
|
|
6095
6306
|
const html = sanitizeGeneratedHtml(markdownConverter.makeHtml(sanitizeMarkdownSource(markdown)));
|
|
6096
6307
|
const inlineStyle = [
|
|
6097
6308
|
"display:flex",
|
|
@@ -6113,24 +6324,24 @@ var renderMdText = (env, node, state, key) => {
|
|
|
6113
6324
|
};
|
|
6114
6325
|
|
|
6115
6326
|
// src/lib/widgets/edit.ts
|
|
6116
|
-
function resolvePlaceholder(env, node, statePlaceholder) {
|
|
6327
|
+
function resolvePlaceholder(env, node, itemContext, statePlaceholder) {
|
|
6117
6328
|
if (statePlaceholder) {
|
|
6118
|
-
return env.
|
|
6329
|
+
return env.resolveTextValue(statePlaceholder, itemContext);
|
|
6119
6330
|
}
|
|
6120
6331
|
if (node.placeholder) {
|
|
6121
|
-
return env.
|
|
6332
|
+
return env.resolveTextValue(node.placeholder, itemContext);
|
|
6122
6333
|
}
|
|
6123
6334
|
if ((node.type ?? "string") === "date") {
|
|
6124
6335
|
return env.getDateFormat(node);
|
|
6125
6336
|
}
|
|
6126
6337
|
return "";
|
|
6127
6338
|
}
|
|
6128
|
-
var renderEdit = (env, node, state, key) => {
|
|
6339
|
+
var renderEdit = (env, node, state, key, _path, itemContext) => {
|
|
6129
6340
|
const common = state.id ? ` id="${env.escapeHtml(state.id)}"` : "";
|
|
6130
6341
|
const enabled = state.enabled ?? env.normalizeBoolean(node.enabled, true);
|
|
6131
6342
|
const editable = state.editable ?? env.normalizeBoolean(node.editable, true);
|
|
6132
|
-
const placeholder = env.escapeHtml(resolvePlaceholder(env, node, state.placeholder));
|
|
6133
|
-
const value = env.escapeHtml(env.
|
|
6343
|
+
const placeholder = env.escapeHtml(resolvePlaceholder(env, node, itemContext, state.placeholder));
|
|
6344
|
+
const value = env.escapeHtml(env.resolveTextValue(state.text ?? node.text, itemContext));
|
|
6134
6345
|
const inputType = node.type === "password" ? "password" : "text";
|
|
6135
6346
|
const disabledAttribute = enabled ? "" : " disabled";
|
|
6136
6347
|
const readonlyAttribute = editable ? "" : " readonly";
|
|
@@ -6153,23 +6364,23 @@ var renderEdit = (env, node, state, key) => {
|
|
|
6153
6364
|
};
|
|
6154
6365
|
|
|
6155
6366
|
// src/lib/widgets/textarea.ts
|
|
6156
|
-
var renderTextarea = (env, node, state, key) => {
|
|
6367
|
+
var renderTextarea = (env, node, state, key, _path, itemContext) => {
|
|
6157
6368
|
const common = state.id ? ` id="${env.escapeHtml(state.id)}"` : "";
|
|
6158
6369
|
const enabled = state.enabled ?? env.normalizeBoolean(node.enabled, true);
|
|
6159
6370
|
const editable = state.editable ?? env.normalizeBoolean(node.editable, true);
|
|
6160
|
-
const placeholder = env.escapeHtml(env.
|
|
6161
|
-
const value = env.escapeHtml(state.text ?? env.
|
|
6371
|
+
const placeholder = env.escapeHtml(env.resolveTextValue(state.placeholder ?? node.placeholder, itemContext));
|
|
6372
|
+
const value = env.escapeHtml(state.text ?? env.resolveTextValue(node.text, itemContext));
|
|
6162
6373
|
const styleString = env.buildStyleString(node);
|
|
6163
6374
|
const styleAttribute = styleString ? ` style="${env.escapeHtml(styleString)}"` : "";
|
|
6164
6375
|
return `<textarea${common}${env.buildWidgetDataAttributes(key, node)} class="vjt-textarea" data-widget="textarea" placeholder="${placeholder}"${enabled ? "" : " disabled"}${editable ? "" : " readonly"}${styleAttribute}>${value}</textarea>`;
|
|
6165
6376
|
};
|
|
6166
6377
|
|
|
6167
6378
|
// src/lib/widgets/button.ts
|
|
6168
|
-
var renderButton = (env, node, state, key) => {
|
|
6379
|
+
var renderButton = (env, node, state, key, _path, itemContext) => {
|
|
6169
6380
|
const common = state.id ? ` id="${env.escapeHtml(state.id)}"` : "";
|
|
6170
6381
|
const enabled = state.enabled ?? env.normalizeBoolean(node.enabled, true);
|
|
6171
6382
|
const disabledAttribute = enabled ? "" : " disabled";
|
|
6172
|
-
const text = env.escapeHtml(env.
|
|
6383
|
+
const text = env.escapeHtml(env.resolveTextValue(state.text ?? node.text, itemContext));
|
|
6173
6384
|
const styleString = env.buildStyleString(node);
|
|
6174
6385
|
const styleAttribute = styleString ? ` style="${env.escapeHtml(styleString)}"` : "";
|
|
6175
6386
|
const buttonType = env.escapeHtml(node.type === "submit" ? "submit" : "button");
|
|
@@ -6218,10 +6429,10 @@ var renderImage = (env, node, state, key) => {
|
|
|
6218
6429
|
};
|
|
6219
6430
|
|
|
6220
6431
|
// src/lib/widgets/link.ts
|
|
6221
|
-
var renderLink = (env, node, state, key) => {
|
|
6432
|
+
var renderLink = (env, node, state, key, _path, itemContext) => {
|
|
6222
6433
|
const type = node.type === "button" || node.type === "text" ? node.type : "link";
|
|
6223
6434
|
const enabled = state.enabled ?? env.normalizeBoolean(node.enabled, true);
|
|
6224
|
-
const text = env.escapeHtml(env.
|
|
6435
|
+
const text = env.escapeHtml(env.resolveTextValue(state.text ?? node.text, itemContext));
|
|
6225
6436
|
const classes = `vjt-link vjt-link--${type}${enabled ? "" : " is-disabled"}`;
|
|
6226
6437
|
const styleString = env.buildStyleString(node);
|
|
6227
6438
|
const styleAttribute = styleString ? ` style="${env.escapeHtml(styleString)}"` : "";
|
|
@@ -6978,6 +7189,7 @@ var RuntimeRenderer = class {
|
|
|
6978
7189
|
i18n;
|
|
6979
7190
|
actionsMap;
|
|
6980
7191
|
requestsMap;
|
|
7192
|
+
routes;
|
|
6981
7193
|
sseConfigs;
|
|
6982
7194
|
systemEvents;
|
|
6983
7195
|
resourceManager;
|
|
@@ -6997,6 +7209,7 @@ var RuntimeRenderer = class {
|
|
|
6997
7209
|
vars = /* @__PURE__ */ new Map();
|
|
6998
7210
|
resizeHandler = null;
|
|
6999
7211
|
pointerHandler = null;
|
|
7212
|
+
popstateHandler = null;
|
|
7000
7213
|
eventSources = [];
|
|
7001
7214
|
referenceRuntime;
|
|
7002
7215
|
networkRuntime;
|
|
@@ -7009,6 +7222,9 @@ var RuntimeRenderer = class {
|
|
|
7009
7222
|
activeConfirmModal = null;
|
|
7010
7223
|
lastPointer = { x: 24, y: 24 };
|
|
7011
7224
|
pendingResetModalIds = /* @__PURE__ */ new Set();
|
|
7225
|
+
pendingScrollAction = null;
|
|
7226
|
+
pendingScrollFrameId = null;
|
|
7227
|
+
activeScrollAnimationFrameId = null;
|
|
7012
7228
|
constructor(description, options = {}) {
|
|
7013
7229
|
this.description = deepClone(description);
|
|
7014
7230
|
this.resourceManager = options.resourceManager ?? null;
|
|
@@ -7022,6 +7238,8 @@ var RuntimeRenderer = class {
|
|
|
7022
7238
|
this.theme = options.theme === "light" ? "light" : "dark";
|
|
7023
7239
|
this.actionsMap = options.actionsMap ?? this.resourceManager?.getActionsMap() ?? {};
|
|
7024
7240
|
this.requestsMap = options.requestsMap ?? this.resourceManager?.getRequestsMap() ?? {};
|
|
7241
|
+
const resolvedRoutes = options.routes ?? this.resourceManager?.getRoutes() ?? [];
|
|
7242
|
+
this.routes = Array.isArray(resolvedRoutes) ? resolvedRoutes.map((route) => ({ ...route })) : Array.isArray(resolvedRoutes?.routes) ? resolvedRoutes.routes.map((route) => ({ ...route })) : [];
|
|
7025
7243
|
const resolvedSseConfigs = options.sseConfigs ?? this.resourceManager?.getSseConfigs() ?? [];
|
|
7026
7244
|
this.sseConfigs = Array.isArray(resolvedSseConfigs) ? resolvedSseConfigs : resolvedSseConfigs ? [resolvedSseConfigs] : [];
|
|
7027
7245
|
this.systemEvents = options.systemEvents ?? this.resourceManager?.getSystemEvents() ?? {};
|
|
@@ -7035,6 +7253,7 @@ var RuntimeRenderer = class {
|
|
|
7035
7253
|
stateByKey: this.stateByKey,
|
|
7036
7254
|
nodeById: this.nodeById,
|
|
7037
7255
|
nodeByKey: this.nodeByKey,
|
|
7256
|
+
getUiResource: (ref) => this.resourceManager?.getUi(ref) ?? null,
|
|
7038
7257
|
getAppValue: (name) => {
|
|
7039
7258
|
switch (name) {
|
|
7040
7259
|
case "language":
|
|
@@ -7108,6 +7327,9 @@ var RuntimeRenderer = class {
|
|
|
7108
7327
|
clearWidget: (widgetId) => this.clearWidget(widgetId),
|
|
7109
7328
|
clearListElementState: (listKey) => this.clearListElementState(listKey),
|
|
7110
7329
|
focusWidget: (reference) => this.focusWidget(reference),
|
|
7330
|
+
scrollWidgetToTop: (reference) => this.scrollWidgetToTop(reference),
|
|
7331
|
+
scrollWidgetToBottom: (reference) => this.scrollWidgetToBottom(reference),
|
|
7332
|
+
scrollWidgetToElementByIndex: (reference, index) => this.scrollWidgetToElementByIndex(reference, index),
|
|
7111
7333
|
playAudio: (value) => this.voiceRuntime.play(value),
|
|
7112
7334
|
stopPlaying: () => this.voiceRuntime.stopPlaying(),
|
|
7113
7335
|
copyToClipboard: (value) => this.copyToClipboard(value),
|
|
@@ -7115,7 +7337,7 @@ var RuntimeRenderer = class {
|
|
|
7115
7337
|
confirmModal: (args, inputValue) => this.confirmModal(args, inputValue),
|
|
7116
7338
|
startRecording: () => this.voiceRuntime.startRecording(),
|
|
7117
7339
|
stopRecording: () => Promise.resolve(this.voiceRuntime.stopRecording()),
|
|
7118
|
-
startListening: () => this.voiceRuntime.startListening(),
|
|
7340
|
+
startListening: (args) => this.voiceRuntime.startListening(args),
|
|
7119
7341
|
stopListening: () => this.voiceRuntime.stopListening(),
|
|
7120
7342
|
setUiReference: (widgetId, resourceRef) => {
|
|
7121
7343
|
const node = this.nodeById.get(widgetId);
|
|
@@ -7145,11 +7367,12 @@ var RuntimeRenderer = class {
|
|
|
7145
7367
|
getInlineActions: (node) => this.getInlineActions(node),
|
|
7146
7368
|
isWidgetEnabled: (node, key) => this.isWidgetEnabled(node, key)
|
|
7147
7369
|
});
|
|
7148
|
-
this.indexStaticNodes(this.
|
|
7370
|
+
this.indexStaticNodes(this.getActiveDescription(), "root");
|
|
7149
7371
|
this.applyRuntimeSnapshot(this.initialRuntimeSnapshot);
|
|
7150
7372
|
}
|
|
7151
7373
|
renderMarkup() {
|
|
7152
|
-
const
|
|
7374
|
+
const activeDescription = this.getActiveDescription();
|
|
7375
|
+
const markup = `${this.renderNode(activeDescription, "root", null)}${this.renderGlobalOverlays()}`;
|
|
7153
7376
|
logRuntimeDebug(this.debugLogging, "html", markup);
|
|
7154
7377
|
return markup;
|
|
7155
7378
|
}
|
|
@@ -7199,6 +7422,17 @@ var RuntimeRenderer = class {
|
|
|
7199
7422
|
};
|
|
7200
7423
|
window.addEventListener("pointerdown", handlePointer);
|
|
7201
7424
|
this.pointerHandler = handlePointer;
|
|
7425
|
+
const handlePopState = () => {
|
|
7426
|
+
void (async () => {
|
|
7427
|
+
await this.runSystemEvent("onBeforeNavigate");
|
|
7428
|
+
await this.rerenderRoot();
|
|
7429
|
+
await this.runSystemEvent("onAfterNavigate");
|
|
7430
|
+
})().catch((error) => {
|
|
7431
|
+
logRuntimeError("popstate", error);
|
|
7432
|
+
});
|
|
7433
|
+
};
|
|
7434
|
+
window.addEventListener("popstate", handlePopState);
|
|
7435
|
+
this.popstateHandler = handlePopState;
|
|
7202
7436
|
return () => {
|
|
7203
7437
|
if (this.resizeHandler) {
|
|
7204
7438
|
window.removeEventListener("resize", this.resizeHandler);
|
|
@@ -7206,6 +7440,9 @@ var RuntimeRenderer = class {
|
|
|
7206
7440
|
if (this.pointerHandler) {
|
|
7207
7441
|
window.removeEventListener("pointerdown", this.pointerHandler);
|
|
7208
7442
|
}
|
|
7443
|
+
if (this.popstateHandler) {
|
|
7444
|
+
window.removeEventListener("popstate", this.popstateHandler);
|
|
7445
|
+
}
|
|
7209
7446
|
for (const source of this.eventSources) {
|
|
7210
7447
|
source.close();
|
|
7211
7448
|
}
|
|
@@ -7228,6 +7465,7 @@ var RuntimeRenderer = class {
|
|
|
7228
7465
|
this.attachInputBehavior(this.root);
|
|
7229
7466
|
this.attachWidgetEvents(this.root);
|
|
7230
7467
|
restoreElementState(this.root, preservedState, this.stateByKey);
|
|
7468
|
+
this.applyPendingScrollAction();
|
|
7231
7469
|
this.activeContextMenu = adjustContextMenuPosition(this.root, this.activeContextMenu);
|
|
7232
7470
|
this.pendingResetModalIds.clear();
|
|
7233
7471
|
if (typeof this.onRuntimeSnapshot === "function") {
|
|
@@ -7407,7 +7645,113 @@ var RuntimeRenderer = class {
|
|
|
7407
7645
|
this.nodeByKey.clear();
|
|
7408
7646
|
this.nodeById.clear();
|
|
7409
7647
|
this.stateById.clear();
|
|
7410
|
-
this.indexStaticNodes(this.
|
|
7648
|
+
this.indexStaticNodes(this.getActiveDescription(), "root");
|
|
7649
|
+
}
|
|
7650
|
+
getActiveDescription() {
|
|
7651
|
+
if (this.hasRoutes() && !this.isCurrentPathValid()) {
|
|
7652
|
+
return this.buildNotFoundDescription(this.getCurrentPathname());
|
|
7653
|
+
}
|
|
7654
|
+
return this.description;
|
|
7655
|
+
}
|
|
7656
|
+
hasRoutes() {
|
|
7657
|
+
return this.routes.length > 0;
|
|
7658
|
+
}
|
|
7659
|
+
isCurrentPathValid() {
|
|
7660
|
+
const pathname = this.getCurrentPathname();
|
|
7661
|
+
if (pathname === "/") {
|
|
7662
|
+
return true;
|
|
7663
|
+
}
|
|
7664
|
+
return this.routes.some((entry) => this.normalizePathname(entry.path) === pathname);
|
|
7665
|
+
}
|
|
7666
|
+
getCurrentPathname() {
|
|
7667
|
+
if (typeof window === "undefined") {
|
|
7668
|
+
return "/";
|
|
7669
|
+
}
|
|
7670
|
+
return this.normalizePathname(window.location.pathname);
|
|
7671
|
+
}
|
|
7672
|
+
normalizePathname(path) {
|
|
7673
|
+
if (!path || path === "/" || path === "/index.html") {
|
|
7674
|
+
return "/";
|
|
7675
|
+
}
|
|
7676
|
+
const normalized = path.startsWith("/") ? path : `/${path}`;
|
|
7677
|
+
return normalized.length > 1 ? normalized.replace(/\/+$/, "") : normalized;
|
|
7678
|
+
}
|
|
7679
|
+
buildNotFoundDescription(pathname) {
|
|
7680
|
+
const dictionary = this.getBuiltinNotFoundTexts();
|
|
7681
|
+
return {
|
|
7682
|
+
widget: "panel",
|
|
7683
|
+
id: "vjt-not-found-panel",
|
|
7684
|
+
css: "position:fixed;left:50%;top:50%;transform:translate(-50%,-50%);width:min(520px, calc(100vw - 32px));padding:28px;border-radius:20px;background:color-mix(in srgb, var(--vjt-surface) 92%, black 8%);border:1px solid var(--vjt-border);box-shadow:var(--vjt-shadow);",
|
|
7685
|
+
child: {
|
|
7686
|
+
widget: "container-layout",
|
|
7687
|
+
type: "vertical",
|
|
7688
|
+
children: [
|
|
7689
|
+
{
|
|
7690
|
+
minHeightPx: 64,
|
|
7691
|
+
maxHeightPx: 64,
|
|
7692
|
+
marginBottomPx: 8,
|
|
7693
|
+
child: {
|
|
7694
|
+
widget: "static-text",
|
|
7695
|
+
heading: "h1",
|
|
7696
|
+
text: dictionary.title,
|
|
7697
|
+
css: "font-size:42px;font-weight:800;letter-spacing:0.04em;text-align:center;justify-content:center;"
|
|
7698
|
+
}
|
|
7699
|
+
},
|
|
7700
|
+
{
|
|
7701
|
+
minHeightPx: 36,
|
|
7702
|
+
maxHeightPx: 36,
|
|
7703
|
+
marginBottomPx: 8,
|
|
7704
|
+
child: {
|
|
7705
|
+
widget: "static-text",
|
|
7706
|
+
heading: "h3",
|
|
7707
|
+
text: dictionary.caption,
|
|
7708
|
+
css: "text-align:center;justify-content:center;"
|
|
7709
|
+
}
|
|
7710
|
+
},
|
|
7711
|
+
{
|
|
7712
|
+
minHeightPx: 64,
|
|
7713
|
+
marginBottomPx: 16,
|
|
7714
|
+
child: {
|
|
7715
|
+
widget: "static-text",
|
|
7716
|
+
text: `${dictionary.note} ${pathname}`,
|
|
7717
|
+
css: "text-align:center;justify-content:center;color:var(--vjt-muted);"
|
|
7718
|
+
}
|
|
7719
|
+
},
|
|
7720
|
+
{
|
|
7721
|
+
minHeightPx: 52,
|
|
7722
|
+
maxHeightPx: 52,
|
|
7723
|
+
child: {
|
|
7724
|
+
widget: "button",
|
|
7725
|
+
text: dictionary.home,
|
|
7726
|
+
events: {
|
|
7727
|
+
onClick: [
|
|
7728
|
+
{
|
|
7729
|
+
action: "navigate /"
|
|
7730
|
+
}
|
|
7731
|
+
]
|
|
7732
|
+
}
|
|
7733
|
+
}
|
|
7734
|
+
}
|
|
7735
|
+
]
|
|
7736
|
+
}
|
|
7737
|
+
};
|
|
7738
|
+
}
|
|
7739
|
+
getBuiltinNotFoundTexts() {
|
|
7740
|
+
const language = this.language.toLowerCase();
|
|
7741
|
+
if (language.startsWith("ru")) {
|
|
7742
|
+
return {
|
|
7743
|
+
title: "404",
|
|
7744
|
+
caption: "\u0421\u0442\u0440\u0430\u043D\u0438\u0446\u0430 \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u0430",
|
|
7745
|
+
note: "\u0417\u0430\u043F\u0440\u043E\u0448\u0435\u043D\u043D\u044B\u0439 \u043F\u0443\u0442\u044C \u043D\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442:",
|
|
7746
|
+
home: "\u041D\u0430 \u0433\u043B\u0430\u0432\u043D\u0443\u044E"
|
|
7747
|
+
};
|
|
7748
|
+
}
|
|
7749
|
+
return {
|
|
7750
|
+
title: "404",
|
|
7751
|
+
caption: "Page not found",
|
|
7752
|
+
note: "The requested path does not exist:",
|
|
7753
|
+
home: "Go home"
|
|
7754
|
+
};
|
|
7411
7755
|
}
|
|
7412
7756
|
getUiReferenceTarget(node, key) {
|
|
7413
7757
|
if (node.widget !== "ui-reference") {
|
|
@@ -7865,6 +8209,20 @@ var RuntimeRenderer = class {
|
|
|
7865
8209
|
}
|
|
7866
8210
|
return `??${key}??`;
|
|
7867
8211
|
}
|
|
8212
|
+
resolveTextValue(value, itemContext) {
|
|
8213
|
+
if (typeof value !== "string") {
|
|
8214
|
+
return value ?? "";
|
|
8215
|
+
}
|
|
8216
|
+
if (value.startsWith("$ref:")) {
|
|
8217
|
+
const resolved = this.referenceRuntime.resolveReference(value.slice(5), itemContext, null);
|
|
8218
|
+
if (resolved == null) {
|
|
8219
|
+
return "";
|
|
8220
|
+
}
|
|
8221
|
+
const resolvedText = typeof resolved === "string" ? resolved : typeof resolved === "number" || typeof resolved === "boolean" || typeof resolved === "bigint" ? String(resolved) : JSON.stringify(resolved);
|
|
8222
|
+
return this.resolveI18nValue(resolvedText);
|
|
8223
|
+
}
|
|
8224
|
+
return this.resolveI18nValue(value);
|
|
8225
|
+
}
|
|
7868
8226
|
buildWidgetDataAttributes(key, node) {
|
|
7869
8227
|
const parts = [` data-widget-key="${escapeHtml(key)}"`];
|
|
7870
8228
|
if (node.id) {
|
|
@@ -7883,6 +8241,7 @@ var RuntimeRenderer = class {
|
|
|
7883
8241
|
escapeHtml,
|
|
7884
8242
|
buildStyleString: (node) => this.buildStyleString(node),
|
|
7885
8243
|
resolveI18nValue: (value) => this.resolveI18nValue(value),
|
|
8244
|
+
resolveTextValue: (value, itemContext) => this.resolveTextValue(value, itemContext),
|
|
7886
8245
|
getUiResource: (ref) => this.resourceManager?.getUi(ref) ?? null,
|
|
7887
8246
|
resolveReference: (reference, currentValue, responseValue) => this.referenceRuntime.resolveReference(reference, currentValue, responseValue),
|
|
7888
8247
|
buildWidgetDataAttributes: (key, node) => this.buildWidgetDataAttributes(key, node),
|
|
@@ -8428,6 +8787,138 @@ var RuntimeRenderer = class {
|
|
|
8428
8787
|
nestedTarget.focus({ preventScroll: true });
|
|
8429
8788
|
}
|
|
8430
8789
|
}
|
|
8790
|
+
scrollWidgetToTop(reference) {
|
|
8791
|
+
this.pendingScrollAction = { kind: "top", reference };
|
|
8792
|
+
this.schedulePendingScrollAction();
|
|
8793
|
+
}
|
|
8794
|
+
scrollWidgetToBottom(reference) {
|
|
8795
|
+
this.pendingScrollAction = { kind: "bottom", reference };
|
|
8796
|
+
this.schedulePendingScrollAction();
|
|
8797
|
+
}
|
|
8798
|
+
scrollWidgetToElementByIndex(reference, indexValue) {
|
|
8799
|
+
this.pendingScrollAction = { kind: "index", reference, indexValue };
|
|
8800
|
+
this.schedulePendingScrollAction();
|
|
8801
|
+
}
|
|
8802
|
+
schedulePendingScrollAction() {
|
|
8803
|
+
if (typeof window === "undefined" || this.pendingScrollFrameId !== null) {
|
|
8804
|
+
return;
|
|
8805
|
+
}
|
|
8806
|
+
this.pendingScrollFrameId = window.requestAnimationFrame(() => {
|
|
8807
|
+
this.pendingScrollFrameId = null;
|
|
8808
|
+
this.applyPendingScrollAction();
|
|
8809
|
+
});
|
|
8810
|
+
}
|
|
8811
|
+
applyPendingScrollAction() {
|
|
8812
|
+
if (!this.pendingScrollAction) {
|
|
8813
|
+
return;
|
|
8814
|
+
}
|
|
8815
|
+
const pending = this.pendingScrollAction;
|
|
8816
|
+
const element = this.findScrollableWidgetElement(pending.reference);
|
|
8817
|
+
if (!element) {
|
|
8818
|
+
return;
|
|
8819
|
+
}
|
|
8820
|
+
if (pending.kind === "top") {
|
|
8821
|
+
this.animateScrollTop(element, 0);
|
|
8822
|
+
this.pendingScrollAction = null;
|
|
8823
|
+
return;
|
|
8824
|
+
}
|
|
8825
|
+
if (pending.kind === "bottom") {
|
|
8826
|
+
this.animateScrollTop(element, element.scrollHeight);
|
|
8827
|
+
this.pendingScrollAction = null;
|
|
8828
|
+
return;
|
|
8829
|
+
}
|
|
8830
|
+
const index = this.toScrollableIndex(pending.indexValue);
|
|
8831
|
+
if (index === null) {
|
|
8832
|
+
this.pendingScrollAction = null;
|
|
8833
|
+
return;
|
|
8834
|
+
}
|
|
8835
|
+
this.performScrollToElementByIndex(element, index);
|
|
8836
|
+
this.pendingScrollAction = null;
|
|
8837
|
+
}
|
|
8838
|
+
performScrollToElementByIndex(element, index) {
|
|
8839
|
+
if (element instanceof HTMLSelectElement) {
|
|
8840
|
+
const option = element.options.item(index);
|
|
8841
|
+
if (!option) {
|
|
8842
|
+
return;
|
|
8843
|
+
}
|
|
8844
|
+
const maxScrollTop = Math.max(0, element.scrollHeight - element.clientHeight);
|
|
8845
|
+
this.animateScrollTop(element, Math.max(0, Math.min(option.offsetTop, maxScrollTop)));
|
|
8846
|
+
return;
|
|
8847
|
+
}
|
|
8848
|
+
const listElement = element.querySelector(`.vjt-list-element[data-list-index="${index}"], .vjt-grid-cell[data-list-index="${index}"]`);
|
|
8849
|
+
if (listElement instanceof HTMLElement) {
|
|
8850
|
+
const maxScrollTop = Math.max(0, element.scrollHeight - element.clientHeight);
|
|
8851
|
+
const containerRect = element.getBoundingClientRect();
|
|
8852
|
+
const itemRect = listElement.getBoundingClientRect();
|
|
8853
|
+
const targetTop = element.scrollTop + (itemRect.top - containerRect.top);
|
|
8854
|
+
const remainingContentHeight = element.scrollHeight - targetTop;
|
|
8855
|
+
const nextScrollTop = remainingContentHeight > element.clientHeight ? Math.max(0, Math.min(targetTop, maxScrollTop)) : maxScrollTop;
|
|
8856
|
+
this.animateScrollTop(element, nextScrollTop);
|
|
8857
|
+
}
|
|
8858
|
+
}
|
|
8859
|
+
animateScrollTop(element, targetTop) {
|
|
8860
|
+
if (typeof window === "undefined") {
|
|
8861
|
+
element.scrollTop = targetTop;
|
|
8862
|
+
return;
|
|
8863
|
+
}
|
|
8864
|
+
if (this.activeScrollAnimationFrameId !== null) {
|
|
8865
|
+
window.cancelAnimationFrame(this.activeScrollAnimationFrameId);
|
|
8866
|
+
this.activeScrollAnimationFrameId = null;
|
|
8867
|
+
}
|
|
8868
|
+
const startTop = element.scrollTop;
|
|
8869
|
+
const clampedTargetTop = Math.max(0, targetTop);
|
|
8870
|
+
const delta = clampedTargetTop - startTop;
|
|
8871
|
+
if (Math.abs(delta) < 1) {
|
|
8872
|
+
element.scrollTop = clampedTargetTop;
|
|
8873
|
+
return;
|
|
8874
|
+
}
|
|
8875
|
+
const durationMs = 300;
|
|
8876
|
+
const startTime = window.performance.now();
|
|
8877
|
+
const easeInOutCubic = (t) => t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;
|
|
8878
|
+
const tick = (now) => {
|
|
8879
|
+
const elapsed = now - startTime;
|
|
8880
|
+
const progress = Math.min(1, elapsed / durationMs);
|
|
8881
|
+
element.scrollTop = startTop + delta * easeInOutCubic(progress);
|
|
8882
|
+
if (progress < 1) {
|
|
8883
|
+
this.activeScrollAnimationFrameId = window.requestAnimationFrame(tick);
|
|
8884
|
+
} else {
|
|
8885
|
+
element.scrollTop = clampedTargetTop;
|
|
8886
|
+
this.activeScrollAnimationFrameId = null;
|
|
8887
|
+
}
|
|
8888
|
+
};
|
|
8889
|
+
this.activeScrollAnimationFrameId = window.requestAnimationFrame(tick);
|
|
8890
|
+
}
|
|
8891
|
+
findScrollableWidgetElement(reference) {
|
|
8892
|
+
if (!(this.root instanceof HTMLElement)) {
|
|
8893
|
+
return null;
|
|
8894
|
+
}
|
|
8895
|
+
const widgetId = reference.split(".")[0]?.trim();
|
|
8896
|
+
if (!widgetId) {
|
|
8897
|
+
return null;
|
|
8898
|
+
}
|
|
8899
|
+
const directTarget = this.root.querySelector(`#${CSS.escape(widgetId)}`);
|
|
8900
|
+
if (directTarget) {
|
|
8901
|
+
return directTarget;
|
|
8902
|
+
}
|
|
8903
|
+
for (const element of Array.from(this.root.querySelectorAll("[data-widget-id]"))) {
|
|
8904
|
+
if (element.dataset.widgetId === widgetId) {
|
|
8905
|
+
return element;
|
|
8906
|
+
}
|
|
8907
|
+
}
|
|
8908
|
+
return null;
|
|
8909
|
+
}
|
|
8910
|
+
toScrollableIndex(value) {
|
|
8911
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
8912
|
+
return Math.max(0, Math.trunc(value));
|
|
8913
|
+
}
|
|
8914
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
8915
|
+
const parsed = Number.parseInt(value, 10);
|
|
8916
|
+
if (Number.isFinite(parsed)) {
|
|
8917
|
+
return Math.max(0, parsed);
|
|
8918
|
+
}
|
|
8919
|
+
}
|
|
8920
|
+
return null;
|
|
8921
|
+
}
|
|
8431
8922
|
};
|
|
8432
8923
|
function renderJson(description, options = {}) {
|
|
8433
8924
|
const renderer = new RuntimeRenderer(description, options);
|
|
@@ -8443,6 +8934,7 @@ var ResourceManager = class {
|
|
|
8443
8934
|
ui = /* @__PURE__ */ new Map();
|
|
8444
8935
|
actions = {};
|
|
8445
8936
|
requests = {};
|
|
8937
|
+
routes = [];
|
|
8446
8938
|
sse = {};
|
|
8447
8939
|
systemEvents = {};
|
|
8448
8940
|
i18n = {};
|
|
@@ -8453,6 +8945,7 @@ var ResourceManager = class {
|
|
|
8453
8945
|
}
|
|
8454
8946
|
this.actions = { ...input.actions ?? {} };
|
|
8455
8947
|
this.requests = { ...input.requests ?? {} };
|
|
8948
|
+
this.routes = Array.isArray(input.routes) ? input.routes.map((route) => ({ ...route })) : Array.isArray(input.routes?.routes) ? input.routes.routes.map((route) => ({ ...route })) : [];
|
|
8456
8949
|
this.sse = { ...input.sse ?? {} };
|
|
8457
8950
|
this.systemEvents = { ...input.systemEvents ?? {} };
|
|
8458
8951
|
this.i18n = { ...input.i18n ?? {} };
|
|
@@ -8470,6 +8963,9 @@ var ResourceManager = class {
|
|
|
8470
8963
|
getRequestsMap() {
|
|
8471
8964
|
return this.requests;
|
|
8472
8965
|
}
|
|
8966
|
+
getRoutes() {
|
|
8967
|
+
return this.routes.map((route) => ({ ...route }));
|
|
8968
|
+
}
|
|
8473
8969
|
getSseConfigs() {
|
|
8474
8970
|
return Object.values(this.sse);
|
|
8475
8971
|
}
|
|
@@ -32,6 +32,9 @@ type ActionRuntimeOptions = {
|
|
|
32
32
|
clearWidget: (widgetId: string) => void;
|
|
33
33
|
clearListElementState: (listKey: string) => void;
|
|
34
34
|
focusWidget: (reference: string) => void;
|
|
35
|
+
scrollWidgetToTop: (reference: string) => void;
|
|
36
|
+
scrollWidgetToBottom: (reference: string) => void;
|
|
37
|
+
scrollWidgetToElementByIndex: (reference: string, index: unknown) => void;
|
|
35
38
|
playAudio: (value: unknown) => Promise<void>;
|
|
36
39
|
stopPlaying: () => Promise<void>;
|
|
37
40
|
copyToClipboard: (value: unknown) => Promise<void>;
|
|
@@ -39,7 +42,7 @@ type ActionRuntimeOptions = {
|
|
|
39
42
|
confirmModal: (options: unknown, inputValue: unknown) => Promise<boolean>;
|
|
40
43
|
startRecording: () => Promise<void>;
|
|
41
44
|
stopRecording: () => Promise<void>;
|
|
42
|
-
startListening: () => Promise<void>;
|
|
45
|
+
startListening: (args?: unknown) => Promise<void>;
|
|
43
46
|
stopListening: () => Promise<void>;
|
|
44
47
|
setUiReference: (widgetId: string, resourceRef: string) => void;
|
|
45
48
|
refreshWidgetTree: (widgetId: string) => Promise<void>;
|
|
@@ -82,6 +85,9 @@ export declare class ActionRuntime {
|
|
|
82
85
|
private readonly clearWidget;
|
|
83
86
|
private readonly clearListElementState;
|
|
84
87
|
private readonly focusWidget;
|
|
88
|
+
private readonly scrollWidgetToTop;
|
|
89
|
+
private readonly scrollWidgetToBottom;
|
|
90
|
+
private readonly scrollWidgetToElementByIndex;
|
|
85
91
|
private readonly playAudio;
|
|
86
92
|
private readonly stopPlaying;
|
|
87
93
|
private readonly copyToClipboard;
|
|
@@ -115,5 +121,8 @@ export declare class ActionRuntime {
|
|
|
115
121
|
private cloneValue;
|
|
116
122
|
private stringifyValue;
|
|
117
123
|
private isCurrentScopedReference;
|
|
124
|
+
private countValue;
|
|
125
|
+
private toNumber;
|
|
126
|
+
private asListWidgetState;
|
|
118
127
|
}
|
|
119
128
|
export {};
|
package/dist/lib/references.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ type ReferenceRuntimeHost = {
|
|
|
4
4
|
readonly stateByKey: Map<string, WidgetState>;
|
|
5
5
|
readonly nodeById: Map<string, DescriptionNode>;
|
|
6
6
|
readonly nodeByKey: Map<string, DescriptionNode>;
|
|
7
|
+
getUiResource: (ref: string) => DescriptionNode | null;
|
|
7
8
|
getAppValue: (name: string) => unknown;
|
|
8
9
|
setAppValue: (name: string, value: unknown) => void;
|
|
9
10
|
getVarValue: (name: string) => unknown;
|
|
@@ -19,12 +20,15 @@ export declare class ReferenceRuntime {
|
|
|
19
20
|
resolveReference(reference: string, currentValue: unknown, responseValue: unknown): unknown;
|
|
20
21
|
resolveCurrentReference(reference: string, currentValue: unknown): unknown;
|
|
21
22
|
readWidgetField(state: WidgetState, field: string): unknown;
|
|
22
|
-
assignReference(reference: string, inputValue: unknown,
|
|
23
|
+
assignReference(reference: string, inputValue: unknown, currentValue: unknown, options?: {
|
|
23
24
|
cookieTtl?: unknown;
|
|
24
25
|
}): void;
|
|
26
|
+
private assignCurrentReference;
|
|
25
27
|
clearListElementState(listKey: string): void;
|
|
26
28
|
resolveMappedValue(template: unknown, currentValue: unknown, responseValue: unknown): unknown;
|
|
27
29
|
isListElementContext(value: unknown): value is ListElementContext;
|
|
28
|
-
findNamedWidget(node: DescriptionNode | undefined, name: string): DescriptionNode | null;
|
|
30
|
+
findNamedWidget(node: DescriptionNode | undefined, name: string, currentValue?: unknown): DescriptionNode | null;
|
|
31
|
+
private resolveListDescriptorNode;
|
|
32
|
+
private resolveUiReferenceNode;
|
|
29
33
|
}
|
|
30
34
|
export {};
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import type { ActionMap, DescriptionNode, I18nMap, RequestMap, SseConfig, SystemEventsMap, StyleMap } from './types.js';
|
|
1
|
+
import type { ActionMap, DescriptionNode, I18nMap, RequestMap, RouteDefinition, RoutesConfigInput, SseConfig, SystemEventsMap, StyleMap } from './types.js';
|
|
2
2
|
export type ResourceManagerInput = {
|
|
3
3
|
ui?: Record<string, DescriptionNode>;
|
|
4
4
|
actions?: ActionMap;
|
|
5
5
|
requests?: RequestMap;
|
|
6
|
+
routes?: RoutesConfigInput;
|
|
6
7
|
sse?: Record<string, SseConfig>;
|
|
7
8
|
systemEvents?: SystemEventsMap;
|
|
8
9
|
i18n?: I18nMap;
|
|
@@ -12,6 +13,7 @@ export declare class ResourceManager {
|
|
|
12
13
|
private readonly ui;
|
|
13
14
|
private actions;
|
|
14
15
|
private requests;
|
|
16
|
+
private routes;
|
|
15
17
|
private sse;
|
|
16
18
|
private systemEvents;
|
|
17
19
|
private i18n;
|
|
@@ -21,6 +23,7 @@ export declare class ResourceManager {
|
|
|
21
23
|
setUi(name: string, description: DescriptionNode): void;
|
|
22
24
|
getActionsMap(): ActionMap;
|
|
23
25
|
getRequestsMap(): RequestMap;
|
|
26
|
+
getRoutes(): RouteDefinition[];
|
|
24
27
|
getSseConfigs(): SseConfig[];
|
|
25
28
|
getSystemEvents(): SystemEventsMap;
|
|
26
29
|
getI18n(): I18nMap;
|
package/dist/lib/types.d.ts
CHANGED
|
@@ -6,6 +6,13 @@ export type HeadingTag = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
|
|
|
6
6
|
export type WidgetEventName = 'onClick' | 'onUserValueChange' | 'onRefresh' | 'onEnter' | 'onShiftEnter' | 'onControlEnter';
|
|
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
|
+
export type RouteDefinition = {
|
|
10
|
+
path: string;
|
|
11
|
+
ui: string;
|
|
12
|
+
};
|
|
13
|
+
export type RoutesConfigInput = RouteDefinition[] | {
|
|
14
|
+
routes: RouteDefinition[];
|
|
15
|
+
};
|
|
9
16
|
export type ActionDefinition = {
|
|
10
17
|
action: string;
|
|
11
18
|
andThen?: ActionDefinition[];
|
|
@@ -139,6 +146,7 @@ export type RenderJsonOptions = {
|
|
|
139
146
|
requestsMap?: RequestMap;
|
|
140
147
|
sseConfigs?: SseConfigInput;
|
|
141
148
|
systemEvents?: SystemEventsMap;
|
|
149
|
+
routes?: RoutesConfigInput;
|
|
142
150
|
actionFunctions?: Record<string, () => unknown>;
|
|
143
151
|
backendUrl?: string;
|
|
144
152
|
resourceManager?: ResourceManager;
|
|
@@ -27,7 +27,7 @@ export declare class VoiceRuntime {
|
|
|
27
27
|
stopPlaying(): Promise<void>;
|
|
28
28
|
startRecording(): Promise<void>;
|
|
29
29
|
stopRecording(): void;
|
|
30
|
-
startListening(): Promise<void>;
|
|
30
|
+
startListening(args?: unknown): Promise<void>;
|
|
31
31
|
stopListening(): Promise<void>;
|
|
32
32
|
dispose(): void;
|
|
33
33
|
private startRecordingInternal;
|
|
@@ -29,6 +29,7 @@ export type WidgetRenderEnvironment = {
|
|
|
29
29
|
escapeHtml: (value: unknown) => string;
|
|
30
30
|
buildStyleString: (node: DescriptionNode) => string;
|
|
31
31
|
resolveI18nValue: (value: string | undefined) => string;
|
|
32
|
+
resolveTextValue: (value: string | undefined, itemContext: ListElementContext | null) => string;
|
|
32
33
|
getUiResource: (ref: string) => DescriptionNode | null;
|
|
33
34
|
resolveReference: (reference: string, currentValue: unknown, responseValue: unknown) => unknown;
|
|
34
35
|
buildWidgetDataAttributes: (key: string, node: DescriptionNode) => string;
|