@vortexm/vjt 0.1.7 → 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 +541 -51
- 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;
|
|
@@ -4678,7 +4752,7 @@ var ActionRuntime = class {
|
|
|
4678
4752
|
let output = rawOutput;
|
|
4679
4753
|
if (action.andThen?.length) {
|
|
4680
4754
|
if (output !== null && output !== void 0) {
|
|
4681
|
-
output = await this.runActions(action.andThen, output,
|
|
4755
|
+
output = await this.runActions(action.andThen, output, context);
|
|
4682
4756
|
} else {
|
|
4683
4757
|
output = null;
|
|
4684
4758
|
}
|
|
@@ -4765,7 +4839,7 @@ var ActionRuntime = class {
|
|
|
4765
4839
|
return null;
|
|
4766
4840
|
}
|
|
4767
4841
|
if (name === "startListening") {
|
|
4768
|
-
await this.startListening();
|
|
4842
|
+
await this.startListening(action.args);
|
|
4769
4843
|
return null;
|
|
4770
4844
|
}
|
|
4771
4845
|
if (name === "stopListening") {
|
|
@@ -4817,6 +4891,18 @@ var ActionRuntime = class {
|
|
|
4817
4891
|
this.focusWidget(name.slice(9));
|
|
4818
4892
|
return null;
|
|
4819
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
|
+
}
|
|
4820
4906
|
if (name.startsWith("setUi ")) {
|
|
4821
4907
|
const widgetId = name.slice(6);
|
|
4822
4908
|
const resourceRef = typeof inputValue === "string" ? inputValue : "";
|
|
@@ -4827,14 +4913,62 @@ var ActionRuntime = class {
|
|
|
4827
4913
|
}
|
|
4828
4914
|
if (name.startsWith("get ")) {
|
|
4829
4915
|
const reference = name.slice(4);
|
|
4830
|
-
if (Array.isArray(
|
|
4831
|
-
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);
|
|
4832
4918
|
}
|
|
4833
4919
|
return this.resolveReference(reference, context.currentValue, context.responseValue);
|
|
4834
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
|
+
}
|
|
4835
4954
|
if (name.startsWith("equals ")) {
|
|
4836
4955
|
return this.resolveReference(name.slice(7), context.currentValue, context.responseValue) === action.args;
|
|
4837
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
|
+
}
|
|
4838
4972
|
if (name.startsWith("isEmpty ")) {
|
|
4839
4973
|
return this.isEmptyReference(name.slice(8), context.currentValue, context.responseValue);
|
|
4840
4974
|
}
|
|
@@ -4852,8 +4986,8 @@ var ActionRuntime = class {
|
|
|
4852
4986
|
}
|
|
4853
4987
|
if (name.startsWith("filter ")) {
|
|
4854
4988
|
const reference = name.slice(7);
|
|
4855
|
-
if (Array.isArray(
|
|
4856
|
-
return
|
|
4989
|
+
if (Array.isArray(inputValue) && this.isCurrentScopedReference(reference)) {
|
|
4990
|
+
return inputValue.filter((entry) => this.resolveReference(reference, entry, context.responseValue));
|
|
4857
4991
|
}
|
|
4858
4992
|
const value = this.resolveReference(reference, context.currentValue, context.responseValue);
|
|
4859
4993
|
return value ? inputValue : null;
|
|
@@ -4878,6 +5012,12 @@ var ActionRuntime = class {
|
|
|
4878
5012
|
this.clearListElementState(listState.key);
|
|
4879
5013
|
return listState.elements;
|
|
4880
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
|
+
}
|
|
4881
5021
|
if (context.currentList && typeof context.currentIndex === "number") {
|
|
4882
5022
|
return context.currentIndex === context.currentList.length - 1 ? [this.unwrapListValue(inputValue), valueToAdd] : this.unwrapListValue(inputValue);
|
|
4883
5023
|
}
|
|
@@ -4902,6 +5042,12 @@ var ActionRuntime = class {
|
|
|
4902
5042
|
return listState.elements;
|
|
4903
5043
|
}
|
|
4904
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
|
+
}
|
|
4905
5051
|
if (context.currentList && typeof context.currentIndex === "number") {
|
|
4906
5052
|
return [this.unwrapListValue(inputValue), valueToInsert];
|
|
4907
5053
|
}
|
|
@@ -4916,8 +5062,8 @@ var ActionRuntime = class {
|
|
|
4916
5062
|
return inputValue;
|
|
4917
5063
|
}
|
|
4918
5064
|
if (name === "map") {
|
|
4919
|
-
if (Array.isArray(
|
|
4920
|
-
return
|
|
5065
|
+
if (Array.isArray(inputValue)) {
|
|
5066
|
+
return inputValue.map((entry) => this.resolveMappedValue(action.args, entry, context.responseValue));
|
|
4921
5067
|
}
|
|
4922
5068
|
return this.resolveMappedValue(action.args, context.currentValue, context.responseValue);
|
|
4923
5069
|
}
|
|
@@ -4964,6 +5110,46 @@ var ActionRuntime = class {
|
|
|
4964
5110
|
isCurrentScopedReference(reference) {
|
|
4965
5111
|
return reference === "current" || reference.startsWith("current.") || reference.startsWith("this.") || reference === "this";
|
|
4966
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
|
+
}
|
|
4967
5153
|
};
|
|
4968
5154
|
function isIfElseArgs(value) {
|
|
4969
5155
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -5393,7 +5579,7 @@ var MAX_CONCURRENT_PLAYERS = 5;
|
|
|
5393
5579
|
var MAX_RECORDING_MS = 10 * 60 * 1e3;
|
|
5394
5580
|
var MAX_LISTENING_SILENCE_MS = 60 * 60 * 1e3;
|
|
5395
5581
|
var SILENCE_STOP_MS = 2e3;
|
|
5396
|
-
var
|
|
5582
|
+
var DEFAULT_SPEECH_THRESHOLD = 0.035;
|
|
5397
5583
|
var RECORDING_MIME_CANDIDATES = [
|
|
5398
5584
|
"audio/webm;codecs=opus",
|
|
5399
5585
|
"audio/webm",
|
|
@@ -5446,6 +5632,21 @@ function blobToBase64(blob) {
|
|
|
5446
5632
|
reader.readAsDataURL(blob);
|
|
5447
5633
|
});
|
|
5448
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
|
+
}
|
|
5449
5650
|
var VoiceRuntime = class {
|
|
5450
5651
|
debugLogging;
|
|
5451
5652
|
triggerSystemEvent;
|
|
@@ -5542,11 +5743,12 @@ var VoiceRuntime = class {
|
|
|
5542
5743
|
this.clearRecordingTimeout();
|
|
5543
5744
|
this.mediaRecorder.stop();
|
|
5544
5745
|
}
|
|
5545
|
-
async startListening() {
|
|
5746
|
+
async startListening(args) {
|
|
5546
5747
|
if (this.listening) {
|
|
5547
5748
|
return;
|
|
5548
5749
|
}
|
|
5549
5750
|
try {
|
|
5751
|
+
const silenceThreshold = isStartListeningArgs(args) ? normalizeSpeechThreshold(args.silenceThreshold) : DEFAULT_SPEECH_THRESHOLD;
|
|
5550
5752
|
const stream = await this.ensureInputStream();
|
|
5551
5753
|
const context = new AudioContext();
|
|
5552
5754
|
const analyser = context.createAnalyser();
|
|
@@ -5573,7 +5775,7 @@ var VoiceRuntime = class {
|
|
|
5573
5775
|
}
|
|
5574
5776
|
const rms = Math.sqrt(squareSum / sampleBuffer.length);
|
|
5575
5777
|
const now = performance.now();
|
|
5576
|
-
if (rms >=
|
|
5778
|
+
if (rms >= silenceThreshold) {
|
|
5577
5779
|
this.lastSpeechAt = now;
|
|
5578
5780
|
this.listeningStartedAt = now;
|
|
5579
5781
|
if (!this.speechEventTriggered) {
|
|
@@ -5595,6 +5797,9 @@ var VoiceRuntime = class {
|
|
|
5595
5797
|
void step();
|
|
5596
5798
|
});
|
|
5597
5799
|
};
|
|
5800
|
+
logRuntimeDebug(this.debugLogging, "voice-listening-started", {
|
|
5801
|
+
silenceThreshold
|
|
5802
|
+
});
|
|
5598
5803
|
void step();
|
|
5599
5804
|
} catch (error) {
|
|
5600
5805
|
await this.handleListeningError(error);
|
|
@@ -6010,7 +6215,7 @@ var renderGridView = (env, node, state, key) => {
|
|
|
6010
6215
|
index: realIndex,
|
|
6011
6216
|
descriptor: element
|
|
6012
6217
|
};
|
|
6013
|
-
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>`;
|
|
6014
6219
|
}).join("");
|
|
6015
6220
|
rows.push(`<div class="vjt-grid-row">${rowMarkup}</div>`);
|
|
6016
6221
|
}
|
|
@@ -6056,13 +6261,13 @@ var renderCombobox = (env, node, state, key) => {
|
|
|
6056
6261
|
var HEADING_TAGS = /* @__PURE__ */ new Set(["h1", "h2", "h3", "h4", "h5", "h6"]);
|
|
6057
6262
|
var TEXT_ALIGN_MAP = { left: "left", center: "center", right: "right" };
|
|
6058
6263
|
var VERTICAL_ALIGN_MAP = { top: "flex-start", center: "center", bottom: "flex-end" };
|
|
6059
|
-
var renderStaticText = (env, node, state, key) => {
|
|
6264
|
+
var renderStaticText = (env, node, state, key, _path, itemContext) => {
|
|
6060
6265
|
const resolvedHeading = node.heading && HEADING_TAGS.has(node.heading) ? node.heading : null;
|
|
6061
6266
|
const tag = resolvedHeading ?? "div";
|
|
6062
6267
|
const align = TEXT_ALIGN_MAP[node["horiz-align"] ?? "left"];
|
|
6063
6268
|
const verticalAlign = VERTICAL_ALIGN_MAP[node["vert-align"] ?? "center"];
|
|
6064
6269
|
const common = state.id ? ` id="${env.escapeHtml(state.id)}"` : "";
|
|
6065
|
-
const text = env.escapeHtml(env.
|
|
6270
|
+
const text = env.escapeHtml(env.resolveTextValue(state.text ?? node.text, itemContext));
|
|
6066
6271
|
const inlineStyle = [
|
|
6067
6272
|
"display:flex",
|
|
6068
6273
|
`align-items:${verticalAlign}`,
|
|
@@ -6093,11 +6298,11 @@ var markdownConverter = new import_showdown.default.Converter({
|
|
|
6093
6298
|
strikethrough: false,
|
|
6094
6299
|
tasklists: false
|
|
6095
6300
|
});
|
|
6096
|
-
var renderMdText = (env, node, state, key) => {
|
|
6301
|
+
var renderMdText = (env, node, state, key, _path, itemContext) => {
|
|
6097
6302
|
const align = TEXT_ALIGN_MAP2[node["horiz-align"] ?? "left"];
|
|
6098
6303
|
const verticalAlign = VERTICAL_ALIGN_MAP2[node["vert-align"] ?? "center"];
|
|
6099
6304
|
const common = state.id ? ` id="${env.escapeHtml(state.id)}"` : "";
|
|
6100
|
-
const markdown = env.
|
|
6305
|
+
const markdown = env.resolveTextValue(state.text ?? node.text, itemContext);
|
|
6101
6306
|
const html = sanitizeGeneratedHtml(markdownConverter.makeHtml(sanitizeMarkdownSource(markdown)));
|
|
6102
6307
|
const inlineStyle = [
|
|
6103
6308
|
"display:flex",
|
|
@@ -6119,24 +6324,24 @@ var renderMdText = (env, node, state, key) => {
|
|
|
6119
6324
|
};
|
|
6120
6325
|
|
|
6121
6326
|
// src/lib/widgets/edit.ts
|
|
6122
|
-
function resolvePlaceholder(env, node, statePlaceholder) {
|
|
6327
|
+
function resolvePlaceholder(env, node, itemContext, statePlaceholder) {
|
|
6123
6328
|
if (statePlaceholder) {
|
|
6124
|
-
return env.
|
|
6329
|
+
return env.resolveTextValue(statePlaceholder, itemContext);
|
|
6125
6330
|
}
|
|
6126
6331
|
if (node.placeholder) {
|
|
6127
|
-
return env.
|
|
6332
|
+
return env.resolveTextValue(node.placeholder, itemContext);
|
|
6128
6333
|
}
|
|
6129
6334
|
if ((node.type ?? "string") === "date") {
|
|
6130
6335
|
return env.getDateFormat(node);
|
|
6131
6336
|
}
|
|
6132
6337
|
return "";
|
|
6133
6338
|
}
|
|
6134
|
-
var renderEdit = (env, node, state, key) => {
|
|
6339
|
+
var renderEdit = (env, node, state, key, _path, itemContext) => {
|
|
6135
6340
|
const common = state.id ? ` id="${env.escapeHtml(state.id)}"` : "";
|
|
6136
6341
|
const enabled = state.enabled ?? env.normalizeBoolean(node.enabled, true);
|
|
6137
6342
|
const editable = state.editable ?? env.normalizeBoolean(node.editable, true);
|
|
6138
|
-
const placeholder = env.escapeHtml(resolvePlaceholder(env, node, state.placeholder));
|
|
6139
|
-
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));
|
|
6140
6345
|
const inputType = node.type === "password" ? "password" : "text";
|
|
6141
6346
|
const disabledAttribute = enabled ? "" : " disabled";
|
|
6142
6347
|
const readonlyAttribute = editable ? "" : " readonly";
|
|
@@ -6159,23 +6364,23 @@ var renderEdit = (env, node, state, key) => {
|
|
|
6159
6364
|
};
|
|
6160
6365
|
|
|
6161
6366
|
// src/lib/widgets/textarea.ts
|
|
6162
|
-
var renderTextarea = (env, node, state, key) => {
|
|
6367
|
+
var renderTextarea = (env, node, state, key, _path, itemContext) => {
|
|
6163
6368
|
const common = state.id ? ` id="${env.escapeHtml(state.id)}"` : "";
|
|
6164
6369
|
const enabled = state.enabled ?? env.normalizeBoolean(node.enabled, true);
|
|
6165
6370
|
const editable = state.editable ?? env.normalizeBoolean(node.editable, true);
|
|
6166
|
-
const placeholder = env.escapeHtml(env.
|
|
6167
|
-
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));
|
|
6168
6373
|
const styleString = env.buildStyleString(node);
|
|
6169
6374
|
const styleAttribute = styleString ? ` style="${env.escapeHtml(styleString)}"` : "";
|
|
6170
6375
|
return `<textarea${common}${env.buildWidgetDataAttributes(key, node)} class="vjt-textarea" data-widget="textarea" placeholder="${placeholder}"${enabled ? "" : " disabled"}${editable ? "" : " readonly"}${styleAttribute}>${value}</textarea>`;
|
|
6171
6376
|
};
|
|
6172
6377
|
|
|
6173
6378
|
// src/lib/widgets/button.ts
|
|
6174
|
-
var renderButton = (env, node, state, key) => {
|
|
6379
|
+
var renderButton = (env, node, state, key, _path, itemContext) => {
|
|
6175
6380
|
const common = state.id ? ` id="${env.escapeHtml(state.id)}"` : "";
|
|
6176
6381
|
const enabled = state.enabled ?? env.normalizeBoolean(node.enabled, true);
|
|
6177
6382
|
const disabledAttribute = enabled ? "" : " disabled";
|
|
6178
|
-
const text = env.escapeHtml(env.
|
|
6383
|
+
const text = env.escapeHtml(env.resolveTextValue(state.text ?? node.text, itemContext));
|
|
6179
6384
|
const styleString = env.buildStyleString(node);
|
|
6180
6385
|
const styleAttribute = styleString ? ` style="${env.escapeHtml(styleString)}"` : "";
|
|
6181
6386
|
const buttonType = env.escapeHtml(node.type === "submit" ? "submit" : "button");
|
|
@@ -6224,10 +6429,10 @@ var renderImage = (env, node, state, key) => {
|
|
|
6224
6429
|
};
|
|
6225
6430
|
|
|
6226
6431
|
// src/lib/widgets/link.ts
|
|
6227
|
-
var renderLink = (env, node, state, key) => {
|
|
6432
|
+
var renderLink = (env, node, state, key, _path, itemContext) => {
|
|
6228
6433
|
const type = node.type === "button" || node.type === "text" ? node.type : "link";
|
|
6229
6434
|
const enabled = state.enabled ?? env.normalizeBoolean(node.enabled, true);
|
|
6230
|
-
const text = env.escapeHtml(env.
|
|
6435
|
+
const text = env.escapeHtml(env.resolveTextValue(state.text ?? node.text, itemContext));
|
|
6231
6436
|
const classes = `vjt-link vjt-link--${type}${enabled ? "" : " is-disabled"}`;
|
|
6232
6437
|
const styleString = env.buildStyleString(node);
|
|
6233
6438
|
const styleAttribute = styleString ? ` style="${env.escapeHtml(styleString)}"` : "";
|
|
@@ -6984,6 +7189,7 @@ var RuntimeRenderer = class {
|
|
|
6984
7189
|
i18n;
|
|
6985
7190
|
actionsMap;
|
|
6986
7191
|
requestsMap;
|
|
7192
|
+
routes;
|
|
6987
7193
|
sseConfigs;
|
|
6988
7194
|
systemEvents;
|
|
6989
7195
|
resourceManager;
|
|
@@ -7003,6 +7209,7 @@ var RuntimeRenderer = class {
|
|
|
7003
7209
|
vars = /* @__PURE__ */ new Map();
|
|
7004
7210
|
resizeHandler = null;
|
|
7005
7211
|
pointerHandler = null;
|
|
7212
|
+
popstateHandler = null;
|
|
7006
7213
|
eventSources = [];
|
|
7007
7214
|
referenceRuntime;
|
|
7008
7215
|
networkRuntime;
|
|
@@ -7015,6 +7222,9 @@ var RuntimeRenderer = class {
|
|
|
7015
7222
|
activeConfirmModal = null;
|
|
7016
7223
|
lastPointer = { x: 24, y: 24 };
|
|
7017
7224
|
pendingResetModalIds = /* @__PURE__ */ new Set();
|
|
7225
|
+
pendingScrollAction = null;
|
|
7226
|
+
pendingScrollFrameId = null;
|
|
7227
|
+
activeScrollAnimationFrameId = null;
|
|
7018
7228
|
constructor(description, options = {}) {
|
|
7019
7229
|
this.description = deepClone(description);
|
|
7020
7230
|
this.resourceManager = options.resourceManager ?? null;
|
|
@@ -7028,6 +7238,8 @@ var RuntimeRenderer = class {
|
|
|
7028
7238
|
this.theme = options.theme === "light" ? "light" : "dark";
|
|
7029
7239
|
this.actionsMap = options.actionsMap ?? this.resourceManager?.getActionsMap() ?? {};
|
|
7030
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 })) : [];
|
|
7031
7243
|
const resolvedSseConfigs = options.sseConfigs ?? this.resourceManager?.getSseConfigs() ?? [];
|
|
7032
7244
|
this.sseConfigs = Array.isArray(resolvedSseConfigs) ? resolvedSseConfigs : resolvedSseConfigs ? [resolvedSseConfigs] : [];
|
|
7033
7245
|
this.systemEvents = options.systemEvents ?? this.resourceManager?.getSystemEvents() ?? {};
|
|
@@ -7041,6 +7253,7 @@ var RuntimeRenderer = class {
|
|
|
7041
7253
|
stateByKey: this.stateByKey,
|
|
7042
7254
|
nodeById: this.nodeById,
|
|
7043
7255
|
nodeByKey: this.nodeByKey,
|
|
7256
|
+
getUiResource: (ref) => this.resourceManager?.getUi(ref) ?? null,
|
|
7044
7257
|
getAppValue: (name) => {
|
|
7045
7258
|
switch (name) {
|
|
7046
7259
|
case "language":
|
|
@@ -7114,6 +7327,9 @@ var RuntimeRenderer = class {
|
|
|
7114
7327
|
clearWidget: (widgetId) => this.clearWidget(widgetId),
|
|
7115
7328
|
clearListElementState: (listKey) => this.clearListElementState(listKey),
|
|
7116
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),
|
|
7117
7333
|
playAudio: (value) => this.voiceRuntime.play(value),
|
|
7118
7334
|
stopPlaying: () => this.voiceRuntime.stopPlaying(),
|
|
7119
7335
|
copyToClipboard: (value) => this.copyToClipboard(value),
|
|
@@ -7121,7 +7337,7 @@ var RuntimeRenderer = class {
|
|
|
7121
7337
|
confirmModal: (args, inputValue) => this.confirmModal(args, inputValue),
|
|
7122
7338
|
startRecording: () => this.voiceRuntime.startRecording(),
|
|
7123
7339
|
stopRecording: () => Promise.resolve(this.voiceRuntime.stopRecording()),
|
|
7124
|
-
startListening: () => this.voiceRuntime.startListening(),
|
|
7340
|
+
startListening: (args) => this.voiceRuntime.startListening(args),
|
|
7125
7341
|
stopListening: () => this.voiceRuntime.stopListening(),
|
|
7126
7342
|
setUiReference: (widgetId, resourceRef) => {
|
|
7127
7343
|
const node = this.nodeById.get(widgetId);
|
|
@@ -7151,11 +7367,12 @@ var RuntimeRenderer = class {
|
|
|
7151
7367
|
getInlineActions: (node) => this.getInlineActions(node),
|
|
7152
7368
|
isWidgetEnabled: (node, key) => this.isWidgetEnabled(node, key)
|
|
7153
7369
|
});
|
|
7154
|
-
this.indexStaticNodes(this.
|
|
7370
|
+
this.indexStaticNodes(this.getActiveDescription(), "root");
|
|
7155
7371
|
this.applyRuntimeSnapshot(this.initialRuntimeSnapshot);
|
|
7156
7372
|
}
|
|
7157
7373
|
renderMarkup() {
|
|
7158
|
-
const
|
|
7374
|
+
const activeDescription = this.getActiveDescription();
|
|
7375
|
+
const markup = `${this.renderNode(activeDescription, "root", null)}${this.renderGlobalOverlays()}`;
|
|
7159
7376
|
logRuntimeDebug(this.debugLogging, "html", markup);
|
|
7160
7377
|
return markup;
|
|
7161
7378
|
}
|
|
@@ -7205,6 +7422,17 @@ var RuntimeRenderer = class {
|
|
|
7205
7422
|
};
|
|
7206
7423
|
window.addEventListener("pointerdown", handlePointer);
|
|
7207
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;
|
|
7208
7436
|
return () => {
|
|
7209
7437
|
if (this.resizeHandler) {
|
|
7210
7438
|
window.removeEventListener("resize", this.resizeHandler);
|
|
@@ -7212,6 +7440,9 @@ var RuntimeRenderer = class {
|
|
|
7212
7440
|
if (this.pointerHandler) {
|
|
7213
7441
|
window.removeEventListener("pointerdown", this.pointerHandler);
|
|
7214
7442
|
}
|
|
7443
|
+
if (this.popstateHandler) {
|
|
7444
|
+
window.removeEventListener("popstate", this.popstateHandler);
|
|
7445
|
+
}
|
|
7215
7446
|
for (const source of this.eventSources) {
|
|
7216
7447
|
source.close();
|
|
7217
7448
|
}
|
|
@@ -7234,6 +7465,7 @@ var RuntimeRenderer = class {
|
|
|
7234
7465
|
this.attachInputBehavior(this.root);
|
|
7235
7466
|
this.attachWidgetEvents(this.root);
|
|
7236
7467
|
restoreElementState(this.root, preservedState, this.stateByKey);
|
|
7468
|
+
this.applyPendingScrollAction();
|
|
7237
7469
|
this.activeContextMenu = adjustContextMenuPosition(this.root, this.activeContextMenu);
|
|
7238
7470
|
this.pendingResetModalIds.clear();
|
|
7239
7471
|
if (typeof this.onRuntimeSnapshot === "function") {
|
|
@@ -7413,7 +7645,113 @@ var RuntimeRenderer = class {
|
|
|
7413
7645
|
this.nodeByKey.clear();
|
|
7414
7646
|
this.nodeById.clear();
|
|
7415
7647
|
this.stateById.clear();
|
|
7416
|
-
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
|
+
};
|
|
7417
7755
|
}
|
|
7418
7756
|
getUiReferenceTarget(node, key) {
|
|
7419
7757
|
if (node.widget !== "ui-reference") {
|
|
@@ -7871,6 +8209,20 @@ var RuntimeRenderer = class {
|
|
|
7871
8209
|
}
|
|
7872
8210
|
return `??${key}??`;
|
|
7873
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
|
+
}
|
|
7874
8226
|
buildWidgetDataAttributes(key, node) {
|
|
7875
8227
|
const parts = [` data-widget-key="${escapeHtml(key)}"`];
|
|
7876
8228
|
if (node.id) {
|
|
@@ -7889,6 +8241,7 @@ var RuntimeRenderer = class {
|
|
|
7889
8241
|
escapeHtml,
|
|
7890
8242
|
buildStyleString: (node) => this.buildStyleString(node),
|
|
7891
8243
|
resolveI18nValue: (value) => this.resolveI18nValue(value),
|
|
8244
|
+
resolveTextValue: (value, itemContext) => this.resolveTextValue(value, itemContext),
|
|
7892
8245
|
getUiResource: (ref) => this.resourceManager?.getUi(ref) ?? null,
|
|
7893
8246
|
resolveReference: (reference, currentValue, responseValue) => this.referenceRuntime.resolveReference(reference, currentValue, responseValue),
|
|
7894
8247
|
buildWidgetDataAttributes: (key, node) => this.buildWidgetDataAttributes(key, node),
|
|
@@ -8434,6 +8787,138 @@ var RuntimeRenderer = class {
|
|
|
8434
8787
|
nestedTarget.focus({ preventScroll: true });
|
|
8435
8788
|
}
|
|
8436
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
|
+
}
|
|
8437
8922
|
};
|
|
8438
8923
|
function renderJson(description, options = {}) {
|
|
8439
8924
|
const renderer = new RuntimeRenderer(description, options);
|
|
@@ -8449,6 +8934,7 @@ var ResourceManager = class {
|
|
|
8449
8934
|
ui = /* @__PURE__ */ new Map();
|
|
8450
8935
|
actions = {};
|
|
8451
8936
|
requests = {};
|
|
8937
|
+
routes = [];
|
|
8452
8938
|
sse = {};
|
|
8453
8939
|
systemEvents = {};
|
|
8454
8940
|
i18n = {};
|
|
@@ -8459,6 +8945,7 @@ var ResourceManager = class {
|
|
|
8459
8945
|
}
|
|
8460
8946
|
this.actions = { ...input.actions ?? {} };
|
|
8461
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 })) : [];
|
|
8462
8949
|
this.sse = { ...input.sse ?? {} };
|
|
8463
8950
|
this.systemEvents = { ...input.systemEvents ?? {} };
|
|
8464
8951
|
this.i18n = { ...input.i18n ?? {} };
|
|
@@ -8476,6 +8963,9 @@ var ResourceManager = class {
|
|
|
8476
8963
|
getRequestsMap() {
|
|
8477
8964
|
return this.requests;
|
|
8478
8965
|
}
|
|
8966
|
+
getRoutes() {
|
|
8967
|
+
return this.routes.map((route) => ({ ...route }));
|
|
8968
|
+
}
|
|
8479
8969
|
getSseConfigs() {
|
|
8480
8970
|
return Object.values(this.sse);
|
|
8481
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;
|