@tribepad/themis 1.0.1 → 1.0.3

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/elements/Accordion/index.js +1 -335
  2. package/dist/elements/Accordion/index.js.map +1 -1
  3. package/dist/elements/Accordion/index.mjs +1 -317
  4. package/dist/elements/Accordion/index.mjs.map +1 -1
  5. package/dist/elements/AlertDialog/AlertDialog.d.ts +43 -0
  6. package/dist/elements/AlertDialog/AlertDialog.d.ts.map +1 -0
  7. package/dist/elements/AlertDialog/AlertDialog.styles.d.ts +15 -0
  8. package/dist/elements/AlertDialog/AlertDialog.styles.d.ts.map +1 -0
  9. package/dist/elements/AlertDialog/AlertDialog.types.d.ts +72 -0
  10. package/dist/elements/AlertDialog/AlertDialog.types.d.ts.map +1 -0
  11. package/dist/elements/AlertDialog/index.d.ts +25 -0
  12. package/dist/elements/AlertDialog/index.d.ts.map +1 -0
  13. package/dist/elements/AlertDialog/index.js +3 -0
  14. package/dist/elements/AlertDialog/index.js.map +1 -0
  15. package/dist/elements/AlertDialog/index.mjs +3 -0
  16. package/dist/elements/AlertDialog/index.mjs.map +1 -0
  17. package/dist/elements/Avatar/index.js +1 -468
  18. package/dist/elements/Avatar/index.js.map +1 -1
  19. package/dist/elements/Avatar/index.mjs +1 -456
  20. package/dist/elements/Avatar/index.mjs.map +1 -1
  21. package/dist/elements/Badge/index.js +1 -243
  22. package/dist/elements/Badge/index.js.map +1 -1
  23. package/dist/elements/Badge/index.mjs +1 -234
  24. package/dist/elements/Badge/index.mjs.map +1 -1
  25. package/dist/elements/Breadcrumbs/index.js +1 -821
  26. package/dist/elements/Breadcrumbs/index.js.map +1 -1
  27. package/dist/elements/Breadcrumbs/index.mjs +1 -810
  28. package/dist/elements/Breadcrumbs/index.mjs.map +1 -1
  29. package/dist/elements/Button/Button.d.ts +26 -81
  30. package/dist/elements/Button/Button.d.ts.map +1 -1
  31. package/dist/elements/Button/Button.styles.d.ts +35 -0
  32. package/dist/elements/Button/Button.styles.d.ts.map +1 -0
  33. package/dist/elements/Button/Button.types.d.ts +20 -8
  34. package/dist/elements/Button/Button.types.d.ts.map +1 -1
  35. package/dist/elements/Button/index.js +1 -288
  36. package/dist/elements/Button/index.js.map +1 -1
  37. package/dist/elements/Button/index.mjs +1 -283
  38. package/dist/elements/Button/index.mjs.map +1 -1
  39. package/dist/elements/ButtonGroup/index.js +1 -237
  40. package/dist/elements/ButtonGroup/index.js.map +1 -1
  41. package/dist/elements/ButtonGroup/index.mjs +1 -222
  42. package/dist/elements/ButtonGroup/index.mjs.map +1 -1
  43. package/dist/elements/Card/index.js +1 -579
  44. package/dist/elements/Card/index.js.map +1 -1
  45. package/dist/elements/Card/index.mjs +1 -560
  46. package/dist/elements/Card/index.mjs.map +1 -1
  47. package/dist/elements/Carousel/Carousel.d.ts +1 -11
  48. package/dist/elements/Carousel/Carousel.d.ts.map +1 -1
  49. package/dist/elements/Carousel/LazyCarousel.d.ts +1 -1
  50. package/dist/elements/Carousel/LazyCarousel.d.ts.map +1 -1
  51. package/dist/elements/Carousel/index.js +1 -789
  52. package/dist/elements/Carousel/index.js.map +1 -1
  53. package/dist/elements/Carousel/index.mjs +1 -786
  54. package/dist/elements/Carousel/index.mjs.map +1 -1
  55. package/dist/elements/Chart/ChartContext.d.ts.map +1 -1
  56. package/dist/elements/Chart/index.js +1 -1842
  57. package/dist/elements/Chart/index.js.map +1 -1
  58. package/dist/elements/Chart/index.mjs +1 -1832
  59. package/dist/elements/Chart/index.mjs.map +1 -1
  60. package/dist/elements/Checkbox/index.js +1 -316
  61. package/dist/elements/Checkbox/index.js.map +1 -1
  62. package/dist/elements/Checkbox/index.mjs +1 -306
  63. package/dist/elements/Checkbox/index.mjs.map +1 -1
  64. package/dist/elements/CheckboxGroup/index.js +1 -455
  65. package/dist/elements/CheckboxGroup/index.js.map +1 -1
  66. package/dist/elements/CheckboxGroup/index.mjs +1 -439
  67. package/dist/elements/CheckboxGroup/index.mjs.map +1 -1
  68. package/dist/elements/Combobox/Combobox.d.ts +56 -0
  69. package/dist/elements/Combobox/Combobox.d.ts.map +1 -0
  70. package/dist/elements/Combobox/Combobox.styles.d.ts +29 -0
  71. package/dist/elements/Combobox/Combobox.styles.d.ts.map +1 -0
  72. package/dist/elements/Combobox/Combobox.types.d.ts +67 -0
  73. package/dist/elements/Combobox/Combobox.types.d.ts.map +1 -0
  74. package/dist/elements/Combobox/index.d.ts +20 -0
  75. package/dist/elements/Combobox/index.d.ts.map +1 -0
  76. package/dist/elements/Combobox/index.js +3 -0
  77. package/dist/elements/Combobox/index.js.map +1 -0
  78. package/dist/elements/Combobox/index.mjs +3 -0
  79. package/dist/elements/Combobox/index.mjs.map +1 -0
  80. package/dist/elements/DatePicker/DatePicker.d.ts +1 -1
  81. package/dist/elements/DatePicker/DatePicker.d.ts.map +1 -1
  82. package/dist/elements/DatePicker/index.js +1 -903
  83. package/dist/elements/DatePicker/index.js.map +1 -1
  84. package/dist/elements/DatePicker/index.mjs +1 -853
  85. package/dist/elements/DatePicker/index.mjs.map +1 -1
  86. package/dist/elements/Dropdown/Dropdown.d.ts +7 -15
  87. package/dist/elements/Dropdown/Dropdown.d.ts.map +1 -1
  88. package/dist/elements/Dropdown/Dropdown.styles.d.ts +22 -0
  89. package/dist/elements/Dropdown/Dropdown.styles.d.ts.map +1 -0
  90. package/dist/elements/Dropdown/index.d.ts +1 -0
  91. package/dist/elements/Dropdown/index.d.ts.map +1 -1
  92. package/dist/elements/Dropdown/index.js +1 -193
  93. package/dist/elements/Dropdown/index.js.map +1 -1
  94. package/dist/elements/Dropdown/index.mjs +1 -184
  95. package/dist/elements/Dropdown/index.mjs.map +1 -1
  96. package/dist/elements/FileField/index.js +1 -1539
  97. package/dist/elements/FileField/index.js.map +1 -1
  98. package/dist/elements/FileField/index.mjs +1 -1507
  99. package/dist/elements/FileField/index.mjs.map +1 -1
  100. package/dist/elements/FormLayout/index.js +1 -170
  101. package/dist/elements/FormLayout/index.js.map +1 -1
  102. package/dist/elements/FormLayout/index.mjs +1 -167
  103. package/dist/elements/FormLayout/index.mjs.map +1 -1
  104. package/dist/elements/Modal/Modal.d.ts +9 -14
  105. package/dist/elements/Modal/Modal.d.ts.map +1 -1
  106. package/dist/elements/Modal/Modal.styles.d.ts +29 -0
  107. package/dist/elements/Modal/Modal.styles.d.ts.map +1 -0
  108. package/dist/elements/Modal/index.d.ts +1 -0
  109. package/dist/elements/Modal/index.d.ts.map +1 -1
  110. package/dist/elements/Modal/index.js +1 -232
  111. package/dist/elements/Modal/index.js.map +1 -1
  112. package/dist/elements/Modal/index.mjs +1 -220
  113. package/dist/elements/Modal/index.mjs.map +1 -1
  114. package/dist/elements/NumberField/NumberField.variants.d.ts +1 -1
  115. package/dist/elements/NumberField/index.js +1 -666
  116. package/dist/elements/NumberField/index.js.map +1 -1
  117. package/dist/elements/NumberField/index.mjs +1 -654
  118. package/dist/elements/NumberField/index.mjs.map +1 -1
  119. package/dist/elements/OTPInput/OTPInput.d.ts.map +1 -1
  120. package/dist/elements/OTPInput/index.js +1 -734
  121. package/dist/elements/OTPInput/index.js.map +1 -1
  122. package/dist/elements/OTPInput/index.mjs +1 -732
  123. package/dist/elements/OTPInput/index.mjs.map +1 -1
  124. package/dist/elements/Pagination/Pagination.d.ts +45 -0
  125. package/dist/elements/Pagination/Pagination.d.ts.map +1 -0
  126. package/dist/elements/Pagination/Pagination.styles.d.ts +10 -0
  127. package/dist/elements/Pagination/Pagination.styles.d.ts.map +1 -0
  128. package/dist/elements/Pagination/Pagination.types.d.ts +55 -0
  129. package/dist/elements/Pagination/Pagination.types.d.ts.map +1 -0
  130. package/dist/elements/Pagination/index.d.ts +21 -0
  131. package/dist/elements/Pagination/index.d.ts.map +1 -0
  132. package/dist/elements/Pagination/index.js +3 -0
  133. package/dist/elements/Pagination/index.js.map +1 -0
  134. package/dist/elements/Pagination/index.mjs +3 -0
  135. package/dist/elements/Pagination/index.mjs.map +1 -0
  136. package/dist/elements/Panel/index.js +1 -330
  137. package/dist/elements/Panel/index.js.map +1 -1
  138. package/dist/elements/Panel/index.mjs +1 -323
  139. package/dist/elements/Panel/index.mjs.map +1 -1
  140. package/dist/elements/PasswordField/PasswordField.d.ts +27 -0
  141. package/dist/elements/PasswordField/PasswordField.d.ts.map +1 -0
  142. package/dist/elements/PasswordField/PasswordField.styles.d.ts +32 -0
  143. package/dist/elements/PasswordField/PasswordField.styles.d.ts.map +1 -0
  144. package/dist/elements/PasswordField/PasswordField.types.d.ts +100 -0
  145. package/dist/elements/PasswordField/PasswordField.types.d.ts.map +1 -0
  146. package/dist/elements/PasswordField/index.css +2 -0
  147. package/dist/elements/PasswordField/index.css.map +1 -0
  148. package/dist/elements/PasswordField/index.d.ts +20 -0
  149. package/dist/elements/PasswordField/index.d.ts.map +1 -0
  150. package/dist/elements/PasswordField/index.js +3 -0
  151. package/dist/elements/PasswordField/index.js.map +1 -0
  152. package/dist/elements/PasswordField/index.mjs +3 -0
  153. package/dist/elements/PasswordField/index.mjs.map +1 -0
  154. package/dist/elements/Progress/index.js +1 -187
  155. package/dist/elements/Progress/index.js.map +1 -1
  156. package/dist/elements/Progress/index.mjs +1 -181
  157. package/dist/elements/Progress/index.mjs.map +1 -1
  158. package/dist/elements/RadioGroup/index.js +1 -369
  159. package/dist/elements/RadioGroup/index.js.map +1 -1
  160. package/dist/elements/RadioGroup/index.mjs +1 -359
  161. package/dist/elements/RadioGroup/index.mjs.map +1 -1
  162. package/dist/elements/Resizable/index.js +1 -1580
  163. package/dist/elements/Resizable/index.js.map +1 -1
  164. package/dist/elements/Resizable/index.mjs +1 -1566
  165. package/dist/elements/Resizable/index.mjs.map +1 -1
  166. package/dist/elements/SearchField/SearchField.d.ts +27 -0
  167. package/dist/elements/SearchField/SearchField.d.ts.map +1 -0
  168. package/dist/elements/SearchField/SearchField.styles.d.ts +32 -0
  169. package/dist/elements/SearchField/SearchField.styles.d.ts.map +1 -0
  170. package/dist/elements/SearchField/SearchField.types.d.ts +45 -0
  171. package/dist/elements/SearchField/SearchField.types.d.ts.map +1 -0
  172. package/dist/elements/SearchField/index.css +2 -0
  173. package/dist/elements/SearchField/index.css.map +1 -0
  174. package/dist/elements/SearchField/index.d.ts +21 -0
  175. package/dist/elements/SearchField/index.d.ts.map +1 -0
  176. package/dist/elements/SearchField/index.js +3 -0
  177. package/dist/elements/SearchField/index.js.map +1 -0
  178. package/dist/elements/SearchField/index.mjs +3 -0
  179. package/dist/elements/SearchField/index.mjs.map +1 -0
  180. package/dist/elements/Select/Select.d.ts +19 -48
  181. package/dist/elements/Select/Select.d.ts.map +1 -1
  182. package/dist/elements/Select/Select.styles.d.ts +55 -0
  183. package/dist/elements/Select/Select.styles.d.ts.map +1 -0
  184. package/dist/elements/Select/index.js +1 -589
  185. package/dist/elements/Select/index.js.map +1 -1
  186. package/dist/elements/Select/index.mjs +1 -582
  187. package/dist/elements/Select/index.mjs.map +1 -1
  188. package/dist/elements/Skeleton/index.js +1 -82
  189. package/dist/elements/Skeleton/index.js.map +1 -1
  190. package/dist/elements/Skeleton/index.mjs +1 -78
  191. package/dist/elements/Skeleton/index.mjs.map +1 -1
  192. package/dist/elements/Switch/index.js +1 -179
  193. package/dist/elements/Switch/index.js.map +1 -1
  194. package/dist/elements/Switch/index.mjs +1 -173
  195. package/dist/elements/Switch/index.mjs.map +1 -1
  196. package/dist/elements/Table/Table.d.ts +3 -24
  197. package/dist/elements/Table/Table.d.ts.map +1 -1
  198. package/dist/elements/Table/Table.styles.d.ts +24 -0
  199. package/dist/elements/Table/Table.styles.d.ts.map +1 -0
  200. package/dist/elements/Table/index.js +1 -595
  201. package/dist/elements/Table/index.js.map +1 -1
  202. package/dist/elements/Table/index.mjs +1 -578
  203. package/dist/elements/Table/index.mjs.map +1 -1
  204. package/dist/elements/Tabs/Tabs.d.ts +5 -3
  205. package/dist/elements/Tabs/Tabs.d.ts.map +1 -1
  206. package/dist/elements/Tabs/Tabs.types.d.ts +15 -0
  207. package/dist/elements/Tabs/Tabs.types.d.ts.map +1 -1
  208. package/dist/elements/Tabs/index.js +1 -337
  209. package/dist/elements/Tabs/index.js.map +1 -1
  210. package/dist/elements/Tabs/index.mjs +1 -320
  211. package/dist/elements/Tabs/index.mjs.map +1 -1
  212. package/dist/elements/TextField/TextField.d.ts +6 -42
  213. package/dist/elements/TextField/TextField.d.ts.map +1 -1
  214. package/dist/elements/TextField/TextField.hooks.d.ts +63 -0
  215. package/dist/elements/TextField/TextField.hooks.d.ts.map +1 -0
  216. package/dist/elements/TextField/TextField.icons.d.ts +19 -0
  217. package/dist/elements/TextField/TextField.icons.d.ts.map +1 -0
  218. package/dist/elements/TextField/TextField.styles.d.ts +37 -0
  219. package/dist/elements/TextField/TextField.styles.d.ts.map +1 -0
  220. package/dist/elements/TextField/TextField.types.d.ts +3 -0
  221. package/dist/elements/TextField/TextField.types.d.ts.map +1 -1
  222. package/dist/elements/TextField/index.css +1 -22
  223. package/dist/elements/TextField/index.css.map +1 -1
  224. package/dist/elements/TextField/index.js +1 -902
  225. package/dist/elements/TextField/index.js.map +1 -1
  226. package/dist/elements/TextField/index.mjs +1 -882
  227. package/dist/elements/TextField/index.mjs.map +1 -1
  228. package/dist/elements/TimeField/index.js +1 -254
  229. package/dist/elements/TimeField/index.js.map +1 -1
  230. package/dist/elements/TimeField/index.mjs +1 -238
  231. package/dist/elements/TimeField/index.mjs.map +1 -1
  232. package/dist/elements/Toast/Toast.d.ts +0 -22
  233. package/dist/elements/Toast/Toast.d.ts.map +1 -1
  234. package/dist/elements/Toast/index.js +1 -737
  235. package/dist/elements/Toast/index.js.map +1 -1
  236. package/dist/elements/Toast/index.mjs +1 -724
  237. package/dist/elements/Toast/index.mjs.map +1 -1
  238. package/dist/elements/Tooltip/index.js +1 -323
  239. package/dist/elements/Tooltip/index.js.map +1 -1
  240. package/dist/elements/Tooltip/index.mjs +1 -310
  241. package/dist/elements/Tooltip/index.mjs.map +1 -1
  242. package/dist/elements/index.css +1 -22
  243. package/dist/elements/index.css.map +1 -1
  244. package/dist/elements/index.d.ts +13 -1
  245. package/dist/elements/index.d.ts.map +1 -1
  246. package/dist/elements/index.js +1 -12455
  247. package/dist/elements/index.js.map +1 -1
  248. package/dist/elements/index.mjs +1 -12233
  249. package/dist/elements/index.mjs.map +1 -1
  250. package/dist/index.css +1 -22
  251. package/dist/index.css.map +1 -1
  252. package/dist/index.js +2 -12490
  253. package/dist/index.js.map +1 -1
  254. package/dist/index.mjs +2 -12262
  255. package/dist/index.mjs.map +1 -1
  256. package/dist/schemas/index.js +2 -54
  257. package/dist/schemas/index.js.map +1 -1
  258. package/dist/schemas/index.mjs +2 -48
  259. package/dist/schemas/index.mjs.map +1 -1
  260. package/dist/styles/defaults.css +151 -0
  261. package/dist/styles/index.js +1 -166
  262. package/dist/styles/index.js.map +1 -1
  263. package/dist/styles/index.mjs +1 -129
  264. package/dist/styles/index.mjs.map +1 -1
  265. package/dist/styles/shared-variants.d.ts +3 -3
  266. package/dist/styles/shared-variants.d.ts.map +1 -1
  267. package/dist/utils/index.js +1 -12
  268. package/dist/utils/index.js.map +1 -1
  269. package/dist/utils/index.mjs +1 -10
  270. package/dist/utils/index.mjs.map +1 -1
  271. package/package.json +9 -7
  272. package/src/elements/Accordion/Accordion.stories.tsx +1 -1
  273. package/src/elements/AlertDialog/AlertDialog.stories.tsx +124 -0
  274. package/src/elements/Avatar/Avatar.stories.tsx +1 -1
  275. package/src/elements/Badge/Badge.stories.tsx +1 -1
  276. package/src/elements/Breadcrumbs/Breadcrumbs.stories.tsx +1 -1
  277. package/src/elements/Button/Button.stories.tsx +1 -1
  278. package/src/elements/ButtonGroup/ButtonGroup.stories.tsx +1 -1
  279. package/src/elements/Card/Card.stories.tsx +1 -1
  280. package/src/elements/Carousel/Carousel.stories.tsx +1 -1
  281. package/src/elements/Chart/Chart.stories.tsx +1 -1
  282. package/src/elements/Checkbox/Checkbox.stories.tsx +1 -1
  283. package/src/elements/CheckboxGroup/CheckboxGroup.stories.tsx +4 -4
  284. package/src/elements/Combobox/Combobox.stories.tsx +133 -0
  285. package/src/elements/DatePicker/DatePicker.stories.tsx +1 -1
  286. package/src/elements/Dropdown/Dropdown.stories.tsx +1 -1
  287. package/src/elements/FileField/FileField.stories.tsx +2 -2
  288. package/src/elements/FileField/FileProgress.stories.tsx +1 -1
  289. package/src/elements/FormLayout/FormLayout.stories.tsx +1 -1
  290. package/src/elements/Modal/Modal.stories.tsx +1 -1
  291. package/src/elements/NumberField/NumberField.stories.tsx +1 -1
  292. package/src/elements/OTPInput/OTPInput.stories.tsx +1 -1
  293. package/src/elements/Pagination/Pagination.stories.tsx +203 -0
  294. package/src/elements/Panel/Panel.stories.tsx +1 -1
  295. package/src/elements/PasswordField/PasswordField.stories.tsx +167 -0
  296. package/src/elements/Progress/Progress.stories.tsx +7 -2
  297. package/src/elements/RadioGroup/RadioGroup.stories.tsx +3 -3
  298. package/src/elements/Resizable/Resizable.stories.tsx +1 -1
  299. package/src/elements/SearchField/SearchField.stories.tsx +146 -0
  300. package/src/elements/Select/Select.stories.tsx +1 -1
  301. package/src/elements/Skeleton/Skeleton.stories.tsx +1 -1
  302. package/src/elements/Switch/Switch.stories.tsx +1 -1
  303. package/src/elements/Table/Table.stories.tsx +1 -1
  304. package/src/elements/Tabs/Tabs.stories.tsx +46 -2
  305. package/src/elements/TextField/TextField.stories.tsx +1 -1
  306. package/src/elements/TimeField/TimeField.stories.tsx +1 -1
  307. package/src/elements/Toast/Toast.stories.tsx +1 -1
  308. package/src/elements/Tooltip/Tooltip.stories.tsx +1 -1
