@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
package/README.md CHANGED
@@ -1,30 +1,39 @@
1
1
  # prefab
2
2
 
3
3
  [![CI](https://github.com/Max-Health-Inc/prefab/actions/workflows/ci.yml/badge.svg)](https://github.com/Max-Health-Inc/prefab/actions/workflows/ci.yml)
4
- [![tests](https://img.shields.io/badge/tests-1077%20passing%20(100%25)-brightgreen)](https://github.com/Max-Health-Inc/prefab/actions/workflows/ci.yml)
4
+ [![tests](https://img.shields.io/badge/tests-2110%20passing%20(100%25)-brightgreen)](https://github.com/Max-Health-Inc/prefab/actions/workflows/ci.yml)
5
5
  [![@maxhealth.tech/prefab](https://img.shields.io/npm/v/@maxhealth.tech/prefab?label=%40maxhealth.tech%2Fprefab)](https://www.npmjs.com/package/@maxhealth.tech/prefab)
6
6
  [![prefab-protocol](https://img.shields.io/badge/prefab--protocol-v0.3-brightgreen)](https://maxhealth.tech/prefab/reference/wire-format.html)
7
+ [![A2UI](https://img.shields.io/badge/A2UI-v1.0-4285F4)](https://maxhealth.tech/prefab/guide/a2ui.html)
7
8
  [![TypeScript](https://img.shields.io/badge/TypeScript-6.0-blue?logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
8
9
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
9
10
 
10
- The TypeScript full-stack framework for MCP app UIs: author server-side, ship JSON, render anywhere.
11
+ TypeScript authoring for **A2UI** and **MCP Apps**: build the UI server-side, emit either wire format, render anywhere.
11
12
 
12
- A superset of PrefectHQ's Python [prefab-ui](https://github.com/PrefectHQ/prefab), on the **`$prefab` v0.3 wire protocol** (still renders legacy `0.2` payloads).
13
+ **[Live Demo](https://maxhealth.tech/prefab/demo/)** · **[Playground](https://maxhealth.tech/prefab/playground/)** · **[Docs](https://maxhealth.tech/prefab/)**
13
14
 
14
- **[Live Demo](https://maxhealth.tech/prefab/demo/)** · **[Playground](https://maxhealth.tech/prefab/playground/)**
15
+ Agent UIs have settled on two shapes. [MCP Apps](https://modelcontextprotocol.io/seps/1865-mcp-apps-interactive-user-interfaces-for-mcp) ships HTML that the host renders in a sandboxed iframe. [A2UI](https://a2ui.org) ships a declarative component tree that the host's own renderer draws as native widgets. Writing a UI twice to reach both is the problem this package removes.
15
16
 
16
- Write MCP servers in **TypeScript/Bun** and generate the same wire format that Python servers produce. Render the output in **any web app** with the included vanilla DOM renderer. Full circle: server-side DSL → JSON → browser UI.
17
+ You describe the interface once with a typed component API, and prefab emits whichever wire format the host wants:
18
+
19
+ ```ts
20
+ const app = new PrefabApp({ view: Column({ children: [H1('Users'), autoTable(rows)] }) })
21
+
22
+ app.toJSON() // $prefab — rendered by prefab's renderer, in an MCP Apps iframe or any web app
23
+ app.toA2UI() // A2UI v1.0 — rendered natively by React, Angular, Lit, Flutter, Swift, Compose
24
+ ```
17
25
 
18
26
  - **115+ components** — layout, form, data, charts, media, interactive, control flow
27
+ - **Auto-renderers** — `autoTable()`, `autoChart()`, `autoForm()`, `autoMetrics()` and more
28
+ - **Two wire formats** — `$prefab` v0.3 (superset of PrefectHQ's Python [prefab-ui](https://github.com/PrefectHQ/prefab), still renders legacy `0.2`) and [A2UI v1.0](https://a2ui.org), schema-validated against the official specification
29
+ - **MCP-native** — `display()`, `display_a2ui()`, `ui://` and `a2ui://` resource helpers, `input_required` for the 2026-07-28 revision
19
30
  - **Reactive state** — `rx()` expressions, `SetState`/`ToggleState`/`AppendState` actions
20
- - **MCP-native** — `display()`, `display_form()`, `CallTool`, `SendMessage` built in
21
31
  - **Browser renderer** — zero dependencies, vanilla DOM (optional separate import)
22
32
  - **PostMessage bridge** — `app()` factory with dual-protocol handshake, host theme, lifecycle hooks
23
- - **Auto-renderers** — `autoTable()`, `autoChart()`, `autoForm()`, `autoMetrics()` and more
24
33
 
25
34
  ## Works Everywhere
26
35
 
27
- The renderer is **vanilla DOM** — no framework dependency. Drop it into any web app:
36
+ On the `$prefab` path the renderer is **vanilla DOM** — no framework dependency. Drop it into any web app:
28
37
 
29
38
  - **React** — mount into a `ref` div
30
39
  - **Vue / Svelte / Angular** — same, it's just DOM
@@ -32,7 +41,7 @@ The renderer is **vanilla DOM** — no framework dependency. Drop it into any we
32
41
  - **Electron / Tauri** — desktop apps with web views
33
42
  - **Any iframe** — MCP Apps, embedded widgets, sandboxed UIs
34
43
 
35
- Any app that connects to MCP servers can render `$prefab` tool output as rich interactive UI tables, charts, forms, badges with zero custom code.
44
+ On the A2UI path there is no prefab renderer at all: the host draws the components itself, so the same tree reaches the A2UI renderers for React, Angular, Lit, Flutter, Swift and Jetpack Compose. See the [A2UI guide](https://maxhealth.tech/prefab/guide/a2ui) for the mapping table and what degrades.
36
45
 
37
46
  ## Install
38
47
 
@@ -361,6 +370,62 @@ return display_error('User not found', `No user with id ${id}.`, {
361
370
  })
362
371
  ```
363
372
 
373
+ ### Asking for input (MCP 2026-07-28)
374
+
375
+ The revision removed server-initiated elicitation: a handler asks for input by
376
+ returning an `input_required` result, and the client retries the call with the
377
+ answers. The same field list drives both paths, so a host with no UI surface
378
+ still gets the form:
379
+
380
+ ```ts
381
+ const FIELDS = [
382
+ { name: 'email', label: 'Email', type: 'email', required: true },
383
+ { name: 'plan', label: 'Plan', options: [{ value: 'pro' }, { value: 'team' }] },
384
+ ]
385
+
386
+ // Rendered as prefab UI, submitting to the `signup` tool:
387
+ display_form(FIELDS, 'signup', { title: 'Create your account' })
388
+
389
+ // Or asked natively by the client, which then retries the call:
390
+ display_form(FIELDS, 'signup', { title: 'Create your account', elicit: true })
391
+ ```
392
+
393
+ Read the answer back with `acceptedFormInput`, which checks the untrusted client
394
+ response against the same fields. Full walkthrough in
395
+ [Asking for Input](https://maxhealth.tech/prefab/guide/input-required).
396
+
397
+ ## A2UI
398
+
399
+ Emit the same tree as [A2UI](https://a2ui.org) and let the host render it natively:
400
+
401
+ ```ts
402
+ const { messages, diagnostics } = app.toA2UI()
403
+ ```
404
+
405
+ Serve it over MCP under the `application/a2ui+json` MIME type:
406
+
407
+ ```ts
408
+ // Per-call, as an embedded resource in a tool result
409
+ server.registerTool('list-users', schema, async () => display_a2ui(autoTable(await db.users())))
410
+
411
+ // Or as a static a2ui:// resource the host can cache
412
+ registerA2uiResource(server, () => Column({ children: [H1('Settings')] }))
413
+ ```
414
+
415
+ Or translate a payload in the browser, from a bundle separate to the renderer:
416
+
417
+ ```html
418
+ <script src="https://cdn.jsdelivr.net/npm/@maxhealth.tech/prefab/dist/a2ui.min.js"></script>
419
+ <script>const { messages, diagnostics } = PrefabA2UI.emit(wireJson)</script>
420
+ ```
421
+
422
+ prefab has 115+ components and the A2UI Basic catalog has 18, so parts of the
423
+ tree change shape on the way across. `diagnostics` reports every one — nothing
424
+ degrades silently. Payloads are validated against the official A2UI v1.0 JSON
425
+ Schemas in CI. The [playground](https://maxhealth.tech/prefab/playground/) has an
426
+ A2UI tab that shows the translation and its diagnostics live. See the
427
+ [A2UI guide](https://maxhealth.tech/prefab/guide/a2ui).
428
+
364
429
  ### `rendererHtml()` — Viewer HTML Shell
365
430
 
366
431
  Generate the complete HTML page for an MCP Apps viewer resource. Loads `prefab.css` + `renderer.auto.min.js` from the CDN automatically — no manual script wiring needed:
@@ -498,6 +563,7 @@ import { ... } from '@maxhealth.tech/prefab/rx' // Rx expressions only
498
563
  import { ... } from '@maxhealth.tech/prefab/charts' // Chart components only
499
564
  import { ... } from '@maxhealth.tech/prefab/auto' // Auto-renderers
500
565
  import { ... } from '@maxhealth.tech/prefab/mcp' // MCP display helpers
566
+ import { ... } from '@maxhealth.tech/prefab/a2ui' // A2UI emitter
501
567
  import { ... } from '@maxhealth.tech/prefab/renderer' // Browser renderer
502
568
  import '@maxhealth.tech/prefab/prefab.css' // Default stylesheet
503
569
  ```
@@ -506,7 +572,7 @@ import '@maxhealth.tech/prefab/prefab.css' // Default stylesheet
506
572
 
507
573
  ```bash
508
574
  bun install # Install dependencies
509
- bun test # Run tests (996 passing)
575
+ bun test # Run tests
510
576
  bun run build # TypeScript compile + IIFE bundle
511
577
  bun run lint # ESLint
512
578
  bun run typecheck # Type check without emitting
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Browser entry for the A2UI emitter — `dist/a2ui.min.js`.
3
+ *
4
+ * Bundled separately from `renderer.min.js` on purpose. The renderer is what
5
+ * every `$prefab` page loads, and emitting A2UI is something almost none of
6
+ * them do, so folding the emitter in would tax every consumer for a feature
7
+ * they do not use. Keeping it apart also means the two can be loaded
8
+ * independently: a tool that only translates payloads needs no renderer at all.
9
+ *
10
+ * The emitter takes wire JSON and returns wire JSON, so nothing here needs the
11
+ * component API. That is what keeps the bundle small.
12
+ *
13
+ * ```html
14
+ * <script src="https://cdn.jsdelivr.net/npm/@maxhealth.tech/prefab/dist/a2ui.min.js"></script>
15
+ * <script>
16
+ * const { messages, diagnostics } = PrefabA2UI.emit(wireJson)
17
+ * </script>
18
+ * ```
19
+ */
20
+ import { type A2uiEmitOptions, type A2uiEmitResult } from './emit.js';
21
+ import { mappedTypes } from './catalog.js';
22
+ import { type A2uiMessage, type A2uiMessageList } from './types.js';
23
+ /**
24
+ * Emit A2UI from a `$prefab` payload.
25
+ *
26
+ * Accepts `unknown` because the caller is usually handing over parsed editor
27
+ * text or a tool result, neither of which is typed. A payload without a `view`
28
+ * is rejected here rather than producing an empty surface further downstream.
29
+ */
30
+ declare function emit(wire: unknown, options?: A2uiEmitOptions): A2uiEmitResult;
31
+ /** Wrap messages in the list envelope, for transports needing a JSON object. */
32
+ declare function envelope(messages: A2uiMessage[]): A2uiMessageList;
33
+ declare const PrefabA2UI: {
34
+ emit: typeof emit;
35
+ envelope: typeof envelope;
36
+ /** Every prefab component type with a first-class A2UI mapping. */
37
+ mappedTypes: typeof mappedTypes;
38
+ VERSION: string;
39
+ A2UI_VERSION: string;
40
+ A2UI_BASIC_CATALOG: string;
41
+ A2UI_MIME: string;
42
+ A2UI_SCHEME: string;
43
+ };
44
+ export default PrefabA2UI;
45
+ export { emit, envelope };
46
+ //# sourceMappingURL=browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../src/a2ui/browser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAY,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,WAAW,CAAA;AAC/E,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAG1C,OAAO,EAKL,KAAK,WAAW,EAChB,KAAK,eAAe,EACrB,MAAM,YAAY,CAAA;AAEnB;;;;;;GAMG;AACH,iBAAS,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,cAAc,CAKtE;AAED,gFAAgF;AAChF,iBAAS,QAAQ,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,eAAe,CAE1D;AAED,QAAA,MAAM,UAAU;;;IAGd,mEAAmE;;;;;;;CAOpE,CAAA;AAED,eAAe,UAAU,CAAA;AACzB,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAA"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Browser entry for the A2UI emitter — `dist/a2ui.min.js`.
3
+ *
4
+ * Bundled separately from `renderer.min.js` on purpose. The renderer is what
5
+ * every `$prefab` page loads, and emitting A2UI is something almost none of
6
+ * them do, so folding the emitter in would tax every consumer for a feature
7
+ * they do not use. Keeping it apart also means the two can be loaded
8
+ * independently: a tool that only translates payloads needs no renderer at all.
9
+ *
10
+ * The emitter takes wire JSON and returns wire JSON, so nothing here needs the
11
+ * component API. That is what keeps the bundle small.
12
+ *
13
+ * ```html
14
+ * <script src="https://cdn.jsdelivr.net/npm/@maxhealth.tech/prefab/dist/a2ui.min.js"></script>
15
+ * <script>
16
+ * const { messages, diagnostics } = PrefabA2UI.emit(wireJson)
17
+ * </script>
18
+ * ```
19
+ */
20
+ import { emitA2UI } from './emit.js';
21
+ import { mappedTypes } from './catalog.js';
22
+ import { VERSION } from '../core/version.js';
23
+ import { A2UI_BASIC_CATALOG, A2UI_MIME, A2UI_SCHEME, A2UI_VERSION, } from './types.js';
24
+ /**
25
+ * Emit A2UI from a `$prefab` payload.
26
+ *
27
+ * Accepts `unknown` because the caller is usually handing over parsed editor
28
+ * text or a tool result, neither of which is typed. A payload without a `view`
29
+ * is rejected here rather than producing an empty surface further downstream.
30
+ */
31
+ function emit(wire, options) {
32
+ if (wire == null || typeof wire !== 'object' || !('view' in wire)) {
33
+ throw new TypeError('PrefabA2UI.emit: expected a $prefab payload with a "view"');
34
+ }
35
+ return emitA2UI(wire, options);
36
+ }
37
+ /** Wrap messages in the list envelope, for transports needing a JSON object. */
38
+ function envelope(messages) {
39
+ return { messages };
40
+ }
41
+ const PrefabA2UI = {
42
+ emit,
43
+ envelope,
44
+ /** Every prefab component type with a first-class A2UI mapping. */
45
+ mappedTypes,
46
+ VERSION,
47
+ A2UI_VERSION,
48
+ A2UI_BASIC_CATALOG,
49
+ A2UI_MIME,
50
+ A2UI_SCHEME,
51
+ };
52
+ export default PrefabA2UI;
53
+ export { emit, envelope };
54
+ if (typeof window !== 'undefined') {
55
+ ;
56
+ window.PrefabA2UI = PrefabA2UI;
57
+ }
58
+ //# sourceMappingURL=browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.js","sourceRoot":"","sources":["../../src/a2ui/browser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,QAAQ,EAA6C,MAAM,WAAW,CAAA;AAC/E,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAE5C,OAAO,EACL,kBAAkB,EAClB,SAAS,EACT,WAAW,EACX,YAAY,GAGb,MAAM,YAAY,CAAA;AAEnB;;;;;;GAMG;AACH,SAAS,IAAI,CAAC,IAAa,EAAE,OAAyB;IACpD,IAAI,IAAI,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,IAAI,IAAI,CAAC,EAAE,CAAC;QAClE,MAAM,IAAI,SAAS,CAAC,2DAA2D,CAAC,CAAA;IAClF,CAAC;IACD,OAAO,QAAQ,CAAC,IAAwB,EAAE,OAAO,CAAC,CAAA;AACpD,CAAC;AAED,gFAAgF;AAChF,SAAS,QAAQ,CAAC,QAAuB;IACvC,OAAO,EAAE,QAAQ,EAAE,CAAA;AACrB,CAAC;AAED,MAAM,UAAU,GAAG;IACjB,IAAI;IACJ,QAAQ;IACR,mEAAmE;IACnE,WAAW;IACX,OAAO;IACP,YAAY;IACZ,kBAAkB;IAClB,SAAS;IACT,WAAW;CACZ,CAAA;AAED,eAAe,UAAU,CAAA;AACzB,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAA;AAEzB,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;IAClC,CAAC;IAAC,MAA6C,CAAC,UAAU,GAAG,UAAU,CAAA;AACzE,CAAC"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * prefab component type → A2UI Basic catalog mapper registry.
3
+ *
4
+ * prefab ships 115+ components; the A2UI Basic catalog defines 18. The gap is
5
+ * closed by degradation rather than by refusing to emit: a `Badge` becomes
6
+ * `Text`, an `Alert` becomes a `Card` wrapping its body, an `H2` becomes `Text`
7
+ * carrying a Markdown `##` prefix (which the Basic catalog's `Text` explicitly
8
+ * supports). Every degradation is recorded as a diagnostic, so what changed is
9
+ * visible at emit time instead of in someone else's renderer.
10
+ *
11
+ * A mapper returns the A2UI properties for one node without its `id`; the
12
+ * emitter allocates ids and owns the adjacency list. Mappers that expand one
13
+ * prefab node into several A2UI components (`Metric`, the table family in
14
+ * `./table.ts`) push the extras through `ctx.push` and return the root of the
15
+ * expansion.
16
+ */
17
+ import type { ComponentJSON } from '../core/component.js';
18
+ import type { A2uiComponentProps, A2uiAction, A2uiDiagnosticKind, A2uiDynamicString } from './types.js';
19
+ import type { BindingResult } from './expr.js';
20
+ /** A2UI properties for one component, before the emitter assigns its id. */
21
+ export type A2uiProps = A2uiComponentProps;
22
+ /** Services the emitter lends to a mapper. */
23
+ export interface EmitContext {
24
+ /** Emit one child subtree, returning its id, or `undefined` if it was dropped. */
25
+ child(node: ComponentJSON): string | undefined;
26
+ /** Emit several child subtrees, returning the ids that survived. */
27
+ children(nodes: unknown): string[];
28
+ /** Emit `nodes` as a single child, wrapping them in a Column when there are several. */
29
+ single(nodes: unknown): string | undefined;
30
+ /** Add a component the mapper synthesized, returning its id. */
31
+ push(props: A2uiProps): string;
32
+ /** Record a translation loss. */
33
+ note(kind: A2uiDiagnosticKind, subject: string, detail: string): void;
34
+ /** Convert a serialized prefab action into an A2UI action. */
35
+ action(value: unknown, subject: string): A2uiAction | undefined;
36
+ /** Seed a literal value into the surface data model, returning its JSON Pointer. */
37
+ bindData(key: string, value: unknown): string;
38
+ /**
39
+ * Convert a `{{ }}` value with the current scope applied.
40
+ *
41
+ * Mappers go through the context rather than calling `./expr.js` directly, so
42
+ * the scope in force — a list-template item, an inlined definition's
43
+ * overrides — is applied at one seam instead of at every call site.
44
+ */
45
+ bind(value: string): BindingResult;
46
+ /** Resolve to a dynamic string under the current scope, or `undefined`. */
47
+ dyn(value: string | undefined): A2uiDynamicString | undefined;
48
+ /** Emit `fn`'s children with `names` added to the binding scope. */
49
+ inScope<T>(names: Record<string, string>, fn: () => T): T;
50
+ /** The body of a named definition, if one was declared and is not already expanding. */
51
+ definition(name: string): ComponentJSON[] | undefined;
52
+ /** Run `fn` with `name` marked as expanding, so a self-reference is caught. */
53
+ expand<T>(name: string, fn: () => T): T;
54
+ /** Emit `fn`'s children with slot content available to any `Slot` inside. */
55
+ withSlots<T>(slots: Record<string, ComponentJSON[]>, fn: () => T): T;
56
+ /** Content for a named slot, from the nearest enclosing `Use`. */
57
+ slotContent(name: string): ComponentJSON[] | undefined;
58
+ }
59
+ export type Mapper = (node: ComponentJSON, ctx: EmitContext) => A2uiProps | undefined;
60
+ export declare function mapperFor(type: string): Mapper | undefined;
61
+ export declare function isConsumedByParent(type: string): boolean;
62
+ /** Every prefab type with a first-class mapping, for docs and tests. */
63
+ export declare function mappedTypes(): string[];
64
+ /**
65
+ * Last-resort mapping for a type the registry does not name.
66
+ *
67
+ * A node with children becomes a Column, a node with text becomes a Text, and
68
+ * anything else is dropped. This is what keeps a tree built from unmapped
69
+ * components emitting something coherent instead of failing outright.
70
+ */
71
+ export declare function fallbackMapper(node: ComponentJSON, ctx: EmitContext): A2uiProps | undefined;
72
+ //# sourceMappingURL=catalog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../src/a2ui/catalog.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,UAAU,EAAE,kBAAkB,EAAE,iBAAiB,EAAoB,MAAM,YAAY,CAAA;AACzH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAK9C,4EAA4E;AAC5E,MAAM,MAAM,SAAS,GAAG,kBAAkB,CAAA;AAE1C,8CAA8C;AAC9C,MAAM,WAAW,WAAW;IAC1B,kFAAkF;IAClF,KAAK,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,GAAG,SAAS,CAAA;IAC9C,oEAAoE;IACpE,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,CAAA;IAClC,wFAAwF;IACxF,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAAA;IAC1C,gEAAgE;IAChE,IAAI,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAAA;IAC9B,iCAAiC;IACjC,IAAI,CAAC,IAAI,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrE,8DAA8D;IAC9D,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAAA;IAC/D,oFAAoF;IACpF,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CAAA;IAC7C;;;;;;OAMG;IACH,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,CAAA;IAClC,2EAA2E;IAC3E,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,iBAAiB,GAAG,SAAS,CAAA;IAC7D,oEAAoE;IACpE,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAAA;IACzD,wFAAwF;IACxF,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,EAAE,GAAG,SAAS,CAAA;IACrD,+EAA+E;IAC/E,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAAA;IACvC,6EAA6E;IAC7E,SAAS,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAAA;IACpE,kEAAkE;IAClE,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,EAAE,GAAG,SAAS,CAAA;CACvD;AAED,MAAM,MAAM,MAAM,GAAG,CAAC,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE,WAAW,KAAK,SAAS,GAAG,SAAS,CAAA;AAkfrF,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE1D;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAExD;AAED,wEAAwE;AACxE,wBAAgB,WAAW,IAAI,MAAM,EAAE,CAEtC;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE,WAAW,GAAG,SAAS,GAAG,SAAS,CAsB3F"}