@raydenui/ui 0.9.6 → 0.10.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 (308) hide show
  1. package/dist/Table-DCNSxua1.d.cts +31 -0
  2. package/dist/Table-DCNSxua1.d.ts +31 -0
  3. package/dist/blocks/ApplicationShellBlock.cjs +157 -0
  4. package/dist/blocks/ApplicationShellBlock.js +154 -0
  5. package/dist/blocks/CheckoutReviewBlock.cjs +16 -0
  6. package/dist/blocks/CheckoutReviewBlock.js +13 -0
  7. package/dist/blocks/CommandPaletteBlock.cjs +334 -0
  8. package/dist/blocks/CommandPaletteBlock.js +331 -0
  9. package/dist/blocks/CreateAccountBlock.cjs +147 -0
  10. package/dist/blocks/CreateAccountBlock.js +143 -0
  11. package/dist/blocks/EmptyStateBlock.cjs +19 -0
  12. package/dist/blocks/EmptyStateBlock.js +16 -0
  13. package/dist/blocks/FeatureOverviewBlock.cjs +54 -0
  14. package/dist/blocks/FeatureOverviewBlock.js +51 -0
  15. package/dist/blocks/HeaderBlock.cjs +230 -0
  16. package/dist/blocks/HeaderBlock.js +227 -0
  17. package/dist/blocks/KpiOverviewBlock.cjs +63 -0
  18. package/dist/blocks/KpiOverviewBlock.js +60 -0
  19. package/dist/blocks/LoginBlock.cjs +66 -0
  20. package/dist/blocks/LoginBlock.js +63 -0
  21. package/dist/blocks/NotificationsBlock.cjs +17 -0
  22. package/dist/blocks/NotificationsBlock.js +14 -0
  23. package/dist/blocks/PageHeaderBlock.cjs +121 -0
  24. package/dist/blocks/PageHeaderBlock.js +118 -0
  25. package/dist/blocks/PricingPlansBlock.cjs +146 -0
  26. package/dist/blocks/PricingPlansBlock.js +143 -0
  27. package/dist/blocks/ProductCollectionBlock.cjs +37 -0
  28. package/dist/blocks/ProductCollectionBlock.js +34 -0
  29. package/dist/blocks/ProductDetailBlock.cjs +30 -0
  30. package/dist/blocks/ProductDetailBlock.js +27 -0
  31. package/dist/blocks/ProductHeroBlock.cjs +83 -0
  32. package/dist/blocks/ProductHeroBlock.js +80 -0
  33. package/dist/blocks/ProfileSettingsBlock.cjs +130 -0
  34. package/dist/blocks/ProfileSettingsBlock.js +126 -0
  35. package/dist/blocks/QuickSendBlock.cjs +11 -0
  36. package/dist/blocks/QuickSendBlock.js +8 -0
  37. package/dist/blocks/RecentTransactionsBlock.cjs +13 -0
  38. package/dist/blocks/RecentTransactionsBlock.js +10 -0
  39. package/dist/blocks/SearchableTableBlock.cjs +91 -0
  40. package/dist/blocks/SearchableTableBlock.js +88 -0
  41. package/dist/blocks/ShoppingCartBlock.cjs +16 -0
  42. package/dist/blocks/ShoppingCartBlock.js +13 -0
  43. package/dist/blocks/SiteFooterBlock.cjs +69 -0
  44. package/dist/blocks/SiteFooterBlock.js +66 -0
  45. package/dist/blocks/TableBlock.cjs +20 -0
  46. package/dist/blocks/TableBlock.js +17 -0
  47. package/dist/blocks/TaskListBlock.cjs +198 -0
  48. package/dist/blocks/TaskListBlock.js +195 -0
  49. package/dist/blocks/WorkspaceSwitcherBlock.cjs +291 -0
  50. package/dist/blocks/WorkspaceSwitcherBlock.js +288 -0
  51. package/dist/blocks/commerce.cjs +44 -0
  52. package/dist/blocks/commerce.js +35 -0
  53. package/dist/blocks/index.cjs +53 -0
  54. package/dist/blocks/index.js +24 -0
  55. package/dist/blocks.d.cts +1820 -0
  56. package/dist/blocks.d.ts +1820 -0
  57. package/dist/chart.cjs +13 -0
  58. package/dist/chart.d.cts +59 -0
  59. package/dist/chart.d.ts +59 -0
  60. package/dist/chart.js +5 -0
  61. package/dist/components/Accordion/Accordion.cjs +94 -0
  62. package/dist/components/Accordion/Accordion.js +91 -0
  63. package/dist/components/Accordion/index.cjs +8 -0
  64. package/dist/components/Accordion/index.js +1 -0
  65. package/dist/components/ActivityFeed/ActivityContent.cjs +40 -0
  66. package/dist/components/ActivityFeed/ActivityContent.js +37 -0
  67. package/dist/components/ActivityFeed/ActivityItem.cjs +19 -0
  68. package/dist/components/ActivityFeed/ActivityItem.js +16 -0
  69. package/dist/components/ActivityFeed/index.cjs +7 -0
  70. package/dist/components/ActivityFeed/index.js +2 -0
  71. package/dist/components/Alert/Alert.cjs +42 -0
  72. package/dist/components/Alert/Alert.js +39 -0
  73. package/dist/components/Alert/index.cjs +5 -0
  74. package/dist/components/Alert/index.js +1 -0
  75. package/dist/components/Avatar/Avatar.cjs +101 -0
  76. package/dist/components/Avatar/Avatar.js +98 -0
  77. package/dist/components/Avatar/index.cjs +6 -0
  78. package/dist/components/Avatar/index.js +1 -0
  79. package/dist/components/Badge/Badge.cjs +53 -0
  80. package/dist/components/Badge/Badge.js +50 -0
  81. package/dist/components/Badge/index.cjs +5 -0
  82. package/dist/components/Badge/index.js +1 -0
  83. package/dist/components/Banner/Banner.cjs +83 -0
  84. package/dist/components/Banner/Banner.js +80 -0
  85. package/dist/components/Banner/index.cjs +5 -0
  86. package/dist/components/Banner/index.js +1 -0
  87. package/dist/components/Breadcrumb/Breadcrumb.cjs +31 -0
  88. package/dist/components/Breadcrumb/Breadcrumb.js +28 -0
  89. package/dist/components/Breadcrumb/index.cjs +5 -0
  90. package/dist/components/Breadcrumb/index.js +1 -0
  91. package/dist/components/Button/Button.cjs +88 -0
  92. package/dist/components/Button/Button.js +85 -0
  93. package/dist/components/Button/index.cjs +5 -0
  94. package/dist/components/Button/index.js +1 -0
  95. package/dist/components/ButtonGroup/ButtonGroup.cjs +8 -0
  96. package/dist/components/ButtonGroup/ButtonGroup.js +5 -0
  97. package/dist/components/ButtonGroup/ButtonGroupItem.cjs +15 -0
  98. package/dist/components/ButtonGroup/ButtonGroupItem.js +12 -0
  99. package/dist/components/ButtonGroup/index.cjs +7 -0
  100. package/dist/components/ButtonGroup/index.js +2 -0
  101. package/dist/components/Card/Card.cjs +94 -0
  102. package/dist/components/Card/Card.js +91 -0
  103. package/dist/components/Card/index.cjs +9 -0
  104. package/dist/components/Card/index.js +1 -0
  105. package/dist/components/Chart/Chart.cjs +160 -0
  106. package/dist/components/Chart/Chart.js +153 -0
  107. package/dist/components/Chart/index.cjs +10 -0
  108. package/dist/components/Chart/index.js +2 -0
  109. package/dist/components/Chart/theme.cjs +67 -0
  110. package/dist/components/Chart/theme.js +62 -0
  111. package/dist/components/Chip/Chip.cjs +18 -0
  112. package/dist/components/Chip/Chip.js +15 -0
  113. package/dist/components/Chip/index.cjs +5 -0
  114. package/dist/components/Chip/index.js +1 -0
  115. package/dist/components/Counter/Counter.cjs +74 -0
  116. package/dist/components/Counter/Counter.js +71 -0
  117. package/dist/components/Counter/index.cjs +6 -0
  118. package/dist/components/Counter/index.js +1 -0
  119. package/dist/components/DatePicker/DatePicker.cjs +343 -0
  120. package/dist/components/DatePicker/DatePicker.js +340 -0
  121. package/dist/components/DatePicker/index.cjs +5 -0
  122. package/dist/components/DatePicker/index.js +1 -0
  123. package/dist/components/Divider/Divider.cjs +31 -0
  124. package/dist/components/Divider/Divider.js +28 -0
  125. package/dist/components/Divider/index.cjs +5 -0
  126. package/dist/components/Divider/index.js +1 -0
  127. package/dist/components/DropdownMenu/DropdownMenu.cjs +108 -0
  128. package/dist/components/DropdownMenu/DropdownMenu.js +105 -0
  129. package/dist/components/DropdownMenu/index.cjs +11 -0
  130. package/dist/components/DropdownMenu/index.js +1 -0
  131. package/dist/components/EmptyStateIllustration/EmptyStateIllustration.cjs +42 -0
  132. package/dist/components/EmptyStateIllustration/EmptyStateIllustration.js +39 -0
  133. package/dist/components/EmptyStateIllustration/illustrations.cjs +3322 -0
  134. package/dist/components/EmptyStateIllustration/illustrations.js +3319 -0
  135. package/dist/components/EmptyStateIllustration/index.cjs +7 -0
  136. package/dist/components/EmptyStateIllustration/index.js +2 -0
  137. package/dist/components/FileUpload/FileUpload.cjs +116 -0
  138. package/dist/components/FileUpload/FileUpload.js +113 -0
  139. package/dist/components/FileUpload/FileUploadDropZone.cjs +58 -0
  140. package/dist/components/FileUpload/FileUploadDropZone.js +55 -0
  141. package/dist/components/FileUpload/FileUploadIcons.cjs +55 -0
  142. package/dist/components/FileUpload/FileUploadIcons.js +50 -0
  143. package/dist/components/FileUpload/FileUploadItem.cjs +34 -0
  144. package/dist/components/FileUpload/FileUploadItem.js +31 -0
  145. package/dist/components/FileUpload/index.cjs +9 -0
  146. package/dist/components/FileUpload/index.js +3 -0
  147. package/dist/components/FormControl/Checkbox.cjs +27 -0
  148. package/dist/components/FormControl/Checkbox.js +24 -0
  149. package/dist/components/FormControl/Radio.cjs +15 -0
  150. package/dist/components/FormControl/Radio.js +12 -0
  151. package/dist/components/FormControl/Toggle.cjs +15 -0
  152. package/dist/components/FormControl/Toggle.js +12 -0
  153. package/dist/components/FormControl/index.cjs +9 -0
  154. package/dist/components/FormControl/index.js +3 -0
  155. package/dist/components/Icon/Icon.cjs +70 -0
  156. package/dist/components/Icon/Icon.js +34 -0
  157. package/dist/components/Icon/catalog.cjs +1672 -0
  158. package/dist/components/Icon/catalog.js +1669 -0
  159. package/dist/components/Icon/icons.cjs +5621 -0
  160. package/dist/components/Icon/icons.js +5610 -0
  161. package/dist/components/Icon/index.cjs +8 -0
  162. package/dist/components/Icon/index.js +2 -0
  163. package/dist/components/Input/Input.cjs +64 -0
  164. package/dist/components/Input/Input.js +61 -0
  165. package/dist/components/Input/index.cjs +5 -0
  166. package/dist/components/Input/index.js +1 -0
  167. package/dist/components/MetricsCard/MetricsCard.cjs +107 -0
  168. package/dist/components/MetricsCard/MetricsCard.js +104 -0
  169. package/dist/components/MetricsCard/index.cjs +5 -0
  170. package/dist/components/MetricsCard/index.js +1 -0
  171. package/dist/components/Modal/Modal.cjs +126 -0
  172. package/dist/components/Modal/Modal.js +123 -0
  173. package/dist/components/Modal/index.cjs +5 -0
  174. package/dist/components/Modal/index.js +1 -0
  175. package/dist/components/Pagination/Pagination.cjs +42 -0
  176. package/dist/components/Pagination/Pagination.js +39 -0
  177. package/dist/components/Pagination/index.cjs +5 -0
  178. package/dist/components/Pagination/index.js +1 -0
  179. package/dist/components/ProgressBar/ProgressBar.cjs +34 -0
  180. package/dist/components/ProgressBar/ProgressBar.js +31 -0
  181. package/dist/components/ProgressBar/index.cjs +5 -0
  182. package/dist/components/ProgressBar/index.js +1 -0
  183. package/dist/components/ProgressCircle/ProgressCircle.cjs +34 -0
  184. package/dist/components/ProgressCircle/ProgressCircle.js +31 -0
  185. package/dist/components/ProgressCircle/index.cjs +5 -0
  186. package/dist/components/ProgressCircle/index.js +1 -0
  187. package/dist/components/Select/Select.cjs +84 -0
  188. package/dist/components/Select/Select.js +80 -0
  189. package/dist/components/Select/SelectOption.cjs +26 -0
  190. package/dist/components/Select/SelectOption.js +23 -0
  191. package/dist/components/Select/index.cjs +7 -0
  192. package/dist/components/Select/index.js +2 -0
  193. package/dist/components/SidebarMenu/SidebarMenu.cjs +85 -0
  194. package/dist/components/SidebarMenu/SidebarMenu.js +81 -0
  195. package/dist/components/SidebarMenu/SidebarMenuItem.cjs +126 -0
  196. package/dist/components/SidebarMenu/SidebarMenuItem.js +122 -0
  197. package/dist/components/SidebarMenu/SidebarMenuSection.cjs +14 -0
  198. package/dist/components/SidebarMenu/SidebarMenuSection.js +11 -0
  199. package/dist/components/SidebarMenu/index.cjs +12 -0
  200. package/dist/components/SidebarMenu/index.js +4 -0
  201. package/dist/components/Slider/Slider.cjs +161 -0
  202. package/dist/components/Slider/Slider.js +158 -0
  203. package/dist/components/Slider/index.cjs +6 -0
  204. package/dist/components/Slider/index.js +1 -0
  205. package/dist/components/Spinner/Spinner.cjs +93 -0
  206. package/dist/components/Spinner/Spinner.js +90 -0
  207. package/dist/components/Spinner/index.cjs +5 -0
  208. package/dist/components/Spinner/index.js +1 -0
  209. package/dist/components/Stepper/Stepper.cjs +82 -0
  210. package/dist/components/Stepper/Stepper.js +79 -0
  211. package/dist/components/Stepper/index.cjs +7 -0
  212. package/dist/components/Stepper/index.js +1 -0
  213. package/dist/components/Table/Table.cjs +25 -0
  214. package/dist/components/Table/Table.js +22 -0
  215. package/dist/components/Table/index.cjs +10 -0
  216. package/dist/components/Table/index.js +1 -0
  217. package/dist/components/Table/useTableSelection.cjs +60 -0
  218. package/dist/components/Table/useTableSelection.js +57 -0
  219. package/dist/components/Tabs/Tab.cjs +70 -0
  220. package/dist/components/Tabs/Tab.js +67 -0
  221. package/dist/components/Tabs/Tabs.cjs +133 -0
  222. package/dist/components/Tabs/Tabs.js +129 -0
  223. package/dist/components/Tabs/index.cjs +7 -0
  224. package/dist/components/Tabs/index.js +2 -0
  225. package/dist/components/Tooltip/Tooltip.cjs +101 -0
  226. package/dist/components/Tooltip/Tooltip.js +98 -0
  227. package/dist/components/Tooltip/index.cjs +5 -0
  228. package/dist/components/Tooltip/index.js +1 -0
  229. package/dist/context/ThemeContext.cjs +97 -0
  230. package/dist/context/ThemeContext.js +92 -0
  231. package/dist/fonts/README.md +13 -0
  232. package/dist/fonts/hanken-grotesk-cyrillic-ext-italic.woff2 +0 -0
  233. package/dist/fonts/hanken-grotesk-cyrillic-ext-normal.woff2 +0 -0
  234. package/dist/fonts/hanken-grotesk-latin-ext-italic.woff2 +0 -0
  235. package/dist/fonts/hanken-grotesk-latin-ext-normal.woff2 +0 -0
  236. package/dist/fonts/hanken-grotesk-latin-italic.woff2 +0 -0
  237. package/dist/fonts/hanken-grotesk-latin-normal.woff2 +0 -0
  238. package/dist/fonts/hanken-grotesk-vietnamese-italic.woff2 +0 -0
  239. package/dist/fonts/hanken-grotesk-vietnamese-normal.woff2 +0 -0
  240. package/dist/fonts/hankengrotesk-LICENSE.txt +94 -0
  241. package/dist/fonts/manrope-LICENSE.txt +93 -0
  242. package/dist/fonts/manrope-cyrillic-ext-normal.woff2 +0 -0
  243. package/dist/fonts/manrope-cyrillic-normal.woff2 +0 -0
  244. package/dist/fonts/manrope-greek-normal.woff2 +0 -0
  245. package/dist/fonts/manrope-latin-ext-normal.woff2 +0 -0
  246. package/dist/fonts/manrope-latin-normal.woff2 +0 -0
  247. package/dist/fonts/manrope-vietnamese-normal.woff2 +0 -0
  248. package/dist/fonts.css +148 -0
  249. package/dist/hooks/form/index.cjs +11 -0
  250. package/dist/hooks/form/index.js +3 -0
  251. package/dist/hooks/form/useRaydenFormControl.cjs +81 -0
  252. package/dist/hooks/form/useRaydenFormControl.js +76 -0
  253. package/dist/hooks/form/useRaydenInput.cjs +38 -0
  254. package/dist/hooks/form/useRaydenInput.js +35 -0
  255. package/dist/hooks/form/useRaydenSelect.cjs +45 -0
  256. package/dist/hooks/form/useRaydenSelect.js +42 -0
  257. package/dist/hooks/index.cjs +17 -0
  258. package/dist/hooks/index.js +1 -0
  259. package/dist/hooks/useBodyScrollLock.cjs +24 -0
  260. package/dist/hooks/useBodyScrollLock.js +21 -0
  261. package/dist/hooks/useCollisionAwareSide.cjs +72 -0
  262. package/dist/hooks/useCollisionAwareSide.js +69 -0
  263. package/dist/hooks/useControllableValue.cjs +16 -0
  264. package/dist/hooks/useControllableValue.js +13 -0
  265. package/dist/hooks/useDismissableLayer.cjs +100 -0
  266. package/dist/hooks/useDismissableLayer.js +97 -0
  267. package/dist/hooks/usePopupList.cjs +101 -0
  268. package/dist/hooks/usePopupList.js +98 -0
  269. package/dist/icons-8yD7I5jO.d.cts +430 -0
  270. package/dist/icons-8yD7I5jO.d.ts +430 -0
  271. package/dist/icons.cjs +2111 -418
  272. package/dist/icons.d.cts +1256 -429
  273. package/dist/icons.d.ts +1256 -429
  274. package/dist/icons.js +2089 -1
  275. package/dist/index.cjs +128 -15034
  276. package/dist/index.d.cts +698 -661
  277. package/dist/index.d.ts +698 -661
  278. package/dist/index.js +43 -14950
  279. package/dist/motion/Collapse.cjs +28 -0
  280. package/dist/motion/Collapse.js +25 -0
  281. package/dist/motion/MotionProvider.cjs +43 -0
  282. package/dist/motion/MotionProvider.js +38 -0
  283. package/dist/motion/Pressable.cjs +46 -0
  284. package/dist/motion/Pressable.js +43 -0
  285. package/dist/motion/Reveal.cjs +19 -0
  286. package/dist/motion/Reveal.js +16 -0
  287. package/dist/motion/SharedLayout.cjs +46 -0
  288. package/dist/motion/SharedLayout.js +43 -0
  289. package/dist/motion/index.cjs +19 -0
  290. package/dist/motion/index.js +6 -0
  291. package/dist/motion/presence.cjs +58 -0
  292. package/dist/motion/presence.js +55 -0
  293. package/dist/motion/presets.cjs +88 -0
  294. package/dist/motion/presets.js +84 -0
  295. package/dist/motion.d.cts +51 -0
  296. package/dist/motion.d.ts +51 -0
  297. package/dist/preset.cjs +356 -195
  298. package/dist/preset.d.cts +111 -32
  299. package/dist/preset.d.ts +111 -32
  300. package/dist/preset.js +353 -187
  301. package/dist/presets-Ba5QndHg.d.cts +144 -0
  302. package/dist/presets-Ba5QndHg.d.ts +144 -0
  303. package/dist/styles.css +1 -1
  304. package/dist/utils/cn.cjs +38 -0
  305. package/dist/utils/cn.js +35 -0
  306. package/dist/utils/resolveIcon.cjs +18 -0
  307. package/dist/utils/resolveIcon.js +15 -0
  308. package/package.json +79 -21
