@plexui/ui 0.19.0 → 0.20.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 (401) hide show
  1. package/README.md +1 -3
  2. package/dist/es/components/Accordion/Accordion.js +2 -2
  3. package/dist/es/components/Accordion/Accordion.js.map +1 -1
  4. package/dist/es/components/Accordion/index.js +1 -1
  5. package/dist/es/components/Alert/Alert.js +6 -6
  6. package/dist/es/components/Alert/Alert.js.map +1 -1
  7. package/dist/es/components/Alert/index.js +1 -1
  8. package/dist/es/components/Avatar/Avatar.js +12 -5
  9. package/dist/es/components/Avatar/Avatar.js.map +1 -1
  10. package/dist/es/components/Avatar/AvatarGroup.js +2 -2
  11. package/dist/es/components/Avatar/AvatarGroup.js.map +1 -1
  12. package/dist/es/components/Avatar/index.js +2 -2
  13. package/dist/es/components/Badge/index.js +3 -3
  14. package/dist/es/components/Badge/index.js.map +1 -1
  15. package/dist/es/components/Breadcrumb/Breadcrumb.js +34 -0
  16. package/dist/es/components/Breadcrumb/Breadcrumb.js.map +1 -0
  17. package/dist/es/components/Breadcrumb/index.js +2 -0
  18. package/dist/es/components/Breadcrumb/index.js.map +1 -0
  19. package/dist/es/components/Button/Button.js +7 -7
  20. package/dist/es/components/Button/Button.js.map +1 -1
  21. package/dist/es/components/Button/CopyButton.js +25 -13
  22. package/dist/es/components/Button/CopyButton.js.map +1 -1
  23. package/dist/es/components/Button/index.js +2 -2
  24. package/dist/es/components/ButtonGroup/ButtonGroup.js +2 -2
  25. package/dist/es/components/ButtonGroup/ButtonGroup.js.map +1 -1
  26. package/dist/es/components/ButtonGroup/index.js +1 -1
  27. package/dist/es/components/Card/Card.js +4 -3
  28. package/dist/es/components/Card/Card.js.map +1 -1
  29. package/dist/es/components/Card/index.js +1 -1
  30. package/dist/es/components/Checkbox/Checkbox.js +12 -6
  31. package/dist/es/components/Checkbox/Checkbox.js.map +1 -1
  32. package/dist/es/components/Checkbox/index.js +1 -1
  33. package/dist/es/components/CodeBlock/CodeBlock.js +25 -25
  34. package/dist/es/components/CodeBlock/CodeBlock.js.map +1 -1
  35. package/dist/es/components/CodeBlock/CollapsibleCodeBlock.js +6 -4
  36. package/dist/es/components/CodeBlock/CollapsibleCodeBlock.js.map +1 -1
  37. package/dist/es/components/CodeBlock/index.js +2 -2
  38. package/dist/es/components/DataTable/DataTable.js +108 -27
  39. package/dist/es/components/DataTable/DataTable.js.map +1 -1
  40. package/dist/es/components/DataTable/DataTableColumnHeader.js +2 -2
  41. package/dist/es/components/DataTable/DataTableColumnHeader.js.map +1 -1
  42. package/dist/es/components/DataTable/DataTablePagination.js +8 -4
  43. package/dist/es/components/DataTable/DataTablePagination.js.map +1 -1
  44. package/dist/es/components/DataTable/columnHelpers.js +3 -3
  45. package/dist/es/components/DataTable/index.js +4 -4
  46. package/dist/es/components/DateInput/DateInput.js +21 -13
  47. package/dist/es/components/DateInput/DateInput.js.map +1 -1
  48. package/dist/es/components/DateInput/index.js +1 -1
  49. package/dist/es/components/DatePicker/Calendar.js +136 -32
  50. package/dist/es/components/DatePicker/Calendar.js.map +1 -1
  51. package/dist/es/components/DatePicker/DatePicker.js +15 -11
  52. package/dist/es/components/DatePicker/DatePicker.js.map +1 -1
  53. package/dist/es/components/DatePicker/index.js +1 -1
  54. package/dist/es/components/DateRangePicker/Calendar.js +125 -22
  55. package/dist/es/components/DateRangePicker/Calendar.js.map +1 -1
  56. package/dist/es/components/DateRangePicker/DateRangePicker.js +10 -9
  57. package/dist/es/components/DateRangePicker/DateRangePicker.js.map +1 -1
  58. package/dist/es/components/DateRangePicker/Trigger.js +12 -9
  59. package/dist/es/components/DateRangePicker/Trigger.js.map +1 -1
  60. package/dist/es/components/DateRangePicker/index.js +2 -2
  61. package/dist/es/components/Dialog/Dialog.js +11 -6
  62. package/dist/es/components/Dialog/Dialog.js.map +1 -1
  63. package/dist/es/components/Dialog/index.js +1 -1
  64. package/dist/es/components/Dialog/index.js.map +1 -1
  65. package/dist/es/components/EmptyMessage/EmptyMessage.js +4 -4
  66. package/dist/es/components/EmptyMessage/EmptyMessage.js.map +1 -1
  67. package/dist/es/components/EmptyMessage/index.js +1 -1
  68. package/dist/es/components/Field/Field.js +22 -7
  69. package/dist/es/components/Field/Field.js.map +1 -1
  70. package/dist/es/components/Field/index.js +1 -1
  71. package/dist/es/components/FieldError/FieldError.js +4 -4
  72. package/dist/es/components/FieldError/FieldError.js.map +1 -1
  73. package/dist/es/components/FieldError/index.js +1 -1
  74. package/dist/es/components/FileUpload/FileUpload.js +12 -9
  75. package/dist/es/components/FileUpload/FileUpload.js.map +1 -1
  76. package/dist/es/components/FileUpload/index.js +1 -1
  77. package/dist/es/components/FloatingLabelInput/FloatingLabelInput.js +31 -4
  78. package/dist/es/components/FloatingLabelInput/FloatingLabelInput.js.map +1 -1
  79. package/dist/es/components/FloatingLabelInput/index.js +1 -1
  80. package/dist/es/components/FloatingLabelSelect/FloatingLabelSelect.js +28 -8
  81. package/dist/es/components/FloatingLabelSelect/FloatingLabelSelect.js.map +1 -1
  82. package/dist/es/components/FloatingLabelSelect/index.js +1 -1
  83. package/dist/es/components/Icon/aliases.js +20 -20
  84. package/dist/es/components/Icon/index.js +653 -653
  85. package/dist/es/components/Image/Image.js +19 -7
  86. package/dist/es/components/Image/Image.js.map +1 -1
  87. package/dist/es/components/Image/index.js +1 -1
  88. package/dist/es/components/Indicator/CircularProgress.js +3 -3
  89. package/dist/es/components/Indicator/CircularProgress.js.map +1 -1
  90. package/dist/es/components/Indicator/LoadingDots.js +1 -1
  91. package/dist/es/components/Indicator/LoadingDots.js.map +1 -1
  92. package/dist/es/components/Indicator/LoadingIndicator.js +2 -2
  93. package/dist/es/components/Indicator/LoadingIndicator.js.map +1 -1
  94. package/dist/es/components/Indicator/index.js +3 -3
  95. package/dist/es/components/Input/Input.js +16 -5
  96. package/dist/es/components/Input/Input.js.map +1 -1
  97. package/dist/es/components/Input/index.js +1 -1
  98. package/dist/es/components/InputGroup/InputGroup.js +60 -0
  99. package/dist/es/components/InputGroup/InputGroup.js.map +1 -0
  100. package/dist/es/components/InputGroup/index.js +2 -0
  101. package/dist/es/components/InputGroup/index.js.map +1 -0
  102. package/dist/es/components/Kbd/Kbd.js +13 -0
  103. package/dist/es/components/Kbd/Kbd.js.map +1 -0
  104. package/dist/es/components/Kbd/index.js +2 -0
  105. package/dist/es/components/Kbd/index.js.map +1 -0
  106. package/dist/es/components/Label/Label.js +1 -1
  107. package/dist/es/components/Label/Label.js.map +1 -1
  108. package/dist/es/components/Label/index.js +1 -1
  109. package/dist/es/components/Markdown/Markdown.js +8 -8
  110. package/dist/es/components/Markdown/Markdown.js.map +1 -1
  111. package/dist/es/components/Markdown/directives.js +2 -2
  112. package/dist/es/components/Markdown/index.js +4 -5
  113. package/dist/es/components/Markdown/index.js.map +1 -1
  114. package/dist/es/components/MarkdownEditor/MarkdownEditor.js +35 -11
  115. package/dist/es/components/MarkdownEditor/MarkdownEditor.js.map +1 -1
  116. package/dist/es/components/MarkdownEditor/index.js +1 -1
  117. package/dist/es/components/Menu/Menu.js +26 -18
  118. package/dist/es/components/Menu/Menu.js.map +1 -1
  119. package/dist/es/components/Menu/index.js +1 -1
  120. package/dist/es/components/OTPInput/OTPInput.js +51 -34
  121. package/dist/es/components/OTPInput/OTPInput.js.map +1 -1
  122. package/dist/es/components/OTPInput/index.js +1 -1
  123. package/dist/es/components/PlexUIProvider/PlexUIProvider.js +3 -1
  124. package/dist/es/components/PlexUIProvider/PlexUIProvider.js.map +1 -1
  125. package/dist/es/components/PlexUIProvider/index.js +1 -1
  126. package/dist/es/components/PlexUIProvider/internal.js +1 -1
  127. package/dist/es/components/Popover/Popover.js +7 -7
  128. package/dist/es/components/Popover/Popover.js.map +1 -1
  129. package/dist/es/components/Popover/index.js +2 -3
  130. package/dist/es/components/Popover/index.js.map +1 -1
  131. package/dist/es/components/Popover/usePopoverController.js +2 -2
  132. package/dist/es/components/Progress/Progress.js +1 -1
  133. package/dist/es/components/Progress/Progress.js.map +1 -1
  134. package/dist/es/components/Progress/index.js +1 -1
  135. package/dist/es/components/ProgressSteps/ProgressSteps.js +6 -4
  136. package/dist/es/components/ProgressSteps/ProgressSteps.js.map +1 -1
  137. package/dist/es/components/ProgressSteps/index.js +1 -1
  138. package/dist/es/components/RadioGroup/RadioGroup.js +10 -6
  139. package/dist/es/components/RadioGroup/RadioGroup.js.map +1 -1
  140. package/dist/es/components/RadioGroup/index.js +1 -1
  141. package/dist/es/components/SegmentedControl/index.js +1 -1
  142. package/dist/es/components/Select/Select.js +104 -67
  143. package/dist/es/components/Select/Select.js.map +1 -1
  144. package/dist/es/components/Select/index.js +1 -1
  145. package/dist/es/components/SelectControl/SelectControl.js +10 -5
  146. package/dist/es/components/SelectControl/SelectControl.js.map +1 -1
  147. package/dist/es/components/SelectControl/index.js +1 -1
  148. package/dist/es/components/Separator/Separator.js +1 -1
  149. package/dist/es/components/Separator/Separator.js.map +1 -1
  150. package/dist/es/components/Separator/index.js +1 -1
  151. package/dist/es/components/ShimmerText/ShimmerText.js +1 -1
  152. package/dist/es/components/ShimmerText/ShimmerText.js.map +1 -1
  153. package/dist/es/components/ShimmerText/index.js +1 -1
  154. package/dist/es/components/Sidebar/Sidebar.js +37 -29
  155. package/dist/es/components/Sidebar/Sidebar.js.map +1 -1
  156. package/dist/es/components/Sidebar/index.js +2 -2
  157. package/dist/es/components/Sidebar/useSidebarContext.js +17 -19
  158. package/dist/es/components/Sidebar/useSidebarContext.js.map +1 -1
  159. package/dist/es/components/Skeleton/index.js +1 -1
  160. package/dist/es/components/Skeleton/index.js.map +1 -1
  161. package/dist/es/components/Slider/Slider.js +48 -19
  162. package/dist/es/components/Slider/Slider.js.map +1 -1
  163. package/dist/es/components/Slider/index.js +1 -1
  164. package/dist/es/components/StatCard/StatCard.js +5 -5
  165. package/dist/es/components/StatCard/StatCard.js.map +1 -1
  166. package/dist/es/components/StatCard/index.js +1 -1
  167. package/dist/es/components/Switch/Switch.js +7 -3
  168. package/dist/es/components/Switch/Switch.js.map +1 -1
  169. package/dist/es/components/Switch/index.js +1 -1
  170. package/dist/es/components/Table/Table.js +1 -1
  171. package/dist/es/components/Table/Table.js.map +1 -1
  172. package/dist/es/components/Table/index.js +1 -1
  173. package/dist/es/components/Tabs/Tabs.js +154 -6
  174. package/dist/es/components/Tabs/Tabs.js.map +1 -1
  175. package/dist/es/components/Tabs/index.js +1 -1
  176. package/dist/es/components/Tabs/overflow.js +44 -0
  177. package/dist/es/components/Tabs/overflow.js.map +1 -0
  178. package/dist/es/components/TagInput/TagInput.js +47 -23
  179. package/dist/es/components/TagInput/TagInput.js.map +1 -1
  180. package/dist/es/components/TagInput/index.js +1 -1
  181. package/dist/es/components/TextLink/TextLink.js +16 -5
  182. package/dist/es/components/TextLink/TextLink.js.map +1 -1
  183. package/dist/es/components/TextLink/index.js +1 -1
  184. package/dist/es/components/Textarea/Textarea.js +4 -4
  185. package/dist/es/components/Textarea/Textarea.js.map +1 -1
  186. package/dist/es/components/Textarea/index.js +1 -1
  187. package/dist/es/components/Toast/Toaster.js +2 -2
  188. package/dist/es/components/Toast/Toaster.js.map +1 -1
  189. package/dist/es/components/Toast/index.js +1 -1
  190. package/dist/es/components/Tooltip/CopyTooltip.js +30 -9
  191. package/dist/es/components/Tooltip/CopyTooltip.js.map +1 -1
  192. package/dist/es/components/Tooltip/Tooltip.js +3 -3
  193. package/dist/es/components/Tooltip/Tooltip.js.map +1 -1
  194. package/dist/es/components/Tooltip/index.js +2 -2
  195. package/dist/es/components/Transition/Animate.js +4 -4
  196. package/dist/es/components/Transition/Animate.js.map +1 -1
  197. package/dist/es/components/Transition/AnimateLayout.js +4 -4
  198. package/dist/es/components/Transition/AnimateLayout.js.map +1 -1
  199. package/dist/es/components/Transition/AnimateLayoutGroup.js +12 -8
  200. package/dist/es/components/Transition/AnimateLayoutGroup.js.map +1 -1
  201. package/dist/es/components/Transition/SlotTransitionGroup.js +4 -4
  202. package/dist/es/components/Transition/TransitionGroup.js +5 -5
  203. package/dist/es/components/Transition/TransitionGroup.js.map +1 -1
  204. package/dist/es/components/Transition/getDisableAnimations.js +1 -1
  205. package/dist/es/components/Transition/index.js +5 -5
  206. package/dist/es/components/Transition/shared.js +7 -5
  207. package/dist/es/components/Transition/shared.js.map +1 -1
  208. package/dist/es/components/UIProvider/UIProvider.js +1 -1
  209. package/dist/es/components/UIProvider/index.js +1 -1
  210. package/dist/es/components/UIProvider/internal.js +1 -1
  211. package/dist/es/hooks/useAnimatedScrollTo.js +1 -1
  212. package/dist/es/hooks/useBreakpoints.js +8 -2
  213. package/dist/es/hooks/useBreakpoints.js.map +1 -1
  214. package/dist/es/hooks/useEscCloseStack.js +1 -1
  215. package/dist/es/hooks/usePrevious.js +7 -5
  216. package/dist/es/hooks/usePrevious.js.map +1 -1
  217. package/dist/es/hooks/useTextSelection.js +2 -2
  218. package/dist/es/hooks/useTrailingValue.js +1 -1
  219. package/dist/es/lib/constants.js +1 -1
  220. package/dist/es/lib/helpers.js +1 -1
  221. package/dist/es/lib/helpers.js.map +1 -1
  222. package/dist/es/lib/renderHelpers.js +15 -6
  223. package/dist/es/lib/renderHelpers.js.map +1 -1
  224. package/dist/es/lib/theme.js +16 -16
  225. package/dist/es/lib/theme.js.map +1 -1
  226. package/dist/es/lib/userAgent.js +3 -2
  227. package/dist/es/lib/userAgent.js.map +1 -1
  228. package/dist/es/styles/base.css +1 -102
  229. package/dist/es/styles/globals.css +1 -50
  230. package/dist/es/styles/index.css +1 -25
  231. package/dist/es/styles/katex.min.css +1 -1296
  232. package/dist/es/styles/tailwind-utilities.css +1 -1316
  233. package/dist/es/styles/variables-components.css +1 -626
  234. package/dist/es/styles/variables-primitive.css +1 -327
  235. package/dist/es/styles/variables-semantic.css +1 -609
  236. package/dist/es/styles/variables-tailwind-theme.css +1 -34
  237. package/dist/es/styles/variables-tokens-root.css +1 -41
  238. package/dist/es/types.js +1 -1
  239. package/dist/es/types.js.map +1 -1
  240. package/dist/es/vite/index.js +3 -53
  241. package/dist/es/vite/index.js.map +1 -1
  242. package/dist/types/components/Accordion/index.d.ts +1 -1
  243. package/dist/types/components/Alert/Alert.d.ts +8 -2
  244. package/dist/types/components/Alert/index.d.ts +1 -1
  245. package/dist/types/components/Avatar/Avatar.d.ts +1 -1
  246. package/dist/types/components/Avatar/index.d.ts +2 -2
  247. package/dist/types/components/Badge/index.d.ts +1 -1
  248. package/dist/types/components/Breadcrumb/Breadcrumb.d.ts +34 -0
  249. package/dist/types/components/Breadcrumb/index.d.ts +1 -0
  250. package/dist/types/components/Button/Button.d.ts +3 -3
  251. package/dist/types/components/Button/CopyButton.d.ts +9 -4
  252. package/dist/types/components/Button/index.d.ts +2 -2
  253. package/dist/types/components/ButtonGroup/ButtonGroup.d.ts +4 -3
  254. package/dist/types/components/ButtonGroup/index.d.ts +1 -1
  255. package/dist/types/components/Card/index.d.ts +1 -1
  256. package/dist/types/components/Checkbox/Checkbox.d.ts +3 -1
  257. package/dist/types/components/Checkbox/index.d.ts +1 -1
  258. package/dist/types/components/CodeBlock/index.d.ts +2 -2
  259. package/dist/types/components/DataTable/DataTable.d.ts +3 -2
  260. package/dist/types/components/DataTable/index.d.ts +4 -4
  261. package/dist/types/components/DateInput/DateInput.d.ts +1 -1
  262. package/dist/types/components/DateInput/index.d.ts +1 -1
  263. package/dist/types/components/DatePicker/DatePicker.d.ts +7 -6
  264. package/dist/types/components/DatePicker/context.d.ts +1 -1
  265. package/dist/types/components/DatePicker/index.d.ts +2 -2
  266. package/dist/types/components/DateRangePicker/Calendar.d.ts +1 -1
  267. package/dist/types/components/DateRangePicker/DateRangePicker.d.ts +5 -5
  268. package/dist/types/components/DateRangePicker/context.d.ts +2 -2
  269. package/dist/types/components/DateRangePicker/index.d.ts +2 -2
  270. package/dist/types/components/Dialog/Dialog.d.ts +19 -1
  271. package/dist/types/components/Dialog/index.d.ts +1 -1
  272. package/dist/types/components/EmptyMessage/EmptyMessage.d.ts +15 -3
  273. package/dist/types/components/EmptyMessage/index.d.ts +1 -1
  274. package/dist/types/components/Field/Field.d.ts +14 -4
  275. package/dist/types/components/Field/index.d.ts +1 -1
  276. package/dist/types/components/FieldError/FieldError.d.ts +7 -1
  277. package/dist/types/components/FieldError/index.d.ts +1 -1
  278. package/dist/types/components/FileUpload/index.d.ts +1 -1
  279. package/dist/types/components/FloatingLabelInput/index.d.ts +1 -1
  280. package/dist/types/components/FloatingLabelSelect/index.d.ts +1 -1
  281. package/dist/types/components/Icon/aliases.d.ts +20 -20
  282. package/dist/types/components/Icon/index.d.ts +653 -653
  283. package/dist/types/components/Image/Image.d.ts +1 -1
  284. package/dist/types/components/Image/index.d.ts +1 -1
  285. package/dist/types/components/Indicator/index.d.ts +3 -3
  286. package/dist/types/components/Input/Input.d.ts +2 -2
  287. package/dist/types/components/Input/index.d.ts +1 -1
  288. package/dist/types/components/InputGroup/InputGroup.d.ts +78 -0
  289. package/dist/types/components/InputGroup/index.d.ts +1 -0
  290. package/dist/types/components/Kbd/Kbd.d.ts +20 -0
  291. package/dist/types/components/Kbd/index.d.ts +1 -0
  292. package/dist/types/components/Label/index.d.ts +1 -1
  293. package/dist/types/components/Markdown/Markdown.d.ts +1 -1
  294. package/dist/types/components/Markdown/index.d.ts +4 -4
  295. package/dist/types/components/MarkdownEditor/MarkdownEditor.d.ts +6 -2
  296. package/dist/types/components/MarkdownEditor/index.d.ts +1 -1
  297. package/dist/types/components/Menu/Menu.d.ts +11 -3
  298. package/dist/types/components/Menu/index.d.ts +1 -1
  299. package/dist/types/components/OTPInput/index.d.ts +1 -1
  300. package/dist/types/components/PlexUIProvider/PlexUIProvider.d.ts +0 -11
  301. package/dist/types/components/PlexUIProvider/index.d.ts +1 -1
  302. package/dist/types/components/Popover/index.d.ts +2 -2
  303. package/dist/types/components/Progress/index.d.ts +1 -1
  304. package/dist/types/components/ProgressSteps/ProgressSteps.d.ts +1 -1
  305. package/dist/types/components/ProgressSteps/index.d.ts +1 -1
  306. package/dist/types/components/RadioGroup/RadioGroup.d.ts +3 -1
  307. package/dist/types/components/RadioGroup/index.d.ts +1 -1
  308. package/dist/types/components/SegmentedControl/index.d.ts +2 -2
  309. package/dist/types/components/Select/Select.d.ts +8 -1
  310. package/dist/types/components/Select/index.d.ts +1 -1
  311. package/dist/types/components/SelectControl/SelectControl.d.ts +1 -1
  312. package/dist/types/components/SelectControl/index.d.ts +1 -1
  313. package/dist/types/components/Separator/index.d.ts +1 -1
  314. package/dist/types/components/ShimmerText/index.d.ts +1 -1
  315. package/dist/types/components/Sidebar/Sidebar.d.ts +4 -8
  316. package/dist/types/components/Sidebar/index.d.ts +4 -4
  317. package/dist/types/components/Slider/Slider.d.ts +8 -0
  318. package/dist/types/components/Slider/index.d.ts +2 -2
  319. package/dist/types/components/StatCard/index.d.ts +1 -1
  320. package/dist/types/components/Switch/index.d.ts +1 -1
  321. package/dist/types/components/Table/index.d.ts +1 -1
  322. package/dist/types/components/Tabs/Tabs.d.ts +15 -2
  323. package/dist/types/components/Tabs/index.d.ts +2 -2
  324. package/dist/types/components/Tabs/overflow.d.ts +17 -0
  325. package/dist/types/components/TagInput/TagInput.d.ts +1 -1
  326. package/dist/types/components/TagInput/index.d.ts +1 -1
  327. package/dist/types/components/TextLink/index.d.ts +1 -1
  328. package/dist/types/components/Textarea/Textarea.d.ts +1 -1
  329. package/dist/types/components/Textarea/index.d.ts +1 -1
  330. package/dist/types/components/Toast/index.d.ts +1 -1
  331. package/dist/types/components/Tooltip/CopyTooltip.d.ts +6 -1
  332. package/dist/types/components/Tooltip/index.d.ts +2 -2
  333. package/dist/types/components/Transition/Animate.d.ts +2 -2
  334. package/dist/types/components/Transition/AnimateLayout.d.ts +2 -2
  335. package/dist/types/components/Transition/AnimateLayoutGroup.d.ts +2 -2
  336. package/dist/types/components/Transition/SlotTransitionGroup.d.ts +1 -1
  337. package/dist/types/components/Transition/TransitionGroup.d.ts +1 -1
  338. package/dist/types/components/Transition/index.d.ts +5 -5
  339. package/dist/types/components/UIProvider/index.d.ts +1 -1
  340. package/dist/types/global.d.ts +5 -1
  341. package/dist/types/lib/constants.d.ts +1 -1
  342. package/dist/types/lib/helpers.d.ts +4 -4
  343. package/dist/types/lib/theme.d.ts +1 -1
  344. package/dist/types/types.d.ts +2 -15
  345. package/dist/types/vite/index.d.ts +2 -55
  346. package/package.json +10 -18
  347. package/dist/es/components/Accordion/Accordion.module.css +0 -89
  348. package/dist/es/components/Alert/Alert.module.css +0 -187
  349. package/dist/es/components/Avatar/Avatar.module.css +0 -168
  350. package/dist/es/components/Avatar/AvatarGroup.module.css +0 -26
  351. package/dist/es/components/Badge/Badge.module.css +0 -196
  352. package/dist/es/components/Button/Button.module.css +0 -859
  353. package/dist/es/components/ButtonGroup/ButtonGroup.module.css +0 -159
  354. package/dist/es/components/Card/Card.module.css +0 -125
  355. package/dist/es/components/Checkbox/Checkbox.module.css +0 -198
  356. package/dist/es/components/CodeBlock/CodeBlock.module.css +0 -137
  357. package/dist/es/components/DataTable/DataTable.module.css +0 -108
  358. package/dist/es/components/DatePicker/Calendar.module.css +0 -271
  359. package/dist/es/components/DateRangePicker/Calendar.module.css +0 -295
  360. package/dist/es/components/DateRangePicker/Trigger.module.css +0 -25
  361. package/dist/es/components/Dialog/Dialog.module.css +0 -133
  362. package/dist/es/components/EmptyMessage/EmptyMessage.module.css +0 -82
  363. package/dist/es/components/Field/Field.module.css +0 -137
  364. package/dist/es/components/FieldError/FieldError.module.css +0 -22
  365. package/dist/es/components/FileUpload/FileUpload.module.css +0 -133
  366. package/dist/es/components/FloatingLabelInput/FloatingLabelInput.module.css +0 -220
  367. package/dist/es/components/FloatingLabelSelect/FloatingLabelSelect.module.css +0 -146
  368. package/dist/es/components/Image/Image.module.css +0 -9
  369. package/dist/es/components/Indicator/CircularProgress.module.css +0 -28
  370. package/dist/es/components/Indicator/LoadingDots.module.css +0 -35
  371. package/dist/es/components/Indicator/LoadingIndicator.module.css +0 -41
  372. package/dist/es/components/Input/Input.module.css +0 -507
  373. package/dist/es/components/Label/Label.module.css +0 -16
  374. package/dist/es/components/Markdown/Markdown.module.css +0 -233
  375. package/dist/es/components/MarkdownEditor/MarkdownEditor.module.css +0 -297
  376. package/dist/es/components/Menu/Menu.module.css +0 -377
  377. package/dist/es/components/OTPInput/OTPInput.module.css +0 -66
  378. package/dist/es/components/Popover/Popover.module.css +0 -82
  379. package/dist/es/components/Progress/Progress.module.css +0 -34
  380. package/dist/es/components/ProgressSteps/ProgressSteps.module.css +0 -246
  381. package/dist/es/components/RadioGroup/RadioGroup.module.css +0 -137
  382. package/dist/es/components/Select/Select.module.css +0 -310
  383. package/dist/es/components/SelectControl/SelectControl.module.css +0 -558
  384. package/dist/es/components/Separator/Separator.module.css +0 -16
  385. package/dist/es/components/ShimmerText/ShimmerText.module.css +0 -43
  386. package/dist/es/components/Sidebar/Sidebar.module.css +0 -909
  387. package/dist/es/components/Skeleton/Skeleton.module.css +0 -17
  388. package/dist/es/components/Slider/Slider.module.css +0 -203
  389. package/dist/es/components/StatCard/StatCard.module.css +0 -234
  390. package/dist/es/components/Switch/Switch.module.css +0 -121
  391. package/dist/es/components/Table/Table.module.css +0 -56
  392. package/dist/es/components/Tabs/Tabs.module.css +0 -672
  393. package/dist/es/components/TagInput/TagInput.module.css +0 -320
  394. package/dist/es/components/TextLink/TextLink.module.css +0 -50
  395. package/dist/es/components/Textarea/Textarea.module.css +0 -272
  396. package/dist/es/components/Toast/Toast.module.css +0 -84
  397. package/dist/es/components/Tooltip/Tooltip.module.css +0 -91
  398. package/dist/es/components/Transition/Animate.module.css +0 -54
  399. package/dist/es/components/Transition/AnimateLayout.module.css +0 -101
  400. package/dist/es/components/Transition/AnimateLayoutGroup.module.css +0 -72
  401. package/dist/es/components/Transition/TransitionGroup.module.css +0 -4