@@ -1,239 +1,3 @@
1
1
  "use client";
2
- 'use strict';
3
-
4
- var react = require('react');
5
- var reactAriaComponents = require('react-aria-components');
6
- var clsx = require('clsx');
7
- var tailwindMerge = require('tailwind-merge');
8
- var classVarianceAuthority = require('class-variance-authority');
9
- var jsxRuntime = require('react/jsx-runtime');
10
- var zod = require('zod');
11
-
12
- // src/elements/ButtonGroup/ButtonGroup.tsx
13
- function cn(...inputs) {
14
- return tailwindMerge.twMerge(clsx.clsx(inputs));
15
- }
16
- var ButtonGroupContext = react.createContext(null);
17
- ButtonGroupContext.displayName = "ButtonGroupContext";
18
- function useButtonGroupContext() {
19
- return react.useContext(ButtonGroupContext);
20
- }
21
- var ButtonGroupItemContext = react.createContext(null);
22
- ButtonGroupItemContext.displayName = "ButtonGroupItemContext";
23
- function useButtonGroupItemContext() {
24
- return react.useContext(ButtonGroupItemContext);
25
- }
26
- var buttonGroupVariants = classVarianceAuthority.cva("inline-flex items-center gap-0", {
27
- variants: {
28
- orientation: {
29
- horizontal: "flex-row",
30
- vertical: "flex-col w-full"
31
- }
32
- },
33
- defaultVariants: {
34
- orientation: "horizontal"
35
- }
36
- });
37
- var buttonGroupItemVariants = classVarianceAuthority.cva("", {
38
- variants: {
39
- orientation: {
40
- // min-w-[44px] ensures visual layer fills touch target width (for icon buttons)
41
- horizontal: "min-w-[44px]",
42
- // flex (overrides inline-flex) + min-h-[44px] makes visual layer fill touch target,
43
- // eliminating gaps between stacked buttons in vertical orientation
44
- vertical: "flex min-h-[44px]"
45
- },
46
- position: {
47
- first: "",
48
- middle: "",
49
- last: "",
50
- only: ""
51
- // Single button - no modifications needed
52
- }
53
- },
54
- compoundVariants: [
55
- // ==========================================================================
56
- // Horizontal Orientation
57
- // ==========================================================================
58
- {
59
- orientation: "horizontal",
60
- position: "first",
61
- className: "rounded-r-none border-r-0"
62
- },
63
- {
64
- orientation: "horizontal",
65
- position: "middle",
66
- className: "rounded-none border-r-0"
67
- },
68
- {
69
- orientation: "horizontal",
70
- position: "last",
71
- className: "rounded-l-none"
72
- },
73
- // ==========================================================================
74
- // Vertical Orientation
75
- // Note: w-full is handled by Button's effectiveFullWidth for both layers
76
- // ==========================================================================
77
- {
78
- orientation: "vertical",
79
- position: "first",
80
- className: "rounded-b-none border-b-0"
81
- },
82
- {
83
- orientation: "vertical",
84
- position: "middle",
85
- className: "rounded-none border-b-0"
86
- },
87
- {
88
- orientation: "vertical",
89
- position: "last",
90
- className: "rounded-t-none"
91
- }
92
- ],
93
- defaultVariants: {
94
- orientation: "horizontal",
95
- position: "only"
96
- }
97
- });
98
- var buttonGroupSeparatorVariants = classVarianceAuthority.cva("bg-[var(--border)]", {
99
- variants: {
100
- orientation: {
101
- horizontal: "w-px h-6 mx-1",
102
- vertical: "h-px w-full my-1"
103
- }
104
- },
105
- defaultVariants: {
106
- orientation: "horizontal"
107
- }
108
- });
109
- var isButtonElement = (child) => {
110
- if (!react.isValidElement(child)) return false;
111
- const componentType = child.type;
112
- return componentType?.displayName === "Button";
113
- };
114
- var isSeparatorElement = (child) => {
115
- if (!react.isValidElement(child)) return false;
116
- const componentType = child.type;
117
- return componentType?.displayName === "ButtonGroupSeparator";
118
- };
119
- var getPosition = (index, total) => {
120
- if (total === 1) return "only";
121
- if (index === 0) return "first";
122
- if (index === total - 1) return "last";
123
- return "middle";
124
- };
125
- var filterButtonChildren = (children) => {
126
- return children.filter(isButtonElement);
127
- };
128
- var getButtonIndex = (child, buttonChildren) => {
129
- return buttonChildren.indexOf(child);
130
- };
131
- var ButtonGroup = react.forwardRef(
132
- ({
133
- orientation = "horizontal",
134
- variant,
135
- size,
136
- isDisabled,
137
- className,
138
- children,
139
- ...props
140
- }, ref) => {
141
- const childArray = react.Children.toArray(children);
142
- const buttonChildren = childArray.filter(isButtonElement);
143
- const totalButtons = buttonChildren.length;
144
- const groupContextValue = {
145
- orientation,
146
- variant,
147
- size,
148
- isDisabled
149
- };
150
- const wrappedChildren = childArray.map((child, index) => {
151
- if (isButtonElement(child)) {
152
- const buttonIndex = buttonChildren.indexOf(child);
153
- const position = getPosition(buttonIndex, totalButtons);
154
- return /* @__PURE__ */ jsxRuntime.jsx(
155
- ButtonGroupItemContext.Provider,
156
- {
157
- value: { position },
158
- children: child
159
- },
160
- index
161
- );
162
- }
163
- return child;
164
- });
165
- return /* @__PURE__ */ jsxRuntime.jsx(
166
- reactAriaComponents.Toolbar,
167
- {
168
- ref,
169
- orientation,
170
- "aria-label": props["aria-label"],
171
- "aria-labelledby": props["aria-labelledby"],
172
- className: cn(buttonGroupVariants({ orientation }), className),
173
- children: /* @__PURE__ */ jsxRuntime.jsx(ButtonGroupContext.Provider, { value: groupContextValue, children: wrappedChildren })
174
- }
175
- );
176
- }
177
- );
178
- ButtonGroup.displayName = "ButtonGroup";
179
- var ButtonGroupSeparator = react.forwardRef(
180
- ({ className, ...props }, ref) => {
181
- const groupContext = useButtonGroupContext();
182
- const orientation = groupContext?.orientation ?? "horizontal";
183
- return /* @__PURE__ */ jsxRuntime.jsx(
184
- "div",
185
- {
186
- ref,
187
- role: "separator",
188
- "aria-hidden": "true",
189
- className: cn(
190
- buttonGroupSeparatorVariants({ orientation }),
191
- className
192
- ),
193
- ...props
194
- }
195
- );
196
- }
197
- );
198
- ButtonGroupSeparator.displayName = "ButtonGroupSeparator";
199
- var ButtonGroupPropsSchema = zod.z.object({
200
- /** Orientation of the button group layout */
201
- orientation: zod.z.enum(["horizontal", "vertical"]).optional().default("horizontal"),
202
- /** Default variant for all child buttons (can be overridden per-button) */
203
- variant: zod.z.enum(["default", "destructive", "outline", "secondary", "ghost"]).optional(),
204
- /** Default size for all child buttons (can be overridden per-button) */
205
- size: zod.z.enum(["sm", "default", "lg", "icon"]).optional(),
206
- /** Disable all buttons in the group */
207
- isDisabled: zod.z.boolean().optional(),
208
- /** Accessible label for the toolbar (recommended) */
209
- "aria-label": zod.z.string().optional(),
210
- /** ID of element that labels the toolbar */
211
- "aria-labelledby": zod.z.string().optional(),
212
- /** Additional CSS classes */
213
- className: zod.z.string().optional(),
214
- /** Child elements (Buttons, Separators, etc.) */
215
- children: zod.z.custom()
216
- });
217
- var ButtonGroupSeparatorPropsSchema = zod.z.object({
218
- /** Additional CSS classes */
219
- className: zod.z.string().optional(),
220
- /** Test ID for testing */
221
- "data-testid": zod.z.string().optional()
222
- });
223
-
224
- exports.ButtonGroup = ButtonGroup;
225
- exports.ButtonGroupPropsSchema = ButtonGroupPropsSchema;
226
- exports.ButtonGroupSeparator = ButtonGroupSeparator;
227
- exports.ButtonGroupSeparatorPropsSchema = ButtonGroupSeparatorPropsSchema;
228
- exports.buttonGroupItemVariants = buttonGroupItemVariants;
229
- exports.buttonGroupSeparatorVariants = buttonGroupSeparatorVariants;
230
- exports.buttonGroupVariants = buttonGroupVariants;
231
- exports.filterButtonChildren = filterButtonChildren;
232
- exports.getButtonIndex = getButtonIndex;
233
- exports.getPosition = getPosition;
234
- exports.isButtonElement = isButtonElement;
235
- exports.isSeparatorElement = isSeparatorElement;
236
- exports.useButtonGroupContext = useButtonGroupContext;
237
- exports.useButtonGroupItemContext = useButtonGroupItemContext;
238
- //# sourceMappingURL=index.js.map
2
+ 'use strict';var react=require('react'),reactAriaComponents=require('react-aria-components'),clsx=require('clsx'),tailwindMerge=require('tailwind-merge'),classVarianceAuthority=require('class-variance-authority'),jsxRuntime=require('react/jsx-runtime'),zod=require('zod');function s(...t){return tailwindMerge.twMerge(clsx.clsx(t))}var a=react.createContext(null);a.displayName="ButtonGroupContext";function m(){return react.useContext(a)}var u=react.createContext(null);u.displayName="ButtonGroupItemContext";function M(){return react.useContext(u)}var d=classVarianceAuthority.cva("inline-flex items-center gap-0",{variants:{orientation:{horizontal:"flex-row",vertical:"flex-col w-full"}},defaultVariants:{orientation:"horizontal"}}),A=classVarianceAuthority.cva("",{variants:{orientation:{horizontal:"min-w-[44px]",vertical:"flex min-h-[44px]"},position:{first:"",middle:"",last:"",only:""}},compoundVariants:[{orientation:"horizontal",position:"first",className:"rounded-r-none border-r-0"},{orientation:"horizontal",position:"middle",className:"rounded-none border-r-0"},{orientation:"horizontal",position:"last",className:"rounded-l-none"},{orientation:"vertical",position:"first",className:"rounded-b-none border-b-0"},{orientation:"vertical",position:"middle",className:"rounded-none border-b-0"},{orientation:"vertical",position:"last",className:"rounded-t-none"}],defaultVariants:{orientation:"horizontal",position:"only"}}),B=classVarianceAuthority.cva("bg-[var(--border)]",{variants:{orientation:{horizontal:"w-px h-6 mx-1",vertical:"h-px w-full my-1"}},defaultVariants:{orientation:"horizontal"}});var r=t=>react.isValidElement(t)?t.type?.displayName==="Button":false,H=t=>react.isValidElement(t)?t.type?.displayName==="ButtonGroupSeparator":false,x=(t,e)=>e===1?"only":t===0?"first":t===e-1?"last":"middle",L=t=>t.filter(r),j=(t,e)=>e.indexOf(t);var P=react.forwardRef(({orientation:t="horizontal",variant:e,size:p,isDisabled:f,className:l,children:S,...G},g)=>{let y=react.Children.toArray(S),b=y.filter(r),z=b.length,I={orientation:t,variant:e,size:p,isDisabled:f},R=y.map((n,E)=>{if(r(n)){let T=b.indexOf(n),w=x(T,z);return jsxRuntime.jsx(u.Provider,{value:{position:w},children:n},E)}return n});return jsxRuntime.jsx(reactAriaComponents.Toolbar,{ref:g,orientation:t,"aria-label":G["aria-label"],"aria-labelledby":G["aria-labelledby"],className:s(d({orientation:t}),l),children:jsxRuntime.jsx(a.Provider,{value:I,children:R})})});P.displayName="ButtonGroup";var N=react.forwardRef(({className:t,...e},p)=>{let l=m()?.orientation??"horizontal";return jsxRuntime.jsx("div",{ref:p,role:"separator","aria-hidden":"true",className:s(B({orientation:l}),t),...e})});N.displayName="ButtonGroupSeparator";var F=zod.z.object({orientation:zod.z.enum(["horizontal","vertical"]).optional().default("horizontal"),variant:zod.z.enum(["default","destructive","outline","secondary","ghost"]).optional(),size:zod.z.enum(["sm","default","lg","icon"]).optional(),isDisabled:zod.z.boolean().optional(),"aria-label":zod.z.string().optional(),"aria-labelledby":zod.z.string().optional(),className:zod.z.string().optional(),children:zod.z.custom()}),J=zod.z.object({className:zod.z.string().optional(),"data-testid":zod.z.string().optional()});exports.ButtonGroup=P;exports.ButtonGroupPropsSchema=F;exports.ButtonGroupSeparator=N;exports.ButtonGroupSeparatorPropsSchema=J;exports.buttonGroupItemVariants=A;exports.buttonGroupSeparatorVariants=B;exports.buttonGroupVariants=d;exports.filterButtonChildren=L;exports.getButtonIndex=j;exports.getPosition=x;exports.isButtonElement=r;exports.isSeparatorElement=H;exports.useButtonGroupContext=m;exports.useButtonGroupItemContext=M;//# sourceMappingURL=index.js.map
239
3
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/utils/cn.ts","../../../src/elements/ButtonGroup/ButtonGroupContext.tsx","../../../src/elements/ButtonGroup/ButtonGroup.variants.ts","../../../src/elements/ButtonGroup/ButtonGroup.utils.ts","../../../src/elements/ButtonGroup/ButtonGroup.tsx","../../../src/elements/ButtonGroup/ButtonGroup.types.ts"],"names":["twMerge","clsx","createContext","useContext","cva","isValidElement","forwardRef","Children","jsx","Toolbar","z"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Class Name Utility\n * Merges Tailwind CSS classes with conflict resolution\n *\n * Combines clsx for conditional classes and tailwind-merge for deduplication\n *\n * @example\n * cn('px-2 py-1', 'px-4') // => 'py-1 px-4' (px-4 overrides px-2)\n * cn('text-red-500', condition && 'text-blue-500') // => conditional application\n */\n\nimport { clsx, type ClassValue } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","\"use client\";\n\nimport { createContext, useContext } from 'react';\nimport type {\n ButtonGroupContextValue,\n ButtonGroupItemContextValue,\n} from './ButtonGroup.types';\n\n/**\n * ButtonGroup Context System (Two-Level)\n *\n * Provides a two-level context pattern for ButtonGroup:\n *\n * 1. ButtonGroupContext (group-level):\n * - Provides: orientation, variant, size, isDisabled\n * - Consumed by: Button (for prop inheritance), Separator (for orientation)\n *\n * 2. ButtonGroupItemContext (item-level):\n * - Provides: position ('first' | 'middle' | 'last' | 'only')\n * - Consumed by: Button (for border-radius styling)\n *\n * Both contexts return null when not in a provider, allowing Button\n * to work standalone without any group context.\n *\n * @see plan.md for architecture details\n * @see ButtonGroup.tsx for Provider implementation\n */\n\n// =============================================================================\n// Group-Level Context\n// =============================================================================\n\n/**\n * Context for group-level props (orientation, variant, size, isDisabled)\n * Default value is null to indicate \"not in a group\"\n */\nconst ButtonGroupContext = createContext<ButtonGroupContextValue | null>(null);\n\nButtonGroupContext.displayName = 'ButtonGroupContext';\n\n/**\n * Hook to access group-level context\n * @returns ButtonGroupContextValue if inside a ButtonGroup, null otherwise\n */\nexport function useButtonGroupContext(): ButtonGroupContextValue | null {\n return useContext(ButtonGroupContext);\n}\n\n// =============================================================================\n// Item-Level Context\n// =============================================================================\n\n/**\n * Context for per-button position information\n * Default value is null to indicate \"not wrapped with position context\"\n */\nconst ButtonGroupItemContext =\n createContext<ButtonGroupItemContextValue | null>(null);\n\nButtonGroupItemContext.displayName = 'ButtonGroupItemContext';\n\n/**\n * Hook to access item-level context (position)\n * @returns ButtonGroupItemContextValue if wrapped with position context, null otherwise\n */\nexport function useButtonGroupItemContext(): ButtonGroupItemContextValue | null {\n return useContext(ButtonGroupItemContext);\n}\n\n// =============================================================================\n// Exports\n// =============================================================================\n\nexport { ButtonGroupContext, ButtonGroupItemContext };\n","import { cva } from 'class-variance-authority';\n\n/**\n * ButtonGroup CVA Variants\n *\n * Defines Class Variance Authority (CVA) variants for:\n * - ButtonGroup container (orientation-based layout)\n * - ButtonGroupItem (position-based border-radius)\n * - ButtonGroupSeparator (orientation-based styling)\n *\n * @see plan.md Phase 1: Design & Contracts - CVA Variants\n * @see constitution.md Principle V (Component Quality Standards)\n */\n\n// =============================================================================\n// Container Variants\n// =============================================================================\n\n/**\n * ButtonGroup container variants\n * Controls the layout direction based on orientation\n * Uses gap-0 to ensure buttons are connected (share borders)\n */\nexport const buttonGroupVariants = cva('inline-flex items-center gap-0', {\n variants: {\n orientation: {\n horizontal: 'flex-row',\n vertical: 'flex-col w-full',\n },\n },\n defaultVariants: {\n orientation: 'horizontal',\n },\n});\n\n// =============================================================================\n// Item Position Variants\n// =============================================================================\n\n/**\n * ButtonGroupItem position variants\n * Applied to Button's visual layer (Layer 2) for position-aware border-radius\n *\n * Compound variants handle both orientation and position combinations:\n * - Horizontal: left/right borders and radii\n * - Vertical: top/bottom borders and radii\n */\nexport const buttonGroupItemVariants = cva('', {\n variants: {\n orientation: {\n // min-w-[44px] ensures visual layer fills touch target width (for icon buttons)\n horizontal: 'min-w-[44px]',\n // flex (overrides inline-flex) + min-h-[44px] makes visual layer fill touch target,\n // eliminating gaps between stacked buttons in vertical orientation\n vertical: 'flex min-h-[44px]',\n },\n position: {\n first: '',\n middle: '',\n last: '',\n only: '', // Single button - no modifications needed\n },\n },\n compoundVariants: [\n // ==========================================================================\n // Horizontal Orientation\n // ==========================================================================\n {\n orientation: 'horizontal',\n position: 'first',\n className: 'rounded-r-none border-r-0',\n },\n {\n orientation: 'horizontal',\n position: 'middle',\n className: 'rounded-none border-r-0',\n },\n {\n orientation: 'horizontal',\n position: 'last',\n className: 'rounded-l-none',\n },\n // ==========================================================================\n // Vertical Orientation\n // Note: w-full is handled by Button's effectiveFullWidth for both layers\n // ==========================================================================\n {\n orientation: 'vertical',\n position: 'first',\n className: 'rounded-b-none border-b-0',\n },\n {\n orientation: 'vertical',\n position: 'middle',\n className: 'rounded-none border-b-0',\n },\n {\n orientation: 'vertical',\n position: 'last',\n className: 'rounded-t-none',\n },\n ],\n defaultVariants: {\n orientation: 'horizontal',\n position: 'only',\n },\n});\n\n// =============================================================================\n// Separator Variants\n// =============================================================================\n\n/**\n * ButtonGroupSeparator variants\n * Orientation-aware visual divider between button groups\n */\nexport const buttonGroupSeparatorVariants = cva('bg-[var(--border)]', {\n variants: {\n orientation: {\n horizontal: 'w-px h-6 mx-1',\n vertical: 'h-px w-full my-1',\n },\n },\n defaultVariants: {\n orientation: 'horizontal',\n },\n});\n","import { isValidElement, type ReactNode, type ComponentType } from 'react';\nimport type { ButtonPosition } from './ButtonGroup.types';\n\n/**\n * ButtonGroup Utility Functions\n *\n * Provides helper functions for:\n * - Child element detection (Button vs Separator vs other)\n * - Position calculation for border-radius styling\n *\n * @see plan.md Decision 6: Non-Button Child Handling\n */\n\n// =============================================================================\n// Child Detection Functions\n// =============================================================================\n\n/**\n * Checks if a React child is a Themis Button component\n * Uses displayName for reliable detection across module boundaries\n *\n * @param child - React child element to check\n * @returns true if the child is a Button component\n */\nexport const isButtonElement = (child: ReactNode): boolean => {\n if (!isValidElement(child)) return false;\n\n const componentType = child.type as ComponentType;\n return componentType?.displayName === 'Button';\n};\n\n/**\n * Checks if a React child is a ButtonGroupSeparator component\n * Uses displayName for reliable detection across module boundaries\n *\n * @param child - React child element to check\n * @returns true if the child is a ButtonGroupSeparator component\n */\nexport const isSeparatorElement = (child: ReactNode): boolean => {\n if (!isValidElement(child)) return false;\n\n const componentType = child.type as ComponentType;\n return componentType?.displayName === 'ButtonGroupSeparator';\n};\n\n// =============================================================================\n// Position Calculation\n// =============================================================================\n\n/**\n * Calculates the position of a button within a group\n * Used for applying position-aware border-radius styling\n *\n * @param index - Zero-based index of the button\n * @param total - Total number of buttons in the group\n * @returns Position enum: 'only' | 'first' | 'last' | 'middle'\n *\n * @example\n * getPosition(0, 1) // 'only' - single button\n * getPosition(0, 3) // 'first'\n * getPosition(1, 3) // 'middle'\n * getPosition(2, 3) // 'last'\n */\nexport const getPosition = (index: number, total: number): ButtonPosition => {\n if (total === 1) return 'only';\n if (index === 0) return 'first';\n if (index === total - 1) return 'last';\n return 'middle';\n};\n\n/**\n * Filters an array of React children to only include Button elements\n * Non-Button children (Separators, custom elements) are excluded\n *\n * @param children - Array of React children\n * @returns Array containing only Button elements\n */\nexport const filterButtonChildren = (children: ReactNode[]): ReactNode[] => {\n return children.filter(isButtonElement);\n};\n\n/**\n * Gets the index of a button within the filtered button array\n * Used when the child array contains non-Button elements (Separators, etc.)\n *\n * @param child - The button element to find\n * @param buttonChildren - Array of only Button elements\n * @returns Index of the button, or -1 if not found\n */\nexport const getButtonIndex = (\n child: ReactNode,\n buttonChildren: ReactNode[]\n): number => {\n return buttonChildren.indexOf(child);\n};\n","\"use client\";\n\n/**\n * ButtonGroup Component\n *\n * A container that groups related Themis Button components with:\n * - Consistent styling (connected borders, position-aware radii)\n * - Accessible keyboard navigation (React Aria Toolbar)\n * - WCAG 2.2 AAA compliance\n *\n * @see plan.md for architecture details\n * @see buttongroup-prd.md for requirements\n */\n\nimport { forwardRef, Children, type ReactElement } from 'react';\nimport { Toolbar } from 'react-aria-components';\nimport { cn } from '../../utils/cn';\nimport {\n ButtonGroupContext,\n ButtonGroupItemContext,\n useButtonGroupContext,\n} from './ButtonGroupContext';\nimport { buttonGroupVariants, buttonGroupSeparatorVariants } from './ButtonGroup.variants';\nimport { isButtonElement, getPosition } from './ButtonGroup.utils';\nimport type { ButtonGroupProps, ButtonGroupSeparatorProps } from './ButtonGroup.types';\n\n// =============================================================================\n// ButtonGroup Component\n// =============================================================================\n\n/**\n * ButtonGroup - Groups related buttons with connected styling and keyboard navigation\n *\n * Uses React Aria's Toolbar for:\n * - Roving tabindex (single tab stop)\n * - Arrow key navigation\n * - Home/End key support\n * - RTL support\n *\n * @example\n * ```tsx\n * <ButtonGroup aria-label=\"Text formatting\">\n * <Button variant=\"outline\">Bold</Button>\n * <Button variant=\"outline\">Italic</Button>\n * <Button variant=\"outline\">Underline</Button>\n * </ButtonGroup>\n * ```\n */\nconst ButtonGroup = forwardRef<HTMLDivElement, ButtonGroupProps>(\n (\n {\n orientation = 'horizontal',\n variant,\n size,\n isDisabled,\n className,\n children,\n ...props\n },\n ref\n ): ReactElement => {\n // Convert children to array for enumeration\n const childArray = Children.toArray(children);\n\n // Filter to get only Button elements for position calculation\n const buttonChildren = childArray.filter(isButtonElement);\n const totalButtons = buttonChildren.length;\n\n // Create context value for group-level props\n const groupContextValue = {\n orientation,\n variant,\n size,\n isDisabled,\n };\n\n // Wrap each child with appropriate context\n const wrappedChildren = childArray.map((child, index) => {\n // If it's a Button, wrap with item context for position\n if (isButtonElement(child)) {\n const buttonIndex = buttonChildren.indexOf(child);\n const position = getPosition(buttonIndex, totalButtons);\n\n return (\n <ButtonGroupItemContext.Provider\n key={index}\n value={{ position }}\n >\n {child}\n </ButtonGroupItemContext.Provider>\n );\n }\n\n // Non-Button children (Separators, etc.) pass through without item context\n return child;\n });\n\n return (\n <Toolbar\n ref={ref}\n orientation={orientation}\n aria-label={props['aria-label']}\n aria-labelledby={props['aria-labelledby']}\n className={cn(buttonGroupVariants({ orientation }), className)}\n >\n <ButtonGroupContext.Provider value={groupContextValue}>\n {wrappedChildren}\n </ButtonGroupContext.Provider>\n </Toolbar>\n );\n }\n);\n\nButtonGroup.displayName = 'ButtonGroup';\n\n// =============================================================================\n// ButtonGroupSeparator Component\n// =============================================================================\n\n/**\n * ButtonGroupSeparator - Visual divider between button groups\n *\n * Renders a decorative separator that:\n * - Adapts to orientation (vertical line for horizontal, horizontal for vertical)\n * - Is hidden from screen readers (aria-hidden)\n * - Is excluded from keyboard navigation\n *\n * @example\n * ```tsx\n * <ButtonGroup aria-label=\"Editor actions\">\n * <Button>Undo</Button>\n * <Button>Redo</Button>\n * <ButtonGroupSeparator />\n * <Button>Cut</Button>\n * <Button>Copy</Button>\n * </ButtonGroup>\n * ```\n */\nconst ButtonGroupSeparator = forwardRef<HTMLDivElement, ButtonGroupSeparatorProps>(\n ({ className, ...props }, ref): ReactElement => {\n const groupContext = useButtonGroupContext();\n const orientation = groupContext?.orientation ?? 'horizontal';\n\n return (\n <div\n ref={ref}\n role=\"separator\"\n aria-hidden=\"true\"\n className={cn(\n buttonGroupSeparatorVariants({ orientation }),\n className\n )}\n {...props}\n />\n );\n }\n);\n\nButtonGroupSeparator.displayName = 'ButtonGroupSeparator';\n\n// =============================================================================\n// Exports\n// =============================================================================\n\nexport { ButtonGroup, ButtonGroupSeparator };\n","import { z } from 'zod';\nimport type { ReactNode } from 'react';\n\n/**\n * ButtonGroup Component Types\n *\n * Defines Zod schemas and TypeScript types for the ButtonGroup component.\n * Uses a two-level context pattern:\n * - ButtonGroupContext: Group-level props (orientation, variant, size, isDisabled)\n * - ButtonGroupItemContext: Per-button position information\n *\n * @see plan.md for architecture details\n * @see constitution.md Principle II (Type Safety First)\n */\n\n// =============================================================================\n// Core Types\n// =============================================================================\n\n/**\n * Orientation of the button group\n */\nexport type ButtonGroupOrientation = 'horizontal' | 'vertical';\n\n/**\n * Position of a button within the group\n * Used for position-aware border-radius styling\n */\nexport type ButtonPosition = 'first' | 'middle' | 'last' | 'only';\n\n/**\n * Button variants (matches Themis Button variants, excluding 'link')\n * Link variant is excluded as it doesn't make sense in a grouped context\n */\nexport type ButtonGroupVariant =\n | 'default'\n | 'destructive'\n | 'outline'\n | 'secondary'\n | 'ghost';\n\n/**\n * Button sizes (matches Themis Button sizes)\n */\nexport type ButtonGroupSize = 'sm' | 'default' | 'lg' | 'icon';\n\n// =============================================================================\n// Zod Schemas\n// =============================================================================\n\n/**\n * ButtonGroup props schema\n * Validates all props for the ButtonGroup container component\n */\nexport const ButtonGroupPropsSchema = z.object({\n /** Orientation of the button group layout */\n orientation: z\n .enum(['horizontal', 'vertical'])\n .optional()\n .default('horizontal'),\n\n /** Default variant for all child buttons (can be overridden per-button) */\n variant: z\n .enum(['default', 'destructive', 'outline', 'secondary', 'ghost'])\n .optional(),\n\n /** Default size for all child buttons (can be overridden per-button) */\n size: z.enum(['sm', 'default', 'lg', 'icon']).optional(),\n\n /** Disable all buttons in the group */\n isDisabled: z.boolean().optional(),\n\n /** Accessible label for the toolbar (recommended) */\n 'aria-label': z.string().optional(),\n\n /** ID of element that labels the toolbar */\n 'aria-labelledby': z.string().optional(),\n\n /** Additional CSS classes */\n className: z.string().optional(),\n\n /** Child elements (Buttons, Separators, etc.) */\n children: z.custom<ReactNode>(),\n});\n\n/**\n * ButtonGroupSeparator props schema\n * Validates props for the visual separator between button groups\n */\nexport const ButtonGroupSeparatorPropsSchema = z.object({\n /** Additional CSS classes */\n className: z.string().optional(),\n /** Test ID for testing */\n 'data-testid': z.string().optional(),\n});\n\n// =============================================================================\n// TypeScript Types (inferred from schemas)\n// =============================================================================\n\n/**\n * Props for the ButtonGroup container component\n */\nexport type ButtonGroupProps = z.infer<typeof ButtonGroupPropsSchema>;\n\n/**\n * Props for the ButtonGroupSeparator component\n */\nexport type ButtonGroupSeparatorProps = z.infer<\n typeof ButtonGroupSeparatorPropsSchema\n>;\n\n// =============================================================================\n// Context Types\n// =============================================================================\n\n/**\n * Group-level context value\n * Provides inherited props to all child buttons\n */\nexport interface ButtonGroupContextValue {\n /** Orientation of the group (affects keyboard navigation and styling) */\n orientation: ButtonGroupOrientation;\n /** Default variant for buttons (can be overridden) */\n variant?: ButtonGroupVariant;\n /** Default size for buttons (can be overridden) */\n size?: ButtonGroupSize;\n /** Whether all buttons in the group are disabled */\n isDisabled?: boolean;\n}\n\n/**\n * Item-level context value\n * Provides position information to each button for border-radius styling\n */\nexport interface ButtonGroupItemContextValue {\n /** Position of this button in the group */\n position: ButtonPosition;\n}\n"]}
1
+ {"version":3,"sources":["../../../src/utils/cn.ts","../../../src/elements/ButtonGroup/ButtonGroupContext.tsx","../../../src/elements/ButtonGroup/ButtonGroup.variants.ts","../../../src/elements/ButtonGroup/ButtonGroup.utils.ts","../../../src/elements/ButtonGroup/ButtonGroup.tsx","../../../src/elements/ButtonGroup/ButtonGroup.types.ts"],"names":["cn","inputs","twMerge","clsx","ButtonGroupContext","createContext","useButtonGroupContext","useContext","ButtonGroupItemContext","useButtonGroupItemContext","buttonGroupVariants","cva","buttonGroupItemVariants","buttonGroupSeparatorVariants","isButtonElement","child","isValidElement","isSeparatorElement","getPosition","index","total","filterButtonChildren","children","getButtonIndex","buttonChildren","ButtonGroup","forwardRef","orientation","variant","size","isDisabled","className","props","ref","childArray","Children","totalButtons","groupContextValue","wrappedChildren","buttonIndex","position","jsx","Toolbar","ButtonGroupSeparator","ButtonGroupPropsSchema","z","ButtonGroupSeparatorPropsSchema"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Class Name Utility\n * Merges Tailwind CSS classes with conflict resolution\n *\n * Combines clsx for conditional classes and tailwind-merge for deduplication\n *\n * @example\n * cn('px-2 py-1', 'px-4') // => 'py-1 px-4' (px-4 overrides px-2)\n * cn('text-red-500', condition && 'text-blue-500') // => conditional application\n */\n\nimport { clsx, type ClassValue } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","\"use client\";\n\nimport { createContext, useContext } from 'react';\nimport type {\n ButtonGroupContextValue,\n ButtonGroupItemContextValue,\n} from './ButtonGroup.types';\n\n/**\n * ButtonGroup Context System (Two-Level)\n *\n * Provides a two-level context pattern for ButtonGroup:\n *\n * 1. ButtonGroupContext (group-level):\n * - Provides: orientation, variant, size, isDisabled\n * - Consumed by: Button (for prop inheritance), Separator (for orientation)\n *\n * 2. ButtonGroupItemContext (item-level):\n * - Provides: position ('first' | 'middle' | 'last' | 'only')\n * - Consumed by: Button (for border-radius styling)\n *\n * Both contexts return null when not in a provider, allowing Button\n * to work standalone without any group context.\n *\n * @see plan.md for architecture details\n * @see ButtonGroup.tsx for Provider implementation\n */\n\n// =============================================================================\n// Group-Level Context\n// =============================================================================\n\n/**\n * Context for group-level props (orientation, variant, size, isDisabled)\n * Default value is null to indicate \"not in a group\"\n */\nconst ButtonGroupContext = createContext<ButtonGroupContextValue | null>(null);\n\nButtonGroupContext.displayName = 'ButtonGroupContext';\n\n/**\n * Hook to access group-level context\n * @returns ButtonGroupContextValue if inside a ButtonGroup, null otherwise\n */\nexport function useButtonGroupContext(): ButtonGroupContextValue | null {\n return useContext(ButtonGroupContext);\n}\n\n// =============================================================================\n// Item-Level Context\n// =============================================================================\n\n/**\n * Context for per-button position information\n * Default value is null to indicate \"not wrapped with position context\"\n */\nconst ButtonGroupItemContext =\n createContext<ButtonGroupItemContextValue | null>(null);\n\nButtonGroupItemContext.displayName = 'ButtonGroupItemContext';\n\n/**\n * Hook to access item-level context (position)\n * @returns ButtonGroupItemContextValue if wrapped with position context, null otherwise\n */\nexport function useButtonGroupItemContext(): ButtonGroupItemContextValue | null {\n return useContext(ButtonGroupItemContext);\n}\n\n// =============================================================================\n// Exports\n// =============================================================================\n\nexport { ButtonGroupContext, ButtonGroupItemContext };\n","import { cva } from 'class-variance-authority';\n\n/**\n * ButtonGroup CVA Variants\n *\n * Defines Class Variance Authority (CVA) variants for:\n * - ButtonGroup container (orientation-based layout)\n * - ButtonGroupItem (position-based border-radius)\n * - ButtonGroupSeparator (orientation-based styling)\n *\n * @see plan.md Phase 1: Design & Contracts - CVA Variants\n * @see constitution.md Principle V (Component Quality Standards)\n */\n\n// =============================================================================\n// Container Variants\n// =============================================================================\n\n/**\n * ButtonGroup container variants\n * Controls the layout direction based on orientation\n * Uses gap-0 to ensure buttons are connected (share borders)\n */\nexport const buttonGroupVariants = cva('inline-flex items-center gap-0', {\n variants: {\n orientation: {\n horizontal: 'flex-row',\n vertical: 'flex-col w-full',\n },\n },\n defaultVariants: {\n orientation: 'horizontal',\n },\n});\n\n// =============================================================================\n// Item Position Variants\n// =============================================================================\n\n/**\n * ButtonGroupItem position variants\n * Applied to Button's visual layer (Layer 2) for position-aware border-radius\n *\n * Compound variants handle both orientation and position combinations:\n * - Horizontal: left/right borders and radii\n * - Vertical: top/bottom borders and radii\n */\nexport const buttonGroupItemVariants = cva('', {\n variants: {\n orientation: {\n // min-w-[44px] ensures visual layer fills touch target width (for icon buttons)\n horizontal: 'min-w-[44px]',\n // flex (overrides inline-flex) + min-h-[44px] makes visual layer fill touch target,\n // eliminating gaps between stacked buttons in vertical orientation\n vertical: 'flex min-h-[44px]',\n },\n position: {\n first: '',\n middle: '',\n last: '',\n only: '', // Single button - no modifications needed\n },\n },\n compoundVariants: [\n // ==========================================================================\n // Horizontal Orientation\n // ==========================================================================\n {\n orientation: 'horizontal',\n position: 'first',\n className: 'rounded-r-none border-r-0',\n },\n {\n orientation: 'horizontal',\n position: 'middle',\n className: 'rounded-none border-r-0',\n },\n {\n orientation: 'horizontal',\n position: 'last',\n className: 'rounded-l-none',\n },\n // ==========================================================================\n // Vertical Orientation\n // Note: w-full is handled by Button's effectiveFullWidth for both layers\n // ==========================================================================\n {\n orientation: 'vertical',\n position: 'first',\n className: 'rounded-b-none border-b-0',\n },\n {\n orientation: 'vertical',\n position: 'middle',\n className: 'rounded-none border-b-0',\n },\n {\n orientation: 'vertical',\n position: 'last',\n className: 'rounded-t-none',\n },\n ],\n defaultVariants: {\n orientation: 'horizontal',\n position: 'only',\n },\n});\n\n// =============================================================================\n// Separator Variants\n// =============================================================================\n\n/**\n * ButtonGroupSeparator variants\n * Orientation-aware visual divider between button groups\n */\nexport const buttonGroupSeparatorVariants = cva('bg-[var(--border)]', {\n variants: {\n orientation: {\n horizontal: 'w-px h-6 mx-1',\n vertical: 'h-px w-full my-1',\n },\n },\n defaultVariants: {\n orientation: 'horizontal',\n },\n});\n","import { isValidElement, type ReactNode, type ComponentType } from 'react';\nimport type { ButtonPosition } from './ButtonGroup.types';\n\n/**\n * ButtonGroup Utility Functions\n *\n * Provides helper functions for:\n * - Child element detection (Button vs Separator vs other)\n * - Position calculation for border-radius styling\n *\n * @see plan.md Decision 6: Non-Button Child Handling\n */\n\n// =============================================================================\n// Child Detection Functions\n// =============================================================================\n\n/**\n * Checks if a React child is a Themis Button component\n * Uses displayName for reliable detection across module boundaries\n *\n * @param child - React child element to check\n * @returns true if the child is a Button component\n */\nexport const isButtonElement = (child: ReactNode): boolean => {\n if (!isValidElement(child)) return false;\n\n const componentType = child.type as ComponentType;\n return componentType?.displayName === 'Button';\n};\n\n/**\n * Checks if a React child is a ButtonGroupSeparator component\n * Uses displayName for reliable detection across module boundaries\n *\n * @param child - React child element to check\n * @returns true if the child is a ButtonGroupSeparator component\n */\nexport const isSeparatorElement = (child: ReactNode): boolean => {\n if (!isValidElement(child)) return false;\n\n const componentType = child.type as ComponentType;\n return componentType?.displayName === 'ButtonGroupSeparator';\n};\n\n// =============================================================================\n// Position Calculation\n// =============================================================================\n\n/**\n * Calculates the position of a button within a group\n * Used for applying position-aware border-radius styling\n *\n * @param index - Zero-based index of the button\n * @param total - Total number of buttons in the group\n * @returns Position enum: 'only' | 'first' | 'last' | 'middle'\n *\n * @example\n * getPosition(0, 1) // 'only' - single button\n * getPosition(0, 3) // 'first'\n * getPosition(1, 3) // 'middle'\n * getPosition(2, 3) // 'last'\n */\nexport const getPosition = (index: number, total: number): ButtonPosition => {\n if (total === 1) return 'only';\n if (index === 0) return 'first';\n if (index === total - 1) return 'last';\n return 'middle';\n};\n\n/**\n * Filters an array of React children to only include Button elements\n * Non-Button children (Separators, custom elements) are excluded\n *\n * @param children - Array of React children\n * @returns Array containing only Button elements\n */\nexport const filterButtonChildren = (children: ReactNode[]): ReactNode[] => {\n return children.filter(isButtonElement);\n};\n\n/**\n * Gets the index of a button within the filtered button array\n * Used when the child array contains non-Button elements (Separators, etc.)\n *\n * @param child - The button element to find\n * @param buttonChildren - Array of only Button elements\n * @returns Index of the button, or -1 if not found\n */\nexport const getButtonIndex = (\n child: ReactNode,\n buttonChildren: ReactNode[]\n): number => {\n return buttonChildren.indexOf(child);\n};\n","\"use client\";\n\n/**\n * ButtonGroup Component\n *\n * A container that groups related Themis Button components with:\n * - Consistent styling (connected borders, position-aware radii)\n * - Accessible keyboard navigation (React Aria Toolbar)\n * - WCAG 2.2 AAA compliance\n *\n * @see plan.md for architecture details\n * @see buttongroup-prd.md for requirements\n */\n\nimport { forwardRef, Children, type ReactElement } from 'react';\nimport { Toolbar } from 'react-aria-components';\nimport { cn } from '../../utils/cn';\nimport {\n ButtonGroupContext,\n ButtonGroupItemContext,\n useButtonGroupContext,\n} from './ButtonGroupContext';\nimport { buttonGroupVariants, buttonGroupSeparatorVariants } from './ButtonGroup.variants';\nimport { isButtonElement, getPosition } from './ButtonGroup.utils';\nimport type { ButtonGroupProps, ButtonGroupSeparatorProps } from './ButtonGroup.types';\n\n// =============================================================================\n// ButtonGroup Component\n// =============================================================================\n\n/**\n * ButtonGroup - Groups related buttons with connected styling and keyboard navigation\n *\n * Uses React Aria's Toolbar for:\n * - Roving tabindex (single tab stop)\n * - Arrow key navigation\n * - Home/End key support\n * - RTL support\n *\n * @example\n * ```tsx\n * <ButtonGroup aria-label=\"Text formatting\">\n * <Button variant=\"outline\">Bold</Button>\n * <Button variant=\"outline\">Italic</Button>\n * <Button variant=\"outline\">Underline</Button>\n * </ButtonGroup>\n * ```\n */\nconst ButtonGroup = forwardRef<HTMLDivElement, ButtonGroupProps>(\n (\n {\n orientation = 'horizontal',\n variant,\n size,\n isDisabled,\n className,\n children,\n ...props\n },\n ref\n ): ReactElement => {\n // Convert children to array for enumeration\n const childArray = Children.toArray(children);\n\n // Filter to get only Button elements for position calculation\n const buttonChildren = childArray.filter(isButtonElement);\n const totalButtons = buttonChildren.length;\n\n // Create context value for group-level props\n const groupContextValue = {\n orientation,\n variant,\n size,\n isDisabled,\n };\n\n // Wrap each child with appropriate context\n const wrappedChildren = childArray.map((child, index) => {\n // If it's a Button, wrap with item context for position\n if (isButtonElement(child)) {\n const buttonIndex = buttonChildren.indexOf(child);\n const position = getPosition(buttonIndex, totalButtons);\n\n return (\n <ButtonGroupItemContext.Provider\n key={index}\n value={{ position }}\n >\n {child}\n </ButtonGroupItemContext.Provider>\n );\n }\n\n // Non-Button children (Separators, etc.) pass through without item context\n return child;\n });\n\n return (\n <Toolbar\n ref={ref}\n orientation={orientation}\n aria-label={props['aria-label']}\n aria-labelledby={props['aria-labelledby']}\n className={cn(buttonGroupVariants({ orientation }), className)}\n >\n <ButtonGroupContext.Provider value={groupContextValue}>\n {wrappedChildren}\n </ButtonGroupContext.Provider>\n </Toolbar>\n );\n }\n);\n\nButtonGroup.displayName = 'ButtonGroup';\n\n// =============================================================================\n// ButtonGroupSeparator Component\n// =============================================================================\n\n/**\n * ButtonGroupSeparator - Visual divider between button groups\n *\n * Renders a decorative separator that:\n * - Adapts to orientation (vertical line for horizontal, horizontal for vertical)\n * - Is hidden from screen readers (aria-hidden)\n * - Is excluded from keyboard navigation\n *\n * @example\n * ```tsx\n * <ButtonGroup aria-label=\"Editor actions\">\n * <Button>Undo</Button>\n * <Button>Redo</Button>\n * <ButtonGroupSeparator />\n * <Button>Cut</Button>\n * <Button>Copy</Button>\n * </ButtonGroup>\n * ```\n */\nconst ButtonGroupSeparator = forwardRef<HTMLDivElement, ButtonGroupSeparatorProps>(\n ({ className, ...props }, ref): ReactElement => {\n const groupContext = useButtonGroupContext();\n const orientation = groupContext?.orientation ?? 'horizontal';\n\n return (\n <div\n ref={ref}\n role=\"separator\"\n aria-hidden=\"true\"\n className={cn(\n buttonGroupSeparatorVariants({ orientation }),\n className\n )}\n {...props}\n />\n );\n }\n);\n\nButtonGroupSeparator.displayName = 'ButtonGroupSeparator';\n\n// =============================================================================\n// Exports\n// =============================================================================\n\nexport { ButtonGroup, ButtonGroupSeparator };\n","import { z } from 'zod';\nimport type { ReactNode } from 'react';\n\n/**\n * ButtonGroup Component Types\n *\n * Defines Zod schemas and TypeScript types for the ButtonGroup component.\n * Uses a two-level context pattern:\n * - ButtonGroupContext: Group-level props (orientation, variant, size, isDisabled)\n * - ButtonGroupItemContext: Per-button position information\n *\n * @see plan.md for architecture details\n * @see constitution.md Principle II (Type Safety First)\n */\n\n// =============================================================================\n// Core Types\n// =============================================================================\n\n/**\n * Orientation of the button group\n */\nexport type ButtonGroupOrientation = 'horizontal' | 'vertical';\n\n/**\n * Position of a button within the group\n * Used for position-aware border-radius styling\n */\nexport type ButtonPosition = 'first' | 'middle' | 'last' | 'only';\n\n/**\n * Button variants (matches Themis Button variants, excluding 'link')\n * Link variant is excluded as it doesn't make sense in a grouped context\n */\nexport type ButtonGroupVariant =\n | 'default'\n | 'destructive'\n | 'outline'\n | 'secondary'\n | 'ghost';\n\n/**\n * Button sizes (matches Themis Button sizes)\n */\nexport type ButtonGroupSize = 'sm' | 'default' | 'lg' | 'icon';\n\n// =============================================================================\n// Zod Schemas\n// =============================================================================\n\n/**\n * ButtonGroup props schema\n * Validates all props for the ButtonGroup container component\n */\nexport const ButtonGroupPropsSchema = z.object({\n /** Orientation of the button group layout */\n orientation: z\n .enum(['horizontal', 'vertical'])\n .optional()\n .default('horizontal'),\n\n /** Default variant for all child buttons (can be overridden per-button) */\n variant: z\n .enum(['default', 'destructive', 'outline', 'secondary', 'ghost'])\n .optional(),\n\n /** Default size for all child buttons (can be overridden per-button) */\n size: z.enum(['sm', 'default', 'lg', 'icon']).optional(),\n\n /** Disable all buttons in the group */\n isDisabled: z.boolean().optional(),\n\n /** Accessible label for the toolbar (recommended) */\n 'aria-label': z.string().optional(),\n\n /** ID of element that labels the toolbar */\n 'aria-labelledby': z.string().optional(),\n\n /** Additional CSS classes */\n className: z.string().optional(),\n\n /** Child elements (Buttons, Separators, etc.) */\n children: z.custom<ReactNode>(),\n});\n\n/**\n * ButtonGroupSeparator props schema\n * Validates props for the visual separator between button groups\n */\nexport const ButtonGroupSeparatorPropsSchema = z.object({\n /** Additional CSS classes */\n className: z.string().optional(),\n /** Test ID for testing */\n 'data-testid': z.string().optional(),\n});\n\n// =============================================================================\n// TypeScript Types (inferred from schemas)\n// =============================================================================\n\n/**\n * Props for the ButtonGroup container component\n */\nexport type ButtonGroupProps = z.infer<typeof ButtonGroupPropsSchema>;\n\n/**\n * Props for the ButtonGroupSeparator component\n */\nexport type ButtonGroupSeparatorProps = z.infer<\n typeof ButtonGroupSeparatorPropsSchema\n>;\n\n// =============================================================================\n// Context Types\n// =============================================================================\n\n/**\n * Group-level context value\n * Provides inherited props to all child buttons\n */\nexport interface ButtonGroupContextValue {\n /** Orientation of the group (affects keyboard navigation and styling) */\n orientation: ButtonGroupOrientation;\n /** Default variant for buttons (can be overridden) */\n variant?: ButtonGroupVariant;\n /** Default size for buttons (can be overridden) */\n size?: ButtonGroupSize;\n /** Whether all buttons in the group are disabled */\n isDisabled?: boolean;\n}\n\n/**\n * Item-level context value\n * Provides position information to each button for border-radius styling\n */\nexport interface ButtonGroupItemContextValue {\n /** Position of this button in the group */\n position: ButtonPosition;\n}\n"]}
@@ -1,224 +1,3 @@
1
1
  "use client";
2
- import { createContext, forwardRef, Children, isValidElement, useContext } from 'react';
3
- import { Toolbar } from 'react-aria-components';
4
- import { clsx } from 'clsx';
5
- import { twMerge } from 'tailwind-merge';
6
- import { cva } from 'class-variance-authority';
7
- import { jsx } from 'react/jsx-runtime';
8
- import { z } from 'zod';
9
-
10
- // src/elements/ButtonGroup/ButtonGroup.tsx
11
- function cn(...inputs) {
12
- return twMerge(clsx(inputs));
13
- }
14
- var ButtonGroupContext = createContext(null);
15
- ButtonGroupContext.displayName = "ButtonGroupContext";
16
- function useButtonGroupContext() {
17
- return useContext(ButtonGroupContext);
18
- }
19
- var ButtonGroupItemContext = createContext(null);
20
- ButtonGroupItemContext.displayName = "ButtonGroupItemContext";
21
- function useButtonGroupItemContext() {
22
- return useContext(ButtonGroupItemContext);
23
- }
24
- var buttonGroupVariants = cva("inline-flex items-center gap-0", {
25
- variants: {
26
- orientation: {
27
- horizontal: "flex-row",
28
- vertical: "flex-col w-full"
29
- }
30
- },
31
- defaultVariants: {
32
- orientation: "horizontal"
33
- }
34
- });
35
- var buttonGroupItemVariants = cva("", {
36
- variants: {
37
- orientation: {
38
- // min-w-[44px] ensures visual layer fills touch target width (for icon buttons)
39
- horizontal: "min-w-[44px]",
40
- // flex (overrides inline-flex) + min-h-[44px] makes visual layer fill touch target,
41
- // eliminating gaps between stacked buttons in vertical orientation
42
- vertical: "flex min-h-[44px]"
43
- },
44
- position: {
45
- first: "",
46
- middle: "",
47
- last: "",
48
- only: ""
49
- // Single button - no modifications needed
50
- }
51
- },
52
- compoundVariants: [
53
- // ==========================================================================
54
- // Horizontal Orientation
55
- // ==========================================================================
56
- {
57
- orientation: "horizontal",
58
- position: "first",
59
- className: "rounded-r-none border-r-0"
60
- },
61
- {
62
- orientation: "horizontal",
63
- position: "middle",
64
- className: "rounded-none border-r-0"
65
- },
66
- {
67
- orientation: "horizontal",
68
- position: "last",
69
- className: "rounded-l-none"
70
- },
71
- // ==========================================================================
72
- // Vertical Orientation
73
- // Note: w-full is handled by Button's effectiveFullWidth for both layers
74
- // ==========================================================================
75
- {
76
- orientation: "vertical",
77
- position: "first",
78
- className: "rounded-b-none border-b-0"
79
- },
80
- {
81
- orientation: "vertical",
82
- position: "middle",
83
- className: "rounded-none border-b-0"
84
- },
85
- {
86
- orientation: "vertical",
87
- position: "last",
88
- className: "rounded-t-none"
89
- }
90
- ],
91
- defaultVariants: {
92
- orientation: "horizontal",
93
- position: "only"
94
- }
95
- });
96
- var buttonGroupSeparatorVariants = cva("bg-[var(--border)]", {
97
- variants: {
98
- orientation: {
99
- horizontal: "w-px h-6 mx-1",
100
- vertical: "h-px w-full my-1"
101
- }
102
- },
103
- defaultVariants: {
104
- orientation: "horizontal"
105
- }
106
- });
107
- var isButtonElement = (child) => {
108
- if (!isValidElement(child)) return false;
109
- const componentType = child.type;
110
- return componentType?.displayName === "Button";
111
- };
112
- var isSeparatorElement = (child) => {
113
- if (!isValidElement(child)) return false;
114
- const componentType = child.type;
115
- return componentType?.displayName === "ButtonGroupSeparator";
116
- };
117
- var getPosition = (index, total) => {
118
- if (total === 1) return "only";
119
- if (index === 0) return "first";
120
- if (index === total - 1) return "last";
121
- return "middle";
122
- };
123
- var filterButtonChildren = (children) => {
124
- return children.filter(isButtonElement);
125
- };
126
- var getButtonIndex = (child, buttonChildren) => {
127
- return buttonChildren.indexOf(child);
128
- };
129
- var ButtonGroup = forwardRef(
130
- ({
131
- orientation = "horizontal",
132
- variant,
133
- size,
134
- isDisabled,
135
- className,
136
- children,
137
- ...props
138
- }, ref) => {
139
- const childArray = Children.toArray(children);
140
- const buttonChildren = childArray.filter(isButtonElement);
141
- const totalButtons = buttonChildren.length;
142
- const groupContextValue = {
143
- orientation,
144
- variant,
145
- size,
146
- isDisabled
147
- };
148
- const wrappedChildren = childArray.map((child, index) => {
149
- if (isButtonElement(child)) {
150
- const buttonIndex = buttonChildren.indexOf(child);
151
- const position = getPosition(buttonIndex, totalButtons);
152
- return /* @__PURE__ */ jsx(
153
- ButtonGroupItemContext.Provider,
154
- {
155
- value: { position },
156
- children: child
157
- },
158
- index
159
- );
160
- }
161
- return child;
162
- });
163
- return /* @__PURE__ */ jsx(
164
- Toolbar,
165
- {
166
- ref,
167
- orientation,
168
- "aria-label": props["aria-label"],
169
- "aria-labelledby": props["aria-labelledby"],
170
- className: cn(buttonGroupVariants({ orientation }), className),
171
- children: /* @__PURE__ */ jsx(ButtonGroupContext.Provider, { value: groupContextValue, children: wrappedChildren })
172
- }
173
- );
174
- }
175
- );
176
- ButtonGroup.displayName = "ButtonGroup";
177
- var ButtonGroupSeparator = forwardRef(
178
- ({ className, ...props }, ref) => {
179
- const groupContext = useButtonGroupContext();
180
- const orientation = groupContext?.orientation ?? "horizontal";
181
- return /* @__PURE__ */ jsx(
182
- "div",
183
- {
184
- ref,
185
- role: "separator",
186
- "aria-hidden": "true",
187
- className: cn(
188
- buttonGroupSeparatorVariants({ orientation }),
189
- className
190
- ),
191
- ...props
192
- }
193
- );
194
- }
195
- );
196
- ButtonGroupSeparator.displayName = "ButtonGroupSeparator";
197
- var ButtonGroupPropsSchema = z.object({
198
- /** Orientation of the button group layout */
199
- orientation: z.enum(["horizontal", "vertical"]).optional().default("horizontal"),
200
- /** Default variant for all child buttons (can be overridden per-button) */
201
- variant: z.enum(["default", "destructive", "outline", "secondary", "ghost"]).optional(),
202
- /** Default size for all child buttons (can be overridden per-button) */
203
- size: z.enum(["sm", "default", "lg", "icon"]).optional(),
204
- /** Disable all buttons in the group */
205
- isDisabled: z.boolean().optional(),
206
- /** Accessible label for the toolbar (recommended) */
207
- "aria-label": z.string().optional(),
208
- /** ID of element that labels the toolbar */
209
- "aria-labelledby": z.string().optional(),
210
- /** Additional CSS classes */
211
- className: z.string().optional(),
212
- /** Child elements (Buttons, Separators, etc.) */
213
- children: z.custom()
214
- });
215
- var ButtonGroupSeparatorPropsSchema = z.object({
216
- /** Additional CSS classes */
217
- className: z.string().optional(),
218
- /** Test ID for testing */
219
- "data-testid": z.string().optional()
220
- });
221
-
222
- export { ButtonGroup, ButtonGroupPropsSchema, ButtonGroupSeparator, ButtonGroupSeparatorPropsSchema, buttonGroupItemVariants, buttonGroupSeparatorVariants, buttonGroupVariants, filterButtonChildren, getButtonIndex, getPosition, isButtonElement, isSeparatorElement, useButtonGroupContext, useButtonGroupItemContext };
223
- //# sourceMappingURL=index.mjs.map
2
+ import {createContext,forwardRef,Children,isValidElement,useContext}from'react';import {Toolbar}from'react-aria-components';import {clsx}from'clsx';import {twMerge}from'tailwind-merge';import {cva}from'class-variance-authority';import {jsx}from'react/jsx-runtime';import {z}from'zod';function s(...t){return twMerge(clsx(t))}var a=createContext(null);a.displayName="ButtonGroupContext";function m(){return useContext(a)}var u=createContext(null);u.displayName="ButtonGroupItemContext";function M(){return useContext(u)}var d=cva("inline-flex items-center gap-0",{variants:{orientation:{horizontal:"flex-row",vertical:"flex-col w-full"}},defaultVariants:{orientation:"horizontal"}}),A=cva("",{variants:{orientation:{horizontal:"min-w-[44px]",vertical:"flex min-h-[44px]"},position:{first:"",middle:"",last:"",only:""}},compoundVariants:[{orientation:"horizontal",position:"first",className:"rounded-r-none border-r-0"},{orientation:"horizontal",position:"middle",className:"rounded-none border-r-0"},{orientation:"horizontal",position:"last",className:"rounded-l-none"},{orientation:"vertical",position:"first",className:"rounded-b-none border-b-0"},{orientation:"vertical",position:"middle",className:"rounded-none border-b-0"},{orientation:"vertical",position:"last",className:"rounded-t-none"}],defaultVariants:{orientation:"horizontal",position:"only"}}),B=cva("bg-[var(--border)]",{variants:{orientation:{horizontal:"w-px h-6 mx-1",vertical:"h-px w-full my-1"}},defaultVariants:{orientation:"horizontal"}});var r=t=>isValidElement(t)?t.type?.displayName==="Button":false,H=t=>isValidElement(t)?t.type?.displayName==="ButtonGroupSeparator":false,x=(t,e)=>e===1?"only":t===0?"first":t===e-1?"last":"middle",L=t=>t.filter(r),j=(t,e)=>e.indexOf(t);var P=forwardRef(({orientation:t="horizontal",variant:e,size:p,isDisabled:f,className:l,children:S,...G},g)=>{let y=Children.toArray(S),b=y.filter(r),z=b.length,I={orientation:t,variant:e,size:p,isDisabled:f},R=y.map((n,E)=>{if(r(n)){let T=b.indexOf(n),w=x(T,z);return jsx(u.Provider,{value:{position:w},children:n},E)}return n});return jsx(Toolbar,{ref:g,orientation:t,"aria-label":G["aria-label"],"aria-labelledby":G["aria-labelledby"],className:s(d({orientation:t}),l),children:jsx(a.Provider,{value:I,children:R})})});P.displayName="ButtonGroup";var N=forwardRef(({className:t,...e},p)=>{let l=m()?.orientation??"horizontal";return jsx("div",{ref:p,role:"separator","aria-hidden":"true",className:s(B({orientation:l}),t),...e})});N.displayName="ButtonGroupSeparator";var F=z.object({orientation:z.enum(["horizontal","vertical"]).optional().default("horizontal"),variant:z.enum(["default","destructive","outline","secondary","ghost"]).optional(),size:z.enum(["sm","default","lg","icon"]).optional(),isDisabled:z.boolean().optional(),"aria-label":z.string().optional(),"aria-labelledby":z.string().optional(),className:z.string().optional(),children:z.custom()}),J=z.object({className:z.string().optional(),"data-testid":z.string().optional()});export{P as ButtonGroup,F as ButtonGroupPropsSchema,N as ButtonGroupSeparator,J as ButtonGroupSeparatorPropsSchema,A as buttonGroupItemVariants,B as buttonGroupSeparatorVariants,d as buttonGroupVariants,L as filterButtonChildren,j as getButtonIndex,x as getPosition,r as isButtonElement,H as isSeparatorElement,m as useButtonGroupContext,M as useButtonGroupItemContext};//# sourceMappingURL=index.mjs.map
224
3
  //# sourceMappingURL=index.mjs.map