@rinzai/zen 0.14.0 → 0.16.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 (225) hide show
  1. package/CHANGELOG.md +153 -0
  2. package/README.md +16 -1
  3. package/dist/animated-number/index.js +14 -14
  4. package/dist/breadcrumbs/index.js +14 -14
  5. package/dist/calendar/index.js +29 -29
  6. package/dist/calendar-heatmap/index.js +12 -12
  7. package/dist/canvas/index.js +19 -19
  8. package/dist/carousel/index.d.ts.map +1 -1
  9. package/dist/carousel/index.js +29 -29
  10. package/dist/chart/index.js +7 -7
  11. package/dist/code-block/index.js +5 -5
  12. package/dist/collapse/index.js +6 -6
  13. package/dist/color-picker/index.js +10 -10
  14. package/dist/combobox/index.js +61 -61
  15. package/dist/command-palette/index.js +5 -5
  16. package/dist/confirm-dialog/index.js +4 -4
  17. package/dist/date-picker/index.js +15 -15
  18. package/dist/dialog/index.d.ts.map +1 -1
  19. package/dist/dialog/index.js +45 -65
  20. package/dist/docs/README.md +205 -0
  21. package/dist/docs/accordion.md +122 -0
  22. package/dist/docs/alert.md +69 -0
  23. package/dist/docs/animated-number.md +105 -0
  24. package/dist/docs/avatar.md +91 -0
  25. package/dist/docs/backdrop.md +94 -0
  26. package/dist/docs/badge.md +37 -0
  27. package/dist/docs/breadcrumbs.md +44 -0
  28. package/dist/docs/button-group.md +76 -0
  29. package/dist/docs/button.md +131 -0
  30. package/dist/docs/calendar-heatmap.md +73 -0
  31. package/dist/docs/calendar.md +101 -0
  32. package/dist/docs/canvas.md +584 -0
  33. package/dist/docs/card.md +180 -0
  34. package/dist/docs/carousel.md +162 -0
  35. package/dist/docs/chart.md +325 -0
  36. package/dist/docs/checkbox.md +88 -0
  37. package/dist/docs/chip.md +52 -0
  38. package/dist/docs/code-block.md +116 -0
  39. package/dist/docs/code-input.md +52 -0
  40. package/dist/docs/collapse.md +46 -0
  41. package/dist/docs/color-picker.md +145 -0
  42. package/dist/docs/combobox.md +208 -0
  43. package/dist/docs/command-palette.md +65 -0
  44. package/dist/docs/date-picker.md +167 -0
  45. package/dist/docs/dialog.md +271 -0
  46. package/dist/docs/disclosure.md +88 -0
  47. package/dist/docs/editable-cell.md +90 -0
  48. package/dist/docs/empty-state.md +46 -0
  49. package/dist/docs/field.md +82 -0
  50. package/dist/docs/file-drop.md +44 -0
  51. package/dist/docs/filter-bar.md +66 -0
  52. package/dist/docs/header.md +51 -0
  53. package/dist/docs/hover-card.md +110 -0
  54. package/dist/docs/icon-picker.md +65 -0
  55. package/dist/docs/input-group.md +89 -0
  56. package/dist/docs/input.md +33 -0
  57. package/dist/docs/inset.md +57 -0
  58. package/dist/docs/kbd.md +34 -0
  59. package/dist/docs/keypad.md +51 -0
  60. package/dist/docs/load-more.md +66 -0
  61. package/dist/docs/locale-provider.md +99 -0
  62. package/dist/docs/marquee.md +86 -0
  63. package/dist/docs/menu.md +456 -0
  64. package/dist/docs/meter.md +102 -0
  65. package/dist/docs/money-input.md +169 -0
  66. package/dist/docs/month-picker.md +80 -0
  67. package/dist/docs/navigation-menu.md +157 -0
  68. package/dist/docs/number-field.md +129 -0
  69. package/dist/docs/page-header.md +44 -0
  70. package/dist/docs/page-transition.md +93 -0
  71. package/dist/docs/pagination.md +42 -0
  72. package/dist/docs/pills.md +85 -0
  73. package/dist/docs/player-bar.md +158 -0
  74. package/dist/docs/popover.md +200 -0
  75. package/dist/docs/progress-ring.md +70 -0
  76. package/dist/docs/radio-cards.md +82 -0
  77. package/dist/docs/radio-group.md +86 -0
  78. package/dist/docs/range-slider.md +64 -0
  79. package/dist/docs/repeat-picker.md +44 -0
  80. package/dist/docs/resizable.md +107 -0
  81. package/dist/docs/seek-bar.md +97 -0
  82. package/dist/docs/segmented.md +89 -0
  83. package/dist/docs/select.md +148 -0
  84. package/dist/docs/separator.md +76 -0
  85. package/dist/docs/side-nav.md +75 -0
  86. package/dist/docs/skeleton.md +89 -0
  87. package/dist/docs/slider.md +87 -0
  88. package/dist/docs/sortable.md +244 -0
  89. package/dist/docs/sparkline.md +56 -0
  90. package/dist/docs/spinner.md +69 -0
  91. package/dist/docs/status-pill.md +81 -0
  92. package/dist/docs/stepper.md +59 -0
  93. package/dist/docs/tab-bar.md +78 -0
  94. package/dist/docs/table-of-contents.md +43 -0
  95. package/dist/docs/table.md +714 -0
  96. package/dist/docs/tabs.md +140 -0
  97. package/dist/docs/tag-input.md +45 -0
  98. package/dist/docs/textarea.md +25 -0
  99. package/dist/docs/theme-toggle.md +85 -0
  100. package/dist/docs/theming.md +193 -0
  101. package/dist/docs/time-field.md +71 -0
  102. package/dist/docs/timeline.md +50 -0
  103. package/dist/docs/toast.md +53 -0
  104. package/dist/docs/toggle-group.md +83 -0
  105. package/dist/docs/toggle.md +38 -0
  106. package/dist/docs/toolbar.md +97 -0
  107. package/dist/docs/tooltip.md +102 -0
  108. package/dist/docs/tree.md +295 -0
  109. package/dist/docs/trend.md +50 -0
  110. package/dist/filter-bar/index.js +6 -6
  111. package/dist/header/index.js +6 -6
  112. package/dist/icon-picker/index.js +5 -5
  113. package/dist/icons/arrow-path.d.ts +3 -0
  114. package/dist/icons/arrow-path.d.ts.map +1 -0
  115. package/dist/icons/arrows-right-left.d.ts +3 -0
  116. package/dist/icons/arrows-right-left.d.ts.map +1 -0
  117. package/dist/icons/backward.d.ts +3 -0
  118. package/dist/icons/backward.d.ts.map +1 -0
  119. package/dist/icons/forward.d.ts +3 -0
  120. package/dist/icons/forward.d.ts.map +1 -0
  121. package/dist/icons/heart-solid.d.ts +3 -0
  122. package/dist/icons/heart-solid.d.ts.map +1 -0
  123. package/dist/icons/heart.d.ts +3 -0
  124. package/dist/icons/heart.d.ts.map +1 -0
  125. package/dist/icons/musical-note.d.ts +3 -0
  126. package/dist/icons/musical-note.d.ts.map +1 -0
  127. package/dist/icons/pause.d.ts +3 -0
  128. package/dist/icons/pause.d.ts.map +1 -0
  129. package/dist/icons/play.d.ts +3 -0
  130. package/dist/icons/play.d.ts.map +1 -0
  131. package/dist/icons/queue-list.d.ts +3 -0
  132. package/dist/icons/queue-list.d.ts.map +1 -0
  133. package/dist/icons/speaker-wave.d.ts +3 -0
  134. package/dist/icons/speaker-wave.d.ts.map +1 -0
  135. package/dist/icons/speaker-x-mark.d.ts +3 -0
  136. package/dist/icons/speaker-x-mark.d.ts.map +1 -0
  137. package/dist/index.d.ts +7 -1
  138. package/dist/index.d.ts.map +1 -1
  139. package/dist/keypad/index.js +5 -5
  140. package/dist/lib.js +86 -80
  141. package/dist/load-more/index.js +5 -5
  142. package/dist/marquee/index.d.ts +15 -0
  143. package/dist/marquee/index.d.ts.map +1 -0
  144. package/dist/marquee/index.js +90 -0
  145. package/dist/menu/index.d.ts +7 -1
  146. package/dist/menu/index.d.ts.map +1 -1
  147. package/dist/menu/index.js +222 -178
  148. package/dist/money-input/index.js +54 -54
  149. package/dist/month-picker/index.js +11 -11
  150. package/dist/number-field/index.js +5 -5
  151. package/dist/pagination/index.js +12 -12
  152. package/dist/player-bar/index.d.ts +11 -0
  153. package/dist/player-bar/index.d.ts.map +1 -0
  154. package/dist/player-bar/index.js +17 -0
  155. package/dist/radio-cards/index.d.ts +2 -1
  156. package/dist/radio-cards/index.d.ts.map +1 -1
  157. package/dist/radio-cards/index.js +3 -3
  158. package/dist/range-slider/index.js +11 -11
  159. package/dist/repeat-picker/index.js +5 -5
  160. package/dist/resizable/index.js +22 -22
  161. package/dist/seek-bar/index.d.ts +26 -0
  162. package/dist/seek-bar/index.d.ts.map +1 -0
  163. package/dist/seek-bar/index.js +121 -0
  164. package/dist/segmented/index.d.ts +3 -2
  165. package/dist/segmented/index.d.ts.map +1 -1
  166. package/dist/segmented/index.js +19 -18
  167. package/dist/select/index.js +21 -21
  168. package/dist/slider/index.d.ts +2 -1
  169. package/dist/slider/index.d.ts.map +1 -1
  170. package/dist/sortable/index.d.ts +13 -1
  171. package/dist/sortable/index.d.ts.map +1 -1
  172. package/dist/sortable/index.js +74 -55
  173. package/dist/sortable/shared.js +14 -14
  174. package/dist/sortable/tree.js +17 -17
  175. package/dist/sparkline/index.js +4 -4
  176. package/dist/stepper/index.js +13 -13
  177. package/dist/tab-bar/index.d.ts +4 -2
  178. package/dist/tab-bar/index.d.ts.map +1 -1
  179. package/dist/tab-bar/index.js +24 -19
  180. package/dist/table/index.js +26 -26
  181. package/dist/table/selection.js +9 -9
  182. package/dist/table-of-contents/index.js +11 -11
  183. package/dist/tag-input/index.js +5 -5
  184. package/dist/textarea/index.d.ts +6 -2
  185. package/dist/textarea/index.d.ts.map +1 -1
  186. package/dist/textarea/index.js +2 -1
  187. package/dist/theme-toggle/index.js +4 -4
  188. package/dist/theme.css +143 -0
  189. package/dist/time-field/index.js +21 -21
  190. package/dist/toast/index.d.ts.map +1 -1
  191. package/dist/toast/index.js +41 -41
  192. package/dist/tooltip/index.d.ts +9 -3
  193. package/dist/tooltip/index.d.ts.map +1 -1
  194. package/dist/tooltip/index.js +19 -16
  195. package/dist/tree/index.js +34 -34
  196. package/dist/trend/index.js +5 -5
  197. package/dist/utils/duration.d.ts +3 -0
  198. package/dist/utils/duration.d.ts.map +1 -0
  199. package/dist/utils/duration.js +7 -0
  200. package/dist/utils/messages.d.ts +3 -0
  201. package/dist/utils/messages.d.ts.map +1 -1
  202. package/dist/utils/messages.js +4 -1
  203. package/dist/utils/slot.d.ts +5 -2
  204. package/dist/utils/slot.d.ts.map +1 -1
  205. package/dist/utils/slot.js +16 -11
  206. package/dist/utils/swipe.d.ts +7 -0
  207. package/dist/utils/swipe.d.ts.map +1 -1
  208. package/dist/utils/swipe.js +45 -25
  209. package/dist/utils/useAnchoredPopup.d.ts +2 -1
  210. package/dist/utils/useAnchoredPopup.d.ts.map +1 -1
  211. package/dist/utils/useAnchoredPopup.js +10 -5
  212. package/dist/utils/useHeightVar.d.ts +7 -0
  213. package/dist/utils/useHeightVar.d.ts.map +1 -0
  214. package/dist/utils/useHeightVar.js +17 -0
  215. package/dist/utils/useMediaPlayer.d.ts +38 -0
  216. package/dist/utils/useMediaPlayer.d.ts.map +1 -0
  217. package/dist/utils/useMediaPlayer.js +91 -0
  218. package/dist/utils/useMediaSession.d.ts +24 -0
  219. package/dist/utils/useMediaSession.d.ts.map +1 -0
  220. package/dist/utils/useMediaSession.js +76 -0
  221. package/dist/utils/useVirtualList.d.ts +6 -1
  222. package/dist/utils/useVirtualList.d.ts.map +1 -1
  223. package/dist/utils/useVirtualList.js +12 -12
  224. package/dist/zen.css +1 -1
  225. package/package.json +4 -2
