@timmbr/ui 1.5.0 → 1.7.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 (258) hide show
  1. package/README.md +12 -10
  2. package/dist/components/Alert/Alert.styles.d.ts +2 -2
  3. package/dist/components/AlertDialog/AlertDialog.d.ts +5 -3
  4. package/dist/components/AlertDialog/AlertDialog.d.ts.map +1 -1
  5. package/dist/components/AlertDialog/AlertDialog.js +21 -8
  6. package/dist/components/AlertDialog/AlertDialog.styles.d.ts +7 -1
  7. package/dist/components/AlertDialog/AlertDialog.styles.d.ts.map +1 -1
  8. package/dist/components/AlertDialog/AlertDialog.styles.js +26 -3
  9. package/dist/components/AlertDialog/AlertDialog.types.d.ts +19 -2
  10. package/dist/components/AlertDialog/AlertDialog.types.d.ts.map +1 -1
  11. package/dist/components/Avatar/Avatar.styles.d.ts +2 -2
  12. package/dist/components/Badge/Badge.styles.d.ts +2 -2
  13. package/dist/components/Badge/Badge.styles.d.ts.map +1 -1
  14. package/dist/components/Badge/Badge.styles.js +3 -1
  15. package/dist/components/Button/Button.d.ts.map +1 -1
  16. package/dist/components/Button/Button.js +6 -0
  17. package/dist/components/Button/Button.styles.d.ts +4 -2
  18. package/dist/components/Button/Button.styles.d.ts.map +1 -1
  19. package/dist/components/Button/Button.styles.js +26 -7
  20. package/dist/components/Card/Card.d.ts.map +1 -1
  21. package/dist/components/Card/Card.js +51 -32
  22. package/dist/components/Card/Card.styles.d.ts +32 -5
  23. package/dist/components/Card/Card.styles.d.ts.map +1 -1
  24. package/dist/components/Card/Card.styles.js +69 -10
  25. package/dist/components/Card/Card.types.d.ts +14 -3
  26. package/dist/components/Card/Card.types.d.ts.map +1 -1
  27. package/dist/components/Checkbox/Checkbox.styles.d.ts +2 -2
  28. package/dist/components/Chip/Chip.styles.d.ts +1 -1
  29. package/dist/components/ConfirmDialog/ConfirmDialog.d.ts +30 -0
  30. package/dist/components/ConfirmDialog/ConfirmDialog.d.ts.map +1 -0
  31. package/dist/components/ConfirmDialog/ConfirmDialog.js +57 -0
  32. package/dist/components/ConfirmDialog/index.d.ts +2 -0
  33. package/dist/components/ConfirmDialog/index.d.ts.map +1 -0
  34. package/dist/components/Container/Container.styles.d.ts +1 -1
  35. package/dist/components/DataList/DataList.d.ts +3 -1
  36. package/dist/components/DataList/DataList.d.ts.map +1 -1
  37. package/dist/components/DataList/DataList.js +53 -15
  38. package/dist/components/DataList/DataList.styles.d.ts +17 -4
  39. package/dist/components/DataList/DataList.styles.d.ts.map +1 -1
  40. package/dist/components/DataList/DataList.styles.js +53 -10
  41. package/dist/components/DataList/DataList.types.d.ts +19 -2
  42. package/dist/components/DataList/DataList.types.d.ts.map +1 -1
  43. package/dist/components/Drawer/Drawer.d.ts +4 -3
  44. package/dist/components/Drawer/Drawer.d.ts.map +1 -1
  45. package/dist/components/Drawer/Drawer.js +33 -6
  46. package/dist/components/Drawer/Drawer.styles.d.ts +4 -0
  47. package/dist/components/Drawer/Drawer.styles.d.ts.map +1 -1
  48. package/dist/components/Drawer/Drawer.styles.js +8 -5
  49. package/dist/components/Drawer/Drawer.types.d.ts +1 -0
  50. package/dist/components/Drawer/Drawer.types.d.ts.map +1 -1
  51. package/dist/components/Dropdown/Dropdown.d.ts.map +1 -1
  52. package/dist/components/Dropdown/Dropdown.js +23 -10
  53. package/dist/components/Dropdown/Dropdown.styles.d.ts +5 -1
  54. package/dist/components/Dropdown/Dropdown.styles.d.ts.map +1 -1
  55. package/dist/components/Dropdown/Dropdown.styles.js +12 -2
  56. package/dist/components/Dropdown/Dropdown.types.d.ts +4 -0
  57. package/dist/components/Dropdown/Dropdown.types.d.ts.map +1 -1
  58. package/dist/components/EmptyState/EmptyState.d.ts.map +1 -1
  59. package/dist/components/EmptyState/EmptyState.js +2 -1
  60. package/dist/components/EmptyState/EmptyState.styles.d.ts +3 -2
  61. package/dist/components/EmptyState/EmptyState.styles.d.ts.map +1 -1
  62. package/dist/components/EmptyState/EmptyState.styles.js +5 -0
  63. package/dist/components/Fieldset/Fieldset.d.ts +14 -0
  64. package/dist/components/Fieldset/Fieldset.d.ts.map +1 -0
  65. package/dist/components/Fieldset/Fieldset.js +24 -0
  66. package/dist/components/Fieldset/index.d.ts +2 -0
  67. package/dist/components/Fieldset/index.d.ts.map +1 -0
  68. package/dist/components/FormActions/FormActions.d.ts +13 -0
  69. package/dist/components/FormActions/FormActions.d.ts.map +1 -0
  70. package/dist/components/FormActions/FormActions.js +24 -0
  71. package/dist/components/FormActions/index.d.ts +2 -0
  72. package/dist/components/FormActions/index.d.ts.map +1 -0
  73. package/dist/components/Grid/Grid.d.ts +3 -1
  74. package/dist/components/Grid/Grid.d.ts.map +1 -1
  75. package/dist/components/Grid/Grid.js +31 -5
  76. package/dist/components/Grid/Grid.styles.d.ts +86 -0
  77. package/dist/components/Grid/Grid.styles.d.ts.map +1 -1
  78. package/dist/components/Grid/Grid.styles.js +85 -1
  79. package/dist/components/Grid/Grid.types.d.ts +31 -3
  80. package/dist/components/Grid/Grid.types.d.ts.map +1 -1
  81. package/dist/components/Heading/Heading.styles.d.ts +2 -2
  82. package/dist/components/Heading/Heading.styles.d.ts.map +1 -1
  83. package/dist/components/Heading/Heading.styles.js +3 -1
  84. package/dist/components/Heading/Heading.types.d.ts +1 -1
  85. package/dist/components/Heading/Heading.types.d.ts.map +1 -1
  86. package/dist/components/Icon/Icon.styles.d.ts +2 -2
  87. package/dist/components/Icon/Icon.styles.d.ts.map +1 -1
  88. package/dist/components/Icon/Icon.styles.js +6 -2
  89. package/dist/components/IconTile/IconTile.d.ts +8 -0
  90. package/dist/components/IconTile/IconTile.d.ts.map +1 -0
  91. package/dist/components/IconTile/IconTile.js +23 -0
  92. package/dist/components/IconTile/IconTile.styles.d.ts +7 -0
  93. package/dist/components/IconTile/IconTile.styles.d.ts.map +1 -0
  94. package/dist/components/IconTile/IconTile.styles.js +24 -0
  95. package/dist/components/IconTile/IconTile.types.d.ts +12 -0
  96. package/dist/components/IconTile/IconTile.types.d.ts.map +1 -0
  97. package/dist/components/IconTile/index.d.ts +4 -0
  98. package/dist/components/IconTile/index.d.ts.map +1 -0
  99. package/dist/components/Inline/Inline.d.ts.map +1 -1
  100. package/dist/components/Inline/Inline.js +10 -2
  101. package/dist/components/Inline/Inline.types.d.ts +6 -1
  102. package/dist/components/Inline/Inline.types.d.ts.map +1 -1
  103. package/dist/components/Input/Input.styles.d.ts +1 -1
  104. package/dist/components/Label/Label.styles.d.ts +1 -1
  105. package/dist/components/LinkButton/LinkButton.d.ts.map +1 -1
  106. package/dist/components/LinkButton/LinkButton.js +2 -0
  107. package/dist/components/LinkButton/LinkButton.styles.d.ts +3 -2
  108. package/dist/components/LinkButton/LinkButton.styles.d.ts.map +1 -1
  109. package/dist/components/LinkButton/LinkButton.styles.js +6 -0
  110. package/dist/components/List/List.d.ts.map +1 -1
  111. package/dist/components/List/List.js +18 -5
  112. package/dist/components/List/List.styles.d.ts +3 -1
  113. package/dist/components/List/List.styles.d.ts.map +1 -1
  114. package/dist/components/List/List.styles.js +4 -3
  115. package/dist/components/List/List.types.d.ts +7 -0
  116. package/dist/components/List/List.types.d.ts.map +1 -1
  117. package/dist/components/MediaCard/MediaCard.d.ts +13 -0
  118. package/dist/components/MediaCard/MediaCard.d.ts.map +1 -0
  119. package/dist/components/MediaCard/MediaCard.js +125 -0
  120. package/dist/components/MediaCard/MediaCard.styles.d.ts +17 -0
  121. package/dist/components/MediaCard/MediaCard.styles.d.ts.map +1 -0
  122. package/dist/components/MediaCard/MediaCard.styles.js +57 -0
  123. package/dist/components/MediaCard/MediaCard.types.d.ts +82 -0
  124. package/dist/components/MediaCard/MediaCard.types.d.ts.map +1 -0
  125. package/dist/components/MediaCard/index.d.ts +4 -0
  126. package/dist/components/MediaCard/index.d.ts.map +1 -0
  127. package/dist/components/NavFooter/NavFooter.styles.d.ts +1 -1
  128. package/dist/components/NavHeader/NavHeader.d.ts.map +1 -1
  129. package/dist/components/NavHeader/NavHeader.js +2 -1
  130. package/dist/components/NavHeader/NavHeader.styles.d.ts +1 -1
  131. package/dist/components/NavHeader/NavHeader.types.d.ts +22 -0
  132. package/dist/components/NavHeader/NavHeader.types.d.ts.map +1 -1
  133. package/dist/components/NavHeader/index.d.ts +1 -1
  134. package/dist/components/NavHeader/index.d.ts.map +1 -1
  135. package/dist/components/NavHeader/subcomponents/NavActions.d.ts +5 -0
  136. package/dist/components/NavHeader/subcomponents/NavActions.d.ts.map +1 -1
  137. package/dist/components/NavHeader/subcomponents/NavActions.js +32 -2
  138. package/dist/components/OtpInput/OtpInput.styles.d.ts +1 -1
  139. package/dist/components/PageHeader/PageHeader.d.ts +8 -0
  140. package/dist/components/PageHeader/PageHeader.d.ts.map +1 -0
  141. package/dist/components/PageHeader/PageHeader.js +55 -0
  142. package/dist/components/PageHeader/PageHeader.styles.d.ts +10 -0
  143. package/dist/components/PageHeader/PageHeader.styles.d.ts.map +1 -0
  144. package/dist/components/PageHeader/PageHeader.styles.js +23 -0
  145. package/dist/components/PageHeader/PageHeader.types.d.ts +24 -0
  146. package/dist/components/PageHeader/PageHeader.types.d.ts.map +1 -0
  147. package/dist/components/PageHeader/index.d.ts +4 -0
  148. package/dist/components/PageHeader/index.d.ts.map +1 -0
  149. package/dist/components/Pagination/Pagination.d.ts +9 -3
  150. package/dist/components/Pagination/Pagination.d.ts.map +1 -1
  151. package/dist/components/Pagination/Pagination.js +60 -39
  152. package/dist/components/Pagination/Pagination.styles.d.ts +1 -1
  153. package/dist/components/Pagination/Pagination.types.d.ts +23 -14
  154. package/dist/components/Pagination/Pagination.types.d.ts.map +1 -1
  155. package/dist/components/Price/Price.d.ts +10 -0
  156. package/dist/components/Price/Price.d.ts.map +1 -0
  157. package/dist/components/Price/Price.js +49 -0
  158. package/dist/components/Price/Price.styles.d.ts +15 -0
  159. package/dist/components/Price/Price.styles.d.ts.map +1 -0
  160. package/dist/components/Price/Price.styles.js +44 -0
  161. package/dist/components/Price/Price.types.d.ts +22 -0
  162. package/dist/components/Price/Price.types.d.ts.map +1 -0
  163. package/dist/components/Price/index.d.ts +4 -0
  164. package/dist/components/Price/index.d.ts.map +1 -0
  165. package/dist/components/Progress/Progress.styles.d.ts +1 -1
  166. package/dist/components/Radio/Radio.styles.d.ts +2 -2
  167. package/dist/components/Rating/Rating.d.ts +5 -0
  168. package/dist/components/Rating/Rating.d.ts.map +1 -0
  169. package/dist/components/Rating/Rating.js +38 -0
  170. package/dist/components/Rating/Rating.styles.d.ts +6 -0
  171. package/dist/components/Rating/Rating.styles.d.ts.map +1 -0
  172. package/dist/components/Rating/Rating.styles.js +13 -0
  173. package/dist/components/Rating/Rating.types.d.ts +18 -0
  174. package/dist/components/Rating/Rating.types.d.ts.map +1 -0
  175. package/dist/components/Rating/index.d.ts +4 -0
  176. package/dist/components/Rating/index.d.ts.map +1 -0
  177. package/dist/components/ResponsiveDialog/ResponsiveDialog.d.ts +29 -0
  178. package/dist/components/ResponsiveDialog/ResponsiveDialog.d.ts.map +1 -0
  179. package/dist/components/ResponsiveDialog/ResponsiveDialog.js +74 -0
  180. package/dist/components/ResponsiveDialog/ResponsiveDialog.types.d.ts +27 -0
  181. package/dist/components/ResponsiveDialog/ResponsiveDialog.types.d.ts.map +1 -0
  182. package/dist/components/ResponsiveDialog/index.d.ts +3 -0
  183. package/dist/components/ResponsiveDialog/index.d.ts.map +1 -0
  184. package/dist/components/SectionNav/SectionNav.d.ts +12 -0
  185. package/dist/components/SectionNav/SectionNav.d.ts.map +1 -0
  186. package/dist/components/SectionNav/SectionNav.js +67 -0
  187. package/dist/components/SectionNav/SectionNav.styles.d.ts +11 -0
  188. package/dist/components/SectionNav/SectionNav.styles.d.ts.map +1 -0
  189. package/dist/components/SectionNav/SectionNav.styles.js +28 -0
  190. package/dist/components/SectionNav/SectionNav.types.d.ts +37 -0
  191. package/dist/components/SectionNav/SectionNav.types.d.ts.map +1 -0
  192. package/dist/components/SectionNav/index.d.ts +4 -0
  193. package/dist/components/SectionNav/index.d.ts.map +1 -0
  194. package/dist/components/Select/Select.styles.d.ts +1 -1
  195. package/dist/components/Spinner/Spinner.styles.d.ts +1 -1
  196. package/dist/components/Stack/Stack.d.ts.map +1 -1
  197. package/dist/components/Stack/Stack.js +16 -1
  198. package/dist/components/Stack/Stack.types.d.ts +14 -1
  199. package/dist/components/Stack/Stack.types.d.ts.map +1 -1
  200. package/dist/components/Stepper/Stepper.d.ts +9 -0
  201. package/dist/components/Stepper/Stepper.d.ts.map +1 -0
  202. package/dist/components/Stepper/Stepper.js +81 -0
  203. package/dist/components/Stepper/Stepper.styles.d.ts +14 -0
  204. package/dist/components/Stepper/Stepper.styles.d.ts.map +1 -0
  205. package/dist/components/Stepper/Stepper.styles.js +40 -0
  206. package/dist/components/Stepper/Stepper.types.d.ts +17 -0
  207. package/dist/components/Stepper/Stepper.types.d.ts.map +1 -0
  208. package/dist/components/Stepper/index.d.ts +4 -0
  209. package/dist/components/Stepper/index.d.ts.map +1 -0
  210. package/dist/components/Steps/Steps.d.ts +9 -0
  211. package/dist/components/Steps/Steps.d.ts.map +1 -0
  212. package/dist/components/Steps/Steps.js +81 -0
  213. package/dist/components/Steps/Steps.styles.d.ts +14 -0
  214. package/dist/components/Steps/Steps.styles.d.ts.map +1 -0
  215. package/dist/components/Steps/Steps.styles.js +40 -0
  216. package/dist/components/Steps/Steps.types.d.ts +17 -0
  217. package/dist/components/Steps/Steps.types.d.ts.map +1 -0
  218. package/dist/components/Steps/index.d.ts +4 -0
  219. package/dist/components/Steps/index.d.ts.map +1 -0
  220. package/dist/components/SubNav/SubNav.d.ts +17 -0
  221. package/dist/components/SubNav/SubNav.d.ts.map +1 -0
  222. package/dist/components/SubNav/SubNav.js +87 -0
  223. package/dist/components/SubNav/SubNav.styles.d.ts +18 -0
  224. package/dist/components/SubNav/SubNav.styles.d.ts.map +1 -0
  225. package/dist/components/SubNav/SubNav.styles.js +33 -0
  226. package/dist/components/SubNav/SubNav.types.d.ts +45 -0
  227. package/dist/components/SubNav/SubNav.types.d.ts.map +1 -0
  228. package/dist/components/SubNav/index.d.ts +4 -0
  229. package/dist/components/SubNav/index.d.ts.map +1 -0
  230. package/dist/components/Switch/Switch.styles.d.ts +2 -2
  231. package/dist/components/Table/Table.styles.d.ts +1 -1
  232. package/dist/components/Tabs/Tabs.d.ts.map +1 -1
  233. package/dist/components/Tabs/Tabs.js +73 -6
  234. package/dist/components/Tabs/Tabs.styles.d.ts +10 -2
  235. package/dist/components/Tabs/Tabs.styles.d.ts.map +1 -1
  236. package/dist/components/Tabs/Tabs.styles.js +17 -2
  237. package/dist/components/Tabs/Tabs.types.d.ts +13 -0
  238. package/dist/components/Tabs/Tabs.types.d.ts.map +1 -1
  239. package/dist/components/Text/Text.d.ts.map +1 -1
  240. package/dist/components/Text/Text.js +4 -0
  241. package/dist/components/Text/Text.styles.d.ts +4 -2
  242. package/dist/components/Text/Text.styles.d.ts.map +1 -1
  243. package/dist/components/Text/Text.styles.js +16 -2
  244. package/dist/components/Text/Text.types.d.ts +1 -1
  245. package/dist/components/Text/Text.types.d.ts.map +1 -1
  246. package/dist/components/Textarea/Textarea.styles.d.ts +1 -1
  247. package/dist/components/VisuallyHidden/VisuallyHidden.d.ts +8 -0
  248. package/dist/components/VisuallyHidden/VisuallyHidden.d.ts.map +1 -0
  249. package/dist/components/VisuallyHidden/VisuallyHidden.js +14 -0
  250. package/dist/components/VisuallyHidden/index.d.ts +2 -0
  251. package/dist/components/VisuallyHidden/index.d.ts.map +1 -0
  252. package/dist/index.d.ts +13 -0
  253. package/dist/index.d.ts.map +1 -1
  254. package/dist/index.js +32 -13
  255. package/dist/utils/gap.d.ts +21 -1
  256. package/dist/utils/gap.d.ts.map +1 -1
  257. package/dist/utils/gap.js +306 -46
  258. package/package.json +5 -5
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Steps.d.ts","sourceRoot":"","sources":["../../../src/components/Steps/Steps.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAQ/B,OAAO,KAAK,EAAa,UAAU,EAAE,MAAM,eAAe,CAAC;AAQ3D;;;;GAIG;AACH,eAAO,MAAM,KAAK,qFA0EjB,CAAC"}
@@ -0,0 +1,81 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import * as React from 'react';
3
+ import { cn } from '@timmbr/utils';
4
+ import { Check, X } from '@timmbr/icons';
5
+ import { stepConnectorVariants, stepIndicatorVariants, stepsVariants } from './Steps.styles.js';
6
+
7
+ function stateOf(index, current, status) {
8
+ if (index < current) return "complete";
9
+ if (index === current) return status === "error" ? "error" : "current";
10
+ return "upcoming";
11
+ }
12
+ const Steps = React.forwardRef(
13
+ ({ steps, current, status = "default", orientation = "horizontal", className, ...props }, ref) => /* @__PURE__ */ jsx(
14
+ "ol",
15
+ {
16
+ ref,
17
+ "data-slot": "steps",
18
+ "data-orientation": orientation,
19
+ className: cn(stepsVariants({ orientation }), className),
20
+ ...props,
21
+ children: steps.map((step, index) => {
22
+ const state = stateOf(index, current, status);
23
+ const isLast = index === steps.length - 1;
24
+ return /* @__PURE__ */ jsxs(
25
+ "li",
26
+ {
27
+ "data-state": state,
28
+ "aria-current": state === "current" || state === "error" ? "step" : void 0,
29
+ className: cn(
30
+ "relative flex min-w-0",
31
+ orientation === "horizontal" ? "flex-1 flex-col items-center text-center" : "gap-3 pb-6 last:pb-0"
32
+ ),
33
+ children: [
34
+ !isLast && /* @__PURE__ */ jsx(
35
+ "span",
36
+ {
37
+ "aria-hidden": "true",
38
+ className: stepConnectorVariants({
39
+ orientation,
40
+ complete: state === "complete"
41
+ })
42
+ }
43
+ ),
44
+ /* @__PURE__ */ jsx("span", { className: stepIndicatorVariants({ state }), "aria-hidden": "true", children: state === "complete" ? /* @__PURE__ */ jsx(Check, { size: 14, strokeWidth: 3 }) : state === "error" ? /* @__PURE__ */ jsx(X, { size: 14, strokeWidth: 3 }) : index + 1 }),
45
+ /* @__PURE__ */ jsxs(
46
+ "span",
47
+ {
48
+ className: cn(
49
+ "min-w-0",
50
+ orientation === "horizontal" ? "mt-2 px-1" : "pt-0.5"
51
+ ),
52
+ children: [
53
+ /* @__PURE__ */ jsxs(
54
+ "span",
55
+ {
56
+ className: cn(
57
+ "block text-body-2 font-medium",
58
+ state === "upcoming" ? "text-muted-foreground" : "text-foreground",
59
+ state === "error" && "text-destructive"
60
+ ),
61
+ children: [
62
+ step.label,
63
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: state === "complete" ? " (completed)" : state === "error" ? " (failed)" : "" })
64
+ ]
65
+ }
66
+ ),
67
+ step.description && /* @__PURE__ */ jsx("span", { className: "mt-0.5 block text-caption-lg text-muted-foreground", children: step.description })
68
+ ]
69
+ }
70
+ )
71
+ ]
72
+ },
73
+ step.id ?? index
74
+ );
75
+ })
76
+ }
77
+ )
78
+ );
79
+ Steps.displayName = "Steps";
80
+
81
+ export { Steps };
@@ -0,0 +1,14 @@
1
+ import { type VariantProps } from 'class-variance-authority';
2
+ export declare const stepsVariants: (props?: ({
3
+ orientation?: "horizontal" | "vertical" | null | undefined;
4
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
5
+ export declare const stepIndicatorVariants: (props?: ({
6
+ state?: "current" | "error" | "complete" | "upcoming" | null | undefined;
7
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
8
+ /** Line to the next step, behind the indicators. */
9
+ export declare const stepConnectorVariants: (props?: ({
10
+ orientation?: "horizontal" | "vertical" | null | undefined;
11
+ complete?: boolean | null | undefined;
12
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
13
+ export type StepsVariants = VariantProps<typeof stepsVariants>;
14
+ //# sourceMappingURL=Steps.styles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Steps.styles.d.ts","sourceRoot":"","sources":["../../../src/components/Steps/Steps.styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAElE,eAAO,MAAM,aAAa;;8EAQxB,CAAC;AAEH,eAAO,MAAM,qBAAqB;;8EAajC,CAAC;AAEF,oDAAoD;AACpD,eAAO,MAAM,qBAAqB;;;8EAYhC,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,YAAY,CAAC,OAAO,aAAa,CAAC,CAAC"}
@@ -0,0 +1,40 @@
1
+ import { cva } from 'class-variance-authority';
2
+
3
+ const stepsVariants = cva("font-sans", {
4
+ variants: {
5
+ orientation: {
6
+ horizontal: "flex items-start",
7
+ vertical: "flex flex-col"
8
+ }
9
+ },
10
+ defaultVariants: { orientation: "horizontal" }
11
+ });
12
+ const stepIndicatorVariants = cva(
13
+ "relative z-10 flex size-7 shrink-0 items-center justify-center rounded-full border-2 text-caption-lg font-semibold tabular-nums transition-colors",
14
+ {
15
+ variants: {
16
+ state: {
17
+ complete: "border-primary bg-primary text-primary-foreground",
18
+ current: "border-primary bg-background text-primary",
19
+ error: "border-destructive bg-destructive text-destructive-foreground",
20
+ upcoming: "border-grey-300 bg-background text-muted-foreground dark:border-grey-700"
21
+ }
22
+ },
23
+ defaultVariants: { state: "upcoming" }
24
+ }
25
+ );
26
+ const stepConnectorVariants = cva("absolute", {
27
+ variants: {
28
+ orientation: {
29
+ horizontal: "left-1/2 top-3.5 h-0.5 w-full",
30
+ vertical: "left-3.5 top-7 h-full w-0.5 -translate-x-1/2"
31
+ },
32
+ complete: {
33
+ true: "bg-primary",
34
+ false: "bg-grey-200 dark:bg-grey-800"
35
+ }
36
+ },
37
+ defaultVariants: { orientation: "horizontal", complete: false }
38
+ });
39
+
40
+ export { stepConnectorVariants, stepIndicatorVariants, stepsVariants };
@@ -0,0 +1,17 @@
1
+ import type * as React from 'react';
2
+ export type StepState = 'complete' | 'current' | 'error' | 'upcoming';
3
+ export interface StepItem {
4
+ id?: string;
5
+ label: React.ReactNode;
6
+ /** Secondary line, e.g. a date. */
7
+ description?: React.ReactNode;
8
+ }
9
+ export interface StepsProps extends React.OlHTMLAttributes<HTMLOListElement> {
10
+ steps: StepItem[];
11
+ /** Index of the current step. Steps before it are complete. */
12
+ current: number;
13
+ /** `error` marks the current step as failed. */
14
+ status?: 'default' | 'error';
15
+ orientation?: 'horizontal' | 'vertical';
16
+ }
17
+ //# sourceMappingURL=Steps.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Steps.types.d.ts","sourceRoot":"","sources":["../../../src/components/Steps/Steps.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AAEpC,MAAM,MAAM,SAAS,GAAG,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,UAAU,CAAC;AAEtE,MAAM,WAAW,QAAQ;IACvB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,mCAAmC;IACnC,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC/B;AAED,MAAM,WAAW,UAAW,SAAQ,KAAK,CAAC,gBAAgB,CAAC,gBAAgB,CAAC;IAC1E,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,+DAA+D;IAC/D,OAAO,EAAE,MAAM,CAAC;IAChB,gDAAgD;IAChD,MAAM,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC;IAC7B,WAAW,CAAC,EAAE,YAAY,GAAG,UAAU,CAAC;CACzC"}
@@ -0,0 +1,4 @@
1
+ export * from './Steps';
2
+ export * from './Steps.types';
3
+ export * from './Steps.styles';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Steps/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC"}
@@ -0,0 +1,17 @@
1
+ import * as React from 'react';
2
+ import type { SubNavActionProps, SubNavProps } from './SubNav.types';
3
+ /** Exact match, or nested under the item (`/orders/1` → `/orders`). */
4
+ export declare function isSubNavItemActive(href: string, activeHref?: string): boolean;
5
+ /**
6
+ * In-page section navigation (account, settings, help centre…): a vertical
7
+ * list on desktop and a horizontally scrolling row on small screens.
8
+ * Unlike `SideBarNavigation` it's not an app shell: no branding, collapse or
9
+ * full-height frame.
10
+ */
11
+ export declare const SubNav: React.ForwardRefExoticComponent<SubNavProps & React.RefAttributes<HTMLElement>>;
12
+ /**
13
+ * A button for the `footer` slot (e.g. Log out), shaped like the items so
14
+ * its icon and label line up with them.
15
+ */
16
+ export declare const SubNavAction: React.ForwardRefExoticComponent<SubNavActionProps & React.RefAttributes<HTMLButtonElement>>;
17
+ //# sourceMappingURL=SubNav.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SubNav.d.ts","sourceRoot":"","sources":["../../../src/components/SubNav/SubNav.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAS/B,OAAO,KAAK,EAAE,iBAAiB,EAAmB,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAUtF,uEAAuE;AACvE,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAK7E;AAED;;;;;GAKG;AACH,eAAO,MAAM,MAAM,iFAgElB,CAAC;AAGF;;;GAGG;AACH,eAAO,MAAM,YAAY,6FAmBxB,CAAC"}
@@ -0,0 +1,87 @@
1
+ "use client";
2
+ import { jsxs, jsx } from 'react/jsx-runtime';
3
+ import * as React from 'react';
4
+ import { cn } from '@timmbr/utils';
5
+ import { subNavIconVariants, subNavItemVariants, subNavListVariants, subNavFooterVariants } from './SubNav.styles.js';
6
+ import { Spinner } from '../Spinner/Spinner.js';
7
+
8
+ const DefaultLink = ({ href, className, children, ...rest }) => /* @__PURE__ */ jsx("a", { href, className, ...rest, children });
9
+ const trimSlash = (path) => path.length > 1 ? path.replace(/\/+$/, "") : path;
10
+ function isSubNavItemActive(href, activeHref) {
11
+ if (!activeHref) return false;
12
+ const item = trimSlash(href);
13
+ const current = trimSlash(activeHref.split(/[?#]/)[0] ?? "");
14
+ return current === item || current.startsWith(`${item}/`);
15
+ }
16
+ const SubNav = React.forwardRef(
17
+ ({
18
+ items,
19
+ activeHref,
20
+ linkComponent: Link = DefaultLink,
21
+ footer,
22
+ mobileLayout = "scroll",
23
+ className,
24
+ "aria-label": ariaLabel = "Section navigation",
25
+ ...props
26
+ }, ref) => {
27
+ const activeId = React.useMemo(() => {
28
+ const matches = items.filter((item) => isSubNavItemActive(item.href, activeHref));
29
+ return matches.sort((a, b) => b.href.length - a.href.length)[0]?.id;
30
+ }, [items, activeHref]);
31
+ return /* @__PURE__ */ jsxs(
32
+ "nav",
33
+ {
34
+ ref,
35
+ "aria-label": ariaLabel,
36
+ "data-slot": "sub-nav",
37
+ className: cn(
38
+ "flex gap-2 lg:flex-col lg:items-stretch lg:gap-0",
39
+ mobileLayout === "wrap" ? "flex-col items-stretch" : "items-center",
40
+ className
41
+ ),
42
+ ...props,
43
+ children: [
44
+ /* @__PURE__ */ jsx("ul", { className: cn(subNavListVariants({ mobileLayout }), "min-w-0 flex-1"), role: "list", children: items.map((item) => {
45
+ const active = item.id === activeId;
46
+ return /* @__PURE__ */ jsx("li", { className: "shrink-0", children: /* @__PURE__ */ jsxs(
47
+ Link,
48
+ {
49
+ href: item.href,
50
+ "aria-current": active ? "page" : void 0,
51
+ className: subNavItemVariants({ active }),
52
+ children: [
53
+ item.icon && /* @__PURE__ */ jsx("span", { className: subNavIconVariants(), "aria-hidden": "true", children: item.icon }),
54
+ /* @__PURE__ */ jsx("span", { className: "flex-1", children: item.label }),
55
+ item.badge !== void 0 && item.badge !== null && /* @__PURE__ */ jsx("span", { className: "text-caption-lg text-muted-foreground", children: item.badge })
56
+ ]
57
+ }
58
+ ) }, item.id);
59
+ }) }),
60
+ footer && /* @__PURE__ */ jsx("div", { className: subNavFooterVariants(), "data-slot": "sub-nav-footer", children: footer })
61
+ ]
62
+ }
63
+ );
64
+ }
65
+ );
66
+ SubNav.displayName = "SubNav";
67
+ const SubNavAction = React.forwardRef(
68
+ ({ icon, tone = "default", loading = false, disabled, className, children, type = "button", ...props }, ref) => /* @__PURE__ */ jsxs(
69
+ "button",
70
+ {
71
+ ref,
72
+ type,
73
+ disabled: disabled || loading,
74
+ "aria-busy": loading || void 0,
75
+ "data-slot": "sub-nav-action",
76
+ className: cn(subNavItemVariants({ tone }), className),
77
+ ...props,
78
+ children: [
79
+ (icon || loading) && /* @__PURE__ */ jsx("span", { className: subNavIconVariants(), "aria-hidden": "true", children: loading ? /* @__PURE__ */ jsx(Spinner, { size: "sm" }) : icon }),
80
+ /* @__PURE__ */ jsx("span", { className: "flex-1", children })
81
+ ]
82
+ }
83
+ )
84
+ );
85
+ SubNavAction.displayName = "SubNavAction";
86
+
87
+ export { SubNav, SubNavAction, isSubNavItemActive };
@@ -0,0 +1,18 @@
1
+ import { type VariantProps } from 'class-variance-authority';
2
+ /** Desktop (lg): a vertical list. Small screens: a scrolling row or wrapped lines. */
3
+ export declare const subNavListVariants: (props?: ({
4
+ mobileLayout?: "scroll" | "wrap" | null | undefined;
5
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
6
+ /**
7
+ * Items and footer actions share this shape so their icons and labels line up.
8
+ * Active: dark brand text on a light brand tint (about 7:1) plus a bar on the
9
+ * inline-start edge on desktop, so the state never relies on colour alone.
10
+ */
11
+ export declare const subNavItemVariants: (props?: ({
12
+ active?: boolean | null | undefined;
13
+ tone?: "default" | "destructive" | null | undefined;
14
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
15
+ export declare const subNavIconVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
16
+ export declare const subNavFooterVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
17
+ export type SubNavItemVariants = VariantProps<typeof subNavItemVariants>;
18
+ //# sourceMappingURL=SubNav.styles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SubNav.styles.d.ts","sourceRoot":"","sources":["../../../src/components/SubNav/SubNav.styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAElE,sFAAsF;AACtF,eAAO,MAAM,kBAAkB;;8EAQ7B,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,kBAAkB;;;8EAe9B,CAAC;AAEF,eAAO,MAAM,kBAAkB,oFAA8E,CAAC;AAE9G,eAAO,MAAM,oBAAoB,oFAEhC,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,YAAY,CAAC,OAAO,kBAAkB,CAAC,CAAC"}
@@ -0,0 +1,33 @@
1
+ import { cva } from 'class-variance-authority';
2
+
3
+ const subNavListVariants = cva("flex gap-1 lg:flex-col lg:flex-nowrap lg:overflow-visible", {
4
+ variants: {
5
+ mobileLayout: {
6
+ scroll: "overflow-x-auto [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
7
+ wrap: "flex-wrap"
8
+ }
9
+ },
10
+ defaultVariants: { mobileLayout: "scroll" }
11
+ });
12
+ const subNavItemVariants = cva(
13
+ "relative flex w-full items-center gap-3 whitespace-nowrap rounded-md px-3 py-2 lg:py-2.5 text-start font-sans text-body-2 font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50",
14
+ {
15
+ variants: {
16
+ active: {
17
+ true: "bg-muted font-semibold text-secondary-foreground lg:before:absolute lg:before:inset-y-2 lg:before:start-0 lg:before:w-1 lg:before:rounded-full lg:before:bg-primary",
18
+ false: "text-muted-foreground hover:bg-accent hover:text-accent-foreground"
19
+ },
20
+ tone: {
21
+ default: "",
22
+ destructive: "text-destructive hover:bg-destructive/10 hover:text-destructive"
23
+ }
24
+ },
25
+ defaultVariants: { active: false, tone: "default" }
26
+ }
27
+ );
28
+ const subNavIconVariants = cva("flex size-5 shrink-0 items-center justify-center [&_svg]:size-[18px]");
29
+ const subNavFooterVariants = cva(
30
+ "flex shrink-0 flex-col lg:mt-2 lg:border-t lg:border-border lg:pt-2"
31
+ );
32
+
33
+ export { subNavFooterVariants, subNavIconVariants, subNavItemVariants, subNavListVariants };
@@ -0,0 +1,45 @@
1
+ import type * as React from 'react';
2
+ export interface SubNavItem {
3
+ id: string;
4
+ label: React.ReactNode;
5
+ href: string;
6
+ /** Leading icon (decorative; hidden from screen readers). */
7
+ icon?: React.ReactNode;
8
+ /** Trailing count or tag, e.g. a number of items. */
9
+ badge?: React.ReactNode;
10
+ }
11
+ export interface SubNavLinkProps {
12
+ href: string;
13
+ className?: string;
14
+ children: React.ReactNode;
15
+ 'aria-current'?: 'page';
16
+ }
17
+ export interface SubNavProps extends Omit<React.HTMLAttributes<HTMLElement>, 'children'> {
18
+ items: SubNavItem[];
19
+ /**
20
+ * Current path. An item is active when it equals its `href` or is nested
21
+ * under it (`/account/orders/123` activates `/account/orders`).
22
+ */
23
+ activeHref?: string;
24
+ /** Link to render items with (e.g. `next/link`). Defaults to `<a>`. */
25
+ linkComponent?: React.ComponentType<SubNavLinkProps>;
26
+ /**
27
+ * Small screens: `scroll` keeps one horizontally scrolling row (good for many
28
+ * short items); `wrap` wraps the items onto several lines so every one stays
29
+ * visible (good for a handful of longer labels).
30
+ */
31
+ mobileLayout?: 'scroll' | 'wrap';
32
+ /** Extra content after the items, e.g. a "Log out" button. */
33
+ footer?: React.ReactNode;
34
+ /** Accessible name of the navigation landmark. */
35
+ 'aria-label'?: string;
36
+ }
37
+ export interface SubNavActionProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
38
+ /** Leading icon, aligned with the item icons. */
39
+ icon?: React.ReactNode;
40
+ /** `destructive` for actions such as Log out. */
41
+ tone?: 'default' | 'destructive';
42
+ /** Shows a spinner in place of the icon and disables the button. */
43
+ loading?: boolean;
44
+ }
45
+ //# sourceMappingURL=SubNav.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SubNav.types.d.ts","sourceRoot":"","sources":["../../../src/components/SubNav/SubNav.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AAEpC,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,6DAA6D;IAC7D,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,qDAAqD;IACrD,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CACzB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,WAAY,SAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,UAAU,CAAC;IACtF,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uEAAuE;IACvE,aAAa,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,eAAe,CAAC,CAAC;IACrD;;;;OAIG;IACH,YAAY,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC;IACjC,8DAA8D;IAC9D,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,kDAAkD;IAClD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,iBAAkB,SAAQ,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC;IACtF,iDAAiD;IACjD,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,iDAAiD;IACjD,IAAI,CAAC,EAAE,SAAS,GAAG,aAAa,CAAC;IACjC,oEAAoE;IACpE,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB"}
@@ -0,0 +1,4 @@
1
+ export * from './SubNav';
2
+ export * from './SubNav.types';
3
+ export * from './SubNav.styles';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/SubNav/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC"}
@@ -1,9 +1,9 @@
1
1
  import { type VariantProps } from 'class-variance-authority';
2
2
  export declare const switchVariants: (props?: ({
3
- size?: "default" | "sm" | "lg" | "md" | null | undefined;
3
+ size?: "sm" | "md" | "lg" | "default" | null | undefined;
4
4
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
5
5
  export declare const switchThumbVariants: (props?: ({
6
- size?: "default" | "sm" | "lg" | "md" | null | undefined;
6
+ size?: "sm" | "md" | "lg" | "default" | null | undefined;
7
7
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
8
8
  export type SwitchVariants = VariantProps<typeof switchVariants>;
9
9
  //# sourceMappingURL=Switch.styles.d.ts.map
@@ -4,7 +4,7 @@ export declare const tableContainerVariants: (props?: ({
4
4
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
5
5
  export declare const tableVariants: (props?: ({
6
6
  variant?: "default" | "bordered" | "striped" | null | undefined;
7
- size?: "default" | "sm" | null | undefined;
7
+ size?: "sm" | "default" | null | undefined;
8
8
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
9
9
  export declare const tableRowVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
10
10
  export declare const tableHeadVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
@@ -1 +1 @@
1
- {"version":3,"file":"Tabs.d.ts","sourceRoot":"","sources":["../../../src/components/Tabs/Tabs.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAW/B,OAAO,KAAK,EACV,SAAS,EACT,aAAa,EACb,gBAAgB,EAChB,gBAAgB,EACjB,MAAM,cAAc,CAAC;AAmBtB,eAAO,MAAM,IAAI,kFA4DhB,CAAC;AAGF,eAAO,MAAM,QAAQ,sFAgBnB,CAAC;AAGH,eAAO,MAAM,WAAW,4FA2EvB,CAAC;AAGF,eAAO,MAAM,WAAW,yFAoBtB,CAAC"}
1
+ {"version":3,"file":"Tabs.d.ts","sourceRoot":"","sources":["../../../src/components/Tabs/Tabs.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAe/B,OAAO,KAAK,EACV,SAAS,EACT,aAAa,EACb,gBAAgB,EAChB,gBAAgB,EACjB,MAAM,cAAc,CAAC;AAmBtB,eAAO,MAAM,IAAI,kFA4DhB,CAAC;AA6BF,eAAO,MAAM,QAAQ,sFA6EnB,CAAC;AAGH,eAAO,MAAM,WAAW,4FA2EvB,CAAC;AAGF,eAAO,MAAM,WAAW,yFAoBtB,CAAC"}
@@ -4,8 +4,9 @@ import * as React from 'react';
4
4
  import * as TabsPrimitive from '@radix-ui/react-tabs';
5
5
  import { cn } from '@timmbr/utils';
6
6
  import { motion } from '@timmbr/motion';
7
+ import { ChevronLeft, ChevronRight } from '@timmbr/icons';
7
8
  import { resolveMotion } from '../../types/motion.js';
8
- import { tabsContentVariants, tabsListVariants, tabsTriggerVariants } from './Tabs.styles.js';
9
+ import { tabsContentVariants, TABS_SCROLL_FADE, tabsListVariants, tabsScrollButtonVariants, tabsScrollEdgeVariants, tabsTriggerVariants } from './Tabs.styles.js';
9
10
  import { useGlobalAnimation } from '../../providers/AnimationProvider.js';
10
11
 
11
12
  const TabsContext = React.createContext({
@@ -71,19 +72,85 @@ const Tabs = React.forwardRef(
71
72
  }
72
73
  );
73
74
  Tabs.displayName = TabsPrimitive.Root.displayName;
74
- const TabsList = React.forwardRef(({ className, variant: localVariant, size: localSize, ...props }, ref) => {
75
+ function useScrollEdges(ref, enabled) {
76
+ const [edges, setEdges] = React.useState({ start: false, end: false });
77
+ React.useEffect(() => {
78
+ const el = ref.current;
79
+ if (!enabled || !el) return;
80
+ const measure = () => {
81
+ const max = el.scrollWidth - el.clientWidth;
82
+ const next = { start: el.scrollLeft > 1, end: el.scrollLeft < max - 1 };
83
+ setEdges((prev) => prev.start === next.start && prev.end === next.end ? prev : next);
84
+ };
85
+ const frame = requestAnimationFrame(measure);
86
+ el.addEventListener("scroll", measure, { passive: true });
87
+ const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(measure);
88
+ observer?.observe(el);
89
+ return () => {
90
+ cancelAnimationFrame(frame);
91
+ el.removeEventListener("scroll", measure);
92
+ observer?.disconnect();
93
+ };
94
+ }, [ref, enabled]);
95
+ return edges;
96
+ }
97
+ const TabsList = React.forwardRef(({ className, variant: localVariant, size: localSize, scrollable = false, scrollLabels, loading = false, ...props }, ref) => {
75
98
  const context = React.useContext(TabsContext);
76
99
  const variant = localVariant ?? context.variant;
77
100
  const size = localSize ?? context.size;
78
- return /* @__PURE__ */ jsx(
101
+ const listRef = React.useRef(null);
102
+ const edges = useScrollEdges(listRef, scrollable);
103
+ const setRefs = (node) => {
104
+ listRef.current = node;
105
+ if (typeof ref === "function") ref(node);
106
+ else if (ref) ref.current = node;
107
+ };
108
+ const fade = scrollable && (edges.start || edges.end) ? `linear-gradient(to right, ${edges.start ? "transparent" : "#000"}, #000 ${edges.start ? TABS_SCROLL_FADE : "0px"}, #000 calc(100% - ${edges.end ? TABS_SCROLL_FADE : "0px"}), ${edges.end ? "transparent" : "#000"})` : void 0;
109
+ const list = /* @__PURE__ */ jsx(
79
110
  TabsPrimitive.List,
80
111
  {
81
- ref,
112
+ ref: setRefs,
82
113
  "data-slot": "tabs-list",
83
- className: cn(tabsListVariants({ variant, size }), className),
84
- ...props
114
+ "aria-busy": loading || void 0,
115
+ className: cn(
116
+ tabsListVariants({ variant, size }),
117
+ loading && "opacity-70 transition-opacity",
118
+ scrollable && "max-w-full justify-start overflow-x-auto overflow-y-hidden scroll-smooth [scrollbar-width:none] [&::-webkit-scrollbar]:hidden [&>*]:shrink-0",
119
+ className
120
+ ),
121
+ ...props,
122
+ style: fade ? { ...props.style, maskImage: fade, WebkitMaskImage: fade } : props.style
85
123
  }
86
124
  );
125
+ if (!scrollable) return list;
126
+ const scrollByPage = (direction) => listRef.current?.scrollBy({ left: direction * listRef.current.clientWidth * 0.7, behavior: "smooth" });
127
+ return /* @__PURE__ */ jsxs("div", { className: "relative", "data-slot": "tabs-scroll", children: [
128
+ edges.start && /* @__PURE__ */ jsx("div", { className: tabsScrollEdgeVariants({ side: "start" }), children: /* @__PURE__ */ jsx(
129
+ "button",
130
+ {
131
+ type: "button",
132
+ tabIndex: -1,
133
+ "aria-label": scrollLabels?.previous ?? "Scroll tabs back",
134
+ "data-slot": "tabs-scroll-previous",
135
+ className: tabsScrollButtonVariants(),
136
+ onClick: () => scrollByPage(-1),
137
+ children: /* @__PURE__ */ jsx(ChevronLeft, { "aria-hidden": "true" })
138
+ }
139
+ ) }),
140
+ list,
141
+ edges.end && /* @__PURE__ */ jsx("div", { className: tabsScrollEdgeVariants({ side: "end" }), children: /* @__PURE__ */ jsx(
142
+ "button",
143
+ {
144
+ type: "button",
145
+ tabIndex: -1,
146
+ "aria-label": scrollLabels?.next ?? "Scroll tabs forward",
147
+ "data-slot": "tabs-scroll-next",
148
+ className: tabsScrollButtonVariants(),
149
+ onClick: () => scrollByPage(1),
150
+ children: /* @__PURE__ */ jsx(ChevronRight, { "aria-hidden": "true" })
151
+ }
152
+ ) })
153
+ ] });
87
154
  });
88
155
  TabsList.displayName = TabsPrimitive.List.displayName;
89
156
  const TabsTrigger = React.forwardRef(
@@ -1,12 +1,20 @@
1
1
  import { type VariantProps } from 'class-variance-authority';
2
2
  export declare const tabsListVariants: (props?: ({
3
3
  variant?: "underline" | "outline" | "pills" | null | undefined;
4
- size?: "default" | "sm" | "lg" | "md" | null | undefined;
4
+ size?: "sm" | "md" | "lg" | "default" | null | undefined;
5
5
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
6
6
  export declare const tabsTriggerVariants: (props?: ({
7
7
  variant?: "underline" | "outline" | "pills" | null | undefined;
8
- size?: "default" | "sm" | "lg" | "md" | null | undefined;
8
+ size?: "sm" | "md" | "lg" | "default" | null | undefined;
9
9
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
10
+ /** Round chevron shown at an edge of a `scrollable` TabsList while there is more to scroll. */
11
+ export declare const tabsScrollButtonVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
12
+ /** Holds a scroll button at one edge (the tabs under it are faded out with a mask). */
13
+ export declare const tabsScrollEdgeVariants: (props?: ({
14
+ side?: "start" | "end" | null | undefined;
15
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
16
+ /** Width of the faded strip under a scroll button. */
17
+ export declare const TABS_SCROLL_FADE = "56px";
10
18
  export declare const tabsContentVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
11
19
  export type TabsListVariants = VariantProps<typeof tabsListVariants>;
12
20
  export type TabsTriggerVariants = VariantProps<typeof tabsTriggerVariants>;
@@ -1 +1 @@
1
- {"version":3,"file":"Tabs.styles.d.ts","sourceRoot":"","sources":["../../../src/components/Tabs/Tabs.styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAElE,eAAO,MAAM,gBAAgB;;;8EAwB5B,CAAC;AAEF,eAAO,MAAM,mBAAmB;;;8EAwB/B,CAAC;AAEF,eAAO,MAAM,mBAAmB,oFAE/B,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG,YAAY,CAAC,OAAO,gBAAgB,CAAC,CAAC;AACrE,MAAM,MAAM,mBAAmB,GAAG,YAAY,CAAC,OAAO,mBAAmB,CAAC,CAAC"}
1
+ {"version":3,"file":"Tabs.styles.d.ts","sourceRoot":"","sources":["../../../src/components/Tabs/Tabs.styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAElE,eAAO,MAAM,gBAAgB;;;8EAwB5B,CAAC;AAEF,eAAO,MAAM,mBAAmB;;;8EAwB/B,CAAC;AAEF,+FAA+F;AAC/F,eAAO,MAAM,wBAAwB,oFAEpC,CAAC;AAEF,uFAAuF;AACvF,eAAO,MAAM,sBAAsB;;8EAUlC,CAAC;AAEF,sDAAsD;AACtD,eAAO,MAAM,gBAAgB,SAAS,CAAC;AAEvC,eAAO,MAAM,mBAAmB,oFAE/B,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG,YAAY,CAAC,OAAO,gBAAgB,CAAC,CAAC;AACrE,MAAM,MAAM,mBAAmB,GAAG,YAAY,CAAC,OAAO,mBAAmB,CAAC,CAAC"}
@@ -6,7 +6,7 @@ const tabsListVariants = cva(
6
6
  variants: {
7
7
  variant: {
8
8
  pills: "rounded-md bg-grey-100 dark:bg-grey-800 p-1 text-muted-foreground",
9
- underline: "border-b border-grey-200 dark:border-grey-700 bg-transparent p-0 gap-6 w-full justify-start",
9
+ underline: "border-b border-grey-200 dark:border-grey-700 bg-transparent p-0 gap-1 w-full justify-start",
10
10
  outline: "rounded-md border border-grey-200 dark:border-grey-700 bg-transparent p-1 gap-1"
11
11
  },
12
12
  size: {
@@ -44,8 +44,23 @@ const tabsTriggerVariants = cva(
44
44
  }
45
45
  }
46
46
  );
47
+ const tabsScrollButtonVariants = cva(
48
+ "pointer-events-auto flex size-8 shrink-0 items-center justify-center rounded-full border border-border bg-card text-foreground shadow-sm transition-colors hover:bg-accent [&_svg]:size-4"
49
+ );
50
+ const tabsScrollEdgeVariants = cva(
51
+ "pointer-events-none absolute inset-y-0 z-10 flex items-center",
52
+ {
53
+ variants: {
54
+ side: {
55
+ start: "start-0",
56
+ end: "end-0"
57
+ }
58
+ }
59
+ }
60
+ );
61
+ const TABS_SCROLL_FADE = "56px";
47
62
  const tabsContentVariants = cva(
48
63
  "mt-3 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary font-sans text-foreground data-[state=active]:animate-tab-slide"
49
64
  );
50
65
 
51
- export { tabsContentVariants, tabsListVariants, tabsTriggerVariants };
66
+ export { TABS_SCROLL_FADE, tabsContentVariants, tabsListVariants, tabsScrollButtonVariants, tabsScrollEdgeVariants, tabsTriggerVariants };
@@ -19,6 +19,19 @@ export interface TabsProps extends TabsPrimitive.TabsProps {
19
19
  motion?: MotionProp;
20
20
  }
21
21
  export interface TabsListProps extends React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>, TabsListVariants {
22
+ /**
23
+ * Let the tabs scroll sideways when they don't fit (e.g. on phones). Round
24
+ * chevron buttons appear at the edges while there is more to scroll.
25
+ * @default false
26
+ */
27
+ scrollable?: boolean;
28
+ /** Accessible names of the scroll buttons. */
29
+ scrollLabels?: {
30
+ previous?: string;
31
+ next?: string;
32
+ };
33
+ /** Content for the selected tab is loading (e.g. after a URL change): dims the tabs and sets aria-busy. */
34
+ loading?: boolean;
22
35
  }
23
36
  export interface TabsTriggerProps extends React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>, TabsTriggerVariants {
24
37
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"Tabs.types.d.ts","sourceRoot":"","sources":["../../../src/components/Tabs/Tabs.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AACpC,OAAO,KAAK,KAAK,aAAa,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAC3E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,MAAM,WAAW,SAAU,SAAQ,aAAa,CAAC,SAAS;IACxD;;;OAGG;IACH,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,GAAG,SAAS,CAAC;IAC5C;;;OAGG;IACH,IAAI,CAAC,EAAE,IAAI,GAAG,SAAS,GAAG,IAAI,GAAG,IAAI,CAAC;IACtC;;OAEG;IACH,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB;AAED,MAAM,WAAW,aACf,SAAQ,KAAK,CAAC,wBAAwB,CAAC,OAAO,aAAa,CAAC,IAAI,CAAC,EAC/D,gBAAgB;CAAG;AAEvB,MAAM,WAAW,gBACf,SAAQ,KAAK,CAAC,wBAAwB,CAAC,OAAO,aAAa,CAAC,OAAO,CAAC,EAClE,mBAAmB;IACrB;;OAEG;IACH,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB;AAED,MAAM,WAAW,gBACf,SAAQ,KAAK,CAAC,wBAAwB,CAAC,OAAO,aAAa,CAAC,OAAO,CAAC;IACpE;;OAEG;IACH,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB"}
1
+ {"version":3,"file":"Tabs.types.d.ts","sourceRoot":"","sources":["../../../src/components/Tabs/Tabs.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AACpC,OAAO,KAAK,KAAK,aAAa,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAC3E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,MAAM,WAAW,SAAU,SAAQ,aAAa,CAAC,SAAS;IACxD;;;OAGG;IACH,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,GAAG,SAAS,CAAC;IAC5C;;;OAGG;IACH,IAAI,CAAC,EAAE,IAAI,GAAG,SAAS,GAAG,IAAI,GAAG,IAAI,CAAC;IACtC;;OAEG;IACH,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB;AAED,MAAM,WAAW,aACf,SAAQ,KAAK,CAAC,wBAAwB,CAAC,OAAO,aAAa,CAAC,IAAI,CAAC,EAC/D,gBAAgB;IAClB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,8CAA8C;IAC9C,YAAY,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACpD,2GAA2G;IAC3G,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,gBACf,SAAQ,KAAK,CAAC,wBAAwB,CAAC,OAAO,aAAa,CAAC,OAAO,CAAC,EAClE,mBAAmB;IACrB;;OAEG;IACH,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB;AAED,MAAM,WAAW,gBACf,SAAQ,KAAK,CAAC,wBAAwB,CAAC,OAAO,aAAa,CAAC,OAAO,CAAC;IACpE;;OAEG;IACH,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB"}
@@ -1 +1 @@
1
- {"version":3,"file":"Text.d.ts","sourceRoot":"","sources":["../../../src/components/Text/Text.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,eAAO,MAAM,IAAI,+EAyChB,CAAC"}
1
+ {"version":3,"file":"Text.d.ts","sourceRoot":"","sources":["../../../src/components/Text/Text.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,eAAO,MAAM,IAAI,+EA6ChB,CAAC"}