cortena-ui 1.1.1 → 1.3.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/README.md CHANGED
@@ -26,6 +26,89 @@ Consuming it: `../../CONSUMING.md`, section "cortena-ui".
26
26
  check in light, dark and system-dark; add an entry with every variant and
27
27
  size when adding a component.
28
28
 
29
+ ## Charts in tests
30
+
31
+ Both chart engines size themselves from the parent box, and under jsdom every
32
+ element measures 0×0. A page test that renders a screen containing a `<Chart>`
33
+ therefore gets an empty `<div>`: no `<svg>`, no bars, nothing to assert. Two
34
+ ways out, in order of preference.
35
+
36
+ **1. `testMode`, when the test is about the page.** It gives the drawing area a
37
+ 600×300 floor, so the chart draws and the page renders as a whole:
38
+
39
+ ```tsx
40
+ <Chart type="bar" data={rows} testMode={import.meta.env.MODE === "test"} />
41
+ ```
42
+
43
+ It is a floor, not a fixed size — a parent that does give the chart 900px still
44
+ gets 900px — so the same prop is harmless in a browser or screenshot test. A
45
+ screen that composes charts internally can take the flag as a prop and pass it
46
+ down, or read it once from the app's own test flag.
47
+
48
+ **2. Mock the module, when the test is about everything except the chart.**
49
+ Cheaper and faster, and the right choice when the assertion is "the dashboard
50
+ renders" rather than "the chart drew". Mock `cortena-ui`'s `Chart` to a stub
51
+ that echoes what it was handed:
52
+
53
+ ```tsx
54
+ vi.mock("cortena-ui", async (importOriginal) => ({
55
+ ...(await importOriginal<typeof import("cortena-ui")>()),
56
+ Chart: (props: { type: string }) => <div data-testid="chart" data-type={props.type} />,
57
+ }));
58
+ ```
59
+
60
+ Neither substitutes for the real check: whether a chart *looks* right is
61
+ settled in the guide and in this package's browser tests, not in a page test.
62
+
63
+ ## A2UI: the vocabulary agents draw with
64
+
65
+ `src/a2ui/` is Layer 1 of `cortena-docs/cortenaUI&Design/05-agent-ui.md`: an
66
+ [A2UI](https://a2ui.org) catalogue bound to this package, plus a React renderer.
67
+ An agent emits an A2UI payload, it arrives as an AG-UI `CUSTOM` event, and
68
+ `<A2UIRenderer>` draws it from the catalogue and sends user events back.
69
+
70
+ ```tsx
71
+ import { A2UIRenderer, defaultCatalogue } from "cortena-ui";
72
+
73
+ <A2UIRenderer
74
+ message={customEvent.value} // message, message[], or JSONL text
75
+ catalogue={defaultCatalogue} // 27 components; see `pnpm a2ui:catalogue`
76
+ onAction={(action) => run.send(action)} // { surfaceId, componentId, name, payload }
77
+ resolveDataSource={(id) => sources[id]} // server-backed DataTable handles
78
+ />;
79
+ ```
80
+
81
+ Two dialects fold onto the same surfaces: **v0.9** (`createSurface`,
82
+ `updateComponents`, `updateDataModel`) and the **v0.8** form core already speaks
83
+ (`beginRendering`, `surfaceUpdate`, `dataModelUpdate`), which is what the
84
+ `canvas` tool pushes as JSON lines. Later messages fold onto earlier ones, so a
85
+ push stream can be accumulated and handed to the renderer whole.
86
+
87
+ Safety is by construction: a node is a catalogue name plus properties that must
88
+ pass that entry's zod schema. An unknown component, an invalid property, a
89
+ missing child id or a `javascript:` URL each render an inline error card; no part
90
+ of a payload ever becomes markup.
91
+
92
+ `pnpm a2ui:catalogue` writes `dist-a2ui/catalogue.json` and `.md` (gitignored,
93
+ derived). DESIGN-34 generates the core system-prompt section from the JSON, so
94
+ the prompt and the renderer cannot describe different components.
95
+
96
+ ### Why the renderer is written rather than adopted
97
+
98
+ `@a2ui/react` 0.11.0 (Google, Apache-2.0) is a maintained v0.9 renderer and does
99
+ support host catalogues. It was evaluated at DESIGN-33 and not adopted:
100
+
101
+ | | |
102
+ | --- | --- |
103
+ | **zod major** | `@a2ui/web_core`'s binder reads zod 3 internals (`_def.typeName`, `_def.shape()`). This package's zod peer is `^3.25 \|\| ^4`; zod 4 has neither, so a catalogue authored with the consumer's zod 4 fails inside the binder. |
104
+ | **Dialect** | It splits `v0_8` and `v0_9` into separate entry points with separate catalogues, so neither reads both. Every A2UI payload already written for Cortena's native nodes would have to be rewritten before it rendered on the web. |
105
+ | **Weight and surface** | It pulls in `@a2ui/web_core` (3.8 MB unpacked), markdown-it, `@preact/signals-core` and date-fns, into a package that externalises everything and already renders markdown through react-markdown with a sanitize schema. `resolveDataSource` and `onAction` have no counterpart there, so it would be wrapped either way. |
106
+
107
+ What is kept is what makes interop work: the wire format is A2UI's, the emitted
108
+ action is shaped like A2UI's client-to-server `action`, and the catalogue is a
109
+ schema-per-component registry. Swapping the engine later is mechanical. Nothing
110
+ from `@a2ui/*` is installed, so `vitest.config.ts` has no entry for it.
111
+
29
112
  ## Commands
30
113
 
31
114
  ```bash
@@ -34,6 +117,7 @@ pnpm lint:design # no literals where a token exists; no dangling var()
34
117
  pnpm build # dist/ via tsdown (ESM + d.ts); also runs on prepack
35
118
  pnpm test # Vitest browser mode, chromium light + dark
36
119
  pnpm guide # three-theme guide on a local Vite server
120
+ pnpm a2ui:catalogue # dist-a2ui/catalogue.json + .md from the A2UI catalogue
37
121
  ```
38
122
 
39
123
  From the repo root the same are `pnpm ui:check`, `ui:build`, `ui:test`, `ui:guide`.
@@ -43,6 +127,7 @@ From the repo root the same are `pnpm ui:check`, `ui:build`, `ui:test`, `ui:guid
43
127
  ```
44
128
  src/index.ts public surface; add an export per component
45
129
  src/components/*.tsx one file per component, shadcn shape, Base UI primitives
130
+ src/a2ui/ A2UI catalogue, React renderer and doc generator
46
131
  src/lib/cn.ts clsx + tailwind-merge
47
132
  src/styles/index.css what consumers import after the tokens: animation
48
133
  utilities and the Base UI data-attribute variants