@@ -1,8 +1,8 @@
1
1
  "use client";
2
- import { cx as e } from "../utils/cx.js";
3
- import { useControllable as t } from "../utils/useControllable.js";
4
- import { useAnchoredPopup as n } from "../utils/useAnchoredPopup.js";
5
- import { useLocale as r, useMessages as i } from "../locale-provider/index.js";
2
+ import { useLocale as e, useMessages as t } from "../locale-provider/index.js";
3
+ import { cx as n } from "../utils/cx.js";
4
+ import { useControllable as r } from "../utils/useControllable.js";
5
+ import { useAnchoredPopup as i } from "../utils/useAnchoredPopup.js";
6
6
  import { useFieldProps as a } from "../field/index.js";
7
7
  import { FIELD_SIZE as o, POPUP as s, TRIGGER as c } from "../utils/styles.js";
8
8
  import { FormValue as l } from "../utils/form-value.js";
@@ -11,8 +11,8 @@ import f from "../calendar/index.js";
11
11
  import p from "../icons/micro/calendar.js";
12
12
  import { Fragment as m, jsx as h, jsxs as g } from "react/jsx-runtime";
13
13
  //#region packages/date-picker/index.tsx
14
- function _({ value: e, defaultValue: n = null, onValueChange: a, locale: o, min: s, max: c, isDisabled: l, weekStartsOn: d, placeholder: p, clearable: m = !1, clearLabel: g, ..._ }) {
15
- let v = i(), b = p ?? v.pickDate, x = g ?? v.clear, S = r(o), [C, w, T] = t(e, n, a);
14
+ function _({ value: n, defaultValue: i = null, onValueChange: a, locale: o, min: s, max: c, isDisabled: l, weekStartsOn: d, placeholder: p, clearable: m = !1, clearLabel: g, ..._ }) {
15
+ let v = t(), b = p ?? v.pickDate, x = g ?? v.clear, S = e(o), [C, w, T] = r(n, i, a);
16
16
  return /* @__PURE__ */ h(y, {
17
17
  ..._,
18
18
  shown: C ? u(C, S) : null,
@@ -36,8 +36,8 @@ function _({ value: e, defaultValue: n = null, onValueChange: a, locale: o, min:
36
36
  })
37
37
  });
38
38
  }
39
- function v({ value: e, defaultValue: n = null, onValueChange: a, locale: o, min: s, max: c, isDisabled: l, weekStartsOn: p, months: m = 1, placeholder: _, clearable: v = !1, clearLabel: b, presets: x, ...S }) {
40
- let C = i(), w = _ ?? C.pickDates, T = b ?? C.clear, E = r(o), [D, O, k] = t(e, n, a), A = D ? D.end ? d(D.start, D.end, E) : `${u(D.start, E)} – …` : null;
39
+ function v({ value: n, defaultValue: i = null, onValueChange: a, locale: o, min: s, max: c, isDisabled: l, weekStartsOn: p, months: m = 1, placeholder: _, clearable: v = !1, clearLabel: b, presets: x, ...S }) {
40
+ let C = t(), w = _ ?? C.pickDates, T = b ?? C.clear, E = e(o), [D, O, k] = r(n, i, a), A = D ? D.end ? d(D.start, D.end, E) : `${u(D.start, E)} – …` : null;
41
41
  return /* @__PURE__ */ h(y, {
42
42
  ...S,
43
43
  shown: A,
@@ -85,8 +85,8 @@ function v({ value: e, defaultValue: n = null, onValueChange: a, locale: o, min:
85
85
  }
86
86
  });
87
87
  }
88
- function y({ shown: t, placeholder: r, label: i, calendar: u, onClear: d, clearLabel: f, name: p, formValue: _, onReset: v, size: y = "default", id: x, className: S, disabled: C = !1, style: w, ...T }) {
89
- let E = n(), D = a({
88
+ function y({ shown: e, placeholder: t, label: r, calendar: u, onClear: d, clearLabel: f, name: p, formValue: _, onReset: v, size: y = "default", id: x, className: S, disabled: C = !1, style: w, ...T }) {
89
+ let E = i(), D = a({
90
90
  ...T,
91
91
  id: x
92
92
  }), O = () => E.setOpen(!1);
@@ -102,10 +102,10 @@ function y({ shown: t, placeholder: r, label: i, calendar: u, onClear: d, clearL
102
102
  ...E.triggerProps.style,
103
103
  ...w
104
104
  },
105
- className: e("zen__date-picker group", c, o[y], "w-full", E.open && "border-glow/60 [--glow-border-color:transparent] shadow-glow-focus", S),
105
+ className: n("zen__date-picker group", c, o[y], "w-full", E.open && "border-glow/60 [--glow-border-color:transparent] shadow-glow-focus", S),
106
106
  children: [/* @__PURE__ */ h("span", {
107
- className: e("truncate", !t && "text-[color:oklch(var(--muted-foreground)/var(--zen-placeholder))]"),
108
- children: t ?? r
107
+ className: n("truncate", !e && "text-[color:oklch(var(--muted-foreground)/var(--zen-placeholder))]"),
108
+ children: e ?? t
109
109
  }), /* @__PURE__ */ h(b, {})]
110
110
  }),
111
111
  /* @__PURE__ */ h(l, {
@@ -116,8 +116,8 @@ function y({ shown: t, placeholder: r, label: i, calendar: u, onClear: d, clearL
116
116
  /* @__PURE__ */ g("div", {
117
117
  ...E.popupProps,
118
118
  role: "dialog",
119
- "aria-label": i,
120
- className: e("zen__popover", s, "p-3"),
119
+ "aria-label": r,
120
+ className: n("zen__popover", s, "p-3"),
121
121
  children: [E.open && u(O), d && /* @__PURE__ */ h("button", {
122
122
  type: "button",
123
123
  onClick: () => {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../packages/dialog/index.tsx"],"names":[],"mappings":"AAIA,OAAe,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAIlD,OAAO,EACH,cAAc,EAGd,SAAS,EACT,SAAS,EAKZ,MAAM,OAAO,CAAC;AAKf;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,EAC3B,IAAI,EACJ,YAAY,EACZ,KAAK,EACL,WAAW,EACX,QAAQ,EACR,WAAkB,EAClB,YAAY,EACZ,IAAW,EACX,IAAI,EACJ,SAAS,EACT,IAAI,EACJ,UAAU,EAAE,cAAc,EAC1B,GAAG,EAAE,OAAO,EACZ,GAAG,IAAI,EACV,EAAE,WAAW,+BA2Eb;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CACpB,GAAG,EAAE,SAAS,CAAC,iBAAiB,GAAG,IAAI,CAAC,EACxC,IAAI,EAAE,OAAO,EACb,YAAY,CAAC,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,GAC7C,IAAI,CA4BN;AAiCD,gEAAgE;AAChE,wBAAgB,YAAY,CAAC,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,EAAE,cAAc,CAAC,KAAK,CAAC,+BAEzE;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,EAAE,WAAW,+BAW5D;AAED,sDAAsD;AACtD,MAAM,WAAW,WAAY,SAAQ,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACjF,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,KAAK,EAAE,SAAS,CAAC;IACjB,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,iFAAiF;IACjF,YAAY,CAAC,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAC7C,sEAAsE;IACtE,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACnB,8EAA8E;IAC9E,IAAI,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;IACnC,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../packages/dialog/index.tsx"],"names":[],"mappings":"AAIA,OAAe,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAIlD,OAAO,EACH,cAAc,EAGd,SAAS,EACT,SAAS,EAKZ,MAAM,OAAO,CAAC;AAKf;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,EAC3B,IAAI,EACJ,YAAY,EACZ,KAAK,EACL,WAAW,EACX,QAAQ,EACR,WAAkB,EAClB,YAAY,EACZ,IAAW,EACX,IAAI,EACJ,SAAS,EACT,IAAI,EACJ,UAAU,EAAE,cAAc,EAC1B,GAAG,EAAE,OAAO,EACZ,GAAG,IAAI,EACV,EAAE,WAAW,+BA2Eb;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CACpB,GAAG,EAAE,SAAS,CAAC,iBAAiB,GAAG,IAAI,CAAC,EACxC,IAAI,EAAE,OAAO,EACb,YAAY,CAAC,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,GAC7C,IAAI,CA4BN;AAED,gEAAgE;AAChE,wBAAgB,YAAY,CAAC,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,EAAE,cAAc,CAAC,KAAK,CAAC,+BAEzE;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,EAAE,WAAW,+BAW5D;AAED,sDAAsD;AACtD,MAAM,WAAW,WAAY,SAAQ,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACjF,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,KAAK,EAAE,SAAS,CAAC;IACjB,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,iFAAiF;IACjF,YAAY,CAAC,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAC7C,sEAAsE;IACtE,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACnB,8EAA8E;IAC9E,IAAI,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;IACnC,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB"}
@@ -1,115 +1,95 @@
1
1
  "use client";
2
- import { cx as e } from "../utils/cx.js";
3
- import { useGraphicsMode as t } from "../utils/graphics.js";
4
- import { useMergedRefs as n } from "../utils/refs.js";
5
- import { useMessages as r } from "../locale-provider/index.js";
6
- import i from "../button/index.js";
7
- import a from "../icons/micro/x-mark.js";
8
- import { useToastHost as o } from "../toast/index.js";
9
- import { useSwipe as s } from "../utils/swipe.js";
2
+ import { useMessages as e } from "../locale-provider/index.js";
3
+ import { cx as t } from "../utils/cx.js";
4
+ import { useGraphicsMode as n } from "../utils/graphics.js";
5
+ import { useMergedRefs as r } from "../utils/refs.js";
6
+ import { useSheetSwipe as i } from "../utils/swipe.js";
7
+ import a from "../button/index.js";
8
+ import o from "../icons/micro/x-mark.js";
9
+ import { useToastHost as s } from "../toast/index.js";
10
10
  import { createContext as c, useContext as l, useEffect as u, useId as d, useRef as f } from "react";
11
11
  import { jsx as p, jsxs as m } from "react/jsx-runtime";
12
12
  //#region packages/dialog/index.tsx
13
13
  var h = c(() => {});
14
- function g({ open: t, onOpenChange: i, title: o, description: s, children: c, dismissible: l = !0, initialFocus: u, size: g = "md", side: v, className: b, role: x, closeLabel: S, ref: C, ...w }) {
15
- let T = r(), E = S ?? T.close, D = f(null), O = n(D, C), k = d(), A = d();
16
- return y(D, l && t ? v : void 0, () => i?.(!1)), _(D, t, u), /* @__PURE__ */ m("dialog", {
14
+ function g({ open: n, onOpenChange: a, title: s, description: c, children: l, dismissible: u = !0, initialFocus: g, size: v = "md", side: y, className: b, role: x, closeLabel: S, ref: C, ...w }) {
15
+ let T = e(), E = S ?? T.close, D = f(null), O = r(D, C), k = d(), A = d();
16
+ return i(D, u && n ? y : void 0, () => a?.(!1)), _(D, n, g), /* @__PURE__ */ m("dialog", {
17
17
  ...w,
18
18
  ref: O,
19
19
  role: x,
20
20
  "aria-labelledby": k,
21
- "aria-describedby": s ? A : void 0,
22
- "data-side": v,
23
- className: e("zen__dialog glass glass-blur glow-edge text-card-foreground bg-card/90! overflow-visible p-0", !v && "m-auto max-h-[calc(100dvh-2rem)] max-w-[calc(100vw-2rem)] rounded-xl", !v && (g === "lg" ? "w-[60rem]" : "w-[28rem]"), v === "bottom" && "mx-auto mt-auto mb-0 max-h-[85dvh] w-full max-w-2xl rounded-t-2xl", (v === "left" || v === "right") && "my-0 h-dvh max-h-dvh w-[24rem] max-w-[calc(100vw-2.5rem)]", v === "right" && "mr-0 ml-auto rounded-l-2xl", v === "left" && "mr-auto ml-0 rounded-r-2xl", "backdrop:bg-[color:var(--backdrop-scrim,oklch(0_0_0/0.5))] backdrop:backdrop-blur-sm pointer-coarse:backdrop:backdrop-blur-none", b),
21
+ "aria-describedby": c ? A : void 0,
22
+ "data-side": y,
23
+ className: t("zen__dialog glass glass-blur glow-edge text-card-foreground bg-card/90! overflow-visible p-0", !y && "m-auto max-h-[calc(100dvh-2rem)] max-w-[calc(100vw-2rem)] rounded-xl", !y && (v === "lg" ? "w-[60rem]" : "w-[28rem]"), y === "bottom" && "mx-auto mt-auto mb-0 max-h-[85dvh] w-full max-w-2xl rounded-t-2xl", (y === "left" || y === "right") && "my-0 h-dvh max-h-dvh w-[24rem] max-w-[calc(100vw-2.5rem)]", y === "right" && "mr-0 ml-auto rounded-l-2xl", y === "left" && "mr-auto ml-0 rounded-r-2xl", "backdrop:bg-[color:var(--backdrop-scrim,oklch(0_0_0/0.5))] backdrop:backdrop-blur-sm pointer-coarse:backdrop:backdrop-blur-none", b),
24
24
  onCancel: (e) => {
25
- e.preventDefault(), l && i?.(!1);
25
+ e.preventDefault(), u && a?.(!1);
26
26
  },
27
27
  onClick: (e) => {
28
- e.target === e.currentTarget && l && i?.(!1);
28
+ e.target === e.currentTarget && u && a?.(!1);
29
29
  },
30
30
  children: [/* @__PURE__ */ m("div", {
31
- className: e("flex flex-col gap-4 overflow-x-hidden overflow-y-auto p-6", v ? v === "bottom" ? "max-h-[85dvh] pt-3" : "h-full" : "max-h-[calc(100dvh-2rem)]"),
31
+ className: t("flex flex-col gap-4 overflow-x-hidden overflow-y-auto p-6", y ? y === "bottom" ? "max-h-[85dvh] pt-3" : "h-full" : "max-h-[calc(100dvh-2rem)]"),
32
32
  children: [
33
- v === "bottom" && /* @__PURE__ */ p("div", {
33
+ y === "bottom" && /* @__PURE__ */ p("div", {
34
34
  "aria-hidden": !0,
35
35
  className: "bg-tint/20 mx-auto h-1 w-10 shrink-0 rounded-full"
36
36
  }),
37
37
  /* @__PURE__ */ m("div", {
38
- className: e("flex flex-col gap-2", l && "pe-8"),
38
+ className: t("flex flex-col gap-2", u && "pe-8"),
39
39
  children: [/* @__PURE__ */ p("h2", {
40
40
  id: k,
41
41
  className: "text-lg font-semibold tracking-tight text-balance",
42
- children: o
43
- }), s && /* @__PURE__ */ p("p", {
42
+ children: s
43
+ }), c && /* @__PURE__ */ p("p", {
44
44
  id: A,
45
45
  className: "text-muted-foreground mt-0! text-sm leading-5",
46
- children: s
46
+ children: c
47
47
  })]
48
48
  }),
49
49
  /* @__PURE__ */ p(h.Provider, {
50
- value: () => i?.(!1),
51
- children: c
50
+ value: () => a?.(!1),
51
+ children: l
52
52
  })
53
53
  ]
54
- }), l && /* @__PURE__ */ p("button", {
54
+ }), u && /* @__PURE__ */ p("button", {
55
55
  type: "button",
56
56
  "aria-label": E,
57
- onClick: () => i?.(!1),
58
- className: e("text-muted-foreground hover:bg-tint/[0.07] hover:text-foreground absolute end-4 grid size-8 cursor-pointer place-items-center rounded-lg outline-hidden transition-colors focus-ring", v === "bottom" ? "top-7.5" : "top-5.5"),
59
- children: /* @__PURE__ */ p(a, { className: "size-4" })
57
+ onClick: () => a?.(!1),
58
+ className: t("text-muted-foreground hover:bg-tint/[0.07] hover:text-foreground absolute end-4 grid size-8 cursor-pointer place-items-center rounded-lg outline-hidden transition-colors focus-ring", y === "bottom" ? "top-7.5" : "top-5.5"),
59
+ children: /* @__PURE__ */ p(o, { className: "size-4" })
60
60
  })]
61
61
  });
62
62
  }
63
- function _(e, n, r) {
64
- t(), u(() => {
65
- let t = e.current;
66
- if (t) {
67
- if (n && !t.open) {
63
+ function _(e, t, r) {
64
+ n(), u(() => {
65
+ let n = e.current;
66
+ if (n) {
67
+ if (t && !n.open) {
68
68
  let e = document.documentElement;
69
69
  e.toggleAttribute("data-zen-scrollbar", window.innerWidth > e.clientWidth);
70
- let n = document.activeElement === document.body ? null : document.activeElement?.getBoundingClientRect(), i = !!n && !t.dataset.side;
71
- if (t.toggleAttribute("data-zen-from", i), t.showModal(), i) {
72
- let e = n.left + n.width / 2 - t.offsetLeft, r = n.top + n.height / 2 - t.offsetTop;
73
- t.style.transformOrigin = `${Math.round(e)}px ${Math.round(r)}px`;
70
+ let t = document.activeElement === document.body ? null : document.activeElement?.getBoundingClientRect(), i = !!t && !n.dataset.side;
71
+ if (n.toggleAttribute("data-zen-from", i), n.showModal(), i) {
72
+ let e = t.left + t.width / 2 - n.offsetLeft, r = t.top + t.height / 2 - n.offsetTop;
73
+ n.style.transformOrigin = `${Math.round(e)}px ${Math.round(r)}px`;
74
74
  }
75
75
  r?.current?.focus();
76
- } else !n && t.open && t.close();
76
+ } else !t && n.open && n.close();
77
77
  }
78
78
  }, [
79
79
  e,
80
- n,
80
+ t,
81
81
  r
82
- ]), o(e, n);
83
- }
84
- var v = .3;
85
- function y(e, t, n) {
86
- let r = t === "bottom" ? "y" : "x", i = t === "left" ? -1 : 1, a = () => r === "y" ? e.current.offsetHeight : e.current.offsetWidth, o = () => {
87
- e.current?.style.removeProperty("--zen-swipe"), e.current?.style.removeProperty("--zen-swipe-progress");
88
- };
89
- u(o, [e, t]), s(e, t ? {
90
- axis: r,
91
- sign: i
92
- } : void 0, {
93
- move: (t) => {
94
- let n = t > 0 ? t : t / 6;
95
- e.current.style.setProperty("--zen-swipe", r === "y" ? `0 ${n}px` : `${n * i}px 0`), e.current.style.setProperty("--zen-swipe-progress", String(Math.max(0, Math.min(1, t / a()))));
96
- },
97
- release: (e, t) => {
98
- e > a() * v || e > 0 && t > .5 ? n() : o();
99
- },
100
- cancel: o,
101
- threshold: () => a() * v
102
- });
82
+ ]), s(e, t);
103
83
  }
104
- function b({ className: t, ...n }) {
84
+ function v({ className: e, ...n }) {
105
85
  return /* @__PURE__ */ p("div", {
106
- className: e("flex justify-end gap-2", t),
86
+ className: t("flex justify-end gap-2", e),
107
87
  ...n
108
88
  });
109
89
  }
110
- function x({ onClick: e, ...t }) {
90
+ function y({ onClick: e, ...t }) {
111
91
  let n = l(h);
112
- return /* @__PURE__ */ p(i, {
92
+ return /* @__PURE__ */ p(a, {
113
93
  ...t,
114
94
  onClick: (t) => {
115
95
  e?.(t), t.defaultPrevented || n();
@@ -117,4 +97,4 @@ function x({ onClick: e, ...t }) {
117
97
  });
118
98
  }
119
99
  //#endregion
120
- export { x as DialogClose, b as DialogFooter, g as default, _ as useModal };
100
+ export { y as DialogClose, v as DialogFooter, g as default, _ as useModal };
@@ -0,0 +1,205 @@
1
+ # Zen
2
+
3
+ > React components in dark glass: translucent surfaces, hairline borders that catch a pointer light, one accent colour. Tailwind v4, no runtime dependencies.
4
+
5
+ ## Installation
6
+
7
+ ```sh
8
+ pnpm add @rinzai/zen
9
+ ```
10
+
11
+ React 19 is the only peer dependency.
12
+
13
+ **Using Tailwind CSS v4?** Add Zen's theme after Tailwind in your stylesheet. Your one Tailwind build then generates everything Zen's components use:
14
+
15
+ ```css
16
+ @import 'tailwindcss';
17
+ @import '@rinzai/zen/tailwind.css';
18
+ ```
19
+
20
+ **Not using Tailwind?** Import the complete stylesheet once, near the root of your app. It includes the default theme:
21
+
22
+ ```js
23
+ import '@rinzai/zen/css';
24
+ ```
25
+
26
+ Zen never styles your own elements. For its page setup (the background showing through), heading scale, inline code and quiet scrollbars, also add the optional base:
27
+
28
+ ```css
29
+ @import '@rinzai/zen/base.css';
30
+ ```
31
+
32
+ The look is set in [Geist](https://vercel.com/font); load it however you like.
33
+
34
+ ## Usage
35
+
36
+ ```tsx
37
+ import { Backdrop, Button, Card, CardHeader, CardTitle } from '@rinzai/zen';
38
+
39
+ export default function App() {
40
+ return (
41
+ <>
42
+ <Backdrop />
43
+ <Card>
44
+ <CardHeader>
45
+ <CardTitle>Budget</CardTitle>
46
+ </CardHeader>
47
+ <Button>Save changes</Button>
48
+ </Card>
49
+ </>
50
+ );
51
+ }
52
+ ```
53
+
54
+ ## Props
55
+
56
+ Every component takes `className`, and a class you pass always overrides the component's default. Other props (`id`, `aria-*`, `data-*`, handlers) and `ref` reach its element, and parts that render a link or button take `asChild` to use your own (a router's Link, say).
57
+
58
+ Zen exports no icons. Use any icon set (the examples use [Heroicons](https://heroicons.com)) and pass icons in as elements, such as `icon={<HomeIcon />}`.
59
+
60
+ ## Values and forms
61
+
62
+ Controls report changes with `onValueChange` (`onCheckedChange` for Checkbox and Toggle). Pass `value` to control one, or `defaultValue` to let it keep its own. Give a control a `name` and it's submitted with its form, the custom ones (Combobox, the date pickers, MoneyInput, ColorPicker, TagInput…) included, and goes back to its first value when the form is reset.
63
+
64
+ ## Languages and right to left
65
+
66
+ ```tsx
67
+ import { LocaleProvider } from '@rinzai/zen';
68
+
69
+ <LocaleProvider locale="fr-FR" messages={{ clear: 'Effacer', noResults: 'Aucun résultat' }}>
70
+ <App />
71
+ </LocaleProvider>;
72
+ ```
73
+
74
+ The locale formats dates, numbers and money, and sets the week's first day. `messages` replaces any of the words Zen shows or announces (`ENGLISH` lists them all); the rest stay English. With `dir="rtl"` on the page or any element above, layout, arrow keys and chevrons mirror.
75
+
76
+ ## Theming
77
+
78
+ Dark is the default. Add the `light` class (or `data-theme="light"`) for the light palette. Colours are OKLCH `L C H` triplets; override any token in your own CSS:
79
+
80
+ ```css
81
+ :root {
82
+ --primary: 0.72 0.13 200; /* teal instead of violet */
83
+ --glow: 0.7 0.13 200;
84
+ }
85
+ ```
86
+
87
+ Or generate a whole theme at runtime:
88
+
89
+ ```ts
90
+ import { applyPreset, applyTheme, DEFAULT_THEME } from '@rinzai/zen';
91
+
92
+ applyTheme(applyPreset(DEFAULT_THEME, 'ocean'));
93
+ ```
94
+
95
+ ## Overlays
96
+
97
+ For a page composited over something else, such as an OBS browser source, which never gets a pointer:
98
+
99
+ ```html
100
+ <html data-zen-glow="ambient" data-zen-page="transparent"></html>
101
+ ```
102
+
103
+ `data-zen-glow="ambient"` sends the edge light round each glowing border by itself (on any element, it does so for what's inside). `data-zen-page="transparent"` paints nothing behind the content; it needs the base stylesheet.
104
+
105
+ ## Browser support
106
+
107
+ Chrome and Edge 114+, Safari 17+ and Firefox 128+: the versions with the native Popover API that popups, menus and toasts are built on, and with what Tailwind v4 needs.
108
+
109
+ - **Popups** are placed with CSS anchor positioning where the browser has it (Chrome 129+, Safari 26+, recent Firefox). Elsewhere Zen places them itself, the same way.
110
+ - **Glass** is blurred live where there's a GPU and a mouse. On touch screens, without hardware acceleration, and with the OS's "reduce transparency", surfaces are solid instead.
111
+ - **Motion** such as entry animations is left out where a browser lacks it, and for anyone who prefers reduced motion.
112
+
113
+ Breaking changes and additions by version are in ../../CHANGELOG.md.
114
+
115
+ ## Components
116
+
117
+ - [Accordion](./accordion.md): Sections under headings that open one at a time, or several: questions and answers, or groups of settings.
118
+ - [Alert](./alert.md): A notice, warning or failure beside what it is about: a tinted box, or a plain line in a form or card.
119
+ - [Animated Number](./animated-number.md): Numbers and amounts that count smoothly to each new value.
120
+ - [Avatar](./avatar.md): A round picture, or the name's initial on the glowing accent. With an in-browser crop for uploads.
121
+ - [Backdrop](./backdrop.md): The page background: aurora glows over contours or dots, and a light that follows the pointer and catches card edges, or drifts round them by itself on pages with no pointer.
122
+ - [Badge](./badge.md): A small label for status, counts and tags.
123
+ - [Breadcrumbs](./breadcrumbs.md): Where a page sits: its parents as links, then the page itself. Works with any router.
124
+ - [Button](./button.md): Actions, from the one glowing primary action to quiet ghost buttons.
125
+ - [Button Group](./button-group.md): Buttons joined into one, rounded only at the ends: a split button, or Previous, Today and Next.
126
+ - [Calendar](./calendar.md): A month grid to pick a date or a range, fully keyboard-driven, with limits, blocked days and a year view to jump far.
127
+ - [Calendar Heatmap](./calendar-heatmap.md): A month of days shaded by their value, like spending per day.
128
+ - [Canvas](./canvas.md): A fixed-size surface where items sit anywhere, like the cards of a stream overlay: drag, resize and select several, by pointer, touch or keyboard, with snapping, a grid, undo and a fit-to-width scale.
129
+ - [Card](./card.md): Glass panels for grouping content, and stats for single figures.
130
+ - [Carousel](./carousel.md): Slides in a row that snap as you swipe or scroll, with glass buttons and dots that light the current one beneath, and the arrow keys. Native scrolling, so it follows the finger exactly.
131
+ - [Chart](./chart.md): Areas, lines and bars on one axis, a donut and an allocation bar: plain SVG that draws itself in, with a crosshair tooltip, keyboard reading, a legend and a table for screen readers.
132
+ - [Checkbox](./checkbox.md): A native checkbox whose tick draws itself in, with a label, a description and a mixed state.
133
+ - [Chip](./chip.md): Small pressable buttons for quick picks beside a field, like common tenures.
134
+ - [Code Block](./code-block.md): Code with a copy button; bring your own highlighter for colours. The copy button runs on useCopyToClipboard, which you can use for copy buttons anywhere.
135
+ - [Code Input](./code-input.md): A one-time code, a box per character, that types, pastes and autofills from a text message like any field.
136
+ - [Collapse](./collapse.md): Shows as many items as fit on one line, and the rest behind "+N".
137
+ - [Color Picker](./color-picker.md): Pick a colour by eye or by hex: a saturation and brightness area, hue and opacity, and your own swatches. With hexToOklch to give a colour to the theme engine.
138
+ - [Combobox](./combobox.md): Search and pick one or several items of any shape, composed from parts: field, panel, search, a virtualized list, empty and create rows.
139
+ - [Command Palette](./command-palette.md): Search everything and act on it from the keyboard: a field over a list that narrows as you type, opened with ⌘K.
140
+ - [Date Picker](./date-picker.md): A field that opens a calendar: one date, or a range previewed as you point. Dates are "YYYY-MM-DD" strings, so they never shift with time zones.
141
+ - [Dialog](./dialog.md): Modal dialogs on the native <dialog> element, sheets that slide in from an edge, and a confirmation for destructive actions.
142
+ - [Disclosure](./disclosure.md): A button that shows and hides a section, like finished goals under a list.
143
+ - [Editable Cell](./editable-cell.md): A value edited in place: shows the value, swaps in any editor on click or Enter.
144
+ - [Empty State](./empty-state.md): What a list or page shows when there's nothing in it yet, and the action that fills it.
145
+ - [Field](./field.md): A label, hint and error wired to their control for screen readers, and messages for a whole form.
146
+ - [File Drop](./file-drop.md): Somewhere to drop files, or click to choose them, that lights up as files are dragged over it.
147
+ - [Filter Bar](./filter-bar.md): The filters in effect, each removed with its ×, and Clear all.
148
+ - [Header](./header.md): A sticky glass bar across the top of the page.
149
+ - [Hover Card](./hover-card.md): A preview of what a link points to, like a person or an account: a glass card once the pointer rests on the link, or while it has keyboard focus.
150
+ - [Icon Picker](./icon-picker.md): An icon and a colour for something, like a spending category, from a grid in a popover.
151
+ - [Input](./input.md): Text fields in faint glass that glow on focus.
152
+ - [Input Group](./input-group.md): A field with slots: put symbols, icons, units, buttons or menus before and after the input.
153
+ - [Inset](./inset.md): A faint box set into a card: a tile for one figure, or a bordered panel for a result, tinted for good or bad news.
154
+ - [Kbd](./kbd.md): Keys on the keyboard, for shortcuts in hints and tooltips.
155
+ - [Keypad](./keypad.md): A number pad for typing an amount on a phone.
156
+ - [Load More](./load-more.md): The end of a long list that has more: loads the next page when it scrolls into view, or on a press.
157
+ - [Locale Provider](./locale-provider.md): The language for everything inside: how dates, numbers and money read, and every word components show or announce. Without it, "en-US" and English.
158
+ - [Marquee](./marquee.md): One line of text cut off with an ellipsis, that scrolls to show the rest on hover or focus (of itself or of its row), or all the time. Only text that doesn't fit moves.
159
+ - [Menu](./menu.md): A button that opens a menu, or a context menu from a right-click or long press, with your own trigger, a header, icons, groups, destructive items, checkbox and radio items, submenus, a bottom sheet on phones, and a menubar of menus.
160
+ - [Meter](./meter.md): A measure against a limit, like spend against a budget: warm near it, red past it.
161
+ - [Money Input](./money-input.md): Amounts in any currency and locale, with shorthand like 1.5L or 10k and sums like 120+45.50, exact to the paisa, and typed in other currencies, converted at your rates. Built on Input Group.
162
+ - [Month Picker](./month-picker.md): A field showing a month that opens a year and a 12-month grid, with optional limits and clearing.
163
+ - [Navigation Menu](./navigation-menu.md): A site’s navigation: links, and labels that open glass panels of links on hover or click, switching at once between them; works with any router.
164
+ - [Number Field](./number-field.md): A number to type or step with − and +, the arrow keys and Page Up and Down: shown the locale’s way, as a percentage or a unit, and kept within bounds. Each change says whether it was a step (and by how much) or typed, and onValueCommit fires once it’s finished.
165
+ - [Page Header](./page-header.md): Eyebrow, aurora title and lead paragraph for the top of a page.
166
+ - [Page Transition](./page-transition.md): The old page fades out as the new one rises in, when your router changes page in a view transition.
167
+ - [Pagination](./pagination.md): The pages a long list is split into, as buttons or links for your router.
168
+ - [Pills](./pills.md): A glass track with a glowing pill that slides to the current page. In a nav, it is site navigation; works with any router.
169
+ - [Player Bar](./player-bar.md): What's playing, along the bottom of the screen, sitting on a TabBar on phones. useMediaPlayer drives your own <audio> or <video>; useMediaSession puts it on the lock screen and the media keys.
170
+ - [Popover](./popover.md): A glass panel that opens from a button, on the native Popover API: small forms, cards and settings. For hints use Tooltip; for actions, Menu.
171
+ - [Progress Ring](./progress-ring.md): Circular progress with room for a label in the middle.
172
+ - [Radio Cards](./radio-cards.md): Choose one of a few cards that each show their option, like a colour palette.
173
+ - [Radio Group](./radio-group.md): Choose one of a list, each option with a label and a description; native radios, so arrow keys work.
174
+ - [Range Slider](./range-slider.md): Two thumbs on one track, for a span like an amount from $50 to $500.
175
+ - [Repeat Picker](./repeat-picker.md): How often something recurs, like a bill, said in words, with the next dates it falls on.
176
+ - [Resizable](./resizable.md): Panels with handles between them to drag, or to move with the arrow keys, within limits you set; groups nest, and the layout is reported to keep.
177
+ - [Seek Bar](./seek-bar.md): Where playback is in a track, and the way to move it: played and loaded on one track, the time played and the length beside it or under its ends.
178
+ - [Segmented](./segmented.md): A pill row for a few mutually exclusive options.
179
+ - [Select](./select.md): Pick one value from a short list, fully keyboard-driven. For long or searchable lists, use Combobox.
180
+ - [Separator](./separator.md): A hairline between groups of content, across or upright.
181
+ - [Side Nav](./side-nav.md): Vertical navigation in titled groups, for docs and settings sidebars. Works with any router.
182
+ - [Skeleton & Spinner](./skeleton.md): Placeholders for content on its way.
183
+ - [Slider](./slider.md): A native range input with a glowing thumb and any track you like.
184
+ - [Sortable List](./sortable.md): Put a list in order, or a tree of groups (a table’s rows, say), by dragging items by a grip or with the keyboard, each step announced: into other groups, open sub-items, or under another item. Also a virtualized list of hundreds.
185
+ - [Sparkline](./sparkline.md): A small line of how a number has moved, with no axes, for beside a figure. It draws itself in.
186
+ - [Spinner](./spinner.md): A small loading spinner in the current text colour, announced to screen readers when labelled.
187
+ - [Status Pill](./status-pill.md): A small status that changes in place, such as Saving…, Saved or Not saved with a Retry, and fades back once the news is old.
188
+ - [Stepper](./stepper.md): The steps of a flow and where you are in it; the line between them fills in as you go.
189
+ - [Tab Bar](./tab-bar.md): Phone navigation fixed to the bottom of the screen. Works with any router.
190
+ - [Table](./table.md): Composable tables: a glass panel that scrolls, sticky headers, first column and totals, sortable columns, rows reordered by drag and drop (into groups and under other rows), and virtual rows for long lists.
191
+ - [Table of Contents](./table-of-contents.md): An "On this page" list that highlights the section being read.
192
+ - [Tabs](./tabs.md): Switch between panels in place, with an underline or a glowing pill that slides to the active tab. To go to another page, use Pills.
193
+ - [Tag Input](./tag-input.md): A field of short values (tags, emails): Enter or a comma adds one, Backspace takes the last back.
194
+ - [Textarea](./textarea.md): Multi-line text, styled like Input.
195
+ - [Theme Toggle](./theme-toggle.md): Switches between the dark and light themes, remembering the choice itself or leaving it to your app.
196
+ - [Theming & styling](./theming.md): Your own colours from a few settings, readable in dark and light for any hue; and className overrides that always win.
197
+ - [Time Field](./time-field.md): A time of day, typed or stepped a part at a time, in the locale’s order, digits and 12- or 24-hour clock.
198
+ - [Timeline](./timeline.md): Events in order, each on a dot joined by a line: an activity feed or a history.
199
+ - [Toast](./toast.md): Short messages that confirm an action or report a problem, with an optional action like Undo. They stack into a deck that fans out when pointed at, and swipe away.
200
+ - [Toggle](./toggle.md): An on/off switch.
201
+ - [Toggle Group](./toggle-group.md): Buttons that stay pressed, in a row: any number of them, like filters, or at most one. One stop in the tab order; the arrow keys go through them.
202
+ - [Toolbar](./toolbar.md): A row of controls for one thing, like a table’s: one stop for Tab, and the arrow keys through its buttons, toggles and fields.
203
+ - [Tooltip](./tooltip.md): A short glass hint on hover or keyboard focus, describing its trigger to screen readers; below its trigger or beside it.
204
+ - [Tree Table](./tree.md): Rows that open into child rows, animated, built from useTree and the Table parts. With virtual rows and editable cells, enough for a budget planner.
205
+ - [Trend](./trend.md): A change, like +12% with an arrow, coloured by whether it is good news.
@@ -0,0 +1,122 @@
1
+ # Accordion
2
+
3
+ Sections under headings that open one at a time, or several: questions and answers, or groups of settings.
4
+
5
+ ```tsx
6
+ import { Accordion, AccordionItem, AccordionTrigger, AccordionContent } from '@rinzai/zen';
7
+ ```
8
+
9
+ ## Examples
10
+
11
+ ### Default
12
+
13
+ ```tsx
14
+ import { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Card, CardHeader, CardTitle } from '@rinzai/zen';
15
+
16
+ const QUESTIONS = [
17
+ {
18
+ q: 'How are other currencies converted?',
19
+ a: 'At the day’s rate when you save the entry. The original amount and rate are kept with it, so the conversion never changes later.',
20
+ },
21
+ {
22
+ q: 'Can I split one payment across categories?',
23
+ a: 'Yes: add it once, then split it. Each part counts towards its own category’s budget.',
24
+ },
25
+ {
26
+ q: 'What happens to a budget I go over?',
27
+ a: 'Nothing is blocked. The bar turns red, and the overspend is shown in the month’s summary.',
28
+ },
29
+ ];
30
+
31
+ /** Questions and answers: opening one closes the last. */
32
+ export default function Default() {
33
+ return (
34
+ <Card className="w-full max-w-md gap-2">
35
+ <CardHeader>
36
+ <CardTitle>Questions</CardTitle>
37
+ </CardHeader>
38
+ <Accordion defaultValue="0">
39
+ {QUESTIONS.map(({ q, a }, i) => (
40
+ <AccordionItem key={q} value={String(i)}>
41
+ <AccordionTrigger>{q}</AccordionTrigger>
42
+ <AccordionContent>{a}</AccordionContent>
43
+ </AccordionItem>
44
+ ))}
45
+ </Accordion>
46
+ </Card>
47
+ );
48
+ }
49
+ ```
50
+
51
+ ### Multiple
52
+
53
+ ```tsx
54
+ import { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Toggle } from '@rinzai/zen';
55
+
56
+ /** `multiple`: each section opens and closes on its own. */
57
+ export default function Multiple() {
58
+ return (
59
+ <Accordion multiple defaultValue={['alerts']} className="w-full max-w-sm">
60
+ <AccordionItem value="alerts">
61
+ <AccordionTrigger>Alerts</AccordionTrigger>
62
+ <AccordionContent className="flex flex-col gap-3">
63
+ <label className="flex items-center justify-between font-normal">
64
+ Over budget
65
+ <Toggle defaultChecked />
66
+ </label>
67
+ <label className="flex items-center justify-between font-normal">
68
+ Large payments
69
+ <Toggle />
70
+ </label>
71
+ </AccordionContent>
72
+ </AccordionItem>
73
+ <AccordionItem value="export">
74
+ <AccordionTrigger>Export</AccordionTrigger>
75
+ <AccordionContent>Download every entry as a CSV file, one row each.</AccordionContent>
76
+ </AccordionItem>
77
+ <AccordionItem value="danger">
78
+ <AccordionTrigger>Delete data</AccordionTrigger>
79
+ <AccordionContent>Removes every entry and budget. This can’t be undone.</AccordionContent>
80
+ </AccordionItem>
81
+ </Accordion>
82
+ );
83
+ }
84
+ ```
85
+
86
+ ## API reference
87
+
88
+ ### Accordion
89
+
90
+ Sections under headings that open one at a time (or several, with
91
+ `multiple`), e.g. questions and answers. Each AccordionItem is a Disclosure:
92
+ an AccordionTrigger and an AccordionContent that grows open and folds shut.
93
+ ↑↓ move between the headings, Home and End jump to the first and last.
94
+
95
+ | Prop | Type | Default | Description |
96
+ | --- | --- | --- | --- |
97
+ | `defaultValue` | `string \| readonly string[] \| null` | | |
98
+ | `multiple` | `boolean` | | One section open at a time (the default); opening one closes the other. Any number open at once. |
99
+ | `onValueChange` | `((value: string \| null) => void) \| ((value: readonly string[]) => void)` | | |
100
+ | `value` | `string \| readonly string[] \| null` | | The open section's value, or null for none, when you keep it. |
101
+
102
+ ### AccordionItem
103
+
104
+ One section: an AccordionTrigger and its AccordionContent.
105
+
106
+ | Prop | Type | Default | Description |
107
+ | --- | --- | --- | --- |
108
+ | `value` (required) | `string` | | Names the section in the Accordion's value. |
109
+
110
+ ### AccordionTrigger
111
+
112
+ The heading and its button: your label, and a chevron that turns over while open.
113
+
114
+ | Prop | Type | Default | Description |
115
+ | --- | --- | --- | --- |
116
+ | `level` | `2 \| 3 \| 4 \| 5 \| 6` | `3` | The heading level it sits in, to fit the page's outline. Default 3. |
117
+
118
+ ### AccordionContent
119
+
120
+ What the trigger shows and hides; only in the page while open (or folding shut).
121
+
122
+ No props of its own; it accepts the props of the element it renders.