@krizaka/ui 2.2.0 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (263) hide show
  1. package/README.md +17 -7
  2. package/dist/{button-Cgfkg_3y.d.ts → button-BMAO7dKF.d.ts} +29 -2
  3. package/dist/button.d.ts +32 -5
  4. package/dist/button.js +62 -9
  5. package/dist/button.js.map +1 -1
  6. package/dist/chip-link.d.ts +53 -0
  7. package/dist/chip-link.js +32 -0
  8. package/dist/chip-link.js.map +1 -0
  9. package/dist/chunk-43PTCDTL.js +31 -0
  10. package/dist/chunk-43PTCDTL.js.map +1 -0
  11. package/dist/chunk-6ISW63JI.js +11 -0
  12. package/dist/chunk-6ISW63JI.js.map +1 -0
  13. package/dist/chunk-HAQWKORZ.js +117 -0
  14. package/dist/chunk-HAQWKORZ.js.map +1 -0
  15. package/dist/{chunk-FHYZSO2S.js → chunk-R6SDS7JM.js} +5 -3
  16. package/dist/chunk-R6SDS7JM.js.map +1 -0
  17. package/dist/chunk-RUPNPMP3.js +103 -0
  18. package/dist/chunk-RUPNPMP3.js.map +1 -0
  19. package/dist/chunk-VDR2EP6K.js +49 -0
  20. package/dist/chunk-VDR2EP6K.js.map +1 -0
  21. package/dist/chunk-WEVYKZIF.js +33 -0
  22. package/dist/chunk-WEVYKZIF.js.map +1 -0
  23. package/dist/command.d.ts +7 -7
  24. package/dist/command.js +3 -2
  25. package/dist/command.js.map +1 -1
  26. package/dist/confirm-button.d.ts +1 -1
  27. package/dist/confirm-button.js +2 -1
  28. package/dist/confirm-button.js.map +1 -1
  29. package/dist/{dialog-GQ4Nvuyf.d.ts → dialog-D42QwYb_.d.ts} +11 -1
  30. package/dist/dialog.d.ts +1 -1
  31. package/dist/dialog.js +3 -2
  32. package/dist/dialog.js.map +1 -1
  33. package/dist/glow-card.d.ts +20 -0
  34. package/dist/glow-card.js +30 -0
  35. package/dist/glow-card.js.map +1 -0
  36. package/dist/index.d.ts +2 -20
  37. package/dist/index.js +7 -64
  38. package/dist/index.js.map +1 -1
  39. package/dist/iso.d.ts +400 -0
  40. package/dist/iso.js +363 -0
  41. package/dist/iso.js.map +1 -0
  42. package/dist/loader.d.ts +206 -0
  43. package/dist/loader.js +138 -0
  44. package/dist/loader.js.map +1 -0
  45. package/dist/marquee.d.ts +33 -0
  46. package/dist/marquee.js +52 -0
  47. package/dist/marquee.js.map +1 -0
  48. package/dist/meter.d.ts +146 -0
  49. package/dist/meter.js +107 -0
  50. package/dist/meter.js.map +1 -0
  51. package/dist/motion.css +394 -3
  52. package/dist/motion.d.ts +46 -0
  53. package/dist/motion.js +10 -0
  54. package/dist/motion.js.map +1 -0
  55. package/dist/nav-bar.d.ts +178 -0
  56. package/dist/nav-bar.js +157 -0
  57. package/dist/nav-bar.js.map +1 -0
  58. package/dist/number-ticker.d.ts +32 -0
  59. package/dist/number-ticker.js +61 -0
  60. package/dist/number-ticker.js.map +1 -0
  61. package/dist/progress.d.ts +56 -1
  62. package/dist/progress.js +72 -25
  63. package/dist/progress.js.map +1 -1
  64. package/dist/skeleton.d.ts +18 -3
  65. package/dist/skeleton.js +9 -1
  66. package/dist/skeleton.js.map +1 -1
  67. package/dist/spinner.d.ts +21 -5
  68. package/dist/spinner.js +13 -12
  69. package/dist/spinner.js.map +1 -1
  70. package/dist/stepper.d.ts +112 -0
  71. package/dist/stepper.js +67 -0
  72. package/dist/stepper.js.map +1 -0
  73. package/dist/tabs.d.ts +1 -1
  74. package/dist/tabs.js +14 -8
  75. package/dist/tabs.js.map +1 -1
  76. package/dist/theme.d.ts +1 -1
  77. package/dist/theme.js +2 -1
  78. package/dist/theme.js.map +1 -1
  79. package/dist/toast.d.ts +39 -4
  80. package/dist/toast.js +81 -7
  81. package/dist/toast.js.map +1 -1
  82. package/package.json +148 -8
  83. package/registry/alert.json +1 -1
  84. package/registry/avatar.json +1 -1
  85. package/registry/badge.json +1 -1
  86. package/registry/button.json +232 -26
  87. package/registry/card.json +1 -1
  88. package/registry/checkbox.json +1 -1
  89. package/registry/chip-link.json +158 -0
  90. package/registry/chip.json +1 -1
  91. package/registry/command.json +1 -1
  92. package/registry/confirm-button.json +91 -7
  93. package/registry/countdown.json +1 -1
  94. package/registry/dialog.json +15 -7
  95. package/registry/dropdown-menu.json +1 -1
  96. package/registry/empty-state.json +1 -1
  97. package/registry/examples/button/error.js +11 -0
  98. package/registry/examples/button/error.tsx +10 -0
  99. package/registry/examples/button/loading.tsx +1 -1
  100. package/registry/examples/button/save-flow.d.ts +4 -0
  101. package/registry/examples/button/save-flow.js +28 -0
  102. package/registry/examples/button/save-flow.tsx +24 -0
  103. package/registry/examples/button/signature.d.ts +4 -0
  104. package/registry/examples/button/signature.js +17 -0
  105. package/registry/examples/button/signature.tsx +19 -0
  106. package/registry/examples/button/upload-progress.d.ts +4 -0
  107. package/registry/examples/button/upload-progress.js +23 -0
  108. package/registry/examples/button/upload-progress.tsx +26 -0
  109. package/registry/examples/chip-link/filters.d.ts +4 -0
  110. package/registry/examples/chip-link/filters.js +12 -0
  111. package/registry/examples/chip-link/filters.tsx +17 -0
  112. package/registry/examples/dialog/left.d.ts +4 -0
  113. package/registry/examples/dialog/left.js +22 -0
  114. package/registry/examples/dialog/left.tsx +32 -0
  115. package/registry/examples/glow-card/link-card.d.ts +4 -0
  116. package/registry/examples/glow-card/link-card.js +14 -0
  117. package/registry/examples/glow-card/link-card.tsx +13 -0
  118. package/registry/examples/glow-card/plans.d.ts +4 -0
  119. package/registry/examples/glow-card/plans.js +25 -0
  120. package/registry/examples/glow-card/plans.tsx +26 -0
  121. package/registry/examples/glow-card/spotlight.d.ts +4 -0
  122. package/registry/examples/glow-card/spotlight.js +14 -0
  123. package/registry/examples/glow-card/spotlight.tsx +15 -0
  124. package/registry/examples/iso/compose.d.ts +4 -0
  125. package/registry/examples/iso/compose.js +22 -0
  126. package/registry/examples/iso/compose.tsx +19 -0
  127. package/registry/examples/iso/orazaka-hero.d.ts +4 -0
  128. package/registry/examples/iso/orazaka-hero.js +26 -0
  129. package/registry/examples/iso/orazaka-hero.tsx +21 -0
  130. package/registry/examples/iso/orochia-hero.d.ts +4 -0
  131. package/registry/examples/iso/orochia-hero.js +29 -0
  132. package/registry/examples/iso/orochia-hero.tsx +23 -0
  133. package/registry/examples/iso/still.d.ts +4 -0
  134. package/registry/examples/iso/still.js +21 -0
  135. package/registry/examples/iso/still.tsx +15 -0
  136. package/registry/examples/loader/endings.d.ts +4 -0
  137. package/registry/examples/loader/endings.js +14 -0
  138. package/registry/examples/loader/endings.tsx +11 -0
  139. package/registry/examples/loader/fetch-flow.d.ts +4 -0
  140. package/registry/examples/loader/fetch-flow.js +24 -0
  141. package/registry/examples/loader/fetch-flow.tsx +24 -0
  142. package/registry/examples/loader/minimal.d.ts +4 -0
  143. package/registry/examples/loader/minimal.js +11 -0
  144. package/registry/examples/loader/minimal.tsx +6 -0
  145. package/registry/examples/loader/overlay.d.ts +4 -0
  146. package/registry/examples/loader/overlay.js +16 -0
  147. package/registry/examples/loader/overlay.tsx +13 -0
  148. package/registry/examples/loader/region-handover.d.ts +4 -0
  149. package/registry/examples/loader/region-handover.js +42 -0
  150. package/registry/examples/loader/region-handover.tsx +29 -0
  151. package/registry/examples/loader/upload-eta.d.ts +4 -0
  152. package/registry/examples/loader/upload-eta.js +11 -0
  153. package/registry/examples/loader/upload-eta.tsx +10 -0
  154. package/registry/examples/marquee/cards.d.ts +4 -0
  155. package/registry/examples/marquee/cards.js +23 -0
  156. package/registry/examples/marquee/cards.tsx +21 -0
  157. package/registry/examples/marquee/logos.d.ts +4 -0
  158. package/registry/examples/marquee/logos.js +12 -0
  159. package/registry/examples/marquee/logos.tsx +17 -0
  160. package/registry/examples/meter/balance.d.ts +4 -0
  161. package/registry/examples/meter/balance.js +14 -0
  162. package/registry/examples/meter/balance.tsx +15 -0
  163. package/registry/examples/meter/quota.d.ts +4 -0
  164. package/registry/examples/meter/quota.js +15 -0
  165. package/registry/examples/meter/quota.tsx +12 -0
  166. package/registry/examples/meter/split.d.ts +4 -0
  167. package/registry/examples/meter/split.js +18 -0
  168. package/registry/examples/meter/split.tsx +18 -0
  169. package/registry/examples/nav-bar/app-bar.d.ts +4 -0
  170. package/registry/examples/nav-bar/app-bar.js +22 -0
  171. package/registry/examples/nav-bar/app-bar.tsx +21 -0
  172. package/registry/examples/nav-bar/menu-open.d.ts +4 -0
  173. package/registry/examples/nav-bar/menu-open.js +26 -0
  174. package/registry/examples/nav-bar/menu-open.tsx +26 -0
  175. package/registry/examples/nav-bar/site.d.ts +4 -0
  176. package/registry/examples/nav-bar/site.js +31 -0
  177. package/registry/examples/nav-bar/site.tsx +36 -0
  178. package/registry/examples/number-ticker/gradient.d.ts +4 -0
  179. package/registry/examples/number-ticker/gradient.js +11 -0
  180. package/registry/examples/number-ticker/gradient.tsx +10 -0
  181. package/registry/examples/number-ticker/live-total.d.ts +4 -0
  182. package/registry/examples/number-ticker/live-total.js +17 -0
  183. package/registry/examples/number-ticker/live-total.tsx +21 -0
  184. package/registry/examples/number-ticker/stats.d.ts +4 -0
  185. package/registry/examples/number-ticker/stats.js +19 -0
  186. package/registry/examples/number-ticker/stats.tsx +23 -0
  187. package/registry/examples/progress/buffer.d.ts +4 -0
  188. package/registry/examples/progress/buffer.js +11 -0
  189. package/registry/examples/progress/buffer.tsx +10 -0
  190. package/registry/examples/progress/statuses.d.ts +4 -0
  191. package/registry/examples/progress/statuses.js +14 -0
  192. package/registry/examples/progress/statuses.tsx +11 -0
  193. package/registry/examples/progress/steps.d.ts +4 -0
  194. package/registry/examples/progress/steps.js +14 -0
  195. package/registry/examples/progress/steps.tsx +13 -0
  196. package/registry/examples/progress/upload.d.ts +4 -0
  197. package/registry/examples/progress/upload.js +11 -0
  198. package/registry/examples/progress/upload.tsx +10 -0
  199. package/registry/examples/skeleton/paragraph.d.ts +4 -0
  200. package/registry/examples/skeleton/paragraph.js +14 -0
  201. package/registry/examples/skeleton/paragraph.tsx +12 -0
  202. package/registry/examples/skeleton/shape-of-content.d.ts +4 -0
  203. package/registry/examples/skeleton/shape-of-content.js +23 -0
  204. package/registry/examples/skeleton/shape-of-content.tsx +26 -0
  205. package/registry/examples/spinner/default.js +5 -2
  206. package/registry/examples/spinner/default.tsx +7 -1
  207. package/registry/examples/spinner/sizes.js +2 -1
  208. package/registry/examples/spinner/sizes.tsx +2 -0
  209. package/registry/examples/spinner/value.d.ts +4 -0
  210. package/registry/examples/spinner/value.js +11 -0
  211. package/registry/examples/spinner/value.tsx +12 -0
  212. package/registry/examples/stepper/checkout.d.ts +4 -0
  213. package/registry/examples/stepper/checkout.js +22 -0
  214. package/registry/examples/stepper/checkout.tsx +17 -0
  215. package/registry/examples/stepper/failed.d.ts +4 -0
  216. package/registry/examples/stepper/failed.js +26 -0
  217. package/registry/examples/stepper/failed.tsx +21 -0
  218. package/registry/examples/stepper/job.d.ts +4 -0
  219. package/registry/examples/stepper/job.js +32 -0
  220. package/registry/examples/stepper/job.tsx +28 -0
  221. package/registry/examples/toast/grouped.d.ts +4 -0
  222. package/registry/examples/toast/grouped.js +21 -0
  223. package/registry/examples/toast/grouped.tsx +23 -0
  224. package/registry/examples/toast/undo.d.ts +4 -0
  225. package/registry/examples/toast/undo.js +29 -0
  226. package/registry/examples/toast/undo.tsx +30 -0
  227. package/registry/examples/toast/upload-progress.d.ts +4 -0
  228. package/registry/examples/toast/upload-progress.js +29 -0
  229. package/registry/examples/toast/upload-progress.tsx +31 -0
  230. package/registry/field.json +1 -1
  231. package/registry/glow-card.json +162 -0
  232. package/registry/index.json +191 -20
  233. package/registry/iso.json +1355 -0
  234. package/registry/kbd.json +1 -1
  235. package/registry/loader.json +399 -0
  236. package/registry/marquee.json +225 -0
  237. package/registry/mascots.json +3 -3
  238. package/registry/meter.json +324 -0
  239. package/registry/nav-bar.json +480 -0
  240. package/registry/number-ticker.json +219 -0
  241. package/registry/page-header.json +1 -1
  242. package/registry/popover.json +1 -1
  243. package/registry/progress.json +116 -11
  244. package/registry/radio-group.json +1 -1
  245. package/registry/section-backdrop.json +1 -1
  246. package/registry/separator.json +1 -1
  247. package/registry/skeleton.json +69 -13
  248. package/registry/slider.json +1 -1
  249. package/registry/slot.json +1 -1
  250. package/registry/spinner.json +91 -27
  251. package/registry/stat.json +1 -1
  252. package/registry/stepper.json +174 -0
  253. package/registry/switch.json +1 -1
  254. package/registry/tabs.json +11 -7
  255. package/registry/theme.json +3 -3
  256. package/registry/toast.json +41 -13
  257. package/registry/tooltip.json +1 -1
  258. package/dist/chunk-FHYZSO2S.js.map +0 -1
  259. package/dist/chunk-PESA2R4U.js +0 -51
  260. package/dist/chunk-PESA2R4U.js.map +0 -1
  261. package/registry/examples/spinner/muted.js +0 -11
  262. package/registry/examples/spinner/muted.tsx +0 -6
  263. /package/registry/examples/{spinner/muted.d.ts → button/error.d.ts} +0 -0
