@cascivo/react 0.16.0 → 0.17.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.
Files changed (99) hide show
  1. package/README.md +6 -1
  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/badge/badge.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/combobox/combobox.js +55 -54
  16. package/dist/context-menu/context-menu.js +42 -38
  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/field/field.css +1 -1
  22. package/dist/field/field.module.js +3 -3
  23. package/dist/index.d.ts +307 -145
  24. package/dist/infinite-scroll/infinite-scroll.css +1 -0
  25. package/dist/infinite-scroll/infinite-scroll.js +49 -0
  26. package/dist/infinite-scroll/infinite-scroll.module.js +8 -0
  27. package/dist/large-title-header/large-title-header.css +1 -0
  28. package/dist/large-title-header/large-title-header.js +38 -0
  29. package/dist/large-title-header/large-title-header.module.js +13 -0
  30. package/dist/layouts/src/grid/grid.css +1 -1
  31. package/dist/layouts/src/grid/grid.module.js +3 -3
  32. package/dist/link/link.css +1 -1
  33. package/dist/link/link.module.js +1 -1
  34. package/dist/menu/menu.js +47 -43
  35. package/dist/node/accordion/accordion.js +5 -4
  36. package/dist/node/app-shell/app-shell.js +28 -26
  37. package/dist/node/app-shell/app-shell.module.js +8 -8
  38. package/dist/node/badge/badge.js +1 -1
  39. package/dist/node/button/button.js +4 -1
  40. package/dist/node/button/button.module.js +4 -1
  41. package/dist/node/calendar/calendar.js +67 -63
  42. package/dist/node/card/card.module.js +8 -8
  43. package/dist/node/checkbox/checkbox.module.js +4 -4
  44. package/dist/node/combobox/combobox.js +55 -54
  45. package/dist/node/context-menu/context-menu.js +42 -38
  46. package/dist/node/data-table/data-table.js +155 -160
  47. package/dist/node/data-table/data-table.module.js +29 -29
  48. package/dist/node/date-picker/date-picker.js +90 -89
  49. package/dist/node/field/field.module.js +3 -3
  50. package/dist/node/infinite-scroll/infinite-scroll.js +49 -0
  51. package/dist/node/infinite-scroll/infinite-scroll.module.js +7 -0
  52. package/dist/node/large-title-header/large-title-header.js +38 -0
  53. package/dist/node/large-title-header/large-title-header.module.js +12 -0
  54. package/dist/node/layouts/src/grid/grid.module.js +3 -3
  55. package/dist/node/link/link.module.js +1 -1
  56. package/dist/node/menu/menu.js +47 -43
  57. package/dist/node/react/src/index.js +27 -23
  58. package/dist/node/reorder-list/reorder-list.js +143 -0
  59. package/dist/node/reorder-list/reorder-list.module.js +11 -0
  60. package/dist/node/search/search.js +5 -4
  61. package/dist/node/side-nav/side-nav.js +90 -89
  62. package/dist/node/skip-nav/skip-nav.js +1 -0
  63. package/dist/node/swap/swap.js +2 -3
  64. package/dist/node/switcher/switcher.js +1 -1
  65. package/dist/node/tabs/tabs.js +41 -40
  66. package/dist/node/tag/tag.module.js +2 -2
  67. package/dist/node/toc/toc.js +5 -4
  68. package/dist/node/virtual-list/virtual-list.js +40 -0
  69. package/dist/node/virtual-list/virtual-list.module.js +7 -0
  70. package/dist/node/wheel-picker/wheel-picker.js +84 -0
  71. package/dist/node/wheel-picker/wheel-picker.module.js +8 -0
  72. package/dist/react/src/index.js +27 -23
  73. package/dist/reorder-list/reorder-list.css +1 -0
  74. package/dist/reorder-list/reorder-list.js +143 -0
  75. package/dist/reorder-list/reorder-list.module.js +12 -0
  76. package/dist/search/search.js +5 -4
  77. package/dist/side-nav/side-nav.js +90 -89
  78. package/dist/skip-nav/skip-nav.js +1 -0
  79. package/dist/styles.css +48 -11
  80. package/dist/swap/swap.js +2 -3
  81. package/dist/switcher/switcher.js +1 -1
  82. package/dist/tabs/tabs.js +41 -40
  83. package/dist/tag/tag.css +1 -1
  84. package/dist/tag/tag.module.js +2 -2
  85. package/dist/toc/toc.js +5 -4
  86. package/dist/virtual-list/virtual-list.css +1 -0
  87. package/dist/virtual-list/virtual-list.js +40 -0
  88. package/dist/virtual-list/virtual-list.module.js +8 -0
  89. package/dist/wheel-picker/wheel-picker.css +1 -0
  90. package/dist/wheel-picker/wheel-picker.js +84 -0
  91. package/dist/wheel-picker/wheel-picker.module.js +9 -0
  92. package/package.json +4 -4
  93. package/readme.body.md +6 -1
  94. package/dist/node/react/src/theme.js +0 -78
  95. package/dist/node/storage/src/drivers.js +0 -34
  96. package/dist/node/storage/src/persisted-signal.js +0 -41
  97. package/dist/react/src/theme.js +0 -78
  98. package/dist/storage/src/drivers.js +0 -34
  99. package/dist/storage/src/persisted-signal.js +0 -41
