@giddaa-housing/ui 0.1.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 (248) hide show
  1. package/README.md +41 -0
  2. package/dist/accordion.d.ts +11 -0
  3. package/dist/accordion.js +124 -0
  4. package/dist/accordion.js.map +1 -0
  5. package/dist/alert.d.ts +18 -0
  6. package/dist/alert.js +152 -0
  7. package/dist/alert.js.map +1 -0
  8. package/dist/avatar.d.ts +14 -0
  9. package/dist/avatar.js +152 -0
  10. package/dist/avatar.js.map +1 -0
  11. package/dist/badge.d.ts +14 -0
  12. package/dist/badge.js +119 -0
  13. package/dist/badge.js.map +1 -0
  14. package/dist/bar-chart.d.ts +136 -0
  15. package/dist/bar-chart.js +302 -0
  16. package/dist/bar-chart.js.map +1 -0
  17. package/dist/base.css +32 -0
  18. package/dist/breadcrumb.d.ts +12 -0
  19. package/dist/breadcrumb.js +161 -0
  20. package/dist/breadcrumb.js.map +1 -0
  21. package/dist/bullet-chart.d.ts +98 -0
  22. package/dist/bullet-chart.js +189 -0
  23. package/dist/bullet-chart.js.map +1 -0
  24. package/dist/button-group.d.ts +18 -0
  25. package/dist/button-group.js +170 -0
  26. package/dist/button-group.js.map +1 -0
  27. package/dist/button.d.ts +19 -0
  28. package/dist/button.js +146 -0
  29. package/dist/button.js.map +1 -0
  30. package/dist/calendar.d.ts +9 -0
  31. package/dist/calendar.js +293 -0
  32. package/dist/calendar.js.map +1 -0
  33. package/dist/card.d.ts +18 -0
  34. package/dist/card.js +186 -0
  35. package/dist/card.js.map +1 -0
  36. package/dist/carousel.d.ts +53 -0
  37. package/dist/carousel.js +396 -0
  38. package/dist/carousel.js.map +1 -0
  39. package/dist/chart.d.ts +122 -0
  40. package/dist/chart.js +494 -0
  41. package/dist/chart.js.map +1 -0
  42. package/dist/checkbox.d.ts +73 -0
  43. package/dist/checkbox.js +87 -0
  44. package/dist/checkbox.js.map +1 -0
  45. package/dist/collapsible.d.ts +8 -0
  46. package/dist/collapsible.js +82 -0
  47. package/dist/collapsible.js.map +1 -0
  48. package/dist/combobox.d.ts +30 -0
  49. package/dist/combobox.js +713 -0
  50. package/dist/combobox.js.map +1 -0
  51. package/dist/date-picker.d.ts +22 -0
  52. package/dist/date-picker.js +528 -0
  53. package/dist/date-picker.js.map +1 -0
  54. package/dist/dialog.d.ts +30 -0
  55. package/dist/dialog.js +339 -0
  56. package/dist/dialog.js.map +1 -0
  57. package/dist/dropdown-menu.d.ts +35 -0
  58. package/dist/dropdown-menu.js +376 -0
  59. package/dist/dropdown-menu.js.map +1 -0
  60. package/dist/dropzone.d.ts +128 -0
  61. package/dist/dropzone.js +490 -0
  62. package/dist/dropzone.js.map +1 -0
  63. package/dist/empty-state.d.ts +17 -0
  64. package/dist/empty-state.js +146 -0
  65. package/dist/empty-state.js.map +1 -0
  66. package/dist/field.d.ts +29 -0
  67. package/dist/field.js +345 -0
  68. package/dist/field.js.map +1 -0
  69. package/dist/files/red-hat-display-latin-300-italic.woff +0 -0
  70. package/dist/files/red-hat-display-latin-300-italic.woff2 +0 -0
  71. package/dist/files/red-hat-display-latin-300-normal.woff +0 -0
  72. package/dist/files/red-hat-display-latin-300-normal.woff2 +0 -0
  73. package/dist/files/red-hat-display-latin-400-italic.woff +0 -0
  74. package/dist/files/red-hat-display-latin-400-italic.woff2 +0 -0
  75. package/dist/files/red-hat-display-latin-400-normal.woff +0 -0
  76. package/dist/files/red-hat-display-latin-400-normal.woff2 +0 -0
  77. package/dist/files/red-hat-display-latin-500-italic.woff +0 -0
  78. package/dist/files/red-hat-display-latin-500-italic.woff2 +0 -0
  79. package/dist/files/red-hat-display-latin-500-normal.woff +0 -0
  80. package/dist/files/red-hat-display-latin-500-normal.woff2 +0 -0
  81. package/dist/files/red-hat-display-latin-600-italic.woff +0 -0
  82. package/dist/files/red-hat-display-latin-600-italic.woff2 +0 -0
  83. package/dist/files/red-hat-display-latin-600-normal.woff +0 -0
  84. package/dist/files/red-hat-display-latin-600-normal.woff2 +0 -0
  85. package/dist/files/red-hat-display-latin-700-italic.woff +0 -0
  86. package/dist/files/red-hat-display-latin-700-italic.woff2 +0 -0
  87. package/dist/files/red-hat-display-latin-700-normal.woff +0 -0
  88. package/dist/files/red-hat-display-latin-700-normal.woff2 +0 -0
  89. package/dist/files/red-hat-display-latin-800-italic.woff +0 -0
  90. package/dist/files/red-hat-display-latin-800-italic.woff2 +0 -0
  91. package/dist/files/red-hat-display-latin-800-normal.woff +0 -0
  92. package/dist/files/red-hat-display-latin-800-normal.woff2 +0 -0
  93. package/dist/files/red-hat-display-latin-900-italic.woff +0 -0
  94. package/dist/files/red-hat-display-latin-900-italic.woff2 +0 -0
  95. package/dist/files/red-hat-display-latin-900-normal.woff +0 -0
  96. package/dist/files/red-hat-display-latin-900-normal.woff2 +0 -0
  97. package/dist/files/red-hat-display-latin-ext-300-italic.woff +0 -0
  98. package/dist/files/red-hat-display-latin-ext-300-italic.woff2 +0 -0
  99. package/dist/files/red-hat-display-latin-ext-300-normal.woff +0 -0
  100. package/dist/files/red-hat-display-latin-ext-300-normal.woff2 +0 -0
  101. package/dist/files/red-hat-display-latin-ext-400-italic.woff +0 -0
  102. package/dist/files/red-hat-display-latin-ext-400-italic.woff2 +0 -0
  103. package/dist/files/red-hat-display-latin-ext-400-normal.woff +0 -0
  104. package/dist/files/red-hat-display-latin-ext-400-normal.woff2 +0 -0
  105. package/dist/files/red-hat-display-latin-ext-500-italic.woff +0 -0
  106. package/dist/files/red-hat-display-latin-ext-500-italic.woff2 +0 -0
  107. package/dist/files/red-hat-display-latin-ext-500-normal.woff +0 -0
  108. package/dist/files/red-hat-display-latin-ext-500-normal.woff2 +0 -0
  109. package/dist/files/red-hat-display-latin-ext-600-italic.woff +0 -0
  110. package/dist/files/red-hat-display-latin-ext-600-italic.woff2 +0 -0
  111. package/dist/files/red-hat-display-latin-ext-600-normal.woff +0 -0
  112. package/dist/files/red-hat-display-latin-ext-600-normal.woff2 +0 -0
  113. package/dist/files/red-hat-display-latin-ext-700-italic.woff +0 -0
  114. package/dist/files/red-hat-display-latin-ext-700-italic.woff2 +0 -0
  115. package/dist/files/red-hat-display-latin-ext-700-normal.woff +0 -0
  116. package/dist/files/red-hat-display-latin-ext-700-normal.woff2 +0 -0
  117. package/dist/files/red-hat-display-latin-ext-800-italic.woff +0 -0
  118. package/dist/files/red-hat-display-latin-ext-800-italic.woff2 +0 -0
  119. package/dist/files/red-hat-display-latin-ext-800-normal.woff +0 -0
  120. package/dist/files/red-hat-display-latin-ext-800-normal.woff2 +0 -0
  121. package/dist/files/red-hat-display-latin-ext-900-italic.woff +0 -0
  122. package/dist/files/red-hat-display-latin-ext-900-italic.woff2 +0 -0
  123. package/dist/files/red-hat-display-latin-ext-900-normal.woff +0 -0
  124. package/dist/files/red-hat-display-latin-ext-900-normal.woff2 +0 -0
  125. package/dist/funnel-chart.d.ts +84 -0
  126. package/dist/funnel-chart.js +569 -0
  127. package/dist/funnel-chart.js.map +1 -0
  128. package/dist/index.d.ts +87 -0
  129. package/dist/index.js +10448 -0
  130. package/dist/index.js.map +1 -0
  131. package/dist/input-group.d.ts +31 -0
  132. package/dist/input-group.js +380 -0
  133. package/dist/input-group.js.map +1 -0
  134. package/dist/input-size-context.d.ts +11 -0
  135. package/dist/input-size-context.js +24 -0
  136. package/dist/input-size-context.js.map +1 -0
  137. package/dist/input.d.ts +13 -0
  138. package/dist/input.js +83 -0
  139. package/dist/input.js.map +1 -0
  140. package/dist/item.d.ts +8 -0
  141. package/dist/item.js +93 -0
  142. package/dist/item.js.map +1 -0
  143. package/dist/kpi-card.d.ts +24 -0
  144. package/dist/kpi-card.js +243 -0
  145. package/dist/kpi-card.js.map +1 -0
  146. package/dist/label.d.ts +8 -0
  147. package/dist/label.js +68 -0
  148. package/dist/label.js.map +1 -0
  149. package/dist/line-chart.d.ts +155 -0
  150. package/dist/line-chart.js +269 -0
  151. package/dist/line-chart.js.map +1 -0
  152. package/dist/logo.d.ts +6 -0
  153. package/dist/logo.js +146 -0
  154. package/dist/logo.js.map +1 -0
  155. package/dist/number-input.d.ts +41 -0
  156. package/dist/number-input.js +418 -0
  157. package/dist/number-input.js.map +1 -0
  158. package/dist/page-header.d.ts +13 -0
  159. package/dist/page-header.js +113 -0
  160. package/dist/page-header.js.map +1 -0
  161. package/dist/pagination.d.ts +35 -0
  162. package/dist/pagination.js +352 -0
  163. package/dist/pagination.js.map +1 -0
  164. package/dist/password-input.d.ts +13 -0
  165. package/dist/password-input.js +356 -0
  166. package/dist/password-input.js.map +1 -0
  167. package/dist/phone-input.d.ts +21 -0
  168. package/dist/phone-input.js +573 -0
  169. package/dist/phone-input.js.map +1 -0
  170. package/dist/photo-gallery.d.ts +42 -0
  171. package/dist/photo-gallery.js +756 -0
  172. package/dist/photo-gallery.js.map +1 -0
  173. package/dist/pie-chart.d.ts +125 -0
  174. package/dist/pie-chart.js +192 -0
  175. package/dist/pie-chart.js.map +1 -0
  176. package/dist/popover.d.ts +20 -0
  177. package/dist/popover.js +169 -0
  178. package/dist/popover.js.map +1 -0
  179. package/dist/progress.d.ts +28 -0
  180. package/dist/progress.js +315 -0
  181. package/dist/progress.js.map +1 -0
  182. package/dist/radio-group.d.ts +32 -0
  183. package/dist/radio-group.js +100 -0
  184. package/dist/radio-group.js.map +1 -0
  185. package/dist/red-hat-display.css +2 -0
  186. package/dist/rich-text-editor.d.ts +16 -0
  187. package/dist/rich-text-editor.js +1000 -0
  188. package/dist/rich-text-editor.js.map +1 -0
  189. package/dist/search-input.d.ts +19 -0
  190. package/dist/search-input.js +411 -0
  191. package/dist/search-input.js.map +1 -0
  192. package/dist/select.d.ts +21 -0
  193. package/dist/select.js +305 -0
  194. package/dist/select.js.map +1 -0
  195. package/dist/separator.d.ts +10 -0
  196. package/dist/separator.js +72 -0
  197. package/dist/separator.js.map +1 -0
  198. package/dist/sheet.d.ts +24 -0
  199. package/dist/sheet.js +282 -0
  200. package/dist/sheet.js.map +1 -0
  201. package/dist/sidebar.d.ts +70 -0
  202. package/dist/sidebar.js +1078 -0
  203. package/dist/sidebar.js.map +1 -0
  204. package/dist/size-context.d.ts +11 -0
  205. package/dist/size-context.js +22 -0
  206. package/dist/size-context.js.map +1 -0
  207. package/dist/skeleton.d.ts +5 -0
  208. package/dist/skeleton.js +48 -0
  209. package/dist/skeleton.js.map +1 -0
  210. package/dist/sparkline.d.ts +94 -0
  211. package/dist/sparkline.js +568 -0
  212. package/dist/sparkline.js.map +1 -0
  213. package/dist/stepper.d.ts +43 -0
  214. package/dist/stepper.js +296 -0
  215. package/dist/stepper.js.map +1 -0
  216. package/dist/styles.css +2 -0
  217. package/dist/switch.d.ts +29 -0
  218. package/dist/switch.js +108 -0
  219. package/dist/switch.js.map +1 -0
  220. package/dist/tab-list.d.ts +38 -0
  221. package/dist/tab-list.js +394 -0
  222. package/dist/tab-list.js.map +1 -0
  223. package/dist/table.d.ts +69 -0
  224. package/dist/table.js +197 -0
  225. package/dist/table.js.map +1 -0
  226. package/dist/tabs.d.ts +18 -0
  227. package/dist/tabs.js +159 -0
  228. package/dist/tabs.js.map +1 -0
  229. package/dist/tag.d.ts +25 -0
  230. package/dist/tag.js +160 -0
  231. package/dist/tag.js.map +1 -0
  232. package/dist/textarea.d.ts +12 -0
  233. package/dist/textarea.js +78 -0
  234. package/dist/textarea.js.map +1 -0
  235. package/dist/theme/giddaa.css +2 -0
  236. package/dist/time-picker.d.ts +13 -0
  237. package/dist/time-picker.js +472 -0
  238. package/dist/time-picker.js.map +1 -0
  239. package/dist/toast.d.ts +23 -0
  240. package/dist/toast.js +330 -0
  241. package/dist/toast.js.map +1 -0
  242. package/dist/tooltip.d.ts +11 -0
  243. package/dist/tooltip.js +96 -0
  244. package/dist/tooltip.js.map +1 -0
  245. package/dist/tree-map.d.ts +127 -0
  246. package/dist/tree-map.js +652 -0
  247. package/dist/tree-map.js.map +1 -0
  248. package/package.json +328 -0
