@assistant-ui/react-generative-ui 0.0.23 → 0.1.0
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/README.md +2 -0
- package/dist/a2ui.d.ts +1 -4
- package/dist/a2ui.d.ts.map +1 -1
- package/dist/a2ui.js +1 -4
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -10
- package/dist/index.server.d.ts +1 -2
- package/dist/index.server.d.ts.map +1 -1
- package/dist/index.server.js +1 -10
- package/dist/ir.d.ts +1 -111
- package/dist/ir.d.ts.map +1 -1
- package/dist/ir.js +1 -175
- package/dist/slack.d.ts +1 -4
- package/dist/slack.d.ts.map +1 -1
- package/dist/slack.js +1 -4
- package/dist/teams.d.ts +1 -4
- package/dist/teams.d.ts.map +1 -1
- package/dist/teams.js +1 -4
- package/package.json +5 -5
- package/src/a2ui.ts +1 -22
- package/src/index.server.ts +1 -2
- package/src/index.test.ts +75 -0
- package/src/index.ts +1 -2
- package/src/ir.ts +1 -279
- package/src/slack.ts +1 -39
- package/src/teams.ts +1 -35
- package/dist/JSONGenerativeUI.client.d.ts +0 -28
- package/dist/JSONGenerativeUI.client.d.ts.map +0 -1
- package/dist/JSONGenerativeUI.client.js +0 -101
- package/dist/JSONGenerativeUI.client.js.map +0 -1
- package/dist/JSONGenerativeUI.server.d.ts +0 -21
- package/dist/JSONGenerativeUI.server.d.ts.map +0 -1
- package/dist/JSONGenerativeUI.server.js +0 -32
- package/dist/JSONGenerativeUI.server.js.map +0 -1
- package/dist/JSONGenerativeUI.shared.d.ts +0 -63
- package/dist/JSONGenerativeUI.shared.d.ts.map +0 -1
- package/dist/JSONGenerativeUI.shared.js +0 -31
- package/dist/JSONGenerativeUI.shared.js.map +0 -1
- package/dist/RadioGroupScope.d.ts +0 -6
- package/dist/RadioGroupScope.d.ts.map +0 -1
- package/dist/RadioGroupScope.js +0 -25
- package/dist/RadioGroupScope.js.map +0 -1
- package/dist/a2ui/BindingContext.d.ts +0 -11
- package/dist/a2ui/BindingContext.d.ts.map +0 -1
- package/dist/a2ui/BindingContext.js +0 -12
- package/dist/a2ui/BindingContext.js.map +0 -1
- package/dist/a2ui/PresentRenderer.d.ts +0 -11
- package/dist/a2ui/PresentRenderer.d.ts.map +0 -1
- package/dist/a2ui/PresentRenderer.js +0 -39
- package/dist/a2ui/PresentRenderer.js.map +0 -1
- package/dist/a2ui/convert.d.ts +0 -15
- package/dist/a2ui/convert.d.ts.map +0 -1
- package/dist/a2ui/convert.js +0 -728
- package/dist/a2ui/convert.js.map +0 -1
- package/dist/a2ui/dataModel.d.ts +0 -9
- package/dist/a2ui/dataModel.d.ts.map +0 -1
- package/dist/a2ui/dataModel.js +0 -44
- package/dist/a2ui/dataModel.js.map +0 -1
- package/dist/a2ui/reducer.d.ts +0 -8
- package/dist/a2ui/reducer.d.ts.map +0 -1
- package/dist/a2ui/reducer.js +0 -242
- package/dist/a2ui/reducer.js.map +0 -1
- package/dist/a2ui/snapshot.d.ts +0 -3
- package/dist/a2ui/snapshot.d.ts.map +0 -1
- package/dist/a2ui/snapshot.js +0 -33
- package/dist/a2ui/snapshot.js.map +0 -1
- package/dist/a2ui/types.d.ts +0 -88
- package/dist/a2ui/types.d.ts.map +0 -1
- package/dist/a2ui/types.js +0 -6
- package/dist/a2ui/types.js.map +0 -1
- package/dist/a2ui/valueFunctions.d.ts +0 -16
- package/dist/a2ui/valueFunctions.d.ts.map +0 -1
- package/dist/a2ui/valueFunctions.js +0 -332
- package/dist/a2ui/valueFunctions.js.map +0 -1
- package/dist/actionRegistry.d.ts +0 -29
- package/dist/actionRegistry.d.ts.map +0 -1
- package/dist/actionRegistry.js +0 -41
- package/dist/actionRegistry.js.map +0 -1
- package/dist/answeredValues.d.ts +0 -16
- package/dist/answeredValues.d.ts.map +0 -1
- package/dist/answeredValues.js +0 -37
- package/dist/answeredValues.js.map +0 -1
- package/dist/buildPresentParameters.d.ts +0 -21
- package/dist/buildPresentParameters.d.ts.map +0 -1
- package/dist/buildPresentParameters.js +0 -95
- package/dist/buildPresentParameters.js.map +0 -1
- package/dist/constants.d.ts +0 -15
- package/dist/constants.d.ts.map +0 -1
- package/dist/constants.js +0 -19
- package/dist/constants.js.map +0 -1
- package/dist/convert/boundSpec.d.ts +0 -48
- package/dist/convert/boundSpec.d.ts.map +0 -1
- package/dist/convert/boundSpec.js +0 -108
- package/dist/convert/boundSpec.js.map +0 -1
- package/dist/convert/copyBounded.d.ts +0 -25
- package/dist/convert/copyBounded.d.ts.map +0 -1
- package/dist/convert/copyBounded.js +0 -38
- package/dist/convert/copyBounded.js.map +0 -1
- package/dist/convert/isElement.d.ts +0 -3
- package/dist/convert/isElement.d.ts.map +0 -1
- package/dist/convert/isElement.js +0 -6
- package/dist/convert/isElement.js.map +0 -1
- package/dist/convert/takeRun.d.ts +0 -6
- package/dist/convert/takeRun.d.ts.map +0 -1
- package/dist/convert/takeRun.js +0 -20
- package/dist/convert/takeRun.js.map +0 -1
- package/dist/defineGenerativeComponents.d.ts +0 -29
- package/dist/defineGenerativeComponents.d.ts.map +0 -1
- package/dist/defineGenerativeComponents.js +0 -34
- package/dist/defineGenerativeComponents.js.map +0 -1
- package/dist/fieldReferences.d.ts +0 -9
- package/dist/fieldReferences.d.ts.map +0 -1
- package/dist/fieldReferences.js +0 -53
- package/dist/fieldReferences.js.map +0 -1
- package/dist/generativeUIToJSX.d.ts +0 -18
- package/dist/generativeUIToJSX.d.ts.map +0 -1
- package/dist/generativeUIToJSX.js +0 -76
- package/dist/generativeUIToJSX.js.map +0 -1
- package/dist/index.shared.d.ts +0 -15
- package/dist/index.shared.d.ts.map +0 -1
- package/dist/index.shared.js +0 -9
- package/dist/ir.js.map +0 -1
- package/dist/renderGenerativeUI.d.ts +0 -14
- package/dist/renderGenerativeUI.d.ts.map +0 -1
- package/dist/renderGenerativeUI.js +0 -83
- package/dist/renderGenerativeUI.js.map +0 -1
- package/dist/scopeSchema.d.ts +0 -6
- package/dist/scopeSchema.d.ts.map +0 -1
- package/dist/scopeSchema.js +0 -56
- package/dist/scopeSchema.js.map +0 -1
- package/dist/slack/constants.d.ts +0 -93
- package/dist/slack/constants.d.ts.map +0 -1
- package/dist/slack/constants.js +0 -146
- package/dist/slack/constants.js.map +0 -1
- package/dist/slack/decodeBlockAction.d.ts +0 -10
- package/dist/slack/decodeBlockAction.d.ts.map +0 -1
- package/dist/slack/decodeBlockAction.js +0 -129
- package/dist/slack/decodeBlockAction.js.map +0 -1
- package/dist/slack/fromSlackBlocks.d.ts +0 -27
- package/dist/slack/fromSlackBlocks.d.ts.map +0 -1
- package/dist/slack/fromSlackBlocks.js +0 -483
- package/dist/slack/fromSlackBlocks.js.map +0 -1
- package/dist/slack/toSlackBlocks.d.ts +0 -4
- package/dist/slack/toSlackBlocks.d.ts.map +0 -1
- package/dist/slack/toSlackBlocks.js +0 -901
- package/dist/slack/toSlackBlocks.js.map +0 -1
- package/dist/slack/types.d.ts +0 -204
- package/dist/slack/types.d.ts.map +0 -1
- package/dist/slack/types.js +0 -0
- package/dist/teams/constants.d.ts +0 -34
- package/dist/teams/constants.d.ts.map +0 -1
- package/dist/teams/constants.js +0 -68
- package/dist/teams/constants.js.map +0 -1
- package/dist/teams/decodeSubmitData.d.ts +0 -26
- package/dist/teams/decodeSubmitData.d.ts.map +0 -1
- package/dist/teams/decodeSubmitData.js +0 -70
- package/dist/teams/decodeSubmitData.js.map +0 -1
- package/dist/teams/temporalId.d.ts +0 -5
- package/dist/teams/temporalId.d.ts.map +0 -1
- package/dist/teams/temporalId.js +0 -28
- package/dist/teams/temporalId.js.map +0 -1
- package/dist/teams/toAdaptiveCard.d.ts +0 -45
- package/dist/teams/toAdaptiveCard.d.ts.map +0 -1
- package/dist/teams/toAdaptiveCard.js +0 -642
- package/dist/teams/toAdaptiveCard.js.map +0 -1
- package/dist/teams/toTeamsAttachments.d.ts +0 -10
- package/dist/teams/toTeamsAttachments.d.ts.map +0 -1
- package/dist/teams/toTeamsAttachments.js +0 -99
- package/dist/teams/toTeamsAttachments.js.map +0 -1
- package/dist/teams/types.d.ts +0 -224
- package/dist/teams/types.d.ts.map +0 -1
- package/dist/teams/types.js +0 -0
- package/dist/temporal.d.ts +0 -33
- package/dist/temporal.d.ts.map +0 -1
- package/dist/temporal.js +0 -152
- package/dist/temporal.js.map +0 -1
- package/dist/types.d.ts +0 -99
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -0
- package/dist/vocabulary/alert.d.ts +0 -32
- package/dist/vocabulary/alert.d.ts.map +0 -1
- package/dist/vocabulary/alert.js +0 -160
- package/dist/vocabulary/alert.js.map +0 -1
- package/dist/vocabulary/collectFormValues.d.ts +0 -23
- package/dist/vocabulary/collectFormValues.d.ts.map +0 -1
- package/dist/vocabulary/collectFormValues.js +0 -44
- package/dist/vocabulary/collectFormValues.js.map +0 -1
- package/dist/vocabulary/data.d.ts +0 -66
- package/dist/vocabulary/data.d.ts.map +0 -1
- package/dist/vocabulary/data.js +0 -503
- package/dist/vocabulary/data.js.map +0 -1
- package/dist/vocabulary/dispatch.d.ts +0 -9
- package/dist/vocabulary/dispatch.d.ts.map +0 -1
- package/dist/vocabulary/dispatch.js +0 -50
- package/dist/vocabulary/dispatch.js.map +0 -1
- package/dist/vocabulary/fact.d.ts +0 -19
- package/dist/vocabulary/fact.d.ts.map +0 -1
- package/dist/vocabulary/fact.js +0 -51
- package/dist/vocabulary/fact.js.map +0 -1
- package/dist/vocabulary/form.d.ts +0 -11
- package/dist/vocabulary/form.d.ts.map +0 -1
- package/dist/vocabulary/form.js +0 -23
- package/dist/vocabulary/form.js.map +0 -1
- package/dist/vocabulary/formatValue.d.ts +0 -7
- package/dist/vocabulary/formatValue.d.ts.map +0 -1
- package/dist/vocabulary/formatValue.js +0 -76
- package/dist/vocabulary/formatValue.js.map +0 -1
- package/dist/vocabulary/icon.d.ts +0 -41
- package/dist/vocabulary/icon.d.ts.map +0 -1
- package/dist/vocabulary/icon.js +0 -272
- package/dist/vocabulary/icon.js.map +0 -1
- package/dist/vocabulary/index.d.ts +0 -12
- package/dist/vocabulary/index.d.ts.map +0 -1
- package/dist/vocabulary/index.js +0 -36
- package/dist/vocabulary/index.js.map +0 -1
- package/dist/vocabulary/interactive.d.ts +0 -230
- package/dist/vocabulary/interactive.d.ts.map +0 -1
- package/dist/vocabulary/interactive.js +0 -530
- package/dist/vocabulary/interactive.js.map +0 -1
- package/dist/vocabulary/layout.d.ts +0 -79
- package/dist/vocabulary/layout.d.ts.map +0 -1
- package/dist/vocabulary/layout.js +0 -139
- package/dist/vocabulary/layout.js.map +0 -1
- package/dist/vocabulary/list.d.ts +0 -14
- package/dist/vocabulary/list.d.ts.map +0 -1
- package/dist/vocabulary/list.js +0 -50
- package/dist/vocabulary/list.js.map +0 -1
- package/dist/vocabulary/media.d.ts +0 -25
- package/dist/vocabulary/media.d.ts.map +0 -1
- package/dist/vocabulary/media.js +0 -42
- package/dist/vocabulary/media.js.map +0 -1
- package/dist/vocabulary/text.d.ts +0 -57
- package/dist/vocabulary/text.d.ts.map +0 -1
- package/dist/vocabulary/text.js +0 -49
- package/dist/vocabulary/text.js.map +0 -1
- package/dist/vocabulary/toTextContent.d.ts +0 -2
- package/dist/vocabulary/toTextContent.d.ts.map +0 -1
- package/dist/vocabulary/toTextContent.js +0 -6
- package/dist/vocabulary/toTextContent.js.map +0 -1
- package/src/JSONGenerativeUI.client.tsx +0 -168
- package/src/JSONGenerativeUI.server.tsx +0 -39
- package/src/JSONGenerativeUI.shared.ts +0 -90
- package/src/JSONGenerativeUI.test.tsx +0 -1298
- package/src/RadioGroupScope.server.test.tsx +0 -24
- package/src/RadioGroupScope.tsx +0 -34
- package/src/a2ui/BindingContext.ts +0 -26
- package/src/a2ui/PresentRenderer.tsx +0 -83
- package/src/a2ui/convert.test.ts +0 -2923
- package/src/a2ui/convert.ts +0 -1207
- package/src/a2ui/dataModel.ts +0 -69
- package/src/a2ui/reducer.test.ts +0 -422
- package/src/a2ui/reducer.ts +0 -363
- package/src/a2ui/snapshot.test.ts +0 -52
- package/src/a2ui/snapshot.ts +0 -52
- package/src/a2ui/types.ts +0 -114
- package/src/a2ui/valueFunctions.test.ts +0 -271
- package/src/a2ui/valueFunctions.ts +0 -523
- package/src/actionRegistry.test.ts +0 -90
- package/src/actionRegistry.ts +0 -88
- package/src/answeredValues.test.ts +0 -33
- package/src/answeredValues.tsx +0 -70
- package/src/buildPresentParameters.test.ts +0 -246
- package/src/buildPresentParameters.ts +0 -130
- package/src/constants.ts +0 -17
- package/src/convert/boundSpec.test.ts +0 -192
- package/src/convert/boundSpec.ts +0 -134
- package/src/convert/copyBounded.test.ts +0 -131
- package/src/convert/copyBounded.ts +0 -38
- package/src/convert/isElement.ts +0 -6
- package/src/convert/takeRun.test.ts +0 -64
- package/src/convert/takeRun.ts +0 -19
- package/src/defineGenerativeComponents.ts +0 -38
- package/src/fieldReferences.test.ts +0 -66
- package/src/fieldReferences.ts +0 -83
- package/src/generativeUIToJSX.test.ts +0 -268
- package/src/generativeUIToJSX.ts +0 -152
- package/src/index.server.test.ts +0 -106
- package/src/index.shared.ts +0 -61
- package/src/ir.test.ts +0 -203
- package/src/renderGenerativeUI.test.tsx +0 -373
- package/src/renderGenerativeUI.tsx +0 -165
- package/src/scopeSchema.test.ts +0 -72
- package/src/scopeSchema.ts +0 -71
- package/src/slack/a2uiSlack.test.ts +0 -198
- package/src/slack/constants.ts +0 -194
- package/src/slack/datePicker.test.ts +0 -612
- package/src/slack/decodeBlockAction.test.ts +0 -233
- package/src/slack/decodeBlockAction.ts +0 -232
- package/src/slack/fromSlackBlocks.test.ts +0 -1465
- package/src/slack/fromSlackBlocks.ts +0 -789
- package/src/slack/toSlackBlocks.test.ts +0 -3065
- package/src/slack/toSlackBlocks.ts +0 -1818
- package/src/slack/types.ts +0 -264
- package/src/teams/constants.ts +0 -93
- package/src/teams/decodeSubmitData.test.ts +0 -397
- package/src/teams/decodeSubmitData.ts +0 -110
- package/src/teams/temporal.test.ts +0 -766
- package/src/teams/temporalId.ts +0 -56
- package/src/teams/toAdaptiveCard.test.ts +0 -1897
- package/src/teams/toAdaptiveCard.ts +0 -1057
- package/src/teams/toTeamsAttachments.test.ts +0 -74
- package/src/teams/toTeamsAttachments.ts +0 -133
- package/src/teams/types.ts +0 -266
- package/src/temporal.test.ts +0 -319
- package/src/temporal.ts +0 -259
- package/src/types.ts +0 -119
- package/src/vocabulary/alert.test.tsx +0 -427
- package/src/vocabulary/alert.tsx +0 -217
- package/src/vocabulary/collectFormValues.test.ts +0 -389
- package/src/vocabulary/collectFormValues.ts +0 -116
- package/src/vocabulary/data.test.tsx +0 -858
- package/src/vocabulary/data.tsx +0 -819
- package/src/vocabulary/datepicker.dom.test.tsx +0 -1148
- package/src/vocabulary/dispatch.ts +0 -83
- package/src/vocabulary/fact.test.tsx +0 -94
- package/src/vocabulary/fact.tsx +0 -54
- package/src/vocabulary/form.test.tsx +0 -113
- package/src/vocabulary/form.tsx +0 -39
- package/src/vocabulary/formatValue.test.ts +0 -72
- package/src/vocabulary/formatValue.ts +0 -127
- package/src/vocabulary/icon.test.tsx +0 -64
- package/src/vocabulary/icon.tsx +0 -174
- package/src/vocabulary/index.test.ts +0 -65
- package/src/vocabulary/index.ts +0 -33
- package/src/vocabulary/interactive.dispatch.test.tsx +0 -454
- package/src/vocabulary/interactive.dom.test.tsx +0 -1747
- package/src/vocabulary/interactive.test.tsx +0 -377
- package/src/vocabulary/interactive.tsx +0 -1048
- package/src/vocabulary/layout.test.tsx +0 -323
- package/src/vocabulary/layout.tsx +0 -247
- package/src/vocabulary/list.test.tsx +0 -222
- package/src/vocabulary/list.tsx +0 -50
- package/src/vocabulary/media.test.tsx +0 -85
- package/src/vocabulary/media.tsx +0 -56
- package/src/vocabulary/text.test.tsx +0 -102
- package/src/vocabulary/text.tsx +0 -60
- package/src/vocabulary/toTextContent.ts +0 -2
package/dist/a2ui/convert.js
DELETED
|
@@ -1,728 +0,0 @@
|
|
|
1
|
-
import { ICON_NAMES } from "../ir.js";
|
|
2
|
-
import { A2UI_SURFACE_ID } from "./types.js";
|
|
3
|
-
import "./reducer.js";
|
|
4
|
-
import { decodePointer, resolvePointer } from "./dataModel.js";
|
|
5
|
-
import { classifyTemporal } from "../temporal.js";
|
|
6
|
-
import { evaluateA2uiValueFunction } from "./valueFunctions.js";
|
|
7
|
-
//#region src/a2ui/convert.ts
|
|
8
|
-
const DEPTH_CAP = 32;
|
|
9
|
-
const TEMPLATE_ITEM_CAP = 100;
|
|
10
|
-
const NODE_BUDGET = 5e3;
|
|
11
|
-
const EVALUATION_BUDGET = 2e4;
|
|
12
|
-
const SUPPORTED_COMPONENTS = /* @__PURE__ */ new Set([
|
|
13
|
-
"Text",
|
|
14
|
-
"Image",
|
|
15
|
-
"Icon",
|
|
16
|
-
"Row",
|
|
17
|
-
"Column",
|
|
18
|
-
"List",
|
|
19
|
-
"Card",
|
|
20
|
-
"Divider",
|
|
21
|
-
"Button",
|
|
22
|
-
"TextField",
|
|
23
|
-
"CheckBox",
|
|
24
|
-
"ChoicePicker",
|
|
25
|
-
"DateTimeInput",
|
|
26
|
-
"Slider"
|
|
27
|
-
]);
|
|
28
|
-
const CHILD_LIST_COMPONENTS = /* @__PURE__ */ new Set([
|
|
29
|
-
"Row",
|
|
30
|
-
"Column",
|
|
31
|
-
"List"
|
|
32
|
-
]);
|
|
33
|
-
const ICON_NAME_SET = new Set(ICON_NAMES);
|
|
34
|
-
const ICON_SIZE_SET = /* @__PURE__ */ new Set([
|
|
35
|
-
"sm",
|
|
36
|
-
"md",
|
|
37
|
-
"lg"
|
|
38
|
-
]);
|
|
39
|
-
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
40
|
-
const isPlainObject = (value) => {
|
|
41
|
-
if (!isRecord(value)) return false;
|
|
42
|
-
const prototype = Object.getPrototypeOf(value);
|
|
43
|
-
return prototype === Object.prototype || prototype === null;
|
|
44
|
-
};
|
|
45
|
-
const setOwnProperty = (target, key, value) => {
|
|
46
|
-
if (key === "__proto__") Object.defineProperty(target, key, {
|
|
47
|
-
value,
|
|
48
|
-
enumerable: true,
|
|
49
|
-
configurable: true,
|
|
50
|
-
writable: true
|
|
51
|
-
});
|
|
52
|
-
else target[key] = value;
|
|
53
|
-
};
|
|
54
|
-
const FUNCTION_CALL_KEYS = /* @__PURE__ */ new Set([
|
|
55
|
-
"call",
|
|
56
|
-
"args",
|
|
57
|
-
"returnType",
|
|
58
|
-
"catalogId"
|
|
59
|
-
]);
|
|
60
|
-
const isFunctionCall = (value) => isPlainObject(value) && typeof value["call"] === "string" && (value["args"] === void 0 || isPlainObject(value["args"])) && Object.keys(value).every((key) => FUNCTION_CALL_KEYS.has(key));
|
|
61
|
-
const isBinding = (value) => isPlainObject(value) && Object.keys(value).length === 1 && typeof value["path"] === "string";
|
|
62
|
-
const childTemplateOf = (children) => {
|
|
63
|
-
const template = isPlainObject(children) && Object.keys(children).length === 1 && isPlainObject(children["template"]) ? children["template"] : children;
|
|
64
|
-
return isPlainObject(template) && Object.keys(template).length === 2 && typeof template["componentId"] === "string" && typeof template["path"] === "string" ? {
|
|
65
|
-
componentId: template["componentId"],
|
|
66
|
-
path: template["path"]
|
|
67
|
-
} : void 0;
|
|
68
|
-
};
|
|
69
|
-
const bindingPath = (value) => isBinding(value) ? value.path : void 0;
|
|
70
|
-
const pointerIn = (scope, path) => (path.startsWith("/") ? "" : scope.path) + decodePointer(path).map((segment) => `/${segment.replaceAll("~", "~0").replaceAll("/", "~1")}`).join("");
|
|
71
|
-
const setIn = (value, segments, leaf) => {
|
|
72
|
-
const [head, ...rest] = segments;
|
|
73
|
-
if (head === void 0) return leaf;
|
|
74
|
-
if (/^(0|[1-9]\d*)$/.test(head) && (Array.isArray(value) || value === void 0 || value === null)) {
|
|
75
|
-
const list = Array.isArray(value) ? value : [];
|
|
76
|
-
const index = Number(head);
|
|
77
|
-
if (index >= list.length && index > 1e4) return value;
|
|
78
|
-
const copy = [...list];
|
|
79
|
-
copy[index] = setIn(copy[index], rest, leaf);
|
|
80
|
-
return copy;
|
|
81
|
-
}
|
|
82
|
-
const copy = isRecord(value) ? { ...value } : {};
|
|
83
|
-
setOwnProperty(copy, head, setIn(Object.hasOwn(copy, head) ? copy[head] : void 0, rest, leaf));
|
|
84
|
-
return copy;
|
|
85
|
-
};
|
|
86
|
-
const withFieldReferences = (value, pointer, fields) => {
|
|
87
|
-
if (fields.has(pointer)) return fields.get(pointer);
|
|
88
|
-
let result = value;
|
|
89
|
-
for (const [name, field] of fields) if (name.startsWith(`${pointer}/`)) result = setIn(result, decodePointer(name.slice(pointer.length)), field);
|
|
90
|
-
return result;
|
|
91
|
-
};
|
|
92
|
-
const materializeEntries = (value, source, context, evaluate, depth, positional = false) => {
|
|
93
|
-
const result = {};
|
|
94
|
-
for (const [key, entry] of Object.entries(value)) {
|
|
95
|
-
const resolved = key === "functionCall" && isFunctionCall(entry) ? {
|
|
96
|
-
...entry,
|
|
97
|
-
...entry.args !== void 0 ? { args: materializeEntries(entry.args, source, context, evaluate, depth, true) } : {}
|
|
98
|
-
} : materialize(entry, source, context, evaluate, depth, positional);
|
|
99
|
-
if (resolved !== void 0) setOwnProperty(result, key, resolved);
|
|
100
|
-
}
|
|
101
|
-
return result;
|
|
102
|
-
};
|
|
103
|
-
function materialize(value, source, context, evaluate = true, depth = 0, positional = false) {
|
|
104
|
-
if (isBinding(value)) {
|
|
105
|
-
const pointer = pointerIn({
|
|
106
|
-
data: source,
|
|
107
|
-
path: context.scopePath
|
|
108
|
-
}, value.path);
|
|
109
|
-
const resolved = resolvePointer(context.surface.dataModel, pointer);
|
|
110
|
-
context.dependencies?.set(pointer, resolved);
|
|
111
|
-
return resolved;
|
|
112
|
-
}
|
|
113
|
-
if (Array.isArray(value)) {
|
|
114
|
-
const entries = value.map((entry) => materialize(entry, source, context, evaluate, depth, positional));
|
|
115
|
-
return positional ? entries : entries.filter((entry) => entry !== void 0);
|
|
116
|
-
}
|
|
117
|
-
if (!isPlainObject(value)) return value;
|
|
118
|
-
if (!evaluate || !isFunctionCall(value)) return materializeEntries(value, source, context, evaluate, depth, positional);
|
|
119
|
-
if (!spendEvaluation(context)) return void 0;
|
|
120
|
-
if (depth >= DEPTH_CAP) {
|
|
121
|
-
if (!context.functionDepthWarned) {
|
|
122
|
-
context.warnings.push(`A2UI function nesting cap of ${DEPTH_CAP} was reached.`);
|
|
123
|
-
context.functionDepthWarned = true;
|
|
124
|
-
}
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
|
-
return evaluateA2uiValueFunction(value.call, materializeEntries(value.args ?? {}, source, context, true, depth + 1, true), {
|
|
128
|
-
resolve: (part) => spendEvaluation(context) ? materialize(part, source, context, true, depth + 1) : void 0,
|
|
129
|
-
warn: (message) => context.warnings.push(message),
|
|
130
|
-
templates: context.templates
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
const firstDefined = (props, keys) => {
|
|
134
|
-
for (const key of keys) if (props[key] !== void 0) return props[key];
|
|
135
|
-
};
|
|
136
|
-
const stringProp = (props, keys) => {
|
|
137
|
-
const value = firstDefined(props, keys);
|
|
138
|
-
return typeof value === "string" ? value : void 0;
|
|
139
|
-
};
|
|
140
|
-
const sourceSurfaceId = (surface) => surface[A2UI_SURFACE_ID] ?? "";
|
|
141
|
-
const BOUND_KEYS = [
|
|
142
|
-
"text",
|
|
143
|
-
"value",
|
|
144
|
-
"binding"
|
|
145
|
-
];
|
|
146
|
-
const INPUT_COMPONENTS = /* @__PURE__ */ new Set([
|
|
147
|
-
"TextField",
|
|
148
|
-
"CheckBox",
|
|
149
|
-
"ChoicePicker",
|
|
150
|
-
"DateTimeInput",
|
|
151
|
-
"Slider"
|
|
152
|
-
]);
|
|
153
|
-
const dateInputType = (value) => {
|
|
154
|
-
const kind = classifyTemporal(value).kind;
|
|
155
|
-
if (kind === "date" || kind === "time") return kind;
|
|
156
|
-
return kind === "floating" || kind === "instant" ? "datetime" : void 0;
|
|
157
|
-
};
|
|
158
|
-
const finiteNumber = (value) => typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
159
|
-
const decimalPlaces = (value) => {
|
|
160
|
-
const [mantissa = "", exponent = "0"] = String(value).split("e");
|
|
161
|
-
return Math.max(0, (mantissa.split(".")[1]?.length ?? 0) - Number(exponent));
|
|
162
|
-
};
|
|
163
|
-
const sliderStep = (min, max, value, steps) => {
|
|
164
|
-
if (max <= min) return void 0;
|
|
165
|
-
if (typeof steps === "number" && Number.isInteger(steps) && steps >= 1) return (max - min) / steps;
|
|
166
|
-
const precision = Math.max(decimalPlaces(min), value === void 0 ? 0 : decimalPlaces(value));
|
|
167
|
-
return Math.min(10 ** Math.floor(Math.log10((max - min) / 100)), 10 ** -precision);
|
|
168
|
-
};
|
|
169
|
-
const recordBindings = (node, props, mapped, scope, context) => {
|
|
170
|
-
const component = node["component"];
|
|
171
|
-
const name = mapped["name"];
|
|
172
|
-
const boundKey = BOUND_KEYS.find((key) => node[key] !== void 0);
|
|
173
|
-
const value = boundKey === void 0 ? void 0 : props[boundKey];
|
|
174
|
-
if (INPUT_COMPONENTS.has(String(component)) && typeof name === "string") {
|
|
175
|
-
context.textFields.set(name, (!context.textFields.has(name) || context.bindings !== void 0) && (component === "TextField" || component === "DateTimeInput"));
|
|
176
|
-
const field = (fallback) => fallback === void 0 ? { $field: name } : {
|
|
177
|
-
$field: name,
|
|
178
|
-
fallback
|
|
179
|
-
};
|
|
180
|
-
const listValued = component === "ChoicePicker" && mapped.$type !== "CheckboxGroup" && typeof value !== "string";
|
|
181
|
-
context.inputFields.set(name, listValued ? [field(Array.isArray(value) ? value[0] : void 0)] : field(value));
|
|
182
|
-
}
|
|
183
|
-
const action = mapped.$action;
|
|
184
|
-
const raw = node["action"];
|
|
185
|
-
if (!action || !isRecord(raw)) return;
|
|
186
|
-
const functionCall = action.type === "a2ui:functionCall";
|
|
187
|
-
const event = isRecord(raw["event"]) ? raw["event"] : raw;
|
|
188
|
-
const userMessage = event["userMessage"];
|
|
189
|
-
if (!functionCall && isBinding(userMessage)) context.boundUserMessages.push({
|
|
190
|
-
action,
|
|
191
|
-
pointer: pointerIn(scope, userMessage.path)
|
|
192
|
-
});
|
|
193
|
-
const rawEntries = functionCall ? isRecord(raw["functionCall"]) ? raw["functionCall"]["args"] : void 0 : event["context"];
|
|
194
|
-
const target = functionCall ? action["args"] : action["context"];
|
|
195
|
-
if (!isRecord(rawEntries) || !isRecord(target)) return;
|
|
196
|
-
for (const [key, entry] of Object.entries(rawEntries)) if (isBinding(entry)) context.boundActionEntries.push({
|
|
197
|
-
target,
|
|
198
|
-
key,
|
|
199
|
-
pointer: pointerIn(scope, entry.path)
|
|
200
|
-
});
|
|
201
|
-
};
|
|
202
|
-
const spendEvaluation = (context) => {
|
|
203
|
-
if (context.evaluations < EVALUATION_BUDGET) {
|
|
204
|
-
context.evaluations++;
|
|
205
|
-
return true;
|
|
206
|
-
}
|
|
207
|
-
if (!context.evaluationBudgetWarned) {
|
|
208
|
-
context.warnings.push(`A2UI function evaluation budget of ${EVALUATION_BUDGET} was reached.`);
|
|
209
|
-
context.evaluationBudgetWarned = true;
|
|
210
|
-
}
|
|
211
|
-
return false;
|
|
212
|
-
};
|
|
213
|
-
const reserveNode = (context) => {
|
|
214
|
-
if (context.emittedNodes >= NODE_BUDGET) {
|
|
215
|
-
if (!context.budgetWarned) {
|
|
216
|
-
context.warnings.push(`A2UI node budget of ${NODE_BUDGET} was reached.`);
|
|
217
|
-
context.budgetWarned = true;
|
|
218
|
-
}
|
|
219
|
-
return false;
|
|
220
|
-
}
|
|
221
|
-
context.emittedNodes++;
|
|
222
|
-
return true;
|
|
223
|
-
};
|
|
224
|
-
const childReferences = (node) => {
|
|
225
|
-
const children = node["children"];
|
|
226
|
-
const references = Array.isArray(children) ? [...children] : [];
|
|
227
|
-
if (node["child"] !== void 0) references.push(node["child"]);
|
|
228
|
-
if (node["component"] === "Modal") references.push(node["trigger"], node["content"]);
|
|
229
|
-
if (node["component"] === "Tabs" && Array.isArray(node["tabs"])) for (const tab of node["tabs"]) references.push(isRecord(tab) ? tab["child"] : void 0);
|
|
230
|
-
return references;
|
|
231
|
-
};
|
|
232
|
-
const childrenOf = (node, scope, context, depth, visited) => {
|
|
233
|
-
const result = [];
|
|
234
|
-
for (const childId of childReferences(node)) {
|
|
235
|
-
if (typeof childId !== "string") {
|
|
236
|
-
context.warnings.push(`Component "${String(node["id"] ?? "")}" has a malformed child reference.`);
|
|
237
|
-
continue;
|
|
238
|
-
}
|
|
239
|
-
const child = convertComponent(childId, scope, context, depth + 1, visited);
|
|
240
|
-
if (child) result.push(child);
|
|
241
|
-
}
|
|
242
|
-
return result;
|
|
243
|
-
};
|
|
244
|
-
const textLabel = (node, children, context) => {
|
|
245
|
-
const references = childReferences(node);
|
|
246
|
-
const [reference] = references;
|
|
247
|
-
const [child] = children;
|
|
248
|
-
if (references.length !== 1 || children.length !== 1 || typeof reference !== "string" || !child || context.surface.components.get(reference)?.["component"] !== "Text") return;
|
|
249
|
-
const text = child.$type === "Header" ? child["text"] : child["value"];
|
|
250
|
-
return typeof text === "string" ? text : void 0;
|
|
251
|
-
};
|
|
252
|
-
const mappedAction = (node, props, context) => {
|
|
253
|
-
const action = props["action"];
|
|
254
|
-
if (action === void 0) return void 0;
|
|
255
|
-
const source = {
|
|
256
|
-
surfaceId: context.surfaceId,
|
|
257
|
-
sourceComponentId: typeof node["id"] === "string" ? node["id"] : ""
|
|
258
|
-
};
|
|
259
|
-
const event = isRecord(action) && isRecord(action["event"]) ? action["event"] : action;
|
|
260
|
-
const actionName = typeof event === "string" ? event : isRecord(event) && typeof event["name"] === "string" ? event["name"] : void 0;
|
|
261
|
-
if (actionName) {
|
|
262
|
-
const actionContext = isRecord(event) ? event["context"] : void 0;
|
|
263
|
-
const userMessage = isRecord(event) ? event["userMessage"] : void 0;
|
|
264
|
-
return {
|
|
265
|
-
type: "a2ui:action",
|
|
266
|
-
name: actionName,
|
|
267
|
-
...source,
|
|
268
|
-
...typeof userMessage === "string" ? { userMessage } : {},
|
|
269
|
-
...actionContext !== void 0 ? { context: actionContext } : {}
|
|
270
|
-
};
|
|
271
|
-
}
|
|
272
|
-
const functionCall = isRecord(action) ? action["functionCall"] : void 0;
|
|
273
|
-
if (isRecord(functionCall) && typeof functionCall["call"] === "string") {
|
|
274
|
-
const args = functionCall["args"];
|
|
275
|
-
return {
|
|
276
|
-
type: "a2ui:functionCall",
|
|
277
|
-
call: functionCall["call"],
|
|
278
|
-
...source,
|
|
279
|
-
...isRecord(args) ? { args } : {}
|
|
280
|
-
};
|
|
281
|
-
}
|
|
282
|
-
context.warnings.push(`Component "${String(node["id"] ?? "")}" has a malformed action.`);
|
|
283
|
-
};
|
|
284
|
-
const choiceOptions = (value) => {
|
|
285
|
-
if (!Array.isArray(value)) return [];
|
|
286
|
-
const options = [];
|
|
287
|
-
for (const option of value) if (isRecord(option) && typeof option["label"] === "string" && typeof option["value"] === "string") options.push({
|
|
288
|
-
label: option["label"],
|
|
289
|
-
value: option["value"]
|
|
290
|
-
});
|
|
291
|
-
return options;
|
|
292
|
-
};
|
|
293
|
-
const mappedProps = (node, props, context, scope) => {
|
|
294
|
-
const component = node["component"];
|
|
295
|
-
if (component === "Text") {
|
|
296
|
-
const text = stringProp(props, ["text", "value"]);
|
|
297
|
-
const variant = props["variant"];
|
|
298
|
-
if (typeof variant === "string" && /^h[1-6]$/.test(variant)) return {
|
|
299
|
-
$type: "Header",
|
|
300
|
-
...text !== void 0 ? { text } : {}
|
|
301
|
-
};
|
|
302
|
-
if (variant === "caption") return {
|
|
303
|
-
$type: "Caption",
|
|
304
|
-
...text !== void 0 ? { value: text } : {}
|
|
305
|
-
};
|
|
306
|
-
return {
|
|
307
|
-
$type: "Markdown",
|
|
308
|
-
...text !== void 0 ? { value: text } : {}
|
|
309
|
-
};
|
|
310
|
-
}
|
|
311
|
-
if (component === "Image") {
|
|
312
|
-
const src = stringProp(props, ["src", "url"]);
|
|
313
|
-
const alt = stringProp(props, [
|
|
314
|
-
"alt",
|
|
315
|
-
"altText",
|
|
316
|
-
"description"
|
|
317
|
-
]);
|
|
318
|
-
const size = props["size"];
|
|
319
|
-
const round = props["round"];
|
|
320
|
-
return {
|
|
321
|
-
$type: "Image",
|
|
322
|
-
...src !== void 0 ? { src } : {},
|
|
323
|
-
...alt !== void 0 ? { alt } : {},
|
|
324
|
-
...typeof size === "string" || typeof size === "number" ? { size } : {},
|
|
325
|
-
...typeof round === "boolean" ? { round } : {}
|
|
326
|
-
};
|
|
327
|
-
}
|
|
328
|
-
if (component === "Icon") {
|
|
329
|
-
const name = stringProp(props, ["name"]);
|
|
330
|
-
if (!name || !ICON_NAME_SET.has(name)) return void 0;
|
|
331
|
-
const size = props["size"];
|
|
332
|
-
return {
|
|
333
|
-
$type: "Icon",
|
|
334
|
-
name,
|
|
335
|
-
...typeof size === "string" && ICON_SIZE_SET.has(size) ? { size } : {}
|
|
336
|
-
};
|
|
337
|
-
}
|
|
338
|
-
if (component === "Row") {
|
|
339
|
-
const gap = props["gap"];
|
|
340
|
-
const align = firstDefined(props, ["align", "alignment"]);
|
|
341
|
-
const justify = firstDefined(props, ["justify", "distribution"]);
|
|
342
|
-
return {
|
|
343
|
-
$type: "Row",
|
|
344
|
-
...typeof gap === "number" ? { gap } : {},
|
|
345
|
-
...typeof align === "string" ? { align } : {},
|
|
346
|
-
...typeof justify === "string" ? { justify } : {}
|
|
347
|
-
};
|
|
348
|
-
}
|
|
349
|
-
if (component === "Column") {
|
|
350
|
-
const gap = props["gap"];
|
|
351
|
-
const align = firstDefined(props, ["align", "alignment"]);
|
|
352
|
-
return {
|
|
353
|
-
$type: "Col",
|
|
354
|
-
...typeof gap === "number" ? { gap } : {},
|
|
355
|
-
...typeof align === "string" ? { align } : {}
|
|
356
|
-
};
|
|
357
|
-
}
|
|
358
|
-
if (component === "List") {
|
|
359
|
-
const direction = props["direction"];
|
|
360
|
-
const align = props["align"];
|
|
361
|
-
if (direction === "horizontal") return {
|
|
362
|
-
$type: "Row",
|
|
363
|
-
...typeof align === "string" ? { align } : {}
|
|
364
|
-
};
|
|
365
|
-
return { $type: "ListView" };
|
|
366
|
-
}
|
|
367
|
-
if (component === "Card") {
|
|
368
|
-
const title = props["title"];
|
|
369
|
-
const padding = props["padding"];
|
|
370
|
-
const background = props["background"];
|
|
371
|
-
return {
|
|
372
|
-
$type: "Card",
|
|
373
|
-
...typeof title === "string" ? { title } : {},
|
|
374
|
-
...typeof padding === "number" ? { padding } : {},
|
|
375
|
-
...typeof background === "string" ? { background } : {}
|
|
376
|
-
};
|
|
377
|
-
}
|
|
378
|
-
if (component === "Divider") return {
|
|
379
|
-
$type: "Divider",
|
|
380
|
-
...typeof props["flush"] === "boolean" ? { flush: props["flush"] } : {}
|
|
381
|
-
};
|
|
382
|
-
if (component === "Button") {
|
|
383
|
-
const label = stringProp(props, ["label", "text"]);
|
|
384
|
-
const variantStyle = props["variant"] === "primary" ? "primary" : props["variant"] === "borderless" ? "ghost" : void 0;
|
|
385
|
-
const buttonStyle = typeof props["buttonStyle"] === "string" ? props["buttonStyle"] : variantStyle;
|
|
386
|
-
const block = props["block"];
|
|
387
|
-
const submit = props["submit"];
|
|
388
|
-
const action = mappedAction(node, props, context);
|
|
389
|
-
return {
|
|
390
|
-
$type: "Button",
|
|
391
|
-
...label !== void 0 ? { label } : {},
|
|
392
|
-
...buttonStyle !== void 0 ? { buttonStyle } : {},
|
|
393
|
-
...typeof block === "boolean" ? { block } : {},
|
|
394
|
-
...typeof submit === "boolean" ? { submit } : {},
|
|
395
|
-
...action ? { $action: action } : {}
|
|
396
|
-
};
|
|
397
|
-
}
|
|
398
|
-
const bound = bindingPath(firstDefined(node, BOUND_KEYS));
|
|
399
|
-
const name = bound === void 0 ? void 0 : pointerIn(scope, bound);
|
|
400
|
-
const label = stringProp(props, ["label"]);
|
|
401
|
-
if (component === "TextField") {
|
|
402
|
-
const placeholder = stringProp(props, ["placeholder"]);
|
|
403
|
-
const inputType = props["variant"] === "obscured" ? "password" : props["variant"] === "number" ? "number" : void 0;
|
|
404
|
-
const multiline = typeof props["multiline"] === "boolean" ? props["multiline"] : props["variant"] === "longText" || props["textFieldType"] === "longText" ? true : void 0;
|
|
405
|
-
const initial = firstDefined(props, ["value", "text"]);
|
|
406
|
-
const defaultValue = typeof initial === "string" ? initial : typeof initial === "number" && Number.isFinite(initial) ? String(initial) : void 0;
|
|
407
|
-
return {
|
|
408
|
-
$type: "Input",
|
|
409
|
-
...inputType !== void 0 ? { inputType } : {},
|
|
410
|
-
...placeholder !== void 0 ? { placeholder } : {},
|
|
411
|
-
...multiline !== void 0 ? { multiline } : {},
|
|
412
|
-
...label !== void 0 ? { label } : {},
|
|
413
|
-
...name !== void 0 ? { name } : {},
|
|
414
|
-
...defaultValue !== void 0 ? { defaultValue } : {}
|
|
415
|
-
};
|
|
416
|
-
}
|
|
417
|
-
if (component === "CheckBox") {
|
|
418
|
-
const defaultChecked = firstDefined(props, ["defaultChecked", "value"]);
|
|
419
|
-
return {
|
|
420
|
-
$type: "Checkbox",
|
|
421
|
-
...label !== void 0 ? { label } : {},
|
|
422
|
-
...name !== void 0 ? { name } : {},
|
|
423
|
-
...typeof defaultChecked === "boolean" ? { defaultChecked } : {}
|
|
424
|
-
};
|
|
425
|
-
}
|
|
426
|
-
if (component === "Slider") {
|
|
427
|
-
const min = finiteNumber(props["min"]) ?? 0;
|
|
428
|
-
const max = finiteNumber(props["max"]);
|
|
429
|
-
if (max === void 0 || max < min) return void 0;
|
|
430
|
-
const value = finiteNumber(props["value"]);
|
|
431
|
-
const step = sliderStep(min, max, name === void 0 ? value : finiteNumber(resolvePointer(context.stepModel, name)), props["steps"]);
|
|
432
|
-
return {
|
|
433
|
-
$type: "Slider",
|
|
434
|
-
min,
|
|
435
|
-
max,
|
|
436
|
-
...step !== void 0 ? { step } : {},
|
|
437
|
-
...value !== void 0 ? { defaultValue: value } : {},
|
|
438
|
-
...label !== void 0 ? { label } : {},
|
|
439
|
-
...name !== void 0 ? { name } : {}
|
|
440
|
-
};
|
|
441
|
-
}
|
|
442
|
-
if (component === "ChoicePicker") {
|
|
443
|
-
const options = choiceOptions(props["options"]);
|
|
444
|
-
const value = props["value"];
|
|
445
|
-
const selected = typeof value === "string" ? [value] : Array.isArray(value) ? value.filter((entry) => typeof entry === "string") : [];
|
|
446
|
-
if (props["variant"] === "multipleSelection") return {
|
|
447
|
-
$type: "CheckboxGroup",
|
|
448
|
-
options,
|
|
449
|
-
...label !== void 0 ? { label } : {},
|
|
450
|
-
...name !== void 0 ? { name } : {},
|
|
451
|
-
...selected.length > 0 ? { defaultValue: selected } : {}
|
|
452
|
-
};
|
|
453
|
-
const [defaultValue] = selected;
|
|
454
|
-
return {
|
|
455
|
-
$type: "RadioGroup",
|
|
456
|
-
options,
|
|
457
|
-
...label !== void 0 ? { label } : {},
|
|
458
|
-
...name !== void 0 ? { name } : {},
|
|
459
|
-
...defaultValue !== void 0 ? { defaultValue } : {}
|
|
460
|
-
};
|
|
461
|
-
}
|
|
462
|
-
if (component === "DateTimeInput") {
|
|
463
|
-
const value = stringProp(props, ["value"]);
|
|
464
|
-
const shapeValue = name === void 0 ? value : resolvePointer(context.stepModel, name);
|
|
465
|
-
const shapeType = typeof shapeValue === "string" ? dateInputType(shapeValue) : void 0;
|
|
466
|
-
let inputType = shapeType ?? "date";
|
|
467
|
-
if ("enableDate" in props || "enableTime" in props) inputType = props["enableTime"] === true ? props["enableDate"] === true ? "datetime" : "time" : "date";
|
|
468
|
-
if (typeof shapeValue === "string" && shapeValue !== "" && shapeType !== inputType) return {
|
|
469
|
-
$type: "Input",
|
|
470
|
-
...value !== void 0 ? { defaultValue: value } : {},
|
|
471
|
-
...label !== void 0 ? { label } : {},
|
|
472
|
-
...name !== void 0 ? { name } : {}
|
|
473
|
-
};
|
|
474
|
-
const bound = (edge) => {
|
|
475
|
-
const boundValue = stringProp(props, [edge]);
|
|
476
|
-
if (boundValue === void 0) return void 0;
|
|
477
|
-
const boundType = dateInputType(boundValue);
|
|
478
|
-
if (boundType === inputType) return boundValue;
|
|
479
|
-
if (inputType === "datetime" && boundType === "date") return `${boundValue}T${edge === "min" ? "00:00" : "23:59:59.999"}`;
|
|
480
|
-
context.warnings.push(`A2UI DateTimeInput "${edge}" of "${boundValue}" is not a ${inputType} value and was dropped.`);
|
|
481
|
-
};
|
|
482
|
-
const min = bound("min");
|
|
483
|
-
const max = bound("max");
|
|
484
|
-
return {
|
|
485
|
-
$type: "DatePicker",
|
|
486
|
-
inputType,
|
|
487
|
-
...value !== void 0 ? { value } : {},
|
|
488
|
-
...min !== void 0 ? { min } : {},
|
|
489
|
-
...max !== void 0 ? { max } : {},
|
|
490
|
-
...label !== void 0 ? { label } : {},
|
|
491
|
-
...name !== void 0 ? { name } : {}
|
|
492
|
-
};
|
|
493
|
-
}
|
|
494
|
-
};
|
|
495
|
-
const convertTemplate = (node, template, scope, context, depth, visited, converted) => {
|
|
496
|
-
if (!reserveNode(context)) return null;
|
|
497
|
-
const container = converted ?? { $type: "ListView" };
|
|
498
|
-
const itemized = container.$type === "ListView";
|
|
499
|
-
const list = resolvePointer(context.surface.dataModel, pointerIn(scope, template.path));
|
|
500
|
-
const listPointer = pointerIn(scope, template.path);
|
|
501
|
-
if (!Array.isArray(list)) {
|
|
502
|
-
context.warnings.push(`Template on component "${String(node["id"] ?? "")}" did not resolve to a list.`);
|
|
503
|
-
return {
|
|
504
|
-
...container,
|
|
505
|
-
children: []
|
|
506
|
-
};
|
|
507
|
-
}
|
|
508
|
-
const itemCount = Math.min(list.length, TEMPLATE_ITEM_CAP);
|
|
509
|
-
if (list.length > TEMPLATE_ITEM_CAP && !context.templateCapWarned) {
|
|
510
|
-
context.warnings.push(`A2UI template expansion was capped at ${TEMPLATE_ITEM_CAP} items.`);
|
|
511
|
-
context.templateCapWarned = true;
|
|
512
|
-
}
|
|
513
|
-
const children = [];
|
|
514
|
-
for (let index = 0; index < itemCount; index++) {
|
|
515
|
-
if (itemized && !reserveNode(context)) break;
|
|
516
|
-
const child = convertComponent(template.componentId, {
|
|
517
|
-
data: list[index],
|
|
518
|
-
path: `${listPointer}/${index}`
|
|
519
|
-
}, context, depth + 1, visited);
|
|
520
|
-
if (itemized) children.push({
|
|
521
|
-
$type: "ListViewItem",
|
|
522
|
-
...child ? { children: child } : {}
|
|
523
|
-
});
|
|
524
|
-
else if (child) children.push(child);
|
|
525
|
-
}
|
|
526
|
-
return {
|
|
527
|
-
...container,
|
|
528
|
-
children
|
|
529
|
-
};
|
|
530
|
-
};
|
|
531
|
-
function convertComponent(componentId, scope, context, depth, visited) {
|
|
532
|
-
if (depth >= DEPTH_CAP) {
|
|
533
|
-
if (!context.depthWarned) {
|
|
534
|
-
context.warnings.push(`A2UI depth cap of ${DEPTH_CAP} was reached.`);
|
|
535
|
-
context.depthWarned = true;
|
|
536
|
-
}
|
|
537
|
-
return null;
|
|
538
|
-
}
|
|
539
|
-
if (visited.has(componentId)) {
|
|
540
|
-
context.warnings.push(`A2UI component cycle detected at "${componentId}".`);
|
|
541
|
-
return null;
|
|
542
|
-
}
|
|
543
|
-
const node = context.surface.components.get(componentId);
|
|
544
|
-
if (!node) {
|
|
545
|
-
context.warnings.push(`A2UI component "${componentId}" was not found.`);
|
|
546
|
-
return null;
|
|
547
|
-
}
|
|
548
|
-
const component = node["component"];
|
|
549
|
-
visited.add(componentId);
|
|
550
|
-
try {
|
|
551
|
-
if (typeof component !== "string") {
|
|
552
|
-
context.warnings.push(`Unknown A2UI component "${String(component ?? "")}" was skipped.`);
|
|
553
|
-
return null;
|
|
554
|
-
}
|
|
555
|
-
const template = childTemplateOf(node["children"]);
|
|
556
|
-
if (!SUPPORTED_COMPONENTS.has(component) && !context.keepUnknownComponents && !template) {
|
|
557
|
-
context.warnings.push(`Unknown A2UI component "${component}" was skipped.`);
|
|
558
|
-
return null;
|
|
559
|
-
}
|
|
560
|
-
const cacheKey = context.cache ? JSON.stringify([
|
|
561
|
-
componentId,
|
|
562
|
-
scope.path,
|
|
563
|
-
depth
|
|
564
|
-
]) : "";
|
|
565
|
-
let cached = context.cache?.get(cacheKey);
|
|
566
|
-
if (cached && (context.evaluations + cached.evaluations > EVALUATION_BUDGET || [...cached.dependencies].some(([path, value]) => !Object.is(resolvePointer(context.surface.dataModel, path), value)))) cached = void 0;
|
|
567
|
-
let props;
|
|
568
|
-
let mapped;
|
|
569
|
-
if (cached) {
|
|
570
|
-
props = cached.props;
|
|
571
|
-
mapped = cached.mapped;
|
|
572
|
-
context.evaluations += cached.evaluations;
|
|
573
|
-
} else {
|
|
574
|
-
props = {};
|
|
575
|
-
const dependencies = /* @__PURE__ */ new Map();
|
|
576
|
-
const evaluations = context.evaluations;
|
|
577
|
-
context.dependencies = dependencies;
|
|
578
|
-
context.scopePath = scope.path;
|
|
579
|
-
for (const [key, value] of Object.entries(node)) {
|
|
580
|
-
if (key === "id" || key === "component" || key === "children" || key === "child") continue;
|
|
581
|
-
const resolved = materialize(value, scope.data, context, key !== "checks");
|
|
582
|
-
if (resolved !== void 0) setOwnProperty(props, key, resolved);
|
|
583
|
-
}
|
|
584
|
-
context.dependencies = void 0;
|
|
585
|
-
mapped = mappedProps(node, props, context, scope);
|
|
586
|
-
if (context.cache && context.warnings.length === 0 && !mapped?.$action) {
|
|
587
|
-
cached = {
|
|
588
|
-
props,
|
|
589
|
-
mapped,
|
|
590
|
-
dependencies,
|
|
591
|
-
evaluations: context.evaluations - evaluations
|
|
592
|
-
};
|
|
593
|
-
context.cache.set(cacheKey, cached);
|
|
594
|
-
}
|
|
595
|
-
}
|
|
596
|
-
if (mapped && context.bindings && typeof mapped["name"] === "string" && INPUT_COMPONENTS.has(component)) {
|
|
597
|
-
const field = mapped.$type === "Checkbox" ? "checked" : "value";
|
|
598
|
-
const defaultField = mapped.$type === "Checkbox" ? "defaultChecked" : "defaultValue";
|
|
599
|
-
const fallback = mapped.$type === "Checkbox" ? false : mapped.$type === "CheckboxGroup" ? [] : mapped.$type === "Slider" ? mapped["min"] : "";
|
|
600
|
-
const { [defaultField]: initialValue, ...rest } = mapped;
|
|
601
|
-
mapped = {
|
|
602
|
-
...rest,
|
|
603
|
-
[field]: initialValue ?? mapped[field] ?? fallback
|
|
604
|
-
};
|
|
605
|
-
context.bindings.set(mapped["name"], {
|
|
606
|
-
value: mapped[field],
|
|
607
|
-
arrayValue: component === "ChoicePicker" && mapped.$type !== "CheckboxGroup" && typeof props["value"] !== "string"
|
|
608
|
-
});
|
|
609
|
-
}
|
|
610
|
-
if (!mapped && SUPPORTED_COMPONENTS.has(component)) {
|
|
611
|
-
context.warnings.push(`A2UI component "${component}" could not be mapped and was skipped.`);
|
|
612
|
-
return null;
|
|
613
|
-
}
|
|
614
|
-
const retained = !mapped && context.keepUnknownComponents ? {
|
|
615
|
-
$type: component,
|
|
616
|
-
...Object.fromEntries(Object.entries(props).filter(([key]) => !key.startsWith("$")))
|
|
617
|
-
} : void 0;
|
|
618
|
-
if (template) return convertTemplate(node, template, scope, context, depth, visited, CHILD_LIST_COMPONENTS.has(component) ? mapped : retained);
|
|
619
|
-
if (!reserveNode(context)) return null;
|
|
620
|
-
const converted = mapped ?? retained;
|
|
621
|
-
if (!converted) return null;
|
|
622
|
-
recordBindings(node, props, converted, scope, context);
|
|
623
|
-
const children = childrenOf(node, scope, context, depth, visited);
|
|
624
|
-
if (mapped?.$type === "Button" && mapped["label"] === void 0) {
|
|
625
|
-
const label = textLabel(node, children, context);
|
|
626
|
-
if (label !== void 0) return {
|
|
627
|
-
...mapped,
|
|
628
|
-
label
|
|
629
|
-
};
|
|
630
|
-
}
|
|
631
|
-
const listChildren = component === "List" && mapped?.$type === "ListView" ? children.map((child) => ({
|
|
632
|
-
$type: "ListViewItem",
|
|
633
|
-
children: child
|
|
634
|
-
})) : children;
|
|
635
|
-
if (cached?.result && cached.children?.length === listChildren.length && cached.children.every((child, index) => child === listChildren[index])) return cached.result;
|
|
636
|
-
const result = {
|
|
637
|
-
...converted,
|
|
638
|
-
...listChildren.length > 0 ? { children: listChildren } : {}
|
|
639
|
-
};
|
|
640
|
-
if (cached) {
|
|
641
|
-
cached.children = listChildren;
|
|
642
|
-
cached.result = result;
|
|
643
|
-
}
|
|
644
|
-
return result;
|
|
645
|
-
} finally {
|
|
646
|
-
visited.delete(componentId);
|
|
647
|
-
}
|
|
648
|
-
}
|
|
649
|
-
function convertSurfaceToUISpec(surface, options = {}) {
|
|
650
|
-
return convertSurface(surface, options.keepUnknownComponents === true);
|
|
651
|
-
}
|
|
652
|
-
const createLiveSurfaceConverter = (surface) => {
|
|
653
|
-
const cache = /* @__PURE__ */ new Map();
|
|
654
|
-
const templates = /* @__PURE__ */ new Map();
|
|
655
|
-
return (dataModel) => {
|
|
656
|
-
const bindings = /* @__PURE__ */ new Map();
|
|
657
|
-
return {
|
|
658
|
-
...convertSurface({
|
|
659
|
-
...surface,
|
|
660
|
-
dataModel,
|
|
661
|
-
[A2UI_SURFACE_ID]: sourceSurfaceId(surface)
|
|
662
|
-
}, false, bindings, cache, templates, surface.dataModel),
|
|
663
|
-
bindings
|
|
664
|
-
};
|
|
665
|
-
};
|
|
666
|
-
};
|
|
667
|
-
function convertSurface(surface, keepUnknownComponents, bindings, cache, templates = /* @__PURE__ */ new Map(), stepModel = surface.dataModel) {
|
|
668
|
-
const warnings = [];
|
|
669
|
-
if (!surface.components.has("root")) return {
|
|
670
|
-
spec: null,
|
|
671
|
-
warnings: ["A2UI root component \"root\" was not found."]
|
|
672
|
-
};
|
|
673
|
-
const context = {
|
|
674
|
-
surface,
|
|
675
|
-
stepModel,
|
|
676
|
-
surfaceId: sourceSurfaceId(surface),
|
|
677
|
-
warnings,
|
|
678
|
-
emittedNodes: 0,
|
|
679
|
-
depthWarned: false,
|
|
680
|
-
budgetWarned: false,
|
|
681
|
-
templateCapWarned: false,
|
|
682
|
-
evaluations: 0,
|
|
683
|
-
evaluationBudgetWarned: false,
|
|
684
|
-
functionDepthWarned: false,
|
|
685
|
-
templates,
|
|
686
|
-
inputFields: /* @__PURE__ */ new Map(),
|
|
687
|
-
textFields: /* @__PURE__ */ new Map(),
|
|
688
|
-
boundActionEntries: [],
|
|
689
|
-
boundUserMessages: [],
|
|
690
|
-
keepUnknownComponents,
|
|
691
|
-
bindings,
|
|
692
|
-
cache,
|
|
693
|
-
dependencies: void 0,
|
|
694
|
-
scopePath: ""
|
|
695
|
-
};
|
|
696
|
-
try {
|
|
697
|
-
const spec = convertComponent("root", {
|
|
698
|
-
data: surface.dataModel,
|
|
699
|
-
path: ""
|
|
700
|
-
}, context, 0, /* @__PURE__ */ new Set());
|
|
701
|
-
for (const { target, key, pointer } of context.boundActionEntries) {
|
|
702
|
-
const value = withFieldReferences(target[key], pointer, context.inputFields);
|
|
703
|
-
if (value !== void 0) setOwnProperty(target, key, value);
|
|
704
|
-
}
|
|
705
|
-
for (const { action, pointer } of context.boundUserMessages) {
|
|
706
|
-
if (!context.textFields.get(pointer)) continue;
|
|
707
|
-
const fallback = action["userMessage"];
|
|
708
|
-
setOwnProperty(action, "userMessage", typeof fallback === "string" ? {
|
|
709
|
-
$field: pointer,
|
|
710
|
-
fallback
|
|
711
|
-
} : { $field: pointer });
|
|
712
|
-
}
|
|
713
|
-
return {
|
|
714
|
-
spec,
|
|
715
|
-
warnings
|
|
716
|
-
};
|
|
717
|
-
} catch {
|
|
718
|
-
warnings.push("A2UI surface conversion encountered malformed input.");
|
|
719
|
-
return {
|
|
720
|
-
spec: null,
|
|
721
|
-
warnings
|
|
722
|
-
};
|
|
723
|
-
}
|
|
724
|
-
}
|
|
725
|
-
//#endregion
|
|
726
|
-
export { convertSurfaceToUISpec, createLiveSurfaceConverter };
|
|
727
|
-
|
|
728
|
-
//# sourceMappingURL=convert.js.map
|