@craftzbay/ui 0.9.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 (208) hide show
  1. package/README.md +82 -10
  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 +71 -0
  5. package/dist-lib/components/ui/Accordion.js.map +1 -0
  6. package/dist-lib/components/ui/Alert.d.ts +17 -1
  7. package/dist-lib/components/ui/Alert.js +79 -0
  8. package/dist-lib/components/ui/Alert.js.map +1 -0
  9. package/dist-lib/components/ui/Avatar.d.ts +3 -3
  10. package/dist-lib/components/ui/Avatar.js +94 -0
  11. package/dist-lib/components/ui/Avatar.js.map +1 -0
  12. package/dist-lib/components/ui/Badge.d.ts +4 -2
  13. package/dist-lib/components/ui/Badge.js +76 -0
  14. package/dist-lib/components/ui/Badge.js.map +1 -0
  15. package/dist-lib/components/ui/Breadcrumbs.d.ts +2 -0
  16. package/dist-lib/components/ui/Breadcrumbs.js +52 -0
  17. package/dist-lib/components/ui/Breadcrumbs.js.map +1 -0
  18. package/dist-lib/components/ui/Button.d.ts +6 -4
  19. package/dist-lib/components/ui/Button.js +131 -0
  20. package/dist-lib/components/ui/Button.js.map +1 -0
  21. package/dist-lib/components/ui/Calendar.d.ts +7 -1
  22. package/dist-lib/components/ui/Calendar.js +139 -0
  23. package/dist-lib/components/ui/Calendar.js.map +1 -0
  24. package/dist-lib/components/ui/Card.d.ts +3 -1
  25. package/dist-lib/components/ui/Card.js +97 -0
  26. package/dist-lib/components/ui/Card.js.map +1 -0
  27. package/dist-lib/components/ui/Carousel.d.ts +11 -7
  28. package/dist-lib/components/ui/Carousel.js +174 -0
  29. package/dist-lib/components/ui/Carousel.js.map +1 -0
  30. package/dist-lib/components/ui/Chart.d.ts +68 -7
  31. package/dist-lib/components/ui/Chart.js +487 -0
  32. package/dist-lib/components/ui/Chart.js.map +1 -0
  33. package/dist-lib/components/ui/Checkbox.js +70 -0
  34. package/dist-lib/components/ui/Checkbox.js.map +1 -0
  35. package/dist-lib/components/ui/Combobox.d.ts +9 -0
  36. package/dist-lib/components/ui/Combobox.js +195 -0
  37. package/dist-lib/components/ui/Combobox.js.map +1 -0
  38. package/dist-lib/components/ui/CommandPalette.d.ts +9 -6
  39. package/dist-lib/components/ui/CommandPalette.js +179 -0
  40. package/dist-lib/components/ui/CommandPalette.js.map +1 -0
  41. package/dist-lib/components/ui/ContextMenu.d.ts +7 -2
  42. package/dist-lib/components/ui/ContextMenu.js +165 -0
  43. package/dist-lib/components/ui/ContextMenu.js.map +1 -0
  44. package/dist-lib/components/ui/DataGrid.d.ts +17 -4
  45. package/dist-lib/components/ui/DataGrid.js +99 -0
  46. package/dist-lib/components/ui/DataGrid.js.map +1 -0
  47. package/dist-lib/components/ui/DatePicker.d.ts +16 -13
  48. package/dist-lib/components/ui/DatePicker.js +193 -0
  49. package/dist-lib/components/ui/DatePicker.js.map +1 -0
  50. package/dist-lib/components/ui/DesignSystemProvider.d.ts +102 -41
  51. package/dist-lib/components/ui/DesignSystemProvider.js +135 -0
  52. package/dist-lib/components/ui/DesignSystemProvider.js.map +1 -0
  53. package/dist-lib/components/ui/Dialog.d.ts +19 -4
  54. package/dist-lib/components/ui/Dialog.js +165 -0
  55. package/dist-lib/components/ui/Dialog.js.map +1 -0
  56. package/dist-lib/components/ui/Drawer.d.ts +23 -2
  57. package/dist-lib/components/ui/Drawer.js +132 -0
  58. package/dist-lib/components/ui/Drawer.js.map +1 -0
  59. package/dist-lib/components/ui/DropdownMenu.js +169 -0
  60. package/dist-lib/components/ui/DropdownMenu.js.map +1 -0
  61. package/dist-lib/components/ui/EmptyState.d.ts +2 -0
  62. package/dist-lib/components/ui/EmptyState.js +46 -0
  63. package/dist-lib/components/ui/EmptyState.js.map +1 -0
  64. package/dist-lib/components/ui/ErrorState.d.ts +13 -2
  65. package/dist-lib/components/ui/ErrorState.js +69 -0
  66. package/dist-lib/components/ui/ErrorState.js.map +1 -0
  67. package/dist-lib/components/ui/FileUpload.d.ts +3 -0
  68. package/dist-lib/components/ui/FileUpload.js +111 -0
  69. package/dist-lib/components/ui/FileUpload.js.map +1 -0
  70. package/dist-lib/components/ui/Form.d.ts +16 -2
  71. package/dist-lib/components/ui/Form.js +131 -0
  72. package/dist-lib/components/ui/Form.js.map +1 -0
  73. package/dist-lib/components/ui/Icon.d.ts +1 -1
  74. package/dist-lib/components/ui/Icon.js +32 -0
  75. package/dist-lib/components/ui/Icon.js.map +1 -0
  76. package/dist-lib/components/ui/IconButton.d.ts +3 -3
  77. package/dist-lib/components/ui/IconButton.js +64 -0
  78. package/dist-lib/components/ui/IconButton.js.map +1 -0
  79. package/dist-lib/components/ui/Input.d.ts +9 -4
  80. package/dist-lib/components/ui/Input.js +149 -0
  81. package/dist-lib/components/ui/Input.js.map +1 -0
  82. package/dist-lib/components/ui/Kbd.js +24 -0
  83. package/dist-lib/components/ui/Kbd.js.map +1 -0
  84. package/dist-lib/components/ui/MultiSelect.d.ts +3 -1
  85. package/dist-lib/components/ui/MultiSelect.js +210 -0
  86. package/dist-lib/components/ui/MultiSelect.js.map +1 -0
  87. package/dist-lib/components/ui/Pagination.d.ts +23 -0
  88. package/dist-lib/components/ui/Pagination.js +153 -0
  89. package/dist-lib/components/ui/Pagination.js.map +1 -0
  90. package/dist-lib/components/ui/Popover.js +35 -0
  91. package/dist-lib/components/ui/Popover.js.map +1 -0
  92. package/dist-lib/components/ui/Progress.d.ts +3 -3
  93. package/dist-lib/components/ui/Progress.js +100 -0
  94. package/dist-lib/components/ui/Progress.js.map +1 -0
  95. package/dist-lib/components/ui/RadioGroup.d.ts +1 -1
  96. package/dist-lib/components/ui/RadioGroup.js +81 -0
  97. package/dist-lib/components/ui/RadioGroup.js.map +1 -0
  98. package/dist-lib/components/ui/RelativeTime.d.ts +19 -0
  99. package/dist-lib/components/ui/RelativeTime.js +31 -0
  100. package/dist-lib/components/ui/RelativeTime.js.map +1 -0
  101. package/dist-lib/components/ui/ScrollArea.d.ts +9 -1
  102. package/dist-lib/components/ui/ScrollArea.js +60 -0
  103. package/dist-lib/components/ui/ScrollArea.js.map +1 -0
  104. package/dist-lib/components/ui/Select.d.ts +6 -1
  105. package/dist-lib/components/ui/Select.js +139 -0
  106. package/dist-lib/components/ui/Select.js.map +1 -0
  107. package/dist-lib/components/ui/Separator.js +26 -0
  108. package/dist-lib/components/ui/Separator.js.map +1 -0
  109. package/dist-lib/components/ui/Sheet.d.ts +10 -1
  110. package/dist-lib/components/ui/Sheet.js +136 -0
  111. package/dist-lib/components/ui/Sheet.js.map +1 -0
  112. package/dist-lib/components/ui/Sidebar.d.ts +29 -14
  113. package/dist-lib/components/ui/Sidebar.js +212 -0
  114. package/dist-lib/components/ui/Sidebar.js.map +1 -0
  115. package/dist-lib/components/ui/Skeleton.d.ts +13 -2
  116. package/dist-lib/components/ui/Skeleton.js +29 -0
  117. package/dist-lib/components/ui/Skeleton.js.map +1 -0
  118. package/dist-lib/components/ui/Slider.js +64 -0
  119. package/dist-lib/components/ui/Slider.js.map +1 -0
  120. package/dist-lib/components/ui/Snackbar.d.ts +1 -1
  121. package/dist-lib/components/ui/Snackbar.js +57 -0
  122. package/dist-lib/components/ui/Snackbar.js.map +1 -0
  123. package/dist-lib/components/ui/Spinner.js +54 -0
  124. package/dist-lib/components/ui/Spinner.js.map +1 -0
  125. package/dist-lib/components/ui/Stepper.d.ts +6 -0
  126. package/dist-lib/components/ui/Stepper.js +111 -0
  127. package/dist-lib/components/ui/Stepper.js.map +1 -0
  128. package/dist-lib/components/ui/Switch.js +80 -0
  129. package/dist-lib/components/ui/Switch.js.map +1 -0
  130. package/dist-lib/components/ui/Table.d.ts +41 -5
  131. package/dist-lib/components/ui/Table.js +179 -0
  132. package/dist-lib/components/ui/Table.js.map +1 -0
  133. package/dist-lib/components/ui/Tabs.d.ts +1 -1
  134. package/dist-lib/components/ui/Tabs.js +91 -0
  135. package/dist-lib/components/ui/Tabs.js.map +1 -0
  136. package/dist-lib/components/ui/TagInput.d.ts +17 -2
  137. package/dist-lib/components/ui/TagInput.js +111 -0
  138. package/dist-lib/components/ui/TagInput.js.map +1 -0
  139. package/dist-lib/components/ui/Textarea.js +88 -0
  140. package/dist-lib/components/ui/Textarea.js.map +1 -0
  141. package/dist-lib/components/ui/Timeline.d.ts +16 -6
  142. package/dist-lib/components/ui/Timeline.js +56 -0
  143. package/dist-lib/components/ui/Timeline.js.map +1 -0
  144. package/dist-lib/components/ui/Toast.d.ts +1 -1
  145. package/dist-lib/components/ui/Toast.js +158 -0
  146. package/dist-lib/components/ui/Toast.js.map +1 -0
  147. package/dist-lib/components/ui/Tooltip.d.ts +4 -1
  148. package/dist-lib/components/ui/Tooltip.js +60 -0
  149. package/dist-lib/components/ui/Tooltip.js.map +1 -0
  150. package/dist-lib/components/ui/TopNav.d.ts +7 -3
  151. package/dist-lib/components/ui/TopNav.js +62 -0
  152. package/dist-lib/components/ui/TopNav.js.map +1 -0
  153. package/dist-lib/components/ui/Tree.d.ts +34 -7
  154. package/dist-lib/components/ui/Tree.js +170 -0
  155. package/dist-lib/components/ui/Tree.js.map +1 -0
  156. package/dist-lib/hooks/use-debounce.d.ts +19 -0
  157. package/dist-lib/hooks/use-debounce.js +36 -0
  158. package/dist-lib/hooks/use-debounce.js.map +1 -0
  159. package/dist-lib/hooks/use-delayed-loading.d.ts +21 -0
  160. package/dist-lib/hooks/use-delayed-loading.js +20 -0
  161. package/dist-lib/hooks/use-delayed-loading.js.map +1 -0
  162. package/dist-lib/hooks/use-field-ids.d.ts +30 -0
  163. package/dist-lib/hooks/use-field-ids.js +18 -0
  164. package/dist-lib/hooks/use-field-ids.js.map +1 -0
  165. package/dist-lib/hooks/use-media-query.d.ts +3 -1
  166. package/dist-lib/hooks/use-media-query.js +22 -0
  167. package/dist-lib/hooks/use-media-query.js.map +1 -0
  168. package/dist-lib/hooks/use-modifier-key.d.ts +13 -0
  169. package/dist-lib/hooks/use-modifier-key.js +19 -0
  170. package/dist-lib/hooks/use-modifier-key.js.map +1 -0
  171. package/dist-lib/hooks/use-strings.d.ts +5 -0
  172. package/dist-lib/hooks/use-strings.js +12 -0
  173. package/dist-lib/hooks/use-strings.js.map +1 -0
  174. package/dist-lib/hooks/use-toast.d.ts +7 -2
  175. package/dist-lib/hooks/use-toast.js +67 -0
  176. package/dist-lib/hooks/use-toast.js.map +1 -0
  177. package/dist-lib/icon.d.ts +8 -0
  178. package/dist-lib/icon.js +7 -0
  179. package/dist-lib/icon.js.map +1 -0
  180. package/dist-lib/icons/index.d.ts +80 -88
  181. package/dist-lib/icons/index.js +163 -0
  182. package/dist-lib/icons/index.js.map +1 -0
  183. package/dist-lib/illustrations/index.d.ts +1 -0
  184. package/dist-lib/illustrations/index.js +114 -0
  185. package/dist-lib/illustrations/index.js.map +1 -0
  186. package/dist-lib/index.d.ts +68 -59
  187. package/dist-lib/index.js +288 -4530
  188. package/dist-lib/index.js.map +1 -1
  189. package/dist-lib/lib/format.d.ts +65 -0
  190. package/dist-lib/lib/format.js +95 -0
  191. package/dist-lib/lib/format.js.map +1 -0
  192. package/dist-lib/lib/return-focus.d.ts +11 -0
  193. package/dist-lib/lib/return-focus.js +12 -0
  194. package/dist-lib/lib/return-focus.js.map +1 -0
  195. package/dist-lib/lib/strings.d.ts +190 -0
  196. package/dist-lib/lib/strings.js +141 -0
  197. package/dist-lib/lib/strings.js.map +1 -0
  198. package/dist-lib/lib/strings.mn.d.ts +3 -0
  199. package/dist-lib/lib/strings.mn.js +115 -0
  200. package/dist-lib/lib/strings.mn.js.map +1 -0
  201. package/dist-lib/lib/utils.d.ts +0 -1
  202. package/dist-lib/lib/utils.js +10 -0
  203. package/dist-lib/lib/utils.js.map +1 -0
  204. package/dist-lib/styles.css +1 -1
  205. package/dist-lib/theme.css +840 -0
  206. package/package.json +38 -8
  207. package/dist-lib/index.cjs +0 -8
  208. package/dist-lib/index.cjs.map +0 -1