@@ -0,0 +1,396 @@
1
+ // src/components/ui/carousel.tsx
2
+ import { cva } from "class-variance-authority";
3
+ import useEmblaCarousel from "embla-carousel-react";
4
+ import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react";
5
+ import * as React from "react";
6
+
7
+ // src/lib/cn.ts
8
+ import { clsx } from "clsx";
9
+ import { extendTailwindMerge } from "tailwind-merge";
10
+ var twMerge = extendTailwindMerge({
11
+ extend: {
12
+ classGroups: {
13
+ "font-size": [
14
+ {
15
+ text: [
16
+ "gdt-display",
17
+ "gdt-h1",
18
+ "gdt-h2",
19
+ "gdt-h3",
20
+ "gdt-h4",
21
+ "gdt-h5",
22
+ "gdt-xl",
23
+ "gdt-lg",
24
+ "gdt-md",
25
+ "gdt-sm",
26
+ "gdt-xs",
27
+ "gdt-subtext",
28
+ "gdt-capitalized"
29
+ ]
30
+ }
31
+ ]
32
+ }
33
+ }
34
+ });
35
+ function cn(...inputs) {
36
+ return twMerge(clsx(inputs));
37
+ }
38
+
39
+ // src/components/ui/size-context.tsx
40
+ import { createContext, useContext } from "react";
41
+ import { Fragment, jsx } from "react/jsx-runtime";
42
+ var SizeContext = createContext(void 0);
43
+ function useComponentSize(size, fallback = "md") {
44
+ const inheritedSize = useContext(SizeContext);
45
+ return size ?? inheritedSize ?? fallback;
46
+ }
47
+
48
+ // src/components/ui/carousel.tsx
49
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
50
+ var glassChrome = "border border-fg-on-brand/[0.18] bg-surface-glass-overlay-button backdrop-blur-[16px]";
51
+ var carouselVariants = cva(
52
+ "relative overflow-hidden rounded-2xl bg-surface-brand-subtle",
53
+ {
54
+ variants: {
55
+ imageSize: {
56
+ sm: "w-[320px] max-w-full aspect-[320/220]",
57
+ md: "w-[520px] max-w-full aspect-[520/340]",
58
+ lg: "w-[800px] max-w-full aspect-[800/500]",
59
+ full: "w-full"
60
+ }
61
+ },
62
+ defaultVariants: {
63
+ imageSize: "md"
64
+ }
65
+ }
66
+ );
67
+ var CarouselContext = React.createContext(null);
68
+ function useCarousel() {
69
+ const context = React.useContext(CarouselContext);
70
+ if (!context) {
71
+ throw new Error("useCarousel must be used within a <Carousel />");
72
+ }
73
+ return context;
74
+ }
75
+ function Carousel({
76
+ orientation = "horizontal",
77
+ opts,
78
+ setApi,
79
+ plugins,
80
+ size,
81
+ imageSize,
82
+ className,
83
+ children,
84
+ ...props
85
+ }) {
86
+ const resolvedSize = useComponentSize(size);
87
+ const [carouselRef, api] = useEmblaCarousel(
88
+ {
89
+ ...opts,
90
+ axis: orientation === "horizontal" ? "x" : "y"
91
+ },
92
+ plugins
93
+ );
94
+ const [canScrollPrev, setCanScrollPrev] = React.useState(false);
95
+ const [canScrollNext, setCanScrollNext] = React.useState(false);
96
+ const [selectedIndex, setSelectedIndex] = React.useState(0);
97
+ const [scrollSnaps, setScrollSnaps] = React.useState([]);
98
+ const onSelect = React.useCallback((api2) => {
99
+ if (!api2) return;
100
+ setCanScrollPrev(api2.canScrollPrev());
101
+ setCanScrollNext(api2.canScrollNext());
102
+ setSelectedIndex(api2.selectedScrollSnap());
103
+ }, []);
104
+ const onReInit = React.useCallback(
105
+ (api2) => {
106
+ if (!api2) return;
107
+ setScrollSnaps(api2.scrollSnapList());
108
+ onSelect(api2);
109
+ },
110
+ [onSelect]
111
+ );
112
+ const scrollPrev = React.useCallback(() => {
113
+ api?.scrollPrev();
114
+ }, [api]);
115
+ const scrollNext = React.useCallback(() => {
116
+ api?.scrollNext();
117
+ }, [api]);
118
+ const scrollTo = React.useCallback(
119
+ (index) => {
120
+ api?.scrollTo(index);
121
+ },
122
+ [api]
123
+ );
124
+ const handleKeyDown = React.useCallback(
125
+ (event) => {
126
+ if (event.key === "ArrowLeft") {
127
+ event.preventDefault();
128
+ scrollPrev();
129
+ } else if (event.key === "ArrowRight") {
130
+ event.preventDefault();
131
+ scrollNext();
132
+ }
133
+ },
134
+ [scrollPrev, scrollNext]
135
+ );
136
+ React.useEffect(() => {
137
+ if (!api || !setApi) return;
138
+ setApi(api);
139
+ }, [api, setApi]);
140
+ React.useEffect(() => {
141
+ if (!api) return;
142
+ onReInit(api);
143
+ api.on("reInit", onReInit);
144
+ api.on("select", onSelect);
145
+ return () => {
146
+ api?.off("reInit", onReInit);
147
+ api?.off("select", onSelect);
148
+ };
149
+ }, [api, onReInit, onSelect]);
150
+ return /* @__PURE__ */ jsx2(
151
+ CarouselContext.Provider,
152
+ {
153
+ value: {
154
+ carouselRef,
155
+ api,
156
+ orientation,
157
+ size: resolvedSize,
158
+ scrollPrev,
159
+ scrollNext,
160
+ scrollTo,
161
+ canScrollPrev,
162
+ canScrollNext,
163
+ selectedIndex,
164
+ scrollSnaps
165
+ },
166
+ children: /* @__PURE__ */ jsx2(
167
+ "div",
168
+ {
169
+ onKeyDownCapture: handleKeyDown,
170
+ className: cn(carouselVariants({ imageSize }), className),
171
+ role: "region",
172
+ "aria-roledescription": "carousel",
173
+ "data-slot": "carousel",
174
+ ...props,
175
+ children
176
+ }
177
+ )
178
+ }
179
+ );
180
+ }
181
+ function CarouselContent({ className, ...props }) {
182
+ const { carouselRef, orientation } = useCarousel();
183
+ return /* @__PURE__ */ jsx2(
184
+ "div",
185
+ {
186
+ ref: carouselRef,
187
+ className: "h-full overflow-hidden",
188
+ "data-slot": "carousel-content",
189
+ children: /* @__PURE__ */ jsx2(
190
+ "div",
191
+ {
192
+ className: cn(
193
+ "flex h-full",
194
+ orientation === "horizontal" ? "" : "flex-col",
195
+ className
196
+ ),
197
+ ...props
198
+ }
199
+ )
200
+ }
201
+ );
202
+ }
203
+ function CarouselItem({ className, ...props }) {
204
+ return (
205
+ // biome-ignore lint/a11y/useSemanticElements: a carousel slide is a role="group" with aria-roledescription per the W3C pattern, not a fieldset.
206
+ /* @__PURE__ */ jsx2(
207
+ "div",
208
+ {
209
+ role: "group",
210
+ "aria-roledescription": "slide",
211
+ "data-slot": "carousel-item",
212
+ className: cn("min-w-0 shrink-0 grow-0 basis-full", className),
213
+ ...props
214
+ }
215
+ )
216
+ );
217
+ }
218
+ var arrowVariants = cva(
219
+ cn(
220
+ "absolute top-1/2 z-10 grid -translate-y-1/2 place-items-center rounded-full text-fg-on-brand/95 shadow-1 transition-[transform,opacity] outline-none",
221
+ glassChrome,
222
+ "hover:scale-105 focus-visible:shadow-[0px_0px_0px_2px_var(--color-line-focus)] active:scale-95 disabled:pointer-events-none disabled:opacity-40"
223
+ ),
224
+ {
225
+ variants: {
226
+ size: {
227
+ sm: "size-8 [&_svg]:size-4",
228
+ md: "size-10 [&_svg]:size-[18px]",
229
+ lg: "size-12 [&_svg]:size-5"
230
+ },
231
+ side: {
232
+ prev: "",
233
+ next: ""
234
+ }
235
+ },
236
+ compoundVariants: [
237
+ { size: "sm", side: "prev", className: "left-3" },
238
+ { size: "sm", side: "next", className: "right-3" },
239
+ { size: "md", side: "prev", className: "left-4" },
240
+ { size: "md", side: "next", className: "right-4" },
241
+ { size: "lg", side: "prev", className: "left-5" },
242
+ { size: "lg", side: "next", className: "right-5" }
243
+ ],
244
+ defaultVariants: {
245
+ size: "md",
246
+ side: "prev"
247
+ }
248
+ }
249
+ );
250
+ function CarouselPrevious({
251
+ className,
252
+ ...props
253
+ }) {
254
+ const { size, scrollPrev, canScrollPrev } = useCarousel();
255
+ return /* @__PURE__ */ jsxs(
256
+ "button",
257
+ {
258
+ type: "button",
259
+ "data-slot": "carousel-previous",
260
+ className: cn(arrowVariants({ size, side: "prev" }), className),
261
+ disabled: !canScrollPrev,
262
+ onClick: scrollPrev,
263
+ ...props,
264
+ children: [
265
+ /* @__PURE__ */ jsx2(ChevronLeftIcon, { className: "cn-rtl-flip" }),
266
+ /* @__PURE__ */ jsx2("span", { className: "sr-only", children: "Previous slide" })
267
+ ]
268
+ }
269
+ );
270
+ }
271
+ function CarouselNext({ className, ...props }) {
272
+ const { size, scrollNext, canScrollNext } = useCarousel();
273
+ return /* @__PURE__ */ jsxs(
274
+ "button",
275
+ {
276
+ type: "button",
277
+ "data-slot": "carousel-next",
278
+ className: cn(arrowVariants({ size, side: "next" }), className),
279
+ disabled: !canScrollNext,
280
+ onClick: scrollNext,
281
+ ...props,
282
+ children: [
283
+ /* @__PURE__ */ jsx2(ChevronRightIcon, { className: "cn-rtl-flip" }),
284
+ /* @__PURE__ */ jsx2("span", { className: "sr-only", children: "Next slide" })
285
+ ]
286
+ }
287
+ );
288
+ }
289
+ var MANY_THRESHOLD = 5;
290
+ var MANY_WINDOW = 5;
291
+ function getIndicatorWindow(count, selected) {
292
+ if (count < MANY_THRESHOLD) {
293
+ const dots2 = Array.from({ length: count }, (_, index) => ({
294
+ index,
295
+ faded: false
296
+ }));
297
+ return { dots: dots2, start: 0, visible: count };
298
+ }
299
+ const half = Math.floor(MANY_WINDOW / 2);
300
+ const start = Math.max(0, Math.min(selected - half, count - MANY_WINDOW));
301
+ const end = start + MANY_WINDOW - 1;
302
+ const overflowLeft = start > 0;
303
+ const overflowRight = end < count - 1;
304
+ const dots = Array.from({ length: count }, (_, index) => ({
305
+ index,
306
+ faded: overflowLeft && index === start || overflowRight && index === end
307
+ }));
308
+ return { dots, start, visible: MANY_WINDOW };
309
+ }
310
+ var INDICATOR_SIZES = {
311
+ sm: { dot: 5, gap: 4, padX: 8, padY: 4 },
312
+ md: { dot: 7, gap: 5, padX: 10, padY: 5 },
313
+ lg: { dot: 9, gap: 6, padX: 12, padY: 6 }
314
+ };
315
+ var INDICATOR_OFFSET = {
316
+ sm: "bottom-3",
317
+ md: "bottom-[18px]",
318
+ lg: "bottom-6"
319
+ };
320
+ function CarouselIndicator({
321
+ className,
322
+ count: countProp,
323
+ selected: selectedProp,
324
+ size: sizeProp,
325
+ onSelect,
326
+ ...props
327
+ }) {
328
+ const ctx = React.useContext(CarouselContext);
329
+ const inheritedSize = useComponentSize(sizeProp);
330
+ const size = sizeProp ?? ctx?.size ?? inheritedSize;
331
+ const count = countProp ?? ctx?.scrollSnaps.length ?? 0;
332
+ const selected = selectedProp ?? ctx?.selectedIndex ?? 0;
333
+ const handleSelect = onSelect ?? ctx?.scrollTo;
334
+ if (count <= 1) return null;
335
+ const { dot, gap, padX, padY } = INDICATOR_SIZES[size];
336
+ const { dots, start, visible } = getIndicatorWindow(count, selected);
337
+ const step = dot + gap;
338
+ const viewportWidth = visible * step - gap;
339
+ return /* @__PURE__ */ jsx2(
340
+ "div",
341
+ {
342
+ "data-slot": "carousel-indicator",
343
+ className: cn(
344
+ "absolute left-1/2 z-10 flex -translate-x-1/2 items-center justify-center rounded-full",
345
+ INDICATOR_OFFSET[size],
346
+ glassChrome,
347
+ className
348
+ ),
349
+ style: { padding: `${padY}px ${padX}px` },
350
+ role: "tablist",
351
+ "aria-label": "Slide indicators",
352
+ ...props,
353
+ children: /* @__PURE__ */ jsx2("div", { className: "overflow-hidden", style: { width: viewportWidth }, children: /* @__PURE__ */ jsx2(
354
+ "div",
355
+ {
356
+ className: "flex items-center transition-transform duration-300 ease-out",
357
+ style: { gap, transform: `translateX(${-start * step}px)` },
358
+ children: dots.map(({ index, faded }) => {
359
+ const isActive = index === selected;
360
+ return /* @__PURE__ */ jsx2(
361
+ "button",
362
+ {
363
+ type: "button",
364
+ role: "tab",
365
+ "aria-selected": isActive,
366
+ "aria-label": `Go to slide ${index + 1}`,
367
+ onClick: () => handleSelect?.(index),
368
+ className: cn(
369
+ "shrink-0 rounded-full bg-fg-on-brand transition-[transform,opacity] duration-300 ease-out",
370
+ handleSelect ? "cursor-pointer" : "cursor-default"
371
+ ),
372
+ style: {
373
+ width: dot,
374
+ height: dot,
375
+ opacity: faded ? 0.3 : isActive ? 1 : 0.55,
376
+ transform: faded ? "scale(0.6)" : "scale(1)"
377
+ }
378
+ },
379
+ index
380
+ );
381
+ })
382
+ }
383
+ ) })
384
+ }
385
+ );
386
+ }
387
+ export {
388
+ Carousel,
389
+ CarouselContent,
390
+ CarouselIndicator,
391
+ CarouselItem,
392
+ CarouselNext,
393
+ CarouselPrevious,
394
+ useCarousel
395
+ };
396
+ //# sourceMappingURL=carousel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/ui/carousel.tsx","../src/lib/cn.ts","../src/components/ui/size-context.tsx"],"sourcesContent":["\"use client\";\n\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport useEmblaCarousel, {\n\ttype UseEmblaCarouselType,\n} from \"embla-carousel-react\";\nimport { ChevronLeftIcon, ChevronRightIcon } from \"lucide-react\";\nimport * as React from \"react\";\nimport { cn } from \"../../lib/cn\";\nimport { type ComponentSize, useComponentSize } from \"./size-context\";\n\ntype CarouselApi = UseEmblaCarouselType[1];\ntype UseCarouselParameters = Parameters<typeof useEmblaCarousel>;\ntype CarouselOptions = UseCarouselParameters[0];\ntype CarouselPlugin = UseCarouselParameters[1];\n\n/**\n * Shared glassmorphic treatment for every overlay surface in the carousel\n * (navigation arrows + indicator). Dark glass at 35% over a 16px backdrop\n * blur with a near-invisible 18% light border that lifts the chrome off the\n * imagery. Always dark, in both themes — see `--color-surface-glass-overlay-button`.\n */\nconst glassChrome =\n\t\"border border-fg-on-brand/[0.18] bg-surface-glass-overlay-button backdrop-blur-[16px]\";\n\nconst carouselVariants = cva(\n\t\"relative overflow-hidden rounded-2xl bg-surface-brand-subtle\",\n\t{\n\t\tvariants: {\n\t\t\timageSize: {\n\t\t\t\tsm: \"w-[320px] max-w-full aspect-[320/220]\",\n\t\t\t\tmd: \"w-[520px] max-w-full aspect-[520/340]\",\n\t\t\t\tlg: \"w-[800px] max-w-full aspect-[800/500]\",\n\t\t\t\tfull: \"w-full\",\n\t\t\t},\n\t\t},\n\t\tdefaultVariants: {\n\t\t\timageSize: \"md\",\n\t\t},\n\t},\n);\n\ntype CarouselContextProps = {\n\tcarouselRef: ReturnType<typeof useEmblaCarousel>[0];\n\tapi: CarouselApi;\n\torientation: \"horizontal\" | \"vertical\";\n\tsize: ComponentSize;\n\tscrollPrev: () => void;\n\tscrollNext: () => void;\n\tscrollTo: (index: number) => void;\n\tcanScrollPrev: boolean;\n\tcanScrollNext: boolean;\n\tselectedIndex: number;\n\tscrollSnaps: number[];\n};\n\nconst CarouselContext = React.createContext<CarouselContextProps | null>(null);\n\nfunction useCarousel() {\n\tconst context = React.useContext(CarouselContext);\n\n\tif (!context) {\n\t\tthrow new Error(\"useCarousel must be used within a <Carousel />\");\n\t}\n\n\treturn context;\n}\n\ntype CarouselProps = {\n\topts?: CarouselOptions;\n\tplugins?: CarouselPlugin;\n\torientation?: \"horizontal\" | \"vertical\";\n\t/** Scales the chrome (arrows + indicator) without touching the image. */\n\tsize?: ComponentSize;\n\tsetApi?: (api: CarouselApi) => void;\n};\n\nfunction Carousel({\n\torientation = \"horizontal\",\n\topts,\n\tsetApi,\n\tplugins,\n\tsize,\n\timageSize,\n\tclassName,\n\tchildren,\n\t...props\n}: React.ComponentProps<\"div\"> &\n\tCarouselProps &\n\tVariantProps<typeof carouselVariants>) {\n\tconst resolvedSize = useComponentSize(size);\n\tconst [carouselRef, api] = useEmblaCarousel(\n\t\t{\n\t\t\t...opts,\n\t\t\taxis: orientation === \"horizontal\" ? \"x\" : \"y\",\n\t\t},\n\t\tplugins,\n\t);\n\tconst [canScrollPrev, setCanScrollPrev] = React.useState(false);\n\tconst [canScrollNext, setCanScrollNext] = React.useState(false);\n\tconst [selectedIndex, setSelectedIndex] = React.useState(0);\n\tconst [scrollSnaps, setScrollSnaps] = React.useState<number[]>([]);\n\n\tconst onSelect = React.useCallback((api: CarouselApi) => {\n\t\tif (!api) return;\n\t\tsetCanScrollPrev(api.canScrollPrev());\n\t\tsetCanScrollNext(api.canScrollNext());\n\t\tsetSelectedIndex(api.selectedScrollSnap());\n\t}, []);\n\n\tconst onReInit = React.useCallback(\n\t\t(api: CarouselApi) => {\n\t\t\tif (!api) return;\n\t\t\tsetScrollSnaps(api.scrollSnapList());\n\t\t\tonSelect(api);\n\t\t},\n\t\t[onSelect],\n\t);\n\n\tconst scrollPrev = React.useCallback(() => {\n\t\tapi?.scrollPrev();\n\t}, [api]);\n\n\tconst scrollNext = React.useCallback(() => {\n\t\tapi?.scrollNext();\n\t}, [api]);\n\n\tconst scrollTo = React.useCallback(\n\t\t(index: number) => {\n\t\t\tapi?.scrollTo(index);\n\t\t},\n\t\t[api],\n\t);\n\n\tconst handleKeyDown = React.useCallback(\n\t\t(event: React.KeyboardEvent<HTMLDivElement>) => {\n\t\t\tif (event.key === \"ArrowLeft\") {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tscrollPrev();\n\t\t\t} else if (event.key === \"ArrowRight\") {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tscrollNext();\n\t\t\t}\n\t\t},\n\t\t[scrollPrev, scrollNext],\n\t);\n\n\tReact.useEffect(() => {\n\t\tif (!api || !setApi) return;\n\t\tsetApi(api);\n\t}, [api, setApi]);\n\n\tReact.useEffect(() => {\n\t\tif (!api) return;\n\t\tonReInit(api);\n\t\tapi.on(\"reInit\", onReInit);\n\t\tapi.on(\"select\", onSelect);\n\n\t\treturn () => {\n\t\t\tapi?.off(\"reInit\", onReInit);\n\t\t\tapi?.off(\"select\", onSelect);\n\t\t};\n\t}, [api, onReInit, onSelect]);\n\n\treturn (\n\t\t<CarouselContext.Provider\n\t\t\tvalue={{\n\t\t\t\tcarouselRef,\n\t\t\t\tapi,\n\t\t\t\torientation,\n\t\t\t\tsize: resolvedSize,\n\t\t\t\tscrollPrev,\n\t\t\t\tscrollNext,\n\t\t\t\tscrollTo,\n\t\t\t\tcanScrollPrev,\n\t\t\t\tcanScrollNext,\n\t\t\t\tselectedIndex,\n\t\t\t\tscrollSnaps,\n\t\t\t}}\n\t\t>\n\t\t\t{/* biome-ignore lint/a11y/useSemanticElements: the W3C carousel pattern is a region with aria-roledescription, not a generic landmark element. */}\n\t\t\t<div\n\t\t\t\tonKeyDownCapture={handleKeyDown}\n\t\t\t\tclassName={cn(carouselVariants({ imageSize }), className)}\n\t\t\t\trole=\"region\"\n\t\t\t\taria-roledescription=\"carousel\"\n\t\t\t\tdata-slot=\"carousel\"\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</div>\n\t\t</CarouselContext.Provider>\n\t);\n}\n\nfunction CarouselContent({ className, ...props }: React.ComponentProps<\"div\">) {\n\tconst { carouselRef, orientation } = useCarousel();\n\n\treturn (\n\t\t<div\n\t\t\tref={carouselRef}\n\t\t\tclassName=\"h-full overflow-hidden\"\n\t\t\tdata-slot=\"carousel-content\"\n\t\t>\n\t\t\t<div\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"flex h-full\",\n\t\t\t\t\torientation === \"horizontal\" ? \"\" : \"flex-col\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t</div>\n\t);\n}\n\nfunction CarouselItem({ className, ...props }: React.ComponentProps<\"div\">) {\n\treturn (\n\t\t// biome-ignore lint/a11y/useSemanticElements: a carousel slide is a role=\"group\" with aria-roledescription per the W3C pattern, not a fieldset.\n\t\t<div\n\t\t\trole=\"group\"\n\t\t\taria-roledescription=\"slide\"\n\t\t\tdata-slot=\"carousel-item\"\n\t\t\tclassName={cn(\"min-w-0 shrink-0 grow-0 basis-full\", className)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nconst arrowVariants = cva(\n\tcn(\n\t\t\"absolute top-1/2 z-10 grid -translate-y-1/2 place-items-center rounded-full text-fg-on-brand/95 shadow-1 transition-[transform,opacity] outline-none\",\n\t\tglassChrome,\n\t\t\"hover:scale-105 focus-visible:shadow-[0px_0px_0px_2px_var(--color-line-focus)] active:scale-95 disabled:pointer-events-none disabled:opacity-40\",\n\t),\n\t{\n\t\tvariants: {\n\t\t\tsize: {\n\t\t\t\tsm: \"size-8 [&_svg]:size-4\",\n\t\t\t\tmd: \"size-10 [&_svg]:size-[18px]\",\n\t\t\t\tlg: \"size-12 [&_svg]:size-5\",\n\t\t\t},\n\t\t\tside: {\n\t\t\t\tprev: \"\",\n\t\t\t\tnext: \"\",\n\t\t\t},\n\t\t},\n\t\tcompoundVariants: [\n\t\t\t{ size: \"sm\", side: \"prev\", className: \"left-3\" },\n\t\t\t{ size: \"sm\", side: \"next\", className: \"right-3\" },\n\t\t\t{ size: \"md\", side: \"prev\", className: \"left-4\" },\n\t\t\t{ size: \"md\", side: \"next\", className: \"right-4\" },\n\t\t\t{ size: \"lg\", side: \"prev\", className: \"left-5\" },\n\t\t\t{ size: \"lg\", side: \"next\", className: \"right-5\" },\n\t\t],\n\t\tdefaultVariants: {\n\t\t\tsize: \"md\",\n\t\t\tside: \"prev\",\n\t\t},\n\t},\n);\n\nfunction CarouselPrevious({\n\tclassName,\n\t...props\n}: React.ComponentProps<\"button\">) {\n\tconst { size, scrollPrev, canScrollPrev } = useCarousel();\n\n\treturn (\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tdata-slot=\"carousel-previous\"\n\t\t\tclassName={cn(arrowVariants({ size, side: \"prev\" }), className)}\n\t\t\tdisabled={!canScrollPrev}\n\t\t\tonClick={scrollPrev}\n\t\t\t{...props}\n\t\t>\n\t\t\t<ChevronLeftIcon className=\"cn-rtl-flip\" />\n\t\t\t<span className=\"sr-only\">Previous slide</span>\n\t\t</button>\n\t);\n}\n\nfunction CarouselNext({ className, ...props }: React.ComponentProps<\"button\">) {\n\tconst { size, scrollNext, canScrollNext } = useCarousel();\n\n\treturn (\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tdata-slot=\"carousel-next\"\n\t\t\tclassName={cn(arrowVariants({ size, side: \"next\" }), className)}\n\t\t\tdisabled={!canScrollNext}\n\t\t\tonClick={scrollNext}\n\t\t\t{...props}\n\t\t>\n\t\t\t<ChevronRightIcon className=\"cn-rtl-flip\" />\n\t\t\t<span className=\"sr-only\">Next slide</span>\n\t\t</button>\n\t);\n}\n\n/**\n * Past this many items the indicator switches from \"show every dot\" to the\n * Airbnb-style windowed mode: at most `MANY_WINDOW` dots, the active one kept\n * near the centre, and dots at a clipped edge faded down to imply more beyond.\n */\nconst MANY_THRESHOLD = 5;\nconst MANY_WINDOW = 5;\n\ntype IndicatorDot = {\n\t/** Index into the full list of slides. */\n\tindex: number;\n\t/** True for the outermost dot on a side that has hidden slides beyond it. */\n\tfaded: boolean;\n};\n\n/**\n * Returns the dots to render plus the window start, so the determinate and\n * windowed (\"many\") cases share one render path. The dot strip is always the\n * full list; `start` drives the translate that slides it under the viewport.\n */\nfunction getIndicatorWindow(count: number, selected: number) {\n\tif (count < MANY_THRESHOLD) {\n\t\tconst dots: IndicatorDot[] = Array.from({ length: count }, (_, index) => ({\n\t\t\tindex,\n\t\t\tfaded: false,\n\t\t}));\n\t\treturn { dots, start: 0, visible: count };\n\t}\n\n\tconst half = Math.floor(MANY_WINDOW / 2);\n\tconst start = Math.max(0, Math.min(selected - half, count - MANY_WINDOW));\n\tconst end = start + MANY_WINDOW - 1;\n\tconst overflowLeft = start > 0;\n\tconst overflowRight = end < count - 1;\n\n\tconst dots: IndicatorDot[] = Array.from({ length: count }, (_, index) => ({\n\t\tindex,\n\t\tfaded:\n\t\t\t(overflowLeft && index === start) || (overflowRight && index === end),\n\t}));\n\n\treturn { dots, start, visible: MANY_WINDOW };\n}\n\n/** Dot diameter, gap, and pill padding per size — in px to keep them crisp. */\nconst INDICATOR_SIZES: Record<\n\tComponentSize,\n\t{ dot: number; gap: number; padX: number; padY: number }\n> = {\n\tsm: { dot: 5, gap: 4, padX: 8, padY: 4 },\n\tmd: { dot: 7, gap: 5, padX: 10, padY: 5 },\n\tlg: { dot: 9, gap: 6, padX: 12, padY: 6 },\n};\n\n/** Distance of the indicator from the bottom edge, per size (12/18/24px). */\nconst INDICATOR_OFFSET: Record<ComponentSize, string> = {\n\tsm: \"bottom-3\",\n\tmd: \"bottom-[18px]\",\n\tlg: \"bottom-6\",\n};\n\ntype CarouselIndicatorProps = Omit<\n\tReact.ComponentProps<\"div\">,\n\t\"children\" | \"onSelect\"\n> & {\n\t/** Override the live count (e.g. for static design previews). */\n\tcount?: number;\n\t/** Override the live selected index. */\n\tselected?: number;\n\t/** Override the inherited carousel size. */\n\tsize?: ComponentSize;\n\t/** Jump to a slide when a dot is activated. Defaults to the carousel API. */\n\tonSelect?: (index: number) => void;\n};\n\nfunction CarouselIndicator({\n\tclassName,\n\tcount: countProp,\n\tselected: selectedProp,\n\tsize: sizeProp,\n\tonSelect,\n\t...props\n}: CarouselIndicatorProps) {\n\t// Read context loosely so the indicator can also stand alone (previews,\n\t// docs) by passing `count`/`selected` directly.\n\tconst ctx = React.useContext(CarouselContext);\n\tconst inheritedSize = useComponentSize(sizeProp);\n\n\tconst size = sizeProp ?? ctx?.size ?? inheritedSize;\n\tconst count = countProp ?? ctx?.scrollSnaps.length ?? 0;\n\tconst selected = selectedProp ?? ctx?.selectedIndex ?? 0;\n\tconst handleSelect = onSelect ?? ctx?.scrollTo;\n\n\tif (count <= 1) return null;\n\n\tconst { dot, gap, padX, padY } = INDICATOR_SIZES[size];\n\tconst { dots, start, visible } = getIndicatorWindow(count, selected);\n\tconst step = dot + gap;\n\t// Viewport width clips the strip to exactly `visible` dots; the strip then\n\t// translates by `start` steps so the windowed dots line up under it.\n\tconst viewportWidth = visible * step - gap;\n\n\treturn (\n\t\t<div\n\t\t\tdata-slot=\"carousel-indicator\"\n\t\t\tclassName={cn(\n\t\t\t\t\"absolute left-1/2 z-10 flex -translate-x-1/2 items-center justify-center rounded-full\",\n\t\t\t\tINDICATOR_OFFSET[size],\n\t\t\t\tglassChrome,\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\tstyle={{ padding: `${padY}px ${padX}px` }}\n\t\t\trole=\"tablist\"\n\t\t\taria-label=\"Slide indicators\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<div className=\"overflow-hidden\" style={{ width: viewportWidth }}>\n\t\t\t\t<div\n\t\t\t\t\tclassName=\"flex items-center transition-transform duration-300 ease-out\"\n\t\t\t\t\tstyle={{ gap, transform: `translateX(${-start * step}px)` }}\n\t\t\t\t>\n\t\t\t\t\t{dots.map(({ index, faded }) => {\n\t\t\t\t\t\tconst isActive = index === selected;\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\tkey={index}\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\trole=\"tab\"\n\t\t\t\t\t\t\t\taria-selected={isActive}\n\t\t\t\t\t\t\t\taria-label={`Go to slide ${index + 1}`}\n\t\t\t\t\t\t\t\tonClick={() => handleSelect?.(index)}\n\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\"shrink-0 rounded-full bg-fg-on-brand transition-[transform,opacity] duration-300 ease-out\",\n\t\t\t\t\t\t\t\t\thandleSelect ? \"cursor-pointer\" : \"cursor-default\",\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\twidth: dot,\n\t\t\t\t\t\t\t\t\theight: dot,\n\t\t\t\t\t\t\t\t\topacity: faded ? 0.3 : isActive ? 1 : 0.55,\n\t\t\t\t\t\t\t\t\ttransform: faded ? \"scale(0.6)\" : \"scale(1)\",\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t);\n\t\t\t\t\t})}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nexport {\n\ttype CarouselApi,\n\tCarousel,\n\tCarouselContent,\n\tCarouselItem,\n\tCarouselPrevious,\n\tCarouselNext,\n\tCarouselIndicator,\n\tuseCarousel,\n};\n","import { type ClassValue, clsx } from \"clsx\";\nimport { extendTailwindMerge } from \"tailwind-merge\";\n\nconst twMerge = extendTailwindMerge({\n\textend: {\n\t\tclassGroups: {\n\t\t\t\"font-size\": [\n\t\t\t\t{\n\t\t\t\t\ttext: [\n\t\t\t\t\t\t\"gdt-display\",\n\t\t\t\t\t\t\"gdt-h1\",\n\t\t\t\t\t\t\"gdt-h2\",\n\t\t\t\t\t\t\"gdt-h3\",\n\t\t\t\t\t\t\"gdt-h4\",\n\t\t\t\t\t\t\"gdt-h5\",\n\t\t\t\t\t\t\"gdt-xl\",\n\t\t\t\t\t\t\"gdt-lg\",\n\t\t\t\t\t\t\"gdt-md\",\n\t\t\t\t\t\t\"gdt-sm\",\n\t\t\t\t\t\t\"gdt-xs\",\n\t\t\t\t\t\t\"gdt-subtext\",\n\t\t\t\t\t\t\"gdt-capitalized\",\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t},\n});\n\nexport function cn(...inputs: ClassValue[]) {\n\treturn twMerge(clsx(inputs));\n}\n","\"use client\";\n\nimport { createContext, type ReactNode, useContext } from \"react\";\n\ntype ComponentSize = \"sm\" | \"md\" | \"lg\";\n\nconst SizeContext = createContext<ComponentSize | undefined>(undefined);\n\nfunction SizeProvider({\n\tchildren,\n\tsize,\n}: {\n\tchildren: ReactNode;\n\tsize?: ComponentSize | null;\n}) {\n\tif (!size) {\n\t\treturn <>{children}</>;\n\t}\n\n\treturn <SizeContext.Provider value={size}>{children}</SizeContext.Provider>;\n}\n\nfunction useComponentSize(\n\tsize?: ComponentSize | null,\n\tfallback: ComponentSize = \"md\",\n) {\n\tconst inheritedSize = useContext(SizeContext);\n\treturn size ?? inheritedSize ?? fallback;\n}\n\nexport { SizeProvider, useComponentSize, type ComponentSize };\n"],"mappings":"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","names":["jsx","api","dots"]}
@@ -0,0 +1,122 @@
1
+ import * as class_variance_authority_types from 'class-variance-authority/types';
2
+ import { VariantProps } from 'class-variance-authority';
3
+ import * as React from 'react';
4
+ import * as RechartsPrimitive from 'recharts';
5
+ import { TooltipValueType } from 'recharts';
6
+ import { ComponentSize } from './size-context.js';
7
+
8
+ /** How a precise value is formatted in the tooltip and which prefix/suffix it carries. */
9
+ type ChartValueType = "number" | "percentage" | "currency";
10
+ declare const THEMES: {
11
+ readonly light: "";
12
+ readonly dark: ".dark";
13
+ };
14
+ type TooltipNameType = number | string;
15
+ type ChartConfig = Record<string, {
16
+ label?: React.ReactNode;
17
+ icon?: React.ComponentType;
18
+ } & ({
19
+ color?: string;
20
+ theme?: never;
21
+ } | {
22
+ color?: never;
23
+ theme: Record<keyof typeof THEMES, string>;
24
+ })>;
25
+ declare function ChartCard({ className, size, children, ...props }: React.ComponentProps<"section"> & {
26
+ size?: ComponentSize;
27
+ }): React.JSX.Element;
28
+ declare function ChartHeader({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
29
+ declare function ChartTitle({ className, size, ...props }: React.ComponentProps<"h3"> & {
30
+ size?: ComponentSize;
31
+ }): React.JSX.Element;
32
+ declare function ChartDescription({ className, size, ...props }: React.ComponentProps<"p"> & {
33
+ size?: ComponentSize;
34
+ }): React.JSX.Element;
35
+ declare function ChartContainer({ id, className, children, config, initialDimension, ...props }: React.ComponentProps<"div"> & {
36
+ config: ChartConfig;
37
+ children: React.ComponentProps<typeof RechartsPrimitive.ResponsiveContainer>["children"];
38
+ initialDimension?: {
39
+ width: number;
40
+ height: number;
41
+ };
42
+ }): React.JSX.Element;
43
+ declare const ChartStyle: ({ id, config }: {
44
+ id: string;
45
+ config: ChartConfig;
46
+ }) => React.JSX.Element | null;
47
+ declare const ChartTooltip: typeof RechartsPrimitive.Tooltip;
48
+ /**
49
+ * Hover tooltip for a chart data point. It surfaces a single precise value with
50
+ * type-appropriate formatting — grouped integers, percentages, or ₦-prefixed
51
+ * currency — sitting on an elevated overlay (bg-surface-overlay, Shadow-2,
52
+ * 1px border-subtle) so users can read exact figures without leaving the chart.
53
+ *
54
+ * Anatomy: series dot · metric label · hero value · period caption.
55
+ */
56
+ declare const chartTooltipVariants: (props?: ({
57
+ size?: "sm" | "md" | "lg" | "xs" | null | undefined;
58
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
59
+ declare function ChartTooltipContent({ active, payload, className, hideIndicator, label, labelFormatter, formatter, color, nameKey, valueType, size, }: React.ComponentProps<typeof RechartsPrimitive.Tooltip> & React.ComponentProps<"div"> & {
60
+ hideIndicator?: boolean;
61
+ nameKey?: string;
62
+ valueType?: ChartValueType;
63
+ } & VariantProps<typeof chartTooltipVariants> & Omit<RechartsPrimitive.DefaultTooltipContentProps<TooltipValueType, TooltipNameType>, "accessibilityLayer">): React.JSX.Element | null;
64
+ declare const ChartLegend: React.MemoExoticComponent<(outsideProps: RechartsPrimitive.LegendProps) => React.ReactPortal | null>;
65
+ /** Marker shape that ties a legend item to its series. */
66
+ type ChartLegendMarker = "dot" | "square" | "line";
67
+ /**
68
+ * A shared legend for all chart types. Each item pairs a series marker with a
69
+ * label and can be toggled to hide or show its series — the inactive state mutes
70
+ * the marker and strikes through the label. Items compose into horizontal rows
71
+ * or vertical columns, in two sizes, with dot, square, or line markers.
72
+ *
73
+ * Toggling: pass `onToggle` to make items interactive. Inactive items are read
74
+ * from each payload entry's `inactive` flag (recharts sets this when wired) or
75
+ * the controlled `inactiveKeys` set.
76
+ */
77
+ declare function ChartLegendContent({ className, hideIcon, payload, verticalAlign, nameKey, marker, size, orientation, inactiveKeys, onToggle, }: React.ComponentProps<"div"> & {
78
+ hideIcon?: boolean;
79
+ nameKey?: string;
80
+ marker?: ChartLegendMarker;
81
+ size?: "sm" | "md";
82
+ orientation?: "horizontal" | "vertical";
83
+ inactiveKeys?: Iterable<string>;
84
+ onToggle?: (key: string) => void;
85
+ } & RechartsPrimitive.DefaultLegendContentProps): React.JSX.Element | null;
86
+ /** The size-scaled layout numbers a cartesian chart needs to build axis props. */
87
+ type CartesianAxisLayout = {
88
+ tickMargin: number;
89
+ tickFontSize: number;
90
+ yAxisWidth: number;
91
+ };
92
+ /**
93
+ * Shared `<XAxis>`/`<YAxis>` props — the giddaa cartesian-axis defaults (no tick
94
+ * or axis lines, a size-scaled tick font, and a reserved value-axis width) that
95
+ * every bar and line chart would otherwise repeat per axis. Spread the result
96
+ * onto the recharts axis, then add the chart-specific props (`dataKey`,
97
+ * `domain`, `ticks`, a `width`/`type` override, …):
98
+ *
99
+ * const chart = useBarChartLayout();
100
+ * <XAxis dataKey="month" {...chart.xAxis} />
101
+ * <YAxis domain={[0, 120]} {...chart.yAxis} />
102
+ */
103
+ declare function cartesianAxisProps(layout: CartesianAxisLayout): {
104
+ readonly xAxis: {
105
+ readonly tickLine: false;
106
+ readonly axisLine: false;
107
+ readonly tickMargin: number;
108
+ readonly tick: {
109
+ fontSize: number;
110
+ };
111
+ };
112
+ readonly yAxis: {
113
+ readonly tickLine: false;
114
+ readonly axisLine: false;
115
+ readonly width: number;
116
+ readonly tick: {
117
+ fontSize: number;
118
+ };
119
+ };
120
+ };
121
+
122
+ export { type CartesianAxisLayout, ChartCard, type ChartConfig, ChartContainer, ChartDescription, ChartHeader, ChartLegend, ChartLegendContent, ChartStyle, ChartTitle, ChartTooltip, ChartTooltipContent, type ChartValueType, cartesianAxisProps };