@@ -0,0 +1,79 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { forwardRef } from "react";
3
+ import { cn } from "../../utils/cn.js";
4
+ /* ─── Icons ────────────────────────────────────────────────────────────── */
5
+ function CheckIcon({ className }) {
6
+ return (_jsx("svg", { className: className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 3, strokeLinecap: "round", strokeLinejoin: "round", children: _jsx("path", { d: "M5 12l5 5L20 7" }) }));
7
+ }
8
+ /* ─── Step Indicator Circle ────────────────────────────────────────────── */
9
+ const statusText = {
10
+ completed: "Completed",
11
+ active: "Current step",
12
+ incomplete: "Not started",
13
+ disabled: "Unavailable",
14
+ };
15
+ function StepCircle({ status, indicator, stepNumber, icon, }) {
16
+ const isCompleted = status === "completed";
17
+ const isActive = status === "active";
18
+ const isDisabled = status === "disabled";
19
+ return (_jsxs("div", { className: cn("shrink-0 flex items-center justify-center rounded-full size-6 border transition-colors", isCompleted && "bg-action-primary border-action-primary text-white", isActive && "bg-primary-50 border-primary-400 text-action-primary-text", !isCompleted && !isActive && !isDisabled && "bg-surface border-grey-300", isDisabled && "bg-grey-100 border-grey-200 text-grey-300"), children: [_jsx("span", { className: "sr-only", children: statusText[status] }), isCompleted ? ((icon ?? _jsx(CheckIcon, { className: "size-3.5" }))) : indicator === "dot" ? (_jsx("div", { className: cn("size-2 rounded-full border", isActive
20
+ ? "bg-primary-400 border-primary-400"
21
+ : isDisabled
22
+ ? "bg-grey-300 border-grey-300"
23
+ : "bg-grey-400 border-grey-300") })) : indicator === "number" ? (_jsx("span", { className: cn("text-xs font-medium", isActive ? "text-primary-400" : isDisabled ? "text-grey-300" : "text-on-surface-muted"), children: stepNumber })) : ((icon ?? (_jsx("div", { className: cn("size-2 rounded-full", isActive ? "bg-primary-400" : isDisabled ? "bg-grey-300" : "bg-grey-400") }))))] }));
24
+ }
25
+ /* ─── Connector Line ───────────────────────────────────────────────────── */
26
+ function Connector({ orientation, completed, }) {
27
+ return orientation === "horizontal" ? (_jsx("div", { className: cn("flex-1 h-0.5 rounded-full", completed ? "bg-primary-400" : "bg-grey-300") })) : (_jsx("div", { className: cn("w-0.5 flex-1 min-h-[20px] ml-[11px] rounded-full", completed ? "bg-primary-400" : "bg-grey-300") }));
28
+ }
29
+ /* ─── Stepper ──────────────────────────────────────────────────────────── */
30
+ function resolveStatuses(steps, activeStep) {
31
+ if (activeStep !== undefined) {
32
+ return steps.map((s, i) => {
33
+ if (s.status === "disabled")
34
+ return "disabled";
35
+ if (i < activeStep)
36
+ return "completed";
37
+ if (i === activeStep)
38
+ return "active";
39
+ return "incomplete";
40
+ });
41
+ }
42
+ return steps.map((s) => s.status ?? "incomplete");
43
+ }
44
+ export const Stepper = forwardRef(({ steps, activeStep, orientation = "horizontal", indicator = "dot", className, ...rest }, ref) => {
45
+ const statuses = resolveStatuses(steps, activeStep);
46
+ if (orientation === "vertical") {
47
+ return (_jsx("div", { ref: ref, className: cn("flex flex-col", className), ...rest, children: steps.map((step, i) => {
48
+ const status = statuses[i];
49
+ const isLast = i === steps.length - 1;
50
+ return (_jsxs("div", { className: "flex gap-3", children: [_jsxs("div", { className: "flex flex-col items-center", children: [_jsx(StepCircle, { status: status, indicator: indicator, stepNumber: i + 1, icon: step.icon }), !isLast && (_jsx(Connector, { orientation: "vertical", completed: status === "completed" }))] }), _jsxs("div", { className: "flex flex-col pb-6", children: [_jsx("span", { className: cn("text-sm font-medium leading-[1.45]", status === "active"
51
+ ? "text-on-surface"
52
+ : status === "disabled"
53
+ ? "text-grey-300"
54
+ : "text-on-surface-secondary"), children: step.title }), step.description && (_jsx("span", { className: "text-xs text-on-surface-muted leading-[1.45]", children: step.description }))] })] }, i));
55
+ }) }));
56
+ }
57
+ // Horizontal
58
+ return (_jsx("div", { ref: ref, className: cn("flex items-start w-full", className), ...rest, children: steps.map((step, i) => {
59
+ const status = statuses[i];
60
+ const isLast = i === steps.length - 1;
61
+ return (_jsxs("div", { className: "flex flex-col flex-1 items-center gap-2.5", children: [_jsxs("div", { className: "flex items-center gap-1 w-full", children: [_jsx(Connector, { orientation: "horizontal", completed: i > 0 && statuses[i - 1] === "completed" }), _jsx(StepCircle, { status: status, indicator: indicator, stepNumber: i + 1, icon: step.icon }), _jsx(Connector, { orientation: "horizontal", completed: !isLast && status === "completed" })] }), _jsxs("div", { className: "flex flex-col gap-0.5 text-center w-full", children: [_jsx("span", { className: cn("text-xs font-medium leading-[1.45] tracking-tight", status === "active"
62
+ ? "text-on-surface-body"
63
+ : status === "disabled"
64
+ ? "text-grey-300"
65
+ : "text-on-surface-secondary"), children: step.title }), step.description && (_jsx("span", { className: "text-xs text-on-surface-muted leading-[1.45] truncate", children: step.description }))] })] }, i));
66
+ }) }));
67
+ });
68
+ Stepper.displayName = "Stepper";
69
+ /* ─── LinearStepper ────────────────────────────────────────────────────── */
70
+ export const LinearStepper = forwardRef(({ currentStep, totalSteps, showLabel = true, className, ...rest }, ref) => {
71
+ const pct = Math.min(100, Math.max(0, (currentStep / totalSteps) * 100));
72
+ return (_jsxs("div", { ref: ref, className: cn("flex flex-col gap-2 w-full", className), ...rest, children: [showLabel && (_jsxs("p", { className: "text-sm font-semibold leading-[1.45]", children: [_jsx("span", { className: "text-on-surface", children: currentStep }), _jsxs("span", { className: "text-on-surface-muted", children: [" / ", totalSteps, " complete"] })] })), _jsx("div", { className: "bg-grey-200 rounded-full p-1 w-full overflow-hidden", role: "progressbar", "aria-valuenow": currentStep, "aria-valuemin": 0, "aria-valuemax": totalSteps, "aria-valuetext": `Step ${currentStep} of ${totalSteps}`, "aria-label": "Progress", children: _jsx("div", { className: "h-2 bg-primary-400 rounded-[10px] transition-all duration-300", style: { width: `${pct}%` } }) })] }));
73
+ });
74
+ LinearStepper.displayName = "LinearStepper";
75
+ /* ─── SegmentedStepper ─────────────────────────────────────────────────── */
76
+ export const SegmentedStepper = forwardRef(({ currentStep, totalSteps, showLabel = true, className, ...rest }, ref) => {
77
+ return (_jsxs("div", { ref: ref, className: cn("flex flex-col gap-2 w-full", className), ...rest, children: [showLabel && (_jsxs("p", { className: "text-sm font-semibold leading-[1.45]", children: [_jsx("span", { className: "text-on-surface", children: currentStep }), _jsxs("span", { className: "text-on-surface-muted", children: [" / ", totalSteps, " complete"] })] })), _jsx("div", { className: "bg-grey-200 rounded-full p-1 w-full overflow-hidden", role: "progressbar", "aria-valuenow": currentStep, "aria-valuemin": 0, "aria-valuemax": totalSteps, "aria-valuetext": `Step ${currentStep} of ${totalSteps}`, "aria-label": "Progress", children: _jsx("div", { className: "flex gap-1 h-2 w-full", children: Array.from({ length: totalSteps }, (_, i) => (_jsx("div", { className: cn("flex-1 rounded-[14px] border border-grey-50 transition-colors", i < currentStep ? "bg-primary-400" : "bg-grey-50") }, i))) }) })] }));
78
+ });
79
+ SegmentedStepper.displayName = "SegmentedStepper";
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SegmentedStepper = exports.LinearStepper = exports.Stepper = void 0;
4
+ var Stepper_1 = require("./Stepper.cjs");
5
+ Object.defineProperty(exports, "Stepper", { enumerable: true, get: function () { return Stepper_1.Stepper; } });
6
+ Object.defineProperty(exports, "LinearStepper", { enumerable: true, get: function () { return Stepper_1.LinearStepper; } });
7
+ Object.defineProperty(exports, "SegmentedStepper", { enumerable: true, get: function () { return Stepper_1.SegmentedStepper; } });
@@ -0,0 +1 @@
1
+ export { Stepper, LinearStepper, SegmentedStepper } from "./Stepper.js";
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TableCell = exports.TableHead = exports.TableRow = exports.TableBody = exports.TableHeader = exports.Table = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const cn_1 = require("../../utils/cn.cjs");
7
+ const Icon_1 = require("../Icon/index.cjs");
8
+ exports.Table = (0, react_1.forwardRef)(({ className, ...rest }, ref) => ((0, jsx_runtime_1.jsx)("div", { role: "region", "aria-label": rest["aria-label"] ?? "Data table", tabIndex: 0,
9
+ // `relative` is load-bearing, not decoration. It makes this scroller the containing
10
+ // block for absolutely positioned descendants — above all the `sr-only` headings that
11
+ // label icon-only columns. Without it those resolve against the initial containing
12
+ // block, so their overflow widens the *document* instead of this element's own scroll
13
+ // area, and a correctly bounded table still drags the whole page sideways at 320px.
14
+ className: "relative w-full min-w-0 max-w-full overflow-x-auto rounded focus-visible:outline-2 focus-visible:outline-action-primary-text", children: (0, jsx_runtime_1.jsx)("table", { ref: ref, className: (0, cn_1.cn)("w-full border-collapse", className), ...rest }) })));
15
+ exports.Table.displayName = "Table";
16
+ exports.TableHeader = (0, react_1.forwardRef)(({ className, ...rest }, ref) => (0, jsx_runtime_1.jsx)("thead", { ref: ref, className: (0, cn_1.cn)("", className), ...rest }));
17
+ exports.TableHeader.displayName = "TableHeader";
18
+ exports.TableBody = (0, react_1.forwardRef)(({ className, ...rest }, ref) => (0, jsx_runtime_1.jsx)("tbody", { ref: ref, className: (0, cn_1.cn)("", className), ...rest }));
19
+ exports.TableBody.displayName = "TableBody";
20
+ exports.TableRow = (0, react_1.forwardRef)(({ selected = false, className, ...rest }, ref) => ((0, jsx_runtime_1.jsx)("tr", { ref: ref, "aria-selected": selected || undefined, className: (0, cn_1.cn)("transition-colors", selected ? "bg-primary-50" : "bg-surface", className), ...rest })));
21
+ exports.TableRow.displayName = "TableRow";
22
+ exports.TableHead = (0, react_1.forwardRef)(({ sortable = false, sortDirection, onSort, children, className, ...rest }, ref) => ((0, jsx_runtime_1.jsx)("th", { ref: ref, scope: "col", "aria-sort": sortDirection === "asc" ? "ascending" : sortDirection === "desc" ? "descending" : undefined, className: (0, cn_1.cn)("h-11 px-6 py-3 text-left text-body-xs font-medium text-on-surface-body border-b border-grey-200", "bg-surface hover:bg-grey-50 transition-colors", sortable && "cursor-pointer select-none", className), ...rest, children: sortable ? ((0, jsx_runtime_1.jsxs)("button", { type: "button", onClick: onSort, className: "flex w-full items-center gap-1 rounded text-left focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-action-primary-text", children: [children, sortable && ((0, jsx_runtime_1.jsx)(Icon_1.Icon, { name: sortDirection === "asc" ? "chevron-up" : "chevron-down", size: "sm", "aria-hidden": "true", className: (0, cn_1.cn)("shrink-0", sortDirection ? "text-on-surface-body" : "text-on-surface-muted") }))] })) : (children) })));
23
+ exports.TableHead.displayName = "TableHead";
24
+ exports.TableCell = (0, react_1.forwardRef)(({ className, ...rest }, ref) => ((0, jsx_runtime_1.jsx)("td", { ref: ref, className: (0, cn_1.cn)("h-[72px] px-6 py-4 border-b border-grey-200 text-body-sm text-on-surface", className), ...rest })));
25
+ exports.TableCell.displayName = "TableCell";
@@ -0,0 +1,22 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { forwardRef, } from "react";
3
+ import { cn } from "../../utils/cn.js";
4
+ import { Icon } from "../Icon/index.js";
5
+ export const Table = forwardRef(({ className, ...rest }, ref) => (_jsx("div", { role: "region", "aria-label": rest["aria-label"] ?? "Data table", tabIndex: 0,
6
+ // `relative` is load-bearing, not decoration. It makes this scroller the containing
7
+ // block for absolutely positioned descendants — above all the `sr-only` headings that
8
+ // label icon-only columns. Without it those resolve against the initial containing
9
+ // block, so their overflow widens the *document* instead of this element's own scroll
10
+ // area, and a correctly bounded table still drags the whole page sideways at 320px.
11
+ className: "relative w-full min-w-0 max-w-full overflow-x-auto rounded focus-visible:outline-2 focus-visible:outline-action-primary-text", children: _jsx("table", { ref: ref, className: cn("w-full border-collapse", className), ...rest }) })));
12
+ Table.displayName = "Table";
13
+ export const TableHeader = forwardRef(({ className, ...rest }, ref) => _jsx("thead", { ref: ref, className: cn("", className), ...rest }));
14
+ TableHeader.displayName = "TableHeader";
15
+ export const TableBody = forwardRef(({ className, ...rest }, ref) => _jsx("tbody", { ref: ref, className: cn("", className), ...rest }));
16
+ TableBody.displayName = "TableBody";
17
+ export const TableRow = forwardRef(({ selected = false, className, ...rest }, ref) => (_jsx("tr", { ref: ref, "aria-selected": selected || undefined, className: cn("transition-colors", selected ? "bg-primary-50" : "bg-surface", className), ...rest })));
18
+ TableRow.displayName = "TableRow";
19
+ export const TableHead = forwardRef(({ sortable = false, sortDirection, onSort, children, className, ...rest }, ref) => (_jsx("th", { ref: ref, scope: "col", "aria-sort": sortDirection === "asc" ? "ascending" : sortDirection === "desc" ? "descending" : undefined, className: cn("h-11 px-6 py-3 text-left text-body-xs font-medium text-on-surface-body border-b border-grey-200", "bg-surface hover:bg-grey-50 transition-colors", sortable && "cursor-pointer select-none", className), ...rest, children: sortable ? (_jsxs("button", { type: "button", onClick: onSort, className: "flex w-full items-center gap-1 rounded text-left focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-action-primary-text", children: [children, sortable && (_jsx(Icon, { name: sortDirection === "asc" ? "chevron-up" : "chevron-down", size: "sm", "aria-hidden": "true", className: cn("shrink-0", sortDirection ? "text-on-surface-body" : "text-on-surface-muted") }))] })) : (children) })));
20
+ TableHead.displayName = "TableHead";
21
+ export const TableCell = forwardRef(({ className, ...rest }, ref) => (_jsx("td", { ref: ref, className: cn("h-[72px] px-6 py-4 border-b border-grey-200 text-body-sm text-on-surface", className), ...rest })));
22
+ TableCell.displayName = "TableCell";
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TableCell = exports.TableHead = exports.TableRow = exports.TableBody = exports.TableHeader = exports.Table = void 0;
4
+ var Table_1 = require("./Table.cjs");
5
+ Object.defineProperty(exports, "Table", { enumerable: true, get: function () { return Table_1.Table; } });
6
+ Object.defineProperty(exports, "TableHeader", { enumerable: true, get: function () { return Table_1.TableHeader; } });
7
+ Object.defineProperty(exports, "TableBody", { enumerable: true, get: function () { return Table_1.TableBody; } });
8
+ Object.defineProperty(exports, "TableRow", { enumerable: true, get: function () { return Table_1.TableRow; } });
9
+ Object.defineProperty(exports, "TableHead", { enumerable: true, get: function () { return Table_1.TableHead; } });
10
+ Object.defineProperty(exports, "TableCell", { enumerable: true, get: function () { return Table_1.TableCell; } });
@@ -0,0 +1 @@
1
+ export { Table, TableHeader, TableBody, TableRow, TableHead, TableCell } from "./Table.js";
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useTableSelection = useTableSelection;
4
+ const react_1 = require("react");
5
+ const EMPTY = [];
6
+ const KEY_SEPARATOR = "\u0000";
7
+ function useTableSelection({ dataIds, scopeIds = dataIds, selectedIds, onSelectionChange, }) {
8
+ const isControlled = selectedIds !== undefined;
9
+ const dataKey = dataIds.join(KEY_SEPARATOR);
10
+ const [state, setState] = (0, react_1.useState)(() => ({
11
+ key: dataKey,
12
+ ids: EMPTY,
13
+ }));
14
+ // Ids dropped by reconciliation are announced from an effect: the prune itself happens
15
+ // during render, where calling a consumer's handler would be a side effect.
16
+ const pendingEmit = (0, react_1.useRef)(null);
17
+ const notify = (0, react_1.useRef)(onSelectionChange);
18
+ notify.current = onSelectionChange;
19
+ let stored = state.ids;
20
+ if (!isControlled && state.key !== dataKey) {
21
+ // Adjust state during render rather than in an effect, so this render already shows
22
+ // the reconciled selection: React re-runs the component before committing.
23
+ const present = new Set(dataIds);
24
+ const pruned = stored.filter((id) => present.has(id));
25
+ if (pruned.length !== stored.length) {
26
+ stored = pruned;
27
+ pendingEmit.current = pruned;
28
+ }
29
+ setState({ key: dataKey, ids: stored });
30
+ }
31
+ (0, react_1.useEffect)(() => {
32
+ const dropped = pendingEmit.current;
33
+ if (!dropped)
34
+ return;
35
+ pendingEmit.current = null;
36
+ notify.current?.(dropped);
37
+ });
38
+ const current = isControlled ? selectedIds : stored;
39
+ const currentSet = new Set(current);
40
+ const scopeSet = new Set(scopeIds);
41
+ const allSelected = scopeIds.length > 0 && scopeIds.every((id) => currentSet.has(id));
42
+ const someSelected = !allSelected && scopeIds.some((id) => currentSet.has(id));
43
+ const commit = (next) => {
44
+ // This change is already being announced, so the reconciliation effect must not
45
+ // announce it a second time.
46
+ pendingEmit.current = null;
47
+ if (!isControlled)
48
+ setState({ key: dataKey, ids: next });
49
+ onSelectionChange?.(next);
50
+ };
51
+ return {
52
+ allSelected,
53
+ someSelected,
54
+ isSelected: (id) => currentSet.has(id),
55
+ toggleRow: (id) => commit(currentSet.has(id) ? current.filter((x) => x !== id) : [...current, id]),
56
+ toggleAll: () => commit(allSelected
57
+ ? current.filter((id) => !scopeSet.has(id))
58
+ : [...current, ...scopeIds.filter((id) => !currentSet.has(id))]),
59
+ };
60
+ }
@@ -0,0 +1,57 @@
1
+ import { useEffect, useRef, useState } from "react";
2
+ const EMPTY = [];
3
+ const KEY_SEPARATOR = "\u0000";
4
+ export function useTableSelection({ dataIds, scopeIds = dataIds, selectedIds, onSelectionChange, }) {
5
+ const isControlled = selectedIds !== undefined;
6
+ const dataKey = dataIds.join(KEY_SEPARATOR);
7
+ const [state, setState] = useState(() => ({
8
+ key: dataKey,
9
+ ids: EMPTY,
10
+ }));
11
+ // Ids dropped by reconciliation are announced from an effect: the prune itself happens
12
+ // during render, where calling a consumer's handler would be a side effect.
13
+ const pendingEmit = useRef(null);
14
+ const notify = useRef(onSelectionChange);
15
+ notify.current = onSelectionChange;
16
+ let stored = state.ids;
17
+ if (!isControlled && state.key !== dataKey) {
18
+ // Adjust state during render rather than in an effect, so this render already shows
19
+ // the reconciled selection: React re-runs the component before committing.
20
+ const present = new Set(dataIds);
21
+ const pruned = stored.filter((id) => present.has(id));
22
+ if (pruned.length !== stored.length) {
23
+ stored = pruned;
24
+ pendingEmit.current = pruned;
25
+ }
26
+ setState({ key: dataKey, ids: stored });
27
+ }
28
+ useEffect(() => {
29
+ const dropped = pendingEmit.current;
30
+ if (!dropped)
31
+ return;
32
+ pendingEmit.current = null;
33
+ notify.current?.(dropped);
34
+ });
35
+ const current = isControlled ? selectedIds : stored;
36
+ const currentSet = new Set(current);
37
+ const scopeSet = new Set(scopeIds);
38
+ const allSelected = scopeIds.length > 0 && scopeIds.every((id) => currentSet.has(id));
39
+ const someSelected = !allSelected && scopeIds.some((id) => currentSet.has(id));
40
+ const commit = (next) => {
41
+ // This change is already being announced, so the reconciliation effect must not
42
+ // announce it a second time.
43
+ pendingEmit.current = null;
44
+ if (!isControlled)
45
+ setState({ key: dataKey, ids: next });
46
+ onSelectionChange?.(next);
47
+ };
48
+ return {
49
+ allSelected,
50
+ someSelected,
51
+ isSelected: (id) => currentSet.has(id),
52
+ toggleRow: (id) => commit(currentSet.has(id) ? current.filter((x) => x !== id) : [...current, id]),
53
+ toggleAll: () => commit(allSelected
54
+ ? current.filter((id) => !scopeSet.has(id))
55
+ : [...current, ...scopeIds.filter((id) => !currentSet.has(id))]),
56
+ };
57
+ }
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Tab = Tab;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const cn_1 = require("../../utils/cn.cjs");
7
+ const resolveIcon_1 = require("../../utils/resolveIcon.cjs");
8
+ const Tabs_1 = require("./Tabs.cjs");
9
+ /* ─── Size mappings ────────────────────────────────────────────────────── */
10
+ const textSize = { sm: "text-xs", md: "text-sm", lg: "text-base" };
11
+ const iconSize = { sm: "size-4", md: "size-5", lg: "size-6" };
12
+ const iconResolveSize = { sm: "sm", md: "md", lg: "md" };
13
+ const badgeText = { sm: "text-xs", md: "text-xs", lg: "text-sm" };
14
+ const linePadding = {
15
+ sm: "px-2 pt-1 pb-1.5",
16
+ md: "px-3 pt-1.5 pb-2",
17
+ lg: "px-4 pt-2 pb-2.5",
18
+ };
19
+ const pillPadding = {
20
+ sm: "px-2 py-1",
21
+ md: "px-3 py-1.5",
22
+ lg: "px-4 py-2",
23
+ };
24
+ const segmentedPadding = {
25
+ sm: "px-2 py-1",
26
+ md: "px-3 py-1.5",
27
+ lg: "px-4 py-2",
28
+ };
29
+ function Tab({ value, icon, badge, disabled = false, children, className }) {
30
+ const { activeValue, onSelect, variant, size, orientation, registerTab, motion } = (0, Tabs_1.useTabsContext)();
31
+ const isActive = activeValue === value;
32
+ const buttonRef = (0, react_1.useRef)(null);
33
+ const isVertical = orientation === "vertical";
34
+ (0, react_1.useEffect)(() => {
35
+ registerTab(value, buttonRef.current);
36
+ return () => registerTab(value, null);
37
+ }, [value, registerTab]);
38
+ const resolvedIcon = icon ? ((0, jsx_runtime_1.jsx)("span", { className: (0, cn_1.cn)("shrink-0", iconSize[size]), children: (0, resolveIcon_1.resolveIcon)(icon, iconResolveSize[size]) })) : null;
39
+ const badgeEl = badge !== undefined ? ((0, jsx_runtime_1.jsx)("span", { className: (0, cn_1.cn)("inline-flex items-center justify-center px-1.5 rounded-full font-medium tracking-tight", badgeText[size], variant === "segmented" && isActive
40
+ ? "bg-action-primary text-white"
41
+ : isActive
42
+ ? motion
43
+ ? "text-action-primary-text"
44
+ : "bg-primary-50 text-action-primary-text"
45
+ : disabled
46
+ ? "bg-grey-200 text-grey-500"
47
+ : "bg-grey-100 text-grey-600"), children: badge })) : null;
48
+ /* ── Segmented ── */
49
+ if (variant === "segmented") {
50
+ return ((0, jsx_runtime_1.jsxs)("button", { ref: buttonRef, type: "button", role: "tab", "aria-selected": isActive, tabIndex: isActive ? 0 : -1, disabled: disabled, onClick: () => !disabled && onSelect(value), className: (0, cn_1.cn)("inline-flex items-center gap-1.5 rounded-md overflow-hidden transition-colors cursor-pointer focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-action-primary-text", motion && "relative z-[1]", segmentedPadding[size], textSize[size], isActive
51
+ ? motion
52
+ ? "text-grey-900"
53
+ : "bg-primary-50 text-grey-900"
54
+ : disabled
55
+ ? "text-grey-300 cursor-not-allowed"
56
+ : "text-grey-500 hover:bg-grey-50", className), children: [resolvedIcon, (0, jsx_runtime_1.jsx)("span", { className: "font-normal leading-[1.45] whitespace-nowrap", children: children }), badgeEl] }));
57
+ }
58
+ /* ── Pill ── */
59
+ if (variant === "pill") {
60
+ return ((0, jsx_runtime_1.jsxs)("button", { ref: buttonRef, type: "button", role: "tab", "aria-selected": isActive, tabIndex: isActive ? 0 : -1, disabled: disabled, onClick: () => !disabled && onSelect(value), className: (0, cn_1.cn)("inline-flex items-center gap-1.5 rounded-full transition-colors cursor-pointer focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-action-primary-text", motion && "relative z-[1]", pillPadding[size], textSize[size], isActive
61
+ ? motion
62
+ ? "text-action-primary-text"
63
+ : "bg-primary-50 text-action-primary-text"
64
+ : disabled
65
+ ? "text-grey-300 cursor-not-allowed"
66
+ : "text-grey-500 hover:bg-grey-50", className), children: [resolvedIcon, (0, jsx_runtime_1.jsx)("span", { className: "font-normal leading-[1.45] whitespace-nowrap", children: children }), badgeEl] }));
67
+ }
68
+ /* ── Line (default) ── */
69
+ return ((0, jsx_runtime_1.jsxs)("button", { ref: buttonRef, type: "button", role: "tab", "aria-selected": isActive, tabIndex: isActive ? 0 : -1, disabled: disabled, onClick: () => !disabled && onSelect(value), className: (0, cn_1.cn)("relative inline-flex cursor-pointer rounded focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-action-primary-text", isVertical ? "flex-row" : "flex-col items-center", disabled && "cursor-not-allowed", className), children: [(0, jsx_runtime_1.jsxs)("div", { className: (0, cn_1.cn)("flex items-center gap-1.5", linePadding[size]), children: [resolvedIcon, (0, jsx_runtime_1.jsx)("span", { className: (0, cn_1.cn)("font-normal leading-[1.45] whitespace-nowrap transition-colors", textSize[size], isActive ? "text-grey-900" : disabled ? "text-grey-300" : "text-grey-500"), children: children }), badgeEl] }), isVertical ? ((0, jsx_runtime_1.jsx)("div", { className: (0, cn_1.cn)("w-0.5 self-stretch transition-colors", isActive ? (motion ? "bg-transparent" : "bg-primary-400") : "bg-grey-100") })) : ((0, jsx_runtime_1.jsx)("div", { className: (0, cn_1.cn)("h-0.5 w-full transition-colors", isActive ? (motion ? "bg-transparent" : "bg-primary-400") : "bg-grey-100") }))] }));
70
+ }
@@ -0,0 +1,67 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useRef } from "react";
3
+ import { cn } from "../../utils/cn.js";
4
+ import { resolveIcon } from "../../utils/resolveIcon.js";
5
+ import { useTabsContext } from "./Tabs.js";
6
+ /* ─── Size mappings ────────────────────────────────────────────────────── */
7
+ const textSize = { sm: "text-xs", md: "text-sm", lg: "text-base" };
8
+ const iconSize = { sm: "size-4", md: "size-5", lg: "size-6" };
9
+ const iconResolveSize = { sm: "sm", md: "md", lg: "md" };
10
+ const badgeText = { sm: "text-xs", md: "text-xs", lg: "text-sm" };
11
+ const linePadding = {
12
+ sm: "px-2 pt-1 pb-1.5",
13
+ md: "px-3 pt-1.5 pb-2",
14
+ lg: "px-4 pt-2 pb-2.5",
15
+ };
16
+ const pillPadding = {
17
+ sm: "px-2 py-1",
18
+ md: "px-3 py-1.5",
19
+ lg: "px-4 py-2",
20
+ };
21
+ const segmentedPadding = {
22
+ sm: "px-2 py-1",
23
+ md: "px-3 py-1.5",
24
+ lg: "px-4 py-2",
25
+ };
26
+ export function Tab({ value, icon, badge, disabled = false, children, className }) {
27
+ const { activeValue, onSelect, variant, size, orientation, registerTab, motion } = useTabsContext();
28
+ const isActive = activeValue === value;
29
+ const buttonRef = useRef(null);
30
+ const isVertical = orientation === "vertical";
31
+ useEffect(() => {
32
+ registerTab(value, buttonRef.current);
33
+ return () => registerTab(value, null);
34
+ }, [value, registerTab]);
35
+ const resolvedIcon = icon ? (_jsx("span", { className: cn("shrink-0", iconSize[size]), children: resolveIcon(icon, iconResolveSize[size]) })) : null;
36
+ const badgeEl = badge !== undefined ? (_jsx("span", { className: cn("inline-flex items-center justify-center px-1.5 rounded-full font-medium tracking-tight", badgeText[size], variant === "segmented" && isActive
37
+ ? "bg-action-primary text-white"
38
+ : isActive
39
+ ? motion
40
+ ? "text-action-primary-text"
41
+ : "bg-primary-50 text-action-primary-text"
42
+ : disabled
43
+ ? "bg-grey-200 text-grey-500"
44
+ : "bg-grey-100 text-grey-600"), children: badge })) : null;
45
+ /* ── Segmented ── */
46
+ if (variant === "segmented") {
47
+ return (_jsxs("button", { ref: buttonRef, type: "button", role: "tab", "aria-selected": isActive, tabIndex: isActive ? 0 : -1, disabled: disabled, onClick: () => !disabled && onSelect(value), className: cn("inline-flex items-center gap-1.5 rounded-md overflow-hidden transition-colors cursor-pointer focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-action-primary-text", motion && "relative z-[1]", segmentedPadding[size], textSize[size], isActive
48
+ ? motion
49
+ ? "text-grey-900"
50
+ : "bg-primary-50 text-grey-900"
51
+ : disabled
52
+ ? "text-grey-300 cursor-not-allowed"
53
+ : "text-grey-500 hover:bg-grey-50", className), children: [resolvedIcon, _jsx("span", { className: "font-normal leading-[1.45] whitespace-nowrap", children: children }), badgeEl] }));
54
+ }
55
+ /* ── Pill ── */
56
+ if (variant === "pill") {
57
+ return (_jsxs("button", { ref: buttonRef, type: "button", role: "tab", "aria-selected": isActive, tabIndex: isActive ? 0 : -1, disabled: disabled, onClick: () => !disabled && onSelect(value), className: cn("inline-flex items-center gap-1.5 rounded-full transition-colors cursor-pointer focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-action-primary-text", motion && "relative z-[1]", pillPadding[size], textSize[size], isActive
58
+ ? motion
59
+ ? "text-action-primary-text"
60
+ : "bg-primary-50 text-action-primary-text"
61
+ : disabled
62
+ ? "text-grey-300 cursor-not-allowed"
63
+ : "text-grey-500 hover:bg-grey-50", className), children: [resolvedIcon, _jsx("span", { className: "font-normal leading-[1.45] whitespace-nowrap", children: children }), badgeEl] }));
64
+ }
65
+ /* ── Line (default) ── */
66
+ return (_jsxs("button", { ref: buttonRef, type: "button", role: "tab", "aria-selected": isActive, tabIndex: isActive ? 0 : -1, disabled: disabled, onClick: () => !disabled && onSelect(value), className: cn("relative inline-flex cursor-pointer rounded focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-action-primary-text", isVertical ? "flex-row" : "flex-col items-center", disabled && "cursor-not-allowed", className), children: [_jsxs("div", { className: cn("flex items-center gap-1.5", linePadding[size]), children: [resolvedIcon, _jsx("span", { className: cn("font-normal leading-[1.45] whitespace-nowrap transition-colors", textSize[size], isActive ? "text-grey-900" : disabled ? "text-grey-300" : "text-grey-500"), children: children }), badgeEl] }), isVertical ? (_jsx("div", { className: cn("w-0.5 self-stretch transition-colors", isActive ? (motion ? "bg-transparent" : "bg-primary-400") : "bg-grey-100") })) : (_jsx("div", { className: cn("h-0.5 w-full transition-colors", isActive ? (motion ? "bg-transparent" : "bg-primary-400") : "bg-grey-100") }))] }));
67
+ }
@@ -0,0 +1,133 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useTabsContext = useTabsContext;
4
+ exports.Tabs = Tabs;
5
+ const jsx_runtime_1 = require("react/jsx-runtime");
6
+ const react_1 = require("react");
7
+ const cn_1 = require("../../utils/cn.cjs");
8
+ const SharedLayout_1 = require("../../motion/SharedLayout.cjs");
9
+ const MotionProvider_1 = require("../../motion/MotionProvider.cjs");
10
+ const useBrowserLayoutEffect = typeof window === "undefined" ? react_1.useEffect : react_1.useLayoutEffect;
11
+ const TabsContext = (0, react_1.createContext)(null);
12
+ function useTabsContext() {
13
+ const ctx = (0, react_1.useContext)(TabsContext);
14
+ if (!ctx)
15
+ throw new Error("Tab must be used within Tabs");
16
+ return ctx;
17
+ }
18
+ function Tabs({ motion = false, variant = "line", size = "sm", orientation = "horizontal", value, defaultValue = "", onValueChange, children, className, }) {
19
+ const listRef = (0, react_1.useRef)(null);
20
+ const [indicator, setIndicator] = (0, react_1.useState)(null);
21
+ const { preset } = (0, MotionProvider_1.useRaydenMotion)(motion);
22
+ const [internalValue, setInternalValue] = (0, react_1.useState)(defaultValue);
23
+ const enabledValues = [];
24
+ function collect(nodes) {
25
+ react_1.Children.forEach(nodes, (node) => {
26
+ if (!(0, react_1.isValidElement)(node))
27
+ return;
28
+ if (typeof node.props.value === "string") {
29
+ if (!node.props.disabled)
30
+ enabledValues.push(node.props.value);
31
+ }
32
+ else if (node.props.children)
33
+ collect(node.props.children);
34
+ });
35
+ }
36
+ collect(children);
37
+ const requestedValue = value ?? internalValue;
38
+ const activeValue = enabledValues.includes(requestedValue)
39
+ ? requestedValue
40
+ : (enabledValues[0] ?? "");
41
+ const tabsRef = (0, react_1.useRef)(new Map());
42
+ const onSelect = (0, react_1.useCallback)((val) => {
43
+ if (value === undefined)
44
+ setInternalValue(val);
45
+ onValueChange?.(val);
46
+ }, [value, onValueChange]);
47
+ const registerTab = (0, react_1.useCallback)((tabValue, element) => {
48
+ if (element) {
49
+ tabsRef.current.set(tabValue, element);
50
+ }
51
+ else {
52
+ tabsRef.current.delete(tabValue);
53
+ }
54
+ }, []);
55
+ const isVertical = orientation === "vertical";
56
+ const arrowNext = isVertical ? "ArrowDown" : "ArrowRight";
57
+ const arrowPrev = isVertical ? "ArrowUp" : "ArrowLeft";
58
+ useBrowserLayoutEffect(() => {
59
+ const list = listRef.current;
60
+ if (!motion || !list)
61
+ return;
62
+ const measure = () => {
63
+ const selected = Array.from(list.querySelectorAll('[role="tab"]')).find((tab) => tab.getAttribute("aria-selected") === "true");
64
+ if (!selected) {
65
+ setIndicator(null);
66
+ return;
67
+ }
68
+ const base = {
69
+ left: selected.offsetLeft,
70
+ top: selected.offsetTop,
71
+ width: selected.offsetWidth,
72
+ height: selected.offsetHeight,
73
+ };
74
+ if (variant === "line") {
75
+ if (isVertical) {
76
+ base.left += base.width - 2;
77
+ base.width = 2;
78
+ }
79
+ else {
80
+ base.top += base.height - 2;
81
+ base.height = 2;
82
+ }
83
+ }
84
+ setIndicator((previous) => previous &&
85
+ Object.keys(base).every((key) => base[key] === previous[key])
86
+ ? previous
87
+ : base);
88
+ };
89
+ measure();
90
+ const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(measure);
91
+ observer?.observe(list);
92
+ Array.from(list.children).forEach((child) => observer?.observe(child));
93
+ return () => observer?.disconnect();
94
+ }, [activeValue, motion, variant, size, isVertical, children]);
95
+ const handleKeyDown = (e) => {
96
+ const tabs = Array.from(tabsRef.current.entries())
97
+ .filter(([, el]) => !el.disabled)
98
+ .sort((a, b) => a[1].compareDocumentPosition(b[1]) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1)
99
+ .map(([val, el]) => ({ value: val, element: el }));
100
+ if (tabs.length === 0)
101
+ return;
102
+ const currentIndex = tabs.findIndex((t) => t.element === document.activeElement);
103
+ let nextIndex;
104
+ switch (e.key) {
105
+ case arrowNext:
106
+ e.preventDefault();
107
+ nextIndex = currentIndex < tabs.length - 1 ? currentIndex + 1 : 0;
108
+ break;
109
+ case arrowPrev:
110
+ e.preventDefault();
111
+ nextIndex = currentIndex > 0 ? currentIndex - 1 : tabs.length - 1;
112
+ break;
113
+ case "Home":
114
+ e.preventDefault();
115
+ nextIndex = 0;
116
+ break;
117
+ case "End":
118
+ e.preventDefault();
119
+ nextIndex = tabs.length - 1;
120
+ break;
121
+ default:
122
+ return;
123
+ }
124
+ const nextTab = tabs[nextIndex];
125
+ if (nextTab) {
126
+ nextTab.element.focus();
127
+ onSelect(nextTab.value);
128
+ }
129
+ };
130
+ const contextValue = (0, react_1.useMemo)(() => ({ activeValue, onSelect, variant, size, orientation, registerTab, motion }), [activeValue, onSelect, variant, size, orientation, registerTab, motion]);
131
+ return ((0, jsx_runtime_1.jsx)(TabsContext.Provider, { value: contextValue, children: (0, jsx_runtime_1.jsxs)("div", { ref: listRef, "data-rayden-motion": motion ? preset : undefined, className: (0, cn_1.cn)("inline-flex", motion && "relative isolate", isVertical ? "flex-col" : "", variant === "line" && !isVertical && "border-b border-grey-200", variant === "line" && isVertical && "border-r border-grey-200", variant === "pill" && (isVertical ? "gap-1" : "gap-1"), variant === "segmented" &&
132
+ "border border-grey-100 bg-grey-50 rounded-lg p-0.5 gap-0.5 overflow-hidden", className), role: "tablist", "aria-orientation": orientation, onKeyDown: handleKeyDown, children: [motion && indicator && ((0, jsx_runtime_1.jsx)(SharedLayout_1.SharedLayout, { "aria-hidden": "true", "data-rayden-tab-indicator": "", motion: motion, layoutKey: `${activeValue}:${indicator.left}:${indicator.top}:${indicator.width}:${indicator.height}`, className: (0, cn_1.cn)("pointer-events-none absolute", variant === "line" ? "bg-primary-400" : "bg-primary-50", variant === "pill" && "rounded-full", variant === "segmented" && "rounded-md"), style: indicator })), children] }) }));
133
+ }