@@ -2,13 +2,22 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import clsx from "clsx";
4
4
  import { ToggleGroup } from "radix-ui";
5
- import { useCallback, useLayoutEffect, useRef } from "react";
5
+ import { Children, cloneElement, Fragment, isValidElement, useCallback, useEffect, useLayoutEffect, useRef, useState, } from "react";
6
6
  import { useResizeObserver } from "usehooks-ts";
7
- import { handlePressableMouseEnter, waitForAnimationFrame } from "../../lib/helpers";
8
- import {} from "../../types";
9
- import { LoadingIndicator } from "../Indicator";
10
- import s from "./Tabs.module.css";
11
- export const Tabs = ({ value, onChange, children, variant = "segmented", orientation = "horizontal", block, pill = true, flush, size = "md", gutterSize, className, onClick, ...restProps }) => {
7
+ import { handlePressableMouseEnter, waitForAnimationFrame } from "../../lib/helpers.js";
8
+ import {} from "../../types.js";
9
+ import { ChevronDownMd } from "../Icon/index.js";
10
+ import { LoadingIndicator } from "../Indicator/index.js";
11
+ import { Menu } from "../Menu/index.js";
12
+ import { fitCount, visibleTabCount } from "./overflow.js";
13
+ import s from "@plexui/styles/components/Tabs/Tabs.module.css";
14
+ export const Tabs = ({ overflow = "scroll", overflowLabel = "More", ...props }) => {
15
+ if (overflow === "menu" && !props.block && props.orientation !== "vertical") {
16
+ return _jsx(OverflowTabs, { ...props, overflowLabel: overflowLabel });
17
+ }
18
+ return _jsx(TabsRoot, { ...props });
19
+ };
20
+ const TabsRoot = ({ value, onChange, children, variant = "segmented", orientation = "horizontal", block, pill = true, flush, size = "md", gutterSize, className, onClick, ...restProps }) => {
12
21
  const rootRef = useRef(null);
13
22
  const thumbRef = useRef(null);
14
23
  const prevSizeRef = useRef(size);
@@ -92,6 +101,24 @@ export const Tabs = ({ value, onChange, children, variant = "segmented", orienta
92
101
  thumb.style.transition = currentTransition;
93
102
  },
94
103
  });
104
+ // Tabs added, removed, reordered or relabelled move the active tab without
105
+ // resizing the group: measure again, instantly, like a resize
106
+ useEffect(() => {
107
+ const root = rootRef.current;
108
+ if (!root || typeof MutationObserver === "undefined")
109
+ return;
110
+ const observer = new MutationObserver(() => {
111
+ const thumb = thumbRef.current;
112
+ if (!thumb)
113
+ return;
114
+ const currentTransition = thumb.style.transition;
115
+ thumb.style.transition = "";
116
+ applyThumbSizing(false);
117
+ thumb.style.transition = currentTransition;
118
+ });
119
+ observer.observe(root, { childList: true, characterData: true, subtree: true });
120
+ return () => observer.disconnect();
121
+ }, [applyThumbSizing]);
95
122
  const transitionProperty = isVertical
96
123
  ? "height 300ms var(--cubic-enter), transform 300ms var(--cubic-enter)"
97
124
  : "width 300ms var(--cubic-enter), transform 300ms var(--cubic-enter)";
@@ -148,6 +175,127 @@ const Tab = ({ children, icon, badge, ...restProps }) => {
148
175
  const badgeProps = badge != null ? (isBadgeObject(badge) ? badge : { content: badge }) : null;
149
176
  return (_jsx(ToggleGroup.Item, { className: s.Tab, ...restProps, onPointerEnter: handlePressableMouseEnter, children: _jsxs("span", { className: s.TabContent, children: [icon, children && _jsx("span", { children: children }), badgeProps && (_jsx("span", { className: s.TabBadge, "data-color": badgeProps.color ?? "secondary", "data-variant": badgeProps.variant ?? "soft", "data-pill": badgeProps.pill ? "" : undefined, children: badgeProps.loading ? _jsx(LoadingIndicator, {}) : badgeProps.content }))] }) }));
150
177
  };
178
+ // =============================================
179
+ // overflow="menu"
180
+ // =============================================
181
+ /** Value of the menu button; no real tab has it */
182
+ const MORE_VALUE = "__plexui_tabs_more__";
183
+ /** The tabs among the children, through fragments */
184
+ const tabElements = (children) => Children.toArray(children).flatMap((child) => {
185
+ if (!isValidElement(child))
186
+ return [];
187
+ return child.type === Fragment ? tabElements(child.props.children) : [child];
188
+ });
189
+ const plainText = (node) => {
190
+ if (typeof node === "string" || typeof node === "number")
191
+ return String(node);
192
+ if (Array.isArray(node))
193
+ return node.map(plainText).join("");
194
+ if (isValidElement(node))
195
+ return plainText(node.props.children);
196
+ return "";
197
+ };
198
+ const badgeText = (badge) => badge != null && isBadgeObject(badge) ? plainText(badge.content) : plainText(badge);
199
+ /** A tab's name: its text, else its accessible name, else its value */
200
+ const tabLabel = (item) => plainText(item.props.children) || item.props["aria-label"] || item.props.value;
201
+ /** What a tab's width depends on: the strip measures again when it changes */
202
+ const tabsSignature = (items) => items
203
+ .map((item) => [item.props.value, plainText(item.props.children), badgeText(item.props.badge), item.props.icon != null].join("\u0000"))
204
+ .join("\u0001");
205
+ /**
206
+ * `Menu.Trigger` sets `data-state` (open or closed) on its child, while a tab
207
+ * keeps `on` or `off` in the same attribute and the thumb finds the active tab
208
+ * by it. The menu's value does not reach the tab; its handlers and
209
+ * `aria-haspopup` / `aria-expanded` do.
210
+ */
211
+ const MoreTab = ({ "data-state": _menuState, ...restProps }) => (_jsx(Tab, { ...restProps }));
212
+ const OverflowTabs = ({ children, value, onChange, overflowLabel, ...restProps }) => {
213
+ const items = tabElements(children);
214
+ // The strip's own props size the tabs and the menu button too
215
+ const { size, variant, gutterSize, pill, flush } = restProps;
216
+ const signature = [overflowLabel, size, variant, gutterSize, pill, flush, tabsSignature(items)].join("\u0002");
217
+ const activeIndex = items.findIndex((item) => item.props.value === value);
218
+ // null while the measuring pass renders every tab and the menu button
219
+ const [visibleCount, setVisibleCount] = useState(null);
220
+ const [known, setKnown] = useState({ signature, activeIndex });
221
+ const hostRef = useRef(null);
222
+ const measuringRef = useRef(true);
223
+ const boxWidthRef = useRef(-1);
224
+ // New tabs measure again. A new active tab measures again when it moves
225
+ // under the menu button or back out: the button carries the hidden one's name
226
+ if (known.signature !== signature || known.activeIndex !== activeIndex) {
227
+ const crossed = visibleCount !== null && (known.activeIndex >= visibleCount || activeIndex >= visibleCount);
228
+ setKnown({ signature, activeIndex });
229
+ if (visibleCount !== null && (known.signature !== signature || crossed))
230
+ setVisibleCount(null);
231
+ }
232
+ useLayoutEffect(() => {
233
+ measuringRef.current = visibleCount === null;
234
+ }, [visibleCount]);
235
+ useLayoutEffect(() => {
236
+ if (visibleCount !== null)
237
+ return;
238
+ const root = hostRef.current?.firstElementChild;
239
+ if (!(root instanceof HTMLElement))
240
+ return;
241
+ // The measuring pass renders every tab, then the menu button
242
+ const buttons = Array.from(root.querySelectorAll(":scope > button"));
243
+ if (buttons.length !== items.length + 1)
244
+ return;
245
+ const widths = buttons.map((button) => button.getBoundingClientRect().width);
246
+ const moreButton = buttons[buttons.length - 1];
247
+ const moreWidth = widths.pop() ?? 0;
248
+ const style = getComputedStyle(root);
249
+ const available = root.getBoundingClientRect().width -
250
+ (Number.parseFloat(style.paddingLeft) || 0) -
251
+ (Number.parseFloat(style.paddingRight) || 0);
252
+ const gap = Number.parseFloat(style.columnGap) || 0;
253
+ boxWidthRef.current = hostRef.current?.parentElement?.clientWidth ?? -1;
254
+ // A hidden strip has no width to decide by: show every tab, and measure
255
+ // when it appears (the observer sees the width change)
256
+ if (available <= 0) {
257
+ setVisibleCount(items.length);
258
+ return;
259
+ }
260
+ // The button with the active tab's name: that tab's width plus the chevron
261
+ const chevron = moreButton?.querySelector("svg");
262
+ const chevronWidth = chevron?.getBoundingClientRect().width ?? 0;
263
+ const labelGap = chevron?.parentElement ? Number.parseFloat(getComputedStyle(chevron.parentElement).columnGap) || 0 : 0;
264
+ const activeWidth = activeIndex < 0 ? 0 : (widths[activeIndex] ?? 0) + chevronWidth + labelGap;
265
+ setVisibleCount(visibleTabCount(widths, moreWidth, activeWidth, activeIndex, gap, available));
266
+ }, [visibleCount, items.length, activeIndex]);
267
+ // The width to fit is the container's, not the strip's: the strip shrinks
268
+ // to its content. Reports during a measuring pass are skipped, since the
269
+ // full strip may be pushing its container wider
270
+ useEffect(() => {
271
+ const box = hostRef.current?.parentElement;
272
+ if (!box || typeof ResizeObserver === "undefined")
273
+ return;
274
+ const observer = new ResizeObserver(() => {
275
+ if (measuringRef.current)
276
+ return;
277
+ const width = box.clientWidth;
278
+ if (width === boxWidthRef.current)
279
+ return;
280
+ boxWidthRef.current = width;
281
+ setVisibleCount(null);
282
+ });
283
+ observer.observe(box);
284
+ return () => observer.disconnect();
285
+ }, []);
286
+ const measuring = visibleCount === null;
287
+ const shown = measuring ? items : items.slice(0, visibleCount);
288
+ const hidden = measuring ? [] : items.slice(visibleCount);
289
+ const hiddenActive = hidden.find((item) => item.props.value === value) ?? null;
290
+ return (_jsx("div", { ref: hostRef, className: s.OverflowHost, children: _jsxs(Menu, { children: [_jsxs(TabsRoot, { ...restProps, "data-overflow": "menu", value: hiddenActive ? MORE_VALUE : value, onChange: (next) => {
291
+ // Pressing the menu button opens the menu; it is not a tab
292
+ if (next !== MORE_VALUE)
293
+ onChange?.(next);
294
+ }, children: [shown.map((item) => cloneElement(item, { key: item.props.value })), (measuring || hidden.length > 0) && (_jsx(Menu.Trigger, { children: _jsx(MoreTab, { value: MORE_VALUE, children: _jsxs("span", { className: s.OverflowLabel, children: [hiddenActive ? tabLabel(hiddenActive) : overflowLabel, _jsx(ChevronDownMd, {})] }) }) }))] }), _jsx(Menu.Content, { align: "end", minWidth: "auto", children: _jsx(Menu.RadioGroup, { value: value, onChange: (next) => onChange?.(next), children: hidden.map((item) => {
295
+ const count = badgeText(item.props.badge);
296
+ return (_jsxs(Menu.RadioItem, { value: item.props.value, disabled: restProps.disabled || item.props.disabled, children: [item.props.icon, item.props.children ?? item.props["aria-label"] ?? item.props.value, count !== "" && _jsx("span", { className: s.OverflowBadge, children: count })] }, item.props.value));
297
+ }) }) })] }) }));
298
+ };
151
299
  // Attach sub-components
152
300
  Tabs.Tab = Tab;
153
301
  // Backward-compat alias
@@ -1 +1 @@
1
- {"version":3,"file":"Tabs.js","sourceRoot":"","sources":["../../../../src/components/Tabs/Tabs.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\"\n\nimport clsx from \"clsx\"\nimport { ToggleGroup } from \"radix-ui\"\nimport { useCallback, useLayoutEffect, useRef } from \"react\"\nimport { useResizeObserver } from \"usehooks-ts\"\nimport { handlePressableMouseEnter, waitForAnimationFrame } from \"../../lib/helpers\"\nimport { type ControlSize, type SemanticColors, type Sizes, type Variants } from \"../../types\"\nimport { LoadingIndicator } from \"../Indicator\"\nimport s from \"./Tabs.module.css\"\n\nexport type SizeVariant = \"2xs\" | \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\"\n\nexport type TabsVariant = \"segmented\" | \"underline\"\nexport type TabsOrientation = \"horizontal\" | \"vertical\"\n\nexport type TabsProps<T extends string> = {\n /**\n * Controlled value for the group\n */\n \"value\": T\n /** Callback for when a new value is selected */\n \"onChange\"?: (nextValue: T) => void\n /** Callback any time the control is clicked (even if a new value was not selected) */\n \"onClick\"?: () => void\n /**\n * Text read aloud to screen readers when the control is focused\n */\n \"aria-label\": string\n /**\n * Visual variant of the tab group\n * - `\"segmented\"` — background container with sliding highlight (default)\n * - `\"underline\"` — no background, animated line indicator under active tab\n * @default \"segmented\"\n */\n \"variant\"?: TabsVariant\n /**\n * Orientation of the tab layout\n * @default \"horizontal\"\n */\n \"orientation\"?: TabsOrientation\n /**\n * Controls the size of the tabs\n *\n * | 3xs | 2xs | xs | sm | md | lg | xl | 2xl | 3xl |\n * | ------- | ------- | ------- | ------- | ------- | ------- | ------- | ------- | ------- |\n * | `22px` | `24px` | `26px` | `28px` | `32px` | `36px` | `40px` | `44px` | `48px` |\n *\n * @default md\n */\n \"size\"?: ControlSize\n /**\n * Controls gutter on the edges of the button, defaults to value from `size`.\n *\n * | 2xs | xs | sm | md | lg | xl |\n * | ------ | ------ | ------ | ------ | ------ | ------ |\n * | `6px` | `8px` | `10px` | `12px` | `14px` | `16px` |\n */\n \"gutterSize\"?: Sizes<\"2xs\" | \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\">\n /** Disable the entire group */\n \"disabled\"?: boolean\n /**\n * Display the control as a block element with equal width segments\n * @default false\n */\n \"block\"?: boolean\n /**\n * Determines if the tabs should be a fully rounded pill shape.\n * Only applies to the `\"segmented\"` variant.\n * @default true\n */\n \"pill\"?: boolean\n /**\n * Flush underline style — removes tab padding so the indicator\n * matches the text width exactly, uses gap for spacing, and\n * removes the bottom border.\n * Only applies to the `\"underline\"` variant.\n * @default false\n */\n \"flush\"?: boolean\n \"className\"?: string\n \"children\": React.ReactNode\n}\n\nexport const Tabs = <T extends string>({\n value,\n onChange,\n children,\n variant = \"segmented\",\n orientation = \"horizontal\",\n block,\n pill = true,\n flush,\n size = \"md\",\n gutterSize,\n className,\n onClick,\n ...restProps\n}: TabsProps<T>) => {\n const rootRef = useRef<HTMLDivElement>(null)\n const thumbRef = useRef<HTMLDivElement>(null)\n const prevSizeRef = useRef(size)\n const isVertical = orientation === \"vertical\"\n\n const applyThumbSizing = useCallback(\n (attemptScroll: boolean) => {\n const root = rootRef.current\n const thumb = thumbRef.current\n\n if (!root || !thumb) {\n return\n }\n\n // Get selected node\n const activeNode = root?.querySelector<HTMLDivElement>('[data-state=\"on\"]')\n\n // Impossible\n if (!activeNode) {\n return\n }\n\n if (isVertical) {\n const rootHeight = root.clientHeight\n let targetHeight = Math.floor(activeNode.clientHeight)\n const targetOffset = activeNode.offsetTop\n\n // Detect subpixel edge case\n if (rootHeight - (targetHeight + targetOffset) < 2) {\n targetHeight = targetHeight - 1\n }\n\n thumb.style.height = `${Math.floor(targetHeight)}px`\n thumb.style.width = \"\"\n thumb.style.transform = `translateY(${targetOffset}px)`\n\n // Scroll into view if needed\n if (root.scrollHeight > rootHeight) {\n const buffer = rootHeight * 0.15\n const scrollTop = root.scrollTop\n const top = activeNode.offsetTop\n const bottom = top + targetHeight\n if (top < scrollTop + buffer || bottom > scrollTop + rootHeight - buffer) {\n if (attemptScroll) {\n activeNode.scrollIntoView({ block: \"center\", inline: \"nearest\", behavior: \"smooth\" })\n }\n }\n }\n } else {\n const rootWidth = root.clientWidth\n let targetWidth = Math.floor(activeNode.clientWidth)\n const targetOffset = activeNode.offsetLeft\n\n // Detect if the thumb is moving too far to the edge of the container.\n // This would most commonly be due to subpixel widths adding up to excessive distance.\n if (rootWidth - (targetWidth + targetOffset) < 2) {\n targetWidth = targetWidth - 1\n }\n\n thumb.style.width = `${Math.floor(targetWidth)}px`\n thumb.style.height = \"\"\n thumb.style.transform = `translateX(${targetOffset}px)`\n\n // If the control is scrollable, ensure the active option is visible\n if (root.scrollWidth > rootWidth) {\n // Only scroll items near the edge, but not the inner 2/3.\n const buffer = rootWidth * 0.15\n const scrollLeft = root.scrollLeft\n const left = activeNode.offsetLeft\n const right = left + targetWidth\n if (left < scrollLeft + buffer || right > scrollLeft + rootWidth - buffer) {\n // Cheap trick to avoid unintentional scroll on mount - transition is set after mounting\n if (attemptScroll) {\n activeNode.scrollIntoView({ block: \"nearest\", inline: \"center\", behavior: \"smooth\" })\n }\n }\n }\n }\n },\n [isVertical],\n )\n\n useResizeObserver({\n // @ts-expect-error(2322) -- bug in types: https://github.com/juliencrn/usehooks-ts/issues/663\n ref: rootRef,\n onResize: () => {\n const thumb = thumbRef.current\n\n if (!thumb) {\n return\n }\n\n // Perform the size update instantly\n const currentTransition = thumb.style.transition\n thumb.style.transition = \"\"\n applyThumbSizing(false)\n thumb.style.transition = currentTransition\n },\n })\n\n const transitionProperty = isVertical\n ? \"height 300ms var(--cubic-enter), transform 300ms var(--cubic-enter)\"\n : \"width 300ms var(--cubic-enter), transform 300ms var(--cubic-enter)\"\n\n useLayoutEffect(() => {\n const root = rootRef.current\n const thumb = thumbRef.current\n\n if (!root || !thumb) {\n return\n }\n\n const sizeChanged = prevSizeRef.current !== size\n prevSizeRef.current = size\n\n if (sizeChanged) {\n // Size changed - disable transition, wait for CSS, then apply sizing\n const currentTransition = thumb.style.transition\n thumb.style.transition = \"\"\n\n waitForAnimationFrame(() => {\n applyThumbSizing(false)\n waitForAnimationFrame(() => {\n thumb.style.transition = currentTransition\n })\n })\n } else {\n // Normal update (value change, etc.)\n waitForAnimationFrame(() => {\n applyThumbSizing(!!thumb.style.transition)\n\n // Apply transition after initial calculation is set\n if (!thumb.style.transition) {\n waitForAnimationFrame(() => {\n thumb.style.transition = transitionProperty\n })\n }\n })\n }\n }, [applyThumbSizing, value, size, gutterSize, pill, flush, transitionProperty])\n\n const handleValueChange = (nextValue: T) => {\n // Only trigger onChange when a value exists\n // Disallow toggling off enabled items\n if (nextValue && onChange) onChange(nextValue)\n }\n\n // Only apply pill for segmented variant\n const isPill = variant === \"segmented\" && pill\n // Only apply flush for underline variant\n const isFlush = variant === \"underline\" && flush\n\n return (\n <ToggleGroup.Root\n ref={rootRef}\n className={clsx(s.Tabs, className)}\n type=\"single\"\n value={value}\n loop={false}\n onValueChange={handleValueChange}\n onClick={onClick}\n data-variant={variant}\n data-orientation={orientation}\n data-block={block ? \"\" : undefined}\n data-pill={isPill ? \"\" : undefined}\n data-flush={isFlush ? \"\" : undefined}\n data-size={size}\n data-gutter-size={gutterSize}\n {...restProps}\n >\n <div className={s.TabsThumb} ref={thumbRef} />\n {children}\n </ToggleGroup.Root>\n )\n}\n\n/**\n * Badge configuration for Tabs.Tab\n */\nexport type TabsBadgeProp =\n | React.ReactNode\n | {\n content: React.ReactNode\n color?: SemanticColors<\n \"secondary\" | \"success\" | \"danger\" | \"warning\" | \"info\" | \"discovery\" | \"caution\"\n >\n variant?: Variants<\"soft\" | \"solid\">\n pill?: boolean\n loading?: boolean\n }\n\nexport type TabProps = {\n /**\n * Tab value\n */\n \"value\": string\n /**\n * Text read aloud to screen readers when the tab is focused\n */\n \"aria-label\"?: string\n /**\n * Text content to render in the tab\n */\n \"children\"?: React.ReactNode\n /**\n * Icon to render before the text content\n */\n \"icon\"?: React.ReactNode\n /**\n * Badge to render after the text content.\n * Can be a simple value or an object with content, color, variant, and loading options.\n * @example badge={5}\n * @example badge={{ content: 5, color: \"danger\" }}\n */\n \"badge\"?: TabsBadgeProp\n /**\n * Disable the individual tab\n */\n \"disabled\"?: boolean\n}\n\n// Type guard for badge object form\nconst isBadgeObject = (\n badge: TabsBadgeProp,\n): badge is Exclude<TabsBadgeProp, React.ReactNode> & { content: React.ReactNode } => {\n return badge != null && typeof badge === \"object\" && \"content\" in badge\n}\n\nconst Tab = ({ children, icon, badge, ...restProps }: TabProps) => {\n // Normalize badge prop\n const badgeProps = badge != null ? (isBadgeObject(badge) ? badge : { content: badge }) : null\n\n return (\n <ToggleGroup.Item\n className={s.Tab}\n {...restProps}\n onPointerEnter={handlePressableMouseEnter}\n >\n <span className={s.TabContent}>\n {icon}\n {children && <span>{children}</span>}\n {badgeProps && (\n <span\n className={s.TabBadge}\n data-color={badgeProps.color ?? \"secondary\"}\n data-variant={badgeProps.variant ?? \"soft\"}\n data-pill={badgeProps.pill ? \"\" : undefined}\n >\n {badgeProps.loading ? <LoadingIndicator /> : badgeProps.content}\n </span>\n )}\n </span>\n </ToggleGroup.Item>\n )\n}\n\n// Attach sub-components\nTabs.Tab = Tab\n// Backward-compat alias\nTabs.Option = Tab\n"]}
1
+ {"version":3,"file":"Tabs.js","sourceRoot":"","sources":["../../../../src/components/Tabs/Tabs.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\"\n\nimport clsx from \"clsx\"\nimport { ToggleGroup } from \"radix-ui\"\nimport {\n Children,\n cloneElement,\n Fragment,\n isValidElement,\n useCallback,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n type ReactElement,\n type ReactNode,\n} from \"react\"\nimport { useResizeObserver } from \"usehooks-ts\"\nimport { handlePressableMouseEnter, waitForAnimationFrame } from \"../../lib/helpers\"\nimport { type ControlSize, type SemanticColors, type Sizes, type Variants } from \"../../types\"\nimport { ChevronDownMd } from \"../Icon\"\nimport { LoadingIndicator } from \"../Indicator\"\nimport { Menu } from \"../Menu\"\nimport { fitCount, visibleTabCount } from \"./overflow\"\nimport s from \"@plexui/styles/components/Tabs/Tabs.module.css\"\n\nexport type SizeVariant = \"2xs\" | \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\"\n\nexport type TabsVariant = \"segmented\" | \"underline\"\nexport type TabsOrientation = \"horizontal\" | \"vertical\"\n\nexport type TabsProps<T extends string> = {\n /**\n * Controlled value for the group\n */\n \"value\": T\n /** Callback for when a new value is selected */\n \"onChange\"?: (nextValue: T) => void\n /** Callback any time the control is clicked (even if a new value was not selected) */\n \"onClick\"?: () => void\n /**\n * Text read aloud to screen readers when the control is focused\n */\n \"aria-label\": string\n /**\n * Visual variant of the tab group\n * - `\"segmented\"` — background container with sliding highlight (default)\n * - `\"underline\"` — no background, animated line indicator under active tab\n * @default \"segmented\"\n */\n \"variant\"?: TabsVariant\n /**\n * Orientation of the tab layout\n * @default \"horizontal\"\n */\n \"orientation\"?: TabsOrientation\n /**\n * Controls the size of the tabs\n *\n * | 3xs | 2xs | xs | sm | md | lg | xl | 2xl | 3xl |\n * | ------- | ------- | ------- | ------- | ------- | ------- | ------- | ------- | ------- |\n * | `22px` | `24px` | `26px` | `28px` | `32px` | `36px` | `40px` | `44px` | `48px` |\n *\n * @default md\n */\n \"size\"?: ControlSize\n /**\n * Controls gutter on the edges of the button, defaults to value from `size`.\n *\n * | 2xs | xs | sm | md | lg | xl |\n * | ------ | ------ | ------ | ------ | ------ | ------ |\n * | `6px` | `8px` | `10px` | `12px` | `14px` | `16px` |\n */\n \"gutterSize\"?: Sizes<\"2xs\" | \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\">\n /** Disable the entire group */\n \"disabled\"?: boolean\n /**\n * Display the control as a block element with equal width segments\n * @default false\n */\n \"block\"?: boolean\n /**\n * Determines if the tabs should be a fully rounded pill shape.\n * Only applies to the `\"segmented\"` variant.\n * @default true\n */\n \"pill\"?: boolean\n /**\n * Flush underline style — removes tab padding so the indicator\n * matches the text width exactly, uses gap for spacing, and\n * removes the bottom border.\n * Only applies to the `\"underline\"` variant.\n * @default false\n */\n \"flush\"?: boolean\n /**\n * What happens to tabs that do not fit in one row: the strip scrolls\n * sideways (`scroll`), or the tabs that do not fit move into a menu at the\n * end of the strip (`menu`). The menu button shows the active tab's name\n * when it is one of the hidden ones. Horizontal tabs without `block` only.\n * @default \"scroll\"\n */\n \"overflow\"?: \"scroll\" | \"menu\"\n /**\n * Text of the menu button with `overflow=\"menu\"`\n * @default \"More\"\n */\n \"overflowLabel\"?: string\n \"className\"?: string\n \"children\": React.ReactNode\n}\n\nexport const Tabs = <T extends string>({ overflow = \"scroll\", overflowLabel = \"More\", ...props }: TabsProps<T>) => {\n if (overflow === \"menu\" && !props.block && props.orientation !== \"vertical\") {\n return <OverflowTabs {...props} overflowLabel={overflowLabel} />\n }\n return <TabsRoot {...props} />\n}\n\nconst TabsRoot = <T extends string>({\n value,\n onChange,\n children,\n variant = \"segmented\",\n orientation = \"horizontal\",\n block,\n pill = true,\n flush,\n size = \"md\",\n gutterSize,\n className,\n onClick,\n ...restProps\n}: Omit<TabsProps<T>, \"overflow\" | \"overflowLabel\">) => {\n const rootRef = useRef<HTMLDivElement>(null)\n const thumbRef = useRef<HTMLDivElement>(null)\n const prevSizeRef = useRef(size)\n const isVertical = orientation === \"vertical\"\n\n const applyThumbSizing = useCallback(\n (attemptScroll: boolean) => {\n const root = rootRef.current\n const thumb = thumbRef.current\n\n if (!root || !thumb) {\n return\n }\n\n // Get selected node\n const activeNode = root?.querySelector<HTMLDivElement>('[data-state=\"on\"]')\n\n // Impossible\n if (!activeNode) {\n return\n }\n\n if (isVertical) {\n const rootHeight = root.clientHeight\n let targetHeight = Math.floor(activeNode.clientHeight)\n const targetOffset = activeNode.offsetTop\n\n // Detect subpixel edge case\n if (rootHeight - (targetHeight + targetOffset) < 2) {\n targetHeight = targetHeight - 1\n }\n\n thumb.style.height = `${Math.floor(targetHeight)}px`\n thumb.style.width = \"\"\n thumb.style.transform = `translateY(${targetOffset}px)`\n\n // Scroll into view if needed\n if (root.scrollHeight > rootHeight) {\n const buffer = rootHeight * 0.15\n const scrollTop = root.scrollTop\n const top = activeNode.offsetTop\n const bottom = top + targetHeight\n if (top < scrollTop + buffer || bottom > scrollTop + rootHeight - buffer) {\n if (attemptScroll) {\n activeNode.scrollIntoView({ block: \"center\", inline: \"nearest\", behavior: \"smooth\" })\n }\n }\n }\n } else {\n const rootWidth = root.clientWidth\n let targetWidth = Math.floor(activeNode.clientWidth)\n const targetOffset = activeNode.offsetLeft\n\n // Detect if the thumb is moving too far to the edge of the container.\n // This would most commonly be due to subpixel widths adding up to excessive distance.\n if (rootWidth - (targetWidth + targetOffset) < 2) {\n targetWidth = targetWidth - 1\n }\n\n thumb.style.width = `${Math.floor(targetWidth)}px`\n thumb.style.height = \"\"\n thumb.style.transform = `translateX(${targetOffset}px)`\n\n // If the control is scrollable, ensure the active option is visible\n if (root.scrollWidth > rootWidth) {\n // Only scroll items near the edge, but not the inner 2/3.\n const buffer = rootWidth * 0.15\n const scrollLeft = root.scrollLeft\n const left = activeNode.offsetLeft\n const right = left + targetWidth\n if (left < scrollLeft + buffer || right > scrollLeft + rootWidth - buffer) {\n // Cheap trick to avoid unintentional scroll on mount - transition is set after mounting\n if (attemptScroll) {\n activeNode.scrollIntoView({ block: \"nearest\", inline: \"center\", behavior: \"smooth\" })\n }\n }\n }\n }\n },\n [isVertical],\n )\n\n useResizeObserver({\n // @ts-expect-error(2322) -- bug in types: https://github.com/juliencrn/usehooks-ts/issues/663\n ref: rootRef,\n onResize: () => {\n const thumb = thumbRef.current\n\n if (!thumb) {\n return\n }\n\n // Perform the size update instantly\n const currentTransition = thumb.style.transition\n thumb.style.transition = \"\"\n applyThumbSizing(false)\n thumb.style.transition = currentTransition\n },\n })\n\n // Tabs added, removed, reordered or relabelled move the active tab without\n // resizing the group: measure again, instantly, like a resize\n useEffect(() => {\n const root = rootRef.current\n if (!root || typeof MutationObserver === \"undefined\") return\n const observer = new MutationObserver(() => {\n const thumb = thumbRef.current\n if (!thumb) return\n const currentTransition = thumb.style.transition\n thumb.style.transition = \"\"\n applyThumbSizing(false)\n thumb.style.transition = currentTransition\n })\n observer.observe(root, { childList: true, characterData: true, subtree: true })\n return () => observer.disconnect()\n }, [applyThumbSizing])\n\n const transitionProperty = isVertical\n ? \"height 300ms var(--cubic-enter), transform 300ms var(--cubic-enter)\"\n : \"width 300ms var(--cubic-enter), transform 300ms var(--cubic-enter)\"\n\n useLayoutEffect(() => {\n const root = rootRef.current\n const thumb = thumbRef.current\n\n if (!root || !thumb) {\n return\n }\n\n const sizeChanged = prevSizeRef.current !== size\n prevSizeRef.current = size\n\n if (sizeChanged) {\n // Size changed - disable transition, wait for CSS, then apply sizing\n const currentTransition = thumb.style.transition\n thumb.style.transition = \"\"\n\n waitForAnimationFrame(() => {\n applyThumbSizing(false)\n waitForAnimationFrame(() => {\n thumb.style.transition = currentTransition\n })\n })\n } else {\n // Normal update (value change, etc.)\n waitForAnimationFrame(() => {\n applyThumbSizing(!!thumb.style.transition)\n\n // Apply transition after initial calculation is set\n if (!thumb.style.transition) {\n waitForAnimationFrame(() => {\n thumb.style.transition = transitionProperty\n })\n }\n })\n }\n }, [applyThumbSizing, value, size, gutterSize, pill, flush, transitionProperty])\n\n const handleValueChange = (nextValue: T) => {\n // Only trigger onChange when a value exists\n // Disallow toggling off enabled items\n if (nextValue && onChange) onChange(nextValue)\n }\n\n // Only apply pill for segmented variant\n const isPill = variant === \"segmented\" && pill\n // Only apply flush for underline variant\n const isFlush = variant === \"underline\" && flush\n\n return (\n <ToggleGroup.Root\n ref={rootRef}\n className={clsx(s.Tabs, className)}\n type=\"single\"\n value={value}\n loop={false}\n onValueChange={handleValueChange}\n onClick={onClick}\n data-variant={variant}\n data-orientation={orientation}\n data-block={block ? \"\" : undefined}\n data-pill={isPill ? \"\" : undefined}\n data-flush={isFlush ? \"\" : undefined}\n data-size={size}\n data-gutter-size={gutterSize}\n {...restProps}\n >\n <div className={s.TabsThumb} ref={thumbRef} />\n {children}\n </ToggleGroup.Root>\n )\n}\n\n/**\n * Badge configuration for Tabs.Tab\n */\nexport type TabsBadgeProp =\n | React.ReactNode\n | {\n content: React.ReactNode\n color?: SemanticColors<\n \"secondary\" | \"success\" | \"danger\" | \"warning\" | \"info\" | \"discovery\" | \"caution\"\n >\n variant?: Variants<\"soft\" | \"solid\">\n pill?: boolean\n loading?: boolean\n }\n\nexport type TabProps = {\n /**\n * Tab value\n */\n \"value\": string\n /**\n * Text read aloud to screen readers when the tab is focused\n */\n \"aria-label\"?: string\n /**\n * Text content to render in the tab\n */\n \"children\"?: React.ReactNode\n /**\n * Icon to render before the text content\n */\n \"icon\"?: React.ReactNode\n /**\n * Badge to render after the text content.\n * Can be a simple value or an object with content, color, variant, and loading options.\n * @example badge={5}\n * @example badge={{ content: 5, color: \"danger\" }}\n */\n \"badge\"?: TabsBadgeProp\n /**\n * Disable the individual tab\n */\n \"disabled\"?: boolean\n}\n\n// Type guard for badge object form\nconst isBadgeObject = (\n badge: TabsBadgeProp,\n): badge is Exclude<TabsBadgeProp, React.ReactNode> & { content: React.ReactNode } => {\n return badge != null && typeof badge === \"object\" && \"content\" in badge\n}\n\nconst Tab = ({ children, icon, badge, ...restProps }: TabProps) => {\n // Normalize badge prop\n const badgeProps = badge != null ? (isBadgeObject(badge) ? badge : { content: badge }) : null\n\n return (\n <ToggleGroup.Item\n className={s.Tab}\n {...restProps}\n onPointerEnter={handlePressableMouseEnter}\n >\n <span className={s.TabContent}>\n {icon}\n {children && <span>{children}</span>}\n {badgeProps && (\n <span\n className={s.TabBadge}\n data-color={badgeProps.color ?? \"secondary\"}\n data-variant={badgeProps.variant ?? \"soft\"}\n data-pill={badgeProps.pill ? \"\" : undefined}\n >\n {badgeProps.loading ? <LoadingIndicator /> : badgeProps.content}\n </span>\n )}\n </span>\n </ToggleGroup.Item>\n )\n}\n\n// =============================================\n// overflow=\"menu\"\n// =============================================\n\n/** Value of the menu button; no real tab has it */\nconst MORE_VALUE = \"__plexui_tabs_more__\"\n\ntype TabElement = ReactElement<TabProps>\n\n/** The tabs among the children, through fragments */\nconst tabElements = (children: ReactNode): TabElement[] =>\n Children.toArray(children).flatMap((child) => {\n if (!isValidElement<{ children?: ReactNode }>(child)) return []\n return child.type === Fragment ? tabElements(child.props.children) : [child as TabElement]\n })\n\nconst plainText = (node: unknown): string => {\n if (typeof node === \"string\" || typeof node === \"number\") return String(node)\n if (Array.isArray(node)) return node.map(plainText).join(\"\")\n if (isValidElement<{ children?: ReactNode }>(node)) return plainText(node.props.children)\n return \"\"\n}\n\nconst badgeText = (badge: TabsBadgeProp | undefined) =>\n badge != null && isBadgeObject(badge) ? plainText(badge.content) : plainText(badge)\n\n/** A tab's name: its text, else its accessible name, else its value */\nconst tabLabel = (item: TabElement) => plainText(item.props.children) || item.props[\"aria-label\"] || item.props.value\n\n/** What a tab's width depends on: the strip measures again when it changes */\nconst tabsSignature = (items: TabElement[]) =>\n items\n .map((item) =>\n [item.props.value, plainText(item.props.children), badgeText(item.props.badge), item.props.icon != null].join(\"\\u0000\"),\n )\n .join(\"\\u0001\")\n\n/**\n * `Menu.Trigger` sets `data-state` (open or closed) on its child, while a tab\n * keeps `on` or `off` in the same attribute and the thumb finds the active tab\n * by it. The menu's value does not reach the tab; its handlers and\n * `aria-haspopup` / `aria-expanded` do.\n */\nconst MoreTab = ({ \"data-state\": _menuState, ...restProps }: TabProps & { \"data-state\"?: string }) => (\n <Tab {...restProps} />\n)\n\nconst OverflowTabs = <T extends string>({\n children,\n value,\n onChange,\n overflowLabel,\n ...restProps\n}: Omit<TabsProps<T>, \"overflow\"> & { overflowLabel: string }) => {\n const items = tabElements(children)\n // The strip's own props size the tabs and the menu button too\n const { size, variant, gutterSize, pill, flush } = restProps\n const signature = [overflowLabel, size, variant, gutterSize, pill, flush, tabsSignature(items)].join(\"\\u0002\")\n const activeIndex = items.findIndex((item) => item.props.value === value)\n\n // null while the measuring pass renders every tab and the menu button\n const [visibleCount, setVisibleCount] = useState<number | null>(null)\n const [known, setKnown] = useState({ signature, activeIndex })\n const hostRef = useRef<HTMLDivElement>(null)\n const measuringRef = useRef(true)\n const boxWidthRef = useRef(-1)\n\n // New tabs measure again. A new active tab measures again when it moves\n // under the menu button or back out: the button carries the hidden one's name\n if (known.signature !== signature || known.activeIndex !== activeIndex) {\n const crossed =\n visibleCount !== null && (known.activeIndex >= visibleCount || activeIndex >= visibleCount)\n setKnown({ signature, activeIndex })\n if (visibleCount !== null && (known.signature !== signature || crossed)) setVisibleCount(null)\n }\n\n useLayoutEffect(() => {\n measuringRef.current = visibleCount === null\n }, [visibleCount])\n\n useLayoutEffect(() => {\n if (visibleCount !== null) return\n const root = hostRef.current?.firstElementChild\n if (!(root instanceof HTMLElement)) return\n\n // The measuring pass renders every tab, then the menu button\n const buttons = Array.from(root.querySelectorAll<HTMLElement>(\":scope > button\"))\n if (buttons.length !== items.length + 1) return\n\n const widths = buttons.map((button) => button.getBoundingClientRect().width)\n const moreButton = buttons[buttons.length - 1]\n const moreWidth = widths.pop() ?? 0\n const style = getComputedStyle(root)\n const available =\n root.getBoundingClientRect().width -\n (Number.parseFloat(style.paddingLeft) || 0) -\n (Number.parseFloat(style.paddingRight) || 0)\n const gap = Number.parseFloat(style.columnGap) || 0\n boxWidthRef.current = hostRef.current?.parentElement?.clientWidth ?? -1\n\n // A hidden strip has no width to decide by: show every tab, and measure\n // when it appears (the observer sees the width change)\n if (available <= 0) {\n setVisibleCount(items.length)\n return\n }\n\n // The button with the active tab's name: that tab's width plus the chevron\n const chevron = moreButton?.querySelector(\"svg\")\n const chevronWidth = chevron?.getBoundingClientRect().width ?? 0\n const labelGap = chevron?.parentElement ? Number.parseFloat(getComputedStyle(chevron.parentElement).columnGap) || 0 : 0\n const activeWidth = activeIndex < 0 ? 0 : (widths[activeIndex] ?? 0) + chevronWidth + labelGap\n\n setVisibleCount(visibleTabCount(widths, moreWidth, activeWidth, activeIndex, gap, available))\n }, [visibleCount, items.length, activeIndex])\n\n // The width to fit is the container's, not the strip's: the strip shrinks\n // to its content. Reports during a measuring pass are skipped, since the\n // full strip may be pushing its container wider\n useEffect(() => {\n const box = hostRef.current?.parentElement\n if (!box || typeof ResizeObserver === \"undefined\") return\n const observer = new ResizeObserver(() => {\n if (measuringRef.current) return\n const width = box.clientWidth\n if (width === boxWidthRef.current) return\n boxWidthRef.current = width\n setVisibleCount(null)\n })\n observer.observe(box)\n return () => observer.disconnect()\n }, [])\n\n const measuring = visibleCount === null\n const shown = measuring ? items : items.slice(0, visibleCount)\n const hidden = measuring ? [] : items.slice(visibleCount)\n const hiddenActive = hidden.find((item) => item.props.value === value) ?? null\n\n return (\n <div ref={hostRef} className={s.OverflowHost}>\n <Menu>\n <TabsRoot<string>\n {...restProps}\n data-overflow=\"menu\"\n value={hiddenActive ? MORE_VALUE : value}\n onChange={(next) => {\n // Pressing the menu button opens the menu; it is not a tab\n if (next !== MORE_VALUE) onChange?.(next as T)\n }}\n >\n {/* Keyed by value: tabs from different fragments may share a key */}\n {shown.map((item) => cloneElement(item, { key: item.props.value }))}\n {(measuring || hidden.length > 0) && (\n <Menu.Trigger>\n <MoreTab value={MORE_VALUE}>\n <span className={s.OverflowLabel}>\n {hiddenActive ? tabLabel(hiddenActive) : overflowLabel}\n <ChevronDownMd />\n </span>\n </MoreTab>\n </Menu.Trigger>\n )}\n </TabsRoot>\n <Menu.Content align=\"end\" minWidth=\"auto\">\n <Menu.RadioGroup<string> value={value} onChange={(next) => onChange?.(next as T)}>\n {hidden.map((item) => {\n const count = badgeText(item.props.badge)\n return (\n <Menu.RadioItem<string>\n key={item.props.value}\n value={item.props.value}\n disabled={restProps.disabled || item.props.disabled}\n >\n {item.props.icon}\n {item.props.children ?? item.props[\"aria-label\"] ?? item.props.value}\n {/* A tab's count moves into the menu with it */}\n {count !== \"\" && <span className={s.OverflowBadge}>{count}</span>}\n </Menu.RadioItem>\n )\n })}\n </Menu.RadioGroup>\n </Menu.Content>\n </Menu>\n </div>\n )\n}\n\n// Attach sub-components\nTabs.Tab = Tab\n// Backward-compat alias\nTabs.Option = Tab\n"]}
@@ -1,2 +1,2 @@
1
- export { Tabs } from "./Tabs";
1
+ export { Tabs } from "./Tabs.js";
2
2
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Width math for `Tabs overflow="menu"`: how many tabs fit before the menu
3
+ * button. Shared by the React and Vue packages (the Vue copy must match).
4
+ */
5
+ /**
6
+ * Slack for subpixels. Widths are fractional (`getBoundingClientRect`), and a
7
+ * tab that fits exactly is sometimes off by the last digit; without the
8
+ * tolerance the strip would flicker between two counts.
9
+ */
10
+ const FIT_TOLERANCE_PX = 0.5;
11
+ /**
12
+ * How many tabs fit. When all of them do, the count is their number and no
13
+ * menu button is needed; otherwise room for the button is taken first.
14
+ */
15
+ export function fitCount(widths, moreWidth, gap, available) {
16
+ const total = widths.reduce((sum, width, index) => sum + width + (index > 0 ? gap : 0), 0);
17
+ if (total <= available + FIT_TOLERANCE_PX)
18
+ return widths.length;
19
+ const budget = available - moreWidth - gap;
20
+ let used = 0;
21
+ let count = 0;
22
+ for (const width of widths) {
23
+ const next = used + width + (count > 0 ? gap : 0);
24
+ if (next > budget + FIT_TOLERANCE_PX)
25
+ break;
26
+ used = next;
27
+ count += 1;
28
+ }
29
+ return count;
30
+ }
31
+ /**
32
+ * How many tabs stay in the strip when the hidden active tab lends its name
33
+ * to the menu button, which then grows wider than "More". Counted twice: with
34
+ * the narrow button first, and with the wide one if the active tab did not
35
+ * fit. The reserve only grows, so the second count cannot bring the active
36
+ * tab back into the strip.
37
+ */
38
+ export function visibleTabCount(widths, moreWidth, activeWidth, activeIndex, gap, available) {
39
+ const count = fitCount(widths, moreWidth, gap, available);
40
+ if (activeIndex < 0 || activeIndex < count)
41
+ return count;
42
+ return fitCount(widths, Math.max(moreWidth, activeWidth), gap, available);
43
+ }
44
+ //# sourceMappingURL=overflow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"overflow.js","sourceRoot":"","sources":["../../../../src/components/Tabs/overflow.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;GAIG;AACH,MAAM,gBAAgB,GAAG,GAAG,CAAA;AAE5B;;;GAGG;AACH,MAAM,UAAU,QAAQ,CAAC,MAAgB,EAAE,SAAiB,EAAE,GAAW,EAAE,SAAiB;IAC1F,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,GAAG,KAAK,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IAC1F,IAAI,KAAK,IAAI,SAAS,GAAG,gBAAgB;QAAE,OAAO,MAAM,CAAC,MAAM,CAAA;IAE/D,MAAM,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,GAAG,CAAA;IAC1C,IAAI,IAAI,GAAG,CAAC,CAAA;IACZ,IAAI,KAAK,GAAG,CAAC,CAAA;IACb,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,IAAI,GAAG,IAAI,GAAG,KAAK,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QACjD,IAAI,IAAI,GAAG,MAAM,GAAG,gBAAgB;YAAE,MAAK;QAC3C,IAAI,GAAG,IAAI,CAAA;QACX,KAAK,IAAI,CAAC,CAAA;IACZ,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAC7B,MAAgB,EAChB,SAAiB,EACjB,WAAmB,EACnB,WAAmB,EACnB,GAAW,EACX,SAAiB;IAEjB,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,CAAC,CAAA;IACzD,IAAI,WAAW,GAAG,CAAC,IAAI,WAAW,GAAG,KAAK;QAAE,OAAO,KAAK,CAAA;IACxD,OAAO,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,WAAW,CAAC,EAAE,GAAG,EAAE,SAAS,CAAC,CAAA;AAC3E,CAAC","sourcesContent":["/**\n * Width math for `Tabs overflow=\"menu\"`: how many tabs fit before the menu\n * button. Shared by the React and Vue packages (the Vue copy must match).\n */\n\n/**\n * Slack for subpixels. Widths are fractional (`getBoundingClientRect`), and a\n * tab that fits exactly is sometimes off by the last digit; without the\n * tolerance the strip would flicker between two counts.\n */\nconst FIT_TOLERANCE_PX = 0.5\n\n/**\n * How many tabs fit. When all of them do, the count is their number and no\n * menu button is needed; otherwise room for the button is taken first.\n */\nexport function fitCount(widths: number[], moreWidth: number, gap: number, available: number): number {\n const total = widths.reduce((sum, width, index) => sum + width + (index > 0 ? gap : 0), 0)\n if (total <= available + FIT_TOLERANCE_PX) return widths.length\n\n const budget = available - moreWidth - gap\n let used = 0\n let count = 0\n for (const width of widths) {\n const next = used + width + (count > 0 ? gap : 0)\n if (next > budget + FIT_TOLERANCE_PX) break\n used = next\n count += 1\n }\n return count\n}\n\n/**\n * How many tabs stay in the strip when the hidden active tab lends its name\n * to the menu button, which then grows wider than \"More\". Counted twice: with\n * the narrow button first, and with the wide one if the active tab did not\n * fit. The reserve only grows, so the second count cannot bring the active\n * tab back into the strip.\n */\nexport function visibleTabCount(\n widths: number[],\n moreWidth: number,\n activeWidth: number,\n activeIndex: number,\n gap: number,\n available: number,\n): number {\n const count = fitCount(widths, moreWidth, gap, available)\n if (activeIndex < 0 || activeIndex < count) return count\n return fitCount(widths, Math.max(moreWidth, activeWidth), gap, available)\n}\n"]}
@@ -2,10 +2,10 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import React, { useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
4
4
  import { useOnClickOutside } from "usehooks-ts";
5
- import { useLatestValue } from "../../hooks/useLatestValue";
6
- import { toCssVariables } from "../../lib/helpers";
7
- import { X } from "../Icon";
8
- import s from "./TagInput.module.css";
5
+ import { useLatestValue } from "../../hooks/useLatestValue.js";
6
+ import { toCssVariables } from "../../lib/helpers.js";
7
+ import { X } from "../Icon/index.js";
8
+ import s from "@plexui/styles/components/TagInput/TagInput.module.css";
9
9
  // How many pixels to reserve on the right of the input as a buffer before wrapping to the next line
10
10
  const INPUT_CURSOR_TOLERANCE_PX = 10;
11
11
  // The total space reserved on either side of the input for padding
@@ -38,7 +38,7 @@ export const TagInput = (props) => {
38
38
  defaultFocusEl.focus();
39
39
  }
40
40
  else {
41
- const selectedTagElement = containerRef.current.querySelector(`[data-tag="${selectedTag}"]`);
41
+ const selectedTagElement = containerRef.current.querySelector(`[data-tag="${CSS.escape(selectedTag)}"]`);
42
42
  if (selectedTagElement) {
43
43
  selectedTagElement.focus();
44
44
  }
@@ -108,30 +108,46 @@ export const TagInput = (props) => {
108
108
  // ============================================
109
109
  // Tag lifecycle functions
110
110
  // ============================================
111
- const addTag = (tagValue) => {
112
- const trimmed = tagValue.trim();
113
- if (!trimmed) {
114
- return;
111
+ // Adds every value in one update: a paste of "a,b" must not compute
112
+ // each addition from the same stale `tags` snapshot.
113
+ const addTags = (tagValues) => {
114
+ const newSet = new Map(tags);
115
+ let changed = false;
116
+ for (const tagValue of tagValues) {
117
+ if (maxTags && newSet.size >= maxTags) {
118
+ break;
119
+ }
120
+ const trimmed = tagValue.trim();
121
+ if (!trimmed) {
122
+ continue;
123
+ }
124
+ if (newSet.has(trimmed)) {
125
+ setDuplicateTags((prevTags) => new Set(prevTags).add(trimmed));
126
+ setTimeout(() => setDuplicateTags((prevTags) => {
127
+ const newTags = new Set(prevTags);
128
+ newTags.delete(trimmed);
129
+ return newTags;
130
+ }), SHAKE_ANIMATION_DURATION_MS);
131
+ continue;
132
+ }
133
+ const validTag = validatorLatest.current?.(trimmed) ?? true;
134
+ newSet.set(trimmed, { value: trimmed, valid: validTag });
135
+ changed = true;
115
136
  }
116
- if (tags.has(trimmed)) {
117
- setDuplicateTags((prevTags) => new Set(prevTags).add(trimmed));
118
- setTimeout(() => setDuplicateTags((prevTags) => {
119
- const newTags = new Set(prevTags);
120
- newTags.delete(trimmed);
121
- return newTags;
122
- }), SHAKE_ANIMATION_DURATION_MS);
137
+ if (!changed) {
123
138
  return;
124
139
  }
125
- const validTag = validatorLatest.current?.(trimmed) ?? true;
126
- const newSet = new Map(tags);
127
- newSet.set(trimmed, { value: trimmed, valid: validTag });
128
140
  const newTags = Array.from(newSet.values());
129
141
  onChangeLatest.current?.(newTags);
130
142
  if (!isControlled) {
131
143
  setInternalTags(newTags);
132
144
  }
133
145
  };
146
+ const addTag = (tagValue) => addTags([tagValue]);
134
147
  const removeTag = (tag) => {
148
+ if (disabled) {
149
+ return;
150
+ }
135
151
  const newSet = new Map(tags);
136
152
  newSet.delete(tag);
137
153
  const newTags = Array.from(newSet.values());
@@ -184,7 +200,8 @@ export const TagInput = (props) => {
184
200
  const handleContainerBlur = () => {
185
201
  setFocused(false);
186
202
  setSelectedTag(null);
187
- if (currentInput) {
203
+ // A disabled tag input keeps the pending text instead of committing it
204
+ if (currentInput && !disabled) {
188
205
  addTag(currentInput);
189
206
  setCurrentInput("");
190
207
  }
@@ -193,6 +210,10 @@ export const TagInput = (props) => {
193
210
  // Event handlers
194
211
  // ============================================
195
212
  const handleContainerKeyDown = (e) => {
213
+ // A tag can keep focus while the input turns disabled: no selecting or removing then
214
+ if (disabled) {
215
+ return;
216
+ }
196
217
  if (e.key === "ArrowLeft" || e.key === "ArrowUp") {
197
218
  if (isEmptyStartingSelection()) {
198
219
  e.preventDefault();
@@ -245,7 +266,7 @@ export const TagInput = (props) => {
245
266
  parts = parts.filter(Boolean);
246
267
  if (parts.length > 1) {
247
268
  e.preventDefault();
248
- parts.forEach((part) => addTag(part));
269
+ addTags(parts);
249
270
  }
250
271
  };
251
272
  const handleContainerMouseDown = (e) => {
@@ -310,8 +331,11 @@ export const TagInput = (props) => {
310
331
  };
311
332
  // @ts-expect-error - Fix once usehooks-ts is updated https://github.com/juliencrn/usehooks-ts/pull/675
312
333
  useOnClickOutside(containerRef, handleContainerBlur);
313
- return (_jsxs(_Fragment, { children: [_jsx("div", { className: s.Container, ref: containerRef, onKeyDown: handleContainerKeyDown, onMouseDown: handleContainerMouseDown, onFocus: handleFocus, onBlur: handleBlur, "data-size": size, "data-focused": focused ? "" : undefined, "data-empty": tags.size === 0 ? "" : undefined, "data-pill": pill ? "" : undefined, tabIndex: -1, style: toCssVariables({ "min-rows": String(rows) }), "data-disabled": disabled ? "" : undefined, children: _jsxs("div", { className: s.TagInput, children: [Array.from(tags.values()).map((tag) => (_jsxs("div", { className: s.Tag, tabIndex: -1, onClick: () => setSelectedTag(tag.value), "data-tag": tag.value, "data-invalid": !tag.valid ? "" : undefined, "data-duplicate": duplicateTags.has(tag.value) ? "" : undefined, children: [_jsx("span", { className: "overflow-hidden text-ellipsis", title: tag.value, children: _jsx("span", { className: s.TagValue, children: tag.value }) }), _jsx("div", { className: s.TagRemove, onClick: () => removeTag(tag.value), role: "button", "aria-label": "Remove item", children: _jsx(X, {}) })] }, tag.value))), showInput && (_jsxs("div", { className: s.InputContainer, children: [_jsx("span", { ref: measureRef, className: s.InputMeasure }), _jsx("div", { className: s.InputWrapper, children: _jsx("input", { id: id, className: s.Input, ref: inputRef, value: currentInput, onChange: (e) => {
334
+ return (_jsxs(_Fragment, { children: [_jsx("div", { className: s.Container, ref: containerRef, onKeyDown: handleContainerKeyDown, onMouseDown: handleContainerMouseDown, onFocus: handleFocus, onBlur: handleBlur, "data-size": size, "data-focused": focused ? "" : undefined, "data-empty": tags.size === 0 ? "" : undefined, "data-pill": pill ? "" : undefined,
335
+ // At maxTags the input is gone, so the container becomes the tab stop;
336
+ // arrow keys and Backspace then select and remove tags from here
337
+ tabIndex: showInput || disabled ? -1 : 0, style: toCssVariables({ "min-rows": String(rows) }), "data-disabled": disabled ? "" : undefined, children: _jsxs("div", { className: s.TagInput, children: [Array.from(tags.values()).map((tag) => (_jsxs("div", { className: s.Tag, tabIndex: -1, onClick: () => setSelectedTag(tag.value), "data-tag": tag.value, "data-invalid": !tag.valid ? "" : undefined, "data-duplicate": duplicateTags.has(tag.value) ? "" : undefined, children: [_jsx("span", { className: "overflow-hidden text-ellipsis", title: tag.value, children: _jsx("span", { className: s.TagValue, children: tag.value }) }), _jsx("div", { className: s.TagRemove, onClick: () => removeTag(tag.value), role: "button", "aria-label": "Remove item", children: _jsx(X, {}) })] }, tag.value))), showInput && (_jsxs("div", { className: s.InputContainer, children: [_jsx("span", { ref: measureRef, className: s.InputMeasure }), _jsx("div", { className: s.InputWrapper, children: _jsx("input", { id: id, className: s.Input, ref: inputRef, value: currentInput, onChange: (e) => {
314
338
  setCurrentInput(e.target.value);
315
- }, onPaste: handlePaste, onKeyDown: handleInputKeyDown, placeholder: placeholderText, style: { width: inputWidth }, disabled: disabled }) })] }))] }) }), maxTags && (_jsxs("div", { className: s.Limit, children: [tags.size, _jsx("span", { className: "mx-px", children: "/" }), maxTags] }))] }));
339
+ }, onPaste: handlePaste, onKeyDown: handleInputKeyDown, placeholder: placeholderText, style: { width: inputWidth }, disabled: disabled }) })] }))] }) }), maxTags ? (_jsxs("div", { className: s.Limit, children: [tags.size, _jsx("span", { className: "mx-px", children: "/" }), maxTags] })) : null] }));
316
340
  };
317
341
  //# sourceMappingURL=TagInput.js.map