cortena-ui 1.3.0 → 1.4.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 (280) hide show
  1. package/README.md +74 -3
  2. package/dist/a2ui/catalogue-doc.d.ts +44 -0
  3. package/dist/a2ui/catalogue-doc.js +169 -0
  4. package/dist/a2ui/catalogue-doc.js.map +1 -0
  5. package/dist/a2ui/catalogue.d.ts +44 -0
  6. package/dist/a2ui/catalogue.js +942 -0
  7. package/dist/a2ui/catalogue.js.map +1 -0
  8. package/dist/a2ui/index.d.ts +7 -0
  9. package/dist/a2ui/message.d.ts +232 -0
  10. package/dist/a2ui/message.js +365 -0
  11. package/dist/a2ui/message.js.map +1 -0
  12. package/dist/a2ui/renderer.d.ts +46 -0
  13. package/dist/a2ui/renderer.js +252 -0
  14. package/dist/a2ui/renderer.js.map +1 -0
  15. package/dist/a2ui/views.d.ts +80 -0
  16. package/dist/a2ui/views.js +596 -0
  17. package/dist/a2ui/views.js.map +1 -0
  18. package/dist/a2ui.d.ts +8 -0
  19. package/dist/a2ui.js +7 -0
  20. package/dist/chart.d.ts +9 -0
  21. package/dist/chart.js +9 -0
  22. package/dist/components/accordion.d.ts +22 -0
  23. package/dist/components/accordion.js +63 -0
  24. package/dist/components/accordion.js.map +1 -0
  25. package/dist/components/alert.d.ts +15 -0
  26. package/dist/components/alert.js +64 -0
  27. package/dist/components/alert.js.map +1 -0
  28. package/dist/components/avatar.d.ts +18 -0
  29. package/dist/components/avatar.js +40 -0
  30. package/dist/components/avatar.js.map +1 -0
  31. package/dist/components/badge.d.ts +12 -0
  32. package/dist/components/badge.js +47 -0
  33. package/dist/components/badge.js.map +1 -0
  34. package/dist/components/breadcrumb.d.ts +71 -0
  35. package/dist/components/breadcrumb.js +123 -0
  36. package/dist/components/breadcrumb.js.map +1 -0
  37. package/dist/components/button-link.d.ts +28 -0
  38. package/dist/components/button-link.js +24 -0
  39. package/dist/components/button-link.js.map +1 -0
  40. package/dist/components/button.d.ts +24 -0
  41. package/dist/components/button.js +65 -0
  42. package/dist/components/button.js.map +1 -0
  43. package/dist/components/calendar.d.ts +28 -0
  44. package/dist/components/calendar.js +123 -0
  45. package/dist/components/calendar.js.map +1 -0
  46. package/dist/components/card.d.ts +32 -0
  47. package/dist/components/card.js +57 -0
  48. package/dist/components/card.js.map +1 -0
  49. package/dist/components/chart/chart.d.ts +71 -0
  50. package/dist/components/chart/chart.js +167 -0
  51. package/dist/components/chart/chart.js.map +1 -0
  52. package/dist/components/chart/container.d.ts +88 -0
  53. package/dist/components/chart/container.js +189 -0
  54. package/dist/components/chart/container.js.map +1 -0
  55. package/dist/components/chart/data.js +128 -0
  56. package/dist/components/chart/data.js.map +1 -0
  57. package/dist/components/chart/index.d.ts +9 -0
  58. package/dist/components/chart/index.js +10 -0
  59. package/dist/components/chart/nivo-charts.js +225 -0
  60. package/dist/components/chart/nivo-charts.js.map +1 -0
  61. package/dist/components/chart/nivo-lazy.js +50 -0
  62. package/dist/components/chart/nivo-lazy.js.map +1 -0
  63. package/dist/components/chart/nivo-theme.d.ts +156 -0
  64. package/dist/components/chart/nivo-theme.js +161 -0
  65. package/dist/components/chart/nivo-theme.js.map +1 -0
  66. package/dist/components/chart/recharts-charts.js +276 -0
  67. package/dist/components/chart/recharts-charts.js.map +1 -0
  68. package/dist/components/chart/recharts-lazy.js +58 -0
  69. package/dist/components/chart/recharts-lazy.js.map +1 -0
  70. package/dist/components/chart/recharts-parts.d.ts +10 -0
  71. package/dist/components/chart/recharts-parts.js +25 -0
  72. package/dist/components/chart/recharts-parts.js.map +1 -0
  73. package/dist/components/chart/tokens.d.ts +62 -0
  74. package/dist/components/chart/tokens.js +192 -0
  75. package/dist/components/chart/tokens.js.map +1 -0
  76. package/dist/components/chart/types.d.ts +114 -0
  77. package/dist/components/chart/types.js +27 -0
  78. package/dist/components/chart/types.js.map +1 -0
  79. package/dist/components/checkbox.d.ts +20 -0
  80. package/dist/components/checkbox.js +24 -0
  81. package/dist/components/checkbox.js.map +1 -0
  82. package/dist/components/chip.d.ts +17 -0
  83. package/dist/components/chip.js +47 -0
  84. package/dist/components/chip.js.map +1 -0
  85. package/dist/components/combobox.d.ts +76 -0
  86. package/dist/components/combobox.js +201 -0
  87. package/dist/components/combobox.js.map +1 -0
  88. package/dist/components/command.d.ts +50 -0
  89. package/dist/components/command.js +117 -0
  90. package/dist/components/command.js.map +1 -0
  91. package/dist/components/data-table/data-table.d.ts +65 -0
  92. package/dist/components/data-table/data-table.js +588 -0
  93. package/dist/components/data-table/data-table.js.map +1 -0
  94. package/dist/components/data-table/export.d.ts +23 -0
  95. package/dist/components/data-table/export.js +95 -0
  96. package/dist/components/data-table/export.js.map +1 -0
  97. package/dist/components/data-table/features.d.ts +66 -0
  98. package/dist/components/data-table/features.js +103 -0
  99. package/dist/components/data-table/features.js.map +1 -0
  100. package/dist/components/data-table/index.d.ts +8 -0
  101. package/dist/components/data-table/parts.d.ts +79 -0
  102. package/dist/components/data-table/parts.js +400 -0
  103. package/dist/components/data-table/parts.js.map +1 -0
  104. package/dist/components/data-table/system-columns.js +84 -0
  105. package/dist/components/data-table/system-columns.js.map +1 -0
  106. package/dist/components/data-table/types.d.ts +172 -0
  107. package/dist/components/data-table/use-data-table.d.ts +19 -0
  108. package/dist/components/data-table/use-data-table.js +171 -0
  109. package/dist/components/data-table/use-data-table.js.map +1 -0
  110. package/dist/components/data-table/use-server-source.js +200 -0
  111. package/dist/components/data-table/use-server-source.js.map +1 -0
  112. package/dist/components/date-field.d.ts +54 -0
  113. package/dist/components/date-field.js +235 -0
  114. package/dist/components/date-field.js.map +1 -0
  115. package/dist/components/date-picker.d.ts +42 -0
  116. package/dist/components/date-picker.js +125 -0
  117. package/dist/components/date-picker.js.map +1 -0
  118. package/dist/components/dialog.d.ts +36 -0
  119. package/dist/components/dialog.js +97 -0
  120. package/dist/components/dialog.js.map +1 -0
  121. package/dist/components/dropdown-menu.d.ts +54 -0
  122. package/dist/components/dropdown-menu.js +191 -0
  123. package/dist/components/dropdown-menu.js.map +1 -0
  124. package/dist/components/dropzone.d.ts +48 -0
  125. package/dist/components/dropzone.js +185 -0
  126. package/dist/components/dropzone.js.map +1 -0
  127. package/dist/components/empty-state.d.ts +22 -0
  128. package/dist/components/empty-state.js +46 -0
  129. package/dist/components/empty-state.js.map +1 -0
  130. package/dist/components/error-banner.d.ts +17 -0
  131. package/dist/components/error-banner.js +52 -0
  132. package/dist/components/error-banner.js.map +1 -0
  133. package/dist/components/field.d.ts +64 -0
  134. package/dist/components/field.js +133 -0
  135. package/dist/components/field.js.map +1 -0
  136. package/dist/components/form.d.ts +37 -0
  137. package/dist/components/form.js +103 -0
  138. package/dist/components/form.js.map +1 -0
  139. package/dist/components/input.d.ts +17 -0
  140. package/dist/components/input.js +26 -0
  141. package/dist/components/input.js.map +1 -0
  142. package/dist/components/kbd.d.ts +11 -0
  143. package/dist/components/kbd.js +20 -0
  144. package/dist/components/kbd.js.map +1 -0
  145. package/dist/components/label.d.ts +14 -0
  146. package/dist/components/label.js +28 -0
  147. package/dist/components/label.js.map +1 -0
  148. package/dist/components/loading-skeleton.d.ts +22 -0
  149. package/dist/components/loading-skeleton.js +123 -0
  150. package/dist/components/loading-skeleton.js.map +1 -0
  151. package/dist/components/markdown.d.ts +44 -0
  152. package/dist/components/markdown.js +231 -0
  153. package/dist/components/markdown.js.map +1 -0
  154. package/dist/components/page-header.d.ts +26 -0
  155. package/dist/components/page-header.js +53 -0
  156. package/dist/components/page-header.js.map +1 -0
  157. package/dist/components/popover.d.ts +29 -0
  158. package/dist/components/popover.js +74 -0
  159. package/dist/components/popover.js.map +1 -0
  160. package/dist/components/progress.d.ts +22 -0
  161. package/dist/components/progress.js +49 -0
  162. package/dist/components/progress.js.map +1 -0
  163. package/dist/components/radio-group.d.ts +20 -0
  164. package/dist/components/radio-group.js +29 -0
  165. package/dist/components/radio-group.js.map +1 -0
  166. package/dist/components/scroll-area.d.ts +25 -0
  167. package/dist/components/scroll-area.js +39 -0
  168. package/dist/components/scroll-area.js.map +1 -0
  169. package/dist/components/section-card.d.ts +29 -0
  170. package/dist/components/section-card.js +55 -0
  171. package/dist/components/section-card.js.map +1 -0
  172. package/dist/components/segmented.d.ts +27 -0
  173. package/dist/components/segmented.js +32 -0
  174. package/dist/components/segmented.js.map +1 -0
  175. package/dist/components/select.d.ts +62 -0
  176. package/dist/components/select.js +97 -0
  177. package/dist/components/select.js.map +1 -0
  178. package/dist/components/separator.d.ts +19 -0
  179. package/dist/components/separator.js +23 -0
  180. package/dist/components/separator.js.map +1 -0
  181. package/dist/components/sheet.d.ts +35 -0
  182. package/dist/components/sheet.js +131 -0
  183. package/dist/components/sheet.js.map +1 -0
  184. package/dist/components/skeleton.d.ts +12 -0
  185. package/dist/components/skeleton.js +22 -0
  186. package/dist/components/skeleton.js.map +1 -0
  187. package/dist/components/sortable-list.d.ts +67 -0
  188. package/dist/components/sortable-list.js +206 -0
  189. package/dist/components/sortable-list.js.map +1 -0
  190. package/dist/components/spinner.d.ts +29 -0
  191. package/dist/components/spinner.js +34 -0
  192. package/dist/components/spinner.js.map +1 -0
  193. package/dist/components/status-dot.d.ts +26 -0
  194. package/dist/components/status-dot.js +47 -0
  195. package/dist/components/status-dot.js.map +1 -0
  196. package/dist/components/switch.d.ts +21 -0
  197. package/dist/components/switch.js +21 -0
  198. package/dist/components/switch.js.map +1 -0
  199. package/dist/components/tabs.d.ts +24 -0
  200. package/dist/components/tabs.js +60 -0
  201. package/dist/components/tabs.js.map +1 -0
  202. package/dist/components/textarea.d.ts +19 -0
  203. package/dist/components/textarea.js +47 -0
  204. package/dist/components/textarea.js.map +1 -0
  205. package/dist/components/toast.d.ts +47 -0
  206. package/dist/components/toast.js +106 -0
  207. package/dist/components/toast.js.map +1 -0
  208. package/dist/components/toolbar.d.ts +19 -0
  209. package/dist/components/toolbar.js +45 -0
  210. package/dist/components/toolbar.js.map +1 -0
  211. package/dist/components/tooltip.d.ts +28 -0
  212. package/dist/components/tooltip.js +59 -0
  213. package/dist/components/tooltip.js.map +1 -0
  214. package/dist/core.d.ts +44 -0
  215. package/dist/core.js +44 -0
  216. package/dist/data-table.d.ts +9 -0
  217. package/dist/data-table.js +7 -0
  218. package/dist/form.d.ts +7 -0
  219. package/dist/form.js +7 -0
  220. package/dist/hooks/use-cortena-theme.d.ts +98 -0
  221. package/dist/hooks/use-cortena-theme.js +145 -0
  222. package/dist/hooks/use-cortena-theme.js.map +1 -0
  223. package/dist/index.d.ts +75 -2678
  224. package/dist/index.js +66 -8598
  225. package/dist/lib/cn.d.ts +10 -0
  226. package/dist/lib/cn.js +15 -0
  227. package/dist/lib/cn.js.map +1 -0
  228. package/dist/lib/render.d.ts +23 -0
  229. package/dist/lib/render.js +20 -0
  230. package/dist/lib/render.js.map +1 -0
  231. package/dist/lib/shakeable.js +39 -0
  232. package/dist/lib/shakeable.js.map +1 -0
  233. package/dist/markdown.d.ts +3 -0
  234. package/dist/markdown.js +3 -0
  235. package/dist/sortable-list.d.ts +3 -0
  236. package/dist/sortable-list.js +3 -0
  237. package/package.json +37 -14
  238. package/src/a2ui/catalogue.ts +140 -103
  239. package/src/a2ui/views.tsx +5 -2
  240. package/src/components/alert.tsx +1 -1
  241. package/src/components/badge.tsx +1 -1
  242. package/src/components/button.tsx +1 -1
  243. package/src/components/chart/chart.tsx +72 -25
  244. package/src/components/chart/container.tsx +24 -39
  245. package/src/components/chart/index.tsx +4 -2
  246. package/src/components/chart/nivo-charts.tsx +41 -13
  247. package/src/components/chart/nivo-lazy.tsx +52 -0
  248. package/src/components/chart/recharts-charts.tsx +98 -3
  249. package/src/components/chart/recharts-lazy.tsx +72 -0
  250. package/src/components/chart/recharts-parts.tsx +34 -0
  251. package/src/components/chart/tokens.ts +1 -1
  252. package/src/components/chart/types.ts +14 -0
  253. package/src/components/chip.tsx +1 -1
  254. package/src/components/combobox.tsx +2 -2
  255. package/src/components/data-table/export.ts +18 -2
  256. package/src/components/data-table/features.ts +77 -45
  257. package/src/components/data-table/parts.tsx +15 -0
  258. package/src/components/data-table/use-data-table.ts +7 -2
  259. package/src/components/data-table/use-server-source.ts +17 -4
  260. package/src/components/date-field.tsx +1 -1
  261. package/src/components/error-banner.tsx +1 -1
  262. package/src/components/field.tsx +2 -2
  263. package/src/components/form.tsx +2 -2
  264. package/src/components/input.tsx +1 -1
  265. package/src/components/label.tsx +1 -1
  266. package/src/components/markdown.tsx +5 -4
  267. package/src/components/sheet.tsx +2 -2
  268. package/src/components/sortable-list.tsx +2 -2
  269. package/src/components/textarea.tsx +1 -1
  270. package/src/components/toast.tsx +1 -1
  271. package/src/entries/a2ui.ts +11 -0
  272. package/src/entries/chart.ts +10 -0
  273. package/src/entries/core.ts +91 -0
  274. package/src/entries/data-table.ts +9 -0
  275. package/src/entries/form.ts +24 -0
  276. package/src/entries/markdown.ts +9 -0
  277. package/src/entries/sortable-list.ts +13 -0
  278. package/src/index.ts +32 -98
  279. package/src/lib/shakeable.ts +33 -0
  280. package/dist/index.js.map +0 -1