package/dist/progress.js CHANGED
@@ -1,4 +1,5 @@
1
1
  // src/progress/progress.tsx
2
+ import * as React from "react";
2
3
  import { tv } from "tailwind-variants";
3
4
  import { jsx, jsxs } from "react/jsx-runtime";
4
5
  var progress = tv({
@@ -6,12 +7,17 @@ var progress = tv({
6
7
  root: "relative",
7
8
  track: "",
8
9
  indicator: "",
9
- center: "absolute inset-0 flex flex-col items-center justify-center text-center"
10
+ center: "absolute inset-0 flex flex-col items-center justify-center text-center",
11
+ buffer: "absolute inset-y-0 left-0 -z-10 rounded-full bg-accent/25 transition-[width] duration-500 motion-reduce:transition-none",
12
+ frame: "flex w-full flex-col gap-1.5",
13
+ header: "flex items-baseline gap-2 text-xs",
14
+ caption: "min-w-0 flex-1 truncate font-medium text-fg",
15
+ figure: "shrink-0 tabular-nums text-fg-secondary"
10
16
  },
11
17
  variants: {
12
18
  variant: {
13
19
  bar: {
14
- root: "w-full overflow-hidden rounded-full bg-surface-3",
20
+ root: "relative isolate w-full overflow-hidden rounded-full bg-surface-3",
15
21
  indicator: "kz-progress h-full rounded-full bg-linear-to-r from-accent to-accent-2 transition-[width] duration-500 motion-reduce:transition-none data-[state=indeterminate]:w-2/5"
16
22
  },
17
23
  ring: {
@@ -20,7 +26,14 @@ var progress = tv({
20
26
  indicator: "stroke-accent transition-[stroke-dashoffset] duration-1000 motion-reduce:transition-none data-[state=indeterminate]:origin-center data-[state=indeterminate]:animate-spin motion-reduce:data-[state=indeterminate]:animate-none"
21
27
  }
22
28
  },
23
- size: { sm: {}, md: {}, lg: {} }
29
+ size: { sm: {}, md: {}, lg: {} },
30
+ status: {
31
+ active: {},
32
+ // Paused: the fill rests, striped — the task is waiting for someone, not broken.
33
+ paused: { indicator: "kz-progress-paused opacity-70" },
34
+ // Failed: the fill turns to the danger colour where it stopped.
35
+ error: { indicator: "from-danger to-danger stroke-danger" }
36
+ }
24
37
  },
25
38
  compoundVariants: [
26
39
  { variant: "bar", size: "sm", class: { root: "h-1" } },
@@ -30,11 +43,27 @@ var progress = tv({
30
43
  { variant: "ring", size: "md", class: { root: "h-20 w-20" } },
31
44
  { variant: "ring", size: "lg", class: { root: "h-36 w-36" } }
32
45
  ],
33
- defaultVariants: { variant: "bar", size: "md" }
46
+ defaultVariants: { variant: "bar", size: "md", status: "active" }
34
47
  });
35
48
  var STROKE = { sm: 12, md: 9, lg: 7 };
36
- function Progress({ variant = "bar", size = "md", value, max = 100, label, valueText, className, children, ...props }) {
37
- const s = progress({ variant, size });
49
+ function Progress({
50
+ variant = "bar",
51
+ size = "md",
52
+ value,
53
+ max = 100,
54
+ label,
55
+ valueText,
56
+ className,
57
+ children,
58
+ buffer,
59
+ segments,
60
+ status = "active",
61
+ showLabel,
62
+ eta,
63
+ ...props
64
+ }) {
65
+ const s = progress({ variant, size, status });
66
+ const maskId = `kz-seg-${React.useId().replace(/[^a-zA-Z0-9_-]/g, "")}`;
38
67
  const known = typeof value === "number" && Number.isFinite(value);
39
68
  const ratio = known ? Math.min(1, Math.max(0, value / (max || 1))) : 0;
40
69
  const percent = Math.round(ratio * 100);
@@ -45,8 +74,9 @@ function Progress({ variant = "bar", size = "md", value, max = 100, label, value
45
74
  "aria-valuemin": known ? 0 : void 0,
46
75
  "aria-valuemax": known ? max : void 0,
47
76
  "aria-valuenow": known ? Math.min(max, Math.max(0, value)) : void 0,
48
- "aria-valuetext": known ? valueText ?? `${percent}%` : valueText,
77
+ "aria-valuetext": [known ? valueText ?? `${percent}%` : valueText, eta].filter(Boolean).join(", ") || void 0,
49
78
  "data-state": state,
79
+ "data-status": status === "active" ? void 0 : status,
50
80
  "data-value": known ? value : void 0,
51
81
  "data-variant": variant
52
82
  };
@@ -55,28 +85,45 @@ function Progress({ variant = "bar", size = "md", value, max = 100, label, value
55
85
  const r = 50 - stroke / 2;
56
86
  return /* @__PURE__ */ jsxs("div", { ...aria, className: s.root({ className }), ...props, children: [
57
87
  /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 100 100", className: "h-full w-full -rotate-90", "aria-hidden": true, children: [
58
- /* @__PURE__ */ jsx("circle", { cx: "50", cy: "50", r, fill: "none", strokeWidth: stroke, className: s.track() }),
59
- /* @__PURE__ */ jsx(
60
- "circle",
61
- {
62
- cx: "50",
63
- cy: "50",
64
- r,
65
- fill: "none",
66
- strokeWidth: stroke,
67
- strokeLinecap: "round",
68
- pathLength: 100,
69
- strokeDasharray: 100,
70
- strokeDashoffset: known ? 100 - percent : 75,
71
- "data-state": state,
72
- className: s.indicator()
73
- }
74
- )
88
+ segments && segments > 1 && /* @__PURE__ */ jsx("mask", { id: maskId, children: /* @__PURE__ */ jsx("circle", { cx: "50", cy: "50", r, fill: "none", stroke: "white", strokeWidth: stroke + 2, pathLength: 100, strokeDasharray: `${100 / segments - 2} 2` }) }),
89
+ /* @__PURE__ */ jsxs("g", { mask: segments && segments > 1 ? `url(#${maskId})` : void 0, children: [
90
+ /* @__PURE__ */ jsx("circle", { cx: "50", cy: "50", r, fill: "none", strokeWidth: stroke, className: s.track() }),
91
+ /* @__PURE__ */ jsx(
92
+ "circle",
93
+ {
94
+ cx: "50",
95
+ cy: "50",
96
+ r,
97
+ fill: "none",
98
+ strokeWidth: stroke,
99
+ strokeLinecap: "round",
100
+ pathLength: 100,
101
+ strokeDasharray: 100,
102
+ strokeDashoffset: known ? 100 - percent : 75,
103
+ "data-state": state,
104
+ className: s.indicator()
105
+ }
106
+ )
107
+ ] })
75
108
  ] }),
76
109
  children !== void 0 && /* @__PURE__ */ jsx("div", { className: s.center(), children })
77
110
  ] });
78
111
  }
79
- return /* @__PURE__ */ jsx("div", { ...aria, className: s.root({ className }), ...props, children: /* @__PURE__ */ jsx("div", { "data-state": state, className: s.indicator(), style: known ? { width: `${ratio * 100}%` } : void 0 }) });
112
+ const segmented = segments && segments > 1 ? { "--kz-segments": segments } : void 0;
113
+ const bufferRatio = typeof buffer === "number" && Number.isFinite(buffer) ? Math.min(1, Math.max(0, buffer / (max || 1))) : null;
114
+ const bar = /* @__PURE__ */ jsxs("div", { ...aria, className: s.root({ className: [segmented && "kz-progress-segmented", className].filter(Boolean).join(" ") || void 0 }), style: segmented, ...props, children: [
115
+ /* @__PURE__ */ jsx("div", { "data-state": state, className: s.indicator(), style: known ? { width: `${ratio * 100}%` } : void 0 }),
116
+ bufferRatio !== null && /* @__PURE__ */ jsx("div", { "aria-hidden": true, className: s.buffer(), style: { width: `${bufferRatio * 100}%` } })
117
+ ] });
118
+ if (!showLabel) return bar;
119
+ const figure = [known ? valueText ?? `${percent} %` : valueText, eta].filter(Boolean).join(" \xB7 ");
120
+ return /* @__PURE__ */ jsxs("div", { className: s.frame(), children: [
121
+ /* @__PURE__ */ jsxs("div", { "aria-hidden": true, className: s.header(), children: [
122
+ /* @__PURE__ */ jsx("span", { className: s.caption(), children: label }),
123
+ figure && /* @__PURE__ */ jsx("span", { className: s.figure(), children: figure })
124
+ ] }),
125
+ bar
126
+ ] });
80
127
  }
81
128
  export {
82
129
  Progress,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/progress/progress.tsx"],"sourcesContent":["// Server-safe: no hook, no context. role=\"progressbar\" with aria-valuenow / aria-valuemax (none when indeterminate),\n// named by `label`. A bar or a ring; the ring can hold content in its centre (an amount, a percentage).\nimport type * as React from \"react\";\nimport { tv, type VariantProps } from \"tailwind-variants\";\n\nexport const progress = tv({\n slots: {\n root: \"relative\",\n track: \"\",\n indicator: \"\",\n center: \"absolute inset-0 flex flex-col items-center justify-center text-center\",\n },\n variants: {\n variant: {\n bar: {\n root: \"w-full overflow-hidden rounded-full bg-surface-3\",\n indicator:\n \"kz-progress h-full rounded-full bg-linear-to-r from-accent to-accent-2 transition-[width] duration-500 motion-reduce:transition-none \" +\n \"data-[state=indeterminate]:w-2/5\",\n },\n ring: {\n root: \"inline-flex shrink-0 items-center justify-center\",\n track: \"stroke-border-default\",\n indicator:\n \"stroke-accent transition-[stroke-dashoffset] duration-1000 motion-reduce:transition-none \" +\n \"data-[state=indeterminate]:origin-center data-[state=indeterminate]:animate-spin motion-reduce:data-[state=indeterminate]:animate-none\",\n },\n },\n size: { sm: {}, md: {}, lg: {} },\n },\n compoundVariants: [\n { variant: \"bar\", size: \"sm\", class: { root: \"h-1\" } },\n { variant: \"bar\", size: \"md\", class: { root: \"h-2\" } },\n { variant: \"bar\", size: \"lg\", class: { root: \"h-3\" } },\n { variant: \"ring\", size: \"sm\", class: { root: \"h-10 w-10\" } },\n { variant: \"ring\", size: \"md\", class: { root: \"h-20 w-20\" } },\n { variant: \"ring\", size: \"lg\", class: { root: \"h-36 w-36\" } },\n ],\n defaultVariants: { variant: \"bar\", size: \"md\" },\n});\n\nexport type ProgressVariants = VariantProps<typeof progress>;\n\nexport type ProgressProps = Omit<React.ComponentProps<\"div\">, \"children\"> &\n ProgressVariants & {\n /** bar · ring (a ring holds its `children` in the centre). */\n variant?: ProgressVariants[\"variant\"];\n /** sm · md · lg: the bar's thickness, the ring's diameter. */\n size?: ProgressVariants[\"size\"];\n /** How far, between 0 and `max`. `null` or absent: indeterminate (a wait of unknown length). */\n value?: number | null;\n /** The value that means complete. */\n max?: number;\n /** The accessible name — passed translated (\"Upload\", \"Raised towards the goal\"). */\n label: string;\n /** The value in words for assistive technology (\"$420 of $1,000\") — default: the percentage. */\n valueText?: string;\n /** A ring's centre: an amount, a percentage, an icon. */\n children?: React.ReactNode;\n };\n\nconst STROKE = { sm: 12, md: 9, lg: 7 } as const;\n\n/** A progress bar or ring: `value` / `max`, indeterminate without a value. State: `data-state` (loading · complete · indeterminate). */\nexport function Progress({ variant = \"bar\", size = \"md\", value, max = 100, label, valueText, className, children, ...props }: ProgressProps) {\n const s = progress({ variant, size });\n const known = typeof value === \"number\" && Number.isFinite(value);\n const ratio = known ? Math.min(1, Math.max(0, value / (max || 1))) : 0;\n const percent = Math.round(ratio * 100);\n const state = !known ? \"indeterminate\" : ratio >= 1 ? \"complete\" : \"loading\";\n const aria = {\n role: \"progressbar\" as const,\n \"aria-label\": label,\n \"aria-valuemin\": known ? 0 : undefined,\n \"aria-valuemax\": known ? max : undefined,\n \"aria-valuenow\": known ? Math.min(max, Math.max(0, value)) : undefined,\n \"aria-valuetext\": known ? (valueText ?? `${percent}%`) : valueText,\n \"data-state\": state,\n \"data-value\": known ? value : undefined,\n \"data-variant\": variant,\n };\n if (variant === \"ring\") {\n const stroke = STROKE[size];\n const r = 50 - stroke / 2;\n return (\n <div {...aria} className={s.root({ className })} {...props}>\n <svg viewBox=\"0 0 100 100\" className=\"h-full w-full -rotate-90\" aria-hidden>\n <circle cx=\"50\" cy=\"50\" r={r} fill=\"none\" strokeWidth={stroke} className={s.track()} />\n <circle\n cx=\"50\"\n cy=\"50\"\n r={r}\n fill=\"none\"\n strokeWidth={stroke}\n strokeLinecap=\"round\"\n pathLength={100}\n strokeDasharray={100}\n strokeDashoffset={known ? 100 - percent : 75}\n data-state={state}\n className={s.indicator()}\n />\n </svg>\n {children !== undefined && <div className={s.center()}>{children}</div>}\n </div>\n );\n }\n return (\n <div {...aria} className={s.root({ className })} {...props}>\n <div data-state={state} className={s.indicator()} style={known ? { width: `${ratio * 100}%` } : undefined} />\n </div>\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/progress/progress.tsx"],"sourcesContent":["// Server-safe: no hook, no context. role=\"progressbar\" with aria-valuenow / aria-valuemax (none when indeterminate),\n// named by `label`. A bar or a ring; the ring can hold content in its centre (an amount, a percentage).\nimport * as React from \"react\";\nimport { tv, type VariantProps } from \"tailwind-variants\";\n\nexport const progress = tv({\n slots: {\n root: \"relative\",\n track: \"\",\n indicator: \"\",\n center: \"absolute inset-0 flex flex-col items-center justify-center text-center\",\n buffer: \"absolute inset-y-0 left-0 -z-10 rounded-full bg-accent/25 transition-[width] duration-500 motion-reduce:transition-none\",\n frame: \"flex w-full flex-col gap-1.5\",\n header: \"flex items-baseline gap-2 text-xs\",\n caption: \"min-w-0 flex-1 truncate font-medium text-fg\",\n figure: \"shrink-0 tabular-nums text-fg-secondary\",\n },\n variants: {\n variant: {\n bar: {\n root: \"relative isolate w-full overflow-hidden rounded-full bg-surface-3\",\n indicator:\n \"kz-progress h-full rounded-full bg-linear-to-r from-accent to-accent-2 transition-[width] duration-500 motion-reduce:transition-none \" +\n \"data-[state=indeterminate]:w-2/5\",\n },\n ring: {\n root: \"inline-flex shrink-0 items-center justify-center\",\n track: \"stroke-border-default\",\n indicator:\n \"stroke-accent transition-[stroke-dashoffset] duration-1000 motion-reduce:transition-none \" +\n \"data-[state=indeterminate]:origin-center data-[state=indeterminate]:animate-spin motion-reduce:data-[state=indeterminate]:animate-none\",\n },\n },\n size: { sm: {}, md: {}, lg: {} },\n status: {\n active: {},\n // Paused: the fill rests, striped — the task is waiting for someone, not broken.\n paused: { indicator: \"kz-progress-paused opacity-70\" },\n // Failed: the fill turns to the danger colour where it stopped.\n error: { indicator: \"from-danger to-danger stroke-danger\" },\n },\n },\n compoundVariants: [\n { variant: \"bar\", size: \"sm\", class: { root: \"h-1\" } },\n { variant: \"bar\", size: \"md\", class: { root: \"h-2\" } },\n { variant: \"bar\", size: \"lg\", class: { root: \"h-3\" } },\n { variant: \"ring\", size: \"sm\", class: { root: \"h-10 w-10\" } },\n { variant: \"ring\", size: \"md\", class: { root: \"h-20 w-20\" } },\n { variant: \"ring\", size: \"lg\", class: { root: \"h-36 w-36\" } },\n ],\n defaultVariants: { variant: \"bar\", size: \"md\", status: \"active\" },\n});\n\nexport type ProgressVariants = VariantProps<typeof progress>;\n\nexport type ProgressProps = Omit<React.ComponentProps<\"div\">, \"children\"> &\n ProgressVariants & {\n /** bar · ring (a ring holds its `children` in the centre). */\n variant?: ProgressVariants[\"variant\"];\n /** sm · md · lg: the bar's thickness, the ring's diameter. */\n size?: ProgressVariants[\"size\"];\n /** How far, between 0 and `max`. `null` or absent: indeterminate (a wait of unknown length). */\n value?: number | null;\n /** The value that means complete. */\n max?: number;\n /** The accessible name — passed translated (\"Upload\", \"Raised towards the goal\"). */\n label: string;\n /** The value in words for assistive technology (\"$420 of $1,000\") — default: the percentage. */\n valueText?: string;\n /** A ring's centre: an amount, a percentage, an icon. */\n children?: React.ReactNode;\n /** How far is already available beyond the value (a video buffered ahead), between 0 and `max` — bar only. */\n buffer?: number;\n /** Splits the bar or the ring into this many segments: the steps of a task, the parts of a goal. */\n segments?: number;\n /**\n * active · paused (the fill rests, striped: waiting for someone) · error (the fill turns to the danger colour where it stopped).\n * @default \"active\"\n */\n status?: ProgressVariants[\"status\"];\n /** Shows the label above the bar, with the percentage (or `valueText`) and `eta` — bar only. */\n showLabel?: boolean;\n /** The time left, in words (“About 2 min left”), shown with `showLabel` and read with the value — passed translated. */\n eta?: string;\n };\n\nconst STROKE = { sm: 12, md: 9, lg: 7 } as const;\n\n/** A progress bar or ring: `value` / `max`, indeterminate without a value. State: `data-state` (loading · complete · indeterminate). */\nexport function Progress({\n variant = \"bar\",\n size = \"md\",\n value,\n max = 100,\n label,\n valueText,\n className,\n children,\n buffer,\n segments,\n status = \"active\",\n showLabel,\n eta,\n ...props\n}: ProgressProps) {\n const s = progress({ variant, size, status });\n const maskId = `kz-seg-${React.useId().replace(/[^a-zA-Z0-9_-]/g, \"\")}`;\n const known = typeof value === \"number\" && Number.isFinite(value);\n const ratio = known ? Math.min(1, Math.max(0, value / (max || 1))) : 0;\n const percent = Math.round(ratio * 100);\n const state = !known ? \"indeterminate\" : ratio >= 1 ? \"complete\" : \"loading\";\n const aria = {\n role: \"progressbar\" as const,\n \"aria-label\": label,\n \"aria-valuemin\": known ? 0 : undefined,\n \"aria-valuemax\": known ? max : undefined,\n \"aria-valuenow\": known ? Math.min(max, Math.max(0, value)) : undefined,\n \"aria-valuetext\": [known ? (valueText ?? `${percent}%`) : valueText, eta].filter(Boolean).join(\", \") || undefined,\n \"data-state\": state,\n \"data-status\": status === \"active\" ? undefined : status,\n \"data-value\": known ? value : undefined,\n \"data-variant\": variant,\n };\n if (variant === \"ring\") {\n const stroke = STROKE[size];\n const r = 50 - stroke / 2;\n return (\n <div {...aria} className={s.root({ className })} {...props}>\n <svg viewBox=\"0 0 100 100\" className=\"h-full w-full -rotate-90\" aria-hidden>\n {segments && segments > 1 && (\n <mask id={maskId}>\n <circle cx=\"50\" cy=\"50\" r={r} fill=\"none\" stroke=\"white\" strokeWidth={stroke + 2} pathLength={100} strokeDasharray={`${100 / segments - 2} 2`} />\n </mask>\n )}\n <g mask={segments && segments > 1 ? `url(#${maskId})` : undefined}>\n <circle cx=\"50\" cy=\"50\" r={r} fill=\"none\" strokeWidth={stroke} className={s.track()} />\n <circle\n cx=\"50\"\n cy=\"50\"\n r={r}\n fill=\"none\"\n strokeWidth={stroke}\n strokeLinecap=\"round\"\n pathLength={100}\n strokeDasharray={100}\n strokeDashoffset={known ? 100 - percent : 75}\n data-state={state}\n className={s.indicator()}\n />\n </g>\n </svg>\n {children !== undefined && <div className={s.center()}>{children}</div>}\n </div>\n );\n }\n const segmented = segments && segments > 1 ? ({ \"--kz-segments\": segments } as React.CSSProperties) : undefined;\n const bufferRatio = typeof buffer === \"number\" && Number.isFinite(buffer) ? Math.min(1, Math.max(0, buffer / (max || 1))) : null;\n const bar = (\n <div {...aria} className={s.root({ className: [segmented && \"kz-progress-segmented\", className].filter(Boolean).join(\" \") || undefined })} style={segmented} {...props}>\n <div data-state={state} className={s.indicator()} style={known ? { width: `${ratio * 100}%` } : undefined} />\n {bufferRatio !== null && <div aria-hidden className={s.buffer()} style={{ width: `${bufferRatio * 100}%` }} />}\n </div>\n );\n if (!showLabel) return bar;\n const figure = [known ? (valueText ?? `${percent} %`) : valueText, eta].filter(Boolean).join(\" · \");\n return (\n <div className={s.frame()}>\n <div aria-hidden className={s.header()}>\n <span className={s.caption()}>{label}</span>\n {figure && <span className={s.figure()}>{figure}</span>}\n </div>\n {bar}\n </div>\n );\n}\n"],"mappings":"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","names":[]}
@@ -8,7 +8,7 @@ declare const skeletonVariants: tailwind_variants.TVReturnType<{
8
8
  circle: "aspect-square h-10 rounded-full";
9
9
  rect: "h-24 w-full rounded-lg";
10
10
  };
11
- }, undefined, "block bg-surface-3 motion-safe:animate-pulse", {
11
+ }, undefined, "kz-skeleton block bg-surface-3", {
12
12
  shape: {
13
13
  text: "h-3 w-full rounded-sm";
14
14
  circle: "aspect-square h-10 rounded-full";
@@ -28,7 +28,22 @@ type SkeletonProps = React.ComponentProps<"span"> & {
28
28
  */
29
29
  shape?: VariantProps<typeof skeletonVariants>["shape"];
30
30
  };
31
- /** A pulsing shape the size of what is loading. Announce the wait elsewhere (aria-busy on the region, a Spinner). */
31
+ /** A shape the size of what is loading. Announce the wait elsewhere (`LoadingRegion` does it, with `aria-busy`). */
32
32
  declare function Skeleton({ shape, className, ...props }: SkeletonProps): React.JSX.Element;
33
+ type SkeletonTextProps = React.ComponentProps<"span"> & {
34
+ /**
35
+ * How many lines.
36
+ * @default 3
37
+ */
38
+ lines?: number;
39
+ };
40
+ /** A paragraph on its way: `lines` lines, the last one shorter — like text that wraps. */
41
+ declare function SkeletonText({ lines, className, ...props }: SkeletonTextProps): React.JSX.Element;
42
+ type SkeletonShapeProps = React.ComponentProps<"div">;
43
+ /**
44
+ * The skeleton of the real thing: render your component with placeholder data inside, and its text, images and icons
45
+ * become skeleton shapes in place — the exact layout, nothing to draw twice. Inert and hidden from assistive technology.
46
+ */
47
+ declare function SkeletonShape({ className, children, ...props }: SkeletonShapeProps): React.JSX.Element;
33
48
 
34
- export { Skeleton, type SkeletonProps, skeletonVariants };
49
+ export { Skeleton, type SkeletonProps, SkeletonShape, type SkeletonShapeProps, SkeletonText, type SkeletonTextProps, skeletonVariants };
package/dist/skeleton.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import { tv } from "tailwind-variants";
3
3
  import { jsx } from "react/jsx-runtime";
4
4
  var skeletonVariants = tv({
5
- base: "block bg-surface-3 motion-safe:animate-pulse",
5
+ base: "kz-skeleton block bg-surface-3",
6
6
  variants: {
7
7
  shape: { text: "h-3 w-full rounded-sm", circle: "aspect-square h-10 rounded-full", rect: "h-24 w-full rounded-lg" }
8
8
  },
@@ -11,8 +11,16 @@ var skeletonVariants = tv({
11
11
  function Skeleton({ shape, className, ...props }) {
12
12
  return /* @__PURE__ */ jsx("span", { "aria-hidden": true, "data-shape": shape ?? "text", className: skeletonVariants({ shape, className }), ...props });
13
13
  }
14
+ function SkeletonText({ lines = 3, className, ...props }) {
15
+ return /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: ["flex w-full flex-col gap-2", className].filter(Boolean).join(" "), ...props, children: Array.from({ length: lines }, (_, i) => /* @__PURE__ */ jsx(Skeleton, { className: i === lines - 1 && lines > 1 ? "w-3/5" : void 0 }, i)) });
16
+ }
17
+ function SkeletonShape({ className, children, ...props }) {
18
+ return /* @__PURE__ */ jsx("div", { "aria-hidden": true, inert: true, className: ["kz-skeleton-shape", className].filter(Boolean).join(" "), ...props, children });
19
+ }
14
20
  export {
15
21
  Skeleton,
22
+ SkeletonShape,
23
+ SkeletonText,
16
24
  skeletonVariants
17
25
  };
18
26
  //# sourceMappingURL=skeleton.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/skeleton/skeleton.tsx"],"sourcesContent":["// Server-safe. A placeholder for content on its way: decorative, so hidden from assistive technology.\nimport type * as React from \"react\";\nimport { tv, type VariantProps } from \"tailwind-variants\";\n\nexport const skeletonVariants = tv({\n base: \"block bg-surface-3 motion-safe:animate-pulse\",\n variants: {\n shape: { text: \"h-3 w-full rounded-sm\", circle: \"aspect-square h-10 rounded-full\", rect: \"h-24 w-full rounded-lg\" },\n },\n defaultVariants: { shape: \"text\" },\n});\n\nexport type SkeletonProps = React.ComponentProps<\"span\"> & {\n /**\n * text (a line) · circle (an avatar; give it a height) · rect (a media; give it a height).\n * @default \"text\"\n */\n shape?: VariantProps<typeof skeletonVariants>[\"shape\"];\n};\n\n/** A pulsing shape the size of what is loading. Announce the wait elsewhere (aria-busy on the region, a Spinner). */\nexport function Skeleton({ shape, className, ...props }: SkeletonProps) {\n return <span aria-hidden data-shape={shape ?? \"text\"} className={skeletonVariants({ shape, className })} {...props} />;\n}\n"],"mappings":";AAEA,SAAS,UAA6B;AAoB7B;AAlBF,IAAM,mBAAmB,GAAG;AAAA,EACjC,MAAM;AAAA,EACN,UAAU;AAAA,IACR,OAAO,EAAE,MAAM,yBAAyB,QAAQ,mCAAmC,MAAM,yBAAyB;AAAA,EACpH;AAAA,EACA,iBAAiB,EAAE,OAAO,OAAO;AACnC,CAAC;AAWM,SAAS,SAAS,EAAE,OAAO,WAAW,GAAG,MAAM,GAAkB;AACtE,SAAO,oBAAC,UAAK,eAAW,MAAC,cAAY,SAAS,QAAQ,WAAW,iBAAiB,EAAE,OAAO,UAAU,CAAC,GAAI,GAAG,OAAO;AACtH;","names":[]}
1
+ {"version":3,"sources":["../src/skeleton/skeleton.tsx"],"sourcesContent":["// Server-safe. A placeholder for content on its way: decorative, so hidden from assistive technology. One reflection of\n// the brand light crosses every skeleton of the page together (`background-attachment: fixed`), instead of each one\n// pulsing on its own; under reduced motion they rest, tinted.\nimport type * as React from \"react\";\nimport { tv, type VariantProps } from \"tailwind-variants\";\n\nexport const skeletonVariants = tv({\n base: \"kz-skeleton block bg-surface-3\",\n variants: {\n shape: { text: \"h-3 w-full rounded-sm\", circle: \"aspect-square h-10 rounded-full\", rect: \"h-24 w-full rounded-lg\" },\n },\n defaultVariants: { shape: \"text\" },\n});\n\nexport type SkeletonProps = React.ComponentProps<\"span\"> & {\n /**\n * text (a line) · circle (an avatar; give it a height) · rect (a media; give it a height).\n * @default \"text\"\n */\n shape?: VariantProps<typeof skeletonVariants>[\"shape\"];\n};\n\n/** A shape the size of what is loading. Announce the wait elsewhere (`LoadingRegion` does it, with `aria-busy`). */\nexport function Skeleton({ shape, className, ...props }: SkeletonProps) {\n return <span aria-hidden data-shape={shape ?? \"text\"} className={skeletonVariants({ shape, className })} {...props} />;\n}\n\nexport type SkeletonTextProps = React.ComponentProps<\"span\"> & {\n /**\n * How many lines.\n * @default 3\n */\n lines?: number;\n};\n\n/** A paragraph on its way: `lines` lines, the last one shorter — like text that wraps. */\nexport function SkeletonText({ lines = 3, className, ...props }: SkeletonTextProps) {\n return (\n <span aria-hidden className={[\"flex w-full flex-col gap-2\", className].filter(Boolean).join(\" \")} {...props}>\n {Array.from({ length: lines }, (_, i) => (\n <Skeleton key={i} className={i === lines - 1 && lines > 1 ? \"w-3/5\" : undefined} />\n ))}\n </span>\n );\n}\n\nexport type SkeletonShapeProps = React.ComponentProps<\"div\">;\n\n/**\n * The skeleton of the real thing: render your component with placeholder data inside, and its text, images and icons\n * become skeleton shapes in place — the exact layout, nothing to draw twice. Inert and hidden from assistive technology.\n */\nexport function SkeletonShape({ className, children, ...props }: SkeletonShapeProps) {\n return (\n <div aria-hidden inert className={[\"kz-skeleton-shape\", className].filter(Boolean).join(\" \")} {...props}>\n {children}\n </div>\n );\n}\n"],"mappings":";AAIA,SAAS,UAA6B;AAoB7B;AAlBF,IAAM,mBAAmB,GAAG;AAAA,EACjC,MAAM;AAAA,EACN,UAAU;AAAA,IACR,OAAO,EAAE,MAAM,yBAAyB,QAAQ,mCAAmC,MAAM,yBAAyB;AAAA,EACpH;AAAA,EACA,iBAAiB,EAAE,OAAO,OAAO;AACnC,CAAC;AAWM,SAAS,SAAS,EAAE,OAAO,WAAW,GAAG,MAAM,GAAkB;AACtE,SAAO,oBAAC,UAAK,eAAW,MAAC,cAAY,SAAS,QAAQ,WAAW,iBAAiB,EAAE,OAAO,UAAU,CAAC,GAAI,GAAG,OAAO;AACtH;AAWO,SAAS,aAAa,EAAE,QAAQ,GAAG,WAAW,GAAG,MAAM,GAAsB;AAClF,SACE,oBAAC,UAAK,eAAW,MAAC,WAAW,CAAC,8BAA8B,SAAS,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,GAAI,GAAG,OACnG,gBAAM,KAAK,EAAE,QAAQ,MAAM,GAAG,CAAC,GAAG,MACjC,oBAAC,YAAiB,WAAW,MAAM,QAAQ,KAAK,QAAQ,IAAI,UAAU,UAAvD,CAAkE,CAClF,GACH;AAEJ;AAQO,SAAS,cAAc,EAAE,WAAW,UAAU,GAAG,MAAM,GAAuB;AACnF,SACE,oBAAC,SAAI,eAAW,MAAC,OAAK,MAAC,WAAW,CAAC,qBAAqB,SAAS,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,GAAI,GAAG,OAC/F,UACH;AAEJ;","names":[]}
package/dist/spinner.d.ts CHANGED
@@ -1,6 +1,17 @@
1
+ import * as React from 'react';
1
2
  import * as tailwind_variants from 'tailwind-variants';
2
3
  import { VariantProps } from 'tailwind-variants';
3
- import * as React from 'react';
4
+
5
+ /** What the glyph shows: a wait (with an optional value), or how it ended. */
6
+ type LoaderGlyphState = "loading" | "success" | "error";
7
+ interface LoaderGlyphProps extends Omit<React.ComponentProps<"svg">, "children"> {
8
+ /** loading · success · error. */
9
+ state?: LoaderGlyphState;
10
+ /** Between 0 and 1: a determinate wait, the trace grows to it. Absent: indeterminate. */
11
+ value?: number | null;
12
+ }
13
+ /** The glyph alone (decorative): the Spinner, the Loader and the Button's `loading` draw it. */
14
+ declare function LoaderGlyph({ state, value, ...props }: LoaderGlyphProps): React.JSX.Element;
4
15
 
5
16
  declare const spinnerVariants: tailwind_variants.TVReturnType<{
6
17
  size: {
@@ -8,7 +19,7 @@ declare const spinnerVariants: tailwind_variants.TVReturnType<{
8
19
  md: "h-6 w-6";
9
20
  lg: "h-10 w-10";
10
21
  };
11
- }, undefined, "shrink-0 text-accent motion-safe:animate-spin", {
22
+ }, undefined, "shrink-0 text-accent", {
12
23
  size: {
13
24
  sm: "h-4 w-4";
14
25
  md: "h-6 w-6";
@@ -29,8 +40,13 @@ type SpinnerProps = Omit<React.ComponentProps<"svg">, "children"> & VariantProps
29
40
  size?: VariantProps<typeof spinnerVariants>["size"];
30
41
  /** The accessible name of the wait, e.g. "Loading" — passed translated. */
31
42
  label: string;
43
+ /** Between 0 and 1: the trace grows to the value (a determinate wait). Absent: it travels around. */
44
+ value?: number | null;
32
45
  };
33
- /** A turning ring with `role="status"` (it stops turning under prefers-reduced-motion). */
34
- declare function Spinner({ label, size, className, ...props }: SpinnerProps): React.JSX.Element;
46
+ /**
47
+ * The Krizaka spinner: a hexagon traced by a segment of light around a breathing node, in `currentColor` (the accent by
48
+ * default). `role="status"`, named by `label`. Under prefers-reduced-motion it rests — a segment and the node lit.
49
+ */
50
+ declare function Spinner({ label, size, value, className, ...props }: SpinnerProps): React.JSX.Element;
35
51
 
36
- export { Spinner, type SpinnerProps, spinnerVariants };
52
+ export { LoaderGlyph, type LoaderGlyphProps, type LoaderGlyphState, Spinner, type SpinnerProps, spinnerVariants };
package/dist/spinner.js CHANGED
@@ -1,30 +1,31 @@
1
+ import {
2
+ LoaderGlyph
3
+ } from "./chunk-43PTCDTL.js";
4
+
1
5
  // src/spinner/spinner.tsx
2
6
  import { tv } from "tailwind-variants";
3
- import { jsx, jsxs } from "react/jsx-runtime";
7
+ import { jsx } from "react/jsx-runtime";
4
8
  var spinnerVariants = tv({
5
- base: "shrink-0 text-accent motion-safe:animate-spin",
9
+ base: "shrink-0 text-accent",
6
10
  variants: { size: { sm: "h-4 w-4", md: "h-6 w-6", lg: "h-10 w-10" } },
7
11
  defaultVariants: { size: "md" }
8
12
  });
9
- function Spinner({ label, size, className, ...props }) {
10
- return /* @__PURE__ */ jsxs(
11
- "svg",
13
+ function Spinner({ label, size, value, className, ...props }) {
14
+ return /* @__PURE__ */ jsx(
15
+ LoaderGlyph,
12
16
  {
13
17
  role: "status",
14
18
  "aria-label": label,
15
- viewBox: "0 0 24 24",
16
- fill: "none",
19
+ "aria-hidden": void 0,
20
+ value,
17
21
  "data-size": size ?? "md",
18
22
  className: spinnerVariants({ size, className }),
19
- ...props,
20
- children: [
21
- /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "9", stroke: "currentColor", strokeOpacity: "0.2", strokeWidth: "3" }),
22
- /* @__PURE__ */ jsx("path", { d: "M21 12a9 9 0 0 0-9-9", stroke: "currentColor", strokeWidth: "3", strokeLinecap: "round" })
23
- ]
23
+ ...props
24
24
  }
25
25
  );
26
26
  }
27
27
  export {
28
+ LoaderGlyph,
28
29
  Spinner,
29
30
  spinnerVariants
30
31
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/spinner/spinner.tsx"],"sourcesContent":["// Server-safe. An indeterminate wait: an SVG ring, announced as a status with its `label`.\nimport type * as React from \"react\";\nimport { tv, type VariantProps } from \"tailwind-variants\";\n\nexport const spinnerVariants = tv({\n base: \"shrink-0 text-accent motion-safe:animate-spin\",\n variants: { size: { sm: \"h-4 w-4\", md: \"h-6 w-6\", lg: \"h-10 w-10\" } },\n defaultVariants: { size: \"md\" },\n});\n\nexport type SpinnerProps = Omit<React.ComponentProps<\"svg\">, \"children\"> &\n VariantProps<typeof spinnerVariants> & {\n /**\n * sm · md · lg.\n * @default \"md\"\n */\n size?: VariantProps<typeof spinnerVariants>[\"size\"];\n /** The accessible name of the wait, e.g. \"Loading\" — passed translated. */\n label: string;\n };\n\n/** A turning ring with `role=\"status\"` (it stops turning under prefers-reduced-motion). */\nexport function Spinner({ label, size, className, ...props }: SpinnerProps) {\n return (\n <svg\n role=\"status\"\n aria-label={label}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n data-size={size ?? \"md\"}\n className={spinnerVariants({ size, className })}\n {...props}\n >\n <circle cx=\"12\" cy=\"12\" r=\"9\" stroke=\"currentColor\" strokeOpacity=\"0.2\" strokeWidth=\"3\" />\n <path d=\"M21 12a9 9 0 0 0-9-9\" stroke=\"currentColor\" strokeWidth=\"3\" strokeLinecap=\"round\" />\n </svg>\n );\n}\n"],"mappings":";AAEA,SAAS,UAA6B;AAsBlC,SASE,KATF;AApBG,IAAM,kBAAkB,GAAG;AAAA,EAChC,MAAM;AAAA,EACN,UAAU,EAAE,MAAM,EAAE,IAAI,WAAW,IAAI,WAAW,IAAI,YAAY,EAAE;AAAA,EACpE,iBAAiB,EAAE,MAAM,KAAK;AAChC,CAAC;AAcM,SAAS,QAAQ,EAAE,OAAO,MAAM,WAAW,GAAG,MAAM,GAAiB;AAC1E,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,cAAY;AAAA,MACZ,SAAQ;AAAA,MACR,MAAK;AAAA,MACL,aAAW,QAAQ;AAAA,MACnB,WAAW,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAAA,MAC7C,GAAG;AAAA,MAEJ;AAAA,4BAAC,YAAO,IAAG,MAAK,IAAG,MAAK,GAAE,KAAI,QAAO,gBAAe,eAAc,OAAM,aAAY,KAAI;AAAA,QACxF,oBAAC,UAAK,GAAE,wBAAuB,QAAO,gBAAe,aAAY,KAAI,eAAc,SAAQ;AAAA;AAAA;AAAA,EAC7F;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../src/spinner/spinner.tsx"],"sourcesContent":["// Server-safe. An indeterminate wait: the Krizaka loader glyph (a hexagon traced by light around a node), announced as\n// a status with its `label`. For a wait with a delay, a value, an ETA or an ending, see `@krizaka/ui/loader`.\nimport type * as React from \"react\";\nimport { tv, type VariantProps } from \"tailwind-variants\";\n\nimport { LoaderGlyph } from \"./glyph\";\n\nexport const spinnerVariants = tv({\n base: \"shrink-0 text-accent\",\n variants: { size: { sm: \"h-4 w-4\", md: \"h-6 w-6\", lg: \"h-10 w-10\" } },\n defaultVariants: { size: \"md\" },\n});\n\nexport type SpinnerProps = Omit<React.ComponentProps<\"svg\">, \"children\"> &\n VariantProps<typeof spinnerVariants> & {\n /**\n * sm · md · lg.\n * @default \"md\"\n */\n size?: VariantProps<typeof spinnerVariants>[\"size\"];\n /** The accessible name of the wait, e.g. \"Loading\" — passed translated. */\n label: string;\n /** Between 0 and 1: the trace grows to the value (a determinate wait). Absent: it travels around. */\n value?: number | null;\n };\n\n/**\n * The Krizaka spinner: a hexagon traced by a segment of light around a breathing node, in `currentColor` (the accent by\n * default). `role=\"status\"`, named by `label`. Under prefers-reduced-motion it rests — a segment and the node lit.\n */\nexport function Spinner({ label, size, value, className, ...props }: SpinnerProps) {\n return (\n <LoaderGlyph\n role=\"status\"\n aria-label={label}\n aria-hidden={undefined}\n value={value}\n data-size={size ?? \"md\"}\n className={spinnerVariants({ size, className })}\n {...props}\n />\n );\n}\n"],"mappings":";;;;;AAGA,SAAS,UAA6B;AA6BlC;AAzBG,IAAM,kBAAkB,GAAG;AAAA,EAChC,MAAM;AAAA,EACN,UAAU,EAAE,MAAM,EAAE,IAAI,WAAW,IAAI,WAAW,IAAI,YAAY,EAAE;AAAA,EACpE,iBAAiB,EAAE,MAAM,KAAK;AAChC,CAAC;AAmBM,SAAS,QAAQ,EAAE,OAAO,MAAM,OAAO,WAAW,GAAG,MAAM,GAAiB;AACjF,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,cAAY;AAAA,MACZ,eAAa;AAAA,MACb;AAAA,MACA,aAAW,QAAQ;AAAA,MACnB,WAAW,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAAA,MAC7C,GAAG;AAAA;AAAA,EACN;AAEJ;","names":[]}
@@ -0,0 +1,112 @@
1
+ import * as tailwind_variants from 'tailwind-variants';
2
+ import * as React from 'react';
3
+
4
+ type StepStatus = "done" | "current" | "upcoming" | "error";
5
+ interface Step {
6
+ /** Its name — passed translated. */
7
+ title: string;
8
+ /** One line under it (what happens, a time) — passed translated. */
9
+ description?: string;
10
+ /** Where it stands; by default from `current` (before: done, at: current, after: upcoming). */
11
+ status?: StepStatus;
12
+ /** Between 0 and 1 for the current step: its glyph grows to it. */
13
+ value?: number;
14
+ /** Anything under the step while it is current or failed: a progress bar, an action, a detail. */
15
+ content?: React.ReactNode;
16
+ }
17
+ declare const stepper: tailwind_variants.TVReturnType<{
18
+ orientation: {
19
+ vertical: {
20
+ root: string;
21
+ step: string;
22
+ connector: string;
23
+ body: string;
24
+ };
25
+ horizontal: {
26
+ root: string;
27
+ step: string;
28
+ connector: string;
29
+ body: string;
30
+ };
31
+ };
32
+ }, {
33
+ root: string;
34
+ step: string;
35
+ node: string;
36
+ glyph: string;
37
+ connector: string;
38
+ body: string;
39
+ title: string;
40
+ description: string;
41
+ state: string;
42
+ content: string;
43
+ }, undefined, {
44
+ orientation: {
45
+ vertical: {
46
+ root: string;
47
+ step: string;
48
+ connector: string;
49
+ body: string;
50
+ };
51
+ horizontal: {
52
+ root: string;
53
+ step: string;
54
+ connector: string;
55
+ body: string;
56
+ };
57
+ };
58
+ }, {
59
+ root: string;
60
+ step: string;
61
+ node: string;
62
+ glyph: string;
63
+ connector: string;
64
+ body: string;
65
+ title: string;
66
+ description: string;
67
+ state: string;
68
+ content: string;
69
+ }, tailwind_variants.TVReturnTypeLike<{
70
+ orientation: {
71
+ vertical: {
72
+ root: string;
73
+ step: string;
74
+ connector: string;
75
+ body: string;
76
+ };
77
+ horizontal: {
78
+ root: string;
79
+ step: string;
80
+ connector: string;
81
+ body: string;
82
+ };
83
+ };
84
+ }, {
85
+ root: string;
86
+ step: string;
87
+ node: string;
88
+ glyph: string;
89
+ connector: string;
90
+ body: string;
91
+ title: string;
92
+ description: string;
93
+ state: string;
94
+ content: string;
95
+ }>>;
96
+ type StepperProps = Omit<React.ComponentProps<"ol">, "children"> & {
97
+ /** The steps, in order. */
98
+ steps: readonly Step[];
99
+ /** The index of the current step: those before it are done, those after it upcoming (a step's own `status` wins). */
100
+ current?: number;
101
+ /** What each state is called, read with every step (“Done”, “In progress”, “Upcoming”, “Failed”) — passed translated. */
102
+ labels: Readonly<Record<StepStatus, string>>;
103
+ /**
104
+ * vertical (a job, a timeline) · horizontal (a short journey, a checkout).
105
+ * @default "vertical"
106
+ */
107
+ orientation?: "vertical" | "horizontal";
108
+ };
109
+ /** An ordered list of steps: `aria-current="step"` on the current one, each state said in words. */
110
+ declare function Stepper({ steps, current, labels, orientation, className, ...props }: StepperProps): React.JSX.Element;
111
+
112
+ export { type Step, type StepStatus, Stepper, type StepperProps, stepper };
@@ -0,0 +1,67 @@
1
+ import {
2
+ LoaderGlyph
3
+ } from "./chunk-43PTCDTL.js";
4
+
5
+ // src/stepper/stepper.tsx
6
+ import { tv } from "tailwind-variants";
7
+ import { jsx, jsxs } from "react/jsx-runtime";
8
+ var stepper = tv({
9
+ slots: {
10
+ root: "flex",
11
+ step: "group/step relative flex min-w-0",
12
+ node: "relative z-10 flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-surface-0",
13
+ glyph: "h-6 w-6",
14
+ connector: "absolute bg-border-default after:absolute after:inset-0 after:origin-top-left after:bg-accent after:transition-transform after:duration-700 motion-reduce:after:transition-none",
15
+ body: "min-w-0",
16
+ title: "text-sm font-semibold text-fg group-data-[status=upcoming]/step:text-fg-secondary",
17
+ description: "mt-0.5 text-xs text-fg-secondary",
18
+ state: "sr-only",
19
+ content: "mt-2"
20
+ },
21
+ variants: {
22
+ orientation: {
23
+ vertical: {
24
+ root: "flex-col",
25
+ step: "gap-3 pb-6 last:pb-0",
26
+ connector: "left-3.5 top-7 bottom-0 w-0.5 -translate-x-1/2 group-last/step:hidden after:scale-y-0 group-data-[status=done]/step:after:scale-y-100",
27
+ body: "pt-1"
28
+ },
29
+ horizontal: {
30
+ root: "flex-row",
31
+ step: "flex-1 flex-col gap-2 pr-3 last:flex-none last:pr-0",
32
+ connector: "left-8 right-1 top-3.5 h-0.5 -translate-y-1/2 group-last/step:hidden after:scale-x-0 group-data-[status=done]/step:after:scale-x-100",
33
+ body: ""
34
+ }
35
+ }
36
+ },
37
+ defaultVariants: { orientation: "vertical" }
38
+ });
39
+ var GLYPH = { done: "success", current: "loading", error: "error", upcoming: null };
40
+ var TONE = { done: "text-accent", current: "text-accent", error: "text-fg-danger", upcoming: "text-border-strong" };
41
+ function Stepper({ steps, current = 0, labels, orientation = "vertical", className, ...props }) {
42
+ const s = stepper({ orientation });
43
+ return /* @__PURE__ */ jsx("ol", { className: s.root({ className }), "data-orientation": orientation, ...props, children: steps.map((step, i) => {
44
+ const status = step.status ?? (i < current ? "done" : i === current ? "current" : "upcoming");
45
+ const glyph = GLYPH[status];
46
+ return /* @__PURE__ */ jsxs("li", { "data-status": status, "aria-current": status === "current" ? "step" : void 0, className: s.step(), children: [
47
+ /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: s.connector() }),
48
+ /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: s.node(), children: glyph ? /* @__PURE__ */ jsx(LoaderGlyph, { state: glyph, value: status === "current" ? step.value : void 0, className: [s.glyph(), TONE[status]].join(" ") }) : /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", className: [s.glyph(), TONE[status]].join(" "), children: /* @__PURE__ */ jsx("path", { d: "M12 3 19.79 7.5 19.79 16.5 12 21 4.21 16.5 4.21 7.5Z", stroke: "currentColor", strokeWidth: "2", strokeLinejoin: "round" }) }) }),
49
+ /* @__PURE__ */ jsxs("div", { className: s.body(), children: [
50
+ /* @__PURE__ */ jsxs("p", { className: s.title(), children: [
51
+ step.title,
52
+ /* @__PURE__ */ jsxs("span", { className: s.state(), children: [
53
+ " \u2014 ",
54
+ labels[status]
55
+ ] })
56
+ ] }),
57
+ step.description && /* @__PURE__ */ jsx("p", { className: s.description(), children: step.description }),
58
+ step.content && (status === "current" || status === "error") && /* @__PURE__ */ jsx("div", { className: s.content(), children: step.content })
59
+ ] })
60
+ ] }, i);
61
+ }) });
62
+ }
63
+ export {
64
+ Stepper,
65
+ stepper
66
+ };
67
+ //# sourceMappingURL=stepper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/stepper/stepper.tsx"],"sourcesContent":["// Server-safe. The steps of a journey or a job: an ordered list whose nodes are the Krizaka loader glyph — the current\n// step traces its hexagon (and grows to its `value` when known), a done step draws its check, a failed one its cross —\n// joined by connectors that fill as the journey advances. The state of every step is said in words, not only colour.\nimport type * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nimport { LoaderGlyph } from \"../spinner/glyph\";\n\nexport type StepStatus = \"done\" | \"current\" | \"upcoming\" | \"error\";\n\nexport interface Step {\n /** Its name — passed translated. */\n title: string;\n /** One line under it (what happens, a time) — passed translated. */\n description?: string;\n /** Where it stands; by default from `current` (before: done, at: current, after: upcoming). */\n status?: StepStatus;\n /** Between 0 and 1 for the current step: its glyph grows to it. */\n value?: number;\n /** Anything under the step while it is current or failed: a progress bar, an action, a detail. */\n content?: React.ReactNode;\n}\n\nexport const stepper = tv({\n slots: {\n root: \"flex\",\n step: \"group/step relative flex min-w-0\",\n node: \"relative z-10 flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-surface-0\",\n glyph: \"h-6 w-6\",\n connector: \"absolute bg-border-default after:absolute after:inset-0 after:origin-top-left after:bg-accent after:transition-transform after:duration-700 motion-reduce:after:transition-none\",\n body: \"min-w-0\",\n title: \"text-sm font-semibold text-fg group-data-[status=upcoming]/step:text-fg-secondary\",\n description: \"mt-0.5 text-xs text-fg-secondary\",\n state: \"sr-only\",\n content: \"mt-2\",\n },\n variants: {\n orientation: {\n vertical: {\n root: \"flex-col\",\n step: \"gap-3 pb-6 last:pb-0\",\n connector: \"left-3.5 top-7 bottom-0 w-0.5 -translate-x-1/2 group-last/step:hidden after:scale-y-0 group-data-[status=done]/step:after:scale-y-100\",\n body: \"pt-1\",\n },\n horizontal: {\n root: \"flex-row\",\n step: \"flex-1 flex-col gap-2 pr-3 last:flex-none last:pr-0\",\n connector: \"left-8 right-1 top-3.5 h-0.5 -translate-y-1/2 group-last/step:hidden after:scale-x-0 group-data-[status=done]/step:after:scale-x-100\",\n body: \"\",\n },\n },\n },\n defaultVariants: { orientation: \"vertical\" },\n});\n\nconst GLYPH: Record<StepStatus, \"loading\" | \"success\" | \"error\" | null> = { done: \"success\", current: \"loading\", error: \"error\", upcoming: null };\nconst TONE: Record<StepStatus, string> = { done: \"text-accent\", current: \"text-accent\", error: \"text-fg-danger\", upcoming: \"text-border-strong\" };\n\nexport type StepperProps = Omit<React.ComponentProps<\"ol\">, \"children\"> & {\n /** The steps, in order. */\n steps: readonly Step[];\n /** The index of the current step: those before it are done, those after it upcoming (a step's own `status` wins). */\n current?: number;\n /** What each state is called, read with every step (“Done”, “In progress”, “Upcoming”, “Failed”) — passed translated. */\n labels: Readonly<Record<StepStatus, string>>;\n /**\n * vertical (a job, a timeline) · horizontal (a short journey, a checkout).\n * @default \"vertical\"\n */\n orientation?: \"vertical\" | \"horizontal\";\n};\n\n/** An ordered list of steps: `aria-current=\"step\"` on the current one, each state said in words. */\nexport function Stepper({ steps, current = 0, labels, orientation = \"vertical\", className, ...props }: StepperProps) {\n const s = stepper({ orientation });\n return (\n <ol className={s.root({ className })} data-orientation={orientation} {...props}>\n {steps.map((step, i) => {\n const status: StepStatus = step.status ?? (i < current ? \"done\" : i === current ? \"current\" : \"upcoming\");\n const glyph = GLYPH[status];\n return (\n <li key={i} data-status={status} aria-current={status === \"current\" ? \"step\" : undefined} className={s.step()}>\n <span aria-hidden className={s.connector()} />\n <span aria-hidden className={s.node()}>\n {glyph ? (\n <LoaderGlyph state={glyph} value={status === \"current\" ? step.value : undefined} className={[s.glyph(), TONE[status]].join(\" \")} />\n ) : (\n <svg viewBox=\"0 0 24 24\" fill=\"none\" className={[s.glyph(), TONE[status]].join(\" \")}>\n <path d=\"M12 3 19.79 7.5 19.79 16.5 12 21 4.21 16.5 4.21 7.5Z\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinejoin=\"round\" />\n </svg>\n )}\n </span>\n <div className={s.body()}>\n <p className={s.title()}>\n {step.title}\n <span className={s.state()}> — {labels[status]}</span>\n </p>\n {step.description && <p className={s.description()}>{step.description}</p>}\n {step.content && (status === \"current\" || status === \"error\") && <div className={s.content()}>{step.content}</div>}\n </div>\n </li>\n );\n })}\n </ol>\n );\n}\n"],"mappings":";;;;;AAIA,SAAS,UAAU;AA8EP,cAaI,YAbJ;AA3DL,IAAM,UAAU,GAAG;AAAA,EACxB,OAAO;AAAA,IACL,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,OAAO;AAAA,IACP,WAAW;AAAA,IACX,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,IACb,OAAO;AAAA,IACP,SAAS;AAAA,EACX;AAAA,EACA,UAAU;AAAA,IACR,aAAa;AAAA,MACX,UAAU;AAAA,QACR,MAAM;AAAA,QACN,MAAM;AAAA,QACN,WAAW;AAAA,QACX,MAAM;AAAA,MACR;AAAA,MACA,YAAY;AAAA,QACV,MAAM;AAAA,QACN,MAAM;AAAA,QACN,WAAW;AAAA,QACX,MAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAAA,EACA,iBAAiB,EAAE,aAAa,WAAW;AAC7C,CAAC;AAED,IAAM,QAAoE,EAAE,MAAM,WAAW,SAAS,WAAW,OAAO,SAAS,UAAU,KAAK;AAChJ,IAAM,OAAmC,EAAE,MAAM,eAAe,SAAS,eAAe,OAAO,kBAAkB,UAAU,qBAAqB;AAiBzI,SAAS,QAAQ,EAAE,OAAO,UAAU,GAAG,QAAQ,cAAc,YAAY,WAAW,GAAG,MAAM,GAAiB;AACnH,QAAM,IAAI,QAAQ,EAAE,YAAY,CAAC;AACjC,SACE,oBAAC,QAAG,WAAW,EAAE,KAAK,EAAE,UAAU,CAAC,GAAG,oBAAkB,aAAc,GAAG,OACtE,gBAAM,IAAI,CAAC,MAAM,MAAM;AACtB,UAAM,SAAqB,KAAK,WAAW,IAAI,UAAU,SAAS,MAAM,UAAU,YAAY;AAC9F,UAAM,QAAQ,MAAM,MAAM;AAC1B,WACE,qBAAC,QAAW,eAAa,QAAQ,gBAAc,WAAW,YAAY,SAAS,QAAW,WAAW,EAAE,KAAK,GAC1G;AAAA,0BAAC,UAAK,eAAW,MAAC,WAAW,EAAE,UAAU,GAAG;AAAA,MAC5C,oBAAC,UAAK,eAAW,MAAC,WAAW,EAAE,KAAK,GACjC,kBACC,oBAAC,eAAY,OAAO,OAAO,OAAO,WAAW,YAAY,KAAK,QAAQ,QAAW,WAAW,CAAC,EAAE,MAAM,GAAG,KAAK,MAAM,CAAC,EAAE,KAAK,GAAG,GAAG,IAEjI,oBAAC,SAAI,SAAQ,aAAY,MAAK,QAAO,WAAW,CAAC,EAAE,MAAM,GAAG,KAAK,MAAM,CAAC,EAAE,KAAK,GAAG,GAChF,8BAAC,UAAK,GAAE,wDAAuD,QAAO,gBAAe,aAAY,KAAI,gBAAe,SAAQ,GAC9H,GAEJ;AAAA,MACA,qBAAC,SAAI,WAAW,EAAE,KAAK,GACrB;AAAA,6BAAC,OAAE,WAAW,EAAE,MAAM,GACnB;AAAA,eAAK;AAAA,UACN,qBAAC,UAAK,WAAW,EAAE,MAAM,GAAG;AAAA;AAAA,YAAI,OAAO,MAAM;AAAA,aAAE;AAAA,WACjD;AAAA,QACC,KAAK,eAAe,oBAAC,OAAE,WAAW,EAAE,YAAY,GAAI,eAAK,aAAY;AAAA,QACrE,KAAK,YAAY,WAAW,aAAa,WAAW,YAAY,oBAAC,SAAI,WAAW,EAAE,QAAQ,GAAI,eAAK,SAAQ;AAAA,SAC9G;AAAA,SAlBO,CAmBT;AAAA,EAEJ,CAAC,GACH;AAEJ;","names":[]}
package/dist/tabs.d.ts CHANGED
@@ -71,7 +71,7 @@ type TabsRootProps = React.ComponentProps<typeof Tabs$1.Root> & {
71
71
  };
72
72
  /** `value`/`defaultValue` + `onValueChange`, `orientation` (horizontal by default), `variant` for the list. */
73
73
  declare function TabsRoot({ variant, className, ...props }: TabsRootProps): React.JSX.Element;
74
- /** The tabs. Name it (`aria-label`) when no heading says what it switches. */
74
+ /** The tabs. Name it (`aria-label`) when no heading says what it switches. One light glides to the active tab. */
75
75
  declare function TabsList({ className, ...props }: React.ComponentProps<typeof Tabs$1.List>): React.JSX.Element;
76
76
  declare function TabsTrigger({ className, ...props }: React.ComponentProps<typeof Tabs$1.Trigger>): React.JSX.Element;
77
77
  declare function TabsContent({ className, ...props }: React.ComponentProps<typeof Tabs$1.Content>): React.JSX.Element;