@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.
Files changed (338) hide show
  1. package/README.md +2 -0
  2. package/dist/a2ui.d.ts +1 -4
  3. package/dist/a2ui.d.ts.map +1 -1
  4. package/dist/a2ui.js +1 -4
  5. package/dist/index.d.ts +1 -2
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +1 -10
  8. package/dist/index.server.d.ts +1 -2
  9. package/dist/index.server.d.ts.map +1 -1
  10. package/dist/index.server.js +1 -10
  11. package/dist/ir.d.ts +1 -111
  12. package/dist/ir.d.ts.map +1 -1
  13. package/dist/ir.js +1 -175
  14. package/dist/slack.d.ts +1 -4
  15. package/dist/slack.d.ts.map +1 -1
  16. package/dist/slack.js +1 -4
  17. package/dist/teams.d.ts +1 -4
  18. package/dist/teams.d.ts.map +1 -1
  19. package/dist/teams.js +1 -4
  20. package/package.json +5 -5
  21. package/src/a2ui.ts +1 -22
  22. package/src/index.server.ts +1 -2
  23. package/src/index.test.ts +75 -0
  24. package/src/index.ts +1 -2
  25. package/src/ir.ts +1 -279
  26. package/src/slack.ts +1 -39
  27. package/src/teams.ts +1 -35
  28. package/dist/JSONGenerativeUI.client.d.ts +0 -28
  29. package/dist/JSONGenerativeUI.client.d.ts.map +0 -1
  30. package/dist/JSONGenerativeUI.client.js +0 -101
  31. package/dist/JSONGenerativeUI.client.js.map +0 -1
  32. package/dist/JSONGenerativeUI.server.d.ts +0 -21
  33. package/dist/JSONGenerativeUI.server.d.ts.map +0 -1
  34. package/dist/JSONGenerativeUI.server.js +0 -32
  35. package/dist/JSONGenerativeUI.server.js.map +0 -1
  36. package/dist/JSONGenerativeUI.shared.d.ts +0 -63
  37. package/dist/JSONGenerativeUI.shared.d.ts.map +0 -1
  38. package/dist/JSONGenerativeUI.shared.js +0 -31
  39. package/dist/JSONGenerativeUI.shared.js.map +0 -1
  40. package/dist/RadioGroupScope.d.ts +0 -6
  41. package/dist/RadioGroupScope.d.ts.map +0 -1
  42. package/dist/RadioGroupScope.js +0 -25
  43. package/dist/RadioGroupScope.js.map +0 -1
  44. package/dist/a2ui/BindingContext.d.ts +0 -11
  45. package/dist/a2ui/BindingContext.d.ts.map +0 -1
  46. package/dist/a2ui/BindingContext.js +0 -12
  47. package/dist/a2ui/BindingContext.js.map +0 -1
  48. package/dist/a2ui/PresentRenderer.d.ts +0 -11
  49. package/dist/a2ui/PresentRenderer.d.ts.map +0 -1
  50. package/dist/a2ui/PresentRenderer.js +0 -39
  51. package/dist/a2ui/PresentRenderer.js.map +0 -1
  52. package/dist/a2ui/convert.d.ts +0 -15
  53. package/dist/a2ui/convert.d.ts.map +0 -1
  54. package/dist/a2ui/convert.js +0 -728
  55. package/dist/a2ui/convert.js.map +0 -1
  56. package/dist/a2ui/dataModel.d.ts +0 -9
  57. package/dist/a2ui/dataModel.d.ts.map +0 -1
  58. package/dist/a2ui/dataModel.js +0 -44
  59. package/dist/a2ui/dataModel.js.map +0 -1
  60. package/dist/a2ui/reducer.d.ts +0 -8
  61. package/dist/a2ui/reducer.d.ts.map +0 -1
  62. package/dist/a2ui/reducer.js +0 -242
  63. package/dist/a2ui/reducer.js.map +0 -1
  64. package/dist/a2ui/snapshot.d.ts +0 -3
  65. package/dist/a2ui/snapshot.d.ts.map +0 -1
  66. package/dist/a2ui/snapshot.js +0 -33
  67. package/dist/a2ui/snapshot.js.map +0 -1
  68. package/dist/a2ui/types.d.ts +0 -88
  69. package/dist/a2ui/types.d.ts.map +0 -1
  70. package/dist/a2ui/types.js +0 -6
  71. package/dist/a2ui/types.js.map +0 -1
  72. package/dist/a2ui/valueFunctions.d.ts +0 -16
  73. package/dist/a2ui/valueFunctions.d.ts.map +0 -1
  74. package/dist/a2ui/valueFunctions.js +0 -332
  75. package/dist/a2ui/valueFunctions.js.map +0 -1
  76. package/dist/actionRegistry.d.ts +0 -29
  77. package/dist/actionRegistry.d.ts.map +0 -1
  78. package/dist/actionRegistry.js +0 -41
  79. package/dist/actionRegistry.js.map +0 -1
  80. package/dist/answeredValues.d.ts +0 -16
  81. package/dist/answeredValues.d.ts.map +0 -1
  82. package/dist/answeredValues.js +0 -37
  83. package/dist/answeredValues.js.map +0 -1
  84. package/dist/buildPresentParameters.d.ts +0 -21
  85. package/dist/buildPresentParameters.d.ts.map +0 -1
  86. package/dist/buildPresentParameters.js +0 -95
  87. package/dist/buildPresentParameters.js.map +0 -1
  88. package/dist/constants.d.ts +0 -15
  89. package/dist/constants.d.ts.map +0 -1
  90. package/dist/constants.js +0 -19
  91. package/dist/constants.js.map +0 -1
  92. package/dist/convert/boundSpec.d.ts +0 -48
  93. package/dist/convert/boundSpec.d.ts.map +0 -1
  94. package/dist/convert/boundSpec.js +0 -108
  95. package/dist/convert/boundSpec.js.map +0 -1
  96. package/dist/convert/copyBounded.d.ts +0 -25
  97. package/dist/convert/copyBounded.d.ts.map +0 -1
  98. package/dist/convert/copyBounded.js +0 -38
  99. package/dist/convert/copyBounded.js.map +0 -1
  100. package/dist/convert/isElement.d.ts +0 -3
  101. package/dist/convert/isElement.d.ts.map +0 -1
  102. package/dist/convert/isElement.js +0 -6
  103. package/dist/convert/isElement.js.map +0 -1
  104. package/dist/convert/takeRun.d.ts +0 -6
  105. package/dist/convert/takeRun.d.ts.map +0 -1
  106. package/dist/convert/takeRun.js +0 -20
  107. package/dist/convert/takeRun.js.map +0 -1
  108. package/dist/defineGenerativeComponents.d.ts +0 -29
  109. package/dist/defineGenerativeComponents.d.ts.map +0 -1
  110. package/dist/defineGenerativeComponents.js +0 -34
  111. package/dist/defineGenerativeComponents.js.map +0 -1
  112. package/dist/fieldReferences.d.ts +0 -9
  113. package/dist/fieldReferences.d.ts.map +0 -1
  114. package/dist/fieldReferences.js +0 -53
  115. package/dist/fieldReferences.js.map +0 -1
  116. package/dist/generativeUIToJSX.d.ts +0 -18
  117. package/dist/generativeUIToJSX.d.ts.map +0 -1
  118. package/dist/generativeUIToJSX.js +0 -76
  119. package/dist/generativeUIToJSX.js.map +0 -1
  120. package/dist/index.shared.d.ts +0 -15
  121. package/dist/index.shared.d.ts.map +0 -1
  122. package/dist/index.shared.js +0 -9
  123. package/dist/ir.js.map +0 -1
  124. package/dist/renderGenerativeUI.d.ts +0 -14
  125. package/dist/renderGenerativeUI.d.ts.map +0 -1
  126. package/dist/renderGenerativeUI.js +0 -83
  127. package/dist/renderGenerativeUI.js.map +0 -1
  128. package/dist/scopeSchema.d.ts +0 -6
  129. package/dist/scopeSchema.d.ts.map +0 -1
  130. package/dist/scopeSchema.js +0 -56
  131. package/dist/scopeSchema.js.map +0 -1
  132. package/dist/slack/constants.d.ts +0 -93
  133. package/dist/slack/constants.d.ts.map +0 -1
  134. package/dist/slack/constants.js +0 -146
  135. package/dist/slack/constants.js.map +0 -1
  136. package/dist/slack/decodeBlockAction.d.ts +0 -10
  137. package/dist/slack/decodeBlockAction.d.ts.map +0 -1
  138. package/dist/slack/decodeBlockAction.js +0 -129
  139. package/dist/slack/decodeBlockAction.js.map +0 -1
  140. package/dist/slack/fromSlackBlocks.d.ts +0 -27
  141. package/dist/slack/fromSlackBlocks.d.ts.map +0 -1
  142. package/dist/slack/fromSlackBlocks.js +0 -483
  143. package/dist/slack/fromSlackBlocks.js.map +0 -1
  144. package/dist/slack/toSlackBlocks.d.ts +0 -4
  145. package/dist/slack/toSlackBlocks.d.ts.map +0 -1
  146. package/dist/slack/toSlackBlocks.js +0 -901
  147. package/dist/slack/toSlackBlocks.js.map +0 -1
  148. package/dist/slack/types.d.ts +0 -204
  149. package/dist/slack/types.d.ts.map +0 -1
  150. package/dist/slack/types.js +0 -0
  151. package/dist/teams/constants.d.ts +0 -34
  152. package/dist/teams/constants.d.ts.map +0 -1
  153. package/dist/teams/constants.js +0 -68
  154. package/dist/teams/constants.js.map +0 -1
  155. package/dist/teams/decodeSubmitData.d.ts +0 -26
  156. package/dist/teams/decodeSubmitData.d.ts.map +0 -1
  157. package/dist/teams/decodeSubmitData.js +0 -70
  158. package/dist/teams/decodeSubmitData.js.map +0 -1
  159. package/dist/teams/temporalId.d.ts +0 -5
  160. package/dist/teams/temporalId.d.ts.map +0 -1
  161. package/dist/teams/temporalId.js +0 -28
  162. package/dist/teams/temporalId.js.map +0 -1
  163. package/dist/teams/toAdaptiveCard.d.ts +0 -45
  164. package/dist/teams/toAdaptiveCard.d.ts.map +0 -1
  165. package/dist/teams/toAdaptiveCard.js +0 -642
  166. package/dist/teams/toAdaptiveCard.js.map +0 -1
  167. package/dist/teams/toTeamsAttachments.d.ts +0 -10
  168. package/dist/teams/toTeamsAttachments.d.ts.map +0 -1
  169. package/dist/teams/toTeamsAttachments.js +0 -99
  170. package/dist/teams/toTeamsAttachments.js.map +0 -1
  171. package/dist/teams/types.d.ts +0 -224
  172. package/dist/teams/types.d.ts.map +0 -1
  173. package/dist/teams/types.js +0 -0
  174. package/dist/temporal.d.ts +0 -33
  175. package/dist/temporal.d.ts.map +0 -1
  176. package/dist/temporal.js +0 -152
  177. package/dist/temporal.js.map +0 -1
  178. package/dist/types.d.ts +0 -99
  179. package/dist/types.d.ts.map +0 -1
  180. package/dist/types.js +0 -0
  181. package/dist/vocabulary/alert.d.ts +0 -32
  182. package/dist/vocabulary/alert.d.ts.map +0 -1
  183. package/dist/vocabulary/alert.js +0 -160
  184. package/dist/vocabulary/alert.js.map +0 -1
  185. package/dist/vocabulary/collectFormValues.d.ts +0 -23
  186. package/dist/vocabulary/collectFormValues.d.ts.map +0 -1
  187. package/dist/vocabulary/collectFormValues.js +0 -44
  188. package/dist/vocabulary/collectFormValues.js.map +0 -1
  189. package/dist/vocabulary/data.d.ts +0 -66
  190. package/dist/vocabulary/data.d.ts.map +0 -1
  191. package/dist/vocabulary/data.js +0 -503
  192. package/dist/vocabulary/data.js.map +0 -1
  193. package/dist/vocabulary/dispatch.d.ts +0 -9
  194. package/dist/vocabulary/dispatch.d.ts.map +0 -1
  195. package/dist/vocabulary/dispatch.js +0 -50
  196. package/dist/vocabulary/dispatch.js.map +0 -1
  197. package/dist/vocabulary/fact.d.ts +0 -19
  198. package/dist/vocabulary/fact.d.ts.map +0 -1
  199. package/dist/vocabulary/fact.js +0 -51
  200. package/dist/vocabulary/fact.js.map +0 -1
  201. package/dist/vocabulary/form.d.ts +0 -11
  202. package/dist/vocabulary/form.d.ts.map +0 -1
  203. package/dist/vocabulary/form.js +0 -23
  204. package/dist/vocabulary/form.js.map +0 -1
  205. package/dist/vocabulary/formatValue.d.ts +0 -7
  206. package/dist/vocabulary/formatValue.d.ts.map +0 -1
  207. package/dist/vocabulary/formatValue.js +0 -76
  208. package/dist/vocabulary/formatValue.js.map +0 -1
  209. package/dist/vocabulary/icon.d.ts +0 -41
  210. package/dist/vocabulary/icon.d.ts.map +0 -1
  211. package/dist/vocabulary/icon.js +0 -272
  212. package/dist/vocabulary/icon.js.map +0 -1
  213. package/dist/vocabulary/index.d.ts +0 -12
  214. package/dist/vocabulary/index.d.ts.map +0 -1
  215. package/dist/vocabulary/index.js +0 -36
  216. package/dist/vocabulary/index.js.map +0 -1
  217. package/dist/vocabulary/interactive.d.ts +0 -230
  218. package/dist/vocabulary/interactive.d.ts.map +0 -1
  219. package/dist/vocabulary/interactive.js +0 -530
  220. package/dist/vocabulary/interactive.js.map +0 -1
  221. package/dist/vocabulary/layout.d.ts +0 -79
  222. package/dist/vocabulary/layout.d.ts.map +0 -1
  223. package/dist/vocabulary/layout.js +0 -139
  224. package/dist/vocabulary/layout.js.map +0 -1
  225. package/dist/vocabulary/list.d.ts +0 -14
  226. package/dist/vocabulary/list.d.ts.map +0 -1
  227. package/dist/vocabulary/list.js +0 -50
  228. package/dist/vocabulary/list.js.map +0 -1
  229. package/dist/vocabulary/media.d.ts +0 -25
  230. package/dist/vocabulary/media.d.ts.map +0 -1
  231. package/dist/vocabulary/media.js +0 -42
  232. package/dist/vocabulary/media.js.map +0 -1
  233. package/dist/vocabulary/text.d.ts +0 -57
  234. package/dist/vocabulary/text.d.ts.map +0 -1
  235. package/dist/vocabulary/text.js +0 -49
  236. package/dist/vocabulary/text.js.map +0 -1
  237. package/dist/vocabulary/toTextContent.d.ts +0 -2
  238. package/dist/vocabulary/toTextContent.d.ts.map +0 -1
  239. package/dist/vocabulary/toTextContent.js +0 -6
  240. package/dist/vocabulary/toTextContent.js.map +0 -1
  241. package/src/JSONGenerativeUI.client.tsx +0 -168
  242. package/src/JSONGenerativeUI.server.tsx +0 -39
  243. package/src/JSONGenerativeUI.shared.ts +0 -90
  244. package/src/JSONGenerativeUI.test.tsx +0 -1298
  245. package/src/RadioGroupScope.server.test.tsx +0 -24
  246. package/src/RadioGroupScope.tsx +0 -34
  247. package/src/a2ui/BindingContext.ts +0 -26
  248. package/src/a2ui/PresentRenderer.tsx +0 -83
  249. package/src/a2ui/convert.test.ts +0 -2923
  250. package/src/a2ui/convert.ts +0 -1207
  251. package/src/a2ui/dataModel.ts +0 -69
  252. package/src/a2ui/reducer.test.ts +0 -422
  253. package/src/a2ui/reducer.ts +0 -363
  254. package/src/a2ui/snapshot.test.ts +0 -52
  255. package/src/a2ui/snapshot.ts +0 -52
  256. package/src/a2ui/types.ts +0 -114
  257. package/src/a2ui/valueFunctions.test.ts +0 -271
  258. package/src/a2ui/valueFunctions.ts +0 -523
  259. package/src/actionRegistry.test.ts +0 -90
  260. package/src/actionRegistry.ts +0 -88
  261. package/src/answeredValues.test.ts +0 -33
  262. package/src/answeredValues.tsx +0 -70
  263. package/src/buildPresentParameters.test.ts +0 -246
  264. package/src/buildPresentParameters.ts +0 -130
  265. package/src/constants.ts +0 -17
  266. package/src/convert/boundSpec.test.ts +0 -192
  267. package/src/convert/boundSpec.ts +0 -134
  268. package/src/convert/copyBounded.test.ts +0 -131
  269. package/src/convert/copyBounded.ts +0 -38
  270. package/src/convert/isElement.ts +0 -6
  271. package/src/convert/takeRun.test.ts +0 -64
  272. package/src/convert/takeRun.ts +0 -19
  273. package/src/defineGenerativeComponents.ts +0 -38
  274. package/src/fieldReferences.test.ts +0 -66
  275. package/src/fieldReferences.ts +0 -83
  276. package/src/generativeUIToJSX.test.ts +0 -268
  277. package/src/generativeUIToJSX.ts +0 -152
  278. package/src/index.server.test.ts +0 -106
  279. package/src/index.shared.ts +0 -61
  280. package/src/ir.test.ts +0 -203
  281. package/src/renderGenerativeUI.test.tsx +0 -373
  282. package/src/renderGenerativeUI.tsx +0 -165
  283. package/src/scopeSchema.test.ts +0 -72
  284. package/src/scopeSchema.ts +0 -71
  285. package/src/slack/a2uiSlack.test.ts +0 -198
  286. package/src/slack/constants.ts +0 -194
  287. package/src/slack/datePicker.test.ts +0 -612
  288. package/src/slack/decodeBlockAction.test.ts +0 -233
  289. package/src/slack/decodeBlockAction.ts +0 -232
  290. package/src/slack/fromSlackBlocks.test.ts +0 -1465
  291. package/src/slack/fromSlackBlocks.ts +0 -789
  292. package/src/slack/toSlackBlocks.test.ts +0 -3065
  293. package/src/slack/toSlackBlocks.ts +0 -1818
  294. package/src/slack/types.ts +0 -264
  295. package/src/teams/constants.ts +0 -93
  296. package/src/teams/decodeSubmitData.test.ts +0 -397
  297. package/src/teams/decodeSubmitData.ts +0 -110
  298. package/src/teams/temporal.test.ts +0 -766
  299. package/src/teams/temporalId.ts +0 -56
  300. package/src/teams/toAdaptiveCard.test.ts +0 -1897
  301. package/src/teams/toAdaptiveCard.ts +0 -1057
  302. package/src/teams/toTeamsAttachments.test.ts +0 -74
  303. package/src/teams/toTeamsAttachments.ts +0 -133
  304. package/src/teams/types.ts +0 -266
  305. package/src/temporal.test.ts +0 -319
  306. package/src/temporal.ts +0 -259
  307. package/src/types.ts +0 -119
  308. package/src/vocabulary/alert.test.tsx +0 -427
  309. package/src/vocabulary/alert.tsx +0 -217
  310. package/src/vocabulary/collectFormValues.test.ts +0 -389
  311. package/src/vocabulary/collectFormValues.ts +0 -116
  312. package/src/vocabulary/data.test.tsx +0 -858
  313. package/src/vocabulary/data.tsx +0 -819
  314. package/src/vocabulary/datepicker.dom.test.tsx +0 -1148
  315. package/src/vocabulary/dispatch.ts +0 -83
  316. package/src/vocabulary/fact.test.tsx +0 -94
  317. package/src/vocabulary/fact.tsx +0 -54
  318. package/src/vocabulary/form.test.tsx +0 -113
  319. package/src/vocabulary/form.tsx +0 -39
  320. package/src/vocabulary/formatValue.test.ts +0 -72
  321. package/src/vocabulary/formatValue.ts +0 -127
  322. package/src/vocabulary/icon.test.tsx +0 -64
  323. package/src/vocabulary/icon.tsx +0 -174
  324. package/src/vocabulary/index.test.ts +0 -65
  325. package/src/vocabulary/index.ts +0 -33
  326. package/src/vocabulary/interactive.dispatch.test.tsx +0 -454
  327. package/src/vocabulary/interactive.dom.test.tsx +0 -1747
  328. package/src/vocabulary/interactive.test.tsx +0 -377
  329. package/src/vocabulary/interactive.tsx +0 -1048
  330. package/src/vocabulary/layout.test.tsx +0 -323
  331. package/src/vocabulary/layout.tsx +0 -247
  332. package/src/vocabulary/list.test.tsx +0 -222
  333. package/src/vocabulary/list.tsx +0 -50
  334. package/src/vocabulary/media.test.tsx +0 -85
  335. package/src/vocabulary/media.tsx +0 -56
  336. package/src/vocabulary/text.test.tsx +0 -102
  337. package/src/vocabulary/text.tsx +0 -60
  338. package/src/vocabulary/toTextContent.ts +0 -2
@@ -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