@craftzbay/ui 0.10.0 → 0.11.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 (187) hide show
  1. package/README.md +14 -8
  2. package/dist-lib/__tests__/helpers/color.d.ts +9 -0
  3. package/dist-lib/__tests__/helpers/theme.d.ts +18 -0
  4. package/dist-lib/components/ui/Accordion.js +18 -7
  5. package/dist-lib/components/ui/Accordion.js.map +1 -1
  6. package/dist-lib/components/ui/Alert.d.ts +16 -0
  7. package/dist-lib/components/ui/Alert.js +47 -34
  8. package/dist-lib/components/ui/Alert.js.map +1 -1
  9. package/dist-lib/components/ui/Avatar.d.ts +1 -1
  10. package/dist-lib/components/ui/Avatar.js +45 -47
  11. package/dist-lib/components/ui/Avatar.js.map +1 -1
  12. package/dist-lib/components/ui/Badge.d.ts +3 -1
  13. package/dist-lib/components/ui/Badge.js +24 -15
  14. package/dist-lib/components/ui/Badge.js.map +1 -1
  15. package/dist-lib/components/ui/Breadcrumbs.d.ts +2 -0
  16. package/dist-lib/components/ui/Breadcrumbs.js +46 -28
  17. package/dist-lib/components/ui/Breadcrumbs.js.map +1 -1
  18. package/dist-lib/components/ui/Button.d.ts +5 -3
  19. package/dist-lib/components/ui/Button.js +59 -45
  20. package/dist-lib/components/ui/Button.js.map +1 -1
  21. package/dist-lib/components/ui/Calendar.d.ts +1 -1
  22. package/dist-lib/components/ui/Calendar.js +87 -59
  23. package/dist-lib/components/ui/Calendar.js.map +1 -1
  24. package/dist-lib/components/ui/Card.d.ts +2 -0
  25. package/dist-lib/components/ui/Card.js +48 -67
  26. package/dist-lib/components/ui/Card.js.map +1 -1
  27. package/dist-lib/components/ui/Carousel.d.ts +6 -6
  28. package/dist-lib/components/ui/Carousel.js +133 -102
  29. package/dist-lib/components/ui/Carousel.js.map +1 -1
  30. package/dist-lib/components/ui/Chart.d.ts +49 -10
  31. package/dist-lib/components/ui/Chart.js +415 -181
  32. package/dist-lib/components/ui/Chart.js.map +1 -1
  33. package/dist-lib/components/ui/Checkbox.js +42 -28
  34. package/dist-lib/components/ui/Checkbox.js.map +1 -1
  35. package/dist-lib/components/ui/Combobox.d.ts +2 -0
  36. package/dist-lib/components/ui/Combobox.js +142 -111
  37. package/dist-lib/components/ui/Combobox.js.map +1 -1
  38. package/dist-lib/components/ui/CommandPalette.d.ts +6 -3
  39. package/dist-lib/components/ui/CommandPalette.js +92 -87
  40. package/dist-lib/components/ui/CommandPalette.js.map +1 -1
  41. package/dist-lib/components/ui/ContextMenu.d.ts +7 -2
  42. package/dist-lib/components/ui/ContextMenu.js +77 -62
  43. package/dist-lib/components/ui/ContextMenu.js.map +1 -1
  44. package/dist-lib/components/ui/DataGrid.d.ts +17 -4
  45. package/dist-lib/components/ui/DataGrid.js +65 -50
  46. package/dist-lib/components/ui/DataGrid.js.map +1 -1
  47. package/dist-lib/components/ui/DatePicker.js +118 -99
  48. package/dist-lib/components/ui/DatePicker.js.map +1 -1
  49. package/dist-lib/components/ui/DesignSystemProvider.d.ts +94 -40
  50. package/dist-lib/components/ui/DesignSystemProvider.js +111 -55
  51. package/dist-lib/components/ui/DesignSystemProvider.js.map +1 -1
  52. package/dist-lib/components/ui/Dialog.d.ts +18 -3
  53. package/dist-lib/components/ui/Dialog.js +105 -80
  54. package/dist-lib/components/ui/Dialog.js.map +1 -1
  55. package/dist-lib/components/ui/Drawer.d.ts +17 -2
  56. package/dist-lib/components/ui/Drawer.js +89 -55
  57. package/dist-lib/components/ui/Drawer.js.map +1 -1
  58. package/dist-lib/components/ui/DropdownMenu.js +14 -9
  59. package/dist-lib/components/ui/DropdownMenu.js.map +1 -1
  60. package/dist-lib/components/ui/EmptyState.d.ts +2 -0
  61. package/dist-lib/components/ui/EmptyState.js +30 -16
  62. package/dist-lib/components/ui/EmptyState.js.map +1 -1
  63. package/dist-lib/components/ui/ErrorState.d.ts +13 -2
  64. package/dist-lib/components/ui/ErrorState.js +44 -23
  65. package/dist-lib/components/ui/ErrorState.js.map +1 -1
  66. package/dist-lib/components/ui/FileUpload.js +59 -56
  67. package/dist-lib/components/ui/FileUpload.js.map +1 -1
  68. package/dist-lib/components/ui/Form.d.ts +15 -2
  69. package/dist-lib/components/ui/Form.js +97 -71
  70. package/dist-lib/components/ui/Form.js.map +1 -1
  71. package/dist-lib/components/ui/Icon.d.ts +1 -1
  72. package/dist-lib/components/ui/Icon.js +20 -14
  73. package/dist-lib/components/ui/Icon.js.map +1 -1
  74. package/dist-lib/components/ui/IconButton.d.ts +2 -2
  75. package/dist-lib/components/ui/IconButton.js +28 -20
  76. package/dist-lib/components/ui/IconButton.js.map +1 -1
  77. package/dist-lib/components/ui/Input.d.ts +3 -1
  78. package/dist-lib/components/ui/Input.js +92 -78
  79. package/dist-lib/components/ui/Input.js.map +1 -1
  80. package/dist-lib/components/ui/Kbd.js +1 -1
  81. package/dist-lib/components/ui/Kbd.js.map +1 -1
  82. package/dist-lib/components/ui/MultiSelect.js +121 -107
  83. package/dist-lib/components/ui/MultiSelect.js.map +1 -1
  84. package/dist-lib/components/ui/Pagination.js +67 -62
  85. package/dist-lib/components/ui/Pagination.js.map +1 -1
  86. package/dist-lib/components/ui/Popover.js +14 -14
  87. package/dist-lib/components/ui/Popover.js.map +1 -1
  88. package/dist-lib/components/ui/Progress.d.ts +3 -3
  89. package/dist-lib/components/ui/Progress.js +77 -72
  90. package/dist-lib/components/ui/Progress.js.map +1 -1
  91. package/dist-lib/components/ui/RadioGroup.d.ts +1 -1
  92. package/dist-lib/components/ui/RadioGroup.js +69 -52
  93. package/dist-lib/components/ui/RadioGroup.js.map +1 -1
  94. package/dist-lib/components/ui/RelativeTime.d.ts +19 -0
  95. package/dist-lib/components/ui/RelativeTime.js +31 -0
  96. package/dist-lib/components/ui/RelativeTime.js.map +1 -0
  97. package/dist-lib/components/ui/ScrollArea.d.ts +9 -1
  98. package/dist-lib/components/ui/ScrollArea.js +43 -27
  99. package/dist-lib/components/ui/ScrollArea.js.map +1 -1
  100. package/dist-lib/components/ui/Select.d.ts +6 -1
  101. package/dist-lib/components/ui/Select.js +79 -71
  102. package/dist-lib/components/ui/Select.js.map +1 -1
  103. package/dist-lib/components/ui/Separator.js +1 -1
  104. package/dist-lib/components/ui/Separator.js.map +1 -1
  105. package/dist-lib/components/ui/Sheet.d.ts +9 -0
  106. package/dist-lib/components/ui/Sheet.js +69 -46
  107. package/dist-lib/components/ui/Sheet.js.map +1 -1
  108. package/dist-lib/components/ui/Sidebar.d.ts +12 -9
  109. package/dist-lib/components/ui/Sidebar.js +152 -109
  110. package/dist-lib/components/ui/Sidebar.js.map +1 -1
  111. package/dist-lib/components/ui/Skeleton.d.ts +13 -2
  112. package/dist-lib/components/ui/Skeleton.js +15 -14
  113. package/dist-lib/components/ui/Skeleton.js.map +1 -1
  114. package/dist-lib/components/ui/Slider.js +41 -29
  115. package/dist-lib/components/ui/Slider.js.map +1 -1
  116. package/dist-lib/components/ui/Snackbar.js +23 -22
  117. package/dist-lib/components/ui/Snackbar.js.map +1 -1
  118. package/dist-lib/components/ui/Spinner.js +18 -6
  119. package/dist-lib/components/ui/Spinner.js.map +1 -1
  120. package/dist-lib/components/ui/Stepper.d.ts +6 -0
  121. package/dist-lib/components/ui/Stepper.js +71 -48
  122. package/dist-lib/components/ui/Stepper.js.map +1 -1
  123. package/dist-lib/components/ui/Switch.js +46 -43
  124. package/dist-lib/components/ui/Switch.js.map +1 -1
  125. package/dist-lib/components/ui/Table.d.ts +33 -5
  126. package/dist-lib/components/ui/Table.js +141 -119
  127. package/dist-lib/components/ui/Table.js.map +1 -1
  128. package/dist-lib/components/ui/Tabs.js +50 -48
  129. package/dist-lib/components/ui/Tabs.js.map +1 -1
  130. package/dist-lib/components/ui/TagInput.js +45 -45
  131. package/dist-lib/components/ui/TagInput.js.map +1 -1
  132. package/dist-lib/components/ui/Textarea.js +65 -54
  133. package/dist-lib/components/ui/Textarea.js.map +1 -1
  134. package/dist-lib/components/ui/Timeline.js +39 -35
  135. package/dist-lib/components/ui/Timeline.js.map +1 -1
  136. package/dist-lib/components/ui/Toast.js +44 -57
  137. package/dist-lib/components/ui/Toast.js.map +1 -1
  138. package/dist-lib/components/ui/Tooltip.d.ts +4 -1
  139. package/dist-lib/components/ui/Tooltip.js +24 -22
  140. package/dist-lib/components/ui/Tooltip.js.map +1 -1
  141. package/dist-lib/components/ui/TopNav.d.ts +7 -3
  142. package/dist-lib/components/ui/TopNav.js +35 -25
  143. package/dist-lib/components/ui/TopNav.js.map +1 -1
  144. package/dist-lib/components/ui/Tree.d.ts +15 -10
  145. package/dist-lib/components/ui/Tree.js +82 -79
  146. package/dist-lib/components/ui/Tree.js.map +1 -1
  147. package/dist-lib/hooks/use-debounce.d.ts +19 -0
  148. package/dist-lib/hooks/use-debounce.js +36 -0
  149. package/dist-lib/hooks/use-debounce.js.map +1 -0
  150. package/dist-lib/hooks/use-delayed-loading.d.ts +21 -0
  151. package/dist-lib/hooks/use-delayed-loading.js +20 -0
  152. package/dist-lib/hooks/use-delayed-loading.js.map +1 -0
  153. package/dist-lib/hooks/use-field-ids.d.ts +2 -1
  154. package/dist-lib/hooks/use-field-ids.js +9 -9
  155. package/dist-lib/hooks/use-field-ids.js.map +1 -1
  156. package/dist-lib/hooks/use-media-query.d.ts +3 -1
  157. package/dist-lib/hooks/use-media-query.js +16 -12
  158. package/dist-lib/hooks/use-media-query.js.map +1 -1
  159. package/dist-lib/hooks/use-modifier-key.d.ts +13 -0
  160. package/dist-lib/hooks/use-modifier-key.js +19 -0
  161. package/dist-lib/hooks/use-modifier-key.js.map +1 -0
  162. package/dist-lib/hooks/use-toast.d.ts +7 -2
  163. package/dist-lib/hooks/use-toast.js +61 -30
  164. package/dist-lib/hooks/use-toast.js.map +1 -1
  165. package/dist-lib/icons/index.d.ts +9 -0
  166. package/dist-lib/icons/index.js +148 -130
  167. package/dist-lib/icons/index.js.map +1 -1
  168. package/dist-lib/illustrations/index.d.ts +1 -0
  169. package/dist-lib/illustrations/index.js +15 -6
  170. package/dist-lib/illustrations/index.js.map +1 -1
  171. package/dist-lib/index.d.ts +6 -0
  172. package/dist-lib/index.js +280 -260
  173. package/dist-lib/index.js.map +1 -1
  174. package/dist-lib/lib/format.d.ts +65 -0
  175. package/dist-lib/lib/format.js +95 -0
  176. package/dist-lib/lib/format.js.map +1 -0
  177. package/dist-lib/lib/return-focus.d.ts +11 -0
  178. package/dist-lib/lib/return-focus.js +12 -0
  179. package/dist-lib/lib/return-focus.js.map +1 -0
  180. package/dist-lib/lib/strings.d.ts +62 -1
  181. package/dist-lib/lib/strings.js +75 -19
  182. package/dist-lib/lib/strings.js.map +1 -1
  183. package/dist-lib/lib/strings.mn.js +50 -5
  184. package/dist-lib/lib/strings.mn.js.map +1 -1
  185. package/dist-lib/styles.css +1 -1
  186. package/dist-lib/theme.css +141 -78
  187. package/package.json +10 -3
