@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.
- package/CHANGELOG.md +723 -671
- package/README.md +76 -10
- package/dist/a2ui/browser.d.ts +46 -0
- package/dist/a2ui/browser.d.ts.map +1 -0
- package/dist/a2ui/browser.js +58 -0
- package/dist/a2ui/browser.js.map +1 -0
- package/dist/a2ui/catalog.d.ts +72 -0
- package/dist/a2ui/catalog.d.ts.map +1 -0
- package/dist/a2ui/catalog.js +521 -0
- package/dist/a2ui/catalog.js.map +1 -0
- package/dist/a2ui/control.d.ts +20 -0
- package/dist/a2ui/control.d.ts.map +1 -0
- package/dist/a2ui/control.js +107 -0
- package/dist/a2ui/control.js.map +1 -0
- package/dist/a2ui/emit.d.ts +59 -0
- package/dist/a2ui/emit.d.ts.map +1 -0
- package/dist/a2ui/emit.js +373 -0
- package/dist/a2ui/emit.js.map +1 -0
- package/dist/a2ui/expr.d.ts +91 -0
- package/dist/a2ui/expr.d.ts.map +1 -0
- package/dist/a2ui/expr.js +201 -0
- package/dist/a2ui/expr.js.map +1 -0
- package/dist/a2ui/icons.d.ts +30 -0
- package/dist/a2ui/icons.d.ts.map +1 -0
- package/dist/a2ui/icons.js +87 -0
- package/dist/a2ui/icons.js.map +1 -0
- package/dist/a2ui/index.d.ts +29 -0
- package/dist/a2ui/index.d.ts.map +1 -0
- package/dist/a2ui/index.js +24 -0
- package/dist/a2ui/index.js.map +1 -0
- package/dist/a2ui/pipes.d.ts +49 -0
- package/dist/a2ui/pipes.d.ts.map +1 -0
- package/dist/a2ui/pipes.js +106 -0
- package/dist/a2ui/pipes.js.map +1 -0
- package/dist/a2ui/table.d.ts +31 -0
- package/dist/a2ui/table.d.ts.map +1 -0
- package/dist/a2ui/table.js +155 -0
- package/dist/a2ui/table.js.map +1 -0
- package/dist/a2ui/types.d.ts +174 -0
- package/dist/a2ui/types.d.ts.map +1 -0
- package/dist/a2ui/types.js +35 -0
- package/dist/a2ui/types.js.map +1 -0
- package/dist/a2ui.min.js +1 -0
- package/dist/app.d.ts +17 -0
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +19 -0
- package/dist/app.js.map +1 -1
- package/dist/auto/form.d.ts +25 -0
- package/dist/auto/form.d.ts.map +1 -1
- package/dist/auto/form.js +21 -8
- package/dist/auto/form.js.map +1 -1
- package/dist/core/version.d.ts +1 -1
- package/dist/core/version.d.ts.map +1 -1
- package/dist/core/version.js +1 -1
- package/dist/core/version.js.map +1 -1
- package/dist/index.d.ts +9 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp/a2ui.d.ts +91 -0
- package/dist/mcp/a2ui.d.ts.map +1 -0
- package/dist/mcp/a2ui.js +134 -0
- package/dist/mcp/a2ui.js.map +1 -0
- package/dist/mcp/display.d.ts +28 -6
- package/dist/mcp/display.d.ts.map +1 -1
- package/dist/mcp/display.js +10 -9
- package/dist/mcp/display.js.map +1 -1
- package/dist/mcp/index.d.ts +7 -2
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +3 -1
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/input-required.d.ts +79 -0
- package/dist/mcp/input-required.d.ts.map +1 -0
- package/dist/mcp/input-required.js +231 -0
- package/dist/mcp/input-required.js.map +1 -0
- package/dist/mcp/resource.d.ts +10 -0
- package/dist/mcp/resource.d.ts.map +1 -1
- package/dist/mcp/resource.js +12 -4
- package/dist/mcp/resource.js.map +1 -1
- package/dist/mcp/result.d.ts +7 -5
- package/dist/mcp/result.d.ts.map +1 -1
- package/dist/mcp/result.js +5 -3
- package/dist/mcp/result.js.map +1 -1
- package/dist/mcp/types.d.ts +117 -0
- package/dist/mcp/types.d.ts.map +1 -1
- package/dist/renderer/components/index.d.ts.map +1 -1
- package/dist/renderer/components/index.js +6 -0
- package/dist/renderer/components/index.js.map +1 -1
- package/dist/renderer/engine.d.ts +4 -0
- package/dist/renderer/engine.d.ts.map +1 -1
- package/dist/renderer/engine.js +24 -0
- package/dist/renderer/engine.js.map +1 -1
- package/dist/renderer.auto.min.js +13 -13
- package/dist/renderer.min.js +13 -13
- package/package.json +14 -3
package/README.md
CHANGED
|
@@ -1,30 +1,39 @@
|
|
|
1
1
|
# prefab
|
|
2
2
|
|
|
3
3
|
[](https://github.com/Max-Health-Inc/prefab/actions/workflows/ci.yml)
|
|
4
|
-
[-brightgreen)](https://github.com/Max-Health-Inc/prefab/actions/workflows/ci.yml)
|
|
5
5
|
[](https://www.npmjs.com/package/@maxhealth.tech/prefab)
|
|
6
6
|
[](https://maxhealth.tech/prefab/reference/wire-format.html)
|
|
7
|
+
[](https://maxhealth.tech/prefab/guide/a2ui.html)
|
|
7
8
|
[](https://www.typescriptlang.org/)
|
|
8
9
|
[](https://opensource.org/licenses/MIT)
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
TypeScript authoring for **A2UI** and **MCP Apps**: build the UI server-side, emit either wire format, render anywhere.
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
**[Live Demo](https://maxhealth.tech/prefab/demo/)** · **[Playground](https://maxhealth.tech/prefab/playground/)** · **[Docs](https://maxhealth.tech/prefab/)**
|
|
13
14
|
|
|
14
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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"}
|