@maxhealth.tech/prefab 0.3.9 → 0.3.10
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 +27 -0
- 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 +51 -0
- package/dist/a2ui/catalog.d.ts.map +1 -0
- package/dist/a2ui/catalog.js +465 -0
- package/dist/a2ui/catalog.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 +269 -0
- package/dist/a2ui/emit.js.map +1 -0
- package/dist/a2ui/expr.d.ts +58 -0
- package/dist/a2ui/expr.d.ts.map +1 -0
- package/dist/a2ui/expr.js +81 -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 +27 -0
- package/dist/a2ui/index.d.ts.map +1 -0
- package/dist/a2ui/index.js +23 -0
- package/dist/a2ui/index.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 +13 -3
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,33 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.3.10] — 2026-08-24
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **A2UI is now a first-class output target: `PrefabApp.toA2UI()` emits the same component tree as [A2UI](https://a2ui.org) v1.0.** A2UI is the Google-backed declarative agent-to-UI protocol, and it overlaps prefab's category exactly: the agent sends a component tree plus a data model, and the host's own renderer draws native widgets from it. It reaches renderers prefab has none of (React, Angular, Lit, Flutter, Swift, Jetpack Compose) with no iframe involved, and its agent-side SDK is Python-only, so a TypeScript authoring layer had no equivalent. Two structural gaps had to be bridged: A2UI keeps components in a flat adjacency list rather than a nested tree, and it binds dynamic values through JSON Pointers rather than interpolating `{{ }}` templates. `src/a2ui/` handles both, allocating ids deterministically so the same tree always emits byte-identical output.
|
|
12
|
+
- **`display_a2ui()` and `registerA2uiResource()` serve A2UI over MCP**, under the `application/a2ui+json` MIME type as an embedded resource in a tool result or as a standalone `a2ui://` resource, per the [A2UI over MCP](https://a2ui.org/guides/a2ui_over_mcp/) guide. They sit alongside the existing `ui://` MCP Apps helpers rather than replacing them, so one server can offer both and let the host choose. A `ui://` viewer is a pure function of the package version and stays shared-cacheable; an `a2ui://` surface is rebuilt on every read and defaults to no caching, so `resolveCache` is now exported from `resource.ts` and takes the defaults as a parameter instead of hard-coding the viewer's.
|
|
13
|
+
- **Multi Round-Trip input requests (protocol revision 2026-07-28).** The revision made the protocol core stateless and removed server-initiated `elicitation/create`; a handler now returns an `input_required` result and the client retries the call with the answers. That left `display_form()` reachable only on hosts that render UI. The same `AutoFormField[]` now also derives the restricted elicitation schema, so `display_form(fields, tool, { elicit: true })` asks for exactly what the rendered form asks for. `formSchema`, `formInputRequest`, `acceptedFormInput` and `inputResponse` are exported for handlers that compose the rounds themselves. `acceptedFormInput` validates the untrusted client response against the same field list: unknown keys, wrong types, out-of-bound numbers and unoffered enum values are dropped, and a missing required field fails the answer.
|
|
14
|
+
- **The playground has an A2UI tab.** The preview pane now switches between the rendered UI and the same payload translated to A2UI, with the message and component counts, a pill per diagnostic kind, and every diagnostic listed underneath. A `Stream` toggle splits the output into the three-message form. Being able to see what a payload costs in translation, on the twenty shipped examples, says more than the mapping table does.
|
|
15
|
+
- **`dist/a2ui.min.js`, the emitter as a standalone browser bundle.** The playground needs the emitter and does not need it inside `renderer.min.js`: almost no page that renders `$prefab` also emits A2UI, so folding it in would tax every consumer for a feature they do not use. It exposes `PrefabA2UI.emit()` and `PrefabA2UI.envelope()`, takes wire JSON rather than a component tree, and comes to 17 KB against the renderer's 108 KB. Attached to GitHub releases alongside the renderer bundles.
|
|
16
|
+
- `AutoFormField` gained `options`, `multiple`, `description`, `min`, `max` and `default`. A field with `options` renders as a `Select` instead of a bare `Input` on the UI path, and as an enum on the elicitation path.
|
|
17
|
+
- `McpDisplayResult<S>` pins `structuredContent` as present. Every display helper populates it, and the optional field on `McpToolResult` was forcing callers into a null check on something that is never absent.
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- **README, docs landing page and package description now lead with "TypeScript authoring for A2UI and MCP Apps".** The previous framing put "a superset of PrefectHQ's Python prefab-ui" in the second line, which tied the package's story to a project moving slowly and described an implementation detail rather than what the package is for. The superset relationship is still stated, one bullet down, where it belongs.
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
|
|
25
|
+
- **The A2UI emitter produced an invalid surface for most icons.** A2UI's `Icon.name` is a closed enum of 59 Material names, so an unrecognised value does not degrade to a fallback glyph — it fails schema validation and takes the component with it. prefab's `Icon(name)` accepts any string and follows Lucide, so every icon outside that enum emitted an invalid payload. The hand-written test view happened to use `Icon('mail')`, which is in the enum, so nothing caught it. `src/a2ui/icons.ts` now normalises the name, matches it against the enum case- and separator-insensitively, translates the Lucide names prefab itself ships (`AlertCircle` → `error`, `CheckCircle` → `check`), and drops the icon with a diagnostic when nothing means the same thing. The enum is duplicated as a literal because the package has no runtime dependencies and cannot read the catalog at emit time; a test asserts it matches the vendored catalog exactly, so a spec revision cannot let it drift.
|
|
26
|
+
- **`test/component-types.test.ts` depended on which test file the runner reached first.** It compared the generated `src/core/component-types.ts` against the whole renderer registry, which is a process-wide singleton any module can add to. `test/renderer-destroy.test.ts` and `test/pipe-wire.test.ts` register a dozen widgets inside their test bodies, so once the runner reached either of them first, all twelve became "renderable but absent from the generated list" and thirteen assertions failed. It passed locally and failed on CI purely on file-discovery order, and adding the A2UI test files was enough to flip it. `registerAllComponents()` now records the delta it contributes as the built-in set, and both the generator and the sync check read that instead of the full registry. The generated list is unchanged at 119 types.
|
|
27
|
+
|
|
28
|
+
### Internal
|
|
29
|
+
|
|
30
|
+
- **Registry-wide A2UI invariants, rather than one hand-written view per mapper family.** The per-family views check that the mappings are right; they cannot check that they are safe, because a mapper is only covered if someone remembered to write a view for it, and the branches that matter most are the guards deciding "this cannot be expressed, drop it and say why". Coverage of `catalog.ts` sat at 72% of functions with nearly every uncovered line being one of those guards. `test/a2ui-registry.test.ts` now asserts two properties across all 81 registry entries, so a mapper added later is covered the moment it is registered: nothing a mapper emits is ever invalid, given generous props or none at all; and nothing is dropped without a diagnostic. The furnished pass additionally requires an actual component, since "emits nothing" would otherwise satisfy the first property trivially. This is what surfaced the `Icon` enum bug. `catalog.ts` is now at 100% of functions and 97% of lines.
|
|
31
|
+
- Removed `hasTemplate` and `isTemplatedList`, both exported with no caller anywhere.
|
|
32
|
+
- Emitted A2UI payloads are validated in CI against the official v1.0 JSON Schemas, vendored under `test/fixtures/a2ui/v1_0/` (Apache-2.0, with a `NOTICE.md` recording the upstream commit) and refreshable with `bun scripts/sync-a2ui-schemas.ts`. They are checked in rather than fetched so the suite runs offline. The upstream YAML conformance suites were considered and rejected: they exercise SDK internals (streaming parser, catalog pruning, validator behaviour) that a producer does not implement, whereas the schemas define exactly what a producer must emit. Two structural rules the schemas cannot express — every child reference resolves, and every component is reachable from `root` — are asserted separately, taken from `conformance/core/validator.yaml`.
|
|
33
|
+
|
|
7
34
|
## [0.3.9] — 2026-08-07
|
|
8
35
|
|
|
9
36
|
### Added
|
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,51 @@
|
|
|
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 } from './types.js';
|
|
19
|
+
/** A2UI properties for one component, before the emitter assigns its id. */
|
|
20
|
+
export type A2uiProps = A2uiComponentProps;
|
|
21
|
+
/** Services the emitter lends to a mapper. */
|
|
22
|
+
export interface EmitContext {
|
|
23
|
+
/** Emit one child subtree, returning its id, or `undefined` if it was dropped. */
|
|
24
|
+
child(node: ComponentJSON): string | undefined;
|
|
25
|
+
/** Emit several child subtrees, returning the ids that survived. */
|
|
26
|
+
children(nodes: unknown): string[];
|
|
27
|
+
/** Emit `nodes` as a single child, wrapping them in a Column when there are several. */
|
|
28
|
+
single(nodes: unknown): string | undefined;
|
|
29
|
+
/** Add a component the mapper synthesized, returning its id. */
|
|
30
|
+
push(props: A2uiProps): string;
|
|
31
|
+
/** Record a translation loss. */
|
|
32
|
+
note(kind: A2uiDiagnosticKind, subject: string, detail: string): void;
|
|
33
|
+
/** Convert a serialized prefab action into an A2UI action. */
|
|
34
|
+
action(value: unknown, subject: string): A2uiAction | undefined;
|
|
35
|
+
/** Seed a literal value into the surface data model, returning its JSON Pointer. */
|
|
36
|
+
bindData(key: string, value: unknown): string;
|
|
37
|
+
}
|
|
38
|
+
export type Mapper = (node: ComponentJSON, ctx: EmitContext) => A2uiProps | undefined;
|
|
39
|
+
export declare function mapperFor(type: string): Mapper | undefined;
|
|
40
|
+
export declare function isConsumedByParent(type: string): boolean;
|
|
41
|
+
/** Every prefab type with a first-class mapping, for docs and tests. */
|
|
42
|
+
export declare function mappedTypes(): string[];
|
|
43
|
+
/**
|
|
44
|
+
* Last-resort mapping for a type the registry does not name.
|
|
45
|
+
*
|
|
46
|
+
* A node with children becomes a Column, a node with text becomes a Text, and
|
|
47
|
+
* anything else is dropped. This is what keeps a tree built from unmapped
|
|
48
|
+
* components emitting something coherent instead of failing outright.
|
|
49
|
+
*/
|
|
50
|
+
export declare function fallbackMapper(node: ComponentJSON, ctx: EmitContext): A2uiProps | undefined;
|
|
51
|
+
//# 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,MAAM,YAAY,CAAA;AAKpF,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;CAC9C;AAED,MAAM,MAAM,MAAM,GAAG,CAAC,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE,WAAW,KAAK,SAAS,GAAG,SAAS,CAAA;AAybrF,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"}
|