@@ -0,0 +1,252 @@
1
+ "use client";
2
+ "use client";
3
+ import { cn } from "../lib/cn.js";
4
+ import { A2UIErrorCard } from "./views.js";
5
+ import { defaultCatalogue } from "./catalogue.js";
6
+ import { foldMessages, isDataBinding, readAction, readChildren, readComponent, resolvePointer, resolveValue, setAtPointer } from "./message.js";
7
+ import { jsx, jsxs } from "react/jsx-runtime";
8
+ import * as React from "react";
9
+ //#region src/a2ui/renderer.tsx
10
+ /**
11
+ * The A2UI React renderer.
12
+ *
13
+ * Takes A2UI messages, folds them onto surfaces, walks the component tree and
14
+ * draws each node through the catalogue. Nothing an agent sends reaches the DOM
15
+ * as markup: a node is a catalogue name plus properties that must pass the
16
+ * entry's zod schema, and anything else becomes an inline error card.
17
+ *
18
+ * ## Why this is written rather than adopted
19
+ *
20
+ * `@a2ui/react` 0.11.0 (Google, Apache-2.0, published 2026-09-01) is a real,
21
+ * maintained v0.9 renderer and it does let a host supply a catalogue. It was
22
+ * evaluated for DESIGN-33 and not adopted, for three reasons:
23
+ *
24
+ * 1. **zod major.** `@a2ui/web_core`'s generic binder reads zod 3 internals —
25
+ * `schema._def.typeName`, `_def.shape()`, `_def.innerType` — to decide how to
26
+ * bind each property. cortena-ui's zod peer is `^3.25 || ^4`, and zod 4 has
27
+ * no `_def.typeName` and exposes `shape` as a property, so a catalogue
28
+ * authored with the consumer's zod 4 fails inside the binder. Adopting would
29
+ * pin the whole package's schema layer to zod 3 while `form.tsx` and
30
+ * `@hookform/resolvers` follow the consumer's.
31
+ * 2. **Dialect.** Cortena already speaks A2UI v0.8: core bundles the Lit
32
+ * renderer at `src/canvas-host/a2ui/` and the `canvas` tool pushes
33
+ * `beginRendering` / `surfaceUpdate` / `dataModelUpdate` as JSONL.
34
+ * `@a2ui/react` splits v0_8 and v0_9 into separate entry points with separate
35
+ * catalogues, so neither one reads both. Every payload written for the
36
+ * native nodes would have to be rewritten before it rendered on the web.
37
+ * 3. **Weight and surface.** It brings `@a2ui/web_core` (3.8 MB unpacked),
38
+ * markdown-it, `@preact/signals-core` and date-fns into a package whose build
39
+ * externalises everything and whose markdown already goes through
40
+ * react-markdown with a sanitize schema. And the API this task needs —
41
+ * `resolveDataSource` for server tables, `onAction` for the AG-UI round trip —
42
+ * has no counterpart there, so it would be wrapped either way.
43
+ *
44
+ * What we keep is the part that matters for interop: the **wire format** is
45
+ * A2UI's, the action we emit is shaped like A2UI's client-to-server `action`
46
+ * (`{ name, surfaceId, sourceComponentId, context }`), and the catalogue is a
47
+ * schema-per-component registry. Swapping the engine later is mechanical.
48
+ */
49
+ /** Depth limit; a tree deeper than this is a malformed payload, not a design. */
50
+ const MAX_DEPTH = 32;
51
+ /**
52
+ * A2UIRenderer — draws A2UI messages through cortena-ui.
53
+ *
54
+ * ```tsx
55
+ * <A2UIRenderer
56
+ * message={customEvent.value}
57
+ * catalogue={defaultCatalogue}
58
+ * onAction={(action) => agent.send(action)}
59
+ * resolveDataSource={(id) => sources[id]}
60
+ * />
61
+ * ```
62
+ */
63
+ function A2UIRenderer({ message, catalogue = defaultCatalogue, onAction, resolveDataSource, surfaceId, debounceMs = 300, className }) {
64
+ const fold = React.useMemo(() => foldMessages(message), [message]);
65
+ const [models, setModels] = React.useState(() => seedModels(fold.surfaces));
66
+ const seenFold = React.useRef(fold);
67
+ if (seenFold.current !== fold) {
68
+ seenFold.current = fold;
69
+ setModels(seedModels(fold.surfaces));
70
+ }
71
+ const resolve = React.useCallback((sourceId) => resolveDataSource?.(sourceId), [resolveDataSource]);
72
+ const surfaces = surfaceId ? fold.surfaces.filter((surface) => surface.id === surfaceId) : fold.surfaces;
73
+ const missingSurface = Boolean(surfaceId) && surfaces.length === 0 && fold.surfaces.length > 0;
74
+ return /* @__PURE__ */ jsxs("div", {
75
+ "data-slot": "a2ui-renderer",
76
+ className: cn("flex min-w-0 flex-col gap-3", className),
77
+ children: [
78
+ fold.errors.length > 0 ? /* @__PURE__ */ jsx(A2UIErrorCard, {
79
+ title: "Malformed A2UI payload",
80
+ detail: fold.errors.slice(0, 5).join(" ")
81
+ }) : null,
82
+ missingSurface ? /* @__PURE__ */ jsx(A2UIErrorCard, {
83
+ title: "Unknown surface",
84
+ detail: `No surface "${surfaceId}" in this payload.`
85
+ }) : null,
86
+ surfaces.map((surface) => /* @__PURE__ */ jsx(A2UISurfaceView, {
87
+ surface,
88
+ catalogue,
89
+ model: models[surface.id] ?? surface.dataModel,
90
+ setModel: (updater) => setModels((current) => ({
91
+ ...current,
92
+ [surface.id]: updater(current[surface.id] ?? surface.dataModel)
93
+ })),
94
+ onAction,
95
+ resolveDataSource: resolve,
96
+ debounceMs
97
+ }, surface.id))
98
+ ]
99
+ });
100
+ }
101
+ function seedModels(surfaces) {
102
+ const models = {};
103
+ for (const surface of surfaces) models[surface.id] = surface.dataModel;
104
+ return models;
105
+ }
106
+ function A2UISurfaceView({ surface, catalogue, model, setModel, onAction, resolveDataSource, debounceMs }) {
107
+ const context = {
108
+ surface,
109
+ catalogue,
110
+ model,
111
+ setModel,
112
+ onAction,
113
+ resolveDataSource,
114
+ debounceMs
115
+ };
116
+ if (!surface.root) return /* @__PURE__ */ jsx("div", {
117
+ "data-slot": "a2ui-surface",
118
+ "data-surface-id": surface.id,
119
+ children: /* @__PURE__ */ jsx(A2UIErrorCard, {
120
+ title: "Empty A2UI surface",
121
+ detail: `Surface "${surface.id}" has no root component. Send updateComponents with a component whose id is "root", or name one in createSurface.`
122
+ })
123
+ });
124
+ return /* @__PURE__ */ jsx("div", {
125
+ "data-slot": "a2ui-surface",
126
+ "data-surface-id": surface.id,
127
+ className: "flex min-w-0 flex-col",
128
+ children: /* @__PURE__ */ jsx(A2UINode, {
129
+ context,
130
+ id: surface.root,
131
+ contextPath: "/",
132
+ ancestors: [],
133
+ depth: 0
134
+ })
135
+ });
136
+ }
137
+ function A2UINode({ context, id, contextPath, ancestors, depth }) {
138
+ const spec = context.surface.components.get(id);
139
+ if (!spec) return /* @__PURE__ */ jsx(A2UIErrorCard, {
140
+ title: "Unknown component id",
141
+ detail: `No component "${id}" in this surface.`
142
+ });
143
+ if (ancestors.includes(id)) return /* @__PURE__ */ jsx(A2UIErrorCard, {
144
+ title: "Circular component reference",
145
+ detail: `"${id}" is already an ancestor of itself: ${[...ancestors, id].join(" → ")}.`,
146
+ componentId: id
147
+ });
148
+ if (depth > MAX_DEPTH) return /* @__PURE__ */ jsx(A2UIErrorCard, {
149
+ title: "Component tree too deep",
150
+ detail: `More than ${MAX_DEPTH} levels below the root.`,
151
+ componentId: id
152
+ });
153
+ const declaration = readComponent(spec);
154
+ if (!declaration) return /* @__PURE__ */ jsx(A2UIErrorCard, {
155
+ title: "Component has no type",
156
+ detail: "Expected `component` to be a catalogue name, or an object keyed by one.",
157
+ componentId: id
158
+ });
159
+ const entry = context.catalogue[declaration.name];
160
+ if (!entry) return /* @__PURE__ */ jsx(A2UIErrorCard, {
161
+ title: `Unknown component "${declaration.name}"`,
162
+ detail: `The catalogue has: ${Object.keys(context.catalogue).sort().join(", ")}.`,
163
+ componentId: id
164
+ });
165
+ const raw = declaration.properties;
166
+ const bindings = {};
167
+ const resolved = {};
168
+ for (const [key, value] of Object.entries(raw)) {
169
+ if (key === "children") continue;
170
+ if (isDataBinding(value)) bindings[key] = resolvePointer(value.path, contextPath);
171
+ const next = resolveValue(value, context.model, contextPath);
172
+ resolved[key] = key.startsWith("on") ? readAction(next) : next;
173
+ }
174
+ const parsed = entry.props.safeParse(resolved);
175
+ if (!parsed.success) {
176
+ const issues = parsed.error.issues.slice(0, 4).map((issue) => `${issue.path.join(".") || "(root)"}: ${issue.message}`).join("; ");
177
+ return /* @__PURE__ */ jsx(A2UIErrorCard, {
178
+ title: `Invalid props for ${declaration.name}`,
179
+ detail: issues,
180
+ componentId: id
181
+ });
182
+ }
183
+ const node = {
184
+ surfaceId: context.surface.id,
185
+ componentId: id,
186
+ dataContextPath: contextPath
187
+ };
188
+ const children = entry.children === "many" ? renderChildren(context, spec, raw, contextPath, [...ancestors, id], depth) : [];
189
+ const emit = (action, fallbackName, payload) => {
190
+ context.onAction?.({
191
+ surfaceId: context.surface.id,
192
+ componentId: id,
193
+ name: action?.name ?? fallbackName,
194
+ payload: {
195
+ ...action?.context ?? {},
196
+ ...payload ?? {}
197
+ }
198
+ });
199
+ };
200
+ const writeBack = (property, value) => {
201
+ const pointer = bindings[property];
202
+ if (!pointer) return;
203
+ context.setModel((model) => setAtPointer(model, pointer, value));
204
+ };
205
+ const View = entry.view;
206
+ return /* @__PURE__ */ jsx(View, {
207
+ props: parsed.data,
208
+ node,
209
+ dataModel: context.model,
210
+ emit,
211
+ writeBack,
212
+ resolveDataSource: context.resolveDataSource,
213
+ debounceMs: context.debounceMs,
214
+ children
215
+ });
216
+ }
217
+ /**
218
+ * Render a component's children.
219
+ *
220
+ * An explicit list renders each id once. A template renders the referenced
221
+ * component once per item in a bound array, each with its own data context, so
222
+ * an agent describes a row of a table or a list item once instead of repeating
223
+ * it per item.
224
+ */
225
+ function renderChildren(context, spec, properties, contextPath, ancestors, depth) {
226
+ const children = readChildren(spec, properties);
227
+ if (children.kind === "none") return [];
228
+ if (children.kind === "list") return children.ids.map((childId) => /* @__PURE__ */ jsx(A2UINode, {
229
+ context,
230
+ id: childId,
231
+ contextPath,
232
+ ancestors,
233
+ depth: depth + 1
234
+ }, childId));
235
+ const pointer = resolvePointer(children.path, contextPath);
236
+ const items = resolveValue({ path: children.path }, context.model, contextPath);
237
+ if (!Array.isArray(items)) return [/* @__PURE__ */ jsx(A2UIErrorCard, {
238
+ title: "Template list is not an array",
239
+ detail: `"${pointer}" does not resolve to an array in the data model.`
240
+ }, "template-error")];
241
+ return items.map((_item, index) => /* @__PURE__ */ jsx(A2UINode, {
242
+ context,
243
+ id: children.componentId,
244
+ contextPath: `${pointer === "/" ? "" : pointer}/${index}`,
245
+ ancestors,
246
+ depth: depth + 1
247
+ }, `${children.componentId}:${index}`));
248
+ }
249
+ //#endregion
250
+ export { A2UIRenderer };
251
+
252
+ //# sourceMappingURL=renderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renderer.js","names":[],"sources":["../../src/a2ui/renderer.tsx"],"sourcesContent":["\"use client\";\n\n/**\n * The A2UI React renderer.\n *\n * Takes A2UI messages, folds them onto surfaces, walks the component tree and\n * draws each node through the catalogue. Nothing an agent sends reaches the DOM\n * as markup: a node is a catalogue name plus properties that must pass the\n * entry's zod schema, and anything else becomes an inline error card.\n *\n * ## Why this is written rather than adopted\n *\n * `@a2ui/react` 0.11.0 (Google, Apache-2.0, published 2026-09-01) is a real,\n * maintained v0.9 renderer and it does let a host supply a catalogue. It was\n * evaluated for DESIGN-33 and not adopted, for three reasons:\n *\n * 1. **zod major.** `@a2ui/web_core`'s generic binder reads zod 3 internals —\n * `schema._def.typeName`, `_def.shape()`, `_def.innerType` — to decide how to\n * bind each property. cortena-ui's zod peer is `^3.25 || ^4`, and zod 4 has\n * no `_def.typeName` and exposes `shape` as a property, so a catalogue\n * authored with the consumer's zod 4 fails inside the binder. Adopting would\n * pin the whole package's schema layer to zod 3 while `form.tsx` and\n * `@hookform/resolvers` follow the consumer's.\n * 2. **Dialect.** Cortena already speaks A2UI v0.8: core bundles the Lit\n * renderer at `src/canvas-host/a2ui/` and the `canvas` tool pushes\n * `beginRendering` / `surfaceUpdate` / `dataModelUpdate` as JSONL.\n * `@a2ui/react` splits v0_8 and v0_9 into separate entry points with separate\n * catalogues, so neither one reads both. Every payload written for the\n * native nodes would have to be rewritten before it rendered on the web.\n * 3. **Weight and surface.** It brings `@a2ui/web_core` (3.8 MB unpacked),\n * markdown-it, `@preact/signals-core` and date-fns into a package whose build\n * externalises everything and whose markdown already goes through\n * react-markdown with a sanitize schema. And the API this task needs —\n * `resolveDataSource` for server tables, `onAction` for the AG-UI round trip —\n * has no counterpart there, so it would be wrapped either way.\n *\n * What we keep is the part that matters for interop: the **wire format** is\n * A2UI's, the action we emit is shaped like A2UI's client-to-server `action`\n * (`{ name, surfaceId, sourceComponentId, context }`), and the catalogue is a\n * schema-per-component registry. Swapping the engine later is mechanical.\n */\n\nimport * as React from \"react\";\nimport type { DataSource } from \"@/components/data-table\";\nimport { cn } from \"@/lib/cn\";\nimport {\n A2UI_DEFAULT_SURFACE_ID,\n foldMessages,\n isDataBinding,\n readAction,\n readChildren,\n readComponent,\n resolvePointer,\n resolveValue,\n setAtPointer,\n type A2UIAction,\n type A2UIComponentSpec,\n type A2UIMessageInput,\n type A2UISurface,\n} from \"./message\";\nimport { defaultCatalogue, type A2UICatalogue } from \"./catalogue\";\nimport { A2UIErrorCard, type A2UINodeInfo, type A2UIResolvedAction, type A2UIRow } from \"./views\";\n\nexport interface A2UIRendererProps {\n /**\n * The payload. One message, the list an AG-UI `CUSTOM` event carries, or the\n * JSONL text `canvas.a2ui.pushJSONL` sends. Later messages fold onto earlier\n * ones, so a push stream can be accumulated by the host and handed here whole.\n */\n message: A2UIMessageInput;\n /** The component vocabulary. Defaults to the whole cortena-ui catalogue. */\n catalogue?: A2UICatalogue;\n /** Receives every user event, shaped like A2UI's client-to-server action. */\n onAction?: (action: A2UIAction) => void;\n /**\n * Resolves a `{ kind: \"server\", sourceId }` table handle into a real data\n * source. Without it, a server table renders an error card rather than an\n * empty one, because a silently empty table reads as \"no results\".\n */\n resolveDataSource?: (sourceId: string) => DataSource<A2UIRow> | undefined;\n /** Render only this surface. Default: every surface, in arrival order. */\n surfaceId?: string;\n /** Debounce before a continuous input becomes an action. @default 300 */\n debounceMs?: number;\n className?: string;\n}\n\n/** Depth limit; a tree deeper than this is a malformed payload, not a design. */\nconst MAX_DEPTH = 32;\n\ninterface NodeContext {\n surface: A2UISurface;\n catalogue: A2UICatalogue;\n model: Record<string, unknown>;\n setModel: (updater: (model: Record<string, unknown>) => Record<string, unknown>) => void;\n onAction: ((action: A2UIAction) => void) | undefined;\n resolveDataSource: (sourceId: string) => DataSource<A2UIRow> | undefined;\n debounceMs: number;\n}\n\n/**\n * A2UIRenderer — draws A2UI messages through cortena-ui.\n *\n * ```tsx\n * <A2UIRenderer\n * message={customEvent.value}\n * catalogue={defaultCatalogue}\n * onAction={(action) => agent.send(action)}\n * resolveDataSource={(id) => sources[id]}\n * />\n * ```\n */\nexport function A2UIRenderer({\n message,\n catalogue = defaultCatalogue,\n onAction,\n resolveDataSource,\n surfaceId,\n debounceMs = 300,\n className,\n}: A2UIRendererProps) {\n const fold = React.useMemo(() => foldMessages(message), [message]);\n\n // Local data model per surface, seeded from the folded one. Inputs write here\n // so a bound value updates as the user types; a new payload replaces it,\n // because the agent is then the authority on what the surface shows.\n const [models, setModels] = React.useState<Record<string, Record<string, unknown>>>(() =>\n seedModels(fold.surfaces),\n );\n const seenFold = React.useRef(fold);\n if (seenFold.current !== fold) {\n seenFold.current = fold;\n setModels(seedModels(fold.surfaces));\n }\n\n const resolve = React.useCallback(\n (sourceId: string) => resolveDataSource?.(sourceId),\n [resolveDataSource],\n );\n\n const surfaces = surfaceId\n ? fold.surfaces.filter((surface) => surface.id === surfaceId)\n : fold.surfaces;\n\n const missingSurface = Boolean(surfaceId) && surfaces.length === 0 && fold.surfaces.length > 0;\n\n return (\n <div data-slot=\"a2ui-renderer\" className={cn(\"flex min-w-0 flex-col gap-3\", className)}>\n {fold.errors.length > 0 ? (\n <A2UIErrorCard\n title=\"Malformed A2UI payload\"\n detail={fold.errors.slice(0, 5).join(\" \")}\n />\n ) : null}\n {missingSurface ? (\n <A2UIErrorCard\n title=\"Unknown surface\"\n detail={`No surface \"${surfaceId}\" in this payload.`}\n />\n ) : null}\n {surfaces.map((surface) => (\n <A2UISurfaceView\n key={surface.id}\n surface={surface}\n catalogue={catalogue}\n model={models[surface.id] ?? surface.dataModel}\n setModel={(updater) =>\n setModels((current) => ({\n ...current,\n [surface.id]: updater(current[surface.id] ?? surface.dataModel),\n }))\n }\n onAction={onAction}\n resolveDataSource={resolve}\n debounceMs={debounceMs}\n />\n ))}\n </div>\n );\n}\n\nfunction seedModels(surfaces: readonly A2UISurface[]): Record<string, Record<string, unknown>> {\n const models: Record<string, Record<string, unknown>> = {};\n for (const surface of surfaces) {\n models[surface.id] = surface.dataModel;\n }\n return models;\n}\n\nfunction A2UISurfaceView({\n surface,\n catalogue,\n model,\n setModel,\n onAction,\n resolveDataSource,\n debounceMs,\n}: {\n surface: A2UISurface;\n catalogue: A2UICatalogue;\n model: Record<string, unknown>;\n setModel: (updater: (model: Record<string, unknown>) => Record<string, unknown>) => void;\n onAction: ((action: A2UIAction) => void) | undefined;\n resolveDataSource: (sourceId: string) => DataSource<A2UIRow> | undefined;\n debounceMs: number;\n}) {\n const context: NodeContext = {\n surface,\n catalogue,\n model,\n setModel,\n onAction,\n resolveDataSource,\n debounceMs,\n };\n\n if (!surface.root) {\n return (\n <div data-slot=\"a2ui-surface\" data-surface-id={surface.id}>\n <A2UIErrorCard\n title=\"Empty A2UI surface\"\n detail={`Surface \"${surface.id}\" has no root component. Send updateComponents with a component whose id is \"root\", or name one in createSurface.`}\n />\n </div>\n );\n }\n\n return (\n <div data-slot=\"a2ui-surface\" data-surface-id={surface.id} className=\"flex min-w-0 flex-col\">\n <A2UINode context={context} id={surface.root} contextPath=\"/\" ancestors={[]} depth={0} />\n </div>\n );\n}\n\nfunction A2UINode({\n context,\n id,\n contextPath,\n ancestors,\n depth,\n}: {\n context: NodeContext;\n id: string;\n contextPath: string;\n ancestors: readonly string[];\n depth: number;\n}) {\n const spec = context.surface.components.get(id);\n\n if (!spec) {\n return <A2UIErrorCard title=\"Unknown component id\" detail={`No component \"${id}\" in this surface.`} />;\n }\n if (ancestors.includes(id)) {\n return (\n <A2UIErrorCard\n title=\"Circular component reference\"\n detail={`\"${id}\" is already an ancestor of itself: ${[...ancestors, id].join(\" → \")}.`}\n componentId={id}\n />\n );\n }\n if (depth > MAX_DEPTH) {\n return (\n <A2UIErrorCard\n title=\"Component tree too deep\"\n detail={`More than ${MAX_DEPTH} levels below the root.`}\n componentId={id}\n />\n );\n }\n\n const declaration = readComponent(spec);\n if (!declaration) {\n return (\n <A2UIErrorCard\n title=\"Component has no type\"\n detail=\"Expected `component` to be a catalogue name, or an object keyed by one.\"\n componentId={id}\n />\n );\n }\n\n const entry = context.catalogue[declaration.name];\n if (!entry) {\n return (\n <A2UIErrorCard\n title={`Unknown component \"${declaration.name}\"`}\n detail={`The catalogue has: ${Object.keys(context.catalogue).sort().join(\", \")}.`}\n componentId={id}\n />\n );\n }\n\n // Resolve bindings first, then normalise actions, then validate. A view\n // therefore only ever sees values that passed the entry's schema.\n const raw = declaration.properties;\n const bindings: Record<string, string> = {};\n const resolved: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(raw)) {\n if (key === \"children\") {\n continue;\n }\n if (isDataBinding(value)) {\n bindings[key] = resolvePointer(value.path, contextPath);\n }\n const next = resolveValue(value, context.model, contextPath);\n resolved[key] = key.startsWith(\"on\") ? readAction(next) : next;\n }\n\n const parsed = entry.props.safeParse(resolved);\n if (!parsed.success) {\n const issues = parsed.error.issues\n .slice(0, 4)\n .map((issue) => `${issue.path.join(\".\") || \"(root)\"}: ${issue.message}`)\n .join(\"; \");\n return (\n <A2UIErrorCard\n title={`Invalid props for ${declaration.name}`}\n detail={issues}\n componentId={id}\n />\n );\n }\n\n const node: A2UINodeInfo = {\n surfaceId: context.surface.id,\n componentId: id,\n dataContextPath: contextPath,\n };\n\n const children =\n entry.children === \"many\"\n ? renderChildren(context, spec, raw, contextPath, [...ancestors, id], depth)\n : [];\n\n const emit = (\n action: A2UIResolvedAction | undefined,\n fallbackName: string,\n payload?: Record<string, unknown>,\n ) => {\n context.onAction?.({\n surfaceId: context.surface.id,\n componentId: id,\n name: action?.name ?? fallbackName,\n payload: { ...(action?.context ?? {}), ...(payload ?? {}) },\n });\n };\n\n const writeBack = (property: string, value: unknown) => {\n const pointer = bindings[property];\n if (!pointer) {\n return;\n }\n context.setModel((model) => setAtPointer(model, pointer, value));\n };\n\n const View = entry.view as React.FC<{\n props: unknown;\n node: A2UINodeInfo;\n children: React.ReactNode[];\n dataModel: Record<string, unknown>;\n emit: typeof emit;\n writeBack: typeof writeBack;\n resolveDataSource: (sourceId: string) => DataSource<A2UIRow> | undefined;\n debounceMs: number;\n }>;\n\n return (\n <View\n props={parsed.data}\n node={node}\n dataModel={context.model}\n emit={emit}\n writeBack={writeBack}\n resolveDataSource={context.resolveDataSource}\n debounceMs={context.debounceMs}\n >\n {children}\n </View>\n );\n}\n\n/**\n * Render a component's children.\n *\n * An explicit list renders each id once. A template renders the referenced\n * component once per item in a bound array, each with its own data context, so\n * an agent describes a row of a table or a list item once instead of repeating\n * it per item.\n */\nfunction renderChildren(\n context: NodeContext,\n spec: A2UIComponentSpec,\n properties: Record<string, unknown>,\n contextPath: string,\n ancestors: readonly string[],\n depth: number,\n): React.ReactNode[] {\n const children = readChildren(spec, properties);\n if (children.kind === \"none\") {\n return [];\n }\n if (children.kind === \"list\") {\n return children.ids.map((childId) => (\n <A2UINode\n key={childId}\n context={context}\n id={childId}\n contextPath={contextPath}\n ancestors={ancestors}\n depth={depth + 1}\n />\n ));\n }\n const pointer = resolvePointer(children.path, contextPath);\n const items = resolveValue({ path: children.path }, context.model, contextPath);\n if (!Array.isArray(items)) {\n return [\n <A2UIErrorCard\n key=\"template-error\"\n title=\"Template list is not an array\"\n detail={`\"${pointer}\" does not resolve to an array in the data model.`}\n />,\n ];\n }\n return items.map((_item, index) => (\n <A2UINode\n key={`${children.componentId}:${index}`}\n context={context}\n id={children.componentId}\n contextPath={`${pointer === \"/\" ? \"\" : pointer}/${index}`}\n ancestors={ancestors}\n depth={depth + 1}\n />\n ));\n}\n\nexport { A2UI_DEFAULT_SURFACE_ID };\n"],"mappings":"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"}
@@ -0,0 +1,80 @@
1
+ "use client";
2
+ import { A2UIAction } from "./message.js";
3
+ import "../components/chart/types.js";
4
+ import { DataSource } from "../components/data-table/types.js";
5
+ import "../components/data-table/index.js";
6
+ import * as React from "react";
7
+ //#region src/a2ui/views.d.ts
8
+ /** A row in an agent-drawn table. Every value is opaque until a column reads it. */
9
+ export type A2UIRow = Record<string, unknown>;
10
+ /** Where a node sits, carried into every action the view emits. */
11
+ export interface A2UINodeInfo {
12
+ surfaceId: string;
13
+ componentId: string;
14
+ /** JSON pointer this node's relative bindings resolve against. */
15
+ dataContextPath: string;
16
+ }
17
+ /** A normalised action attached to an interactive property. */
18
+ export interface A2UIResolvedAction {
19
+ name: string;
20
+ context?: Record<string, unknown>;
21
+ }
22
+ /** What every view receives. */
23
+ export interface A2UIViewProps<P> {
24
+ props: P;
25
+ node: A2UINodeInfo;
26
+ /** Already-rendered child nodes, in the order the component listed them. */
27
+ children: React.ReactNode[];
28
+ /** The surface data model, for actions that report the whole form. */
29
+ dataModel: Record<string, unknown>;
30
+ /**
31
+ * Send an action. `action` is what the agent attached to the property; when
32
+ * it is absent the event still fires under `fallbackName` so a host can
33
+ * observe interactions the agent did not ask for.
34
+ */
35
+ emit: (action: A2UIResolvedAction | undefined, fallbackName: string, payload?: Record<string, unknown>) => void;
36
+ /** Write a value back to the data model where this prop was bound. No-op for a literal. */
37
+ writeBack: (property: string, value: unknown) => void;
38
+ /** Resolve a `{ kind: "server", sourceId }` handle into a real data source. */
39
+ resolveDataSource: (sourceId: string) => DataSource<A2UIRow> | undefined;
40
+ /** Debounce applied to continuous inputs before they become actions. */
41
+ debounceMs: number;
42
+ }
43
+ export type A2UIView<P> = React.FC<A2UIViewProps<P>>;
44
+ export interface A2UIColumn {
45
+ id: string;
46
+ label?: string;
47
+ align?: "start" | "center" | "end";
48
+ filter?: "faceted" | "text";
49
+ width?: number;
50
+ }
51
+ /**
52
+ * Where a table's rows come from.
53
+ *
54
+ * `client` carries the rows inline, which suits a short result an agent
55
+ * already has. `server` carries a handle instead: the agent obtains a
56
+ * `sourceId` from a tool and the host resolves it through
57
+ * `resolveDataSource`, so search, sort and paging run on the backend and the
58
+ * agent never has to put ten thousand rows in a message.
59
+ */
60
+ export type A2UITableSource = {
61
+ kind: "client";
62
+ rows: A2UIRow[];
63
+ } | {
64
+ kind: "server";
65
+ sourceId: string;
66
+ };
67
+ /**
68
+ * What the renderer draws instead of a component it cannot draw.
69
+ *
70
+ * Never raw markup and never the offending payload as HTML: the detail is set
71
+ * as text, so a malformed message cannot inject anything. This is the
72
+ * "fallback: an error card on malformed payloads" of `05-agent-ui.md`.
73
+ */
74
+ export declare function A2UIErrorCard({ title, detail, componentId }: {
75
+ title: string;
76
+ detail?: string;
77
+ componentId?: string;
78
+ }): React.JSX.Element;
79
+ //#endregion
80
+ //# sourceMappingURL=views.d.ts.map