@@ -0,0 +1,40 @@
1
+ "use client";
2
+
3
+ import e from "./virtual-list.module.js";
4
+ import { cn as t, useSignal as n, useSignals as r } from "@cascivo/core";
5
+ import { jsx as i } from "react/jsx-runtime";
6
+ //#region ../components/src/virtual-list/virtual-list.tsx
7
+ function a({ items: a, itemHeight: o, height: s, renderItem: c, overscan: l = 3, ariaLabel: u, className: d }) {
8
+ r();
9
+ let f = n(0), p = Math.ceil(s / o), m = Math.floor(f.value / o), h = Math.max(0, m - l), g = Math.min(a.length, m + p + l), _ = a.slice(h, g), v = (e) => {
10
+ f.value = e.currentTarget.scrollTop;
11
+ }, y = { blockSize: `${s}px` };
12
+ return /* @__PURE__ */ i("div", {
13
+ className: t(e.viewport, d),
14
+ style: y,
15
+ onScroll: v,
16
+ role: "list",
17
+ "aria-label": u,
18
+ tabIndex: 0,
19
+ children: /* @__PURE__ */ i("div", {
20
+ className: e.canvas,
21
+ style: { blockSize: `${a.length * o}px` },
22
+ children: _.map((t, n) => {
23
+ let r = h + n;
24
+ return /* @__PURE__ */ i("div", {
25
+ role: "listitem",
26
+ "aria-setsize": a.length,
27
+ "aria-posinset": r + 1,
28
+ className: e.row,
29
+ style: {
30
+ blockSize: `${o}px`,
31
+ transform: `translateY(${r * o}px)`
32
+ },
33
+ children: c(t, r)
34
+ }, r);
35
+ })
36
+ })
37
+ });
38
+ }
39
+ //#endregion
40
+ export { a as VirtualList };
@@ -0,0 +1,8 @@
1
+ import './virtual-list.css';
2
+ var e = {
3
+ viewport: "_viewport_1wmsq_2",
4
+ canvas: "_canvas_1wmsq_14",
5
+ row: "_row_1wmsq_19"
6
+ };
7
+ //#endregion
8
+ export { e as default };
@@ -0,0 +1 @@
1
+ @layer cascivo.component{._root_11q00_2{inline-size:fit-content;position:relative}._column_11q00_7{block-size:var(--_column-height);scroll-snap-type:y mandatory;scrollbar-width:none;padding-block:var(--_pad);overflow-y:auto;-webkit-mask-image:linear-gradient(#0000 0%,#000 25% 75%,#0000 100%);mask-image:linear-gradient(#0000 0%,#000 25% 75%,#0000 100%)}._column_11q00_7::-webkit-scrollbar{display:none}._column_11q00_7:focus-visible{outline:var(--cascivo-ring-width) solid var(--cascivo-ring-color);outline-offset:2px;border-radius:var(--cascivo-radius-md)}._option_11q00_29{block-size:var(--_item-height);scroll-snap-align:center;padding-inline:var(--cascivo-space-4);color:var(--cascivo-color-text-muted);font-size:var(--cascivo-text-ui);white-space:nowrap;-webkit-user-select:none;user-select:none;justify-content:center;align-items:center;display:flex}._option_11q00_29[aria-selected=true]{color:var(--cascivo-color-foreground);font-weight:var(--cascivo-font-semibold)}._band_11q00_48{block-size:var(--_item-height);border-block:1px solid var(--cascivo-border-subtle);pointer-events:none;position:absolute;inset-block-start:50%;inset-inline:0;translate:0 -50%}@media (prefers-reduced-motion:no-preference){._column_11q00_7{scroll-behavior:smooth}}}
@@ -0,0 +1,84 @@
1
+ "use client";
2
+
3
+ import e from "./wheel-picker.module.js";
4
+ import { useRef as t } from "react";
5
+ import { cn as n, useEffectPropSignal as r, useId as i, useSignalEffect as a } from "@cascivo/core";
6
+ import { jsx as o, jsxs as s } from "react/jsx-runtime";
7
+ //#region ../components/src/wheel-picker/wheel-picker.tsx
8
+ var c = 120;
9
+ function l({ options: l, value: u, onValueChange: d, visibleCount: f = 5, itemHeight: p = 36, ariaLabel: m, className: h }) {
10
+ let g = t(null), _ = i(), v = Math.max(0, l.findIndex((e) => e.value === u)), y = t(l);
11
+ y.current = l;
12
+ let b = t(d);
13
+ b.current = d;
14
+ let x = t(p);
15
+ x.current = p;
16
+ let S = t(u);
17
+ S.current = u;
18
+ let C = (e, t) => {
19
+ let n = g.current;
20
+ n && n.scrollTo({
21
+ top: e * x.current,
22
+ behavior: t ? "smooth" : "instant"
23
+ });
24
+ }, w = r(u);
25
+ a(() => {
26
+ let e = w.value, t = y.current.findIndex((t) => t.value === e);
27
+ t >= 0 && C(t, !1);
28
+ }), a(() => {
29
+ let e = g.current;
30
+ if (!e) return;
31
+ let t, n = () => {
32
+ clearTimeout(t), t = setTimeout(() => {
33
+ let t = Math.round(e.scrollTop / x.current), n = y.current[t];
34
+ n && n.value !== S.current && b.current(n.value);
35
+ }, c);
36
+ };
37
+ return e.addEventListener("scroll", n, { passive: !0 }), () => {
38
+ clearTimeout(t), e.removeEventListener("scroll", n);
39
+ };
40
+ });
41
+ let T = (e) => {
42
+ let t = Math.max(0, Math.min(l.length - 1, e)), n = l[t];
43
+ !n || n.value === u || (d(n.value), C(t, !0));
44
+ }, E = (e) => {
45
+ let t = {
46
+ ArrowDown: v + 1,
47
+ ArrowUp: v - 1,
48
+ Home: 0,
49
+ End: l.length - 1,
50
+ PageDown: v + f,
51
+ PageUp: v - f
52
+ }[e.key];
53
+ t !== void 0 && (e.preventDefault(), T(t));
54
+ }, D = (f - 1) / 2 * p, O = {
55
+ "--_item-height": `${p}px`,
56
+ "--_pad": `${D}px`,
57
+ "--_column-height": `${f * p}px`
58
+ };
59
+ return /* @__PURE__ */ s("div", {
60
+ className: n(e.root, h),
61
+ style: O,
62
+ children: [/* @__PURE__ */ o("div", {
63
+ ref: g,
64
+ role: "listbox",
65
+ tabIndex: 0,
66
+ "aria-label": m,
67
+ "aria-activedescendant": `${_}-${v}`,
68
+ className: e.column,
69
+ onKeyDown: E,
70
+ children: l.map((t, n) => /* @__PURE__ */ o("div", {
71
+ id: `${_}-${n}`,
72
+ role: "option",
73
+ "aria-selected": n === v,
74
+ className: e.option,
75
+ children: t.label
76
+ }, t.value))
77
+ }), /* @__PURE__ */ o("div", {
78
+ "aria-hidden": "true",
79
+ className: e.band
80
+ })]
81
+ });
82
+ }
83
+ //#endregion
84
+ export { l as WheelPicker };
@@ -0,0 +1,9 @@
1
+ import './wheel-picker.css';
2
+ var e = {
3
+ root: "_root_11q00_2",
4
+ column: "_column_11q00_7",
5
+ option: "_option_11q00_29",
6
+ band: "_band_11q00_48"
7
+ };
8
+ //#endregion
9
+ export { e as default };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cascivo/react",
3
- "version": "0.16.0",
3
+ "version": "0.17.0",
4
4
  "private": false,
5
5
  "description": "Prebuilt cascivo design system components — use without copying source. @cascivo/themes installs with it; pair with @cascivo/charts (data-viz) and @cascivo/icons. Docs offline: npx @cascivo/docs",
6
6
  "keywords": [
@@ -45,9 +45,9 @@
45
45
  "provenance": true
46
46
  },
47
47
  "dependencies": {
48
- "@cascivo/core": "^0.16.0",
49
- "@cascivo/i18n": "^0.16.0",
50
- "@cascivo/themes": "^0.4.10"
48
+ "@cascivo/core": "^0.17.0",
49
+ "@cascivo/i18n": "^0.17.0",
50
+ "@cascivo/themes": "^0.4.11"
51
51
  },
52
52
  "devDependencies": {
53
53
  "@testing-library/jest-dom": "^6.9.1",
package/readme.body.md CHANGED
@@ -231,7 +231,7 @@ routing break after adding one of these, check that the import resolves to
231
231
 
232
232
  ## Component index
233
233
 
234
- 192 components, exported from `@cascivo/react`. Full props, examples, and live demos at [cascivo.com/docs](https://cascivo.com/docs).
234
+ 197 components, exported from `@cascivo/react`. Full props, examples, and live demos at [cascivo.com/docs](https://cascivo.com/docs).
235
235
 
236
236
  ### Inputs
237
237
 
@@ -264,6 +264,7 @@ routing break after adding one of these, check that the import resolves to
264
264
  - **Radio** — Single choice from a set, grouped with RadioGroup
265
265
  - **RadioCard** — Selectable card backed by a native radio input. Use RadioCardGroup for single-select groups.
266
266
  - **RatingGroup** — Star rating input with accessible radio group pattern
267
+ - **ReorderList** — List whose rows can be reordered by pointer drag or entirely by keyboard
267
268
  - **Search** — Search input with debounced search callback and clear button
268
269
  - **SegmentedControl** — Mutually exclusive toggle group
269
270
  - **Select** — Native select menu styled to match the design system
@@ -275,6 +276,7 @@ routing break after adding one of these, check that the import resolves to
275
276
  - **TimePicker** — Native time input wrapper with label, hint, error, and size variants
276
277
  - **Toggle** — On/off switch built as an accessible button
277
278
  - **ToggleGroup** — A set of toggle buttons for single or multiple selection
279
+ - **WheelPicker** — iOS-style drum picker — a column of options that scrolls and snaps to a selection
278
280
 
279
281
  ### Display
280
282
 
@@ -335,6 +337,7 @@ routing break after adding one of these, check that the import resolves to
335
337
  - **TreeView** — Hierarchical, expandable tree of nodes with keyboard navigation and selection
336
338
  - **User** — Identity composite: an avatar with a name, description, and optional action slot
337
339
  - **UsersTablePage** — Full users management page with table, search, and invite action.
340
+ - **VirtualList** — Renders only the rows inside the viewport, so list length costs no extra DOM
338
341
  - **VisuallyHidden** — Hides content visually while keeping it available to screen readers
339
342
 
340
343
  ### Overlay
@@ -363,6 +366,7 @@ routing break after adding one of these, check that the import resolves to
363
366
  - **Dock** — Fixed bottom navigation bar for mobile app shells with up to 5 items
364
367
  - **Header** — App top bar with brand, primary navigation links, and an actions slot
365
368
  - **HeaderPanel** — Non-modal panel anchored below the shell header at the inline-end edge — hosts notifications, app switcher, user settings
369
+ - **LargeTitleHeader** — Scrolling region whose large title collapses into a compact sticky bar as it scrolls
366
370
  - **Link** — Styled anchor for navigation, standalone or inline within prose
367
371
  - **Menubar** — Horizontal application menu bar with keyboard-navigable dropdown menus
368
372
  - **MenuButton** — A button that opens an anchored action menu of one-shot commands
@@ -409,6 +413,7 @@ routing break after adding one of these, check that the import resolves to
409
413
 
410
414
  ### Feedback
411
415
 
416
+ - **InfiniteScroll** — Loads the next page when the end of a list scrolls into view
412
417
  - **InlineLoading** — Compact inline status indicator that pairs a label with a loading, success, or error state
413
418
  - **Notification** — Inline, actionable notification banner that surfaces a titled message with an optional recovery action
414
419
  - **Progress** — Horizontal bar showing the completion progress of a tracked operation
@@ -1,78 +0,0 @@
1
- "use client";
2
-
3
- import { persistedSignal as e } from "../../storage/src/persisted-signal.js";
4
- import { useRef as t } from "react";
5
- import { useSignalEffect as n, useSignals as r } from "@cascivo/core";
6
- import { Fragment as i, jsx as a, jsxs as o } from "react/jsx-runtime";
7
- //#region src/theme.tsx
8
- var s = "cascivo-theme", c = "data-theme";
9
- function l() {
10
- return globalThis.process?.env?.NODE_ENV !== "production";
11
- }
12
- var u = /* @__PURE__ */ new Set();
13
- function d(e, t) {
14
- l() && (e === null || typeof document > "u" || typeof requestAnimationFrame != "function" || u.has(t) || requestAnimationFrame(() => {
15
- u.has(t) || getComputedStyle(e).getPropertyValue("--cascivo-color-accent").trim() === "" && (u.add(t), console.warn(`cascivo ThemeProvider: data-theme=${JSON.stringify(t)} was set, but no cascivo theme CSS defines it — every --cascivo-color-* token is unresolved, so components render grayscale. Import '@cascivo/themes/all.css' once in your entry (or '@cascivo/react/styles.css', which bundles the light and dark themes). Using a custom theme? Ensure its stylesheet is loaded and defines [data-theme=${JSON.stringify(t)}]. Docs: https://cascivo.com/docs/theming.md — offline: npx -y @cascivo/docs guide theming`));
16
- }));
17
- }
18
- var f = null, p = {
19
- storageKey: s,
20
- defaultTheme: "light",
21
- explicit: !1
22
- };
23
- function m(e) {
24
- return typeof window > "u" || typeof window.matchMedia != "function" ? e : window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : window.matchMedia("(prefers-color-scheme: light)").matches ? "light" : e;
25
- }
26
- function h() {
27
- return p.explicit ? p.defaultTheme : m(p.defaultTheme);
28
- }
29
- function g() {
30
- return f ??= e(p.storageKey, h()), f;
31
- }
32
- var _ = !1, v = !1;
33
- function y(e) {
34
- !l() || v || typeof requestAnimationFrame == "function" && requestAnimationFrame(() => {
35
- _ || v || (v = !0, console.warn(`cascivo setTheme(${JSON.stringify(e)}): no <ThemeProvider> is mounted, so the theme signal updated but the ${c} attribute was never written — nothing on the page will restyle. Wrap your app in <ThemeProvider> (it is SSR-safe and persists the choice), or call applyTheme() to write the attribute directly if you are theming outside React. Docs: https://cascivo.com/docs/theming.md — offline: npx -y @cascivo/docs guide theming`));
36
- });
37
- }
38
- function b(e) {
39
- g().value = e, y(e);
40
- }
41
- function x(e, t) {
42
- g().value = e;
43
- let n = t ?? (typeof document < "u" ? document.documentElement : null);
44
- n !== null && (n.setAttribute(c, e), d(n, e));
45
- }
46
- function S() {
47
- return r(), [g().value, b];
48
- }
49
- function C() {
50
- return g();
51
- }
52
- function w(e) {
53
- return JSON.stringify(e).replace(/</g, "\\u003c");
54
- }
55
- function T({ defaultTheme: e, value: r, storageKey: l = s, attribute: u = c, target: m, onChange: h, nonce: v, children: y }) {
56
- let b = t(!1);
57
- b.current || (b.current = !0, (f === null || p.storageKey !== l) && (p = {
58
- storageKey: l,
59
- defaultTheme: e ?? "light",
60
- explicit: e !== void 0
61
- }, f = null));
62
- let x = g();
63
- r !== void 0 && (x.value = r);
64
- let S = t(h);
65
- return S.current = h, n(() => {
66
- let e = x.value, t = m ? m.current : typeof document < "u" ? document.documentElement : null;
67
- _ = !0, t?.setAttribute(u, e), d(t, e), S.current?.(e);
68
- }), r !== void 0 && !m ? /* @__PURE__ */ o(i, { children: [/* @__PURE__ */ a("script", {
69
- nonce: v,
70
- dangerouslySetInnerHTML: { __html: `document.documentElement.setAttribute(${w(u)},${w(r)})` }
71
- }), y] }) : /* @__PURE__ */ a(i, { children: y });
72
- }
73
- function E(e = {}) {
74
- let t = JSON.stringify(e.storageKey ?? s), n = JSON.stringify(e.attribute ?? c), r = JSON.stringify(e.defaultTheme ?? "light"), i = e.defaultTheme === void 0 ? "if(typeof matchMedia==='function'){if(matchMedia('(prefers-color-scheme: dark)').matches)v='dark';else if(matchMedia('(prefers-color-scheme: light)').matches)v='light';}" : "";
75
- return `(function(){try{var v=${r};` + i + `var raw=localStorage.getItem(${t});if(raw){v=raw;try{var e=JSON.parse(raw);if(e&&typeof e==='object'&&'value'in e)v=e.value;}catch(_){}}document.documentElement.setAttribute(${n},v);}catch(_){}})();`;
76
- }
77
- //#endregion
78
- export { T as ThemeProvider, x as applyTheme, b as setTheme, E as themePreloadScript, C as themeSignal, S as useTheme };
@@ -1,34 +0,0 @@
1
- //#region ../storage/src/drivers.ts
2
- function e() {
3
- let e = /* @__PURE__ */ new Map();
4
- return {
5
- get: (t) => e.get(t) ?? null,
6
- set: (t, n) => {
7
- e.set(t, n);
8
- },
9
- remove: (t) => {
10
- e.delete(t);
11
- }
12
- };
13
- }
14
- function t() {
15
- return typeof window > "u" ? e() : {
16
- get: (e) => window.localStorage.getItem(e),
17
- set: (e, t) => {
18
- try {
19
- window.localStorage.setItem(e, t);
20
- } catch {}
21
- },
22
- remove: (e) => {
23
- window.localStorage.removeItem(e);
24
- },
25
- subscribe(e, t) {
26
- let n = (n) => {
27
- n.storageArea === window.localStorage && n.key === e && t(n.newValue);
28
- };
29
- return window.addEventListener("storage", n), () => window.removeEventListener("storage", n);
30
- }
31
- };
32
- }
33
- //#endregion
34
- export { t as localStorageDriver };
@@ -1,41 +0,0 @@
1
- import { localStorageDriver as e } from "./drivers.js";
2
- import { effect as t, signal as n } from "@cascivo/core";
3
- //#region ../storage/src/persisted-signal.ts
4
- function r(r, i, a = {}) {
5
- let o = a.driver ?? e(), s = a.version ?? 1, c = n(i), l = n(!1), u = !1;
6
- function d(e) {
7
- if (e !== null) try {
8
- let t = JSON.parse(e);
9
- if (typeof t != "object" || !t || typeof t.v != "number") return;
10
- if (t.v !== s) {
11
- if (!a.migrate) return;
12
- let e = a.migrate(t.value, t.v);
13
- return o.set(r, JSON.stringify({
14
- v: s,
15
- value: e
16
- })), e;
17
- }
18
- return t.value;
19
- } catch {
20
- return;
21
- }
22
- }
23
- function f(e) {
24
- let t = d(e);
25
- t !== void 0 && (u = !0, c.value = t, u = !1);
26
- }
27
- let p = o.get(r);
28
- p instanceof Promise ? p.then((e) => {
29
- f(e), l.value = !0;
30
- }) : (f(p), l.value = !0), t(() => {
31
- let e = c.value;
32
- !l.value || u || o.set(r, JSON.stringify({
33
- v: s,
34
- value: e
35
- }));
36
- }), o.subscribe?.(r, f);
37
- let m = c;
38
- return m.ready = l, m;
39
- }
40
- //#endregion
41
- export { r as persistedSignal };
@@ -1,78 +0,0 @@
1
- "use client";
2
-
3
- import { persistedSignal as e } from "../../storage/src/persisted-signal.js";
4
- import { useRef as t } from "react";
5
- import { useSignalEffect as n, useSignals as r } from "@cascivo/core";
6
- import { Fragment as i, jsx as a, jsxs as o } from "react/jsx-runtime";
7
- //#region src/theme.tsx
8
- var s = "cascivo-theme", c = "data-theme";
9
- function l() {
10
- return globalThis.process?.env?.NODE_ENV !== "production";
11
- }
12
- var u = /* @__PURE__ */ new Set();
13
- function d(e, t) {
14
- l() && (e === null || typeof document > "u" || typeof requestAnimationFrame != "function" || u.has(t) || requestAnimationFrame(() => {
15
- u.has(t) || getComputedStyle(e).getPropertyValue("--cascivo-color-accent").trim() === "" && (u.add(t), console.warn(`cascivo ThemeProvider: data-theme=${JSON.stringify(t)} was set, but no cascivo theme CSS defines it — every --cascivo-color-* token is unresolved, so components render grayscale. Import '@cascivo/themes/all.css' once in your entry (or '@cascivo/react/styles.css', which bundles the light and dark themes). Using a custom theme? Ensure its stylesheet is loaded and defines [data-theme=${JSON.stringify(t)}]. Docs: https://cascivo.com/docs/theming.md — offline: npx -y @cascivo/docs guide theming`));
16
- }));
17
- }
18
- var f = null, p = {
19
- storageKey: s,
20
- defaultTheme: "light",
21
- explicit: !1
22
- };
23
- function m(e) {
24
- return typeof window > "u" || typeof window.matchMedia != "function" ? e : window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : window.matchMedia("(prefers-color-scheme: light)").matches ? "light" : e;
25
- }
26
- function h() {
27
- return p.explicit ? p.defaultTheme : m(p.defaultTheme);
28
- }
29
- function g() {
30
- return f ??= e(p.storageKey, h()), f;
31
- }
32
- var _ = !1, v = !1;
33
- function y(e) {
34
- !l() || v || typeof requestAnimationFrame == "function" && requestAnimationFrame(() => {
35
- _ || v || (v = !0, console.warn(`cascivo setTheme(${JSON.stringify(e)}): no <ThemeProvider> is mounted, so the theme signal updated but the ${c} attribute was never written — nothing on the page will restyle. Wrap your app in <ThemeProvider> (it is SSR-safe and persists the choice), or call applyTheme() to write the attribute directly if you are theming outside React. Docs: https://cascivo.com/docs/theming.md — offline: npx -y @cascivo/docs guide theming`));
36
- });
37
- }
38
- function b(e) {
39
- g().value = e, y(e);
40
- }
41
- function x(e, t) {
42
- g().value = e;
43
- let n = t ?? (typeof document < "u" ? document.documentElement : null);
44
- n !== null && (n.setAttribute(c, e), d(n, e));
45
- }
46
- function S() {
47
- return r(), [g().value, b];
48
- }
49
- function C() {
50
- return g();
51
- }
52
- function w(e) {
53
- return JSON.stringify(e).replace(/</g, "\\u003c");
54
- }
55
- function T({ defaultTheme: e, value: r, storageKey: l = s, attribute: u = c, target: m, onChange: h, nonce: v, children: y }) {
56
- let b = t(!1);
57
- b.current || (b.current = !0, (f === null || p.storageKey !== l) && (p = {
58
- storageKey: l,
59
- defaultTheme: e ?? "light",
60
- explicit: e !== void 0
61
- }, f = null));
62
- let x = g();
63
- r !== void 0 && (x.value = r);
64
- let S = t(h);
65
- return S.current = h, n(() => {
66
- let e = x.value, t = m ? m.current : typeof document < "u" ? document.documentElement : null;
67
- _ = !0, t?.setAttribute(u, e), d(t, e), S.current?.(e);
68
- }), r !== void 0 && !m ? /* @__PURE__ */ o(i, { children: [/* @__PURE__ */ a("script", {
69
- nonce: v,
70
- dangerouslySetInnerHTML: { __html: `document.documentElement.setAttribute(${w(u)},${w(r)})` }
71
- }), y] }) : /* @__PURE__ */ a(i, { children: y });
72
- }
73
- function E(e = {}) {
74
- let t = JSON.stringify(e.storageKey ?? s), n = JSON.stringify(e.attribute ?? c), r = JSON.stringify(e.defaultTheme ?? "light"), i = e.defaultTheme === void 0 ? "if(typeof matchMedia==='function'){if(matchMedia('(prefers-color-scheme: dark)').matches)v='dark';else if(matchMedia('(prefers-color-scheme: light)').matches)v='light';}" : "";
75
- return `(function(){try{var v=${r};` + i + `var raw=localStorage.getItem(${t});if(raw){v=raw;try{var e=JSON.parse(raw);if(e&&typeof e==='object'&&'value'in e)v=e.value;}catch(_){}}document.documentElement.setAttribute(${n},v);}catch(_){}})();`;
76
- }
77
- //#endregion
78
- export { T as ThemeProvider, x as applyTheme, b as setTheme, E as themePreloadScript, C as themeSignal, S as useTheme };
@@ -1,34 +0,0 @@
1
- //#region ../storage/src/drivers.ts
2
- function e() {
3
- let e = /* @__PURE__ */ new Map();
4
- return {
5
- get: (t) => e.get(t) ?? null,
6
- set: (t, n) => {
7
- e.set(t, n);
8
- },
9
- remove: (t) => {
10
- e.delete(t);
11
- }
12
- };
13
- }
14
- function t() {
15
- return typeof window > "u" ? e() : {
16
- get: (e) => window.localStorage.getItem(e),
17
- set: (e, t) => {
18
- try {
19
- window.localStorage.setItem(e, t);
20
- } catch {}
21
- },
22
- remove: (e) => {
23
- window.localStorage.removeItem(e);
24
- },
25
- subscribe(e, t) {
26
- let n = (n) => {
27
- n.storageArea === window.localStorage && n.key === e && t(n.newValue);
28
- };
29
- return window.addEventListener("storage", n), () => window.removeEventListener("storage", n);
30
- }
31
- };
32
- }
33
- //#endregion
34
- export { t as localStorageDriver };
@@ -1,41 +0,0 @@
1
- import { localStorageDriver as e } from "./drivers.js";
2
- import { effect as t, signal as n } from "@cascivo/core";
3
- //#region ../storage/src/persisted-signal.ts
4
- function r(r, i, a = {}) {
5
- let o = a.driver ?? e(), s = a.version ?? 1, c = n(i), l = n(!1), u = !1;
6
- function d(e) {
7
- if (e !== null) try {
8
- let t = JSON.parse(e);
9
- if (typeof t != "object" || !t || typeof t.v != "number") return;
10
- if (t.v !== s) {
11
- if (!a.migrate) return;
12
- let e = a.migrate(t.value, t.v);
13
- return o.set(r, JSON.stringify({
14
- v: s,
15
- value: e
16
- })), e;
17
- }
18
- return t.value;
19
- } catch {
20
- return;
21
- }
22
- }
23
- function f(e) {
24
- let t = d(e);
25
- t !== void 0 && (u = !0, c.value = t, u = !1);
26
- }
27
- let p = o.get(r);
28
- p instanceof Promise ? p.then((e) => {
29
- f(e), l.value = !0;
30
- }) : (f(p), l.value = !0), t(() => {
31
- let e = c.value;
32
- !l.value || u || o.set(r, JSON.stringify({
33
- v: s,
34
- value: e
35
- }));
36
- }), o.subscribe?.(r, f);
37
- let m = c;
38
- return m.ready = l, m;
39
- }
40
- //#endregion
41
- export { r as persistedSignal };