@cascivo/react 0.16.1 → 0.17.1

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.
Files changed (62) hide show
  1. package/README.md +14 -13
  2. package/dist/accordion/accordion.js +5 -4
  3. package/dist/app-shell/app-shell.css +1 -1
  4. package/dist/app-shell/app-shell.js +28 -26
  5. package/dist/app-shell/app-shell.module.js +8 -8
  6. package/dist/breadcrumb/breadcrumb.js +1 -1
  7. package/dist/button/button.css +1 -1
  8. package/dist/button/button.js +4 -1
  9. package/dist/button/button.module.js +4 -1
  10. package/dist/calendar/calendar.js +67 -63
  11. package/dist/card/card.css +1 -1
  12. package/dist/card/card.module.js +8 -8
  13. package/dist/checkbox/checkbox.css +1 -1
  14. package/dist/checkbox/checkbox.module.js +4 -4
  15. package/dist/code-snippet/code-snippet.js +31 -26
  16. package/dist/combobox/combobox.js +55 -54
  17. package/dist/data-table/data-table.css +1 -1
  18. package/dist/data-table/data-table.js +155 -160
  19. package/dist/data-table/data-table.module.js +29 -29
  20. package/dist/date-picker/date-picker.js +90 -89
  21. package/dist/dock/dock.js +1 -1
  22. package/dist/field/field.css +1 -1
  23. package/dist/field/field.module.js +3 -3
  24. package/dist/index.d.ts +157 -10
  25. package/dist/large-title-header/large-title-header.js +1 -1
  26. package/dist/layouts/src/grid/grid.css +1 -1
  27. package/dist/layouts/src/grid/grid.module.js +3 -3
  28. package/dist/node/accordion/accordion.js +5 -4
  29. package/dist/node/app-shell/app-shell.js +28 -26
  30. package/dist/node/app-shell/app-shell.module.js +8 -8
  31. package/dist/node/breadcrumb/breadcrumb.js +1 -1
  32. package/dist/node/button/button.js +4 -1
  33. package/dist/node/button/button.module.js +4 -1
  34. package/dist/node/calendar/calendar.js +67 -63
  35. package/dist/node/card/card.module.js +8 -8
  36. package/dist/node/checkbox/checkbox.module.js +4 -4
  37. package/dist/node/code-snippet/code-snippet.js +31 -26
  38. package/dist/node/combobox/combobox.js +55 -54
  39. package/dist/node/data-table/data-table.js +155 -160
  40. package/dist/node/data-table/data-table.module.js +29 -29
  41. package/dist/node/date-picker/date-picker.js +90 -89
  42. package/dist/node/dock/dock.js +1 -1
  43. package/dist/node/field/field.module.js +3 -3
  44. package/dist/node/large-title-header/large-title-header.js +1 -1
  45. package/dist/node/layouts/src/grid/grid.module.js +3 -3
  46. package/dist/node/search/search.js +5 -4
  47. package/dist/node/side-nav/side-nav.js +90 -89
  48. package/dist/node/swap/swap.js +4 -3
  49. package/dist/node/switcher/switcher.js +1 -1
  50. package/dist/node/tabs/tabs.js +5 -4
  51. package/dist/node/toc/toc.js +5 -4
  52. package/dist/search/search.js +5 -4
  53. package/dist/side-nav/side-nav.js +90 -89
  54. package/dist/styles.css +7 -7
  55. package/dist/swap/swap.js +4 -3
  56. package/dist/switcher/switcher.js +1 -1
  57. package/dist/tabs/tabs.js +5 -4
  58. package/dist/toc/toc.js +5 -4
  59. package/dist/types.d.ts +21 -0
  60. package/dist/types.js +1 -0
  61. package/package.json +11 -4
  62. package/readme.body.md +14 -13
@@ -2,25 +2,25 @@
2
2
 
3
3
  import e from "./date-picker.module.js";
4
4
  import { useId as t, useRef as n } from "react";
5
- import { batch as r, cn as i, createMachine as a, useMachine as o, useSignal as s, useSignalEffect as c, useSignals as ee } from "@cascivo/core";
6
- import { builtin as l, currentLocale as te, t as u } from "@cascivo/i18n";
7
- import { jsx as d, jsxs as f } from "react/jsx-runtime";
5
+ import { batch as r, cn as i, createMachine as a, useControllableSignal as o, useMachine as s, useSignal as c, useSignalEffect as l, useSignals as ee } from "@cascivo/core";
6
+ import { builtin as u, currentLocale as d, t as f } from "@cascivo/i18n";
7
+ import { jsx as p, jsxs as m } from "react/jsx-runtime";
8
8
  //#region ../components/src/date-picker/date-picker.tsx