@@ -1,143 +1,174 @@
1
1
  "use client";
2
- import { jsx as a } from "react/jsx-runtime";
3
- import { forwardRef as b, useState as x, useCallback as k, useEffect as N, createContext as R, useContext as E } from "react";
4
- import L from "embla-carousel-react";
5
- import { ChevronRight as j, ChevronLeft as B } from "../../icons/index.js";
6
- import { cn as f } from "../../lib/utils.js";
7
- import { useStrings as d } from "../../hooks/use-strings.js";
8
- import { formatString as q } from "../../lib/strings.js";
9
- import { IconButton as h } from "./IconButton.js";
10
- const g = R(null);
11
- function C() {
12
- const r = E(g);
13
- if (!r) throw new Error("Carousel components must be used inside <Carousel>");
14
- return r;
2
+ import { jsx as c } from "react/jsx-runtime";
3
+ import { forwardRef as m, useState as x, useCallback as O, useEffect as P, createContext as T, useContext as U, version as _ } from "react";
4
+ import q from "embla-carousel-react";
5
+ import { ChevronRight as F, ChevronLeft as G } from "../../icons/index.js";
6
+ import { cn as C } from "../../lib/utils.js";
7
+ import { useStrings as b } from "../../hooks/use-strings.js";
8
+ import { formatString as H } from "../../lib/strings.js";
9
+ import { IconButton as g } from "./IconButton.js";
10
+ const J = {
11
+ inert: Number(_.split(".")[0]) >= 19 ? !0 : ""
12
+ }, p = T(null);
13
+ function h() {
14
+ const f = U(p);
15
+ if (!f) throw new Error("Carousel components must be used inside <Carousel>");
16
+ return f;
15
17
  }
16
- const D = b(function({ opts: n, orientation: t = "horizontal", setApi: o, className: l, children: c, ...u }, m) {
17
- const v = d(), [P, e] = L({
18
- ...n,
19
- axis: t === "horizontal" ? "x" : "y"
20
- }), [z, I] = x(!1), [y, S] = x(!1), [p, w] = x(0), i = k((s) => {
21
- s && (I(s.canScrollPrev()), S(s.canScrollNext()));
22
- }, []);
23
- return N(() => {
18
+ const K = m(function({
19
+ opts: l,
20
+ orientation: o = "horizontal",
21
+ setApi: t,
22
+ className: s,
23
+ children: n,
24
+ onKeyDown: a,
25
+ "aria-label": d,
26
+ "aria-labelledby": i,
27
+ ...v
28
+ }, w) {
29
+ const N = b(), [I, e] = q({
30
+ ...l,
31
+ axis: o === "horizontal" ? "x" : "y"
32
+ }), [y, z] = x(!1), [S, R] = x(!1), [k, V] = x(0), [E, L] = x([]), u = O((r) => {
33
+ r && (z(r.canScrollPrev()), R(r.canScrollNext()), L(r.slidesInView()));
34
+ }, []), j = (r) => {
35
+ if (a == null || a(r), r.defaultPrevented) return;
36
+ const B = o === "horizontal" ? "ArrowLeft" : "ArrowUp", D = o === "horizontal" ? "ArrowRight" : "ArrowDown";
37
+ r.key === B ? (r.preventDefault(), e == null || e.scrollPrev()) : r.key === D && (r.preventDefault(), e == null || e.scrollNext());
38
+ };
39
+ return P(() => {
24
40
  if (e)
25
- return o == null || o(e), i(e), e.on("reInit", i).on("select", i), () => {
26
- e.off("reInit", i).off("select", i);
41
+ return t == null || t(e), u(e), e.on("reInit", u).on("select", u).on("slidesInView", u), () => {
42
+ e.off("reInit", u).off("select", u).off("slidesInView", u);
27
43
  };
28
- }, [e, i, o]), N(() => {
44
+ }, [e, u, t]), P(() => {
29
45
  if (!e) return;
30
- const s = () => w(e.slideNodes().length);
31
- return s(), e.on("reInit", s), () => {
32
- e.off("reInit", s);
46
+ const r = () => V(e.slideNodes().length);
47
+ return r(), e.on("reInit", r), () => {
48
+ e.off("reInit", r);
33
49
  };
34
- }, [e]), /* @__PURE__ */ a(
35
- g.Provider,
50
+ }, [e]), /* @__PURE__ */ c(
51
+ p.Provider,
36
52
  {
37
53
  value: {
38
- carouselRef: P,
54
+ carouselRef: I,
39
55
  api: e,
40
- canPrev: z,
41
- canNext: y,
56
+ canPrev: y,
57
+ canNext: S,
42
58
  scrollPrev: () => e == null ? void 0 : e.scrollPrev(),
43
59
  scrollNext: () => e == null ? void 0 : e.scrollNext(),
44
- orientation: t,
45
- slideCount: p
60
+ orientation: o,
61
+ slideCount: k,
62
+ inView: E
46
63
  },
47
- children: /* @__PURE__ */ a(
64
+ children: /* @__PURE__ */ c(
48
65
  "div",
49
66
  {
50
- ref: m,
51
- className: f("relative", l),
67
+ ref: w,
68
+ className: C("relative isolate", s),
52
69
  role: "region",
53
70
  "aria-roledescription": "carousel",
54
- "aria-label": u["aria-label"] ?? (u["aria-labelledby"] ? void 0 : v.carousel.label),
55
- ...u,
56
- children: c
71
+ "aria-label": d ?? (i ? void 0 : N.carousel.label),
72
+ "aria-labelledby": i,
73
+ onKeyDown: j,
74
+ ...v,
75
+ children: n
57
76
  }
58
77
  )
59
78
  }
60
79
  );
61
80
  });
62
- D.displayName = "Carousel";
63
- const F = b(
64
- function({ className: n, ...t }, o) {
65
- const { carouselRef: l, orientation: c } = C();
66
- return /* @__PURE__ */ a("div", { ref: l, className: "overflow-hidden", children: /* @__PURE__ */ a(
81
+ K.displayName = "Carousel";
82
+ const M = m(
83
+ function({ className: l, ...o }, t) {
84
+ const { carouselRef: s, orientation: n } = h();
85
+ return /* @__PURE__ */ c("div", { ref: s, className: "overflow-hidden", children: /* @__PURE__ */ c(
67
86
  "div",
68
87
  {
69
- ref: o,
70
- className: f(
88
+ ref: t,
89
+ className: C(
71
90
  "flex",
72
- c === "horizontal" ? "-ml-4" : "-mt-4 flex-col",
73
- n
91
+ n === "horizontal" ? "-ml-4" : "-mt-4 flex-col",
92
+ l
74
93
  ),
75
- ...t
94
+ ...o
76
95
  }
77
96
  ) });
78
97
  }
79
98
  );
80
- F.displayName = "CarouselContent";
81
- const G = b(function({ className: n, index: t, ...o }, l) {
82
- const c = d(), { orientation: u, slideCount: m } = C(), v = t !== void 0 && m > 0 ? q(c.carousel.slide, { index: t + 1, count: m }) : void 0;
83
- return /* @__PURE__ */ a(
99
+ M.displayName = "CarouselContent";
100
+ const Q = m(function({ className: l, index: o, "aria-label": t, ...s }, n) {
101
+ const a = b(), { orientation: d, slideCount: i, inView: v } = h(), w = o !== void 0 && i > 0 ? H(a.carousel.slide, { index: o + 1, count: i }) : void 0, N = o !== void 0 && v.length > 0 && !v.includes(o);
102
+ return /* @__PURE__ */ c(
84
103
  "div",
85
104
  {
86
- ref: l,
105
+ ref: n,
87
106
  role: "group",
88
107
  "aria-roledescription": "slide",
89
- "aria-label": o["aria-label"] ?? v,
90
- className: f(
108
+ "aria-label": t ?? w,
109
+ "aria-hidden": N || void 0,
110
+ ...N ? J : void 0,
111
+ className: C(
91
112
  "min-w-0 shrink-0 grow-0 basis-full",
92
- u === "horizontal" ? "pl-4" : "pt-4",
93
- n
113
+ d === "horizontal" ? "pl-4" : "pt-4",
114
+ l
94
115
  ),
95
- ...o
116
+ ...s
96
117
  }
97
118
  );
98
119
  });
99
- G.displayName = "CarouselItem";
100
- function V({ className: r }) {
101
- const { canPrev: n, scrollPrev: t, orientation: o } = C(), l = d();
102
- return /* @__PURE__ */ a(
103
- h,
104
- {
105
- "aria-label": l.carousel.previous,
106
- variant: "outline",
107
- disabled: !n,
108
- onClick: t,
109
- icon: /* @__PURE__ */ a(B, {}),
110
- className: f(
111
- "absolute z-10",
112
- o === "horizontal" ? "top-1/2 -left-12 -translate-y-1/2" : "-top-12 left-1/2 -translate-x-1/2 rotate-90",
113
- r
114
- )
115
- }
116
- );
117
- }
118
- function W({ className: r }) {
119
- const { canNext: n, scrollNext: t, orientation: o } = C(), l = d();
120
- return /* @__PURE__ */ a(
121
- h,
122
- {
123
- "aria-label": l.carousel.next,
124
- variant: "outline",
125
- disabled: !n,
126
- onClick: t,
127
- icon: /* @__PURE__ */ a(j, {}),
128
- className: f(
129
- "absolute z-10",
130
- o === "horizontal" ? "top-1/2 -right-12 -translate-y-1/2" : "-bottom-12 left-1/2 -translate-x-1/2 rotate-90",
131
- r
132
- )
133
- }
134
- );
135
- }
120
+ Q.displayName = "CarouselItem";
121
+ const W = m(
122
+ function({ className: l, "aria-label": o, ...t }, s) {
123
+ const { canPrev: n, scrollPrev: a, orientation: d } = h(), i = b();
124
+ return /* @__PURE__ */ c(
125
+ g,
126
+ {
127
+ ref: s,
128
+ "aria-label": o ?? i.carousel.previous,
129
+ variant: "outline",
130
+ disabled: !n,
131
+ onClick: a,
132
+ icon: /* @__PURE__ */ c(G, {}),
133
+ className: C(
134
+ "absolute z-10",
135
+ d === "horizontal" ? "top-1/2 -left-12 -translate-y-1/2" : "-top-12 left-1/2 -translate-x-1/2 rotate-90",
136
+ l
137
+ ),
138
+ ...t
139
+ }
140
+ );
141
+ }
142
+ );
143
+ W.displayName = "CarouselPrevious";
144
+ const X = m(
145
+ function({ className: l, "aria-label": o, ...t }, s) {
146
+ const { canNext: n, scrollNext: a, orientation: d } = h(), i = b();
147
+ return /* @__PURE__ */ c(
148
+ g,
149
+ {
150
+ ref: s,
151
+ "aria-label": o ?? i.carousel.next,
152
+ variant: "outline",
153
+ disabled: !n,
154
+ onClick: a,
155
+ icon: /* @__PURE__ */ c(F, {}),
156
+ className: C(
157
+ "absolute z-10",
158
+ d === "horizontal" ? "top-1/2 -right-12 -translate-y-1/2" : "-bottom-12 left-1/2 -translate-x-1/2 rotate-90",
159
+ l
160
+ ),
161
+ ...t
162
+ }
163
+ );
164
+ }
165
+ );
166
+ X.displayName = "CarouselNext";
136
167
  export {
137
- D as Carousel,
138
- F as CarouselContent,
139
- G as CarouselItem,
140
- W as CarouselNext,
141
- V as CarouselPrevious
168
+ K as Carousel,
169
+ M as CarouselContent,
170
+ Q as CarouselItem,
171
+ X as CarouselNext,
172
+ W as CarouselPrevious
142
173
  };
143
174
  //# sourceMappingURL=Carousel.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Carousel.js","sources":["../../../src/components/ui/Carousel.tsx"],"sourcesContent":["'use client';\n\nimport {\n createContext,\n forwardRef,\n useCallback,\n useContext,\n useEffect,\n useState,\n type HTMLAttributes,\n} from 'react';\nimport useEmblaCarousel, { type UseEmblaCarouselType } from 'embla-carousel-react';\nimport { ChevronLeft, ChevronRight } from '@/icons';\nimport { cn } from '@/lib/utils';\nimport { useStrings } from '@/hooks/use-strings';\nimport { formatString } from '@/lib/strings';\nimport { IconButton } from './IconButton';\n\ntype CarouselApi = UseEmblaCarouselType[1];\ntype CarouselOptions = Parameters<typeof useEmblaCarousel>[0];\n\ninterface CarouselContextValue {\n carouselRef: ReturnType<typeof useEmblaCarousel>[0];\n api: CarouselApi;\n canPrev: boolean;\n canNext: boolean;\n scrollPrev: () => void;\n scrollNext: () => void;\n orientation: 'horizontal' | 'vertical';\n slideCount: number;\n}\n\nconst CarouselContext = createContext<CarouselContextValue | null>(null);\n\nfunction useCarousel() {\n const ctx = useContext(CarouselContext);\n if (!ctx) throw new Error('Carousel components must be used inside <Carousel>');\n return ctx;\n}\n\nexport interface CarouselProps extends HTMLAttributes<HTMLDivElement> {\n opts?: CarouselOptions;\n orientation?: 'horizontal' | 'vertical';\n setApi?: (api: CarouselApi) => void;\n}\n\n/**\n * Embla-backed carousel. Compose with `<CarouselContent>`, `<CarouselItem>`,\n * `<CarouselPrevious>`, and `<CarouselNext>`.\n */\nexport const Carousel = forwardRef<HTMLDivElement, CarouselProps>(function Carousel(\n { opts, orientation = 'horizontal', setApi, className, children, ...props },\n ref,\n) {\n const strings = useStrings();\n const [carouselRef, api] = useEmblaCarousel({\n ...opts,\n axis: orientation === 'horizontal' ? 'x' : 'y',\n });\n const [canPrev, setCanPrev] = useState(false);\n const [canNext, setCanNext] = useState(false);\n const [slideCount, setSlideCount] = useState(0);\n\n const onSelect = useCallback((api: CarouselApi) => {\n if (!api) return;\n setCanPrev(api.canScrollPrev());\n setCanNext(api.canScrollNext());\n }, []);\n\n useEffect(() => {\n if (!api) return;\n setApi?.(api);\n onSelect(api);\n api.on('reInit', onSelect).on('select', onSelect);\n return () => {\n api.off('reInit', onSelect).off('select', onSelect);\n };\n }, [api, onSelect, setApi]);\n\n useEffect(() => {\n if (!api) return;\n const count = () => setSlideCount(api.slideNodes().length);\n count();\n api.on('reInit', count);\n return () => {\n api.off('reInit', count);\n };\n }, [api]);\n\n return (\n <CarouselContext.Provider\n value={{\n carouselRef,\n api,\n canPrev,\n canNext,\n scrollPrev: () => api?.scrollPrev(),\n scrollNext: () => api?.scrollNext(),\n orientation,\n slideCount,\n }}\n >\n <div\n ref={ref}\n className={cn('relative', className)}\n role=\"region\"\n aria-roledescription=\"carousel\"\n aria-label={props['aria-label'] ?? (props['aria-labelledby'] ? undefined : strings.carousel.label)}\n {...props}\n >\n {children}\n </div>\n </CarouselContext.Provider>\n );\n});\nCarousel.displayName = 'Carousel';\n\nexport const CarouselContent = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(\n function CarouselContent({ className, ...props }, ref) {\n const { carouselRef, orientation } = useCarousel();\n return (\n <div ref={carouselRef} className=\"overflow-hidden\">\n <div\n ref={ref}\n className={cn(\n 'flex',\n orientation === 'horizontal' ? '-ml-4' : '-mt-4 flex-col',\n className,\n )}\n {...props}\n />\n </div>\n );\n },\n);\nCarouselContent.displayName = 'CarouselContent';\n\nexport interface CarouselItemProps extends HTMLAttributes<HTMLDivElement> {\n /** 0-based position, used for the default \"{i+1} of {n}\" label. */\n index?: number;\n}\n\nexport const CarouselItem = forwardRef<HTMLDivElement, CarouselItemProps>(function CarouselItem(\n { className, index, ...props },\n ref,\n) {\n const strings = useStrings();\n const { orientation, slideCount } = useCarousel();\n const defaultLabel =\n index !== undefined && slideCount > 0\n ? formatString(strings.carousel.slide, { index: index + 1, count: slideCount })\n : undefined;\n return (\n <div\n ref={ref}\n role=\"group\"\n aria-roledescription=\"slide\"\n aria-label={props['aria-label'] ?? defaultLabel}\n className={cn(\n 'min-w-0 shrink-0 grow-0 basis-full',\n orientation === 'horizontal' ? 'pl-4' : 'pt-4',\n className,\n )}\n {...props}\n />\n );\n});\nCarouselItem.displayName = 'CarouselItem';\n\nexport function CarouselPrevious({ className }: { className?: string }) {\n const { canPrev, scrollPrev, orientation } = useCarousel();\n const strings = useStrings();\n return (\n <IconButton\n aria-label={strings.carousel.previous}\n variant=\"outline\"\n disabled={!canPrev}\n onClick={scrollPrev}\n icon={<ChevronLeft />}\n className={cn(\n 'absolute z-10',\n orientation === 'horizontal'\n ? 'top-1/2 -left-12 -translate-y-1/2'\n : '-top-12 left-1/2 -translate-x-1/2 rotate-90',\n className,\n )}\n />\n );\n}\n\nexport function CarouselNext({ className }: { className?: string }) {\n const { canNext, scrollNext, orientation } = useCarousel();\n const strings = useStrings();\n return (\n <IconButton\n aria-label={strings.carousel.next}\n variant=\"outline\"\n disabled={!canNext}\n onClick={scrollNext}\n icon={<ChevronRight />}\n className={cn(\n 'absolute z-10',\n orientation === 'horizontal'\n ? 'top-1/2 -right-12 -translate-y-1/2'\n : '-bottom-12 left-1/2 -translate-x-1/2 rotate-90',\n className,\n )}\n />\n );\n}\n"],"names":["CarouselContext","createContext","useCarousel","ctx","useContext","Carousel","forwardRef","opts","orientation","setApi","className","children","props","ref","strings","useStrings","carouselRef","api","useEmblaCarousel","canPrev","setCanPrev","useState","canNext","setCanNext","slideCount","setSlideCount","onSelect","useCallback","useEffect","count","jsx","cn","CarouselContent","CarouselItem","index","defaultLabel","formatString","CarouselPrevious","scrollPrev","IconButton","ChevronLeft","CarouselNext","scrollNext","ChevronRight"],"mappings":"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"}
1
+ {"version":3,"file":"Carousel.js","sources":["../../../src/components/ui/Carousel.tsx"],"sourcesContent":["'use client';\n\nimport {\n createContext,\n forwardRef,\n useCallback,\n useContext,\n useEffect,\n useState,\n type HTMLAttributes,\n type ComponentPropsWithoutRef,\n type KeyboardEvent,\n} from 'react';\nimport { version as reactVersion } from 'react';\nimport useEmblaCarousel, { type UseEmblaCarouselType } from 'embla-carousel-react';\nimport { ChevronLeft, ChevronRight } from '@/icons';\nimport { cn } from '@/lib/utils';\nimport { useStrings } from '@/hooks/use-strings';\nimport { formatString } from '@/lib/strings';\nimport { IconButton } from './IconButton';\n\n// `inert` is a boolean attribute. React 19 renders `inert={true}` as `inert=\"\"`;\n// React 18 has no knowledge of it and only forwards a string, so pass `''`\n// there (it would drop `true` with a warning). Typed loosely for both.\nconst INERT_PROPS = {\n inert: Number(reactVersion.split('.')[0]) >= 19 ? true : '',\n} as Record<string, unknown>;\n\ntype CarouselApi = UseEmblaCarouselType[1];\ntype CarouselOptions = Parameters<typeof useEmblaCarousel>[0];\n\ninterface CarouselContextValue {\n carouselRef: ReturnType<typeof useEmblaCarousel>[0];\n api: CarouselApi;\n canPrev: boolean;\n canNext: boolean;\n scrollPrev: () => void;\n scrollNext: () => void;\n orientation: 'horizontal' | 'vertical';\n slideCount: number;\n /** Indices of slides currently in view (others are inert). */\n inView: number[];\n}\n\nconst CarouselContext = createContext<CarouselContextValue | null>(null);\n\nfunction useCarousel() {\n const ctx = useContext(CarouselContext);\n if (!ctx) throw new Error('Carousel components must be used inside <Carousel>');\n return ctx;\n}\n\nexport interface CarouselProps extends HTMLAttributes<HTMLDivElement> {\n opts?: CarouselOptions;\n orientation?: 'horizontal' | 'vertical';\n setApi?: (api: CarouselApi) => void;\n}\n\n/**\n * Embla-backed carousel. Compose with `<CarouselContent>`, `<CarouselItem>`,\n * `<CarouselPrevious>`, and `<CarouselNext>`.\n */\nexport const Carousel = forwardRef<HTMLDivElement, CarouselProps>(function Carousel(\n {\n opts,\n orientation = 'horizontal',\n setApi,\n className,\n children,\n onKeyDown,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledby,\n ...props\n },\n ref,\n) {\n const strings = useStrings();\n const [carouselRef, api] = useEmblaCarousel({\n ...opts,\n axis: orientation === 'horizontal' ? 'x' : 'y',\n });\n const [canPrev, setCanPrev] = useState(false);\n const [canNext, setCanNext] = useState(false);\n const [slideCount, setSlideCount] = useState(0);\n const [inView, setInView] = useState<number[]>([]);\n\n const onSelect = useCallback((api: CarouselApi) => {\n if (!api) return;\n setCanPrev(api.canScrollPrev());\n setCanNext(api.canScrollNext());\n setInView(api.slidesInView());\n }, []);\n\n const handleKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n onKeyDown?.(event);\n if (event.defaultPrevented) return;\n const prevKey = orientation === 'horizontal' ? 'ArrowLeft' : 'ArrowUp';\n const nextKey = orientation === 'horizontal' ? 'ArrowRight' : 'ArrowDown';\n if (event.key === prevKey) {\n event.preventDefault();\n api?.scrollPrev();\n } else if (event.key === nextKey) {\n event.preventDefault();\n api?.scrollNext();\n }\n };\n\n useEffect(() => {\n if (!api) return;\n setApi?.(api);\n onSelect(api);\n api.on('reInit', onSelect).on('select', onSelect).on('slidesInView', onSelect);\n return () => {\n api.off('reInit', onSelect).off('select', onSelect).off('slidesInView', onSelect);\n };\n }, [api, onSelect, setApi]);\n\n useEffect(() => {\n if (!api) return;\n const count = () => setSlideCount(api.slideNodes().length);\n count();\n api.on('reInit', count);\n return () => {\n api.off('reInit', count);\n };\n }, [api]);\n\n return (\n <CarouselContext.Provider\n value={{\n carouselRef,\n api,\n canPrev,\n canNext,\n scrollPrev: () => api?.scrollPrev(),\n scrollNext: () => api?.scrollNext(),\n orientation,\n slideCount,\n inView,\n }}\n >\n {/* Arrow keys act only while focus is inside the region (it is not itself\n focusable); the buttons remain the primary control. */}\n {/* eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions */}\n <div\n ref={ref}\n className={cn('relative isolate', className)}\n role=\"region\"\n aria-roledescription=\"carousel\"\n aria-label={ariaLabel ?? (ariaLabelledby ? undefined : strings.carousel.label)}\n aria-labelledby={ariaLabelledby}\n onKeyDown={handleKeyDown}\n {...props}\n >\n {children}\n </div>\n </CarouselContext.Provider>\n );\n});\nCarousel.displayName = 'Carousel';\n\nexport const CarouselContent = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(\n function CarouselContent({ className, ...props }, ref) {\n const { carouselRef, orientation } = useCarousel();\n return (\n <div ref={carouselRef} className=\"overflow-hidden\">\n <div\n ref={ref}\n className={cn(\n 'flex',\n orientation === 'horizontal' ? '-ml-4' : '-mt-4 flex-col',\n className,\n )}\n {...props}\n />\n </div>\n );\n },\n);\nCarouselContent.displayName = 'CarouselContent';\n\nexport interface CarouselItemProps extends HTMLAttributes<HTMLDivElement> {\n /** 0-based position, used for the default \"{i+1} of {n}\" label. */\n index?: number;\n}\n\nexport const CarouselItem = forwardRef<HTMLDivElement, CarouselItemProps>(function CarouselItem(\n { className, index, 'aria-label': ariaLabel, ...props },\n ref,\n) {\n const strings = useStrings();\n const { orientation, slideCount, inView } = useCarousel();\n const defaultLabel =\n index !== undefined && slideCount > 0\n ? formatString(strings.carousel.slide, { index: index + 1, count: slideCount })\n : undefined;\n // Off-screen slides are inert: not in the tab order, not read by AT. Only\n // possible when `index` is provided (unknown index → always live).\n const offscreen = index !== undefined && inView.length > 0 && !inView.includes(index);\n return (\n <div\n ref={ref}\n role=\"group\"\n aria-roledescription=\"slide\"\n aria-label={ariaLabel ?? defaultLabel}\n aria-hidden={offscreen || undefined}\n {...(offscreen ? INERT_PROPS : undefined)}\n className={cn(\n 'min-w-0 shrink-0 grow-0 basis-full',\n orientation === 'horizontal' ? 'pl-4' : 'pt-4',\n className,\n )}\n {...props}\n />\n );\n});\nCarouselItem.displayName = 'CarouselItem';\n\ntype CarouselButtonProps = Omit<\n ComponentPropsWithoutRef<typeof IconButton>,\n 'icon' | 'aria-label'\n> & { 'aria-label'?: string };\n\nexport const CarouselPrevious = forwardRef<HTMLButtonElement, CarouselButtonProps>(\n function CarouselPrevious({ className, 'aria-label': ariaLabel, ...props }, ref) {\n const { canPrev, scrollPrev, orientation } = useCarousel();\n const strings = useStrings();\n return (\n <IconButton\n ref={ref}\n aria-label={ariaLabel ?? strings.carousel.previous}\n variant=\"outline\"\n disabled={!canPrev}\n onClick={scrollPrev}\n icon={<ChevronLeft />}\n className={cn(\n 'absolute z-10',\n orientation === 'horizontal'\n ? 'top-1/2 -left-12 -translate-y-1/2'\n : '-top-12 left-1/2 -translate-x-1/2 rotate-90',\n className,\n )}\n {...props}\n />\n );\n },\n);\nCarouselPrevious.displayName = 'CarouselPrevious';\n\nexport const CarouselNext = forwardRef<HTMLButtonElement, CarouselButtonProps>(\n function CarouselNext({ className, 'aria-label': ariaLabel, ...props }, ref) {\n const { canNext, scrollNext, orientation } = useCarousel();\n const strings = useStrings();\n return (\n <IconButton\n ref={ref}\n aria-label={ariaLabel ?? strings.carousel.next}\n variant=\"outline\"\n disabled={!canNext}\n onClick={scrollNext}\n icon={<ChevronRight />}\n className={cn(\n 'absolute z-10',\n orientation === 'horizontal'\n ? 'top-1/2 -right-12 -translate-y-1/2'\n : '-bottom-12 left-1/2 -translate-x-1/2 rotate-90',\n className,\n )}\n {...props}\n />\n );\n },\n);\nCarouselNext.displayName = 'CarouselNext';\n"],"names":["INERT_PROPS","reactVersion","CarouselContext","createContext","useCarousel","ctx","useContext","Carousel","forwardRef","opts","orientation","setApi","className","children","onKeyDown","ariaLabel","ariaLabelledby","props","ref","strings","useStrings","carouselRef","api","useEmblaCarousel","canPrev","setCanPrev","useState","canNext","setCanNext","slideCount","setSlideCount","inView","setInView","onSelect","useCallback","handleKeyDown","event","prevKey","nextKey","useEffect","count","jsx","cn","CarouselContent","CarouselItem","index","defaultLabel","formatString","offscreen","CarouselPrevious","scrollPrev","IconButton","ChevronLeft","CarouselNext","scrollNext","ChevronRight"],"mappings":"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"}
@@ -2,27 +2,46 @@ import { ReactNode } from 'react';
2
2
  /**
3
3
  * Tiny, dependency-free chart primitives for inline dashboards — sparklines,
4
4
  * KPI cards, at-a-glance trends. For heavy interactive visualisations reach for
5
- * a charting library. These render as responsive SVG (the line/area stretch to
6
- * the container width; strokes stay crisp via non-scaling-stroke).
5
+ * a charting library. The SVG is drawn in real pixels: a ResizeObserver
6
+ * measures the container width, so points and bars are never distorted.
7
+ *
8
+ * Keyboard: one tab stop per series; ←/→ (Home/End) move between points and
9
+ * the active point is announced via a polite live region.
7
10
  */
8
11
  export interface ChartPoint {
9
12
  x: string | number;
10
- y: number;
13
+ /** `null` breaks the line (a gap) and is skipped in bars/tables. */
14
+ y: number | null;
11
15
  }
12
16
  export interface ChartSeries {
13
- /** Name used in the accessible summary and tooltips. */
17
+ /** Name used in the accessible summary, table header and tooltips. */
14
18
  name?: string;
15
19
  data: ChartPoint[];
16
20
  }
21
+ export type ChartState = 'loading' | 'empty' | 'error';
22
+ /** Text builders for the accessible summary + point labels (i18n). */
23
+ export interface ChartLabels {
24
+ /** `<desc>` sentence per series. */
25
+ summary: (s: {
26
+ name: string;
27
+ count: number;
28
+ min: number;
29
+ max: number;
30
+ lastX: string | number | undefined;
31
+ lastY: number | undefined;
32
+ }) => string;
33
+ /** Label of one data point (tooltip, live region). */
34
+ point: (name: string | undefined, x: string | number, y: number) => string;
35
+ /** Accessible name of a series' tab stop. */
36
+ series: (name: string, count: number) => string;
37
+ }
38
+ export declare const defaultChartLabels: ChartLabels;
17
39
  export interface ChartProps {
18
40
  /** Primary series. Ignored when `series` is provided. */
19
41
  data?: ChartPoint[];
20
42
  /** Multiple series drawn on the same scale. */
21
43
  series?: ChartSeries[];
22
- /**
23
- * Per-series colours. Defaults to the categorical token list below.
24
- * TODO(globals.css): add `--chart-1..6` tokens and switch the defaults.
25
- */
44
+ /** Per-series colours. Defaults to `--chart-1..6` (categorical; never the accent). */
26
45
  colors?: string[];
27
46
  /** Drawing height in px. */
28
47
  height?: number;
@@ -38,11 +57,31 @@ export interface ChartProps {
38
57
  grid?: boolean;
39
58
  /** Y-axis tick labels + first/last x labels. Default true. */
40
59
  showAxis?: boolean;
60
+ /**
61
+ * Render a visually-hidden `<table>` of the data after the SVG so screen
62
+ * readers and copy/paste get the numbers. Default true.
63
+ */
64
+ tableFallback?: boolean;
65
+ /** Show a small "View as table" toggle that reveals the fallback table. */
66
+ showTableToggle?: boolean;
67
+ /** Replace the drawing with a loading skeleton / empty / error message. */
68
+ state?: ChartState;
69
+ /** Override the generated accessible text (English defaults). */
70
+ labels?: Partial<ChartLabels>;
41
71
  className?: string;
42
72
  }
43
73
  export declare const DEFAULT_CHART_COLORS: string[];
44
74
  /** 1234 → "1.2K", 3_400_000 → "3.4M". */
45
75
  export declare function abbreviateNumber(n: number): string;
46
- export declare function LineChart({ data, series, colors, height, width, caption, 'aria-label': ariaLabel, title, grid, showAxis, className, }: ChartProps): import("react/jsx-runtime").JSX.Element;
76
+ /**
77
+ * "Nice" axis: expands [min, max] to multiples of a 1/2/2.5/5 step so ticks
78
+ * read as round numbers (never `754.5`).
79
+ */
80
+ export declare function niceTicks(min: number, max: number, maxTicks?: number): {
81
+ min: number;
82
+ max: number;
83
+ ticks: number[];
84
+ };
85
+ export declare function LineChart({ data, series, colors, height, width, caption, 'aria-label': ariaLabel, title, grid, showAxis, tableFallback, showTableToggle, state, labels: labelsProp, className, }: ChartProps): import("react/jsx-runtime").JSX.Element;
47
86
  export declare function AreaChart(props: ChartProps): import("react/jsx-runtime").JSX.Element;
48
- export declare function BarChart({ data, series, colors, height, width, caption, 'aria-label': ariaLabel, title, grid, showAxis, className, }: ChartProps): import("react/jsx-runtime").JSX.Element;
87
+ export declare function BarChart({ data, series, colors, height, width, caption, 'aria-label': ariaLabel, title, grid, showAxis, tableFallback, showTableToggle, state, labels: labelsProp, className, }: ChartProps): import("react/jsx-runtime").JSX.Element;