@@ -0,0 +1,174 @@
1
+ "use client";
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;
17
+ }
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(() => {
40
+ if (e)
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);
43
+ };
44
+ }, [e, u, t]), P(() => {
45
+ if (!e) return;
46
+ const r = () => V(e.slideNodes().length);
47
+ return r(), e.on("reInit", r), () => {
48
+ e.off("reInit", r);
49
+ };
50
+ }, [e]), /* @__PURE__ */ c(
51
+ p.Provider,
52
+ {
53
+ value: {
54
+ carouselRef: I,
55
+ api: e,
56
+ canPrev: y,
57
+ canNext: S,
58
+ scrollPrev: () => e == null ? void 0 : e.scrollPrev(),
59
+ scrollNext: () => e == null ? void 0 : e.scrollNext(),
60
+ orientation: o,
61
+ slideCount: k,
62
+ inView: E
63
+ },
64
+ children: /* @__PURE__ */ c(
65
+ "div",
66
+ {
67
+ ref: w,
68
+ className: C("relative isolate", s),
69
+ role: "region",
70
+ "aria-roledescription": "carousel",
71
+ "aria-label": d ?? (i ? void 0 : N.carousel.label),
72
+ "aria-labelledby": i,
73
+ onKeyDown: j,
74
+ ...v,
75
+ children: n
76
+ }
77
+ )
78
+ }
79
+ );
80
+ });
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(
86
+ "div",
87
+ {
88
+ ref: t,
89
+ className: C(
90
+ "flex",
91
+ n === "horizontal" ? "-ml-4" : "-mt-4 flex-col",
92
+ l
93
+ ),
94
+ ...o
95
+ }
96
+ ) });
97
+ }
98
+ );
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(
103
+ "div",
104
+ {
105
+ ref: n,
106
+ role: "group",
107
+ "aria-roledescription": "slide",
108
+ "aria-label": t ?? w,
109
+ "aria-hidden": N || void 0,
110
+ ...N ? J : void 0,
111
+ className: C(
112
+ "min-w-0 shrink-0 grow-0 basis-full",
113
+ d === "horizontal" ? "pl-4" : "pt-4",
114
+ l
115
+ ),
116
+ ...s
117
+ }
118
+ );
119
+ });
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";
167
+ export {
168
+ K as Carousel,
169
+ M as CarouselContent,
170
+ Q as CarouselItem,
171
+ X as CarouselNext,
172
+ W as CarouselPrevious
173
+ };
174
+ //# sourceMappingURL=Carousel.js.map
@@ -0,0 +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 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,25 +2,86 @@ 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
- export interface ChartProps {
16
+ export interface ChartSeries {
17
+ /** Name used in the accessible summary, table header and tooltips. */
18
+ name?: string;
13
19
  data: ChartPoint[];
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;
39
+ export interface ChartProps {
40
+ /** Primary series. Ignored when `series` is provided. */
41
+ data?: ChartPoint[];
42
+ /** Multiple series drawn on the same scale. */
43
+ series?: ChartSeries[];
44
+ /** Per-series colours. Defaults to `--chart-1..6` (categorical; never the accent). */
45
+ colors?: string[];
14
46
  /** Drawing height in px. */
15
47
  height?: number;
16
48
  /** Defaults to fluid 100%. */
17
49
  width?: number | string;
18
- /** Tooltip / label rendered above the chart. */
50
+ /** Visible caption rendered above the chart. Doubles as the accessible name. */
19
51
  caption?: ReactNode;
52
+ /** Accessible name when there is no `caption`. */
53
+ 'aria-label'?: string;
54
+ /** Alias of `aria-label` (SVG `<title>`). */
55
+ title?: string;
20
56
  /** Faint horizontal gridlines. Default true. */
21
57
  grid?: boolean;
58
+ /** Y-axis tick labels + first/last x labels. Default true. */
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>;
22
71
  className?: string;
23
72
  }
24
- export declare function LineChart({ data, height, width, caption, grid, className }: ChartProps): import("react/jsx-runtime").JSX.Element;
73
+ export declare const DEFAULT_CHART_COLORS: string[];
74
+ /** 1234 → "1.2K", 3_400_000 → "3.4M". */
75
+ export declare function abbreviateNumber(n: number): string;
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;
25
86
  export declare function AreaChart(props: ChartProps): import("react/jsx-runtime").JSX.Element;
26
- export declare function BarChart({ data, height, width, caption, grid, 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;