@assistant-ui/react-generative-ui 0.0.21 → 0.0.23
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/LICENSE +1 -1
- package/dist/JSONGenerativeUI.client.d.ts.map +1 -1
- package/dist/JSONGenerativeUI.client.js +30 -13
- package/dist/JSONGenerativeUI.client.js.map +1 -1
- package/dist/RadioGroupScope.d.ts +6 -0
- package/dist/RadioGroupScope.d.ts.map +1 -0
- package/dist/RadioGroupScope.js +25 -0
- package/dist/RadioGroupScope.js.map +1 -0
- package/dist/a2ui/BindingContext.d.ts +11 -0
- package/dist/a2ui/BindingContext.d.ts.map +1 -0
- package/dist/a2ui/BindingContext.js +12 -0
- package/dist/a2ui/BindingContext.js.map +1 -0
- package/dist/a2ui/PresentRenderer.d.ts +11 -0
- package/dist/a2ui/PresentRenderer.d.ts.map +1 -0
- package/dist/a2ui/PresentRenderer.js +39 -0
- package/dist/a2ui/PresentRenderer.js.map +1 -0
- package/dist/a2ui/convert.d.ts +6 -0
- package/dist/a2ui/convert.d.ts.map +1 -1
- package/dist/a2ui/convert.js +363 -85
- package/dist/a2ui/convert.js.map +1 -1
- package/dist/a2ui/dataModel.d.ts +9 -0
- package/dist/a2ui/dataModel.d.ts.map +1 -0
- package/dist/a2ui/dataModel.js +44 -0
- package/dist/a2ui/dataModel.js.map +1 -0
- package/dist/a2ui/reducer.d.ts +5 -0
- package/dist/a2ui/reducer.d.ts.map +1 -1
- package/dist/a2ui/reducer.js +3 -3
- package/dist/a2ui/reducer.js.map +1 -1
- package/dist/a2ui/types.d.ts +8 -2
- package/dist/a2ui/types.d.ts.map +1 -1
- package/dist/a2ui/types.js.map +1 -1
- package/dist/a2ui/valueFunctions.d.ts +16 -0
- package/dist/a2ui/valueFunctions.d.ts.map +1 -0
- package/dist/a2ui/valueFunctions.js +332 -0
- package/dist/a2ui/valueFunctions.js.map +1 -0
- package/dist/actionRegistry.d.ts +1 -1
- package/dist/actionRegistry.js.map +1 -1
- package/dist/answeredValues.d.ts +16 -0
- package/dist/answeredValues.d.ts.map +1 -0
- package/dist/answeredValues.js +37 -0
- package/dist/answeredValues.js.map +1 -0
- package/dist/constants.d.ts +3 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +4 -1
- package/dist/constants.js.map +1 -1
- package/dist/fieldReferences.d.ts +9 -0
- package/dist/fieldReferences.d.ts.map +1 -0
- package/dist/fieldReferences.js +53 -0
- package/dist/fieldReferences.js.map +1 -0
- package/dist/generativeUIToJSX.js +3 -3
- package/dist/generativeUIToJSX.js.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.server.js +2 -2
- package/dist/index.shared.js +2 -2
- package/dist/ir.d.ts +1 -1
- package/dist/ir.js.map +1 -1
- package/dist/renderGenerativeUI.d.ts.map +1 -1
- package/dist/renderGenerativeUI.js +12 -1
- package/dist/renderGenerativeUI.js.map +1 -1
- package/dist/slack/constants.d.ts +2 -0
- package/dist/slack/constants.d.ts.map +1 -1
- package/dist/slack/constants.js +3 -1
- package/dist/slack/constants.js.map +1 -1
- package/dist/slack/decodeBlockAction.d.ts +3 -1
- package/dist/slack/decodeBlockAction.d.ts.map +1 -1
- package/dist/slack/decodeBlockAction.js +96 -7
- package/dist/slack/decodeBlockAction.js.map +1 -1
- package/dist/slack/fromSlackBlocks.d.ts.map +1 -1
- package/dist/slack/fromSlackBlocks.js +43 -3
- package/dist/slack/fromSlackBlocks.js.map +1 -1
- package/dist/slack/toSlackBlocks.d.ts.map +1 -1
- package/dist/slack/toSlackBlocks.js +244 -20
- package/dist/slack/toSlackBlocks.js.map +1 -1
- package/dist/slack/types.d.ts +24 -1
- package/dist/slack/types.d.ts.map +1 -1
- package/dist/slack.d.ts +1 -1
- package/dist/slack.d.ts.map +1 -1
- package/dist/teams/constants.d.ts +1 -1
- package/dist/teams/constants.d.ts.map +1 -1
- package/dist/teams/constants.js +1 -1
- package/dist/teams/constants.js.map +1 -1
- package/dist/teams/decodeSubmitData.d.ts +4 -0
- package/dist/teams/decodeSubmitData.d.ts.map +1 -1
- package/dist/teams/decodeSubmitData.js +29 -3
- package/dist/teams/decodeSubmitData.js.map +1 -1
- package/dist/teams/temporalId.d.ts +5 -0
- package/dist/teams/temporalId.d.ts.map +1 -0
- package/dist/teams/temporalId.js +28 -0
- package/dist/teams/temporalId.js.map +1 -0
- package/dist/teams/toAdaptiveCard.d.ts +5 -4
- package/dist/teams/toAdaptiveCard.d.ts.map +1 -1
- package/dist/teams/toAdaptiveCard.js +136 -18
- package/dist/teams/toAdaptiveCard.js.map +1 -1
- package/dist/teams/toTeamsAttachments.d.ts.map +1 -1
- package/dist/teams/toTeamsAttachments.js.map +1 -1
- package/dist/teams/types.d.ts +23 -2
- package/dist/teams/types.d.ts.map +1 -1
- package/dist/teams.d.ts +1 -1
- package/dist/teams.d.ts.map +1 -1
- package/dist/temporal.d.ts +33 -0
- package/dist/temporal.d.ts.map +1 -0
- package/dist/temporal.js +152 -0
- package/dist/temporal.js.map +1 -0
- package/dist/vocabulary/alert.d.ts +9 -2
- package/dist/vocabulary/alert.d.ts.map +1 -1
- package/dist/vocabulary/alert.js +116 -19
- package/dist/vocabulary/alert.js.map +1 -1
- package/dist/vocabulary/collectFormValues.d.ts +2 -1
- package/dist/vocabulary/collectFormValues.d.ts.map +1 -1
- package/dist/vocabulary/collectFormValues.js +15 -4
- package/dist/vocabulary/collectFormValues.js.map +1 -1
- package/dist/vocabulary/data.d.ts +22 -5
- package/dist/vocabulary/data.d.ts.map +1 -1
- package/dist/vocabulary/data.js +278 -83
- package/dist/vocabulary/data.js.map +1 -1
- package/dist/vocabulary/dispatch.d.ts +3 -2
- package/dist/vocabulary/dispatch.d.ts.map +1 -1
- package/dist/vocabulary/dispatch.js +33 -4
- package/dist/vocabulary/dispatch.js.map +1 -1
- package/dist/vocabulary/fact.d.ts +8 -1
- package/dist/vocabulary/fact.d.ts.map +1 -1
- package/dist/vocabulary/fact.js +37 -11
- package/dist/vocabulary/fact.js.map +1 -1
- package/dist/vocabulary/form.d.ts.map +1 -1
- package/dist/vocabulary/form.js +3 -3
- package/dist/vocabulary/form.js.map +1 -1
- package/dist/vocabulary/formatValue.d.ts +7 -0
- package/dist/vocabulary/formatValue.d.ts.map +1 -0
- package/dist/vocabulary/formatValue.js +76 -0
- package/dist/vocabulary/formatValue.js.map +1 -0
- package/dist/vocabulary/icon.d.ts +1 -1
- package/dist/vocabulary/interactive.d.ts +143 -8
- package/dist/vocabulary/interactive.d.ts.map +1 -1
- package/dist/vocabulary/interactive.js +458 -107
- package/dist/vocabulary/interactive.js.map +1 -1
- package/dist/vocabulary/layout.d.ts.map +1 -1
- package/dist/vocabulary/layout.js +4 -4
- package/dist/vocabulary/layout.js.map +1 -1
- package/dist/vocabulary/list.js +2 -2
- package/dist/vocabulary/list.js.map +1 -1
- package/dist/vocabulary/text.d.ts +1 -1
- package/package.json +8 -5
- package/src/JSONGenerativeUI.client.tsx +84 -40
- package/src/JSONGenerativeUI.test.tsx +964 -68
- package/src/RadioGroupScope.server.test.tsx +24 -0
- package/src/RadioGroupScope.tsx +34 -0
- package/src/a2ui/BindingContext.ts +26 -0
- package/src/a2ui/PresentRenderer.tsx +83 -0
- package/src/a2ui/convert.test.ts +2054 -229
- package/src/a2ui/convert.ts +665 -134
- package/src/a2ui/dataModel.ts +69 -0
- package/src/a2ui/reducer.test.ts +35 -0
- package/src/a2ui/reducer.ts +5 -4
- package/src/a2ui/types.ts +9 -2
- package/src/a2ui/valueFunctions.test.ts +271 -0
- package/src/a2ui/valueFunctions.ts +523 -0
- package/src/actionRegistry.ts +1 -1
- package/src/answeredValues.test.ts +33 -0
- package/src/answeredValues.tsx +70 -0
- package/src/constants.ts +5 -0
- package/src/fieldReferences.test.ts +66 -0
- package/src/fieldReferences.ts +83 -0
- package/src/generativeUIToJSX.test.ts +18 -0
- package/src/generativeUIToJSX.ts +4 -6
- package/src/index.server.test.ts +106 -0
- package/src/ir.ts +1 -1
- package/src/renderGenerativeUI.test.tsx +14 -5
- package/src/renderGenerativeUI.tsx +30 -1
- package/src/slack/a2uiSlack.test.ts +198 -0
- package/src/slack/constants.ts +3 -0
- package/src/slack/datePicker.test.ts +612 -0
- package/src/slack/decodeBlockAction.test.ts +98 -0
- package/src/slack/decodeBlockAction.ts +182 -16
- package/src/slack/fromSlackBlocks.test.ts +222 -3
- package/src/slack/fromSlackBlocks.ts +82 -2
- package/src/slack/toSlackBlocks.test.ts +682 -3
- package/src/slack/toSlackBlocks.ts +463 -25
- package/src/slack/types.ts +28 -0
- package/src/slack.ts +2 -0
- package/src/teams/constants.ts +1 -1
- package/src/teams/decodeSubmitData.test.ts +249 -0
- package/src/teams/decodeSubmitData.ts +57 -4
- package/src/teams/temporal.test.ts +766 -0
- package/src/teams/temporalId.ts +56 -0
- package/src/teams/toAdaptiveCard.test.ts +219 -0
- package/src/teams/toAdaptiveCard.ts +259 -21
- package/src/teams/toTeamsAttachments.ts +4 -1
- package/src/teams/types.ts +21 -1
- package/src/teams.ts +1 -0
- package/src/temporal.test.ts +319 -0
- package/src/temporal.ts +259 -0
- package/src/vocabulary/alert.test.tsx +288 -7
- package/src/vocabulary/alert.tsx +168 -26
- package/src/vocabulary/collectFormValues.test.ts +225 -1
- package/src/vocabulary/collectFormValues.ts +54 -5
- package/src/vocabulary/data.test.tsx +248 -6
- package/src/vocabulary/data.tsx +398 -100
- package/src/vocabulary/datepicker.dom.test.tsx +1148 -0
- package/src/vocabulary/dispatch.ts +63 -2
- package/src/vocabulary/fact.test.tsx +67 -0
- package/src/vocabulary/fact.tsx +40 -9
- package/src/vocabulary/form.tsx +7 -2
- package/src/vocabulary/formatValue.test.ts +72 -0
- package/src/vocabulary/formatValue.ts +127 -0
- package/src/vocabulary/index.test.ts +2 -0
- package/src/vocabulary/interactive.dispatch.test.tsx +167 -79
- package/src/vocabulary/interactive.dom.test.tsx +1747 -0
- package/src/vocabulary/interactive.test.tsx +60 -4
- package/src/vocabulary/interactive.tsx +910 -155
- package/src/vocabulary/layout.test.tsx +6 -4
- package/src/vocabulary/layout.tsx +13 -2
- package/src/vocabulary/list.tsx +2 -2
package/dist/a2ui/convert.js
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import { ICON_NAMES } from "../ir.js";
|
|
2
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";
|
|
3
7
|
//#region src/a2ui/convert.ts
|
|
4
8
|
const DEPTH_CAP = 32;
|
|
5
9
|
const TEMPLATE_ITEM_CAP = 100;
|
|
6
10
|
const NODE_BUDGET = 5e3;
|
|
11
|
+
const EVALUATION_BUDGET = 2e4;
|
|
7
12
|
const SUPPORTED_COMPONENTS = /* @__PURE__ */ new Set([
|
|
8
13
|
"Text",
|
|
9
14
|
"Image",
|
|
@@ -17,7 +22,13 @@ const SUPPORTED_COMPONENTS = /* @__PURE__ */ new Set([
|
|
|
17
22
|
"TextField",
|
|
18
23
|
"CheckBox",
|
|
19
24
|
"ChoicePicker",
|
|
20
|
-
"DateTimeInput"
|
|
25
|
+
"DateTimeInput",
|
|
26
|
+
"Slider"
|
|
27
|
+
]);
|
|
28
|
+
const CHILD_LIST_COMPONENTS = /* @__PURE__ */ new Set([
|
|
29
|
+
"Row",
|
|
30
|
+
"Column",
|
|
31
|
+
"List"
|
|
21
32
|
]);
|
|
22
33
|
const ICON_NAME_SET = new Set(ICON_NAMES);
|
|
23
34
|
const ICON_SIZE_SET = /* @__PURE__ */ new Set([
|
|
@@ -40,44 +51,85 @@ const setOwnProperty = (target, key, value) => {
|
|
|
40
51
|
});
|
|
41
52
|
else target[key] = value;
|
|
42
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));
|
|
43
61
|
const isBinding = (value) => isPlainObject(value) && Object.keys(value).length === 1 && typeof value["path"] === "string";
|
|
44
|
-
const
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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;
|
|
49
68
|
};
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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;
|
|
62
81
|
}
|
|
63
|
-
|
|
82
|
+
const copy = isRecord(value) ? { ...value } : {};
|
|
83
|
+
setOwnProperty(copy, head, setIn(Object.hasOwn(copy, head) ? copy[head] : void 0, rest, leaf));
|
|
84
|
+
return copy;
|
|
64
85
|
};
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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;
|
|
69
91
|
};
|
|
70
|
-
const
|
|
71
|
-
if (isBinding(value)) return resolvePointer(source, value.path);
|
|
72
|
-
if (Array.isArray(value)) return value.map((entry) => materialize(entry, source)).filter((entry) => entry !== void 0);
|
|
73
|
-
if (!isPlainObject(value)) return value;
|
|
92
|
+
const materializeEntries = (value, source, context, evaluate, depth, positional = false) => {
|
|
74
93
|
const result = {};
|
|
75
94
|
for (const [key, entry] of Object.entries(value)) {
|
|
76
|
-
const resolved =
|
|
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);
|
|
77
99
|
if (resolved !== void 0) setOwnProperty(result, key, resolved);
|
|
78
100
|
}
|
|
79
101
|
return result;
|
|
80
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
|
+
}
|
|
81
133
|
const firstDefined = (props, keys) => {
|
|
82
134
|
for (const key of keys) if (props[key] !== void 0) return props[key];
|
|
83
135
|
};
|
|
@@ -86,6 +138,78 @@ const stringProp = (props, keys) => {
|
|
|
86
138
|
return typeof value === "string" ? value : void 0;
|
|
87
139
|
};
|
|
88
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
|
+
};
|
|
89
213
|
const reserveNode = (context) => {
|
|
90
214
|
if (context.emittedNodes >= NODE_BUDGET) {
|
|
91
215
|
if (!context.budgetWarned) {
|
|
@@ -105,14 +229,14 @@ const childReferences = (node) => {
|
|
|
105
229
|
if (node["component"] === "Tabs" && Array.isArray(node["tabs"])) for (const tab of node["tabs"]) references.push(isRecord(tab) ? tab["child"] : void 0);
|
|
106
230
|
return references;
|
|
107
231
|
};
|
|
108
|
-
const childrenOf = (node,
|
|
232
|
+
const childrenOf = (node, scope, context, depth, visited) => {
|
|
109
233
|
const result = [];
|
|
110
234
|
for (const childId of childReferences(node)) {
|
|
111
235
|
if (typeof childId !== "string") {
|
|
112
236
|
context.warnings.push(`Component "${String(node["id"] ?? "")}" has a malformed child reference.`);
|
|
113
237
|
continue;
|
|
114
238
|
}
|
|
115
|
-
const child = convertComponent(childId,
|
|
239
|
+
const child = convertComponent(childId, scope, context, depth + 1, visited);
|
|
116
240
|
if (child) result.push(child);
|
|
117
241
|
}
|
|
118
242
|
return result;
|
|
@@ -127,17 +251,35 @@ const textLabel = (node, children, context) => {
|
|
|
127
251
|
};
|
|
128
252
|
const mappedAction = (node, props, context) => {
|
|
129
253
|
const action = props["action"];
|
|
130
|
-
|
|
131
|
-
const
|
|
132
|
-
if (!actionName) return void 0;
|
|
133
|
-
const actionContext = isRecord(event) ? event["context"] : void 0;
|
|
134
|
-
return {
|
|
135
|
-
type: "a2ui:action",
|
|
136
|
-
name: actionName,
|
|
254
|
+
if (action === void 0) return void 0;
|
|
255
|
+
const source = {
|
|
137
256
|
surfaceId: context.surfaceId,
|
|
138
|
-
sourceComponentId: typeof node["id"] === "string" ? node["id"] : ""
|
|
139
|
-
...actionContext !== void 0 ? { context: actionContext } : {}
|
|
257
|
+
sourceComponentId: typeof node["id"] === "string" ? node["id"] : ""
|
|
140
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.`);
|
|
141
283
|
};
|
|
142
284
|
const choiceOptions = (value) => {
|
|
143
285
|
if (!Array.isArray(value)) return [];
|
|
@@ -148,7 +290,7 @@ const choiceOptions = (value) => {
|
|
|
148
290
|
});
|
|
149
291
|
return options;
|
|
150
292
|
};
|
|
151
|
-
const mappedProps = (node, props, context) => {
|
|
293
|
+
const mappedProps = (node, props, context, scope) => {
|
|
152
294
|
const component = node["component"];
|
|
153
295
|
if (component === "Text") {
|
|
154
296
|
const text = stringProp(props, ["text", "value"]);
|
|
@@ -239,35 +381,37 @@ const mappedProps = (node, props, context) => {
|
|
|
239
381
|
};
|
|
240
382
|
if (component === "Button") {
|
|
241
383
|
const label = stringProp(props, ["label", "text"]);
|
|
242
|
-
const
|
|
384
|
+
const variantStyle = props["variant"] === "primary" ? "primary" : props["variant"] === "borderless" ? "ghost" : void 0;
|
|
385
|
+
const buttonStyle = typeof props["buttonStyle"] === "string" ? props["buttonStyle"] : variantStyle;
|
|
243
386
|
const block = props["block"];
|
|
244
387
|
const submit = props["submit"];
|
|
245
388
|
const action = mappedAction(node, props, context);
|
|
246
389
|
return {
|
|
247
390
|
$type: "Button",
|
|
248
391
|
...label !== void 0 ? { label } : {},
|
|
249
|
-
...
|
|
392
|
+
...buttonStyle !== void 0 ? { buttonStyle } : {},
|
|
250
393
|
...typeof block === "boolean" ? { block } : {},
|
|
251
394
|
...typeof submit === "boolean" ? { submit } : {},
|
|
252
395
|
...action ? { $action: action } : {}
|
|
253
396
|
};
|
|
254
397
|
}
|
|
255
|
-
const
|
|
256
|
-
|
|
257
|
-
"value",
|
|
258
|
-
"binding"
|
|
259
|
-
]);
|
|
260
|
-
const name = lastPointerSegment(bindingPath(binding));
|
|
398
|
+
const bound = bindingPath(firstDefined(node, BOUND_KEYS));
|
|
399
|
+
const name = bound === void 0 ? void 0 : pointerIn(scope, bound);
|
|
261
400
|
const label = stringProp(props, ["label"]);
|
|
262
401
|
if (component === "TextField") {
|
|
263
402
|
const placeholder = stringProp(props, ["placeholder"]);
|
|
264
|
-
const
|
|
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;
|
|
265
407
|
return {
|
|
266
408
|
$type: "Input",
|
|
409
|
+
...inputType !== void 0 ? { inputType } : {},
|
|
267
410
|
...placeholder !== void 0 ? { placeholder } : {},
|
|
268
411
|
...multiline !== void 0 ? { multiline } : {},
|
|
269
412
|
...label !== void 0 ? { label } : {},
|
|
270
|
-
...name !== void 0 ? { name } : {}
|
|
413
|
+
...name !== void 0 ? { name } : {},
|
|
414
|
+
...defaultValue !== void 0 ? { defaultValue } : {}
|
|
271
415
|
};
|
|
272
416
|
}
|
|
273
417
|
if (component === "CheckBox") {
|
|
@@ -279,32 +423,67 @@ const mappedProps = (node, props, context) => {
|
|
|
279
423
|
...typeof defaultChecked === "boolean" ? { defaultChecked } : {}
|
|
280
424
|
};
|
|
281
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
|
+
}
|
|
282
442
|
if (component === "ChoicePicker") {
|
|
283
443
|
const options = choiceOptions(props["options"]);
|
|
284
444
|
const value = props["value"];
|
|
285
|
-
const
|
|
286
|
-
if (props["variant"] === "
|
|
287
|
-
$type: "
|
|
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",
|
|
288
448
|
options,
|
|
289
449
|
...label !== void 0 ? { label } : {},
|
|
290
450
|
...name !== void 0 ? { name } : {},
|
|
291
|
-
...
|
|
451
|
+
...selected.length > 0 ? { defaultValue: selected } : {}
|
|
292
452
|
};
|
|
293
|
-
const
|
|
453
|
+
const [defaultValue] = selected;
|
|
294
454
|
return {
|
|
295
|
-
$type: "
|
|
455
|
+
$type: "RadioGroup",
|
|
296
456
|
options,
|
|
297
|
-
...placeholder !== void 0 ? { placeholder } : {},
|
|
298
457
|
...label !== void 0 ? { label } : {},
|
|
299
|
-
...name !== void 0 ? { name } : {}
|
|
458
|
+
...name !== void 0 ? { name } : {},
|
|
459
|
+
...defaultValue !== void 0 ? { defaultValue } : {}
|
|
300
460
|
};
|
|
301
461
|
}
|
|
302
462
|
if (component === "DateTimeInput") {
|
|
303
463
|
const value = stringProp(props, ["value"]);
|
|
304
|
-
const
|
|
305
|
-
const
|
|
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");
|
|
306
484
|
return {
|
|
307
485
|
$type: "DatePicker",
|
|
486
|
+
inputType,
|
|
308
487
|
...value !== void 0 ? { value } : {},
|
|
309
488
|
...min !== void 0 ? { min } : {},
|
|
310
489
|
...max !== void 0 ? { max } : {},
|
|
@@ -313,11 +492,12 @@ const mappedProps = (node, props, context) => {
|
|
|
313
492
|
};
|
|
314
493
|
}
|
|
315
494
|
};
|
|
316
|
-
const convertTemplate = (node,
|
|
495
|
+
const convertTemplate = (node, template, scope, context, depth, visited, converted) => {
|
|
317
496
|
if (!reserveNode(context)) return null;
|
|
318
|
-
const
|
|
319
|
-
const
|
|
320
|
-
const list = resolvePointer(
|
|
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);
|
|
321
501
|
if (!Array.isArray(list)) {
|
|
322
502
|
context.warnings.push(`Template on component "${String(node["id"] ?? "")}" did not resolve to a list.`);
|
|
323
503
|
return {
|
|
@@ -332,21 +512,23 @@ const convertTemplate = (node, templateChildren, dataSource, context, depth, vis
|
|
|
332
512
|
}
|
|
333
513
|
const children = [];
|
|
334
514
|
for (let index = 0; index < itemCount; index++) {
|
|
335
|
-
if (
|
|
336
|
-
const child = convertComponent(
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
}
|
|
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({
|
|
340
521
|
$type: "ListViewItem",
|
|
341
522
|
...child ? { children: child } : {}
|
|
342
523
|
});
|
|
524
|
+
else if (child) children.push(child);
|
|
343
525
|
}
|
|
344
526
|
return {
|
|
345
527
|
...container,
|
|
346
528
|
children
|
|
347
529
|
};
|
|
348
530
|
};
|
|
349
|
-
function convertComponent(componentId,
|
|
531
|
+
function convertComponent(componentId, scope, context, depth, visited) {
|
|
350
532
|
if (depth >= DEPTH_CAP) {
|
|
351
533
|
if (!context.depthWarned) {
|
|
352
534
|
context.warnings.push(`A2UI depth cap of ${DEPTH_CAP} was reached.`);
|
|
@@ -370,19 +552,61 @@ function convertComponent(componentId, dataSource, context, depth, visited) {
|
|
|
370
552
|
context.warnings.push(`Unknown A2UI component "${String(component ?? "")}" was skipped.`);
|
|
371
553
|
return null;
|
|
372
554
|
}
|
|
373
|
-
const
|
|
374
|
-
|
|
375
|
-
if (!SUPPORTED_COMPONENTS.has(component) && !context.keepUnknownComponents && !hasTemplate) {
|
|
555
|
+
const template = childTemplateOf(node["children"]);
|
|
556
|
+
if (!SUPPORTED_COMPONENTS.has(component) && !context.keepUnknownComponents && !template) {
|
|
376
557
|
context.warnings.push(`Unknown A2UI component "${component}" was skipped.`);
|
|
377
558
|
return null;
|
|
378
559
|
}
|
|
379
|
-
const
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
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
|
+
});
|
|
384
609
|
}
|
|
385
|
-
const mapped = mappedProps(node, props, context);
|
|
386
610
|
if (!mapped && SUPPORTED_COMPONENTS.has(component)) {
|
|
387
611
|
context.warnings.push(`A2UI component "${component}" could not be mapped and was skipped.`);
|
|
388
612
|
return null;
|
|
@@ -391,11 +615,12 @@ function convertComponent(componentId, dataSource, context, depth, visited) {
|
|
|
391
615
|
$type: component,
|
|
392
616
|
...Object.fromEntries(Object.entries(props).filter(([key]) => !key.startsWith("$")))
|
|
393
617
|
} : void 0;
|
|
394
|
-
if (
|
|
618
|
+
if (template) return convertTemplate(node, template, scope, context, depth, visited, CHILD_LIST_COMPONENTS.has(component) ? mapped : retained);
|
|
395
619
|
if (!reserveNode(context)) return null;
|
|
396
620
|
const converted = mapped ?? retained;
|
|
397
621
|
if (!converted) return null;
|
|
398
|
-
|
|
622
|
+
recordBindings(node, props, converted, scope, context);
|
|
623
|
+
const children = childrenOf(node, scope, context, depth, visited);
|
|
399
624
|
if (mapped?.$type === "Button" && mapped["label"] === void 0) {
|
|
400
625
|
const label = textLabel(node, children, context);
|
|
401
626
|
if (label !== void 0) return {
|
|
@@ -407,15 +632,39 @@ function convertComponent(componentId, dataSource, context, depth, visited) {
|
|
|
407
632
|
$type: "ListViewItem",
|
|
408
633
|
children: child
|
|
409
634
|
})) : children;
|
|
410
|
-
return
|
|
635
|
+
if (cached?.result && cached.children?.length === listChildren.length && cached.children.every((child, index) => child === listChildren[index])) return cached.result;
|
|
636
|
+
const result = {
|
|
411
637
|
...converted,
|
|
412
638
|
...listChildren.length > 0 ? { children: listChildren } : {}
|
|
413
639
|
};
|
|
640
|
+
if (cached) {
|
|
641
|
+
cached.children = listChildren;
|
|
642
|
+
cached.result = result;
|
|
643
|
+
}
|
|
644
|
+
return result;
|
|
414
645
|
} finally {
|
|
415
646
|
visited.delete(componentId);
|
|
416
647
|
}
|
|
417
648
|
}
|
|
418
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) {
|
|
419
668
|
const warnings = [];
|
|
420
669
|
if (!surface.components.has("root")) return {
|
|
421
670
|
spec: null,
|
|
@@ -423,17 +672,46 @@ function convertSurfaceToUISpec(surface, options = {}) {
|
|
|
423
672
|
};
|
|
424
673
|
const context = {
|
|
425
674
|
surface,
|
|
675
|
+
stepModel,
|
|
426
676
|
surfaceId: sourceSurfaceId(surface),
|
|
427
677
|
warnings,
|
|
428
678
|
emittedNodes: 0,
|
|
429
679
|
depthWarned: false,
|
|
430
680
|
budgetWarned: false,
|
|
431
681
|
templateCapWarned: false,
|
|
432
|
-
|
|
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: ""
|
|
433
695
|
};
|
|
434
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
|
+
}
|
|
435
713
|
return {
|
|
436
|
-
spec
|
|
714
|
+
spec,
|
|
437
715
|
warnings
|
|
438
716
|
};
|
|
439
717
|
} catch {
|
|
@@ -445,6 +723,6 @@ function convertSurfaceToUISpec(surface, options = {}) {
|
|
|
445
723
|
}
|
|
446
724
|
}
|
|
447
725
|
//#endregion
|
|
448
|
-
export { convertSurfaceToUISpec };
|
|
726
|
+
export { convertSurfaceToUISpec, createLiveSurfaceConverter };
|
|
449
727
|
|
|
450
728
|
//# sourceMappingURL=convert.js.map
|