@maxhealth.tech/prefab 0.3.9 → 0.3.11

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 (95) hide show
  1. package/CHANGELOG.md +723 -671
  2. package/README.md +76 -10
  3. package/dist/a2ui/browser.d.ts +46 -0
  4. package/dist/a2ui/browser.d.ts.map +1 -0
  5. package/dist/a2ui/browser.js +58 -0
  6. package/dist/a2ui/browser.js.map +1 -0
  7. package/dist/a2ui/catalog.d.ts +72 -0
  8. package/dist/a2ui/catalog.d.ts.map +1 -0
  9. package/dist/a2ui/catalog.js +521 -0
  10. package/dist/a2ui/catalog.js.map +1 -0
  11. package/dist/a2ui/control.d.ts +20 -0
  12. package/dist/a2ui/control.d.ts.map +1 -0
  13. package/dist/a2ui/control.js +107 -0
  14. package/dist/a2ui/control.js.map +1 -0
  15. package/dist/a2ui/emit.d.ts +59 -0
  16. package/dist/a2ui/emit.d.ts.map +1 -0
  17. package/dist/a2ui/emit.js +373 -0
  18. package/dist/a2ui/emit.js.map +1 -0
  19. package/dist/a2ui/expr.d.ts +91 -0
  20. package/dist/a2ui/expr.d.ts.map +1 -0
  21. package/dist/a2ui/expr.js +201 -0
  22. package/dist/a2ui/expr.js.map +1 -0
  23. package/dist/a2ui/icons.d.ts +30 -0
  24. package/dist/a2ui/icons.d.ts.map +1 -0
  25. package/dist/a2ui/icons.js +87 -0
  26. package/dist/a2ui/icons.js.map +1 -0
  27. package/dist/a2ui/index.d.ts +29 -0
  28. package/dist/a2ui/index.d.ts.map +1 -0
  29. package/dist/a2ui/index.js +24 -0
  30. package/dist/a2ui/index.js.map +1 -0
  31. package/dist/a2ui/pipes.d.ts +49 -0
  32. package/dist/a2ui/pipes.d.ts.map +1 -0
  33. package/dist/a2ui/pipes.js +106 -0
  34. package/dist/a2ui/pipes.js.map +1 -0
  35. package/dist/a2ui/table.d.ts +31 -0
  36. package/dist/a2ui/table.d.ts.map +1 -0
  37. package/dist/a2ui/table.js +155 -0
  38. package/dist/a2ui/table.js.map +1 -0
  39. package/dist/a2ui/types.d.ts +174 -0
  40. package/dist/a2ui/types.d.ts.map +1 -0
  41. package/dist/a2ui/types.js +35 -0
  42. package/dist/a2ui/types.js.map +1 -0
  43. package/dist/a2ui.min.js +1 -0
  44. package/dist/app.d.ts +17 -0
  45. package/dist/app.d.ts.map +1 -1
  46. package/dist/app.js +19 -0
  47. package/dist/app.js.map +1 -1
  48. package/dist/auto/form.d.ts +25 -0
  49. package/dist/auto/form.d.ts.map +1 -1
  50. package/dist/auto/form.js +21 -8
  51. package/dist/auto/form.js.map +1 -1
  52. package/dist/core/version.d.ts +1 -1
  53. package/dist/core/version.d.ts.map +1 -1
  54. package/dist/core/version.js +1 -1
  55. package/dist/core/version.js.map +1 -1
  56. package/dist/index.d.ts +9 -2
  57. package/dist/index.d.ts.map +1 -1
  58. package/dist/index.js +4 -0
  59. package/dist/index.js.map +1 -1
  60. package/dist/mcp/a2ui.d.ts +91 -0
  61. package/dist/mcp/a2ui.d.ts.map +1 -0
  62. package/dist/mcp/a2ui.js +134 -0
  63. package/dist/mcp/a2ui.js.map +1 -0
  64. package/dist/mcp/display.d.ts +28 -6
  65. package/dist/mcp/display.d.ts.map +1 -1
  66. package/dist/mcp/display.js +10 -9
  67. package/dist/mcp/display.js.map +1 -1
  68. package/dist/mcp/index.d.ts +7 -2
  69. package/dist/mcp/index.d.ts.map +1 -1
  70. package/dist/mcp/index.js +3 -1
  71. package/dist/mcp/index.js.map +1 -1
  72. package/dist/mcp/input-required.d.ts +79 -0
  73. package/dist/mcp/input-required.d.ts.map +1 -0
  74. package/dist/mcp/input-required.js +231 -0
  75. package/dist/mcp/input-required.js.map +1 -0
  76. package/dist/mcp/resource.d.ts +10 -0
  77. package/dist/mcp/resource.d.ts.map +1 -1
  78. package/dist/mcp/resource.js +12 -4
  79. package/dist/mcp/resource.js.map +1 -1
  80. package/dist/mcp/result.d.ts +7 -5
  81. package/dist/mcp/result.d.ts.map +1 -1
  82. package/dist/mcp/result.js +5 -3
  83. package/dist/mcp/result.js.map +1 -1
  84. package/dist/mcp/types.d.ts +117 -0
  85. package/dist/mcp/types.d.ts.map +1 -1
  86. package/dist/renderer/components/index.d.ts.map +1 -1
  87. package/dist/renderer/components/index.js +6 -0
  88. package/dist/renderer/components/index.js.map +1 -1
  89. package/dist/renderer/engine.d.ts +4 -0
  90. package/dist/renderer/engine.d.ts.map +1 -1
  91. package/dist/renderer/engine.js +24 -0
  92. package/dist/renderer/engine.js.map +1 -1
  93. package/dist/renderer.auto.min.js +13 -13
  94. package/dist/renderer.min.js +13 -13
  95. package/package.json +14 -3
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expr.d.ts","sourceRoot":"","sources":["../../src/a2ui/expr.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAoB,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAgBxG;;;;;GAKG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AAK9C;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,6DAA6D;AAC7D,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAExD;AA0CD,6EAA6E;AAC7E,MAAM,MAAM,aAAa;AACvB,wCAAwC;AACtC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE;AACpC,8DAA8D;GAC5D;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,eAAe,CAAA;CAAE;AAC7C;;;;GAIG;GACD;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,gBAAgB,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE;AAC5D,+DAA+D;GAC7D;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,gBAAgB,CAAA;CAAE;AAC5C,iFAAiF;GAC/E;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAA;AA8D9C;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,GAAE,SAAc,GAAG,aAAa,CAgC7E;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,GAAE,SAAc,GAAG,iBAAiB,GAAG,SAAS,CAU7G"}
@@ -0,0 +1,201 @@
1
+ /**
2
+ * `{{ }}` template → A2UI data binding.
3
+ *
4
+ * `$prefab` interpolates arbitrary expressions client-side. A2UI binds values
5
+ * through JSON Pointers and, for text that mixes literals with values, through
6
+ * the `formatString` catalog function. Between them those cover more than a
7
+ * plain-path conversion would suggest:
8
+ *
9
+ * - `{{ user.name }}` → `{ path: '/user/name' }`
10
+ * - `Hi {{ name }}!` → `{ call: 'formatString', args: { value: 'Hi ${/name}!' } }`
11
+ * - `{{ p | currency:'EUR' }}` → `{ call: 'formatCurrency', args: { … } }`
12
+ * - `{{ count + 1 }}` → nothing; A2UI has no expression language
13
+ *
14
+ * What does not survive is arithmetic, conditionals, and the pipes that
15
+ * transform data rather than format it (see `./pipes.ts`). Those are reported as
16
+ * `expression` diagnostics rather than emitted as a binding that would render an
17
+ * empty string in someone's renderer.
18
+ *
19
+ * ## Scopes
20
+ *
21
+ * A binding is resolved against a {@link BindScope}, which is how names local to
22
+ * a region become pointers. Inside a list template A2UI resolves relative paths
23
+ * against the current item, so prefab's `$item` maps to the empty prefix; inside
24
+ * an inlined definition, a `Use`'s overrides map to wherever the emitter seeded
25
+ * them. Without this, a name that means something local would silently bind to
26
+ * the root of the data model and read whatever happened to be there.
27
+ */
28
+ import { parsePipe, pipeCall } from './pipes.js';
29
+ /** Matches a string that is exactly one `{{ … }}` template and nothing else. */
30
+ const SOLE_TEMPLATE = /^\s*\{\{\s*(.+?)\s*\}\}\s*$/s;
31
+ /** Matches every `{{ … }}` occurrence, for interpolating mixed text. */
32
+ const EVERY_TEMPLATE = /\{\{\s*(.+?)\s*\}\}/g;
33
+ /**
34
+ * A plain member path: `user.name`, `items.0.label`, `count`, `$item.title`.
35
+ *
36
+ * Deliberately narrow. Anything outside this shape (operators, pipes, calls,
37
+ * ternaries, string literals) has no A2UI equivalent.
38
+ */
39
+ const PLAIN_PATH = /^\$?[A-Za-z_][\w$]*(?:\.(?:[A-Za-z_$][\w$]*|\d+))*$/;
40
+ /** prefab's loop index. A2UI exposes the same thing as a system function. */
41
+ const LOOP_INDEX = '$index';
42
+ /**
43
+ * Escape one JSON Pointer reference token (RFC 6901 §3).
44
+ *
45
+ * `~` must be escaped before `/`, otherwise the `~1` produced for a slash gets
46
+ * re-escaped into `~01` on the second pass.
47
+ */
48
+ export function escapePointerToken(token) {
49
+ return token.replace(/~/g, '~0').replace(/\//g, '~1');
50
+ }
51
+ /** Build a JSON Pointer from already-split path segments. */
52
+ export function toJsonPointer(segments) {
53
+ return '/' + segments.map(escapePointerToken).join('/');
54
+ }
55
+ /**
56
+ * prefab state expressions address state keys directly (`count`), but actions
57
+ * and docs also spell the same key as `state.count`. Both mean the root of the
58
+ * data model, so the prefix is stripped before the pointer is built.
59
+ */
60
+ function stripStatePrefix(path) {
61
+ return path.startsWith('state.') ? path.slice('state.'.length) : path;
62
+ }
63
+ /**
64
+ * Resolve a member path to a JSON Pointer under `scope`.
65
+ *
66
+ * A leading segment named in the scope is replaced by its prefix; everything
67
+ * else resolves from the data-model root.
68
+ */
69
+ function pathToPointer(expr, scope) {
70
+ if (!PLAIN_PATH.test(expr))
71
+ return undefined;
72
+ const segments = stripStatePrefix(expr).split('.');
73
+ const head = segments[0];
74
+ // `hasOwn` rather than a truthiness check: '' is a meaningful prefix, meaning
75
+ // "relative to the current template item".
76
+ const prefix = Object.hasOwn(scope, head) ? scope[head] : undefined;
77
+ if (prefix === undefined) {
78
+ // A `$`-prefixed name is a runtime binding prefab supplies ($event, $error,
79
+ // $result). Outside a scope that defines it, there is nothing to point at.
80
+ if (head.startsWith('$'))
81
+ return undefined;
82
+ return toJsonPointer(segments);
83
+ }
84
+ const rest = segments.slice(1);
85
+ if (prefix === '') {
86
+ // Relative to the current template item. `{{ $item }}` alone has no field to
87
+ // address, so it cannot become a pointer.
88
+ return rest.length === 0 ? undefined : rest.map(escapePointerToken).join('/');
89
+ }
90
+ return rest.length === 0 ? prefix : `${prefix}/${rest.map(escapePointerToken).join('/')}`;
91
+ }
92
+ /**
93
+ * Escape a literal segment for a `formatString` template.
94
+ *
95
+ * `${` is the interpolation opener, so a literal one has to be escaped or the
96
+ * renderer reads the surrounding text as an expression.
97
+ */
98
+ function escapeFormatLiteral(text) {
99
+ return text.replace(/\$\{/g, '\\${');
100
+ }
101
+ /**
102
+ * Convert mixed literal and template text into a `formatString` call.
103
+ *
104
+ * @returns `undefined` when any embedded expression is richer than a path, in
105
+ * which case the whole string is unbindable rather than partly interpolated.
106
+ */
107
+ function toFormatString(value, scope) {
108
+ let failed;
109
+ let interpolated = '';
110
+ let cursor = 0;
111
+ for (const match of value.matchAll(EVERY_TEMPLATE)) {
112
+ const expr = match[1].trim();
113
+ const pointer = pathToPointer(expr, scope);
114
+ if (pointer == null) {
115
+ failed = expr;
116
+ break;
117
+ }
118
+ interpolated += escapeFormatLiteral(value.slice(cursor, match.index));
119
+ interpolated += `\${${pointer}}`;
120
+ cursor = match.index + match[0].length;
121
+ }
122
+ if (failed != null)
123
+ return undefined;
124
+ interpolated += escapeFormatLiteral(value.slice(cursor));
125
+ return { call: 'formatString', args: { value: interpolated } };
126
+ }
127
+ /**
128
+ * Resolve a piped expression to a catalog-function call.
129
+ *
130
+ * The base must itself be a plain path or a literal, since A2UI function
131
+ * arguments take a value rather than an expression to evaluate.
132
+ */
133
+ function toPipeCall(expr, scope) {
134
+ const pipe = parsePipe(expr);
135
+ if (pipe == null)
136
+ return undefined;
137
+ const pointer = pathToPointer(pipe.base, scope);
138
+ const value = pointer != null
139
+ ? { path: pointer }
140
+ : /^-?\d+(\.\d+)?$/.test(pipe.base) ? Number(pipe.base) : undefined;
141
+ if (value === undefined)
142
+ return undefined;
143
+ const mapped = pipeCall(pipe, value);
144
+ if (mapped == null)
145
+ return undefined;
146
+ return { kind: 'format', value: mapped.call, ...(mapped.note != null && { note: mapped.note }) };
147
+ }
148
+ /**
149
+ * Convert a prefab string value into an A2UI dynamic value.
150
+ *
151
+ * A whole-string template over a plain path becomes a binding, one over a
152
+ * formatting pipe becomes a catalog-function call, mixed text becomes a
153
+ * `formatString` call, a string with no template passes through, and anything
154
+ * else is unbindable.
155
+ */
156
+ export function toBinding(value, scope = {}) {
157
+ const sole = SOLE_TEMPLATE.exec(value);
158
+ // The capture is lazy but still spans `}} … {{`, so `{{ a }} of {{ b }}`
159
+ // matches as one template whose body is `a }} of {{ b`. Rejecting a capture
160
+ // that contains delimiters sends those strings down the interpolation path,
161
+ // which is where they belong.
162
+ const isSole = sole != null && !sole[1].includes('{{') && !sole[1].includes('}}');
163
+ if (isSole) {
164
+ const expr = sole[1].trim();
165
+ if (expr === LOOP_INDEX && LOOP_INDEX in scope) {
166
+ return { kind: 'index', value: { call: '@index' } };
167
+ }
168
+ const pointer = pathToPointer(expr, scope);
169
+ if (pointer != null)
170
+ return { kind: 'binding', value: { path: pointer } };
171
+ // A pipe is not part of A2UI's expression language, but the common
172
+ // formatting ones exist in its catalog as functions.
173
+ const piped = toPipeCall(expr, scope);
174
+ if (piped != null)
175
+ return piped;
176
+ return { kind: 'unbindable', expression: expr };
177
+ }
178
+ if (!value.includes('{{'))
179
+ return { kind: 'literal', value };
180
+ const format = toFormatString(value, scope);
181
+ if (format != null)
182
+ return { kind: 'format', value: format };
183
+ return { kind: 'unbindable', expression: value };
184
+ }
185
+ /**
186
+ * Resolve a value to an `A2uiDynamicString`, or `undefined` when it cannot be
187
+ * expressed. Callers pair this with a diagnostic when it returns `undefined`.
188
+ */
189
+ export function dynamicString(value, scope = {}) {
190
+ if (value == null)
191
+ return undefined;
192
+ const r = toBinding(value, scope);
193
+ switch (r.kind) {
194
+ case 'literal': return r.value;
195
+ case 'binding': return r.value;
196
+ case 'format': return r.value;
197
+ case 'index': return r.value;
198
+ default: return undefined;
199
+ }
200
+ }
201
+ //# sourceMappingURL=expr.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expr.js","sourceRoot":"","sources":["../../src/a2ui/expr.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * prefab icon name → A2UI Basic catalog icon.
3
+ *
4
+ * The one place where the two catalogs disagree on *values* rather than on
5
+ * component shape. prefab's `Icon(name)` takes any string, because its renderer
6
+ * resolves Lucide names at runtime and new icons cost nothing. A2UI's
7
+ * `Icon.name` is a closed enum of 59 names, so an unrecognised value does not
8
+ * render as a fallback glyph — it makes the whole component fail validation.
9
+ *
10
+ * Passing the name through unchecked therefore emits an invalid surface for
11
+ * every icon outside those 59, which is most of them. Instead the name is
12
+ * normalised, matched against the enum, and dropped with a diagnostic when
13
+ * nothing fits, so an unmappable icon costs a glyph rather than the payload.
14
+ */
15
+ /**
16
+ * The A2UI Basic catalog's `Icon.name` enum, v1.0.
17
+ *
18
+ * Duplicated as a literal because prefab ships zero runtime dependencies and
19
+ * cannot read the catalog JSON at emit time. `test/a2ui-icons.test.ts` asserts
20
+ * this matches the vendored catalog exactly, so it cannot drift silently.
21
+ */
22
+ export declare const A2UI_ICONS: readonly string[];
23
+ /**
24
+ * Resolve a prefab icon name to an A2UI one.
25
+ *
26
+ * @returns the catalog name, or `undefined` when nothing in the enum means the
27
+ * same thing. Callers drop the icon and record a diagnostic.
28
+ */
29
+ export declare function a2uiIconName(name: string): string | undefined;
30
+ //# sourceMappingURL=icons.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"icons.d.ts","sourceRoot":"","sources":["../../src/a2ui/icons.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,EAAE,SAAS,MAAM,EAUvC,CAAA;AAiDD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAG7D"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * prefab icon name → A2UI Basic catalog icon.
3
+ *
4
+ * The one place where the two catalogs disagree on *values* rather than on
5
+ * component shape. prefab's `Icon(name)` takes any string, because its renderer
6
+ * resolves Lucide names at runtime and new icons cost nothing. A2UI's
7
+ * `Icon.name` is a closed enum of 59 names, so an unrecognised value does not
8
+ * render as a fallback glyph — it makes the whole component fail validation.
9
+ *
10
+ * Passing the name through unchecked therefore emits an invalid surface for
11
+ * every icon outside those 59, which is most of them. Instead the name is
12
+ * normalised, matched against the enum, and dropped with a diagnostic when
13
+ * nothing fits, so an unmappable icon costs a glyph rather than the payload.
14
+ */
15
+ /**
16
+ * The A2UI Basic catalog's `Icon.name` enum, v1.0.
17
+ *
18
+ * Duplicated as a literal because prefab ships zero runtime dependencies and
19
+ * cannot read the catalog JSON at emit time. `test/a2ui-icons.test.ts` asserts
20
+ * this matches the vendored catalog exactly, so it cannot drift silently.
21
+ */
22
+ export const A2UI_ICONS = [
23
+ 'accountCircle', 'add', 'arrowBack', 'arrowForward', 'attachFile', 'calendarToday',
24
+ 'call', 'camera', 'check', 'close', 'delete', 'download', 'edit', 'event', 'error',
25
+ 'fastForward', 'favorite', 'favoriteOff', 'folder', 'help', 'home', 'info',
26
+ 'locationOn', 'lock', 'lockOpen', 'mail', 'menu', 'moreVert', 'moreHoriz',
27
+ 'notificationsOff', 'notifications', 'pause', 'payment', 'person', 'phone', 'photo',
28
+ 'play', 'print', 'refresh', 'rewind', 'search', 'send', 'settings', 'share',
29
+ 'shoppingCart', 'skipNext', 'skipPrevious', 'star', 'starHalf', 'starOff', 'stop',
30
+ 'upload', 'visibility', 'visibilityOff', 'volumeDown', 'volumeMute', 'volumeOff',
31
+ 'volumeUp', 'warning',
32
+ ];
33
+ /** Lookup by normalised form, so `Arrow-Back`, `arrow_back` and `ArrowBack` all hit. */
34
+ const BY_NORMALISED = new Map(A2UI_ICONS.map(name => [normalise(name), name]));
35
+ /**
36
+ * Names that differ between the two vocabularies rather than merely in case.
37
+ *
38
+ * prefab follows Lucide, A2UI follows Material. Where the concept exists in both
39
+ * under different words, the alias keeps the icon; where it does not, the entry
40
+ * is absent and the icon is dropped rather than mapped to something that means
41
+ * something else. Keys are normalised, so one entry covers every spelling.
42
+ */
43
+ const ALIASES = {
44
+ // Status and feedback
45
+ alertcircle: 'error', alerttriangle: 'warning', alertoctagon: 'error',
46
+ xcircle: 'error', circlex: 'error', circlealert: 'error',
47
+ checkcircle: 'check', circlecheck: 'check', checkcircle2: 'check',
48
+ infocircle: 'info', circleinfo: 'info', helpcircle: 'help', circlehelp: 'help',
49
+ bell: 'notifications', belloff: 'notificationsOff',
50
+ // Navigation
51
+ arrowleft: 'arrowBack', arrowright: 'arrowForward',
52
+ chevronleft: 'arrowBack', chevronright: 'arrowForward',
53
+ x: 'close', plus: 'add', trash: 'delete', trash2: 'delete',
54
+ ellipsisvertical: 'moreVert', ellipsis: 'moreHoriz', morehorizontal: 'moreHoriz',
55
+ morevertical: 'moreVert',
56
+ // Objects and actions
57
+ pencil: 'edit', pen: 'edit', squarepen: 'edit',
58
+ user: 'person', usercircle: 'accountCircle', circleuser: 'accountCircle',
59
+ eye: 'visibility', eyeoff: 'visibilityOff',
60
+ mappin: 'locationOn', map: 'locationOn',
61
+ image: 'photo', images: 'photo', file: 'folder', files: 'folder',
62
+ calendar: 'calendarToday', calendardays: 'calendarToday', clock: 'event',
63
+ creditcard: 'payment', cart: 'shoppingCart', shoppingbag: 'shoppingCart',
64
+ phonecall: 'call', mailopen: 'mail', inbox: 'mail',
65
+ cog: 'settings', gear: 'settings', sliders: 'settings',
66
+ rotatecw: 'refresh', rotateccw: 'refresh', refreshcw: 'refresh',
67
+ heart: 'favorite', heartoff: 'favoriteOff',
68
+ volume: 'volumeUp', volume1: 'volumeDown', volume2: 'volumeUp', volumex: 'volumeOff',
69
+ skipforward: 'skipNext', skipback: 'skipPrevious',
70
+ paperclip: 'attachFile', link: 'share', share2: 'share',
71
+ magnifyingglass: 'search', searchicon: 'search',
72
+ };
73
+ /** Case-insensitive, separator-insensitive key for matching either vocabulary. */
74
+ function normalise(name) {
75
+ return name.replace(/[\s._-]/g, '').toLowerCase();
76
+ }
77
+ /**
78
+ * Resolve a prefab icon name to an A2UI one.
79
+ *
80
+ * @returns the catalog name, or `undefined` when nothing in the enum means the
81
+ * same thing. Callers drop the icon and record a diagnostic.
82
+ */
83
+ export function a2uiIconName(name) {
84
+ const key = normalise(name);
85
+ return BY_NORMALISED.get(key) ?? ALIASES[key];
86
+ }
87
+ //# sourceMappingURL=icons.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"icons.js","sourceRoot":"","sources":["../../src/a2ui/icons.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,UAAU,GAAsB;IAC3C,eAAe,EAAE,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,YAAY,EAAE,eAAe;IAClF,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO;IAClF,aAAa,EAAE,UAAU,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAC1E,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW;IACzE,kBAAkB,EAAE,eAAe,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO;IACnF,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO;IAC3E,cAAc,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM;IACjF,QAAQ,EAAE,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW;IAChF,UAAU,EAAE,SAAS;CACtB,CAAA;AAED,wFAAwF;AACxF,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;AAE9E;;;;;;;GAOG;AACH,MAAM,OAAO,GAA2B;IACtC,sBAAsB;IACtB,WAAW,EAAE,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,YAAY,EAAE,OAAO;IACrE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO;IACxD,WAAW,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO;IACjE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM;IAC9E,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,kBAAkB;IAClD,aAAa;IACb,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,cAAc;IAClD,WAAW,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc;IACtD,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ;IAC1D,gBAAgB,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,cAAc,EAAE,WAAW;IAChF,YAAY,EAAE,UAAU;IACxB,sBAAsB;IACtB,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;IAC9C,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,eAAe,EAAE,UAAU,EAAE,eAAe;IACxE,GAAG,EAAE,YAAY,EAAE,MAAM,EAAE,eAAe;IAC1C,MAAM,EAAE,YAAY,EAAE,GAAG,EAAE,YAAY;IACvC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ;IAChE,QAAQ,EAAE,eAAe,EAAE,YAAY,EAAE,eAAe,EAAE,KAAK,EAAE,OAAO;IACxE,UAAU,EAAE,SAAS,EAAE,IAAI,EAAE,cAAc,EAAE,WAAW,EAAE,cAAc;IACxE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;IAClD,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU;IACtD,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS;IAC/D,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,aAAa;IAC1C,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW;IACpF,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,cAAc;IACjD,SAAS,EAAE,YAAY,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO;IACvD,eAAe,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ;CAChD,CAAA;AAED,kFAAkF;AAClF,SAAS,SAAS,CAAC,IAAY;IAC7B,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAA;AACnD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,CAAC,CAAA;IAC3B,OAAO,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,CAAA;AAC/C,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * A2UI emitter — the second output target alongside the `$prefab` wire format.
3
+ *
4
+ * `$prefab` payloads render through prefab's own renderer, in an MCP Apps
5
+ * iframe or any web app. A2UI payloads render natively in the A2UI renderers
6
+ * (React, Angular, Lit, Flutter, Swift, Compose) with no iframe involved. Both
7
+ * come from the same server-side component tree.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * import { Column, H1, autoTable } from '@maxhealth.tech/prefab'
12
+ * import { PrefabApp } from '@maxhealth.tech/prefab'
13
+ *
14
+ * const app = new PrefabApp({ view: Column({ children: [H1('Users'), autoTable(rows)] }) })
15
+ * const { messages, diagnostics } = app.toA2UI()
16
+ * ```
17
+ */
18
+ export { emitA2UI } from './emit.js';
19
+ export type { A2uiEmitOptions, A2uiEmitResult } from './emit.js';
20
+ export { mappedTypes } from './catalog.js';
21
+ export { a2uiIconName, A2UI_ICONS } from './icons.js';
22
+ export { mappedPipes, parsePipe } from './pipes.js';
23
+ export type { ParsedPipe, PipeMapping } from './pipes.js';
24
+ export type { A2uiProps, EmitContext, Mapper } from './catalog.js';
25
+ export { toBinding, toJsonPointer, escapePointerToken, dynamicString } from './expr.js';
26
+ export type { BindingResult } from './expr.js';
27
+ export { A2UI_VERSION, A2UI_BASIC_CATALOG, A2UI_MIME, A2UI_SCHEME, A2UI_ROOT_ID, } from './types.js';
28
+ export type { A2uiAccessibility, A2uiAction, A2uiChildList, A2uiChildTemplate, A2uiComponent, A2uiCreateSurface, A2uiDataBinding, A2uiDeleteSurface, A2uiDiagnostic, A2uiDiagnosticKind, A2uiDynamicBoolean, A2uiDynamicNumber, A2uiDynamicString, A2uiDynamicValue, A2uiEventAction, A2uiFunctionAction, A2uiFunctionCall, A2uiMessage, A2uiMessageList, A2uiUpdateComponents, A2uiUpdateDataModel, } from './types.js';
29
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/a2ui/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AACpC,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAEhE,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC1C,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AACrD,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AACnD,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AACzD,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAElE,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AACvF,YAAY,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAE9C,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,SAAS,EACT,WAAW,EACX,YAAY,GACb,MAAM,YAAY,CAAA;AACnB,YAAY,EACV,iBAAiB,EACjB,UAAU,EACV,aAAa,EACb,iBAAiB,EACjB,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,cAAc,EACd,kBAAkB,EAClB,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EACf,kBAAkB,EAClB,gBAAgB,EAChB,WAAW,EACX,eAAe,EACf,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,YAAY,CAAA"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * A2UI emitter — the second output target alongside the `$prefab` wire format.
3
+ *
4
+ * `$prefab` payloads render through prefab's own renderer, in an MCP Apps
5
+ * iframe or any web app. A2UI payloads render natively in the A2UI renderers
6
+ * (React, Angular, Lit, Flutter, Swift, Compose) with no iframe involved. Both
7
+ * come from the same server-side component tree.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * import { Column, H1, autoTable } from '@maxhealth.tech/prefab'
12
+ * import { PrefabApp } from '@maxhealth.tech/prefab'
13
+ *
14
+ * const app = new PrefabApp({ view: Column({ children: [H1('Users'), autoTable(rows)] }) })
15
+ * const { messages, diagnostics } = app.toA2UI()
16
+ * ```
17
+ */
18
+ export { emitA2UI } from './emit.js';
19
+ export { mappedTypes } from './catalog.js';
20
+ export { a2uiIconName, A2UI_ICONS } from './icons.js';
21
+ export { mappedPipes, parsePipe } from './pipes.js';
22
+ export { toBinding, toJsonPointer, escapePointerToken, dynamicString } from './expr.js';
23
+ export { A2UI_VERSION, A2UI_BASIC_CATALOG, A2UI_MIME, A2UI_SCHEME, A2UI_ROOT_ID, } from './types.js';
24
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/a2ui/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAGpC,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC1C,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AACrD,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAInD,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAGvF,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,SAAS,EACT,WAAW,EACX,YAAY,GACb,MAAM,YAAY,CAAA"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * prefab pipe → A2UI catalog function.
3
+ *
4
+ * `{{ price | currency:'USD' }}` was previously reported as unbindable on the
5
+ * grounds that A2UI has no expression language. That is true of the language and
6
+ * false of the catalog: A2UI ships `formatCurrency`, `formatNumber`, `formatDate`
7
+ * and `pluralize` as functions, which is exactly what these pipes are.
8
+ *
9
+ * Seven of prefab's twenty-two built-ins map. The rest — `truncate`, `join`,
10
+ * `selectattr`, `percent`, `compact` and friends — transform data rather than
11
+ * format it and have no equivalent, so they stay unbindable.
12
+ *
13
+ * The date pipes are the one inexact mapping. prefab renders through
14
+ * `toLocaleDateString()`, so the output follows the reader's locale; A2UI's
15
+ * `formatDate` requires an explicit Unicode TR35 pattern. Choosing a pattern
16
+ * changes what the reader sees, so it is done with a diagnostic rather than
17
+ * silently — losing the value entirely would be the worse trade.
18
+ */
19
+ import type { A2uiDynamicValue, A2uiFunctionCall } from './types.js';
20
+ /** A pipe applied to a base expression: `path | name:arg`. */
21
+ export interface ParsedPipe {
22
+ base: string;
23
+ name: string;
24
+ arg?: string | number;
25
+ }
26
+ /**
27
+ * Split a pipe expression into its parts.
28
+ *
29
+ * Only a single pipe with at most one argument, which is the shape prefab's own
30
+ * evaluator handles. A chained expression returns `undefined` and is reported
31
+ * rather than half-translated.
32
+ */
33
+ export declare function parsePipe(expr: string): ParsedPipe | undefined;
34
+ /** What a mapped pipe produces, plus anything the mapping cost. */
35
+ export interface PipeMapping {
36
+ call: A2uiFunctionCall;
37
+ /** Set when the translation is inexact, for the caller to report. */
38
+ note?: string;
39
+ }
40
+ /** Every prefab pipe with an A2UI equivalent, for docs and tests. */
41
+ export declare function mappedPipes(): string[];
42
+ /**
43
+ * Map a parsed pipe onto a catalog function.
44
+ *
45
+ * @param value the already-resolved base, as a binding or a literal.
46
+ * @returns `undefined` when the pipe transforms rather than formats.
47
+ */
48
+ export declare function pipeCall(pipe: ParsedPipe, value: A2uiDynamicValue): PipeMapping | undefined;
49
+ //# sourceMappingURL=pipes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipes.d.ts","sourceRoot":"","sources":["../../src/a2ui/pipes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAEpE,8DAA8D;AAC9D,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;CACtB;AAKD;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CA2B9D;AAED,mEAAmE;AACnE,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,gBAAgB,CAAA;IACtB,qEAAqE;IACrE,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AA2CD,qEAAqE;AACrE,wBAAgB,WAAW,IAAI,MAAM,EAAE,CAEtC;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,gBAAgB,GAAG,WAAW,GAAG,SAAS,CAE3F"}
@@ -0,0 +1,106 @@
1
+ /**
2
+ * prefab pipe → A2UI catalog function.
3
+ *
4
+ * `{{ price | currency:'USD' }}` was previously reported as unbindable on the
5
+ * grounds that A2UI has no expression language. That is true of the language and
6
+ * false of the catalog: A2UI ships `formatCurrency`, `formatNumber`, `formatDate`
7
+ * and `pluralize` as functions, which is exactly what these pipes are.
8
+ *
9
+ * Seven of prefab's twenty-two built-ins map. The rest — `truncate`, `join`,
10
+ * `selectattr`, `percent`, `compact` and friends — transform data rather than
11
+ * format it and have no equivalent, so they stay unbindable.
12
+ *
13
+ * The date pipes are the one inexact mapping. prefab renders through
14
+ * `toLocaleDateString()`, so the output follows the reader's locale; A2UI's
15
+ * `formatDate` requires an explicit Unicode TR35 pattern. Choosing a pattern
16
+ * changes what the reader sees, so it is done with a diagnostic rather than
17
+ * silently — losing the value entirely would be the worse trade.
18
+ */
19
+ /** Matches `<base> | <name>` with an optional single `:arg`. */
20
+ const PIPE = /^(.+?)\s*\|\s*([A-Za-z_][\w]*)\s*(?::\s*(.+))?$/;
21
+ /**
22
+ * Split a pipe expression into its parts.
23
+ *
24
+ * Only a single pipe with at most one argument, which is the shape prefab's own
25
+ * evaluator handles. A chained expression returns `undefined` and is reported
26
+ * rather than half-translated.
27
+ */
28
+ export function parsePipe(expr) {
29
+ const m = PIPE.exec(expr);
30
+ if (m == null)
31
+ return undefined;
32
+ const base = m[1].trim();
33
+ // A second `|` means a chain, which has no single-function equivalent.
34
+ if (base.includes('|'))
35
+ return undefined;
36
+ // `at` rather than indexing: an optional capture group is typed `string` but
37
+ // is genuinely absent when the pipe took no argument.
38
+ const raw = m.at(3)?.trim();
39
+ if (raw === undefined)
40
+ return { base, name: m[2] };
41
+ const quoted = /^'([^']*)'$|^"([^"]*)"$/.exec(raw);
42
+ if (quoted != null) {
43
+ // One alternative matched, so exactly one group is present. An empty capture
44
+ // is a real empty-string argument, which `??` keeps and `||` would discard.
45
+ const literal = quoted.at(1) ?? quoted.at(2);
46
+ return { base, name: m[2], arg: literal ?? '' };
47
+ }
48
+ const num = Number(raw);
49
+ if (!Number.isNaN(num))
50
+ return { base, name: m[2], arg: num };
51
+ // An unquoted, non-numeric argument is a reference prefab would resolve at
52
+ // render time. A2UI function args take a value, not an expression to evaluate.
53
+ return undefined;
54
+ }
55
+ /** Build a `formatDate` call, noting that an explicit pattern replaces the locale. */
56
+ function dateFormat(pattern, pipe) {
57
+ return (value) => ({
58
+ call: { call: 'formatDate', args: { value, format: pattern } },
59
+ note: `the "${pipe}" pipe renders in the reader's locale; A2UI needs an explicit pattern, so "${pattern}" was used`,
60
+ });
61
+ }
62
+ const BUILDERS = {
63
+ currency: (value, arg) => ({
64
+ call: {
65
+ call: 'formatCurrency',
66
+ // prefab defaults to USD when the pipe is given no code.
67
+ args: { value, currency: typeof arg === 'string' ? arg : 'USD' },
68
+ },
69
+ }),
70
+ number: (value, arg) => ({
71
+ call: {
72
+ call: 'formatNumber',
73
+ args: { value, ...(typeof arg === 'number' && { decimals: arg }) },
74
+ },
75
+ }),
76
+ round: (value, arg) => ({
77
+ call: {
78
+ call: 'formatNumber',
79
+ // prefab's `round` with no argument means whole numbers.
80
+ args: { value, decimals: typeof arg === 'number' ? arg : 0 },
81
+ },
82
+ }),
83
+ pluralize: (value, arg) => {
84
+ if (typeof arg !== 'string')
85
+ return undefined;
86
+ // prefab pluralizes by appending an s, which is the rule it can express.
87
+ return { call: { call: 'pluralize', args: { value, one: arg, other: `${arg}s` } } };
88
+ },
89
+ date: dateFormat('y-MM-dd', 'date'),
90
+ time: dateFormat('HH:mm', 'time'),
91
+ datetime: dateFormat('y-MM-dd HH:mm', 'datetime'),
92
+ };
93
+ /** Every prefab pipe with an A2UI equivalent, for docs and tests. */
94
+ export function mappedPipes() {
95
+ return Object.keys(BUILDERS).sort();
96
+ }
97
+ /**
98
+ * Map a parsed pipe onto a catalog function.
99
+ *
100
+ * @param value the already-resolved base, as a binding or a literal.
101
+ * @returns `undefined` when the pipe transforms rather than formats.
102
+ */
103
+ export function pipeCall(pipe, value) {
104
+ return BUILDERS[pipe.name]?.(value, pipe.arg);
105
+ }
106
+ //# sourceMappingURL=pipes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipes.js","sourceRoot":"","sources":["../../src/a2ui/pipes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Table mappers — the one place a prefab component gains structure on the way
3
+ * out rather than losing it.
4
+ *
5
+ * The A2UI Basic catalog has no table component, so a table becomes a `Column`
6
+ * of `Row`s. For `DataTable` that would be a poor trade, because prefab's table
7
+ * is data-driven and flattening it would inline every row as its own component
8
+ * and lose the binding. A2UI's own answer is the child template: a `Column`
9
+ * whose `children` is `{ path, componentId }` instantiates one copy of the
10
+ * template component per item in a data-model list, and paths inside the
11
+ * template resolve relative to the current item. That maps onto `DataTable`
12
+ * exactly — one `Row` template, one `Text` per column bound to the column key —
13
+ * so the emitted surface stays as small and as reactive as the prefab original.
14
+ *
15
+ * The pattern follows `catalogs/basic/examples/18_track-list.json` in the A2UI
16
+ * specification, which is the normative example for templated lists.
17
+ */
18
+ import type { ComponentJSON } from '../core/component.js';
19
+ import type { A2uiProps, EmitContext } from './catalog.js';
20
+ /** prefab table parts that only exist inside a `Table` and never map on their own. */
21
+ export declare const TABLE_PART_TYPES: readonly ["TableHead", "TableBody", "TableFooter", "TableRow", "TableCell", "TableHeader", "ExpandableRow"];
22
+ /**
23
+ * `DataTable` → a header `Row` plus a templated `Column`.
24
+ *
25
+ * A column key containing a `.` addresses a nested field on the row. Relative
26
+ * paths inside a template are JSON Pointers too, so the dots become slashes.
27
+ */
28
+ export declare function mapDataTable(node: ComponentJSON, ctx: EmitContext): A2uiProps | undefined;
29
+ /** `Table` → a `Column` of `Row`s, one per `TableRow`. */
30
+ export declare function mapTable(node: ComponentJSON, ctx: EmitContext): A2uiProps | undefined;
31
+ //# sourceMappingURL=table.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table.d.ts","sourceRoot":"","sources":["../../src/a2ui/table.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACzD,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAG1D,sFAAsF;AACtF,eAAO,MAAM,gBAAgB,6GAEnB,CAAA;AAyCV;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE,WAAW,GAAG,SAAS,GAAG,SAAS,CAkCzF;AAyCD,0DAA0D;AAC1D,wBAAgB,QAAQ,CAAC,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE,WAAW,GAAG,SAAS,GAAG,SAAS,CAkBrF"}