9
- var p = a({
9
+ var h = a({
10
10
  initial: "closed",
11
11
  states: {
12
12
  closed: { on: { OPEN: "open" } },
13
13
  open: { on: { CLOSE: "closed" } }
14
14
  }
15
15
  });
16
- function ne(e) {
16
+ function g(e) {
17
17
  try {
18
18
  let t = new Intl.Locale(e).weekInfo;
19
19
  if (t) return t.firstDay % 7;
20
20
  } catch {}
21
21
  return 1;
22
22
  }
23
- function m(e, t, n) {
23
+ function te(e, t, n) {
24
24
  let r = new Date(Date.UTC(e, t, 1)), i = new Date(Date.UTC(e, t + 1, 0)), a = (r.getUTCDay() - n + 7) % 7, o = [];
25
25
  for (let e = 0; e < a; e++) o.push(null);
26
26
  for (let n = 1; n <= i.getUTCDate(); n++) o.push(new Date(Date.UTC(e, t, n)));
@@ -29,170 +29,171 @@ function m(e, t, n) {
29
29
  for (let e = 0; e < o.length; e += 7) s.push(o.slice(e, e + 7));
30
30
  return s;
31
31
  }
32
- function h(e, t) {
32
+ function _(e, t) {
33
33
  return new Intl.DateTimeFormat(t).format(e);
34
34
  }
35
- function g(e) {
35
+ function v(e) {
36
36
  return e.toISOString().slice(0, 10);
37
37
  }
38
- function _(e) {
38
+ function y(e) {
39
39
  let [t, n, r] = e.split("-").map(Number);
40
40
  return new Date(Date.UTC(t, n - 1, r));
41
41
  }
42
- function v({ value: a, defaultValue: v, onValueChange: y, onChange: b, min: x, max: S, clearable: C = !1, label: w, hint: T, error: E, size: D = "md", disabled: O = !1, labels: k, className: re, id: A }) {
42
+ function b({ value: a, defaultValue: b, onValueChange: ne, onChange: x, min: S, max: C, clearable: w = !1, label: T, hint: E, error: D, size: re = "md", disabled: O = !1, labels: k, className: ie, id: ae }) {
43
43
  ee();
44
- let [j, M] = o(p), N = t(), P = A ?? `cascade-date-picker-${N}`, F = `${N}-grid`, I = te(), ie = k?.placeholder ?? u(l.datePicker.placeholder), ae = k?.previousMonth ?? u(l.datePicker.previousMonth), L = k?.nextMonth ?? u(l.datePicker.nextMonth), R = k?.clear ?? u(l.datePicker.clear), z = /* @__PURE__ */ new Date(), B = g(z), V = s(a ?? v);
45
- a !== void 0 && (V.value = a);
46
- let H = s(V.value ? _(V.value).getUTCFullYear() : z.getUTCFullYear()), U = s(V.value ? _(V.value).getUTCMonth() : z.getUTCMonth()), W = s(V.value), G = n(null);
47
- c(() => {
48
- if (j.value !== "open") return;
44
+ let [A, j] = s(h), M = t(), N = ae ?? `cascade-date-picker-${M}`, P = `${M}-grid`, F = d(), I = k?.placeholder ?? f(u.datePicker.placeholder), L = k?.previousMonth ?? f(u.datePicker.previousMonth), R = k?.nextMonth ?? f(u.datePicker.nextMonth), z = k?.clear ?? f(u.datePicker.clear), B = /* @__PURE__ */ new Date(), V = v(B), [H] = o({
45
+ value: a,
46
+ defaultValue: b
47
+ }), U = c(H.value ? y(H.value).getUTCFullYear() : B.getUTCFullYear()), W = c(H.value ? y(H.value).getUTCMonth() : B.getUTCMonth()), G = c(H.value), K = n(null);
48
+ l(() => {
49
+ if (A.value !== "open") return;
49
50
  let e = (e) => {
50
- G.current && !G.current.contains(e.target) && M("CLOSE");
51
+ K.current && !K.current.contains(e.target) && j("CLOSE");
51
52
  };
52
53
  return document.addEventListener("mousedown", e), () => document.removeEventListener("mousedown", e);
53
54
  });
54
- let K = () => {
55
- O || M("OPEN");
56
- }, q = () => M("CLOSE"), J = y ?? b, Y = (e) => {
57
- x && e < x || S && e > S || (a === void 0 && (V.value = e), J?.(e), q());
55
+ let q = () => {
56
+ O || j("OPEN");
57
+ }, J = () => j("CLOSE"), Y = ne ?? x, X = (e) => {
58
+ S && e < S || C && e > C || (a === void 0 && (H.value = e), Y?.(e), J());
58
59
  }, oe = (e) => {
59
- e.stopPropagation(), a === void 0 && (V.value = void 0), J?.(void 0);
60
+ e.stopPropagation(), a === void 0 && (H.value = void 0), Y?.(void 0);
60
61
  }, se = () => {
61
- U.value === 0 ? r(() => {
62
- H.value--, U.value = 11;
63
- }) : U.value--;
62
+ W.value === 0 ? r(() => {
63
+ U.value--, W.value = 11;
64
+ }) : W.value--;
64
65
  }, ce = () => {
65
- U.value === 11 ? r(() => {
66
- H.value++, U.value = 0;
67
- }) : U.value++;
68
- }, X = ne(I), Z = m(H.value, U.value, X), le = new Intl.DateTimeFormat(I, { weekday: "short" }), ue = Array.from({ length: 7 }, (e, t) => {
69
- let n = new Date(Date.UTC(2024, 0, 7 + X + t));
70
- return le.format(n);
71
- }), Q = new Intl.DateTimeFormat(I, {
66
+ W.value === 11 ? r(() => {
67
+ U.value++, W.value = 0;
68
+ }) : W.value++;
69
+ }, Z = g(F), le = te(U.value, W.value, Z), ue = new Intl.DateTimeFormat(F, { weekday: "short" }), de = Array.from({ length: 7 }, (e, t) => {
70
+ let n = new Date(Date.UTC(2024, 0, 7 + Z + t));
71
+ return ue.format(n);
72
+ }), Q = new Intl.DateTimeFormat(F, {
72
73
  month: "long",
73
74
  year: "numeric"
74
- }).format(new Date(Date.UTC(H.value, U.value, 1))), de = (e) => {
75
- let t = W.value;
75
+ }).format(new Date(Date.UTC(U.value, W.value, 1))), fe = (e) => {
76
+ let t = G.value;
76
77
  if (!t) return;
77
- let n = _(t), i;
78
+ let n = y(t), i;
78
79
  if (e.key === "ArrowRight") i = new Date(Date.UTC(n.getUTCFullYear(), n.getUTCMonth(), n.getUTCDate() + 1));
79
80
  else if (e.key === "ArrowLeft") i = new Date(Date.UTC(n.getUTCFullYear(), n.getUTCMonth(), n.getUTCDate() - 1));
80
81
  else if (e.key === "ArrowDown") i = new Date(Date.UTC(n.getUTCFullYear(), n.getUTCMonth(), n.getUTCDate() + 7));
81
82
  else if (e.key === "ArrowUp") i = new Date(Date.UTC(n.getUTCFullYear(), n.getUTCMonth(), n.getUTCDate() - 7));
82
83
  else if (e.key === "Enter" || e.key === " ") {
83
- e.preventDefault(), Y(t);
84
+ e.preventDefault(), X(t);
84
85
  return;
85
86
  } else if (e.key === "Escape") {
86
- q();
87
+ J();
87
88
  return;
88
89
  } else return;
89
90
  if (e.preventDefault(), i) {
90
- let e = g(i);
91
- if (x && e < x || S && e > S) return;
92
- W.value = e, r(() => {
93
- H.value = i.getUTCFullYear(), U.value = i.getUTCMonth();
91
+ let e = v(i);
92
+ if (S && e < S || C && e > C) return;
93
+ G.value = e, r(() => {
94
+ U.value = i.getUTCFullYear(), W.value = i.getUTCMonth();
94
95
  });
95
96
  }
96
- }, $ = V.value ? h(_(V.value), I) : "";
97
- return /* @__PURE__ */ f("div", {
98
- ref: G,
99
- className: i(e.wrapper, re),
100
- "data-state": E ? "error" : j.value,
101
- "data-size": D,
97
+ }, $ = H.value ? _(y(H.value), F) : "";
98
+ return /* @__PURE__ */ m("div", {
99
+ ref: K,
100
+ className: i(e.wrapper, ie),
101
+ "data-state": D ? "error" : A.value,
102
+ "data-size": re,
102
103
  children: [
103
- w && /* @__PURE__ */ d("label", {
104
+ T && /* @__PURE__ */ p("label", {
104
105
  className: e.label,
105
- htmlFor: P,
106
- children: w
106
+ htmlFor: N,
107
+ children: T
107
108
  }),
108
- /* @__PURE__ */ f("div", {
109
+ /* @__PURE__ */ m("div", {
109
110
  className: e.field,
110
- children: [/* @__PURE__ */ f("button", {
111
- id: P,
111
+ children: [/* @__PURE__ */ m("button", {
112
+ id: N,
112
113
  type: "button",
113
114
  role: "combobox",
114
- "aria-expanded": j.value === "open",
115
- "aria-controls": F,
115
+ "aria-expanded": A.value === "open",
116
+ "aria-controls": P,
116
117
  "aria-haspopup": "dialog",
117
- "aria-invalid": E ? !0 : void 0,
118
- "aria-describedby": E ? `${N}-error` : T ? `${N}-hint` : void 0,
118
+ "aria-invalid": D ? !0 : void 0,
119
+ "aria-describedby": D ? `${M}-error` : E ? `${M}-hint` : void 0,
119
120
  className: e.trigger,
120
121
  disabled: O,
121
- onClick: j.value === "open" ? q : K,
122
- children: [/* @__PURE__ */ d("span", {
122
+ onClick: A.value === "open" ? J : q,
123
+ children: [/* @__PURE__ */ p("span", {
123
124
  className: i(e.value, $ ? void 0 : e.placeholder),
124
- children: $ || ie
125
- }), /* @__PURE__ */ d("span", {
125
+ children: $ || I
126
+ }), /* @__PURE__ */ p("span", {
126
127
  className: e.icon,
127
128
  "aria-hidden": "true",
128
129
  children: "📅"
129
130
  })]
130
- }), C && V.value !== void 0 && /* @__PURE__ */ d("button", {
131
+ }), w && H.value !== void 0 && /* @__PURE__ */ p("button", {
131
132
  type: "button",
132
133
  className: e.clear,
133
- "aria-label": R,
134
+ "aria-label": z,
134
135
  onClick: oe,
135
136
  children: "✕"
136
137
  })]
137
138
  }),
138
- /* @__PURE__ */ f("div", {
139
- id: F,
139
+ /* @__PURE__ */ m("div", {
140
+ id: P,
140
141
  role: "dialog",
141
142
  "aria-label": Q,
142
143
  className: e.calendar,
143
- "data-state": j.value,
144
- onKeyDown: de,
145
- children: [/* @__PURE__ */ f("div", {
144
+ "data-state": A.value,
145
+ onKeyDown: fe,
146
+ children: [/* @__PURE__ */ m("div", {
146
147
  className: e.header,
147
148
  children: [
148
- /* @__PURE__ */ d("button", {
149
+ /* @__PURE__ */ p("button", {
149
150
  type: "button",
150
151
  className: e.navButton,
151
- "aria-label": ae,
152
+ "aria-label": L,
152
153
  onClick: se,
153
154
  children: "‹"
154
155
  }),
155
- /* @__PURE__ */ d("span", {
156
+ /* @__PURE__ */ p("span", {
156
157
  className: e.monthLabel,
157
158
  "aria-live": "polite",
158
159
  children: Q
159
160
  }),
160
- /* @__PURE__ */ d("button", {
161
+ /* @__PURE__ */ p("button", {
161
162
  type: "button",
162
163
  className: e.navButton,
163
- "aria-label": L,
164
+ "aria-label": R,
164
165
  onClick: ce,
165
166
  children: "›"
166
167
  })
167
168
  ]
168
- }), /* @__PURE__ */ f("table", {
169
+ }), /* @__PURE__ */ m("table", {
169
170
  role: "grid",
170
171
  className: e.grid,
171
- children: [/* @__PURE__ */ d("thead", { children: /* @__PURE__ */ d("tr", { children: ue.map((t) => /* @__PURE__ */ d("th", {
172
+ children: [/* @__PURE__ */ p("thead", { children: /* @__PURE__ */ p("tr", { children: de.map((t) => /* @__PURE__ */ p("th", {
172
173
  className: e.weekday,
173
174
  abbr: t,
174
175
  scope: "col",
175
176
  children: t
176
- }, t)) }) }), /* @__PURE__ */ d("tbody", { children: Z.map((t, n) => /* @__PURE__ */ d("tr", { children: t.map((t, n) => {
177
- if (!t) return /* @__PURE__ */ d("td", { className: e.empty }, n);
178
- let r = g(t), i = r === V.value, a = r === B, o = r === W.value, s = x !== void 0 && r < x || S !== void 0 && r > S;
179
- return /* @__PURE__ */ d("td", {
177
+ }, t)) }) }), /* @__PURE__ */ p("tbody", { children: le.map((t, n) => /* @__PURE__ */ p("tr", { children: t.map((t, n) => {
178
+ if (!t) return /* @__PURE__ */ p("td", { className: e.empty }, n);
179
+ let r = v(t), i = r === H.value, a = r === V, o = r === G.value, s = S !== void 0 && r < S || C !== void 0 && r > C;
180
+ return /* @__PURE__ */ p("td", {
180
181
  className: e.cell,
181
- children: /* @__PURE__ */ d("button", {
182
+ children: /* @__PURE__ */ p("button", {
182
183
  type: "button",
183
184
  className: e.day,
184
185
  tabIndex: o ? 0 : -1,
185
186
  "aria-pressed": i,
186
- "aria-label": h(t, I),
187
+ "aria-label": _(t, F),
187
188
  "aria-current": a ? "date" : void 0,
188
189
  "aria-disabled": s || void 0,
189
190
  "data-selected": i || void 0,
190
191
  "data-today": a || void 0,
191
192
  onClick: () => {
192
- s || Y(r);
193
+ s || X(r);
193
194
  },
194
195
  onFocus: () => {
195
- W.value = r;
196
+ G.value = r;
196
197
  },
197
198
  children: t.getUTCDate()
198
199
  })
@@ -200,19 +201,19 @@ function v({ value: a, defaultValue: v, onValueChange: y, onChange: b, min: x, m
200
201
  }) }, n)) })]
201
202
  })]
202
203
  }),
203
- E && /* @__PURE__ */ d("span", {
204
- id: `${N}-error`,
204
+ D && /* @__PURE__ */ p("span", {
205
+ id: `${M}-error`,
205
206
  className: e.error,
206
207
  role: "alert",
207
- children: E
208
+ children: D
208
209
  }),
209
- !E && T && /* @__PURE__ */ d("span", {
210
- id: `${N}-hint`,
210
+ !D && E && /* @__PURE__ */ p("span", {
211
+ id: `${M}-hint`,
211
212
  className: e.hint,
212
- children: T
213
+ children: E
213
214
  })
214
215
  ]
215
216
  });
216
217
  }
217
218
  //#endregion
218
- export { v as DatePicker };
219
+ export { b as DatePicker };
package/dist/dock/dock.js CHANGED
@@ -26,7 +26,7 @@ function s({ items: s, activeIndex: c, className: l, ariaLabel: u }) {
26
26
  className: e.label,
27
27
  children: n.label
28
28
  })]
29
- }, r);
29
+ }, n.id ?? `${r}-${n.label}`);
30
30
  })
31
31
  });
32
32
  }
@@ -1 +1 @@
1
- @layer cascivo.component{._field_ws86v_2{gap:var(--cascivo-space-2);font-family:var(--cascivo-font-sans);display:grid}._field_ws86v_2[data-disabled]{opacity:.5}._description_ws86v_12{font-size:var(--cascivo-text-sm);line-height:var(--cascivo-leading-snug);color:var(--cascivo-color-text-muted);margin:0}._error_ws86v_19{font-size:var(--cascivo-text-sm);line-height:var(--cascivo-leading-snug);color:var(--cascivo-color-destructive);margin:0}}@media (forced-colors:active){._error_ws86v_19{color:buttontext}}
1
+ @layer cascivo.component{._field_1y14o_2{gap:var(--cascivo-space-2);font-family:var(--cascivo-font-sans);align-content:start;display:grid}._field_1y14o_2[data-disabled]{opacity:.5}._description_1y14o_20{font-size:var(--cascivo-text-sm);line-height:var(--cascivo-leading-snug);color:var(--cascivo-color-text-muted);margin:0}._error_1y14o_27{font-size:var(--cascivo-text-sm);line-height:var(--cascivo-leading-snug);color:var(--cascivo-color-destructive);margin:0}}@media (forced-colors:active){._error_1y14o_27{color:buttontext}}
@@ -1,8 +1,8 @@
1
1
  import './field.css';
2
2
  var e = {
3
- field: "_field_ws86v_2",
4
- description: "_description_ws86v_12",
5
- error: "_error_ws86v_19"
3
+ field: "_field_1y14o_2",
4
+ description: "_description_1y14o_20",
5
+ error: "_error_1y14o_27"
6
6
  };
7
7
  //#endregion
8
8
  export { e as default };
package/dist/index.d.ts CHANGED
@@ -24,6 +24,16 @@
24
24
  import { AnchorHTMLAttributes, ButtonHTMLAttributes, FormHTMLAttributes, HTMLAttributes, ImgHTMLAttributes, InputHTMLAttributes, LabelHTMLAttributes, LiHTMLAttributes, MouseEvent, ReactElement, ReactNode, RefObject, SelectHTMLAttributes, TextareaHTMLAttributes, TimeHTMLAttributes } from "react";
25
25
  import { DismissableLayer, DismissableLayerProps, ErrorBoundary, FocusScope, LinkComponent, LinkComponentProps, Machine, MachineConfig, Portal, Presence, ProgressInput, RovingOrientation, Signal, Slot, SlotProps, SpaceStep, SuspenseBoundary, ThemeProvider, ThemeProviderProps, ToneInput, UseClipboardOptions, UseClipboardReturn, UseControllableSignalOptions, UseDisclosureOptions, UseDisclosureReturn, VisuallyHidden, VisuallyHiddenProps, applyTheme, batch, cn, composeRefs, computePosition, computed, createMachine, createScope, createStreamBuffer, effect, getLinkComponent, mergeProps, setLinkComponent, setTheme, signal, themePreloadScript, themeSignal, useAnchorPosition, useClipboard, useComputed, useControllableSignal, useDisclosure, useEffectPropSignal, useId, useMachine, useMediaQuery, useRovingFocus, useScope, useScrollLock, useSignal, useSignalEffect, useSignals, useStreamBuffer, useTheme, useTypeahead } from "@cascivo/core";
26
26
 
27
+ /**
28
+ * Button.
29
+ *
30
+ * ⚠ **DOM shape:** children are wrapped in an inner `<span>` so the loading `Spinner` can be
31
+ * a sibling rather than being nested inside the label. Layout CSS written against
32
+ * `.my-button > span` therefore targets that wrapper, not your content — one adopter's
33
+ * `> span { display: flex }` hit the wrapper and collapsed the spacing inside it. The wrapper
34
+ * is already a flex row that inherits the button's `gap`, so composing an icon with a label
35
+ * needs no CSS of your own.
36
+ */
27
37
  interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
28
38
  /**
29
39
  * Selects the visual style variant.
@@ -78,7 +88,12 @@ interface CardProps extends HTMLAttributes<HTMLDivElement> {
78
88
  */
79
89
  variant?: 'default' | 'outlined' | 'elevated';
80
90
  /**
81
- * Inner padding of the component.
91
+ * Inner padding of the CARD BOX. ⚠ `padding="none"` deliberately does NOT strip the
92
+ * padding from CardHeader/CardContent/CardFooter — those keep their own. It means "let a
93
+ * flush child (a LogViewer, an image, an edge-to-edge table) reach the card's edge";
94
+ * zeroing both put the title flush against the border and made the mode unusable with the
95
+ * composition it exists for. For an edge-to-edge table, skip CardContent and pass the
96
+ * table as a direct child.
82
97
  *
83
98
  * @defaultValue `md`
84
99
  * @see the component manifest
@@ -128,16 +143,29 @@ declare function CardFooter({
128
143
  children,
129
144
  ...props
130
145
  }: CardFooterProps): import("react").JSX.Element;
131
- /** Badge-only looks that aren't a severity tone. */
132
- type BadgeShape = 'secondary' | 'outline' | 'primary';
146
+ /**
147
+ * Badge-only looks that aren't a severity tone.
148
+ *
149
+ * Named for the PROP it types, not for a prop that does not exist. As `BadgeShape` it sat
150
+ * directly above `BadgeProps` in the generated `.d.ts` and read as the type of a `shape`
151
+ * prop, so an adopter wrote `<Badge shape="outline">` in four files before the compiler
152
+ * disagreed (2026-08-08 report A). A type named after a prop the component does not have is
153
+ * a trap of our own making.
154
+ */
155
+ type BadgeVariant = 'secondary' | 'outline' | 'primary';
133
156
  interface BadgeProps extends HTMLAttributes<HTMLSpanElement> {
134
157
  /**
135
158
  * Severity tone or badge-specific look. Accepts the catalog-wide `Tone` vocabulary
136
159
  * (`neutral | info | success | warning | danger`) as well as Badge's historical spellings
137
160
  * (`default`, `destructive`, `error`) — they are aliases of the same tones, so one domain
138
161
  * enum can drive `Badge`, `Tag`, `Status` and `Notification` with no lookup table.
162
+ *
163
+ * To name this type in your own code, import it: `import type { Tone } from
164
+ * '@cascivo/react/types'` on the prebuilt path, or from `@cascivo/core` if you copied the
165
+ * source. Do not add `@cascivo/core` to a prebuilt app just for this; it is a transitive
166
+ * dependency there.
139
167
  */
140
- variant?: ToneInput | BadgeShape;
168
+ variant?: ToneInput | BadgeVariant;
141
169
  size?: 'sm' | 'md';
142
170
  }
143
171
  declare function Badge({
@@ -685,7 +713,8 @@ interface TabsTriggerProps extends HTMLAttributes<HTMLButtonElement> {
685
713
  *
686
714
  * With `asChild`, `disabled` becomes `aria-disabled`: it is not a valid attribute on an
687
715
  * anchor, and a slotted element gets no `type` either. See
688
- * [USING-WITH-A-ROUTER.md](../../../../docs/USING-WITH-A-ROUTER.md) for the full recipe.
716
+ * https://cascivo.com/docs/using-with-a-router.md for the full recipe — offline:
717
+ * `npx -y @cascivo/docs guide using-with-a-router`.
689
718
  */
690
719
  asChild?: boolean;
691
720
  }
@@ -816,7 +845,8 @@ interface LinkProps extends AnchorHTMLAttributes<HTMLAnchorElement> {
816
845
  * styling lands on your router's `Link`. **This is the supported way to style an
817
846
  * in-content router link** — `setLinkComponent` only covers the config-driven nav
818
847
  * components (SideNav, ShellHeader, Breadcrumb, …), not links you write in page
819
- * content. See `docs/USING-WITH-A-ROUTER.md`.
848
+ * content. See https://cascivo.com/docs/using-with-a-router.md — offline:
849
+ * `npx -y @cascivo/docs guide using-with-a-router`.
820
850
  *
821
851
  * ```tsx
822
852
  * <Link asChild><RouterLink to="/projects/a">Project A</RouterLink></Link>
@@ -832,6 +862,17 @@ interface LinkProps extends AnchorHTMLAttributes<HTMLAnchorElement> {
832
862
  */
833
863
  declare const Link: import("react").ForwardRefExoticComponent<LinkProps & import("react").RefAttributes<HTMLAnchorElement>>;
834
864
  interface BreadcrumbItem {
865
+ /**
866
+ * Stable React key. Provide when `label`/`href` may repeat.
867
+ *
868
+ * A real breadcrumb repeats hrefs — "Overview" and "Projects" both pointing at `/` is the
869
+ * normal shape of a console trail — and without an `id` the crumbs key on their index, so
870
+ * reordering or truncating the trail re-keys every row after the change.
871
+ * `SideNavItem`, `ShellHeaderNavLink`, `ShellHeaderNavMenuItem`, `HeaderLink`,
872
+ * `CommandItem` and `SwitcherLink` all carry this field; `BreadcrumbItem` was missed by
873
+ * both earlier sweeps (2026-08-14 report §9).
874
+ */
875
+ id?: string;
835
876
  label: string;
836
877
  href?: string;
837
878
  }
@@ -1461,6 +1502,14 @@ interface Column<Row> {
1461
1502
  * can exceed its container — the extra columns are reachable by horizontal scroll, not
1462
1503
  * dropped. Leave at least one free-form column unsized unless you specifically want
1463
1504
  * page-stable widths.
1505
+ *
1506
+ * ⚠ **"Leave one unsized" is necessary, not sufficient.** The leftover width is split
1507
+ * between the unsized columns by `table-layout: auto`, which weighs them by content — so
1508
+ * if the sized columns nearly fill the table, what remains can be narrower than the
1509
+ * content needs and long tokens wrap mid-word (`acme-` / `storefront`). Reported at
1510
+ * 6-of-8 columns sized. Rules of thumb: leave the widest free-form column unsized, keep
1511
+ * the sized columns to roughly two thirds of the table, and give the free-form one a
1512
+ * `minWidth` when the data has long unbreakable tokens like slugs or IDs.
1464
1513
  */
1465
1514
  width?: string;
1466
1515
  /**
@@ -1515,6 +1564,18 @@ interface DataTableProps<Row> {
1515
1564
  onClick: (selectedIds: string[]) => void;
1516
1565
  }[];
1517
1566
  renderExpandedRow?: (row: Row) => ReactNode;
1567
+ /**
1568
+ * Row height preset.
1569
+ *
1570
+ * ⚠ It sets a row **height floor** (`--_row-height`), so it is invisible whenever the cell
1571
+ * content is already taller — a two-line cell or a cell containing a `Badge` stack looks
1572
+ * identical at every density. Reported as "barely distinguishable"; the prop is working,
1573
+ * the content is simply winning. Shrink the cell content, or set
1574
+ * `--cascivo-data-table-cell-gap` to tighten the horizontal rhythm too.
1575
+ *
1576
+ * @defaultValue `normal`
1577
+ * @see the component manifest
1578
+ */
1518
1579
  density?: 'compact' | 'normal' | 'relaxed';
1519
1580
  /**
1520
1581
  * When true, applies alternating row striping.
@@ -2650,6 +2711,16 @@ declare function HeaderPanel({
2650
2711
  className
2651
2712
  }: HeaderPanelProps): import("react").JSX.Element;
2652
2713
  interface SwitcherLink {
2714
+ /**
2715
+ * Stable React key. Provide when `label`/`href` may repeat (e.g. placeholder `#` links).
2716
+ *
2717
+ * Without it the rows key on `href`, so three sibling teams that all link to `/` produce
2718
+ * duplicate-key warnings on every render and the adopter has to make the hrefs artificially
2719
+ * distinct (2026-08-08 report A). `SideNavItem`, `ShellHeaderNavLink`,
2720
+ * `ShellHeaderNavMenuItem`, `HeaderLink` and `CommandItem` all carry this field already;
2721
+ * `Switcher` was missed by that sweep.
2722
+ */
2723
+ id?: string;
2653
2724
  label: string;
2654
2725
  href: string;
2655
2726
  active?: boolean;
@@ -2729,6 +2800,16 @@ interface StatProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
2729
2800
  * a `Card` you control; `Kpi` always brings its own chrome, which made a `Stat` row and
2730
2801
  * a `Kpi` row on adjacent pages of one dashboard look like different products. Set this
2731
2802
  * when you are mixing the two, or use it instead of hand-wrapping every `Stat` in a `Card`.
2803
+ *
2804
+ * ⚠ **`card` matches the CHROME only — the internal layout still differs, so do not mix
2805
+ * `Stat` and `Kpi` in one app.** `Kpi` puts value and delta on one line with the sparkline
2806
+ * below; `Stat` stacks value → delta → help text and puts `visual` in a trailing slot.
2807
+ * With `card` set they share surface, border, radius and padding and still read as two
2808
+ * tile designs (2026-08-14 report §6 — the exact symptom this prop was added to cure, on
2809
+ * an overview page using `Stat card` next to an analytics page using `Kpi`).
2810
+ *
2811
+ * Pick one per app: `Kpi` when you have a numeric delta it should format and a sparkline;
2812
+ * `Stat` otherwise.
2732
2813
  */
2733
2814
  card?: boolean;
2734
2815
  /** Trailing visual, e.g. a `Sparkline` from the separate `@cascivo/charts` package (not exported from `@cascivo/react`; `pnpm add @cascivo/charts`). Purely decorative — mark it `aria-hidden` yourself if it duplicates the value/delta already announced. */
@@ -2751,6 +2832,11 @@ interface StatusProps extends HTMLAttributes<HTMLSpanElement> {
2751
2832
  * Severity tone. Accepts the catalog-wide `Tone` vocabulary
2752
2833
  * (`neutral | info | success | warning | danger`) plus Status's historical spellings
2753
2834
  * (`error`, `destructive`, `default`).
2835
+ *
2836
+ * To name this type in your own code — a `Record<DeployState, Tone>` is the usual shape —
2837
+ * import it: `import type { Tone } from '@cascivo/react/types'` on the prebuilt path, or
2838
+ * from `@cascivo/core` if you copied the source. Do not add `@cascivo/core` to a prebuilt
2839
+ * app just for this; it is a transitive dependency there.
2754
2840
  */
2755
2841
  status?: ToneInput;
2756
2842
  /**
@@ -4128,6 +4214,16 @@ declare function Resizable({
4128
4214
  label
4129
4215
  }: ResizableProps): import("react").JSX.Element;
4130
4216
  interface DockItem {
4217
+ /**
4218
+ * Stable React key. Provide when `label`/`href` may repeat.
4219
+ *
4220
+ * Without it the items key on their array index, so inserting or reordering a dock entry
4221
+ * re-keys every item after it. `SideNavItem`, `ShellHeaderNavLink`, `SwitcherLink`,
4222
+ * `BreadcrumbItem` and the rest carry this field; `Dock` was missed by all three earlier
4223
+ * sweeps and found only once the guard derived its subjects instead of listing them
4224
+ * (2026-08-14 report §9).
4225
+ */
4226
+ id?: string;
4131
4227
  label: string;
4132
4228
  icon: React.ReactNode;
4133
4229
  onClick?: () => void;
@@ -4442,8 +4538,24 @@ interface NativeSelectProps extends Omit<SelectHTMLAttributes<HTMLSelectElement>
4442
4538
  declare const NativeSelect: import("react").ForwardRefExoticComponent<NativeSelectProps & import("react").RefAttributes<HTMLSelectElement>>;
4443
4539
  type CodeLang = 'bash' | 'css' | 'js' | 'ts';
4444
4540
  interface CodeSnippetProps {
4445
- /** The code to display (and copy). */
4446
- code: string;
4541
+ /**
4542
+ * The code to display (and copy). Equivalent to passing a plain string as `children`;
4543
+ * `code` wins if you pass both.
4544
+ *
4545
+ * One of the two is required. It is a **string**, not a `ReactNode`, because the content
4546
+ * is tokenized for highlighting and handed to the clipboard — neither works on arbitrary
4547
+ * JSX, so accepting nodes here would silently produce an uncopyable snippet.
4548
+ */
4549
+ code?: string;
4550
+ /**
4551
+ * The code, as children — `<CodeSnippet>npm i foo</CodeSnippet>`.
4552
+ *
4553
+ * Every other content component in the catalog takes children, so this was the natural
4554
+ * guess and the only compile error in a 2026-08-14 adopter's whole build (§8). Must be a
4555
+ * plain string for the reason on `code` above; interpolation is fine
4556
+ * (`{`npm i ${pkg}`}`), arbitrary elements are not.
4557
+ */
4558
+ children?: string;
4447
4559
  /**
4448
4560
  * inline = a <code> span; single = one-line <pre>; multi = multi-line <pre>.
4449
4561
  *
@@ -4482,6 +4594,7 @@ interface CodeSnippetProps {
4482
4594
  */
4483
4595
  declare function CodeSnippet({
4484
4596
  code,
4597
+ children,
4485
4598
  variant,
4486
4599
  language,
4487
4600
  terminal,
@@ -4645,6 +4758,20 @@ interface AppShellProps extends HTMLAttributes<HTMLDivElement> {
4645
4758
  defaultOpen?: boolean;
4646
4759
  /** Fired when the nav requests open/close (burger, Escape, scrim). */
4647
4760
  onOpenChange?: ((open: boolean) => void) | undefined;
4761
+ /**
4762
+ * Inset around the main content area, as a space-scale step.
4763
+ *
4764
+ * ⚠ It **defaults to `6`**, not to none. `<main>` shipped with `padding: 0` for three
4765
+ * releases, so every adopter wrote the same wrapper `<div style={{ padding: … }}>` and
4766
+ * every app's first screenshot had its buttons clipped against the viewport edge — the CLI's
4767
+ * own generated dashboard modelled the workaround with an inline style its sibling
4768
+ * AGENTS.md forbids. Reported three times (2026-07-24, 2026-08-06, 2026-08-08).
4769
+ *
4770
+ * Pass `'none'` for a full-bleed layout that owns its own insets (a map, a split pane).
4771
+ *
4772
+ * @defaultValue `6`
4773
+ */
4774
+ padding?: SpaceStep | 'none';
4648
4775
  className?: string | undefined;
4649
4776
  }
4650
4777
  /**
@@ -4673,6 +4800,7 @@ declare function AppShell({
4673
4800
  open,
4674
4801
  defaultOpen,
4675
4802
  onOpenChange,
4803
+ padding,
4676
4804
  className,
4677
4805
  ...props
4678
4806
  }: AppShellProps): import("react").JSX.Element;
@@ -4969,8 +5097,27 @@ declare function AutoGrid({
4969
5097
  ...props
4970
5098
  }: AutoGridProps): import("react").JSX.Element;
4971
5099
  interface PageHeaderProps {
4972
- title: string;
4973
- description?: string;
5100
+ /**
5101
+ * The page title, rendered as the `<h1>`.
5102
+ *
5103
+ * `ReactNode`, not `string`, so a deploy console can put the production domain in the
5104
+ * heading as a link and a status badge beside the project name — the canonical shape of a
5105
+ * project header. `RECIPE-DASHBOARD.md` tells you not to hand-compose `PageHeader` out of
5106
+ * `Heading`/`Text`/`Flex`, so this has to be composable here (2026-08-14 report §7).
5107
+ *
5108
+ * ```tsx
5109
+ * <PageHeader
5110
+ * title={<>acme-web <Badge variant="success">Ready</Badge></>}
5111
+ * description={<>Deployed from <Link asChild><RouterLink to="/c/abc">abc123</RouterLink></Link></>}
5112
+ * />
5113
+ * ```
5114
+ *
5115
+ * Keep it short and heading-like: it is an `<h1>`, so anything block-level inside it is
5116
+ * invalid HTML and will fight the heading's own typography.
5117
+ */
5118
+ title: ReactNode;
5119
+ /** Supporting line under the title, rendered as a `<p>`. Accepts nodes, like `title`. */
5120
+ description?: ReactNode;
4974
5121
  breadcrumb?: ReactNode;
4975
5122
  actions?: ReactNode;
4976
5123
  className?: string;
@@ -1,5 +1,5 @@
1
1
  import e from "./large-title-header.module.js";
2
- import { cn as t } from "@cascivo/core";
2
+ import { cn as t } from "@cascivo/core/pure";
3
3
  import { jsx as n, jsxs as r } from "react/jsx-runtime";
4
4
  //#region ../components/src/large-title-header/large-title-header.tsx
5
5
  function i({ title: i, children: a, leading: o, actions: s, level: c = 1, collapseDistance: l = 48, className: u }) {
@@ -1 +1 @@
1
- @layer cascivo.component{._grid-container_qly9o_5{display:grid;container-type:inline-size}._grid_qly9o_2{grid-template-columns:repeat(var(--_grid-cols,12), minmax(0, 1fr));gap:var(--_grid-gap,var(--cascivo-space-4));align-items:var(--_grid-align,stretch);justify-items:var(--_grid-justify,stretch);min-inline-size:0;display:grid;container-type:inline-size}@container (width<=40rem){._grid_qly9o_2:not([data-responsive]){grid-template-columns:1fr}}@container (width>=30rem){._grid_qly9o_2[data-responsive]{grid-template-columns:repeat(var(--_grid-cols-sm,var(--_grid-cols,12)), minmax(0, 1fr))}}@container (width>=40rem){._grid_qly9o_2[data-responsive]{grid-template-columns:repeat(var(--_grid-cols-md,var(--_grid-cols-sm,var(--_grid-cols,12))), minmax(0, 1fr))}}@container (width>=64rem){._grid_qly9o_2[data-responsive]{grid-template-columns:repeat(var(--_grid-cols-lg,var(--_grid-cols-md,var(--_grid-cols-sm,var(--_grid-cols,12)))), minmax(0, 1fr))}}@container (width>=80rem){._grid_qly9o_2[data-responsive]{grid-template-columns:repeat(var(--_grid-cols-xl,var(--_grid-cols-lg,var(--_grid-cols-md,var(--_grid-cols-sm,var(--_grid-cols,12))))), minmax(0, 1fr))}}._grid-item_qly9o_55{grid-column:span var(--_span,1)}@container (width>=30rem){._grid-item_qly9o_55[data-responsive]{grid-column:span var(--_span-sm,var(--_span,1))}}@container (width>=40rem){._grid-item_qly9o_55[data-responsive]{grid-column:span var(--_span-md,var(--_span-sm,var(--_span,1)))}}@container (width>=64rem){._grid-item_qly9o_55[data-responsive]{grid-column:span var(--_span-lg,var(--_span-md,var(--_span-sm,var(--_span,1))))}}@container (width>=80rem){._grid-item_qly9o_55[data-responsive]{grid-column:span var(--_span-xl,var(--_span-lg,var(--_span-md,var(--_span-sm,var(--_span,1)))))}}}
1
+ @layer cascivo.component{._grid-container_1tchk_5{display:grid;container-type:inline-size}._grid_1tchk_2{grid-template-columns:repeat(var(--_grid-cols,12), minmax(0, 1fr));gap:var(--_grid-gap,var(--cascivo-space-4));align-items:var(--_grid-align,stretch);justify-items:var(--_grid-justify,stretch);min-inline-size:0;display:grid;container-type:inline-size}@container (width<=40rem){._grid_1tchk_2:not([data-responsive]){grid-template-columns:1fr}}@container (width>=30rem){._grid_1tchk_2[data-responsive]{grid-template-columns:repeat(var(--_grid-cols-sm,var(--_grid-cols,12)), minmax(0, 1fr))}}@container (width>=40rem){._grid_1tchk_2[data-responsive]{grid-template-columns:repeat(var(--_grid-cols-md,var(--_grid-cols-sm,var(--_grid-cols,12))), minmax(0, 1fr))}}@container (width>=64rem){._grid_1tchk_2[data-responsive]{grid-template-columns:repeat(var(--_grid-cols-lg,var(--_grid-cols-md,var(--_grid-cols-sm,var(--_grid-cols,12)))), minmax(0, 1fr))}}@container (width>=80rem){._grid_1tchk_2[data-responsive]{grid-template-columns:repeat(var(--_grid-cols-xl,var(--_grid-cols-lg,var(--_grid-cols-md,var(--_grid-cols-sm,var(--_grid-cols,12))))), minmax(0, 1fr))}}._grid-item_1tchk_55{grid-column:span var(--_span,1);align-content:stretch;display:grid}@container (width>=30rem){._grid-item_1tchk_55[data-responsive]{grid-column:span var(--_span-sm,var(--_span,1))}}@container (width>=40rem){._grid-item_1tchk_55[data-responsive]{grid-column:span var(--_span-md,var(--_span-sm,var(--_span,1)))}}@container (width>=64rem){._grid-item_1tchk_55[data-responsive]{grid-column:span var(--_span-lg,var(--_span-md,var(--_span-sm,var(--_span,1))))}}@container (width>=80rem){._grid-item_1tchk_55[data-responsive]{grid-column:span var(--_span-xl,var(--_span-lg,var(--_span-md,var(--_span-sm,var(--_span,1)))))}}}