@vantageos/mosaic 0.3.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +88 -2
- package/LICENSE +110 -0
- package/README.md +193 -21
- package/dist/PipelineBoard-FucyGArR.d.cts +759 -0
- package/dist/PipelineBoard-FucyGArR.d.ts +759 -0
- package/dist/PipelineBoard.markdown-DIcvrS-2.d.cts +16 -0
- package/dist/PipelineBoard.markdown-DIcvrS-2.d.ts +16 -0
- package/dist/{StatusBadge.schema-1tOjB4Ir.d.cts → StatusBadge.schema-BEjSH2_4.d.cts} +2 -2
- package/dist/{StatusBadge.schema-1tOjB4Ir.d.ts → StatusBadge.schema-BEjSH2_4.d.ts} +2 -2
- package/dist/{Tabs.schema-BzcEyeq8.d.cts → Tabs.schema-Dqr6vwV3.d.cts} +2 -2
- package/dist/{Tabs.schema-BzcEyeq8.d.ts → Tabs.schema-Dqr6vwV3.d.ts} +2 -2
- package/dist/Timeline-Coo_3tA_.d.cts +114 -0
- package/dist/Timeline-Coo_3tA_.d.ts +114 -0
- package/dist/Timeline.markdown-C6UPDv1H.d.cts +4 -0
- package/dist/Timeline.markdown-C6UPDv1H.d.ts +4 -0
- package/dist/TransactionPreview-BzWDn8kE.d.cts +391 -0
- package/dist/TransactionPreview-BzWDn8kE.d.ts +391 -0
- package/dist/TransactionPreview.markdown-Dpb0VYgN.d.cts +7 -0
- package/dist/TransactionPreview.markdown-Dpb0VYgN.d.ts +7 -0
- package/dist/artifacts.cjs +190 -2
- package/dist/artifacts.cjs.map +1 -1
- package/dist/artifacts.js +190 -2
- package/dist/artifacts.js.map +1 -1
- package/dist/confirmation.cjs +728 -2
- package/dist/confirmation.cjs.map +1 -1
- package/dist/confirmation.d.cts +2 -1
- package/dist/confirmation.d.ts +2 -1
- package/dist/confirmation.js +726 -4
- package/dist/confirmation.js.map +1 -1
- package/dist/display.cjs +1555 -203
- package/dist/display.cjs.map +1 -1
- package/dist/display.d.cts +6 -229
- package/dist/display.d.ts +6 -229
- package/dist/display.js +1539 -206
- package/dist/display.js.map +1 -1
- package/dist/forms.cjs +139 -46
- package/dist/forms.cjs.map +1 -1
- package/dist/forms.d.cts +2 -2
- package/dist/forms.d.ts +2 -2
- package/dist/forms.js +139 -46
- package/dist/forms.js.map +1 -1
- package/dist/host.cjs +822 -0
- package/dist/host.cjs.map +1 -0
- package/dist/host.d.cts +287 -0
- package/dist/host.d.ts +287 -0
- package/dist/host.js +794 -0
- package/dist/host.js.map +1 -0
- package/dist/{index-CwXVgtGb.d.cts → index-BadRcCbm.d.cts} +28 -11
- package/dist/{index-CwXVgtGb.d.ts → index-BadRcCbm.d.ts} +28 -11
- package/dist/index.cjs +2202 -247
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +42 -8
- package/dist/index.d.ts +42 -8
- package/dist/index.js +2167 -251
- package/dist/index.js.map +1 -1
- package/dist/input.d.cts +2 -2
- package/dist/input.d.ts +2 -2
- package/dist/media.cjs +190 -2
- package/dist/media.cjs.map +1 -1
- package/dist/media.d.cts +1 -1
- package/dist/media.d.ts +1 -1
- package/dist/media.js +190 -2
- package/dist/media.js.map +1 -1
- package/dist/preact/artifacts.js +190 -2
- package/dist/preact/artifacts.js.map +1 -1
- package/dist/preact/confirmation.d.ts +321 -1
- package/dist/preact/confirmation.js +629 -4
- package/dist/preact/confirmation.js.map +1 -1
- package/dist/preact/display.d.ts +570 -31
- package/dist/preact/display.js +1248 -126
- package/dist/preact/display.js.map +1 -1
- package/dist/preact/forms.d.ts +32 -15
- package/dist/preact/forms.js +139 -46
- package/dist/preact/forms.js.map +1 -1
- package/dist/preact/host.d.ts +307 -0
- package/dist/preact/host.js +875 -0
- package/dist/preact/host.js.map +1 -0
- package/dist/preact/media.d.ts +37 -1
- package/dist/preact/media.js +423 -0
- package/dist/preact/media.js.map +1 -1
- package/dist/preact/progress.d.ts +92 -1
- package/dist/preact/progress.js +469 -3
- package/dist/preact/progress.js.map +1 -1
- package/dist/progress.cjs +525 -2
- package/dist/progress.cjs.map +1 -1
- package/dist/progress.d.cts +2 -1
- package/dist/progress.d.ts +2 -1
- package/dist/progress.js +522 -3
- package/dist/progress.js.map +1 -1
- package/dist/react/artifacts.cjs +190 -2
- package/dist/react/artifacts.cjs.map +1 -1
- package/dist/react/artifacts.js +190 -2
- package/dist/react/artifacts.js.map +1 -1
- package/dist/react/confirmation.cjs +630 -2
- package/dist/react/confirmation.cjs.map +1 -1
- package/dist/react/confirmation.d.cts +3 -3
- package/dist/react/confirmation.d.ts +3 -3
- package/dist/react/confirmation.js +629 -4
- package/dist/react/confirmation.js.map +1 -1
- package/dist/react/display.cjs +1137 -123
- package/dist/react/display.cjs.map +1 -1
- package/dist/react/display.d.cts +42 -14
- package/dist/react/display.d.ts +42 -14
- package/dist/react/display.js +1122 -126
- package/dist/react/display.js.map +1 -1
- package/dist/react/forms.cjs +139 -46
- package/dist/react/forms.cjs.map +1 -1
- package/dist/react/forms.d.cts +1 -1
- package/dist/react/forms.d.ts +1 -1
- package/dist/react/forms.js +139 -46
- package/dist/react/forms.js.map +1 -1
- package/dist/react/host.cjs +910 -0
- package/dist/react/host.cjs.map +1 -0
- package/dist/react/host.d.cts +24 -0
- package/dist/react/host.d.ts +24 -0
- package/dist/react/host.js +875 -0
- package/dist/react/host.js.map +1 -0
- package/dist/react/input.d.cts +1 -1
- package/dist/react/input.d.ts +1 -1
- package/dist/react/media.cjs +426 -0
- package/dist/react/media.cjs.map +1 -1
- package/dist/react/media.d.cts +19 -1
- package/dist/react/media.d.ts +19 -1
- package/dist/react/media.js +423 -0
- package/dist/react/media.js.map +1 -1
- package/dist/react/progress.cjs +471 -2
- package/dist/react/progress.cjs.map +1 -1
- package/dist/react/progress.d.cts +1 -1
- package/dist/react/progress.d.ts +1 -1
- package/dist/react/progress.js +469 -3
- package/dist/react/progress.js.map +1 -1
- package/dist/server/resource.cjs +151 -0
- package/dist/server/resource.cjs.map +1 -0
- package/dist/server/resource.d.cts +90 -0
- package/dist/server/resource.d.ts +90 -0
- package/dist/server/resource.js +147 -0
- package/dist/server/resource.js.map +1 -0
- package/dist/server.cjs +1100 -25
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +84 -5
- package/dist/server.d.ts +84 -5
- package/dist/server.js +1087 -27
- package/dist/server.js.map +1 -1
- package/dist/tokens.cjs +73 -22
- package/dist/tokens.cjs.map +1 -1
- package/dist/tokens.d.cts +23 -3
- package/dist/tokens.d.ts +23 -3
- package/dist/tokens.js +73 -22
- package/dist/tokens.js.map +1 -1
- package/package.json +250 -231
- package/registry.yaml +51 -2
- package/dist/Alert.schema-LPJE5gFP.d.cts +0 -71
- package/dist/Alert.schema-LPJE5gFP.d.ts +0 -71
- package/dist/ProgressBar.schema-CdVYx0Wq.d.cts +0 -22
- package/dist/ProgressBar.schema-CdVYx0Wq.d.ts +0 -22
- package/dist/{ConfirmDialog-B3CQQGmJ.d.cts → ConfirmDialog-BCtOcmHe.d.cts} +1 -1
- package/dist/{ConfirmDialog-B3CQQGmJ.d.ts → ConfirmDialog-BCtOcmHe.d.ts} +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -9,15 +9,99 @@ Versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
9
9
|
|
|
10
10
|
## [Unreleased]
|
|
11
11
|
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## [0.5.0] — 2026-10-11 — MCP App kit for ChatGPT and Claude (D0)
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
- **Behaviour change — declared secrets never reach `content[]`.** `createMosaicResource` (published `./server`) now strips every field declared in `MOSAIC_NEVER_SERIALISE` from the embedded props BY DEFAULT; pass `includeSecrets: true` to keep the previous behaviour. `createMosaicToolResult` carries a declared secret only in `_meta["mosaic/secrets"]` and throws `MosaicSecretLeakError` (naming the field, never the value) if one appears in `content[]`, or if a declared field does not exist on the view. A `TableView` column flagged `sensitive` is masked in markdown and stripped from the embedded props. `TokenDisplayOnceModal`'s fallback carries label, scope, expiry and an issuer-supplied fingerprint, never the token.
|
|
18
|
+
- **Behaviour notes for the #75 fallbacks.** `openLink` now hands the host the PARSED href, so `https://x.example` is sent as `https://x.example/` (trailing slash; a raw string with an embedded newline can no longer reach the host). The TransactionPreview markdown fallback joins the swap route with `→` instead of `>` (`USDC → WFUSE → FUSE`), because `>` is escaped as markdown. The secret guard in `createMosaicToolResult` compares case-folded and NFKC-normalised text on both sides.
|
|
19
|
+
- **Gate 4 script fail-closed** (`scripts/cross-runtime-subpath-coverage-check.py`): exit 2 naming the input for any unreadable input (package root, `package.json`, registry, built entry, empty category set, a registry that yields no categories or has no `components` list, or the PyYAML and built-in readers disagreeing) and exit 1 only for a real coverage gap; the default `--package-root` is the package the script lives in, not the working directory; the registry cross-check no longer skips without PyYAML (built-in reader) or with a missing registry (`--skip-registry-check` is the explicit opt-out).
|
|
20
|
+
- **MCP Apps views and host layer, delivery 2 (task k17ehg71z31ec50fkh95p3xxr58fjm98; Eta corrections k178bt8enj99wv1gtc8h3315kx8g0w13).**
|
|
21
|
+
- **Views** (React + Preact barrels, FR+EN, Zod, Skeleton loading, `{}` parses as an empty state, A-1 markdown): `StatCard` (R08) and `BalanceCard` (R09, Fuse balance, exact decimal strings) in `display`; `MessageFeed` (R03, read-only, plain text, safe links) and `PipelineBoard` (R06, read-only, fullscreen board / inline summary, stage filter chips) in `display`; `Timeline` (R02) in `progress`; `TransactionPreview` (R11, prepare-only, swap-quote variant, **no sign / send / approve control**, "NOT SIGNED - preparation only") in `confirmation`.
|
|
22
|
+
- **`TableView` extended** (R01 / R10, every new prop optional): sortable columns with `aria-sort`, `single` / `multiple` selection (`onSelectionChange` rows + keys), sticky header, compact density, column `align` / `width`, `amount` (exact decimal string compare) and `icon` cell kinds, `loading` Skeleton, serialisable `rows` in the schema.
|
|
23
|
+
- **`RadioGroup` / `MultiSelect`** (R25): `appearance` `segmented` | `chips` (RadioGroup) and `chips` (MultiSelect: visible toggle buttons, `aria-pressed`, no dropdown).
|
|
24
|
+
- **Host layer** (`./host`, `./react/host`, `./preact/host`): safe-area insets (H01), host style variables bridged onto mosaic-tokens + host fonts + transparent background (H02), `sendMessage` / `openLink` helpers that refuse what the host cannot honour (H04, H18), typed model-context blocks + `openai/modelContext` read + `selectionModelContext` (H03), hooks `useMosaicHostLayout`, `useSendMessage`, `useOpenLink`.
|
|
25
|
+
- **Server**: `buildMcpAppResource({ visibility, hostFonts })` (H05); `createMosaicToolResult` returning `content: [text, ui:// resource]` (A-1) and a `<name>ToMarkdown` for all 12 components (H17). `createMosaicResource` now supports 12 components, honours its `uri` and `markdownFallback` options, and `_meta.ui.fallback` (kept: published contract) carries the data instead of a title and note.
|
|
26
|
+
- **Adapter**: `startSizeReporting` / `postSizeChanged` send `ui/notifications/size-changed` from the raw adapter (H15).
|
|
27
|
+
- **Fix — host-context dispatcher** (Eta #74 re-gate): a foreign handler that overwrites `app.onhostcontextchanged` while subscribers are live is adopted as `previous` and the dispatcher reinstalled on the next subscribe; resubscribe-after-full-unsubscribe is pinned by a test that goes RED when `dispatchers.delete(app)` is removed.
|
|
28
|
+
- **MCP Apps host layer for ChatGPT and Claude (task k17ehg71z31ec50fkh95p3xxr58fjm98, items 1-2).** New subpaths `./host` (framework-agnostic core: host theme/display mode/locale/container dimensions, `openai/deepLink` when present, `requestDisplayMode` limited to inline | fullscreen with a typed AND runtime refusal of `pip` for a ChatGPT host, `updateModelContext` over `ui/update-model-context`, host theme mapped onto mosaic-tokens `data-theme`), `./react/host` and `./preact/host` (hooks over the core) and `./server/resource` (`buildMcpAppResource`: pure, no React/DOM; `_meta.ui` standard keys first with the four csp arrays explicit, `domain` derived from `servedUrl` for Claude, `openai/*` keys only when passed: `_meta["openai/ui"]` display modes on the resource, `openai/outputTemplate` and `openai/ui` entrypoints on the tool; deepLink typed as `{ url }`; ChatGPT detected from `openai/*` keys, no user-agent sniffing). Composes with ext-apps `registerAppResource`/`registerAppTool`, which pass `_meta` through. No new dependency: the ext-apps `App` is typed structurally.
|
|
29
|
+
- **Fix — `react/media` and `preact/media` were empty barrels; Gate 4 passed anyway.** Both now re-export `StatusBadge` (+ props type, schema, validator) from the existing `display` components (display exports kept, no new component), and Gate 4 now fails any runtime subpath entry whose built `.js` or `.d.ts` exports zero symbols, naming the entry (`exports-zero-symbols`).
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## [0.4.0] — 2026-10-04
|
|
34
|
+
|
|
12
35
|
### Added
|
|
36
|
+
- **Badge primitive, cross-runtime.** `Badge` is exported from `./display`, `./react/display` and
|
|
37
|
+
`./preact/display`, with its schema, stories, i18n strings and a 205-line React test. Landed on
|
|
38
|
+
`main` in #61 against `target 0.3.2` and unpublished until this release, so no consumer could
|
|
39
|
+
import it.
|
|
40
|
+
- **`docs/GA-RELEASE-V0.3.1.md`** — the canonical release procedure (bilingual EN+FR): the five
|
|
41
|
+
fail-closed CI gate jobs, the `ETA_APPROVED_TASK_ID` approval hook, the
|
|
42
|
+
`prepublishOnly`/`postpublish` workspace-rewrite pattern, the 0.3.0 → 0.3.1 incident and its
|
|
43
|
+
lesson, the cross-runtime architecture and the migration guide. Written for 0.3.1 and itself
|
|
44
|
+
unpublished until now, which is why this release follows it rather than a recalled procedure.
|
|
45
|
+
|
|
46
|
+
### Documentation
|
|
47
|
+
- **The package README was frozen at 0.3.1 and is rewritten against the built artifact.**
|
|
48
|
+
It told a consumer to `npm install @vantageos/mosaic@^0.2.0 @vantageos/mosaic-tokens@^0.2.0`,
|
|
49
|
+
neither of which is what ships. Corrected to the versions actually published.
|
|
50
|
+
- **Six sentences claiming form primitives were still unshipped are deleted.** Each had
|
|
51
|
+
been appended as a primitive landed and never removed, so each sat directly above a
|
|
52
|
+
table row documenting the very primitive it called missing. All of Input, Textarea,
|
|
53
|
+
Select, Checkbox, MultiSelect, RadioGroup and FieldArray are exported — read from
|
|
54
|
+
`dist/react/forms.d.ts`, not from the prose.
|
|
55
|
+
- **A derived per-subpath export inventory replaces a partial list that read as complete.**
|
|
56
|
+
It records that `media` exports no components although it is one of the seven categories
|
|
57
|
+
gated for cross-runtime parity.
|
|
58
|
+
- **Bundle sizes are the `size-limit` output with their gates**, replacing figures for
|
|
59
|
+
surfaces the gate no longer measures.
|
|
60
|
+
- **The changelog link pointed at the repo root**, which is not the file the tarball
|
|
61
|
+
carries; it now points at this one.
|
|
62
|
+
- **The README stated MIT while `package.json` carried no `license` field** and `files`
|
|
63
|
+
shipped no LICENSE, so every version up to 0.3.1 reached consumers with no licence terms
|
|
64
|
+
at all.
|
|
65
|
+
|
|
66
|
+
### Added — licence
|
|
67
|
+
- **`FSL-1.1-Apache-2.0` is now declared and shipped.** `package.json` carries the
|
|
68
|
+
`license` field, `LICENSE` is in `files`, and the file is byte-identical to the one every
|
|
69
|
+
sibling `@vantageos` package ships
|
|
70
|
+
(sha256 `3d458972e6e84e5d2361a886ef64b07aefdc38dd8955e281ea8c2ae8849646a4`). Verified
|
|
71
|
+
against what the registry serves for `mosaic-blocks`, `mosaic-tokens` and `mcp-doctor` —
|
|
72
|
+
this package was the only one of the four publishing `license: NONE`. Nothing about the
|
|
73
|
+
terms is new; they were simply never attached to this package.
|
|
74
|
+
|
|
75
|
+
### Changed
|
|
76
|
+
- **`@vantageos/mosaic-tokens` moves from `^0.2.0` to `^0.7.0`** in the published manifest. This is
|
|
77
|
+
why the release is `0.4.0` and not the `0.3.2` the source commit targeted: `^0.2.0` does **not**
|
|
78
|
+
satisfy `0.7.0` (a caret on a `0.x` range pins the minor), so a consumer upgrading receives a
|
|
79
|
+
five-minor jump in a runtime dependency. On a `0.x` package the minor is the only available
|
|
80
|
+
signal for that, and a patch number would have understated it.
|
|
81
|
+
|
|
82
|
+
The range was never edited by hand — the manifest carries `workspace:*` and `prepublishOnly`
|
|
83
|
+
resolves it to whatever the sibling package is at, which is now `0.7.0`. That is correct
|
|
84
|
+
behaviour and it is precisely why the published version has to be derived from the packed
|
|
85
|
+
tarball rather than from the commit that said `target 0.3.2`.
|
|
86
|
+
|
|
87
|
+
### Note on this release
|
|
88
|
+
Nothing else changed in the source. `latest` served `0.3.1` from 2026-06-13 until this version, so
|
|
89
|
+
the items above are the entire delta a consumer receives — derived by locating the commit that set
|
|
90
|
+
the version to `0.3.1` and listing what touched `packages/mosaic` after it, not by reading a date
|
|
91
|
+
window (a date window includes the release commits themselves and reported 19).
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
### Recorded late — shipped by 0.4.0 at the latest, never listed in a release section
|
|
95
|
+
|
|
96
|
+
These entries sat under `[Unreleased]` after their code had shipped. Each one's commit is an ancestor of the 0.4.0 release commit `12475a6` (`git merge-base --is-ancestor <sha> 12475a6`).
|
|
97
|
+
|
|
13
98
|
- **D-PR1 — Pre-publish dry-run evidence for v0.3.0 GA.** New doc `docs/D-PR1-PRE-PUBLISH-DRY-RUN-V0.3.0.md` (bilingual EN+FR) capturing the hard-evidence pre-publish gate run in a fresh sandbox worktree off `origin/main` @ `7ae5450`: sandbox build-pass (RULE #19, `SANDBOX_BUILD_PASS_ID=7ae5450`, build exit 0), Gate 1 build-parity (exit 0), `npm pack --dry-run` (150 files / 511.8 kB / unpacked 3.0 MB / version 0.3.0 / sha `31caed2f`, CHANGELOG + README + package.json + registry.yaml + full `dist/` surface present — **no real publish**), corrected vendored cross-runtime subpath coverage gate (`--ga-mode`, exit 0, 0 missing), and the full gate set re-run green (tsc, biome, vitest 854, playwright-axe 29, size-limit, registry-drift, storybook-test 103, Gate 2 peer-resolution, Gate 3 coherence 10). Documents the **D-T1 blocker**: the canonical B-PR1 skill / B-PR2 publish hook carry a category-prefixed layout defect (`./forms/react`) vs Mosaic's runtime-prefixed layout (`./react/forms`) and **false-block** the real publish — must be fixed before `tag v0.3.0` (Sigma task `k176e5rpz`); plus `ETA_APPROVED_TASK_ID` must be set after Eta approval. Mission `k57b6d1b` · task `k177e1wr`. No source/build/gate code changed — docs-only.
|
|
14
99
|
- **CI Gate 4 — Cross-runtime subpath coverage (B-PR3).** New fail-fast CI gate asserting that **every bare component category** in `packages/mosaic/package.json` `exports` (`./forms`, `./progress`, `./display`, `./artifacts`, `./confirmation`, `./media`, `./input`) also exports a **non-empty** `dist` artifact under **both** `./react/<cat>` and `./preact/<cat>`. This is the gate that would have caught the original v0.3.0 GA blocker (foundation components present as bare exports but missing/empty under `/react` + `/preact`).
|
|
15
100
|
- New vendored script `packages/mosaic/scripts/cross-runtime-subpath-coverage-check.py` — vendored from the canonical B-PR1 skill `mosaic-cross-runtime-subpath-coverage-check` (VantageRegistry; PR #20). Stdlib-only, with an optional PyYAML registry cross-check that degrades gracefully when PyYAML is absent (no Python dependency added to CI). Carries one documented deviation: a `RUNTIME_PREFIXED` toggle adapting the canonical category-prefixed layout (`./forms/react`) to this repo's runtime-prefixed layout (`./react/forms`).
|
|
16
101
|
- New job `cross-runtime-subpath-coverage` (`needs: build-parity-cross-runtime`) builds tokens + mosaic so `dist/` exists, then runs `python3 .../cross-runtime-subpath-coverage-check.py --package-root packages/mosaic --ga-mode` (exit 1 fails CI with a `component × runtime` diagnostic). CI-side equivalent of the B-PR2 npm-publish hook.
|
|
17
102
|
- New doc `docs/CROSS-RUNTIME-GATE.md` (bilingual EN+FR). Additive change — no existing gate (Gate 1 build-parity, Gate 2 peerDeps smoke, Gate 3 coherence, `ci` job) weakened or replaced. Mission `k57b6d1b` · task `k176pzsszyy4v3f505khwg33gx88j36n`.
|
|
18
|
-
- Wave 3 components TBD (DatePicker, Avatar, FilterChip, Pagination — demand-driven T21+).
|
|
19
103
|
|
|
20
|
-
|
|
104
|
+
#### Fixed
|
|
21
105
|
- CI Gate 2 (PeerDeps optionality smoke) now runs GREEN (unblocks v0.3.0 GA publish gate). Two layered bugs, both packaging-scope:
|
|
22
106
|
- **Build (tsup):** the preact runtime bundles that re-export the shared React implementation (`preact/progress`, `preact/input`, `preact/confirmation`, `preact/forms`) shipped `import … from "react/jsx-runtime"` and `import … from "react"`. `esbuildOptions.alias` (`react → preact/compat`) never fired because tsup auto-externalises peerDeps (`react`, `react/jsx-runtime`) *before* alias resolution, so the alias was a no-op for those specifiers. A react-only consumer (which has react) could therefore resolve `@vantageos/mosaic/preact/*` even with preact absent — optionality broken in both directions. Fix: replaced the alias with an esbuild `onResolve` plugin (`mosaic-react-to-preact`) that deterministically rewrites the whole react family (`react`, `react-dom`, `react-dom/client`, `react/jsx-runtime`, `react/jsx-dev-runtime`) to their preact equivalents and marks them external; paired with `noExternal: [/^react…/]` on the preact pass so tsup's own external plugin returns undefined for the react family and lets the rewrite run. Added `preact/jsx-runtime` to `PREACT_EXTERNAL`. Preact bundles now import only preact specifiers; react bundles unchanged.
|
|
23
107
|
- **Smoke fixture (run-smoke.sh):** the fixtures installed mosaic via `npm install file:../../../packages/mosaic`, which npm symlinks into the monorepo source tree; Node then resolved the bundle's runtime imports by climbing out of the fixture into the monorepo root `node_modules` (where both react and preact are hoisted devDeps), producing a false PASS. Rewrote the driver to model a real npm consumer faithfully: `pnpm pack` both packages (rewriting the `workspace:*` tokens dep to a concrete version) and install the tarballs into an isolated `mktemp -d` consumer outside the repo tree, with `--legacy-peer-deps` so npm does not auto-install the *transitive* peer react pulled by `@tanstack/react-virtual` into a preact-only consumer. Fixture assertions (`index.mjs`) untouched. Smoke now PASSES: react-only resolves `react/*` and fails `preact/*`; preact-only resolves `preact/*` and fails `react/*`.
|
|
@@ -28,6 +112,8 @@ Versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
28
112
|
|
|
29
113
|
---
|
|
30
114
|
|
|
115
|
+
---
|
|
116
|
+
|
|
31
117
|
## [0.3.1] — 2026-06-13 — hotfix: workspace:* leak in published 0.3.0 manifest (Path B — root-cause fix)
|
|
32
118
|
|
|
33
119
|
### Fixed
|
package/LICENSE
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
Functional Source License, Version 1.1, Apache 2.0 Future License
|
|
2
|
+
|
|
3
|
+
Abbreviation
|
|
4
|
+
|
|
5
|
+
FSL-1.1-Apache-2.0
|
|
6
|
+
|
|
7
|
+
Notice
|
|
8
|
+
|
|
9
|
+
Copyright 2026 VantageOS (ElPi Corp)
|
|
10
|
+
|
|
11
|
+
Terms and Conditions
|
|
12
|
+
|
|
13
|
+
Licensor: VantageOS (ElPi Corp)
|
|
14
|
+
|
|
15
|
+
Licensed Work: VantagePeers
|
|
16
|
+
The Licensed Work is (c) 2026 VantageOS (ElPi Corp)
|
|
17
|
+
|
|
18
|
+
Additional Use Grant: You may make production use of the Licensed Work,
|
|
19
|
+
provided Your use does not include offering the Licensed
|
|
20
|
+
Work to third parties as a hosted or managed service
|
|
21
|
+
where the service provides users with access to any
|
|
22
|
+
substantial set of the features or functionality of the
|
|
23
|
+
Licensed Work.
|
|
24
|
+
|
|
25
|
+
Change Date: 2028-04-03 (two years from publication)
|
|
26
|
+
|
|
27
|
+
Change License: Apache License, Version 2.0
|
|
28
|
+
|
|
29
|
+
For information about alternative licensing arrangements for the Licensed Work,
|
|
30
|
+
please contact: contact@vantageos.com
|
|
31
|
+
|
|
32
|
+
License text below is provided for informational purposes only.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
Functional Source License, Version 1.1, Apache 2.0 Future License
|
|
37
|
+
|
|
38
|
+
1. Purpose
|
|
39
|
+
|
|
40
|
+
This license gives you broad permission to use, modify, and share this
|
|
41
|
+
software, with one important condition: you may not use it to compete with us.
|
|
42
|
+
|
|
43
|
+
2. Acceptance
|
|
44
|
+
|
|
45
|
+
To use the software, you must agree to these terms. If you do not agree, you
|
|
46
|
+
may not use the software.
|
|
47
|
+
|
|
48
|
+
3. Copyright License
|
|
49
|
+
|
|
50
|
+
The licensor grants you a non-exclusive, royalty-free, worldwide, non-
|
|
51
|
+
sublicensable, non-transferable license to use, copy, distribute, make
|
|
52
|
+
available, and prepare derivative works of the software, in each case subject
|
|
53
|
+
to the limitations below.
|
|
54
|
+
|
|
55
|
+
4. Limitations
|
|
56
|
+
|
|
57
|
+
You may not make the functionality of the software available to third parties
|
|
58
|
+
as a service, or otherwise use the software to provide a service to third
|
|
59
|
+
parties that competes with the licensor.
|
|
60
|
+
|
|
61
|
+
5. Patents
|
|
62
|
+
|
|
63
|
+
The licensor grants you a license, under any patent claims the licensor can
|
|
64
|
+
license or becomes able to license, to make, have made, use, sell, offer for
|
|
65
|
+
sale, import, and have imported the software, in each case subject to the
|
|
66
|
+
limitations and conditions in this license.
|
|
67
|
+
|
|
68
|
+
6. Fair Use
|
|
69
|
+
|
|
70
|
+
This license is not intended to limit any rights you may have under applicable
|
|
71
|
+
fair use or other laws.
|
|
72
|
+
|
|
73
|
+
7. No Other Rights
|
|
74
|
+
|
|
75
|
+
These terms do not grant any other rights. The licensor reserves all rights not
|
|
76
|
+
expressly granted.
|
|
77
|
+
|
|
78
|
+
8. Termination
|
|
79
|
+
|
|
80
|
+
Your license is automatically terminated if you violate the terms. However, if
|
|
81
|
+
you cure the violation within 30 days of discovering it, your license is
|
|
82
|
+
reinstated retroactively.
|
|
83
|
+
|
|
84
|
+
9. Disclaimer
|
|
85
|
+
|
|
86
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
87
|
+
IMPLIED.
|
|
88
|
+
|
|
89
|
+
10. Limitation of Liability
|
|
90
|
+
|
|
91
|
+
TO THE EXTENT PERMITTED BY LAW, THE LICENSOR IS NOT LIABLE FOR ANY DAMAGES
|
|
92
|
+
ARISING FROM THE USE OF THE SOFTWARE.
|
|
93
|
+
|
|
94
|
+
11. Change Date and License
|
|
95
|
+
|
|
96
|
+
After the Change Date, the licensor grants you the rights under the Change
|
|
97
|
+
License.
|
|
98
|
+
|
|
99
|
+
12. Definitions
|
|
100
|
+
|
|
101
|
+
"Compete" means providing a product or service that is substantially similar
|
|
102
|
+
to, or a replacement for, all or a significant portion of the Licensed Work.
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
Apache License, Version 2.0
|
|
107
|
+
|
|
108
|
+
After the Change Date (2028-04-03), this software will be available under the
|
|
109
|
+
Apache License, Version 2.0. See https://www.apache.org/licenses/LICENSE-2.0
|
|
110
|
+
for full text.
|
package/README.md
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
# @vantageos/mosaic
|
|
2
2
|
|
|
3
|
-
Fleet-wide MCP UI design system. Zod-validated, taxonomy-organized (
|
|
3
|
+
Fleet-wide MCP UI design system. Zod-validated, taxonomy-organized (7 categories: artifacts, confirmation, display, forms, input, media, progress), streaming-ready, **cross-runtime React 19 + Preact 10**. Built for MCP Apps (SEP-1865 extension).
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
7
7
|
```sh
|
|
8
8
|
# React 19
|
|
9
|
-
npm install @vantageos/mosaic@^0.
|
|
9
|
+
npm install @vantageos/mosaic@^0.5.0 @vantageos/mosaic-tokens@^0.7.0 react react-dom
|
|
10
10
|
|
|
11
11
|
# Preact 10
|
|
12
|
-
npm install @vantageos/mosaic@^0.
|
|
12
|
+
npm install @vantageos/mosaic@^0.5.0 @vantageos/mosaic-tokens@^0.7.0 preact
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
All runtime peers are marked optional via `peerDependenciesMeta` — install only what your runtime needs.
|
|
@@ -32,19 +32,22 @@ This constraint is codified locally via the `build` script (the `NODE_OPTIONS` p
|
|
|
32
32
|
|---|---|---|
|
|
33
33
|
| `@vantageos/mosaic` | React 19 (back-compat) | v0.1.x consumers (Sigma VP, Theta CRM) |
|
|
34
34
|
| `@vantageos/mosaic/<cat>` | React 19 (back-compat) | Tree-shakable category imports v0.1.x style |
|
|
35
|
-
| `@vantageos/mosaic/react` | React 19 |
|
|
35
|
+
| `@vantageos/mosaic/react` | React 19 | React consumers — explicit runtime opt-in (the preferred surface since v0.2.0) |
|
|
36
36
|
| `@vantageos/mosaic/react/<cat>` | React 19 | Tree-shakable category imports under explicit react/ prefix |
|
|
37
37
|
| `@vantageos/mosaic/preact` | Preact 10 | Mu vantage-bridge iframe, Chi gptpowerups (LLM-host target) |
|
|
38
38
|
| `@vantageos/mosaic/preact/<cat>` | Preact 10 | Tree-shakable category imports under preact/ prefix |
|
|
39
39
|
| `@vantageos/mosaic/tokens` | runtime-free | Re-export of `@vantageos/mosaic-tokens` |
|
|
40
40
|
| `@vantageos/mosaic/server` | Node | `createMosaicResource()` MCP UI builder (runtime-agnostic) |
|
|
41
|
+
| `@vantageos/mosaic/server/resource` | Node | `buildMcpAppResource()` MCP Apps `_meta` helper (pure, no React, no DOM) |
|
|
42
|
+
| `@vantageos/mosaic/host` | runtime-free | Host-context core (theme, display mode, locale, model context) |
|
|
43
|
+
| `@vantageos/mosaic/react/host` · `/preact/host` | React 19 · Preact 10 | Hooks over the host-context core |
|
|
41
44
|
|
|
42
45
|
`<cat>` = `progress` | `input` | `display` | `artifacts` | `confirmation` | `media`.
|
|
43
46
|
|
|
44
47
|
## Quick start
|
|
45
48
|
|
|
46
49
|
```tsx
|
|
47
|
-
// React 19 — preferred
|
|
50
|
+
// React 19 — the preferred runtime-explicit surface
|
|
48
51
|
import { ProgressBar } from "@vantageos/mosaic/react/progress";
|
|
49
52
|
import { ConfirmDialog } from "@vantageos/mosaic/react/confirmation";
|
|
50
53
|
import "@vantageos/mosaic-tokens/css"; // declares --mosaic-* vars on :root
|
|
@@ -64,7 +67,7 @@ export function MyComponent({ progress, label }: { progress: number; label: stri
|
|
|
64
67
|
}
|
|
65
68
|
```
|
|
66
69
|
|
|
67
|
-
## Forms
|
|
70
|
+
## Forms
|
|
68
71
|
|
|
69
72
|
`@vantageos/mosaic/{react,preact}/forms` — composite form primitives wrapping `react-hook-form` + `@hookform/resolvers/zod`. Default validation mode is `onBlur` (Chi co-validated, Day 102 DM). Cross-runtime: same imports, React 19 path or Preact 10 path.
|
|
70
73
|
|
|
@@ -130,17 +133,14 @@ export function SignupForm({ onSubmit }: { onSubmit: (data: z.infer<typeof schem
|
|
|
130
133
|
| `<SubmitButton label="..." loadingLabel="..." />` | Bound to the surrounding `FormProvider`. Disabled while invalid OR submitting. |
|
|
131
134
|
| `<Input name="..." type="text\|email\|password\|number\|url" label="..." placeholder? disabled? autoComplete? />` | Single-field `<input>` bound to the surrounding `FormProvider`. `label` is required (consumer-driven i18n). Emits `aria-invalid` + `aria-describedby` on validation error. |
|
|
132
135
|
|
|
133
|
-
Field primitives (Textarea, Select, Checkbox, MultiSelect, RadioGroup, FieldArray) land in T12-T20 — see `docs/v0.3.0-plan.md` §7.
|
|
134
136
|
| `<Textarea name="..." rows? maxLength? autoResize? placeholder? disabled? label? />` | Multi-line text input field primitive. `rows` default 3, `maxLength` enforced via shared logic gate, optional `autoResize` grows to content. `aria-invalid` + `aria-describedby` on error. |
|
|
135
137
|
|
|
136
|
-
Remaining field primitives (Input shipped T11, Select, Checkbox, MultiSelect, RadioGroup, FieldArray) land in T13-T20 — see `docs/v0.3.0-plan.md` §7.
|
|
137
138
|
| `useFieldArray({ name, control? })` | Thin wrapper around RHF's `useFieldArray`. Returns `{ fields, append, remove, move, swap }` + the rest of RHF's native return for advanced cases. Reads `control` from `FormProvider` when omitted. |
|
|
138
139
|
| `<FieldArray name="...">{({ field, index }, { append, remove, move, swap, fields }) => ...}</FieldArray>` | Render-prop wrapper around `useFieldArray`. Emits `role="list"` shell + `role="listitem"` per row, keyed by RHF's stable `field.id` (NOT array index). Powers PromptForm Add Variable, Hermes variable mappings, Demeter filter chips. |
|
|
139
140
|
|
|
140
141
|
| `<Checkbox name="..." label="..." indeterminate? description? disabled? />` | Boolean checkbox primitive. `indeterminate=true` → `aria-checked="mixed"` + DOM `.indeterminate=true` via ref. `description` wired via `aria-describedby`. `aria-invalid` + `aria-describedby` on error. |
|
|
141
142
|
| `<RadioGroup name="..." label="..." options={[...]} orientation? disabled? />` | WCAG-AA radiogroup. Roving tabIndex, Arrow key selection sync, Home/End, Space/Enter. |
|
|
142
143
|
|
|
143
|
-
Remaining field primitives (Input, Textarea, Select, MultiSelect) land in T11-T15 + T18-T20 — see `docs/v0.3.0-plan.md` §7.
|
|
144
144
|
|
|
145
145
|
### RadioGroup
|
|
146
146
|
|
|
@@ -191,13 +191,10 @@ export function PlanSelector() {
|
|
|
191
191
|
- `aria-disabled` on disabled options; disabled options skipped in arrow nav
|
|
192
192
|
- `aria-orientation` reflects `orientation` prop
|
|
193
193
|
|
|
194
|
-
Field primitives (Textarea, Select, MultiSelect, RadioGroup, FieldArray) land in T12-T20 — see `docs/v0.3.0-plan.md` §7.
|
|
195
194
|
| `<MultiSelect name="..." label="..." options={...} placeholder? disabled? searchable? maxItems? />` | Multi-value dropdown. RHF value is `string[]`. Selected items render as removable chips (Backspace/Delete on trigger removes last, per-chip × removes specific). WCAG-AA combobox (`role=combobox aria-multiselectable=true`), Arrow/Enter keyboard nav, optional case-insensitive search, optional `maxItems` cap. |
|
|
196
195
|
|
|
197
|
-
Remaining field primitives (Input + Textarea + MultiSelect shipped T11/T12/T15; Select, Checkbox, RadioGroup, FieldArray) land in T13-T20 — see `docs/v0.3.0-plan.md` §7.
|
|
198
196
|
| `<Select name="..." label="..." options={[...]} />` | Single-select dropdown (combobox+listbox APG). Optional `searchable` prop enables in-popup filter. Full keyboard nav + type-ahead. WCAG-AA strict. |
|
|
199
197
|
|
|
200
|
-
Field primitives (Input, Textarea, Checkbox, MultiSelect, RadioGroup, FieldArray) land in T11, T14-T20 — see `docs/v0.3.0-plan.md` §7.
|
|
201
198
|
|
|
202
199
|
|
|
203
200
|
|
|
@@ -214,10 +211,163 @@ const resource = createMosaicResource({
|
|
|
214
211
|
```
|
|
215
212
|
|
|
216
213
|
|
|
214
|
+
## MCP Apps host layer (ChatGPT and Claude)
|
|
215
|
+
|
|
216
|
+
Standard MCP Apps keys come first; `openai/*` keys are strictly additive. A view built
|
|
217
|
+
on this layer works with no `openai` key at all, and never requests `pip` for ChatGPT.
|
|
218
|
+
`@modelcontextprotocol/ext-apps` is **not** a dependency: the core types the `App`
|
|
219
|
+
structurally, so any `App` instance fits.
|
|
220
|
+
|
|
221
|
+
### Resource helper (server, pure)
|
|
222
|
+
|
|
223
|
+
```ts
|
|
224
|
+
import { buildMcpAppResource } from "@vantageos/mosaic/server/resource";
|
|
225
|
+
|
|
226
|
+
const { resource, toolMeta } = buildMcpAppResource({
|
|
227
|
+
uri: "ui://mosaic/tasks",
|
|
228
|
+
html, // your bundled single-file view
|
|
229
|
+
csp: { connectDomains: ["https://api.example.com"] }, // the 4 arrays are always emitted
|
|
230
|
+
servedUrl: "https://example.com/mcp", // Claude `ui.domain` is DERIVED from it, never typed
|
|
231
|
+
prefersBorder: true,
|
|
232
|
+
openai: { outputTemplate: "ui://mosaic/tasks", preferredDisplayMode: "inline" }, // optional
|
|
233
|
+
});
|
|
234
|
+
// resource._meta = { ui: { csp, prefersBorder, domain }, "openai/ui"?: { availableDisplayModes?, preferredDisplayMode? } }
|
|
235
|
+
// toolMeta = { ui: { resourceUri }, "openai/outputTemplate"?, "openai/ui"?: { entrypoints } }
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
`domain` is `{sha256(servedUrl) first 32 hex}.claudemcpcontent.com` and is absent when
|
|
239
|
+
`servedUrl` is not given. `openai.availableDisplayModes` / `preferredDisplayMode` accept
|
|
240
|
+
`inline` | `fullscreen` only; `pip` throws.
|
|
241
|
+
|
|
242
|
+
It composes with `@modelcontextprotocol/ext-apps/server`: `registerAppResource` and
|
|
243
|
+
`registerAppTool` pass `_meta` through (they only default the MIME type and back-fill the
|
|
244
|
+
deprecated flat `ui/resourceUri`), so feed them `resource._meta` and `toolMeta`; this helper adds
|
|
245
|
+
the csp defaults, the derived Claude `domain` and the additive `openai/*` keys they do not produce.
|
|
246
|
+
|
|
247
|
+
### Host context (view)
|
|
248
|
+
|
|
249
|
+
```tsx
|
|
250
|
+
import { useMosaicHostTheme, useRequestDisplayMode, useUpdateModelContext } from "@vantageos/mosaic/react/host";
|
|
251
|
+
// Preact: the same names from "@vantageos/mosaic/preact/host"
|
|
252
|
+
|
|
253
|
+
const ctx = useMosaicHostTheme(app); // theme, displayMode, locale, containerDimensions, deepLink
|
|
254
|
+
const goFullscreen = useRequestDisplayMode(app); // "inline" | "fullscreen"; pip refused for ChatGPT
|
|
255
|
+
const tellModel = useUpdateModelContext(app); // ui/update-model-context
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
`ctx.theme` is mapped onto mosaic-tokens (`data-theme` light/dark, applied to `<html>`).
|
|
259
|
+
`ctx.deepLink` reads `hostContext["openai/deepLink"]` (`{ url }`) when present and is `undefined`
|
|
260
|
+
otherwise. ChatGPT is detected from `openai/*` keys in the host context or experimental host
|
|
261
|
+
capabilities (the spec defines no host-identification field; no user-agent sniffing). Framework-free equivalents (`readHostContext`, `requestDisplayMode`,
|
|
262
|
+
`updateModelContext`, `subscribeHostContext`, `applyMosaicTheme`) live in
|
|
263
|
+
`@vantageos/mosaic/host`.
|
|
264
|
+
|
|
265
|
+
### Host layout, messages and links (view)
|
|
266
|
+
|
|
267
|
+
```tsx
|
|
268
|
+
import { useMosaicHostLayout, useSendMessage, useOpenLink } from "@vantageos/mosaic/react/host";
|
|
269
|
+
|
|
270
|
+
useMosaicHostLayout(app); // data-theme + safe-area padding + host style variables + host fonts
|
|
271
|
+
const send = useSendMessage(app); // ui/message: await send("Show the overdue tasks")
|
|
272
|
+
const open = useOpenLink(app); // ui/open-link: await open("https://wallet.example/swap?q=1")
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
* **Safe-area insets** (`hostContext.safeAreaInsets`, MCP Apps spec): applied as root padding and as
|
|
276
|
+
`--mosaic-safe-area-<side>` variables (for `scroll-padding`).
|
|
277
|
+
* **Host style variables** (`hostContext.styles.variables`, 76 standardized keys) are written on the
|
|
278
|
+
root and bridged onto the mosaic-tokens custom properties they correspond to (`HOST_TO_MOSAIC_TOKENS`);
|
|
279
|
+
variables the host does not pass leave the mosaic-tokens defaults untouched. Host fonts
|
|
280
|
+
(`styles.css.fonts`) are injected once; add the Claude font origin to `csp.resourceDomains` with
|
|
281
|
+
`buildMcpAppResource({ hostFonts: true })`. `applyTransparentBackground(document)` sets html/body to
|
|
282
|
+
`transparent` (Claude transparent theming).
|
|
283
|
+
* **`sendMessage`**: options `{ target, send }` need the host to advertise `openai/message` and a
|
|
284
|
+
non-mobile platform; otherwise it THROWS rather than silently dropping `send: false`.
|
|
285
|
+
* **`openLink`**: http(s) only; the host's denial reason is thrown (`HostRequestError`).
|
|
286
|
+
* **Typed model context**: `textBlock(text, { title, thumbnail, background })` builds blocks with
|
|
287
|
+
`_meta["openai/title"]`, `_meta["openai/thumbnail"]` and `annotations.audience: ["assistant"]`;
|
|
288
|
+
`selectionModelContext(rows, columns, locale)` turns a table selection into one titled block (feed it
|
|
289
|
+
to `updateModelContext` from `onSelectionChange`); `hostContext["openai/modelContext"]` is read into
|
|
290
|
+
`ctx.modelContext` (`null` = cleared by the user).
|
|
291
|
+
* **Tool visibility**: `buildMcpAppResource({ visibility: ["app"] })` emits `_meta.ui.visibility`
|
|
292
|
+
(omitted = the spec default `["model", "app"]`).
|
|
293
|
+
* **Size reporting**: a view that talks to the host through the raw adapter calls
|
|
294
|
+
`startSizeReporting()` (`ui/notifications/size-changed` through a ResizeObserver). The ext-apps `App`
|
|
295
|
+
does this itself with `autoResize`.
|
|
296
|
+
|
|
297
|
+
### Tool results with an A-1 markdown fallback (server)
|
|
298
|
+
|
|
299
|
+
```ts
|
|
300
|
+
import { createMosaicToolResult } from "@vantageos/mosaic/server";
|
|
301
|
+
|
|
302
|
+
return createMosaicToolResult("PipelineBoard", { stages, currency: "EUR" }, "en");
|
|
303
|
+
// { content: [ { type: "text", text: "# Pipeline\n\n| Stage | Deals | Total | ..." },
|
|
304
|
+
// { type: "resource", resource: { uri: "ui://mosaic/pipelineboard", ... } } ] }
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
The text block carries the view's DATA (App standard A-1: a client with no UI layer gets an equivalent,
|
|
308
|
+
meaningful answer). All 12 supported components have a pure `<name>ToMarkdown(props, locale)`, also
|
|
309
|
+
exported from `@vantageos/mosaic/server`. `_meta.ui.fallback` is kept (it is part of the published
|
|
310
|
+
`createMosaicResource` result) and now holds the same text instead of a title and a note. A one-time
|
|
311
|
+
token's value is never written into `content[]`.
|
|
312
|
+
|
|
313
|
+
**Secret guard.** `MOSAIC_NEVER_SERIALISE` lists, per view, the fields whose value must never reach
|
|
314
|
+
`content[]`. `createMosaicToolResult` renders the fallback from the props without them, delivers them in
|
|
315
|
+
the result `_meta["mosaic/secrets"]`, and refuses (`MosaicSecretLeakError`) if any non-empty declared
|
|
316
|
+
value still appears, at any length. The comparison is case-folded and NFKC-normalised on both sides, so
|
|
317
|
+
`ABCD` is an echo of `abcd`; a very short secret can therefore also collide with unrelated text and
|
|
318
|
+
refuse loudly (the issuer keeps it out of the other props).
|
|
319
|
+
|
|
217
320
|
## Components
|
|
218
321
|
|
|
322
|
+
### What each subpath actually exports
|
|
323
|
+
|
|
324
|
+
Derived from the built type declarations, not maintained by hand:
|
|
325
|
+
|
|
326
|
+
```sh
|
|
327
|
+
# capitalised exports per subpath, excluding the
|
|
328
|
+
# Props/Schema/Validated/Option/Args/Return/Options/Shape/Mode/Type/Controls suffixes
|
|
329
|
+
node -e '...' # see the release PR for the exact script
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
| Subpath | Exports |
|
|
333
|
+
|---|---|
|
|
334
|
+
| `forms` | Checkbox, ErrorDisplay, FieldArray, FormField, FormProvider, Input, MultiSelect, RadioGroup, Select, SubmitButton, Textarea |
|
|
335
|
+
| `display` | BalanceCard, Badge, EmptyState, MessageFeed, PipelineBoard, Skeleton, StatCard, StatusBadge, StreamingTableView, TableView, VirtualList |
|
|
336
|
+
| `progress` | ProgressBar, Timeline |
|
|
337
|
+
| `input` | Tabs |
|
|
338
|
+
| `confirmation` | Alert, ConfirmDialog, ConfirmModal, TokenDisplayOnceModal, TransactionPreview |
|
|
339
|
+
| `artifacts` | MarkdownRenderer |
|
|
340
|
+
| `media` | *(none)* |
|
|
341
|
+
|
|
342
|
+
Two things this table says that prose would have hidden. **`media` exports no
|
|
343
|
+
components**, although it is one of the seven categories gated for cross-runtime
|
|
344
|
+
parity — the subpath exists and is empty of components. And the sections below
|
|
345
|
+
document only a few of these; the table is the inventory, the sections are
|
|
346
|
+
examples. Previously the sections WERE presented as the inventory, which is how
|
|
347
|
+
six separate sentences came to claim that form primitives were still unshipped
|
|
348
|
+
while a table row documenting each one sat directly beneath them.
|
|
349
|
+
|
|
350
|
+
The same list for `preact` is identical by construction — cross-runtime parity is
|
|
351
|
+
gated in CI (`scripts/verify-build-parity.sh`).
|
|
352
|
+
|
|
219
353
|
### Display
|
|
220
354
|
|
|
355
|
+
#### Badge
|
|
356
|
+
|
|
357
|
+
Static label primitive, cross-runtime. New in 0.4.0 — it was merged to `main` well
|
|
358
|
+
before and shipped in no published version until then.
|
|
359
|
+
|
|
360
|
+
```tsx
|
|
361
|
+
import { Badge } from "@vantageos/mosaic/react/display";
|
|
362
|
+
// Preact: import { Badge } from "@vantageos/mosaic/preact/display";
|
|
363
|
+
|
|
364
|
+
<Badge variant="success">Active</Badge>
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
See `src/components/display/Badge.schema.ts` for the prop contract and
|
|
368
|
+
`Badge.stories.tsx` for the rendered variants — both ship in the repo, and the
|
|
369
|
+
schema is the authority on the props rather than this snippet.
|
|
370
|
+
|
|
221
371
|
#### VirtualList
|
|
222
372
|
|
|
223
373
|
Generic virtualized list for large datasets. Uses @tanstack/react-virtual v3 (already bundled via TableView). Cross-runtime: React 19 + Preact 10.
|
|
@@ -260,7 +410,7 @@ type Task = { id: string; title: string; status: string };
|
|
|
260
410
|
## Doctrine
|
|
261
411
|
|
|
262
412
|
- **Pattern 1 (Zod runtime validation)** — every component validates props at the MCP host boundary; invalid props render an a11y fallback (`role="alert"`), never white-screen.
|
|
263
|
-
- **Pattern 2 (
|
|
413
|
+
- **Pattern 2 (category taxonomy)** — components live under exactly one category. Bilingual `category.meta.json` per category. The category list is the bare subpaths in the `exports` map, which is the authority; a count written here would be wrong at the next category added, as it was.
|
|
264
414
|
- **Pattern 3 (Registry-gated)** — `registry.yaml` declares every component; CI gate ensures parity between source and registry.
|
|
265
415
|
- **Pattern 4 (Streaming-hydration ready)** — components opt-in to MCP Apps streaming via `getStreamFor()` callbacks.
|
|
266
416
|
|
|
@@ -278,18 +428,40 @@ Consumer-driven i18n contract: components NEVER render raw alphabetic text as JS
|
|
|
278
428
|
// <ProgressBar value={50} label="Uploading…" />
|
|
279
429
|
```
|
|
280
430
|
|
|
281
|
-
## Bundle sizes
|
|
431
|
+
## Bundle sizes
|
|
282
432
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
433
|
+
Every figure below is the output of `pnpm --filter @vantageos/mosaic run size-limit`
|
|
434
|
+
against the built `dist/`, and the gates are the `limit` values in
|
|
435
|
+
`packages/mosaic/.size-limit.json`. Re-run the command rather than trusting this
|
|
436
|
+
table: a size written by hand is wrong at the next dependency bump.
|
|
437
|
+
|
|
438
|
+
| Surface | gz | gate |
|
|
439
|
+
|---|---|---|
|
|
440
|
+
| `dist/index.js` | 133.21 kB | 250 kB |
|
|
441
|
+
| `dist/react/forms.js` | 20.79 kB | 50 kB |
|
|
442
|
+
| `dist/preact/forms.js` | 20.79 kB | 50 kB |
|
|
443
|
+
|
|
444
|
+
Per-component subpaths are tree-shakeable; only the three surfaces above are gated.
|
|
288
445
|
|
|
289
446
|
## License
|
|
290
447
|
|
|
291
|
-
|
|
448
|
+
**FSL-1.1-Apache-2.0** — Functional Source License, Version 1.1, Apache 2.0 Future
|
|
449
|
+
License. © VantageOS / ElPi Corp.
|
|
450
|
+
|
|
451
|
+
The full text ships in the published tarball as [`LICENSE`](./LICENSE), and
|
|
452
|
+
`package.json` carries `"license": "FSL-1.1-Apache-2.0"`, so a consumer receives the
|
|
453
|
+
terms with the package rather than having to find them.
|
|
454
|
+
|
|
455
|
+
This is the same licence as every sibling `@vantageos` package — verified against
|
|
456
|
+
what the registry actually serves for `@vantageos/mosaic-blocks`,
|
|
457
|
+
`@vantageos/mosaic-tokens` and `@vantageos/mcp-doctor`, not against a convention
|
|
458
|
+
recalled from elsewhere, and the file is byte-identical to theirs
|
|
459
|
+
(sha256 `3d458972e6e84e5d2361a886ef64b07aefdc38dd8955e281ea8c2ae8849646a4`).
|
|
460
|
+
|
|
461
|
+
Versions up to and including 0.3.1 shipped with no licence field and no licence
|
|
462
|
+
file. From 0.4.0 they are present.
|
|
292
463
|
|
|
293
464
|
## Changelog
|
|
294
465
|
|
|
295
|
-
|
|
466
|
+
[`CHANGELOG.md`](./CHANGELOG.md), which ships inside the published tarball — the
|
|
467
|
+
repo-root file this used to point at is not what a consumer receives.
|