@pebble-software/bonsai 0.2.1 → 0.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
@@ -141,6 +141,8 @@ export function Example() {
141
141
  | `@pebble-software/bonsai/constants` | Component type names (`COMPONENT`, `COMPONENT_LIST`) and webhook event names. |
142
142
  | `@pebble-software/bonsai/ast` | The expression engine (`compileExpression`, `isExpression`, `parseExpression`, `extractVariables`, `clearExpressionCache`). |
143
143
  | `@pebble-software/bonsai/styles/*` | The raw layer stylesheets (`css/*.css`, `vendor/*.css`) and `presets.json`, for compiling template CSS yourself, e.g. `styles/css/theme.css?raw` in Vite. |
144
+ | `@pebble-software/bonsai/classes.json` | The class manifest: every Tailwind candidate each component type can emit, for compiling a per-template stylesheet without rendering (see [Compiling CSS per template](#compiling-css-per-template)). |
145
+ | `@pebble-software/bonsai/classes` | `classesFor(manifest, templates)` and the `ClassManifest` type. |
144
146
 
145
147
  Named exports of `@pebble-software/bonsai` and `@pebble-software/bonsai/core`:
146
148
 
@@ -269,7 +271,7 @@ The template format is defined by the Zod schema in [`library/schemas/src/bonsai
269
271
 
270
272
  ### Validating templates
271
273
 
272
- Validation is a separate, explicit step. The root entry exports `validateTemplate(template, registry, options?)`, which checks a template against a registry — unknown types, each component's `args` against its `propsSchema`, whether it accepts children, and whether it supports the target `mode` (`"web"` or `"pdf"`):
274
+ Validation is a separate, explicit step. The root entry exports `validateTemplate(template, registry, options?)`, which checks a template against a registry — unknown types, each component's `args` against its `propsSchema`, whether it accepts children, whether it supports the target `mode` (`"web"` or `"pdf"`), and whether every class a `className` expression can produce is written whole in a string literal (see [Compiling CSS per template](#compiling-css-per-template)):
273
275
 
274
276
  ```ts
275
277
  import { validateTemplate, pebbleRegistry } from "@pebble-software/bonsai";
@@ -304,7 +306,7 @@ Complete example templates live in the repo's [`examples/`](https://github.com/P
304
306
  - To mix text and values, put each part in its own child (`["{{a}}", " of ", "{{b}}"]`), or build the string in one expression (`"{{ concat(a, ' of ', b) }}"`).
305
307
  - Paths support dot notation (`user.email`) and array indexing (`addresses[0].street`).
306
308
  - Missing keys resolve to `undefined`; use the `default(value, fallback)` helper for a fallback inline, or handle defaults in host data.
307
- - Any `args` prop or string child can contain a binding.
309
+ - Any `args` prop or string child can contain a binding. A `className` binding must resolve to classes written whole in its string literals, so stylesheets can be compiled without rendering — see [Compiling CSS per template](#compiling-css-per-template).
308
310
  - Besides your own `data`, the instance's top-level state fields — `status`, `expiry`, and `submitting` — are readable from bindings (e.g. an `if` on `{{submitting}}`). **These names are reserved:** a top-level `data` key called `status`, `expiry`, or `submitting` is shadowed by the state field and can't be read from a binding. Nest it (`{{order.status}}`) instead.
309
311
  - Inside an `each` row, an identifier resolves against the loop alias first (e.g. `applicant.name`), then falls back to the surrounding data for anything the alias doesn't shadow (e.g. `orgName` from outside the loop) — see [Structural nodes](#structural-nodes-each--if).
310
312
  - On the client, evaluating a node's bindings is also what subscribes that node to the store — see [Controlled inputs & state](#controlled-inputs--state).
@@ -490,6 +492,29 @@ Bonsai is styled with **Tailwind CSS v4**. Components emit plain Tailwind utilit
490
492
  - **Theming**: the theme is token-driven — redefine the CSS variables (e.g. `--color-main`, `--font-heading`) after the stylesheet to restyle every component at once, or target `.bonsai-root` descendants for finer overrides.
491
493
  - **Utilities in your templates**: a `className` utility that no built-in component uses (say, `grid-cols-5`) is only generated if your build also scans the templates that use it — add their location with `@source`. Inside the Pebble Bonsai platform, CSS is compiled per template so this never comes up.
492
494
 
495
+ ### Compiling CSS per template
496
+
497
+ To ship each template a minimal stylesheet, compile it from two sources instead of rendering the template: the template's own JSON, for the classes it writes, and the class manifest, for the classes Bonsai's components emit.
498
+
499
+ ```ts
500
+ import { compile } from "tailwindcss";
501
+ import manifest from "@pebble-software/bonsai/classes.json" with { type: "json" };
502
+ import { classesFor } from "@pebble-software/bonsai/classes";
503
+
504
+ const candidates = [
505
+ ...classesFor(manifest, [template, header, footer]),
506
+ ...tokensFrom(JSON.stringify([template, header, footer])), // your own scan of the template text
507
+ ];
508
+ const css = (await compile(input, { loadStylesheet })).build(candidates);
509
+ ```
510
+
511
+ - **Every state is covered.** The manifest lists every variant and state of each component type a template uses, whichever `if` branch, status, render mode or data the template ends up rendered with. One stylesheet serves them all.
512
+ - **It overshoots slightly.** A template with one `button` gets the classes for every button size and variant, and the lists include tokens that aren't utilities. Tailwind ignores candidates it can't parse, so the extra tokens cost nothing.
513
+ - **Cache on `manifest.hash`.** It changes whenever any component's classes do, so include it in the cache key of any stylesheet you store.
514
+ - **`className` expressions must write each class whole.** `{{ status == 'pending' ? 'bg-accent-cyan p-4' : 'hidden' }}` and `{{ 'p-4 ' + (done ? 'line-through' : '') }}` are fine. `{{ 'bg-' + color }}` and `{{ cls }}` are not, because the class only exists once data arrives. `validateTemplate` reports them.
515
+
516
+ The manifest is generated on every build from the component sources by Tailwind's own scanner; see `scripts/class-manifest.ts`.
517
+
493
518
  ## Extending Bonsai
494
519
 
495
520
  ### Add or replace components
@@ -579,8 +604,9 @@ To add a component to Bonsai itself (in this monorepo):
579
604
 
580
605
  1. Add it to `COMPONENT` in `library/constants/src/components.ts`.
581
606
  2. Add its node and `args` contract to `library/schemas/src/bonsai.schema.ts`, and list it in `PEBBLE_COMPONENT_SCHEMAS` there (that is where `pebbleRegistry` gets its `propsSchema`).
582
- 3. Register the React implementation in `coreComponents` (`apps/bonsai/src/renderer/core-registry.ts`) — or, if it pulls in a heavy dependency, in a new preset under `apps/bonsai/src/renderer/presets/`, with a matching entry in `vite.config.ts` and `package.json#exports`.
607
+ 3. Register the React implementation in `coreComponents` (`apps/bonsai/src/renderer/core-registry.ts`) — or, if it pulls in a heavy dependency, in a new preset under `apps/bonsai/src/renderer/presets/`, with a matching entry in `vite.config.ts` and `package.json#exports`. Keep the `[COMPONENT.X]: Component` form, with `Component` imported by name from a module in `src/`: the class manifest build reads these entries to find each type's source.
583
608
  4. If it's an input, add its binding to `coreControlledInputs` (or the preset's `controlledInputs`).
609
+ 5. Write its classes as whole string literals (in `cva` variants or `cn(...)` arguments), never built with interpolation like `` `bg-${color}` ``. The class manifest is scanned from source, so an interpolated class is missing from every per-template stylesheet; `src/tests/classes.manifest.test.tsx` renders the example templates and fails on any class the manifest doesn't cover.
584
610
 
585
611
  ## Performance
586
612
 
@@ -636,8 +662,8 @@ From `apps/bonsai`:
636
662
  pnpm lint # Static analysis using ESLint
637
663
  pnpm test # Run the test suite (vitest)
638
664
  pnpm type-check # TypeScript without emit
639
- pnpm build # Bundles dist/ (ESM + type declarations) via Vite and copies the raw index.css theme
665
+ pnpm build # Bundles dist/ (ESM + type declarations) via Vite, copies the raw index.css theme and writes classes.json
640
666
  pnpm size-check # Checks each entry against its gzip budget (run after build)
641
667
  ```
642
668
 
643
- `dist/` contains the ESM bundle, TypeScript declarations, and the uncompiled `index.css` theme consumed by downstream Tailwind builds. The shared `@bonsai/constants` and `@bonsai/schemas` workspaces are aliased to their sources and bundled in, so the published package has no workspace dependencies.
669
+ `dist/` contains the ESM bundle, TypeScript declarations, the uncompiled `index.css` theme consumed by downstream Tailwind builds, and `classes.json`, the class manifest for consumers that compile CSS per template. The shared `@bonsai/constants` and `@bonsai/schemas` workspaces are aliased to their sources and bundled in, so the published package has no workspace dependencies.
@@ -1,23 +1,23 @@
1
1
  import { jsx as d } from "react/jsx-runtime";
2
2
  import { createElement as y, memo as h, useCallback as N, useState as j, useRef as B, useEffectEvent as L, useLayoutEffect as M, useEffect as P, createContext as W, useContext as A } from "react";
3
- import { i as T, B as O, r as b, j as S, k as V, l as D, m, n as $, o as q, p as R, q as J, V as z, s as F, t as G, v as H, f as Q, b as U, w as X } from "./render-shared-Cwb527d4.js";
3
+ import { i as T, B as O, r as b, j as S, k as V, l as D, m, n as R, o as q, p as $, q as J, V as z, s as F, t as G, v as H, f as Q, b as U, w as X } from "./render-shared-CrG0OFhJ.js";
4
4
  import { proxy as Y, snapshot as v, subscribe as Z, useSnapshot as k } from "valtio";
5
5
  const tt = {
6
6
  dataSlice(t, e, r) {
7
7
  return D(t.dynamicKeys, (n) => n in r && n !== "data" ? r[n] : m(r.data ?? r, n));
8
8
  },
9
- rowCtx(t, e, r, n, s, o) {
10
- const { as: a, indexAlias: i } = s, c = {
9
+ rowCtx(t, e, r, n, o, s) {
10
+ const { as: a, indexAlias: i } = o, c = {
11
11
  ...e,
12
12
  data: {
13
13
  ...e.data ?? e,
14
14
  [a]: r,
15
15
  ...i ? { [i]: n } : {}
16
16
  }
17
- }, u = o ? { ...t.scope, [a]: `${o}.${n}` } : t.scope;
17
+ }, u = s ? { ...t.scope, [a]: `${s}.${n}` } : t.scope;
18
18
  return { data: c, scope: u };
19
19
  },
20
- renderChild(t, e, r, n, s) {
20
+ renderChild(t, e, r, n, o) {
21
21
  return /* @__PURE__ */ d(
22
22
  K,
23
23
  {
@@ -27,20 +27,20 @@ const tt = {
27
27
  data: n.data,
28
28
  scope: n.scope
29
29
  },
30
- s
30
+ o
31
31
  );
32
32
  }
33
33
  }, K = h(
34
- ({ node: t, index: e = 0, path: r = "root", data: n, scope: s }) => {
35
- const o = S(), a = N(() => {
34
+ ({ node: t, index: e = 0, path: r = "root", data: n, scope: o }) => {
35
+ const s = S(), a = N(() => {
36
36
  }, []);
37
37
  return V(
38
38
  t,
39
39
  e,
40
40
  r,
41
- { data: n, scope: s },
41
+ { data: n, scope: o },
42
42
  n,
43
- o,
43
+ s,
44
44
  a,
45
45
  tt
46
46
  );
@@ -51,8 +51,8 @@ function et({
51
51
  expiry: e,
52
52
  data: r,
53
53
  status: n = "pending",
54
- render: s = "web",
55
- as: o,
54
+ render: o = "web",
55
+ as: s,
56
56
  registry: a
57
57
  }) {
58
58
  const i = {
@@ -60,12 +60,12 @@ function et({
60
60
  expiry: e ?? "",
61
61
  status: n,
62
62
  submitting: !1
63
- }, c = T(t).root, u = b(s, o);
64
- return /* @__PURE__ */ d(O, { registry: a, render: s, children: y(
63
+ }, c = T(t).root, u = b(o, s);
64
+ return /* @__PURE__ */ d(O, { registry: a, render: o, children: y(
65
65
  u,
66
66
  {
67
- "data-mode": s,
68
- className: `group bonsai-root${s === "pdf" ? " w-full" : ""}`
67
+ "data-mode": o,
68
+ className: o === "pdf" ? "group bonsai-root w-full" : "group bonsai-root"
69
69
  },
70
70
  /* @__PURE__ */ d(K, { node: c, index: 0, path: "root", data: i })
71
71
  ) });
@@ -84,18 +84,18 @@ function rt() {
84
84
  [t]
85
85
  );
86
86
  }
87
- function nt(t, e, r, n, s) {
88
- const o = G(t);
89
- return n && o in n ? t === o ? n[o] : void 0 : r && o in r ? m(e.data ?? e, H(t, r)) : s && Object.hasOwn(s, o) ? m(s, t) : t in e && t !== "data" ? e[t] : m(e.data ?? e, t);
87
+ function nt(t, e, r, n, o) {
88
+ const s = G(t);
89
+ return n && s in n ? t === s ? n[s] : void 0 : r && s in r ? m(e.data ?? e, H(t, r)) : o && Object.hasOwn(o, s) ? m(o, t) : t in e && t !== "data" ? e[t] : m(e.data ?? e, t);
90
90
  }
91
- const st = h(
92
- ({ node: t, index: e = 0, path: r = "root", scope: n, indexScope: s, valueScope: o }) => {
91
+ const ot = h(
92
+ ({ node: t, index: e = 0, path: r = "root", scope: n, indexScope: o, valueScope: s }) => {
93
93
  const a = S(), i = t.source;
94
94
  if (!i) return null;
95
95
  if (t.isText)
96
96
  return i;
97
97
  try {
98
- const c = t.type, u = q(a, c), p = R(t, e, r), l = J(t, {}, p);
98
+ const c = t.type, u = q(a, c), p = $(t, e, r), l = J(t, {}, p);
99
99
  if (t.isImage && (l.src === "" || l.src == null))
100
100
  return null;
101
101
  const f = t.children.length > 0 ? t.children.map(
@@ -104,9 +104,9 @@ const st = h(
104
104
  E,
105
105
  `${r}-${e}`,
106
106
  n,
107
- s,
108
107
  o,
109
- R(t, E, `${r}-${e}`)
108
+ s,
109
+ $(t, E, `${r}-${e}`)
110
110
  )
111
111
  ) : void 0, C = typeof u == "string" && z.has(u) ? void 0 : f;
112
112
  return C !== void 0 ? y(u, l, C) : y(u, l);
@@ -115,16 +115,16 @@ const st = h(
115
115
  }
116
116
  }
117
117
  );
118
- function g(t, e, r, n, s, o, a) {
118
+ function g(t, e, r, n, o, s, a) {
119
119
  return t.isStatic ? /* @__PURE__ */ d(
120
- st,
120
+ ot,
121
121
  {
122
122
  node: t,
123
123
  index: e,
124
124
  path: r,
125
125
  scope: n,
126
- indexScope: s,
127
- valueScope: o
126
+ indexScope: o,
127
+ valueScope: s
128
128
  },
129
129
  a
130
130
  ) : /* @__PURE__ */ d(
@@ -134,8 +134,8 @@ function g(t, e, r, n, s, o, a) {
134
134
  index: e,
135
135
  path: r,
136
136
  scope: n,
137
- indexScope: s,
138
- valueScope: o
137
+ indexScope: o,
138
+ valueScope: s
139
139
  },
140
140
  a
141
141
  );
@@ -145,17 +145,17 @@ function x(t, e) {
145
145
  const r = { ...t };
146
146
  return delete r[e], r;
147
147
  }
148
- const ot = {
148
+ const st = {
149
149
  dataSlice(t, e, r) {
150
150
  return D(
151
151
  t.dynamicKeys,
152
152
  (n) => nt(n, r, e.scope, e.indexScope, e.valueScope)
153
153
  );
154
154
  },
155
- rowCtx(t, e, r, n, s, o) {
156
- const { as: a, indexAlias: i } = s, c = i ? { ...t.indexScope, [i]: n } : t.indexScope;
157
- return o ? {
158
- scope: { ...t.scope, [a]: `${o}.${n}` },
155
+ rowCtx(t, e, r, n, o, s) {
156
+ const { as: a, indexAlias: i } = o, c = i ? { ...t.indexScope, [i]: n } : t.indexScope;
157
+ return s ? {
158
+ scope: { ...t.scope, [a]: `${s}.${n}` },
159
159
  indexScope: c,
160
160
  valueScope: x(t.valueScope, a)
161
161
  } : {
@@ -164,21 +164,21 @@ const ot = {
164
164
  valueScope: { ...t.valueScope, [a]: r }
165
165
  };
166
166
  },
167
- renderChild(t, e, r, n, s) {
168
- return g(t, e, r, n.scope, n.indexScope, n.valueScope, s);
167
+ renderChild(t, e, r, n, o) {
168
+ return g(t, e, r, n.scope, n.indexScope, n.valueScope, o);
169
169
  }
170
170
  }, at = h(
171
- ({ node: t, index: e = 0, path: r = "root", scope: n, indexScope: s, valueScope: o }) => {
171
+ ({ node: t, index: e = 0, path: r = "root", scope: n, indexScope: o, valueScope: s }) => {
172
172
  const a = S(), i = w(), c = k(i, { sync: !0 }), u = rt();
173
173
  return V(
174
174
  t,
175
175
  e,
176
176
  r,
177
- { scope: n, indexScope: s, valueScope: o },
177
+ { scope: n, indexScope: o, valueScope: s },
178
178
  c,
179
179
  a,
180
180
  u,
181
- ot
181
+ st
182
182
  );
183
183
  }
184
184
  );
@@ -187,16 +187,16 @@ function it({
187
187
  template: e,
188
188
  render: r = "web",
189
189
  as: n,
190
- onSubmit: s,
191
- onError: o,
190
+ onSubmit: o,
191
+ onError: s,
192
192
  registry: a
193
193
  }) {
194
194
  const i = w(), c = async (l) => {
195
- if (l.preventDefault(), i.status === "pending" && !(!s && !t)) {
195
+ if (l.preventDefault(), i.status === "pending" && !(!o && !t)) {
196
196
  i.submitting = !0;
197
197
  try {
198
- if (s)
199
- await s(v(i.data));
198
+ if (o)
199
+ await o(v(i.data));
200
200
  else {
201
201
  const f = await fetch(t, {
202
202
  method: "POST",
@@ -213,8 +213,8 @@ function it({
213
213
  }
214
214
  i.status = "captured";
215
215
  } catch (f) {
216
- if (!o) throw f;
217
- o(f);
216
+ if (!s) throw f;
217
+ s(f);
218
218
  } finally {
219
219
  i.submitting = !1;
220
220
  }
@@ -224,7 +224,7 @@ function it({
224
224
  p,
225
225
  {
226
226
  "data-mode": r,
227
- className: `group bonsai-root${r === "pdf" ? " w-full" : ""}`,
227
+ className: r === "pdf" ? "group bonsai-root w-full" : "group bonsai-root",
228
228
  ...p === "form" ? { onSubmit: c } : {}
229
229
  },
230
230
  g(u, 0, "root", void 0, void 0, void 0, "root-0")
@@ -235,28 +235,28 @@ function ct(t) {
235
235
  () => Y({
236
236
  status: t.status ?? "pending",
237
237
  expiry: t.expiry ?? "",
238
- data: $(t.data ?? {}),
238
+ data: R(t.data ?? {}),
239
239
  submitting: !1
240
240
  })
241
- ), r = B(t.data), n = B(!1), s = L((o) => {
242
- t.onDataChange?.(o);
241
+ ), r = B(t.data), n = B(!1), o = L((s) => {
242
+ t.onDataChange?.(s);
243
243
  });
244
244
  return M(() => {
245
245
  if (!Object.is(r.current, t.data)) {
246
246
  r.current = t.data, n.current = !0;
247
247
  try {
248
- e.data = $(t.data ?? {});
248
+ e.data = R(t.data ?? {});
249
249
  } finally {
250
250
  n.current = !1;
251
251
  }
252
252
  }
253
253
  }, [e, t.data]), P(() => {
254
- let o = v(e.data);
254
+ let s = v(e.data);
255
255
  return Z(
256
256
  e,
257
257
  () => {
258
258
  const a = v(e.data);
259
- a !== o && (o = a, !n.current && s(a));
259
+ a !== s && (s = a, !n.current && o(a));
260
260
  },
261
261
  !0
262
262
  );
@@ -279,4 +279,4 @@ export {
279
279
  mt as c,
280
280
  rt as u
281
281
  };
282
- //# sourceMappingURL=create-renderer-C4nV9RV6.js.map
282
+ //# sourceMappingURL=create-renderer-kgClEYyp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-renderer-kgClEYyp.js","sources":["../../src/components/core/render-tree-server.tsx","../../src/components/core/render-tree-client.tsx","../../src/components/core/bonsai.tsx","../../src/renderer/create-renderer.tsx"],"sourcesContent":["import { createElement, memo, useCallback } from \"react\";\nimport { type CompiledNode } from \"../../lib/renderer/compile-template\";\nimport { compileTemplate } from \"../../lib/renderer/compile-template\";\nimport {\n BonsaiRoot,\n useBonsaiRegistry,\n buildDataSlice,\n getValue,\n resolveWrapper,\n renderCompiledNode,\n type GlobalData,\n type NodeCtx,\n type RenderStrategy,\n type BonsaiProps,\n} from \"./render-shared\";\n\ninterface RenderTreeServerProps {\n // Precompiled metadata for this node; `node.source` is the raw template node.\n node: CompiledNode;\n index?: number;\n path?: string;\n data: GlobalData;\n // Alias -> real store path prefix set by an ancestor `each` (e.g. { applicant: \"applicants.3\" }); SSR-only.\n scope?: Record<string, string>;\n}\n\n// SSR ctx is the prop-drilled global data object plus the current `each` scope.\ninterface ServerCtx extends NodeCtx {\n data: GlobalData;\n}\n\nconst SERVER_MODE: RenderStrategy<ServerCtx> = {\n dataSlice(node, _ctx, globalData) {\n return buildDataSlice(node.dynamicKeys, (key) => {\n if (key in globalData && key !== \"data\") return globalData[key];\n return getValue(globalData.data ?? globalData, key);\n });\n },\n rowCtx(ctx, globalData, item, i, each, realItemsPath) {\n const { as, indexAlias } = each;\n const rowData = {\n ...globalData,\n data: {\n ...(globalData.data ?? globalData),\n [as]: item,\n ...(indexAlias ? { [indexAlias]: i } : {}),\n },\n };\n const rowScope = realItemsPath\n ? { ...ctx.scope, [as]: `${realItemsPath}.${i}` }\n : ctx.scope;\n return { data: rowData, scope: rowScope };\n },\n renderChild(child, i, path, ctx, key) {\n return (\n <RenderTreeServer\n key={key}\n node={child}\n index={i}\n path={path}\n data={ctx.data}\n scope={ctx.scope}\n />\n );\n },\n};\n\n// SSR: single-pass render over a plain, prop-drilled object — no store, no snapshots.\nconst RenderTreeServer = memo(\n ({ node, index = 0, path = \"root\", data, scope }: RenderTreeServerProps) => {\n const registry = useBonsaiRegistry();\n const updateData = useCallback(() => {\n // Attached for the controlled-component contract but never invoked during SSR.\n }, []);\n\n return renderCompiledNode(\n node,\n index,\n path,\n { data, scope },\n data,\n registry,\n updateData,\n SERVER_MODE,\n );\n },\n);\n\nexport function BonsaiServer({\n template,\n expiry,\n data,\n status = \"pending\",\n render = \"web\",\n as,\n registry,\n}: BonsaiProps) {\n const ctx = {\n data: data ?? {},\n expiry: expiry ?? \"\",\n status,\n submitting: false,\n };\n\n // Cached by template identity, so N instances of the same template compile once.\n const root = compileTemplate(template).root;\n const Wrapper = resolveWrapper(render, as);\n\n return (\n <BonsaiRoot registry={registry} render={render}>\n {createElement(\n Wrapper,\n {\n \"data-mode\": render,\n className:\n render === \"pdf\" ? \"group bonsai-root w-full\" : \"group bonsai-root\",\n },\n <RenderTreeServer node={root} index={0} path=\"root\" data={ctx} />,\n )}\n </BonsaiRoot>\n );\n}\n","import {\n createContext,\n createElement,\n memo,\n useCallback,\n useContext,\n useEffect,\n useEffectEvent,\n useLayoutEffect,\n useRef,\n useState,\n type SubmitEvent,\n} from \"react\";\nimport { proxy, snapshot, subscribe, useSnapshot } from \"valtio\";\nimport { type CompiledNode } from \"../../lib/renderer/compile-template\";\nimport { compileTemplate } from \"../../lib/renderer/compile-template\";\nimport {\n BonsaiRoot,\n useBonsaiRegistry,\n VOID_ELEMENTS,\n getKey,\n getValue,\n setValue,\n resolveScopedPath,\n pathRoot,\n buildDataSlice,\n resolveElementType,\n prepareState,\n resolveWrapper,\n cloneData,\n renderCompiledNode,\n type GlobalData,\n type NodeCtx,\n type RenderStrategy,\n type BonsaiProps,\n} from \"./render-shared\";\n\n// scope/indexScope/valueScope are the only things an `each` row hands its children on the live path —\n// store data is never prop-drilled (valueScope carries only computed-row items, which have no store path).\ninterface RenderTreeClientProps {\n node: CompiledNode;\n index?: number;\n path?: string;\n scope?: Record<string, string>;\n indexScope?: Record<string, number>;\n valueScope?: Record<string, unknown>;\n}\n\ntype BonsaiState = {\n status: string;\n expiry: string;\n data: Record<string, unknown>;\n submitting: boolean;\n};\n\nconst BonsaiContext = createContext<ReturnType<\n typeof proxy<BonsaiState>\n> | null>(null);\n\nfunction useBonsaiStore(): ReturnType<typeof proxy<BonsaiState>> {\n const store = useContext(BonsaiContext);\n if (!store) {\n throw new Error(\"useBonsaiStore must be used within a <Bonsai> component\");\n }\n return store;\n}\n\nexport function useUpdateData() {\n const store = useBonsaiStore();\n return useCallback(\n (path: string, value: unknown) => setValue(store.data, path, value),\n [store],\n );\n}\n\n// Live-path lookup: resolves each-scoped aliases at read time against a fresh snapshot.\nfunction resolveKeyValue(\n key: string,\n globalData: GlobalData,\n scope: Record<string, string> | undefined,\n indexScope: Record<string, number> | undefined,\n valueScope: Record<string, unknown> | undefined,\n): unknown {\n const root = pathRoot(key);\n\n if (indexScope && root in indexScope) {\n return key === root ? indexScope[root] : undefined;\n }\n\n if (scope && root in scope) {\n return getValue(globalData.data ?? globalData, resolveScopedPath(key, scope));\n }\n\n if (valueScope && Object.hasOwn(valueScope, root)) {\n return getValue(valueScope, key);\n }\n\n if (key in globalData && key !== \"data\") {\n return globalData[key];\n }\n\n return getValue(globalData.data ?? globalData, key);\n}\n\n// Children still go through `renderClientNode`, so a binding nested inside an unbound wrapper stays reactive.\nconst StaticNode = memo(\n ({ node, index = 0, path = \"root\", scope, indexScope, valueScope }: RenderTreeClientProps) => {\n const registry = useBonsaiRegistry();\n const tree = node.source;\n\n if (!tree) return null;\n if (node.isText) {\n // `isStatic` guarantees this has no `{{...}}` binding to evaluate.\n return tree as unknown as string;\n }\n\n try {\n const type = node.type;\n const ElementType = resolveElementType(registry, type);\n const key = getKey(node, index, path);\n const props = prepareState(node, {}, key);\n\n if (node.isImage && (props.src === \"\" || props.src == null)) {\n return null;\n }\n\n const childNodes =\n node.children.length > 0\n ? node.children.map((branch: CompiledNode, i: number) =>\n renderClientNode(\n branch,\n i,\n `${path}-${index}`,\n scope,\n indexScope,\n valueScope,\n getKey(node, i, `${path}-${index}`),\n ),\n )\n : undefined;\n\n const safeChildNodes =\n typeof ElementType === \"string\" && VOID_ELEMENTS.has(ElementType)\n ? undefined\n : childNodes;\n\n if (safeChildNodes !== undefined) {\n return createElement(ElementType, props, safeChildNodes);\n }\n return createElement(ElementType, props);\n } catch (error) {\n console.error(`Error at ${path}-${index}:`, error);\n return null;\n }\n },\n);\n\n// A plain function, not a hook, since it decides which component type to mount — always a safe conditional.\nfunction renderClientNode(\n node: CompiledNode,\n index: number,\n path: string,\n scope: Record<string, string> | undefined,\n indexScope: Record<string, number> | undefined,\n valueScope: Record<string, unknown> | undefined,\n key: string,\n): React.ReactNode {\n return node.isStatic ? (\n <StaticNode\n key={key}\n node={node}\n index={index}\n path={path}\n scope={scope}\n indexScope={indexScope}\n valueScope={valueScope}\n />\n ) : (\n <RenderTreeClient\n key={key}\n node={node}\n index={index}\n path={path}\n scope={scope}\n indexScope={indexScope}\n valueScope={valueScope}\n />\n );\n}\n\n// Client ctx carries only what an `each` row hands its children on this path — no data is prop-drilled.\ninterface ClientCtx extends NodeCtx {\n indexScope?: Record<string, number>;\n}\n\nfunction omitKey<T>(\n obj: Record<string, T> | undefined,\n key: string,\n): Record<string, T> | undefined {\n if (!obj || !Object.hasOwn(obj, key)) return obj;\n const rest = { ...obj };\n delete rest[key];\n return rest;\n}\n\nconst CLIENT_MODE: RenderStrategy<ClientCtx> = {\n dataSlice(node, ctx, globalData) {\n return buildDataSlice(node.dynamicKeys, (key) =>\n resolveKeyValue(key, globalData, ctx.scope, ctx.indexScope, ctx.valueScope),\n );\n },\n rowCtx(ctx, _globalData, item, i, each, realItemsPath) {\n const { as, indexAlias } = each;\n const rowIndexScope = indexAlias\n ? { ...ctx.indexScope, [indexAlias]: i }\n : ctx.indexScope;\n // A plain-path row resolves its alias against the store; a computed row has no store path, so it\n // carries the item itself. Each clears the alias from the other map so an inner alias shadows an outer one.\n if (realItemsPath) {\n return {\n scope: { ...ctx.scope, [as]: `${realItemsPath}.${i}` },\n indexScope: rowIndexScope,\n valueScope: omitKey(ctx.valueScope, as),\n };\n }\n return {\n scope: omitKey(ctx.scope, as),\n indexScope: rowIndexScope,\n valueScope: { ...ctx.valueScope, [as]: item },\n };\n },\n renderChild(child, i, path, ctx, key) {\n return renderClientNode(child, i, path, ctx.scope, ctx.indexScope, ctx.valueScope, key);\n },\n};\n\n// Client: every node calls useSnapshot itself, so it only re-renders when a path it actually reads changes.\nconst RenderTreeClient = memo(\n ({ node, index = 0, path = \"root\", scope, indexScope, valueScope }: RenderTreeClientProps) => {\n const registry = useBonsaiRegistry();\n const store = useBonsaiStore();\n // sync: true keeps the store write and its re-render in the same event, avoiding a one-tick display lag.\n const globalData = useSnapshot(store, { sync: true });\n const updateData = useUpdateData();\n\n return renderCompiledNode(\n node,\n index,\n path,\n { scope, indexScope, valueScope },\n globalData,\n registry,\n updateData,\n CLIENT_MODE,\n );\n },\n);\n\nexport function BonsaiClient({\n captureUrl,\n template,\n render = \"web\",\n as,\n onSubmit,\n onError,\n registry,\n}: BonsaiProps) {\n const store = useBonsaiStore();\n\n const submit = async (e: SubmitEvent) => {\n e.preventDefault();\n // Already captured/completed/revoked: nothing to send, and the lifecycle flags stay as they are.\n if (store.status !== \"pending\") return;\n // Display-only instance: nothing to submit to, so don't touch the lifecycle.\n if (!onSubmit && !captureUrl) return;\n\n // eslint-disable-next-line react-hooks/immutability -- the store is a valtio proxy, mutated by design\n store.submitting = true;\n try {\n if (onSubmit) {\n await onSubmit(snapshot(store.data) as Record<string, unknown>);\n } else {\n const res = await fetch(captureUrl!, {\n method: \"POST\",\n credentials: \"include\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n data: store.data,\n }),\n });\n // fetch only rejects on network failure; an error status must not count as captured.\n if (!res.ok) {\n throw new Error(`Capture failed: ${res.status} ${res.statusText}`.trim());\n }\n }\n\n store.status = \"captured\";\n } catch (error) {\n // Without an `onError`, this keeps the pre-existing behaviour of letting\n // the failure propagate out of the submit handler.\n if (!onError) throw error;\n onError(error);\n } finally {\n store.submitting = false;\n }\n };\n\n // Cached by template identity, so N instances of the same template compile once.\n const root = compileTemplate(template).root;\n const Wrapper = resolveWrapper(render, as);\n\n return (\n <BonsaiRoot registry={registry} render={render}>\n {createElement(\n Wrapper,\n {\n \"data-mode\": render,\n className:\n render === \"pdf\" ? \"group bonsai-root w-full\" : \"group bonsai-root\",\n ...(Wrapper === \"form\" ? { onSubmit: submit } : {}),\n },\n renderClientNode(root, 0, \"root\", undefined, undefined, undefined, \"root-0\"),\n )}\n </BonsaiRoot>\n );\n}\n\nexport function BonsaiProvider(props: BonsaiProps) {\n const [store] = useState(() =>\n proxy<BonsaiState>({\n status: props.status ?? \"pending\",\n expiry: props.expiry ?? \"\",\n data: cloneData(props.data ?? {}),\n submitting: false,\n }),\n );\n // The `data` object identity this store was last seeded from.\n const seenDataRef = useRef<BonsaiProps[\"data\"]>(props.data);\n // Set while the provider itself writes to the store, so a parent-driven\n // resync isn't echoed back out through `onDataChange`.\n const resyncingRef = useRef(false);\n const onDataChange = useEffectEvent((next: Record<string, unknown>) => {\n props.onDataChange?.(next);\n });\n\n useLayoutEffect(() => {\n // A new `data` object arrived from the parent — adopt it before paint.\n // Same-reference renders (including in-place mutations) are deliberately ignored.\n if (Object.is(seenDataRef.current, props.data)) return;\n seenDataRef.current = props.data;\n resyncingRef.current = true;\n try {\n store.data = cloneData(props.data ?? {});\n } finally {\n resyncingRef.current = false;\n }\n }, [store, props.data]);\n\n useEffect(() => {\n // valtio only populates subscription `ops` when the (unstable) op tracking\n // is switched on globally, so changes are detected by snapshot identity\n // instead: `snapshot` is memoised per version, so an unchanged `data`\n // subtree returns the very same object and is filtered out here.\n //\n // Notify in sync: the resync flag below is only reliable if the callback\n // runs inside the write, not on a later microtask.\n let previous = snapshot(store.data);\n return subscribe(\n store,\n () => {\n const next = snapshot(store.data);\n if (next === previous) return;\n previous = next;\n // A parent-driven resync isn't a user edit — don't echo it back.\n if (resyncingRef.current) return;\n onDataChange(next as Record<string, unknown>);\n },\n true,\n );\n }, [store]);\n\n return (\n <BonsaiContext.Provider value={store}>\n <BonsaiClient {...props} />\n </BonsaiContext.Provider>\n );\n}\n","import { BonsaiServer } from \"./render-tree-server\";\nimport { BonsaiProvider } from \"./render-tree-client\";\nimport type { BonsaiProps } from \"./render-shared\";\n\nexport {\n BonsaiRegistryContext,\n getValue,\n setValue,\n useBonsaiRenderMode,\n type BonsaiProps,\n type RenderMode,\n} from \"./render-shared\";\nexport { useUpdateData, BonsaiClient, BonsaiProvider } from \"./render-tree-client\";\nexport { BonsaiServer } from \"./render-tree-server\";\n\nexport function Bonsai(props: BonsaiProps) {\n if (typeof window === \"undefined\") {\n return <BonsaiServer {...props} />;\n }\n\n return <BonsaiProvider {...props} />;\n}\n","import {\n Bonsai as BonsaiRenderer,\n BonsaiRegistryContext,\n type BonsaiProps,\n} from \"../components/core/bonsai\";\nimport {\n coreRegistry,\n extendRegistry,\n type ComponentRegistry,\n type ControlledInputRegistry,\n} from \"./core-registry\";\nimport type { BonsaiRegistry } from \"../lib/registry/types\";\n\nexport interface BonsaiRendererOptions {\n /** Base registry. Defaults to the lightweight core registry. */\n registry?: BonsaiRegistry;\n /** Extra components layered over `registry` (they win on key collision). */\n components?: Partial<ComponentRegistry>;\n controlledInputs?: Partial<ControlledInputRegistry>;\n}\n\nexport interface BonsaiRendererInstance {\n Bonsai: React.ComponentType<BonsaiProps>;\n}\n\n/**\n * Builds a renderer bound to its own component registry.\n *\n * The registry is `options.registry` (the lightweight core set by default)\n * plus whatever components the caller supplies (caller entries win on key\n * collision); a `registry` prop on an individual `<Bonsai>` still overrides it. It is captured in a React context at\n * this call, so registries never leak between renderer instances and consumers\n * never have to mutate the exported `componentMap`.\n *\n * Heavy built-ins are opt-in via the presets in `renderer/presets/*`:\n *\n * ```ts\n * import { createBonsaiRenderer } from \"@pebble-software/bonsai/core\";\n * import { calendarPreset } from \"@pebble-software/bonsai/presets/calendar\";\n *\n * const { Bonsai } = createBonsaiRenderer({\n * components: { ...calendarPreset.components, rating: Rating },\n * controlledInputs: { ...calendarPreset.controlledInputs },\n * });\n * ```\n *\n * Call this at module scope: each call returns a fresh component type, so\n * calling it during render would remount the whole tree every time.\n */\nexport function createBonsaiRenderer(\n options: BonsaiRendererOptions = {},\n): BonsaiRendererInstance {\n // Cast: a `Partial<...>` widens values to `| undefined`, but it only ever\n // holds keys the caller actually supplied.\n const registry = extendRegistry(options.registry ?? coreRegistry, {\n components: options.components as ComponentRegistry | undefined,\n controlledInputs: options.controlledInputs as ControlledInputRegistry | undefined,\n });\n\n function Bonsai(props: BonsaiProps) {\n return (\n <BonsaiRegistryContext.Provider value={registry}>\n <BonsaiRenderer {...props} />\n </BonsaiRegistryContext.Provider>\n );\n }\n Bonsai.displayName = \"Bonsai\";\n\n return { Bonsai };\n}\n"],"names":["SERVER_MODE","node","_ctx","globalData","buildDataSlice","key","getValue","ctx","item","i","each","realItemsPath","as","indexAlias","rowData","rowScope","child","path","jsx","RenderTreeServer","memo","index","data","scope","registry","useBonsaiRegistry","updateData","useCallback","renderCompiledNode","BonsaiServer","template","expiry","status","render","root","compileTemplate","Wrapper","resolveWrapper","BonsaiRoot","createElement","BonsaiContext","createContext","useBonsaiStore","store","useContext","useUpdateData","value","setValue","resolveKeyValue","indexScope","valueScope","pathRoot","resolveScopedPath","StaticNode","tree","type","ElementType","resolveElementType","getKey","props","prepareState","childNodes","branch","renderClientNode","safeChildNodes","VOID_ELEMENTS","error","RenderTreeClient","omitKey","obj","rest","CLIENT_MODE","_globalData","rowIndexScope","useSnapshot","BonsaiClient","captureUrl","onSubmit","onError","submit","e","snapshot","res","BonsaiProvider","useState","proxy","cloneData","seenDataRef","useRef","resyncingRef","onDataChange","useEffectEvent","next","useLayoutEffect","useEffect","previous","subscribe","Bonsai","createBonsaiRenderer","options","extendRegistry","coreRegistry","BonsaiRegistryContext","BonsaiRenderer"],"mappings":"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"}
@@ -282,7 +282,7 @@ function Wa({
282
282
  {
283
283
  "data-slot": "accordion-trigger",
284
284
  className: i(
285
- "neo-base neo-accordion-focus pt-3 text-left text-base font-medium cursor-pointer shrink-0 group/accordion-trigger relative flex flex-1 items-center justify-between border border-transparent transition-[opacity,border], data-disabled:pointer-events-none data-disabled:opacity-50",
285
+ "neo-base neo-accordion-focus pt-3 text-left text-base font-medium cursor-pointer shrink-0 group/accordion-trigger relative flex flex-1 items-center justify-between border border-transparent transition-[opacity,border] data-disabled:pointer-events-none data-disabled:opacity-50",
286
286
  "p-4",
287
287
  "hover:underline",
288
288
  "group-first/accordion-item:rounded-t-base",
@@ -2028,4 +2028,4 @@ export {
2028
2028
  $ as v,
2029
2029
  ha as w
2030
2030
  };
2031
- //# sourceMappingURL=render-shared-Cwb527d4.js.map
2031
+ //# sourceMappingURL=render-shared-CrG0OFhJ.js.map