@intlayer/design-system 8.9.1 → 8.9.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 (348) hide show
  1. package/dist/esm/components/Accordion/Accordion.mjs.map +1 -1
  2. package/dist/esm/components/Avatar/image.mjs.map +1 -1
  3. package/dist/esm/components/Avatar/index.mjs.map +1 -1
  4. package/dist/esm/components/Badge/index.mjs.map +1 -1
  5. package/dist/esm/components/Breadcrumb/index.mjs.map +1 -1
  6. package/dist/esm/components/Browser/Browser.mjs.map +1 -1
  7. package/dist/esm/components/Button/Button.mjs.map +1 -1
  8. package/dist/esm/components/Carousel/index.mjs.map +1 -1
  9. package/dist/esm/components/ClickOutsideDiv/index.mjs.map +1 -1
  10. package/dist/esm/components/CollapsibleTable/CollapsibleTable.mjs.map +1 -1
  11. package/dist/esm/components/Command/index.mjs.map +1 -1
  12. package/dist/esm/components/Container/index.mjs.map +1 -1
  13. package/dist/esm/components/ContentEditor/ContentEditor.mjs.map +1 -1
  14. package/dist/esm/components/ContentEditor/ContentEditorInput.mjs.map +1 -1
  15. package/dist/esm/components/ContentEditor/ContentEditorTextArea.mjs +1 -1
  16. package/dist/esm/components/ContentEditor/ContentEditorTextArea.mjs.map +1 -1
  17. package/dist/esm/components/CopyButton/index.mjs.map +1 -1
  18. package/dist/esm/components/CopyToClipboard/index.mjs.map +1 -1
  19. package/dist/esm/components/DictionaryEditor/DictionaryEditor.mjs.map +1 -1
  20. package/dist/esm/components/DictionaryEditor/NodeWrapper/ArrayWrapper.mjs.map +1 -1
  21. package/dist/esm/components/DictionaryEditor/NodeWrapper/BooleanWrapper.mjs.map +1 -1
  22. package/dist/esm/components/DictionaryEditor/NodeWrapper/ConditionWrapper.mjs.map +1 -1
  23. package/dist/esm/components/DictionaryEditor/NodeWrapper/EnumerationWrapper.mjs.map +1 -1
  24. package/dist/esm/components/DictionaryEditor/NodeWrapper/FileWrapper.mjs.map +1 -1
  25. package/dist/esm/components/DictionaryEditor/NodeWrapper/HtmlWrapper.mjs.map +1 -1
  26. package/dist/esm/components/DictionaryEditor/NodeWrapper/InsertionWrapper.mjs.map +1 -1
  27. package/dist/esm/components/DictionaryEditor/NodeWrapper/MarkdownWrapper.mjs.map +1 -1
  28. package/dist/esm/components/DictionaryEditor/NodeWrapper/NestedObjectWrapper.mjs.map +1 -1
  29. package/dist/esm/components/DictionaryEditor/NodeWrapper/NumberWrapper.mjs.map +1 -1
  30. package/dist/esm/components/DictionaryEditor/NodeWrapper/PluralWrapper.mjs.map +1 -1
  31. package/dist/esm/components/DictionaryEditor/NodeWrapper/StringWrapper.mjs.map +1 -1
  32. package/dist/esm/components/DictionaryEditor/NodeWrapper/TranslationWrapper.mjs.map +1 -1
  33. package/dist/esm/components/DictionaryEditor/NodeWrapper/index.mjs.map +1 -1
  34. package/dist/esm/components/DictionaryFieldEditor/ContentEditor.mjs.map +1 -1
  35. package/dist/esm/components/DictionaryFieldEditor/ContentEditorView/TextEditor.mjs +2 -2
  36. package/dist/esm/components/DictionaryFieldEditor/ContentEditorView/TextEditor.mjs.map +1 -1
  37. package/dist/esm/components/DictionaryFieldEditor/ContentEditorView/object.mjs.map +1 -1
  38. package/dist/esm/components/DictionaryFieldEditor/DictionaryCreationForm/DictionaryCreationForm.mjs +1 -1
  39. package/dist/esm/components/DictionaryFieldEditor/DictionaryCreationForm/DictionaryCreationForm.mjs.map +1 -1
  40. package/dist/esm/components/DictionaryFieldEditor/DictionaryCreationForm/useDictionaryFormSchema.mjs.map +1 -1
  41. package/dist/esm/components/DictionaryFieldEditor/DictionaryDetails/DictionaryDetailsForm.mjs +40 -44
  42. package/dist/esm/components/DictionaryFieldEditor/DictionaryDetails/DictionaryDetailsForm.mjs.map +1 -1
  43. package/dist/esm/components/DictionaryFieldEditor/DictionaryDetails/useDictionaryDetailsSchema.mjs.map +1 -1
  44. package/dist/esm/components/DictionaryFieldEditor/DictionaryFieldEditor.mjs +25 -18
  45. package/dist/esm/components/DictionaryFieldEditor/DictionaryFieldEditor.mjs.map +1 -1
  46. package/dist/esm/components/DictionaryFieldEditor/EnumKeyInput.mjs.map +1 -1
  47. package/dist/esm/components/DictionaryFieldEditor/JSONEditor.mjs.map +1 -1
  48. package/dist/esm/components/DictionaryFieldEditor/KeyPathBreadcrumb.mjs.map +1 -1
  49. package/dist/esm/components/DictionaryFieldEditor/NavigationView/NavigationViewNode.mjs +2 -2
  50. package/dist/esm/components/DictionaryFieldEditor/NavigationView/NavigationViewNode.mjs.map +1 -1
  51. package/dist/esm/components/DictionaryFieldEditor/NodeTypeSelector.mjs.map +1 -1
  52. package/dist/esm/components/DictionaryFieldEditor/SaveForm/SaveForm.mjs +3 -3
  53. package/dist/esm/components/DictionaryFieldEditor/SaveForm/SaveForm.mjs.map +1 -1
  54. package/dist/esm/components/DictionaryFieldEditor/StructureEditor.mjs.map +1 -1
  55. package/dist/esm/components/DictionaryFieldEditor/StructureView/StructureView.mjs +1 -1
  56. package/dist/esm/components/DictionaryFieldEditor/StructureView/StructureView.mjs.map +1 -1
  57. package/dist/esm/components/DictionaryFieldEditor/VersionSwitcherDropDown/VersionSwitcher.mjs.map +1 -1
  58. package/dist/esm/components/DictionaryFieldEditor/VersionSwitcherDropDown/VersionSwitcherContext.mjs.map +1 -1
  59. package/dist/esm/components/DictionaryFieldEditor/getIsEditableSection.mjs.map +1 -1
  60. package/dist/esm/components/DropDown/index.mjs.map +1 -1
  61. package/dist/esm/components/EditableField/EditableFieldInput.mjs.map +1 -1
  62. package/dist/esm/components/EditableField/EditableFieldLayout.mjs.map +1 -1
  63. package/dist/esm/components/EditableField/EditableFieldTextArea.mjs.map +1 -1
  64. package/dist/esm/components/ExpandCollapse/ExpandCollapse.mjs.map +1 -1
  65. package/dist/esm/components/Flags/Flag.mjs.map +1 -1
  66. package/dist/esm/components/Flags/ae.mjs.map +1 -1
  67. package/dist/esm/components/Flags/af.mjs.map +1 -1
  68. package/dist/esm/components/Flags/al.mjs.map +1 -1
  69. package/dist/esm/components/Flags/am.mjs.map +1 -1
  70. package/dist/esm/components/Flags/ar.mjs.map +1 -1
  71. package/dist/esm/components/Flags/at.mjs.map +1 -1
  72. package/dist/esm/components/Flags/au.mjs.map +1 -1
  73. package/dist/esm/components/Flags/az.mjs.map +1 -1
  74. package/dist/esm/components/Flags/ba.mjs.map +1 -1
  75. package/dist/esm/components/Flags/bd.mjs.map +1 -1
  76. package/dist/esm/components/Flags/be.mjs.map +1 -1
  77. package/dist/esm/components/Flags/bg.mjs.map +1 -1
  78. package/dist/esm/components/Flags/bh.mjs.map +1 -1
  79. package/dist/esm/components/Flags/bn.mjs.map +1 -1
  80. package/dist/esm/components/Flags/bo.mjs.map +1 -1
  81. package/dist/esm/components/Flags/br.mjs.map +1 -1
  82. package/dist/esm/components/Flags/bw.mjs.map +1 -1
  83. package/dist/esm/components/Flags/by.mjs.map +1 -1
  84. package/dist/esm/components/Flags/bz.mjs.map +1 -1
  85. package/dist/esm/components/Flags/ca.mjs.map +1 -1
  86. package/dist/esm/components/Flags/ch.mjs.map +1 -1
  87. package/dist/esm/components/Flags/cl.mjs.map +1 -1
  88. package/dist/esm/components/Flags/cn.mjs.map +1 -1
  89. package/dist/esm/components/Flags/co.mjs.map +1 -1
  90. package/dist/esm/components/Flags/cr.mjs.map +1 -1
  91. package/dist/esm/components/Flags/cu.mjs.map +1 -1
  92. package/dist/esm/components/Flags/cv.mjs.map +1 -1
  93. package/dist/esm/components/Flags/cz.mjs.map +1 -1
  94. package/dist/esm/components/Flags/de.mjs.map +1 -1
  95. package/dist/esm/components/Flags/dj.mjs.map +1 -1
  96. package/dist/esm/components/Flags/dk.mjs.map +1 -1
  97. package/dist/esm/components/Flags/do.mjs.map +1 -1
  98. package/dist/esm/components/Flags/dz.mjs.map +1 -1
  99. package/dist/esm/components/Flags/ec.mjs.map +1 -1
  100. package/dist/esm/components/Flags/ee.mjs.map +1 -1
  101. package/dist/esm/components/Flags/eg.mjs.map +1 -1
  102. package/dist/esm/components/Flags/es-ct.mjs.map +1 -1
  103. package/dist/esm/components/Flags/es-ga.mjs.map +1 -1
  104. package/dist/esm/components/Flags/es-pv.mjs.map +1 -1
  105. package/dist/esm/components/Flags/es.mjs.map +1 -1
  106. package/dist/esm/components/Flags/et.mjs.map +1 -1
  107. package/dist/esm/components/Flags/fi.mjs.map +1 -1
  108. package/dist/esm/components/Flags/fo.mjs.map +1 -1
  109. package/dist/esm/components/Flags/fr.mjs.map +1 -1
  110. package/dist/esm/components/Flags/gb-wls.mjs.map +1 -1
  111. package/dist/esm/components/Flags/gb.mjs.map +1 -1
  112. package/dist/esm/components/Flags/ge.mjs.map +1 -1
  113. package/dist/esm/components/Flags/gh.mjs.map +1 -1
  114. package/dist/esm/components/Flags/gr.mjs.map +1 -1
  115. package/dist/esm/components/Flags/gt.mjs.map +1 -1
  116. package/dist/esm/components/Flags/gw.mjs.map +1 -1
  117. package/dist/esm/components/Flags/hk.mjs.map +1 -1
  118. package/dist/esm/components/Flags/hn.mjs.map +1 -1
  119. package/dist/esm/components/Flags/hr.mjs.map +1 -1
  120. package/dist/esm/components/Flags/hu.mjs.map +1 -1
  121. package/dist/esm/components/Flags/id.mjs.map +1 -1
  122. package/dist/esm/components/Flags/ie.mjs.map +1 -1
  123. package/dist/esm/components/Flags/il.mjs.map +1 -1
  124. package/dist/esm/components/Flags/in.mjs.map +1 -1
  125. package/dist/esm/components/Flags/iq.mjs.map +1 -1
  126. package/dist/esm/components/Flags/ir.mjs.map +1 -1
  127. package/dist/esm/components/Flags/is.mjs.map +1 -1
  128. package/dist/esm/components/Flags/it.mjs.map +1 -1
  129. package/dist/esm/components/Flags/jm.mjs.map +1 -1
  130. package/dist/esm/components/Flags/jo.mjs.map +1 -1
  131. package/dist/esm/components/Flags/jp.mjs.map +1 -1
  132. package/dist/esm/components/Flags/ke.mjs.map +1 -1
  133. package/dist/esm/components/Flags/kg.mjs.map +1 -1
  134. package/dist/esm/components/Flags/kh.mjs.map +1 -1
  135. package/dist/esm/components/Flags/km.mjs.map +1 -1
  136. package/dist/esm/components/Flags/kr.mjs.map +1 -1
  137. package/dist/esm/components/Flags/kw.mjs.map +1 -1
  138. package/dist/esm/components/Flags/kz.mjs.map +1 -1
  139. package/dist/esm/components/Flags/la.mjs.map +1 -1
  140. package/dist/esm/components/Flags/lb.mjs.map +1 -1
  141. package/dist/esm/components/Flags/li.mjs.map +1 -1
  142. package/dist/esm/components/Flags/lk.mjs.map +1 -1
  143. package/dist/esm/components/Flags/lt.mjs.map +1 -1
  144. package/dist/esm/components/Flags/lu.mjs.map +1 -1
  145. package/dist/esm/components/Flags/lv.mjs.map +1 -1
  146. package/dist/esm/components/Flags/ly.mjs.map +1 -1
  147. package/dist/esm/components/Flags/ma.mjs.map +1 -1
  148. package/dist/esm/components/Flags/mc.mjs.map +1 -1
  149. package/dist/esm/components/Flags/md.mjs.map +1 -1
  150. package/dist/esm/components/Flags/mk.mjs.map +1 -1
  151. package/dist/esm/components/Flags/mm.mjs.map +1 -1
  152. package/dist/esm/components/Flags/mn.mjs.map +1 -1
  153. package/dist/esm/components/Flags/mo.mjs.map +1 -1
  154. package/dist/esm/components/Flags/mr.mjs.map +1 -1
  155. package/dist/esm/components/Flags/mt.mjs.map +1 -1
  156. package/dist/esm/components/Flags/mv.mjs.map +1 -1
  157. package/dist/esm/components/Flags/mx.mjs.map +1 -1
  158. package/dist/esm/components/Flags/my.mjs.map +1 -1
  159. package/dist/esm/components/Flags/mz.mjs.map +1 -1
  160. package/dist/esm/components/Flags/ng.mjs.map +1 -1
  161. package/dist/esm/components/Flags/ni.mjs.map +1 -1
  162. package/dist/esm/components/Flags/nl.mjs.map +1 -1
  163. package/dist/esm/components/Flags/no.mjs.map +1 -1
  164. package/dist/esm/components/Flags/np.mjs.map +1 -1
  165. package/dist/esm/components/Flags/nz.mjs.map +1 -1
  166. package/dist/esm/components/Flags/om.mjs.map +1 -1
  167. package/dist/esm/components/Flags/pa.mjs.map +1 -1
  168. package/dist/esm/components/Flags/pe.mjs.map +1 -1
  169. package/dist/esm/components/Flags/ph.mjs.map +1 -1
  170. package/dist/esm/components/Flags/pk.mjs.map +1 -1
  171. package/dist/esm/components/Flags/pl.mjs.map +1 -1
  172. package/dist/esm/components/Flags/pr.mjs.map +1 -1
  173. package/dist/esm/components/Flags/ps.mjs.map +1 -1
  174. package/dist/esm/components/Flags/pt.mjs.map +1 -1
  175. package/dist/esm/components/Flags/py.mjs.map +1 -1
  176. package/dist/esm/components/Flags/qa.mjs.map +1 -1
  177. package/dist/esm/components/Flags/ro.mjs.map +1 -1
  178. package/dist/esm/components/Flags/rs.mjs.map +1 -1
  179. package/dist/esm/components/Flags/ru.mjs.map +1 -1
  180. package/dist/esm/components/Flags/sa.mjs.map +1 -1
  181. package/dist/esm/components/Flags/sd.mjs.map +1 -1
  182. package/dist/esm/components/Flags/se.mjs.map +1 -1
  183. package/dist/esm/components/Flags/sg.mjs.map +1 -1
  184. package/dist/esm/components/Flags/si.mjs.map +1 -1
  185. package/dist/esm/components/Flags/sk.mjs.map +1 -1
  186. package/dist/esm/components/Flags/so.mjs.map +1 -1
  187. package/dist/esm/components/Flags/st.mjs.map +1 -1
  188. package/dist/esm/components/Flags/sv.mjs.map +1 -1
  189. package/dist/esm/components/Flags/sy.mjs.map +1 -1
  190. package/dist/esm/components/Flags/td.mjs.map +1 -1
  191. package/dist/esm/components/Flags/th.mjs.map +1 -1
  192. package/dist/esm/components/Flags/tl.mjs.map +1 -1
  193. package/dist/esm/components/Flags/tn.mjs.map +1 -1
  194. package/dist/esm/components/Flags/tr.mjs.map +1 -1
  195. package/dist/esm/components/Flags/tt.mjs.map +1 -1
  196. package/dist/esm/components/Flags/tw.mjs.map +1 -1
  197. package/dist/esm/components/Flags/tz.mjs.map +1 -1
  198. package/dist/esm/components/Flags/ua.mjs.map +1 -1
  199. package/dist/esm/components/Flags/ug.mjs.map +1 -1
  200. package/dist/esm/components/Flags/us.mjs.map +1 -1
  201. package/dist/esm/components/Flags/uy.mjs.map +1 -1
  202. package/dist/esm/components/Flags/uz.mjs.map +1 -1
  203. package/dist/esm/components/Flags/ve.mjs.map +1 -1
  204. package/dist/esm/components/Flags/vn.mjs.map +1 -1
  205. package/dist/esm/components/Flags/xx.mjs.map +1 -1
  206. package/dist/esm/components/Flags/ye.mjs.map +1 -1
  207. package/dist/esm/components/Flags/za.mjs.map +1 -1
  208. package/dist/esm/components/Flags/zw.mjs.map +1 -1
  209. package/dist/esm/components/Form/FormBase.mjs.map +1 -1
  210. package/dist/esm/components/Form/FormControl.mjs.map +1 -1
  211. package/dist/esm/components/Form/FormDescription.mjs.map +1 -1
  212. package/dist/esm/components/Form/FormField.mjs.map +1 -1
  213. package/dist/esm/components/Form/FormItem.mjs.map +1 -1
  214. package/dist/esm/components/Form/FormLabel.mjs.map +1 -1
  215. package/dist/esm/components/Form/FormMessage.mjs.map +1 -1
  216. package/dist/esm/components/Form/elements/FormElement.mjs.map +1 -1
  217. package/dist/esm/components/Form/elements/FormElementWrapper.mjs.map +1 -1
  218. package/dist/esm/components/Form/elements/MultiselectElement.mjs.map +1 -1
  219. package/dist/esm/components/Form/elements/OTPElement.mjs +1 -1
  220. package/dist/esm/components/Form/elements/OTPElement.mjs.map +1 -1
  221. package/dist/esm/components/Form/elements/SelectElement.mjs.map +1 -1
  222. package/dist/esm/components/Form/elements/SwitchSelectorElement.mjs.map +1 -1
  223. package/dist/esm/components/HTMLRender/HTMLRender.mjs.map +1 -1
  224. package/dist/esm/components/Headers/index.mjs.map +1 -1
  225. package/dist/esm/components/HeightResizer/index.mjs.map +1 -1
  226. package/dist/esm/components/HideShow/index.mjs.map +1 -1
  227. package/dist/esm/components/IDE/Code.mjs.map +1 -1
  228. package/dist/esm/components/IDE/CodeBlockHighlight.mjs.map +1 -1
  229. package/dist/esm/components/IDE/CodeBlockServer.mjs.map +1 -1
  230. package/dist/esm/components/IDE/CodeBlockShiki.mjs.map +1 -1
  231. package/dist/esm/components/IDE/CodeConditionalRenderer.mjs.map +1 -1
  232. package/dist/esm/components/IDE/CodeContext.mjs.map +1 -1
  233. package/dist/esm/components/IDE/CodeFormatSelector.mjs.map +1 -1
  234. package/dist/esm/components/IDE/ContentDeclarationFormatSelector.mjs.map +1 -1
  235. package/dist/esm/components/IDE/CopyCode.mjs.map +1 -1
  236. package/dist/esm/components/IDE/FileTree.mjs.map +1 -1
  237. package/dist/esm/components/IDE/IDE.mjs.map +1 -1
  238. package/dist/esm/components/IDE/MonacoCode.mjs.map +1 -1
  239. package/dist/esm/components/IDE/PackageManagerSelector.mjs.map +1 -1
  240. package/dist/esm/components/IDE/codeTransformer.mjs.map +1 -1
  241. package/dist/esm/components/IDE/createFileTree.mjs.map +1 -1
  242. package/dist/esm/components/Input/Checkbox.mjs +2 -0
  243. package/dist/esm/components/Input/Checkbox.mjs.map +1 -1
  244. package/dist/esm/components/Input/Input.mjs.map +1 -1
  245. package/dist/esm/components/Input/InputPassword.mjs.map +1 -1
  246. package/dist/esm/components/Input/OTPInput.mjs.map +1 -1
  247. package/dist/esm/components/KeyboardScreenAdapter/index.mjs.map +1 -1
  248. package/dist/esm/components/KeyboardShortcut/KeyboardShortcut.mjs.map +1 -1
  249. package/dist/esm/components/LanguageBackground/index.mjs.map +1 -1
  250. package/dist/esm/components/Link/Link.mjs.map +1 -1
  251. package/dist/esm/components/LocaleSwitcherContentDropDown/LocaleSwitcherContent.mjs +1 -1
  252. package/dist/esm/components/LocaleSwitcherContentDropDown/LocaleSwitcherContent.mjs.map +1 -1
  253. package/dist/esm/components/LocaleSwitcherContentDropDown/LocaleSwitcherContentContext.mjs.map +1 -1
  254. package/dist/esm/components/LocaleSwitcherDropDown/LocaleSwitcher.mjs.map +1 -1
  255. package/dist/esm/components/MarkDownRender/MarkDownIframe.mjs.map +1 -1
  256. package/dist/esm/components/MarkDownRender/MarkDownRender.mjs +5 -20
  257. package/dist/esm/components/MarkDownRender/MarkDownRender.mjs.map +1 -1
  258. package/dist/esm/components/Modal/Modal.mjs +2 -2
  259. package/dist/esm/components/Modal/Modal.mjs.map +1 -1
  260. package/dist/esm/components/Navbar/MobileNavbar.mjs +1 -1
  261. package/dist/esm/components/Navbar/MobileNavbar.mjs.map +1 -1
  262. package/dist/esm/components/Navbar/index.mjs.map +1 -1
  263. package/dist/esm/components/Navbar/useNavigation.mjs.map +1 -1
  264. package/dist/esm/components/Pagination/NumberItemsSelector.mjs.map +1 -1
  265. package/dist/esm/components/Pagination/Pagination.mjs +1 -1
  266. package/dist/esm/components/Pagination/Pagination.mjs.map +1 -1
  267. package/dist/esm/components/Pagination/ShowingResultsNumberItems.mjs.map +1 -1
  268. package/dist/esm/components/Popover/dynamic.mjs.map +1 -1
  269. package/dist/esm/components/Popover/static.mjs.map +1 -1
  270. package/dist/esm/components/PressableSpan/PressableSpan.mjs.map +1 -1
  271. package/dist/esm/components/RightDrawer/RightDrawer.mjs +3 -3
  272. package/dist/esm/components/RightDrawer/RightDrawer.mjs.map +1 -1
  273. package/dist/esm/components/RightDrawer/isElementAtTopAndNotCovered.mjs.map +1 -1
  274. package/dist/esm/components/RightDrawer/useRightDrawer.mjs.map +1 -1
  275. package/dist/esm/components/Select/Multiselect.mjs.map +1 -1
  276. package/dist/esm/components/Select/Select.mjs.map +1 -1
  277. package/dist/esm/components/SwitchSelector/SwitchSelector.mjs.map +1 -1
  278. package/dist/esm/components/SwitchSelector/VerticalSwitchSelector.mjs.map +1 -1
  279. package/dist/esm/components/SwitchSelector/useSwitchSelector.mjs.map +1 -1
  280. package/dist/esm/components/Tab/Tab.mjs.map +1 -1
  281. package/dist/esm/components/Tab/TabContext.mjs.map +1 -1
  282. package/dist/esm/components/TabSelector/TabSelector.mjs.map +1 -1
  283. package/dist/esm/components/Table/ExpandButton.mjs.map +1 -1
  284. package/dist/esm/components/Table/SmartTable.mjs.map +1 -1
  285. package/dist/esm/components/Table/TableElements.mjs +24 -0
  286. package/dist/esm/components/Table/TableElements.mjs.map +1 -0
  287. package/dist/esm/components/Table/index.mjs +2 -1
  288. package/dist/esm/components/Table/useTableWidths.mjs.map +1 -1
  289. package/dist/esm/components/Tag/index.mjs.map +1 -1
  290. package/dist/esm/components/TechLogo/TechLogo.mjs.map +1 -1
  291. package/dist/esm/components/TechLogo/types.mjs.map +1 -1
  292. package/dist/esm/components/Terminal/Terminal.mjs.map +1 -1
  293. package/dist/esm/components/TextArea/AutoSizeTextArea.mjs.map +1 -1
  294. package/dist/esm/components/TextArea/AutocompleteTextArea.mjs.map +1 -1
  295. package/dist/esm/components/TextArea/ContentEditableTextArea.mjs.map +1 -1
  296. package/dist/esm/components/ThemeSwitcherDropDown/DesktopThemeSwitcher.mjs.map +1 -1
  297. package/dist/esm/components/ThemeSwitcherDropDown/MobileThemeSwitcher.mjs.map +1 -1
  298. package/dist/esm/components/ThemeSwitcherDropDown/types.mjs.map +1 -1
  299. package/dist/esm/components/Toaster/Toast.mjs.map +1 -1
  300. package/dist/esm/components/Toaster/Toaster.mjs.map +1 -1
  301. package/dist/esm/components/Toaster/useToast.mjs.map +1 -1
  302. package/dist/esm/components/WithResizer/index.mjs.map +1 -1
  303. package/dist/esm/components/index.mjs +2 -1
  304. package/dist/esm/hooks/index.mjs +9 -9
  305. package/dist/esm/hooks/reactQuery.mjs.map +1 -1
  306. package/dist/esm/hooks/useAuth/useAuth.mjs.map +1 -1
  307. package/dist/esm/hooks/useAuth/useOAuth2.mjs +1 -1
  308. package/dist/esm/hooks/useAuth/useOAuth2.mjs.map +1 -1
  309. package/dist/esm/hooks/useAuth/useSession.mjs +1 -1
  310. package/dist/esm/hooks/useAuth/useSession.mjs.map +1 -1
  311. package/dist/esm/hooks/useDevice.mjs.map +1 -1
  312. package/dist/esm/hooks/useGetElementById.mjs.map +1 -1
  313. package/dist/esm/hooks/useGetElementOrWindow.mjs.map +1 -1
  314. package/dist/esm/hooks/useHorizontalSwipe.mjs.map +1 -1
  315. package/dist/esm/hooks/useIntlayerAPI.mjs.map +1 -1
  316. package/dist/esm/hooks/useIsDarkMode.mjs.map +1 -1
  317. package/dist/esm/hooks/useIsMounted.mjs.map +1 -1
  318. package/dist/esm/hooks/useItemSelector.mjs.map +1 -1
  319. package/dist/esm/hooks/useKeyboardDetector.mjs.map +1 -1
  320. package/dist/esm/hooks/usePersistedStore.mjs.map +1 -1
  321. package/dist/esm/hooks/useScreenWidth.mjs.map +1 -1
  322. package/dist/esm/hooks/useScrollBlockage/index.mjs.map +1 -1
  323. package/dist/esm/hooks/useScrollBlockage/useScrollBlockageStore.mjs.map +1 -1
  324. package/dist/esm/hooks/useScrollDetection.mjs.map +1 -1
  325. package/dist/esm/hooks/useScrollY.mjs.map +1 -1
  326. package/dist/esm/hooks/useSearch.mjs.map +1 -1
  327. package/dist/esm/hooks/useUser/index.mjs.map +1 -1
  328. package/dist/esm/libs/auth.mjs +1 -1
  329. package/dist/esm/libs/auth.mjs.map +1 -1
  330. package/dist/esm/providers/ReactQueryProvider.mjs.map +1 -1
  331. package/dist/esm/tailwind.config.mjs.map +1 -1
  332. package/dist/types/components/Badge/index.d.ts +1 -1
  333. package/dist/types/components/Button/Button.d.ts +3 -3
  334. package/dist/types/components/Command/index.d.ts +1 -1
  335. package/dist/types/components/Container/index.d.ts +2 -2
  336. package/dist/types/components/DictionaryFieldEditor/DictionaryFieldEditor.d.ts.map +1 -1
  337. package/dist/types/components/Input/Checkbox.d.ts +2 -1
  338. package/dist/types/components/Input/Checkbox.d.ts.map +1 -1
  339. package/dist/types/components/Link/Link.d.ts +2 -2
  340. package/dist/types/components/MarkDownRender/MarkDownRender.d.ts.map +1 -1
  341. package/dist/types/components/Pagination/Pagination.d.ts +1 -1
  342. package/dist/types/components/Tab/Tab.d.ts +1 -1
  343. package/dist/types/components/Table/TableElements.d.ts +23 -0
  344. package/dist/types/components/Table/TableElements.d.ts.map +1 -0
  345. package/dist/types/components/Table/index.d.ts +2 -1
  346. package/dist/types/components/Tag/index.d.ts +1 -1
  347. package/dist/types/components/index.d.ts +2 -1
  348. package/package.json +17 -17
@@ -1 +1 @@
1
- {"version":3,"file":"PressableSpan.mjs","names":[],"sources":["../../../../src/components/PressableSpan/PressableSpan.tsx"],"sourcesContent":["'use client';\n\nimport { cn } from '@utils/cn';\nimport {\n type FC,\n type HTMLAttributes,\n type MouseEventHandler,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from 'react';\n\nconst DEFAULT_PRESS_DETECT_DURATION = 400;\n\n/**\n * Props for the PressableSpan component\n */\ntype PressableSpanProps = {\n /**\n * Callback function triggered when a long press is detected\n * @example\n * ```tsx\n * <PressableSpan onPress={() => console.log('Long pressed!')}>\n * Press and hold me\n * </PressableSpan>\n * ```\n */\n onPress: () => void;\n\n /**\n * Optional callback function triggered when clicking outside the component while it's in selecting state\n * @example\n * ```tsx\n * <PressableSpan\n * onPress={() => setIsEditing(true)}\n * onClickOutside={() => setIsEditing(false)}\n * >\n * Click outside to deselect\n * </PressableSpan>\n * ```\n */\n onClickOutside?: () => void;\n\n /**\n * Duration in milliseconds for long press detection\n * @default 400\n * @example\n * ```tsx\n * <PressableSpan pressDuration={800} onPress={() => {}}>\n * Longer press required\n * </PressableSpan>\n * ```\n */\n pressDuration?: number;\n\n /**\n * External control for the selecting state\n * @example\n * ```tsx\n * <PressableSpan isSelecting={isEditing} onPress={() => {}}>\n * Externally controlled\n * </PressableSpan>\n * ```\n */\n isSelecting?: boolean;\n} & HTMLAttributes<HTMLSpanElement>;\n\n/**\n * PressableSpan - An interactive span element that responds to long press gestures\n *\n * A versatile component that detects long press interactions and provides visual feedback.\n * Commonly used for text editing interfaces, selection systems, and interactive content\n * that requires differentiation between quick clicks and intentional long presses.\n *\n * ## Key Features\n * - **Long Press Detection**: Configurable press duration for different interaction patterns\n * - **Visual Feedback**: Smooth outline transitions to indicate interactive and selected states\n * - **Click Outside Detection**: Automatically deselects when clicking outside the component\n * - **Touch Support**: Works seamlessly on both desktop and mobile devices\n * - **Accessible**: Keyboard navigation support and proper ARIA attributes\n *\n * ## Use Cases\n * - Text editing interfaces where long press activates edit mode\n * - Content selection systems with visual feedback\n * - Interactive cards or elements that need press-and-hold activation\n * - Mobile-friendly interfaces requiring long press gestures\n *\n * ## Accessibility\n * - Uses semantic `role=\"button\"` for proper screen reader announcement\n * - Keyboard navigable with `tabIndex={0}`\n * - Focus management with proper blur handling\n * - Visual outline indicators for focus and selection states\n *\n * @example\n * Basic usage with long press detection:\n * ```tsx\n * <PressableSpan onPress={() => setIsEditing(true)}>\n * Press and hold to edit this text\n * </PressableSpan>\n * ```\n *\n * @example\n * With custom press duration and click outside handling:\n * ```tsx\n * <PressableSpan\n * pressDuration={600}\n * onPress={() => setIsEditing(true)}\n * onClickOutside={() => setIsEditing(false)}\n * isSelecting={isEditing}\n * >\n * Custom behavior configuration\n * </PressableSpan>\n * ```\n *\n * @example\n * In a content editing context:\n * ```tsx\n * <PressableSpan\n * onPress={() => startEditingContent(contentId)}\n * onClickOutside={() => saveAndExitEditing()}\n * className=\"prose-text\"\n * >\n * {editableContent}\n * </PressableSpan>\n * ```\n */\n\nexport const PressableSpan: FC<PressableSpanProps> = ({\n children,\n onPress: onSelect,\n onClickOutside: onUnselect,\n pressDuration = DEFAULT_PRESS_DETECT_DURATION,\n isSelecting: isSelectingProp,\n ...props\n}) => {\n const elementRef = useRef<HTMLSpanElement>(null);\n const [isSelectingState, setIsSelectingState] = useState(isSelectingProp);\n const pressTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const handleOnLongPress = () => {\n setIsSelectingState(true);\n onSelect();\n };\n\n const startPressTimer = () => {\n pressTimerRef.current = setTimeout(() => {\n handleOnLongPress();\n }, pressDuration);\n };\n\n const clearPressTimer = () => {\n if (pressTimerRef.current) {\n clearTimeout(pressTimerRef.current);\n pressTimerRef.current = null;\n }\n };\n\n const handleMouseDown = () => {\n clearPressTimer(); // Ensure any previous timer is cleared\n startPressTimer();\n };\n\n const handleMouseUp = () => {\n clearPressTimer();\n };\n\n // Use useCallback to ensure the function identity remains stable\n const handleClickOutside = useCallback(\n (event: MouseEvent) => {\n if (\n elementRef.current &&\n !elementRef.current.contains(event.target as Node)\n ) {\n setIsSelectingState(false);\n onUnselect?.();\n }\n },\n [onUnselect]\n );\n\n useEffect(() => {\n // Attach click outside listener\n document.addEventListener('mousedown', handleClickOutside);\n\n return () => {\n // Cleanup\n document.removeEventListener('mousedown', handleClickOutside);\n // clearPressTimer(); // Ensure to clear the timer when component unmounts\n };\n }, [handleClickOutside]);\n\n const handleOnClick: MouseEventHandler<HTMLDivElement> = (e) => {\n if (isSelectingState) {\n e.preventDefault();\n e.stopPropagation();\n }\n };\n\n const handleOnBlur = () => {\n // Stop editing when the element loses focus\n setIsSelectingState(false);\n };\n\n /**\n * Handle keyboard interactions\n * - Enter/Space: Trigger long press action immediately\n * - Escape: Cancel selection/editing state\n */\n const handleKeyDown = (e: React.KeyboardEvent<HTMLSpanElement>) => {\n switch (e.key) {\n case 'Enter':\n case ' ':\n e.preventDefault();\n handleOnLongPress();\n break;\n case 'Escape':\n e.preventDefault();\n setIsSelectingState(false);\n onUnselect?.();\n break;\n default:\n break;\n }\n };\n\n const isCurrentlySelecting = isSelectingProp ?? isSelectingState;\n\n return (\n <span\n className={cn(\n 'inline cursor-pointer select-none rounded-md outline outline-2 outline-transparent outline-offset-4 transition-all delay-100 duration-200',\n isCurrentlySelecting ? 'outline-inherit' : 'hover:outline-inherit'\n )}\n role=\"button\"\n tabIndex={0}\n aria-pressed={isCurrentlySelecting ? 'true' : 'false'}\n aria-label={`${isCurrentlySelecting ? 'Selected' : 'Selectable'} content`}\n onKeyDown={handleKeyDown}\n onClick={handleOnClick}\n onMouseDown={handleMouseDown}\n onMouseUp={handleMouseUp}\n onMouseLeave={handleMouseUp}\n onTouchStart={handleMouseDown}\n onTouchEnd={handleMouseUp}\n onTouchCancel={handleMouseUp}\n onBlur={handleOnBlur}\n ref={elementRef}\n {...props}\n >\n {children}\n </span>\n );\n};\n"],"mappings":";;;;;;;AAaA,MAAM,gCAAgC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmHtC,MAAa,iBAAyC,EACpD,UACA,SAAS,UACT,gBAAgB,YAChB,gBAAgB,+BAChB,aAAa,iBACb,GAAG,YACC;CACJ,MAAM,aAAa,OAAwB,KAAK;CAChD,MAAM,CAAC,kBAAkB,uBAAuB,SAAS,gBAAgB;CACzE,MAAM,gBAAgB,OAA6C,KAAK;CAExE,MAAM,0BAA0B;AAC9B,sBAAoB,KAAK;AACzB,YAAU;;CAGZ,MAAM,wBAAwB;AAC5B,gBAAc,UAAU,iBAAiB;AACvC,sBAAmB;KAClB,cAAc;;CAGnB,MAAM,wBAAwB;AAC5B,MAAI,cAAc,SAAS;AACzB,gBAAa,cAAc,QAAQ;AACnC,iBAAc,UAAU;;;CAI5B,MAAM,wBAAwB;AAC5B,mBAAiB;AACjB,mBAAiB;;CAGnB,MAAM,sBAAsB;AAC1B,mBAAiB;;CAInB,MAAM,qBAAqB,aACxB,UAAsB;AACrB,MACE,WAAW,WACX,CAAC,WAAW,QAAQ,SAAS,MAAM,OAAe,EAClD;AACA,uBAAoB,MAAM;AAC1B,iBAAc;;IAGlB,CAAC,WAAW,CACb;AAED,iBAAgB;AAEd,WAAS,iBAAiB,aAAa,mBAAmB;AAE1D,eAAa;AAEX,YAAS,oBAAoB,aAAa,mBAAmB;;IAG9D,CAAC,mBAAmB,CAAC;CAExB,MAAM,iBAAoD,MAAM;AAC9D,MAAI,kBAAkB;AACpB,KAAE,gBAAgB;AAClB,KAAE,iBAAiB;;;CAIvB,MAAM,qBAAqB;AAEzB,sBAAoB,MAAM;;;;;;;CAQ5B,MAAM,iBAAiB,MAA4C;AACjE,UAAQ,EAAE,KAAV;GACE,KAAK;GACL,KAAK;AACH,MAAE,gBAAgB;AAClB,uBAAmB;AACnB;GACF,KAAK;AACH,MAAE,gBAAgB;AAClB,wBAAoB,MAAM;AAC1B,kBAAc;AACd;GACF,QACE;;;CAIN,MAAM,uBAAuB,mBAAmB;AAEhD,QACE,oBAAC,QAAD;EACE,WAAW,GACT,6IACA,uBAAuB,oBAAoB,wBAC5C;EACD,MAAK;EACL,UAAU;EACV,gBAAc,uBAAuB,SAAS;EAC9C,cAAY,GAAG,uBAAuB,aAAa,aAAa;EAChE,WAAW;EACX,SAAS;EACT,aAAa;EACb,WAAW;EACX,cAAc;EACd,cAAc;EACd,YAAY;EACZ,eAAe;EACf,QAAQ;EACR,KAAK;EACL,GAAI;EAEH;EACI"}
1
+ {"version":3,"file":"PressableSpan.mjs","names":[],"sources":["../../../../src/components/PressableSpan/PressableSpan.tsx"],"sourcesContent":["'use client';\n\nimport { cn } from '@utils/cn';\nimport {\n type FC,\n type HTMLAttributes,\n type MouseEventHandler,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from 'react';\n\nconst DEFAULT_PRESS_DETECT_DURATION = 400;\n\n/**\n * Props for the PressableSpan component\n */\ntype PressableSpanProps = {\n /**\n * Callback function triggered when a long press is detected\n * @example\n * ```tsx\n * <PressableSpan onPress={() => console.log('Long pressed!')}>\n * Press and hold me\n * </PressableSpan>\n * ```\n */\n onPress: () => void;\n\n /**\n * Optional callback function triggered when clicking outside the component while it's in selecting state\n * @example\n * ```tsx\n * <PressableSpan\n * onPress={() => setIsEditing(true)}\n * onClickOutside={() => setIsEditing(false)}\n * >\n * Click outside to deselect\n * </PressableSpan>\n * ```\n */\n onClickOutside?: () => void;\n\n /**\n * Duration in milliseconds for long press detection\n * @default 400\n * @example\n * ```tsx\n * <PressableSpan pressDuration={800} onPress={() => {}}>\n * Longer press required\n * </PressableSpan>\n * ```\n */\n pressDuration?: number;\n\n /**\n * External control for the selecting state\n * @example\n * ```tsx\n * <PressableSpan isSelecting={isEditing} onPress={() => {}}>\n * Externally controlled\n * </PressableSpan>\n * ```\n */\n isSelecting?: boolean;\n} & HTMLAttributes<HTMLSpanElement>;\n\n/**\n * PressableSpan - An interactive span element that responds to long press gestures\n *\n * A versatile component that detects long press interactions and provides visual feedback.\n * Commonly used for text editing interfaces, selection systems, and interactive content\n * that requires differentiation between quick clicks and intentional long presses.\n *\n * ## Key Features\n * - **Long Press Detection**: Configurable press duration for different interaction patterns\n * - **Visual Feedback**: Smooth outline transitions to indicate interactive and selected states\n * - **Click Outside Detection**: Automatically deselects when clicking outside the component\n * - **Touch Support**: Works seamlessly on both desktop and mobile devices\n * - **Accessible**: Keyboard navigation support and proper ARIA attributes\n *\n * ## Use Cases\n * - Text editing interfaces where long press activates edit mode\n * - Content selection systems with visual feedback\n * - Interactive cards or elements that need press-and-hold activation\n * - Mobile-friendly interfaces requiring long press gestures\n *\n * ## Accessibility\n * - Uses semantic `role=\"button\"` for proper screen reader announcement\n * - Keyboard navigable with `tabIndex={0}`\n * - Focus management with proper blur handling\n * - Visual outline indicators for focus and selection states\n *\n * @example\n * Basic usage with long press detection:\n * ```tsx\n * <PressableSpan onPress={() => setIsEditing(true)}>\n * Press and hold to edit this text\n * </PressableSpan>\n * ```\n *\n * @example\n * With custom press duration and click outside handling:\n * ```tsx\n * <PressableSpan\n * pressDuration={600}\n * onPress={() => setIsEditing(true)}\n * onClickOutside={() => setIsEditing(false)}\n * isSelecting={isEditing}\n * >\n * Custom behavior configuration\n * </PressableSpan>\n * ```\n *\n * @example\n * In a content editing context:\n * ```tsx\n * <PressableSpan\n * onPress={() => startEditingContent(contentId)}\n * onClickOutside={() => saveAndExitEditing()}\n * className=\"prose-text\"\n * >\n * {editableContent}\n * </PressableSpan>\n * ```\n */\n\nexport const PressableSpan: FC<PressableSpanProps> = ({\n children,\n onPress: onSelect,\n onClickOutside: onUnselect,\n pressDuration = DEFAULT_PRESS_DETECT_DURATION,\n isSelecting: isSelectingProp,\n ...props\n}) => {\n const elementRef = useRef<HTMLSpanElement>(null);\n const [isSelectingState, setIsSelectingState] = useState(isSelectingProp);\n const pressTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const handleOnLongPress = () => {\n setIsSelectingState(true);\n onSelect();\n };\n\n const startPressTimer = () => {\n pressTimerRef.current = setTimeout(() => {\n handleOnLongPress();\n }, pressDuration);\n };\n\n const clearPressTimer = () => {\n if (pressTimerRef.current) {\n clearTimeout(pressTimerRef.current);\n pressTimerRef.current = null;\n }\n };\n\n const handleMouseDown = () => {\n clearPressTimer(); // Ensure any previous timer is cleared\n startPressTimer();\n };\n\n const handleMouseUp = () => {\n clearPressTimer();\n };\n\n // Use useCallback to ensure the function identity remains stable\n const handleClickOutside = useCallback(\n (event: MouseEvent) => {\n if (\n elementRef.current &&\n !elementRef.current.contains(event.target as Node)\n ) {\n setIsSelectingState(false);\n onUnselect?.();\n }\n },\n [onUnselect]\n );\n\n useEffect(() => {\n // Attach click outside listener\n document.addEventListener('mousedown', handleClickOutside);\n\n return () => {\n // Cleanup\n document.removeEventListener('mousedown', handleClickOutside);\n // clearPressTimer(); // Ensure to clear the timer when component unmounts\n };\n }, [handleClickOutside]);\n\n const handleOnClick: MouseEventHandler<HTMLDivElement> = (e) => {\n if (isSelectingState) {\n e.preventDefault();\n e.stopPropagation();\n }\n };\n\n const handleOnBlur = () => {\n // Stop editing when the element loses focus\n setIsSelectingState(false);\n };\n\n /**\n * Handle keyboard interactions\n * - Enter/Space: Trigger long press action immediately\n * - Escape: Cancel selection/editing state\n */\n const handleKeyDown = (e: React.KeyboardEvent<HTMLSpanElement>) => {\n switch (e.key) {\n case 'Enter':\n case ' ':\n e.preventDefault();\n handleOnLongPress();\n break;\n case 'Escape':\n e.preventDefault();\n setIsSelectingState(false);\n onUnselect?.();\n break;\n default:\n break;\n }\n };\n\n const isCurrentlySelecting = isSelectingProp ?? isSelectingState;\n\n return (\n <span\n className={cn(\n 'inline cursor-pointer select-none rounded-md outline outline-2 outline-transparent outline-offset-4 transition-all delay-100 duration-200',\n isCurrentlySelecting ? 'outline-inherit' : 'hover:outline-inherit'\n )}\n role=\"button\"\n tabIndex={0}\n aria-pressed={isCurrentlySelecting ? 'true' : 'false'}\n aria-label={`${isCurrentlySelecting ? 'Selected' : 'Selectable'} content`}\n onKeyDown={handleKeyDown}\n onClick={handleOnClick}\n onMouseDown={handleMouseDown}\n onMouseUp={handleMouseUp}\n onMouseLeave={handleMouseUp}\n onTouchStart={handleMouseDown}\n onTouchEnd={handleMouseUp}\n onTouchCancel={handleMouseUp}\n onBlur={handleOnBlur}\n ref={elementRef}\n {...props}\n >\n {children}\n </span>\n );\n};\n"],"mappings":";;;;;;;AAaA,MAAM,gCAAgC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmHtC,MAAa,iBAAyC,EACpD,UACA,SAAS,UACT,gBAAgB,YAChB,gBAAgB,+BAChB,aAAa,iBACb,GAAG,YACC;CACJ,MAAM,aAAa,OAAwB,KAAK;CAChD,MAAM,CAAC,kBAAkB,uBAAuB,SAAS,gBAAgB;CACzE,MAAM,gBAAgB,OAA6C,KAAK;CAExE,MAAM,0BAA0B;EAC9B,oBAAoB,KAAK;EACzB,UAAU;;CAGZ,MAAM,wBAAwB;EAC5B,cAAc,UAAU,iBAAiB;GACvC,mBAAmB;KAClB,cAAc;;CAGnB,MAAM,wBAAwB;EAC5B,IAAI,cAAc,SAAS;GACzB,aAAa,cAAc,QAAQ;GACnC,cAAc,UAAU;;;CAI5B,MAAM,wBAAwB;EAC5B,iBAAiB;EACjB,iBAAiB;;CAGnB,MAAM,sBAAsB;EAC1B,iBAAiB;;CAInB,MAAM,qBAAqB,aACxB,UAAsB;EACrB,IACE,WAAW,WACX,CAAC,WAAW,QAAQ,SAAS,MAAM,OAAe,EAClD;GACA,oBAAoB,MAAM;GAC1B,cAAc;;IAGlB,CAAC,WAAW,CACb;CAED,gBAAgB;EAEd,SAAS,iBAAiB,aAAa,mBAAmB;EAE1D,aAAa;GAEX,SAAS,oBAAoB,aAAa,mBAAmB;;IAG9D,CAAC,mBAAmB,CAAC;CAExB,MAAM,iBAAoD,MAAM;EAC9D,IAAI,kBAAkB;GACpB,EAAE,gBAAgB;GAClB,EAAE,iBAAiB;;;CAIvB,MAAM,qBAAqB;EAEzB,oBAAoB,MAAM;;;;;;;CAQ5B,MAAM,iBAAiB,MAA4C;EACjE,QAAQ,EAAE,KAAV;GACE,KAAK;GACL,KAAK;IACH,EAAE,gBAAgB;IAClB,mBAAmB;IACnB;GACF,KAAK;IACH,EAAE,gBAAgB;IAClB,oBAAoB,MAAM;IAC1B,cAAc;IACd;GACF,SACE;;;CAIN,MAAM,uBAAuB,mBAAmB;CAEhD,OACE,oBAAC,QAAD;EACE,WAAW,GACT,6IACA,uBAAuB,oBAAoB,wBAC5C;EACD,MAAK;EACL,UAAU;EACV,gBAAc,uBAAuB,SAAS;EAC9C,cAAY,GAAG,uBAAuB,aAAa,aAAa;EAChE,WAAW;EACX,SAAS;EACT,aAAa;EACb,WAAW;EACX,cAAc;EACd,cAAc;EACd,YAAY;EACZ,eAAe;EACf,QAAQ;EACR,KAAK;EACL,GAAI;EAEH;EACI"}
@@ -1,12 +1,12 @@
1
1
  'use client';
2
2
 
3
- import { useGetElementOrWindow } from "../../hooks/useGetElementOrWindow.mjs";
4
- import { useDevice } from "../../hooks/useDevice.mjs";
5
- import { useScrollBlockage } from "../../hooks/useScrollBlockage/index.mjs";
6
3
  import { Container } from "../Container/index.mjs";
7
4
  import { Button, ButtonColor, ButtonSize, ButtonVariant } from "../Button/Button.mjs";
5
+ import { useDevice } from "../../hooks/useDevice.mjs";
8
6
  import { KeyboardShortcut } from "../KeyboardShortcut/KeyboardShortcut.mjs";
9
7
  import { Popover } from "../Popover/dynamic.mjs";
8
+ import { useGetElementOrWindow } from "../../hooks/useGetElementOrWindow.mjs";
9
+ import { useScrollBlockage } from "../../hooks/useScrollBlockage/index.mjs";
10
10
  import { MaxWidthSmoother } from "../MaxWidthSmoother/index.mjs";
11
11
  import { isElementAtTopAndNotCovered } from "./isElementAtTopAndNotCovered.mjs";
12
12
  import { useRightDrawer } from "./useRightDrawer.mjs";
@@ -1 +1 @@
1
- {"version":3,"file":"RightDrawer.mjs","names":[],"sources":["../../../../src/components/RightDrawer/RightDrawer.tsx"],"sourcesContent":["'use client';\n\nimport { useGetElementOrWindow } from '@hooks/index';\nimport { useDevice } from '@hooks/useDevice';\nimport { useScrollBlockage } from '@hooks/useScrollBlockage';\nimport { ChevronLeft, X } from 'lucide-react';\nimport {\n type FC,\n type KeyboardEventHandler,\n type MouseEventHandler,\n type ReactNode,\n useEffect,\n useRef,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport { useIntlayer } from 'react-intlayer';\nimport { Button, ButtonColor, ButtonSize, ButtonVariant } from '../Button';\nimport { Container } from '../Container';\nimport { KeyboardShortcut } from '../KeyboardShortcut';\nimport { MaxWidthSmoother } from '../MaxWidthSmoother/index';\nimport { Popover } from '../Popover';\nimport { isElementAtTopAndNotCovered } from './isElementAtTopAndNotCovered';\nimport { useRightDrawer } from './useRightDrawer';\n\n/**\n * Configuration for the back button functionality in the RightDrawer\n *\n * @interface BackButtonProps\n */\ntype BackButtonProps = {\n /** Callback function triggered when the back button is clicked */\n onBack: () => void;\n /** Optional custom text for the back buttoDefaults to \"Go back\" if not provided */\n text?: string;\n};\n\n/**\n * Props configuration for the RightDrawer component\n *\n * @interface RightDrawerProps\n */\ntype RightDrawerProps = {\n /**\n * Title displayed in the drawer header\n */\n title?: ReactNode;\n\n /**\n * Unique identifier for the drawer instancRequired for store management\n */\n identifier: string;\n\n /** The content to be displayed inside the drawer */\n children?: ReactNode;\n\n /**\n * Optional header content displayed below the title\n */\n header?: ReactNode;\n\n /**\n * Optional footer content pinned to the bottom of the drawer\n */\n footer?: ReactNode;\n\n /**\n * Whether the drawer should close when clicking outside of it\n * @default true\n */\n closeOnOutsideClick?: boolean;\n\n /**\n * Configuration for an optional back button in the drawer header\n */\n backButton?: BackButtonProps;\n\n /**\n * External control for the open statWhen provided, overrides internal store state\n */\n isOpen?: boolean;\n\n /**\n * Callback function triggered when the drawer is closed\n */\n onClose?: () => void;\n\n /**\n * Optional container to render the drawer into.\n * If not provided, it will be rendered into the body.\n */\n container?: HTMLElement;\n};\n\nexport const RightDrawer: FC<RightDrawerProps> = ({\n title,\n identifier,\n children,\n header,\n footer,\n closeOnOutsideClick = true,\n backButton,\n isOpen: isOpenProp,\n onClose,\n container,\n}) => {\n const content = useIntlayer('right-drawer');\n const { isMobile } = useDevice('md');\n const panelRef = useRef<HTMLDivElement>(null);\n const childrenContainerRef = useRef<HTMLDivElement>(null);\n const containerElement = useGetElementOrWindow(container);\n\n const {\n open: openDrawer,\n close: closeDrawer,\n isOpen: checkIsOpen,\n } = useRightDrawer();\n const storeIsOpen = checkIsOpen(identifier);\n const isOpen = storeIsOpen;\n\n useScrollBlockage({\n disableScroll: isOpen,\n key: identifier ? `right_drawer_${identifier}` : 'right_drawer',\n });\n\n // Handle Click Outside\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n try {\n if (!panelRef.current) return;\n\n const isClickAble = isOpen && closeOnOutsideClick;\n const isClickOutside =\n event.target && !panelRef.current.contains(event.target as Node);\n const isAtTopAndVisible = isElementAtTopAndNotCovered(panelRef.current);\n\n if (\n (isClickAble && isClickOutside && isAtTopAndVisible) ||\n !event.target\n ) {\n closeDrawer(identifier);\n onClose?.();\n }\n } catch (_e) {\n closeDrawer(identifier);\n onClose?.();\n }\n };\n\n window.addEventListener('mousedown', handleClickOutside);\n return () => window.removeEventListener('mousedown', handleClickOutside);\n }, [isOpen, closeDrawer, onClose, closeOnOutsideClick, identifier]);\n\n const onCloseRef = useRef(onClose);\n useEffect(() => {\n onCloseRef.current = onClose;\n }, [onClose]);\n\n useEffect(() => {\n if (isOpenProp === undefined) return;\n if (isOpenProp === storeIsOpen) return;\n\n if (isOpenProp) {\n openDrawer(identifier);\n } else {\n closeDrawer(identifier);\n onCloseRef.current?.();\n }\n }, [isOpenProp, storeIsOpen, identifier, openDrawer, closeDrawer]);\n\n const handleSpareSpaceClick: MouseEventHandler<HTMLDivElement> = (e) => {\n if (e.target !== e.currentTarget) {\n return;\n }\n if (isMobile) {\n closeDrawer(identifier);\n onClose?.();\n }\n };\n\n // Handle Keyboard on Spare Space (Linter Fix)\n const handleSpareSpaceKeyDown: KeyboardEventHandler<HTMLDivElement> = (e) => {\n if (e.target !== e.currentTarget) return;\n\n // Allow closing via Enter or Space if focused on the spare area\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n if (isMobile) {\n closeDrawer(identifier);\n onClose?.();\n }\n }\n };\n\n if (!containerElement) return <></>;\n\n return createPortal(\n <div className=\"fixed top-0 right-0 z-50 flex h-full justify-end\">\n <MaxWidthSmoother isHidden={!isOpen} align=\"right\">\n <Container\n className=\"relative flex h-screen w-screen flex-col text-text md:w-[400px]\"\n ref={panelRef}\n roundedSize=\"none\"\n >\n {/* Header */}\n <div className=\"flex shrink-0 flex-col gap-3 px-6 pt-6\">\n <div className=\"flex justify-between gap-3\">\n <div>\n {backButton && (\n <Button\n variant={ButtonVariant.HOVERABLE}\n color={ButtonColor.TEXT}\n label={backButton.text ?? content.goBack.value}\n onClick={backButton.onBack}\n Icon={ChevronLeft}\n >\n {backButton?.text}\n </Button>\n )}\n </div>\n <div>\n <Popover identifier=\"close-drawer\">\n <Button\n variant={ButtonVariant.HOVERABLE}\n color={ButtonColor.TEXT}\n label=\"Close\"\n className=\"ml-auto\"\n onClick={() => {\n closeDrawer(identifier);\n onClose?.();\n }}\n Icon={X}\n size={ButtonSize.ICON_MD}\n />\n\n <Popover.Detail identifier=\"close-drawer\">\n <div className=\"flex items-center gap-2 p-2\">\n <span className=\"whitespace-nowrap text-neutral text-xs\">\n {content.closeDrawer}\n </span>\n <KeyboardShortcut\n shortcut=\"Escape\"\n size=\"sm\"\n onTriggered={() => {\n closeDrawer(identifier);\n onClose?.();\n }}\n />\n </div>\n </Popover.Detail>\n </Popover>\n </div>\n </div>\n {title && (\n <h2 className=\"flex items-center justify-center font-bold text-lg\">\n {title}\n </h2>\n )}\n {header}\n </div>\n\n {/* Body */}\n <div className=\"flex min-h-0 flex-1 flex-col overflow-y-auto p-2\">\n {/** biome-ignore lint/a11y/useSemanticElements: This div is used to handle the spare space click and keydown events */}\n <div\n className=\"flex flex-1 flex-col outline-none\"\n onClick={handleSpareSpaceClick}\n onKeyDown={handleSpareSpaceKeyDown}\n ref={childrenContainerRef}\n role=\"button\" // Semantically acts as a button area\n tabIndex={0} // Makes it focusable to receive key events\n >\n {children}\n </div>\n </div>\n\n {/* Footer */}\n {footer && <div className=\"shrink-0\">{footer}</div>}\n </Container>\n </MaxWidthSmoother>\n </div>,\n containerElement\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"RightDrawer.mjs","names":[],"sources":["../../../../src/components/RightDrawer/RightDrawer.tsx"],"sourcesContent":["'use client';\n\nimport { useGetElementOrWindow } from '@hooks/index';\nimport { useDevice } from '@hooks/useDevice';\nimport { useScrollBlockage } from '@hooks/useScrollBlockage';\nimport { ChevronLeft, X } from 'lucide-react';\nimport {\n type FC,\n type KeyboardEventHandler,\n type MouseEventHandler,\n type ReactNode,\n useEffect,\n useRef,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport { useIntlayer } from 'react-intlayer';\nimport { Button, ButtonColor, ButtonSize, ButtonVariant } from '../Button';\nimport { Container } from '../Container';\nimport { KeyboardShortcut } from '../KeyboardShortcut';\nimport { MaxWidthSmoother } from '../MaxWidthSmoother/index';\nimport { Popover } from '../Popover';\nimport { isElementAtTopAndNotCovered } from './isElementAtTopAndNotCovered';\nimport { useRightDrawer } from './useRightDrawer';\n\n/**\n * Configuration for the back button functionality in the RightDrawer\n *\n * @interface BackButtonProps\n */\ntype BackButtonProps = {\n /** Callback function triggered when the back button is clicked */\n onBack: () => void;\n /** Optional custom text for the back buttoDefaults to \"Go back\" if not provided */\n text?: string;\n};\n\n/**\n * Props configuration for the RightDrawer component\n *\n * @interface RightDrawerProps\n */\ntype RightDrawerProps = {\n /**\n * Title displayed in the drawer header\n */\n title?: ReactNode;\n\n /**\n * Unique identifier for the drawer instancRequired for store management\n */\n identifier: string;\n\n /** The content to be displayed inside the drawer */\n children?: ReactNode;\n\n /**\n * Optional header content displayed below the title\n */\n header?: ReactNode;\n\n /**\n * Optional footer content pinned to the bottom of the drawer\n */\n footer?: ReactNode;\n\n /**\n * Whether the drawer should close when clicking outside of it\n * @default true\n */\n closeOnOutsideClick?: boolean;\n\n /**\n * Configuration for an optional back button in the drawer header\n */\n backButton?: BackButtonProps;\n\n /**\n * External control for the open statWhen provided, overrides internal store state\n */\n isOpen?: boolean;\n\n /**\n * Callback function triggered when the drawer is closed\n */\n onClose?: () => void;\n\n /**\n * Optional container to render the drawer into.\n * If not provided, it will be rendered into the body.\n */\n container?: HTMLElement;\n};\n\nexport const RightDrawer: FC<RightDrawerProps> = ({\n title,\n identifier,\n children,\n header,\n footer,\n closeOnOutsideClick = true,\n backButton,\n isOpen: isOpenProp,\n onClose,\n container,\n}) => {\n const content = useIntlayer('right-drawer');\n const { isMobile } = useDevice('md');\n const panelRef = useRef<HTMLDivElement>(null);\n const childrenContainerRef = useRef<HTMLDivElement>(null);\n const containerElement = useGetElementOrWindow(container);\n\n const {\n open: openDrawer,\n close: closeDrawer,\n isOpen: checkIsOpen,\n } = useRightDrawer();\n const storeIsOpen = checkIsOpen(identifier);\n const isOpen = storeIsOpen;\n\n useScrollBlockage({\n disableScroll: isOpen,\n key: identifier ? `right_drawer_${identifier}` : 'right_drawer',\n });\n\n // Handle Click Outside\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n try {\n if (!panelRef.current) return;\n\n const isClickAble = isOpen && closeOnOutsideClick;\n const isClickOutside =\n event.target && !panelRef.current.contains(event.target as Node);\n const isAtTopAndVisible = isElementAtTopAndNotCovered(panelRef.current);\n\n if (\n (isClickAble && isClickOutside && isAtTopAndVisible) ||\n !event.target\n ) {\n closeDrawer(identifier);\n onClose?.();\n }\n } catch (_e) {\n closeDrawer(identifier);\n onClose?.();\n }\n };\n\n window.addEventListener('mousedown', handleClickOutside);\n return () => window.removeEventListener('mousedown', handleClickOutside);\n }, [isOpen, closeDrawer, onClose, closeOnOutsideClick, identifier]);\n\n const onCloseRef = useRef(onClose);\n useEffect(() => {\n onCloseRef.current = onClose;\n }, [onClose]);\n\n useEffect(() => {\n if (isOpenProp === undefined) return;\n if (isOpenProp === storeIsOpen) return;\n\n if (isOpenProp) {\n openDrawer(identifier);\n } else {\n closeDrawer(identifier);\n onCloseRef.current?.();\n }\n }, [isOpenProp, storeIsOpen, identifier, openDrawer, closeDrawer]);\n\n const handleSpareSpaceClick: MouseEventHandler<HTMLDivElement> = (e) => {\n if (e.target !== e.currentTarget) {\n return;\n }\n if (isMobile) {\n closeDrawer(identifier);\n onClose?.();\n }\n };\n\n // Handle Keyboard on Spare Space (Linter Fix)\n const handleSpareSpaceKeyDown: KeyboardEventHandler<HTMLDivElement> = (e) => {\n if (e.target !== e.currentTarget) return;\n\n // Allow closing via Enter or Space if focused on the spare area\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n if (isMobile) {\n closeDrawer(identifier);\n onClose?.();\n }\n }\n };\n\n if (!containerElement) return <></>;\n\n return createPortal(\n <div className=\"fixed top-0 right-0 z-50 flex h-full justify-end\">\n <MaxWidthSmoother isHidden={!isOpen} align=\"right\">\n <Container\n className=\"relative flex h-screen w-screen flex-col text-text md:w-[400px]\"\n ref={panelRef}\n roundedSize=\"none\"\n >\n {/* Header */}\n <div className=\"flex shrink-0 flex-col gap-3 px-6 pt-6\">\n <div className=\"flex justify-between gap-3\">\n <div>\n {backButton && (\n <Button\n variant={ButtonVariant.HOVERABLE}\n color={ButtonColor.TEXT}\n label={backButton.text ?? content.goBack.value}\n onClick={backButton.onBack}\n Icon={ChevronLeft}\n >\n {backButton?.text}\n </Button>\n )}\n </div>\n <div>\n <Popover identifier=\"close-drawer\">\n <Button\n variant={ButtonVariant.HOVERABLE}\n color={ButtonColor.TEXT}\n label=\"Close\"\n className=\"ml-auto\"\n onClick={() => {\n closeDrawer(identifier);\n onClose?.();\n }}\n Icon={X}\n size={ButtonSize.ICON_MD}\n />\n\n <Popover.Detail identifier=\"close-drawer\">\n <div className=\"flex items-center gap-2 p-2\">\n <span className=\"whitespace-nowrap text-neutral text-xs\">\n {content.closeDrawer}\n </span>\n <KeyboardShortcut\n shortcut=\"Escape\"\n size=\"sm\"\n onTriggered={() => {\n closeDrawer(identifier);\n onClose?.();\n }}\n />\n </div>\n </Popover.Detail>\n </Popover>\n </div>\n </div>\n {title && (\n <h2 className=\"flex items-center justify-center font-bold text-lg\">\n {title}\n </h2>\n )}\n {header}\n </div>\n\n {/* Body */}\n <div className=\"flex min-h-0 flex-1 flex-col overflow-y-auto p-2\">\n {/** biome-ignore lint/a11y/useSemanticElements: This div is used to handle the spare space click and keydown events */}\n <div\n className=\"flex flex-1 flex-col outline-none\"\n onClick={handleSpareSpaceClick}\n onKeyDown={handleSpareSpaceKeyDown}\n ref={childrenContainerRef}\n role=\"button\" // Semantically acts as a button area\n tabIndex={0} // Makes it focusable to receive key events\n >\n {children}\n </div>\n </div>\n\n {/* Footer */}\n {footer && <div className=\"shrink-0\">{footer}</div>}\n </Container>\n </MaxWidthSmoother>\n </div>,\n containerElement\n );\n};\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"isElementAtTopAndNotCovered.mjs","names":[],"sources":["../../../../src/components/RightDrawer/isElementAtTopAndNotCovered.tsx"],"sourcesContent":["/**\n * Utility function to determine if an HTML element is at the top of the viewport and not covered by other elements\n *\n * This function is specifically used by the RightDrawer component to ensure that click-outside\n * detection only triggers when the drawer is actually visible and not obscured by other UI elements.\n *\n * ## Algorithm\n * 1. **Viewport Check**: Verifies the element is within the visible viewport bounds\n * 2. **Coverage Check**: Uses `document.elementFromPoint()` to ensure no other elements are covering the drawer\n * 3. **Center Point Testing**: Tests the center-top point of the element for accurate detection\n *\n * ## Use Cases\n * - Click-outside detection for modal and drawer components\n * - Visibility validation for overlay components\n * - Z-index conflict resolution\n * - Accessibility focus management\n *\n * @param element - The HTML element to check for visibility and coverage\n * @returns Boolean indicating if the element is visible at the top and not covered by other elements\n *\n * @example\n * Basic usage in click-outside detection:\n * ```tsx\n * const handleClickOutside = (event: MouseEvent) => {\n * if (!drawerRef.current) return;\n *\n * const isVisible = isElementAtTopAndNotCovered(drawerRef.current);\n * const isClickOutside = !drawerRef.current.contains(event.target as Node);\n *\n * if (isVisible && isClickOutside) {\n * closeDrawer();\n * }\n * };\n * ```\n *\n * @example\n * Checking multiple overlays:\n * ```tsx\n * const overlays = document.querySelectorAll('.overlay');\n * const visibleOverlays = Array.from(overlays).filter(overlay =>\n * isElementAtTopAndNotCovered(overlay as HTMLElement)\n * );\n * ```\n */\nexport const isElementAtTopAndNotCovered = (element: HTMLElement): boolean => {\n const rect = element.getBoundingClientRect();\n const elemTop = rect.top;\n const elemBottom = rect.bottom - 1; // -1 to avoid the border of the element\n\n // Check if element is at the top of the viewport\n const isVisibleAtTop = elemTop >= 0 && elemBottom <= window.innerHeight;\n\n // Further check if the element is not covered by any other element at the center point of its top boundary\n if (isVisibleAtTop) {\n const centerX = rect.left + rect.width / 2;\n const centerY = rect.top + 10; // slight offset from the very top to ensure we're within the element bounds\n const topElement = document.elementFromPoint(centerX, centerY);\n\n // Check if our element is the topmost element at these coordinates or a child of the topmost element\n return element === topElement || element.contains(topElement);\n }\n\n return false;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4CA,MAAa,+BAA+B,YAAkC;CAC5E,MAAM,OAAO,QAAQ,uBAAuB;CAC5C,MAAM,UAAU,KAAK;CACrB,MAAM,aAAa,KAAK,SAAS;AAMjC,KAHuB,WAAW,KAAK,cAAc,OAAO,aAGxC;EAClB,MAAM,UAAU,KAAK,OAAO,KAAK,QAAQ;EACzC,MAAM,UAAU,KAAK,MAAM;EAC3B,MAAM,aAAa,SAAS,iBAAiB,SAAS,QAAQ;AAG9D,SAAO,YAAY,cAAc,QAAQ,SAAS,WAAW;;AAG/D,QAAO"}
1
+ {"version":3,"file":"isElementAtTopAndNotCovered.mjs","names":[],"sources":["../../../../src/components/RightDrawer/isElementAtTopAndNotCovered.tsx"],"sourcesContent":["/**\n * Utility function to determine if an HTML element is at the top of the viewport and not covered by other elements\n *\n * This function is specifically used by the RightDrawer component to ensure that click-outside\n * detection only triggers when the drawer is actually visible and not obscured by other UI elements.\n *\n * ## Algorithm\n * 1. **Viewport Check**: Verifies the element is within the visible viewport bounds\n * 2. **Coverage Check**: Uses `document.elementFromPoint()` to ensure no other elements are covering the drawer\n * 3. **Center Point Testing**: Tests the center-top point of the element for accurate detection\n *\n * ## Use Cases\n * - Click-outside detection for modal and drawer components\n * - Visibility validation for overlay components\n * - Z-index conflict resolution\n * - Accessibility focus management\n *\n * @param element - The HTML element to check for visibility and coverage\n * @returns Boolean indicating if the element is visible at the top and not covered by other elements\n *\n * @example\n * Basic usage in click-outside detection:\n * ```tsx\n * const handleClickOutside = (event: MouseEvent) => {\n * if (!drawerRef.current) return;\n *\n * const isVisible = isElementAtTopAndNotCovered(drawerRef.current);\n * const isClickOutside = !drawerRef.current.contains(event.target as Node);\n *\n * if (isVisible && isClickOutside) {\n * closeDrawer();\n * }\n * };\n * ```\n *\n * @example\n * Checking multiple overlays:\n * ```tsx\n * const overlays = document.querySelectorAll('.overlay');\n * const visibleOverlays = Array.from(overlays).filter(overlay =>\n * isElementAtTopAndNotCovered(overlay as HTMLElement)\n * );\n * ```\n */\nexport const isElementAtTopAndNotCovered = (element: HTMLElement): boolean => {\n const rect = element.getBoundingClientRect();\n const elemTop = rect.top;\n const elemBottom = rect.bottom - 1; // -1 to avoid the border of the element\n\n // Check if element is at the top of the viewport\n const isVisibleAtTop = elemTop >= 0 && elemBottom <= window.innerHeight;\n\n // Further check if the element is not covered by any other element at the center point of its top boundary\n if (isVisibleAtTop) {\n const centerX = rect.left + rect.width / 2;\n const centerY = rect.top + 10; // slight offset from the very top to ensure we're within the element bounds\n const topElement = document.elementFromPoint(centerX, centerY);\n\n // Check if our element is the topmost element at these coordinates or a child of the topmost element\n return element === topElement || element.contains(topElement);\n }\n\n return false;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4CA,MAAa,+BAA+B,YAAkC;CAC5E,MAAM,OAAO,QAAQ,uBAAuB;CAC5C,MAAM,UAAU,KAAK;CACrB,MAAM,aAAa,KAAK,SAAS;CAMjC,IAHuB,WAAW,KAAK,cAAc,OAAO,aAGxC;EAClB,MAAM,UAAU,KAAK,OAAO,KAAK,QAAQ;EACzC,MAAM,UAAU,KAAK,MAAM;EAC3B,MAAM,aAAa,SAAS,iBAAiB,SAAS,QAAQ;EAG9D,OAAO,YAAY,cAAc,QAAQ,SAAS,WAAW;;CAG/D,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"useRightDrawer.mjs","names":[],"sources":["../../../../src/components/RightDrawer/useRightDrawer.ts"],"sourcesContent":["'use client';\n\nimport { useSyncExternalStore } from 'react';\n\ntype DrawerState = Record<string, boolean>;\n\nclass DrawerObservable {\n private listeners = new Set<() => void>();\n private drawers: DrawerState = {};\n\n subscribe = (listener: () => void) => {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n };\n\n getSnapshot = () => {\n return this.drawers;\n };\n\n open = (key: string) => {\n if (this.drawers[key]) return;\n this.drawers = { ...this.drawers, [key]: true };\n this.emit();\n };\n\n close = (key: string) => {\n if (!this.drawers[key]) return;\n this.drawers = { ...this.drawers, [key]: false };\n this.emit();\n };\n\n set = (states: DrawerState) => {\n let changed = false;\n const newDrawers = { ...this.drawers };\n\n for (const [key, value] of Object.entries(states)) {\n if (newDrawers[key] !== value) {\n newDrawers[key] = value;\n changed = true;\n }\n }\n\n if (changed) {\n this.drawers = newDrawers;\n this.emit();\n }\n };\n\n private emit = () => {\n this.listeners.forEach((listener) => {\n listener();\n });\n };\n}\n\nexport const drawerManager = new DrawerObservable();\n\nexport const useRightDrawer = () => {\n const drawers = useSyncExternalStore(\n drawerManager.subscribe,\n drawerManager.getSnapshot,\n () => ({}) as DrawerState\n );\n\n return {\n open: drawerManager.open,\n close: drawerManager.close,\n set: drawerManager.set,\n isOpen: (key: string) => !!drawers[key],\n };\n};\n"],"mappings":";;;;;AAMA,IAAM,mBAAN,MAAuB;CACrB,AAAQ,4BAAY,IAAI,KAAiB;CACzC,AAAQ,UAAuB,EAAE;CAEjC,aAAa,aAAyB;AACpC,OAAK,UAAU,IAAI,SAAS;AAC5B,eAAa;AACX,QAAK,UAAU,OAAO,SAAS;;;CAInC,oBAAoB;AAClB,SAAO,KAAK;;CAGd,QAAQ,QAAgB;AACtB,MAAI,KAAK,QAAQ,KAAM;AACvB,OAAK,UAAU;GAAE,GAAG,KAAK;IAAU,MAAM;GAAM;AAC/C,OAAK,MAAM;;CAGb,SAAS,QAAgB;AACvB,MAAI,CAAC,KAAK,QAAQ,KAAM;AACxB,OAAK,UAAU;GAAE,GAAG,KAAK;IAAU,MAAM;GAAO;AAChD,OAAK,MAAM;;CAGb,OAAO,WAAwB;EAC7B,IAAI,UAAU;EACd,MAAM,aAAa,EAAE,GAAG,KAAK,SAAS;AAEtC,OAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,OAAO,CAC/C,KAAI,WAAW,SAAS,OAAO;AAC7B,cAAW,OAAO;AAClB,aAAU;;AAId,MAAI,SAAS;AACX,QAAK,UAAU;AACf,QAAK,MAAM;;;CAIf,AAAQ,aAAa;AACnB,OAAK,UAAU,SAAS,aAAa;AACnC,aAAU;IACV;;;AAIN,MAAa,gBAAgB,IAAI,kBAAkB;AAEnD,MAAa,uBAAuB;CAClC,MAAM,UAAU,qBACd,cAAc,WACd,cAAc,oBACP,EAAE,EACV;AAED,QAAO;EACL,MAAM,cAAc;EACpB,OAAO,cAAc;EACrB,KAAK,cAAc;EACnB,SAAS,QAAgB,CAAC,CAAC,QAAQ;EACpC"}
1
+ {"version":3,"file":"useRightDrawer.mjs","names":[],"sources":["../../../../src/components/RightDrawer/useRightDrawer.ts"],"sourcesContent":["'use client';\n\nimport { useSyncExternalStore } from 'react';\n\ntype DrawerState = Record<string, boolean>;\n\nclass DrawerObservable {\n private listeners = new Set<() => void>();\n private drawers: DrawerState = {};\n\n subscribe = (listener: () => void) => {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n };\n\n getSnapshot = () => {\n return this.drawers;\n };\n\n open = (key: string) => {\n if (this.drawers[key]) return;\n this.drawers = { ...this.drawers, [key]: true };\n this.emit();\n };\n\n close = (key: string) => {\n if (!this.drawers[key]) return;\n this.drawers = { ...this.drawers, [key]: false };\n this.emit();\n };\n\n set = (states: DrawerState) => {\n let changed = false;\n const newDrawers = { ...this.drawers };\n\n for (const [key, value] of Object.entries(states)) {\n if (newDrawers[key] !== value) {\n newDrawers[key] = value;\n changed = true;\n }\n }\n\n if (changed) {\n this.drawers = newDrawers;\n this.emit();\n }\n };\n\n private emit = () => {\n this.listeners.forEach((listener) => {\n listener();\n });\n };\n}\n\nexport const drawerManager = new DrawerObservable();\n\nexport const useRightDrawer = () => {\n const drawers = useSyncExternalStore(\n drawerManager.subscribe,\n drawerManager.getSnapshot,\n () => ({}) as DrawerState\n );\n\n return {\n open: drawerManager.open,\n close: drawerManager.close,\n set: drawerManager.set,\n isOpen: (key: string) => !!drawers[key],\n };\n};\n"],"mappings":";;;;;AAMA,IAAM,mBAAN,MAAuB;CACrB,AAAQ,4BAAY,IAAI,KAAiB;CACzC,AAAQ,UAAuB,EAAE;CAEjC,aAAa,aAAyB;EACpC,KAAK,UAAU,IAAI,SAAS;EAC5B,aAAa;GACX,KAAK,UAAU,OAAO,SAAS;;;CAInC,oBAAoB;EAClB,OAAO,KAAK;;CAGd,QAAQ,QAAgB;EACtB,IAAI,KAAK,QAAQ,MAAM;EACvB,KAAK,UAAU;GAAE,GAAG,KAAK;IAAU,MAAM;GAAM;EAC/C,KAAK,MAAM;;CAGb,SAAS,QAAgB;EACvB,IAAI,CAAC,KAAK,QAAQ,MAAM;EACxB,KAAK,UAAU;GAAE,GAAG,KAAK;IAAU,MAAM;GAAO;EAChD,KAAK,MAAM;;CAGb,OAAO,WAAwB;EAC7B,IAAI,UAAU;EACd,MAAM,aAAa,EAAE,GAAG,KAAK,SAAS;EAEtC,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,OAAO,EAC/C,IAAI,WAAW,SAAS,OAAO;GAC7B,WAAW,OAAO;GAClB,UAAU;;EAId,IAAI,SAAS;GACX,KAAK,UAAU;GACf,KAAK,MAAM;;;CAIf,AAAQ,aAAa;EACnB,KAAK,UAAU,SAAS,aAAa;GACnC,UAAU;IACV;;;AAIN,MAAa,gBAAgB,IAAI,kBAAkB;AAEnD,MAAa,uBAAuB;CAClC,MAAM,UAAU,qBACd,cAAc,WACd,cAAc,oBACP,EAAE,EACV;CAED,OAAO;EACL,MAAM,cAAc;EACpB,OAAO,cAAc;EACrB,KAAK,cAAc;EACnB,SAAS,QAAgB,CAAC,CAAC,QAAQ;EACpC"}
@@ -1 +1 @@
1
- {"version":3,"file":"Multiselect.mjs","names":["RemoveIcon"],"sources":["../../../../src/components/Select/Multiselect.tsx"],"sourcesContent":["'use client';\n\nimport { cn } from '@utils/cn';\nimport { Check, X as RemoveIcon } from 'lucide-react';\nimport {\n type ComponentProps,\n createContext,\n type Dispatch,\n type FC,\n type HTMLAttributes,\n type KeyboardEvent,\n type LegacyRef,\n type MouseEventHandler,\n type RefObject,\n type SetStateAction,\n type SyntheticEvent,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { Badge, BadgeColor } from '../Badge';\nimport { Command, CommandRoot } from '../Command';\n\n/**\n * Context properties for MultiSelect component state management\n *\n * @interface MultiSelectContextProps\n */\ntype MultiSelectContextProps = {\n /** Array of currently selected values */\n value: string[];\n /** Handler for value changes */\n onValueChange: (value: string) => void;\n /** Whether the dropdown is currently open */\n open: boolean;\n /** Function to set the open state */\n setOpen: (value: boolean) => void;\n /** Current input field value for filtering */\n inputValue: string;\n /** Function to set the input value */\n setInputValue: Dispatch<SetStateAction<string>>;\n /** Index of currently focused option for keyboard navigation */\n activeIndex: number;\n /** Function to set the active index */\n setActiveIndex: Dispatch<SetStateAction<number>>;\n /** Ref to the input element */\n ref: RefObject<HTMLInputElement | null>;\n /** Handler for option selection */\n handleSelect: (e: SyntheticEvent<HTMLInputElement>) => void;\n};\n\nconst MultiSelectContext = createContext<MultiSelectContextProps | null>(null);\n\n/**\n * Custom hook to access MultiSelect context\n *\n * Provides access to the internal state and methods of the MultiSelect component.\n * Must be used within a MultiSelect component tree.\n *\n * @returns MultiSelectContextProps - All context properties and methods\n * @throws Error when used outside of MultiSelect component\n *\n * @example\n * ```tsx\n * function CustomMultiSelectItem() {\n * const { value, onValueChange, open } = useMultiSelect();\n * // Use context properties...\n * }\n * ```\n */\nconst useMultiSelect = () => {\n const context = useContext(MultiSelectContext);\n if (!context) {\n throw new Error('useMultiSelect must be used within MultiSelectProvider');\n }\n return context;\n};\n\n/**\n * Props interface for the main MultiSelect component\n *\n * @interface MultiSelectProps\n */\ntype MultiSelectProps = ComponentProps<typeof CommandRoot> & {\n /**\n * Array of selected values (controlled mode)\n * @example\n * ```tsx\n * const [selected, setSelected] = useState(['react', 'vue']);\n * <MultiSelect values={selected} onValueChange={setSelected} />\n * ```\n */\n values?: string[];\n\n /**\n * Default selected values for uncontrolled mode\n * @example\n * ```tsx\n * <MultiSelect defaultValues={['react']} />\n * ```\n */\n defaultValues?: string[];\n\n /**\n * Callback fired when selection changes\n * @param value - New array of selected values\n * @example\n * ```tsx\n * <MultiSelect onValueChange={(values) => console.log('Selected:', values)} />\n * ```\n */\n onValueChange?: (value: string[]) => void;\n\n /**\n * Whether keyboard navigation should loop through options\n * @default false\n * @example\n * ```tsx\n * <MultiSelect loop /> // Arrow keys wrap around at list boundaries\n * ```\n */\n loop?: boolean;\n};\n\n/**\n * MultiSelect - A comprehensive multi-selection dropdown component\n *\n * An advanced multi-select component that combines the functionality of a searchable dropdown\n * with the ability to select multiple values. Built on top of Command component primitives,\n * it provides filtering, keyboard navigation, and visual feedback through badges.\n *\n * ## Key Features\n * - **Multi-Selection**: Select multiple options with visual badge representation\n * - **Searchable**: Built-in filtering to quickly find options in large lists\n * - **Keyboard Navigation**: Full arrow key navigation with optional looping\n * - **Accessibility**: Screen reader support, ARIA attributes, and focus management\n * - **Flexible State**: Both controlled and uncontrolled usage patterns\n * - **Rich UI**: Customizable badges, icons, and content layout\n *\n * ## Use Cases\n * - Tag/category selection in forms\n * - Multi-user assignment interfaces\n * - Feature/permission selection\n * - Filter selection in search interfaces\n * - Any multi-choice selection requirement\n *\n * ## Architecture\n * The component follows a compound pattern similar to Select:\n * - `MultiSelect` (root): Manages state and provides context\n * - `MultiSelect.Trigger`: Container for input and selected badges\n * - `MultiSelect.Input`: Searchable input field with filtering\n * - `MultiSelect.Content`: Dropdown container for options\n * - `MultiSelect.List`: Options container with keyboard navigation\n * - `MultiSelect.Item`: Individual selectable options\n *\n * ## Accessibility\n * - **Keyboard Navigation**: Arrow keys, Enter to select, Backspace to remove\n * - **Screen Readers**: Proper ARIA labels and live region announcements\n * - **Focus Management**: Clear focus indicators and logical tab flow\n * - **Search**: Real-time filtering with screen reader announcements\n *\n * @example\n * Basic multi-select usage:\n * ```tsx\n * const [frameworks, setFrameworks] = useState<string[]>([]);\n *\n * <MultiSelect values={frameworks} onValueChange={setFrameworks}>\n * <MultiSelect.Trigger>\n * <MultiSelect.Input placeholder=\"Select frameworks...\" />\n * </MultiSelect.Trigger>\n * <MultiSelect.Content>\n * <MultiSelect.List>\n * <MultiSelect.Item value=\"react\">React</MultiSelect.Item>\n * <MultiSelect.Item value=\"vue\">Vue</MultiSelect.Item>\n * <MultiSelect.Item value=\"svelte\">Svelte</MultiSelect.Item>\n * </MultiSelect.List>\n * </MultiSelect.Content>\n * </MultiSelect>\n * ```\n *\n * @example\n * Advanced usage with keyboard looping:\n * ```tsx\n * <MultiSelect defaultValues={['react']} loop>\n * <MultiSelect.Trigger>\n * <MultiSelect.Input placeholder=\"Choose technologies...\" />\n * </MultiSelect.Trigger>\n * <MultiSelect.Content>\n * <MultiSelect.List>\n * <MultiSelect.Item value=\"react\">⚛️ React</MultiSelect.Item>\n * <MultiSelect.Item value=\"vue\">💚 Vue</MultiSelect.Item>\n * <MultiSelect.Item value=\"angular\">🔴 Angular</MultiSelect.Item>\n * </MultiSelect.List>\n * </MultiSelect.Content>\n * </MultiSelect>\n * ```\n *\n * @example\n * Form integration with validation:\n * ```tsx\n * <form>\n * <MultiSelect\n * values={selectedSkills}\n * onValueChange={setSelectedSkills}\n * required\n * >\n * <MultiSelect.Trigger className=\"min-h-[2.5rem]\">\n * <MultiSelect.Input placeholder=\"Select your skills...\" />\n * </MultiSelect.Trigger>\n * <MultiSelect.Content>\n * <MultiSelect.List>\n * <MultiSelect.Item value=\"javascript\">JavaScript</MultiSelect.Item>\n * <MultiSelect.Item value=\"typescript\">TypeScript</MultiSelect.Item>\n * <MultiSelect.Item value=\"python\">Python</MultiSelect.Item>\n * </MultiSelect.List>\n * </MultiSelect.Content>\n * </MultiSelect>\n * </form>\n * ```\n */\nconst MultiSelectRoot: FC<MultiSelectProps> = ({\n values: valuesProp,\n defaultValues,\n onValueChange,\n loop = false,\n className,\n children,\n dir,\n ...props\n}) => {\n const [value, setValue] = useState<string[]>(defaultValues ?? []);\n const [inputValue, setInputValue] = useState('');\n const [open, setOpen] = useState<boolean>(false);\n const [activeIndex, setActiveIndex] = useState<number>(-1);\n const inputRef = useRef<HTMLInputElement>(null);\n const [isValueSelected, setIsValueSelected] = useState(false);\n const [selectedValue, setSelectedValue] = useState('');\n\n useEffect(() => {\n if (valuesProp) {\n setValue(valuesProp);\n }\n }, [valuesProp]);\n\n const onValueChangeHandler = useCallback(\n (val: string) => {\n if (value.includes(val)) {\n const newValue = value.filter((item) => item !== val);\n setValue(newValue);\n onValueChange?.(newValue);\n } else {\n const newValue = [...value, val];\n setValue(newValue);\n onValueChange?.(newValue);\n }\n },\n\n [value]\n );\n\n const handleSelect = useCallback(\n (e: SyntheticEvent<HTMLInputElement>) => {\n e.preventDefault();\n const target = e.currentTarget;\n const selection = target.value.substring(\n target.selectionStart ?? 0,\n target.selectionEnd ?? 0\n );\n\n setSelectedValue(selection);\n setIsValueSelected(selection === inputValue);\n },\n [inputValue]\n );\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLDivElement>) => {\n e.stopPropagation();\n const target = inputRef.current;\n\n if (!target) return;\n\n const moveNext = () => {\n const nextIndex = activeIndex + 1;\n setActiveIndex(\n nextIndex > value.length - 1 ? (loop ? 0 : -1) : nextIndex\n );\n };\n\n const movePrev = () => {\n const prevIndex = activeIndex - 1;\n setActiveIndex(prevIndex < 0 ? value.length - 1 : prevIndex);\n };\n\n const moveCurrent = () => {\n const newIndex =\n activeIndex - 1 <= 0\n ? value.length - 1 === 0\n ? -1\n : 0\n : activeIndex - 1;\n setActiveIndex(newIndex);\n };\n\n switch (e.key) {\n case 'ArrowLeft':\n if (dir === 'rtl') {\n if (value.length > 0 && (activeIndex !== -1 || loop)) {\n moveNext();\n }\n } else if (value.length > 0 && target.selectionStart === 0) {\n movePrev();\n }\n break;\n\n case 'ArrowRight':\n if (dir === 'rtl') {\n if (value.length > 0 && target.selectionStart === 0) {\n movePrev();\n }\n } else if (value.length > 0 && (activeIndex !== -1 || loop)) {\n moveNext();\n }\n break;\n\n case 'Backspace':\n case 'Delete':\n if (value.length > 0) {\n if (activeIndex !== -1 && activeIndex < value.length) {\n onValueChangeHandler(value[activeIndex]);\n moveCurrent();\n } else if (\n (target.selectionStart === 0 && selectedValue === inputValue) ||\n isValueSelected\n ) {\n onValueChangeHandler(value[value.length - 1]);\n }\n }\n break;\n\n case 'Enter':\n setOpen(true);\n break;\n\n case 'Escape':\n if (activeIndex !== -1) {\n setActiveIndex(-1);\n } else if (open) {\n setOpen(false);\n }\n break;\n }\n },\n\n [value, inputValue, activeIndex, loop]\n );\n\n const memoValue = useMemo(\n () => ({\n value,\n onValueChange: onValueChangeHandler,\n open,\n setOpen,\n inputValue,\n setInputValue,\n activeIndex,\n setActiveIndex,\n ref: inputRef,\n handleSelect,\n }),\n [\n value,\n onValueChangeHandler,\n open,\n setOpen,\n inputValue,\n setInputValue,\n activeIndex,\n setActiveIndex,\n inputRef,\n handleSelect,\n ]\n );\n\n return (\n <MultiSelectContext value={memoValue}>\n <CommandRoot\n onKeyDown={handleKeyDown}\n className={cn(\n 'flex w-full flex-col gap-2 overflow-visible bg-transparent',\n className\n )}\n dir={dir}\n {...props}\n >\n {children}\n </CommandRoot>\n </MultiSelectContext>\n );\n};\n\nconst MultiSelectTrigger: FC<\n HTMLAttributes<HTMLDivElement> & {\n getBadgeValue?: (value: string) => string;\n validationStyleEnabled?: boolean;\n }\n> = ({\n className,\n getBadgeValue = (value) => value,\n validationStyleEnabled = false,\n children,\n ...props\n}) => {\n const { value, onValueChange, activeIndex } = useMultiSelect();\n\n const mousePreventDefault: MouseEventHandler<HTMLButtonElement> = useCallback(\n (e) => {\n e.preventDefault();\n e.stopPropagation();\n },\n []\n );\n\n return (\n <div\n className={cn(\n // Base layout\n 'flex w-full flex-col gap-3',\n 'cursor-pointer select-text text-base shadow-none outline-none md:text-sm',\n\n // Corner shape\n 'rounded-xl [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-2xl',\n\n // Spacing\n 'px-2 py-3 md:py-2',\n\n // Background and text\n 'bg-neutral-50 dark:bg-neutral-950',\n 'text-text',\n\n // Focus ring\n 'ring-0',\n 'focus-within:outline-none',\n 'focus-within:ring-3',\n 'focus-within:ring-neutral-200',\n 'dark:focus-within:ring-neutral-500',\n\n 'focus-within:ring-offset-white',\n 'dark:focus-within:ring-offset-neutral-500',\n\n // Remove box-shadow\n '[box-shadow:none]',\n\n // States\n 'disabled:cursor-not-allowed disabled:opacity-50',\n 'aria-invalid:border-error',\n\n // Validation styles\n validationStyleEnabled && 'valid:border-success invalid:border-error',\n\n className\n )}\n {...props}\n >\n {value.length > 0 && (\n <div className=\"flex w-full flex-wrap gap-1\">\n {value.map((item, index) => (\n <Badge\n key={item}\n className={cn(\n 'flex items-center gap-1 rounded-xl px-1',\n activeIndex === index && 'ring-2 ring-muted-foreground'\n )}\n color={BadgeColor.TEXT}\n >\n <span className=\"text-xs\">{getBadgeValue(item)}</span>\n <button\n aria-label={`Remove ${item} option`}\n aria-roledescription=\"button to remove option\"\n onMouseDown={mousePreventDefault}\n onClick={() => onValueChange(item)}\n >\n <span className=\"sr-only\">Remove {item} option</span>\n <RemoveIcon className=\"size-4 cursor-pointer\" />\n </button>\n </Badge>\n ))}\n </div>\n )}\n {children}\n </div>\n );\n};\n\nconst MultiSelectInput: FC<ComponentProps<typeof Command.Input>> = ({\n className,\n ...props\n}) => {\n const {\n setOpen,\n inputValue,\n setInputValue,\n activeIndex,\n setActiveIndex,\n handleSelect,\n ref: inputRef,\n } = useMultiSelect();\n\n return (\n <Command.Input\n {...props}\n tabIndex={0}\n ref={inputRef as LegacyRef<HTMLInputElement>}\n value={inputValue}\n onValueChange={activeIndex === -1 ? setInputValue : undefined}\n onSelect={handleSelect}\n onBlur={() => setOpen(false)}\n onFocus={() => setOpen(true)}\n onClick={() => setActiveIndex(-1)}\n className={cn(\n 'ml-2 flex-1 cursor-pointer outline-hidden',\n className,\n activeIndex !== -1 && 'caret-transparent'\n )}\n />\n );\n};\n\nconst MultiSelectContent: FC<HTMLAttributes<HTMLDivElement>> = ({\n children,\n}) => {\n const { open } = useMultiSelect();\n return <div className=\"relative\">{open && children}</div>;\n};\n\nconst MultiSelectList: typeof Command.List = ({ className, children }) => (\n <Command.List\n className={cn(\n // Base layout\n 'absolute top-0 z-10 flex w-full flex-col gap-2',\n 'rounded-xl p-2 shadow-md',\n\n // Background and text\n 'bg-white dark:bg-neutral-950',\n 'text-text',\n\n // Border\n 'border border-neutral-200 dark:border-neutral-800',\n\n // Transitions\n 'transition-colors',\n\n className\n )}\n >\n {children}\n <Command.Empty>\n <span className=\"text-muted-foreground\">No results found</span>\n </Command.Empty>\n </Command.List>\n);\n\nconst MultiSelectItem: FC<\n { value: string } & ComponentProps<typeof Command.Item>\n> = ({ className, value, children, ...props }) => {\n const { value: Options, onValueChange, setInputValue } = useMultiSelect();\n\n const mousePreventDefault: MouseEventHandler<HTMLDivElement> = useCallback(\n (e) => {\n e.preventDefault();\n e.stopPropagation();\n },\n []\n );\n\n const isIncluded = Options.includes(value);\n return (\n <Command.Item\n {...props}\n onSelect={() => {\n onValueChange(value);\n setInputValue('');\n }}\n className={cn(\n // Base layout\n 'flex cursor-pointer justify-between',\n 'rounded-lg px-2 py-1',\n\n // Hover and transitions\n 'transition-colors',\n 'hover:bg-neutral/10',\n\n // States\n isIncluded && 'opacity-50',\n props.disabled && 'cursor-not-allowed opacity-50',\n\n className\n )}\n onMouseDown={mousePreventDefault}\n >\n {children}\n {isIncluded && <Check className=\"size-4\" />}\n </Command.Item>\n );\n};\n\ntype MultiSelectType = typeof MultiSelectRoot & {\n Trigger: typeof MultiSelectTrigger;\n Input: typeof MultiSelectInput;\n Content: typeof MultiSelectContent;\n List: typeof MultiSelectList;\n Item: typeof MultiSelectItem;\n};\n\n/**\n *\n * Usage example:\n * ```jsx\n * <MultiSelect\n * values={value}\n * onValuesChange={setValue}\n * loop\n * >\n * <MultiSelect.Trigger>\n * <MultiSelect.Input placeholder=\"Select your framework\" />\n * </MultiSelect.Trigger>\n * <MultiSelect.Content>\n * <MultiSelect.List>\n * <MultiSelect.Item value={\"React\"}>React</MultiSelect.Item>\n * <MultiSelect.Item value={\"Vue\"}>Vue</MultiSelect.Item>\n * <MultiSelect.Item value={\"Svelte\"}>Svelte</MultiSelect.Item>\n * </MultiSelect.List>\n * </MultiSelect.Content>\n * </MultiSelect>\n * ```\n */\nexport const MultiSelect = MultiSelectRoot as MultiSelectType;\nMultiSelect.Trigger = MultiSelectTrigger;\nMultiSelect.Input = MultiSelectInput;\nMultiSelect.Content = MultiSelectContent;\nMultiSelect.List = MultiSelectList;\nMultiSelect.Item = MultiSelectItem;\n"],"mappings":"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"}
1
+ {"version":3,"file":"Multiselect.mjs","names":["RemoveIcon"],"sources":["../../../../src/components/Select/Multiselect.tsx"],"sourcesContent":["'use client';\n\nimport { cn } from '@utils/cn';\nimport { Check, X as RemoveIcon } from 'lucide-react';\nimport {\n type ComponentProps,\n createContext,\n type Dispatch,\n type FC,\n type HTMLAttributes,\n type KeyboardEvent,\n type LegacyRef,\n type MouseEventHandler,\n type RefObject,\n type SetStateAction,\n type SyntheticEvent,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { Badge, BadgeColor } from '../Badge';\nimport { Command, CommandRoot } from '../Command';\n\n/**\n * Context properties for MultiSelect component state management\n *\n * @interface MultiSelectContextProps\n */\ntype MultiSelectContextProps = {\n /** Array of currently selected values */\n value: string[];\n /** Handler for value changes */\n onValueChange: (value: string) => void;\n /** Whether the dropdown is currently open */\n open: boolean;\n /** Function to set the open state */\n setOpen: (value: boolean) => void;\n /** Current input field value for filtering */\n inputValue: string;\n /** Function to set the input value */\n setInputValue: Dispatch<SetStateAction<string>>;\n /** Index of currently focused option for keyboard navigation */\n activeIndex: number;\n /** Function to set the active index */\n setActiveIndex: Dispatch<SetStateAction<number>>;\n /** Ref to the input element */\n ref: RefObject<HTMLInputElement | null>;\n /** Handler for option selection */\n handleSelect: (e: SyntheticEvent<HTMLInputElement>) => void;\n};\n\nconst MultiSelectContext = createContext<MultiSelectContextProps | null>(null);\n\n/**\n * Custom hook to access MultiSelect context\n *\n * Provides access to the internal state and methods of the MultiSelect component.\n * Must be used within a MultiSelect component tree.\n *\n * @returns MultiSelectContextProps - All context properties and methods\n * @throws Error when used outside of MultiSelect component\n *\n * @example\n * ```tsx\n * function CustomMultiSelectItem() {\n * const { value, onValueChange, open } = useMultiSelect();\n * // Use context properties...\n * }\n * ```\n */\nconst useMultiSelect = () => {\n const context = useContext(MultiSelectContext);\n if (!context) {\n throw new Error('useMultiSelect must be used within MultiSelectProvider');\n }\n return context;\n};\n\n/**\n * Props interface for the main MultiSelect component\n *\n * @interface MultiSelectProps\n */\ntype MultiSelectProps = ComponentProps<typeof CommandRoot> & {\n /**\n * Array of selected values (controlled mode)\n * @example\n * ```tsx\n * const [selected, setSelected] = useState(['react', 'vue']);\n * <MultiSelect values={selected} onValueChange={setSelected} />\n * ```\n */\n values?: string[];\n\n /**\n * Default selected values for uncontrolled mode\n * @example\n * ```tsx\n * <MultiSelect defaultValues={['react']} />\n * ```\n */\n defaultValues?: string[];\n\n /**\n * Callback fired when selection changes\n * @param value - New array of selected values\n * @example\n * ```tsx\n * <MultiSelect onValueChange={(values) => console.log('Selected:', values)} />\n * ```\n */\n onValueChange?: (value: string[]) => void;\n\n /**\n * Whether keyboard navigation should loop through options\n * @default false\n * @example\n * ```tsx\n * <MultiSelect loop /> // Arrow keys wrap around at list boundaries\n * ```\n */\n loop?: boolean;\n};\n\n/**\n * MultiSelect - A comprehensive multi-selection dropdown component\n *\n * An advanced multi-select component that combines the functionality of a searchable dropdown\n * with the ability to select multiple values. Built on top of Command component primitives,\n * it provides filtering, keyboard navigation, and visual feedback through badges.\n *\n * ## Key Features\n * - **Multi-Selection**: Select multiple options with visual badge representation\n * - **Searchable**: Built-in filtering to quickly find options in large lists\n * - **Keyboard Navigation**: Full arrow key navigation with optional looping\n * - **Accessibility**: Screen reader support, ARIA attributes, and focus management\n * - **Flexible State**: Both controlled and uncontrolled usage patterns\n * - **Rich UI**: Customizable badges, icons, and content layout\n *\n * ## Use Cases\n * - Tag/category selection in forms\n * - Multi-user assignment interfaces\n * - Feature/permission selection\n * - Filter selection in search interfaces\n * - Any multi-choice selection requirement\n *\n * ## Architecture\n * The component follows a compound pattern similar to Select:\n * - `MultiSelect` (root): Manages state and provides context\n * - `MultiSelect.Trigger`: Container for input and selected badges\n * - `MultiSelect.Input`: Searchable input field with filtering\n * - `MultiSelect.Content`: Dropdown container for options\n * - `MultiSelect.List`: Options container with keyboard navigation\n * - `MultiSelect.Item`: Individual selectable options\n *\n * ## Accessibility\n * - **Keyboard Navigation**: Arrow keys, Enter to select, Backspace to remove\n * - **Screen Readers**: Proper ARIA labels and live region announcements\n * - **Focus Management**: Clear focus indicators and logical tab flow\n * - **Search**: Real-time filtering with screen reader announcements\n *\n * @example\n * Basic multi-select usage:\n * ```tsx\n * const [frameworks, setFrameworks] = useState<string[]>([]);\n *\n * <MultiSelect values={frameworks} onValueChange={setFrameworks}>\n * <MultiSelect.Trigger>\n * <MultiSelect.Input placeholder=\"Select frameworks...\" />\n * </MultiSelect.Trigger>\n * <MultiSelect.Content>\n * <MultiSelect.List>\n * <MultiSelect.Item value=\"react\">React</MultiSelect.Item>\n * <MultiSelect.Item value=\"vue\">Vue</MultiSelect.Item>\n * <MultiSelect.Item value=\"svelte\">Svelte</MultiSelect.Item>\n * </MultiSelect.List>\n * </MultiSelect.Content>\n * </MultiSelect>\n * ```\n *\n * @example\n * Advanced usage with keyboard looping:\n * ```tsx\n * <MultiSelect defaultValues={['react']} loop>\n * <MultiSelect.Trigger>\n * <MultiSelect.Input placeholder=\"Choose technologies...\" />\n * </MultiSelect.Trigger>\n * <MultiSelect.Content>\n * <MultiSelect.List>\n * <MultiSelect.Item value=\"react\">⚛️ React</MultiSelect.Item>\n * <MultiSelect.Item value=\"vue\">💚 Vue</MultiSelect.Item>\n * <MultiSelect.Item value=\"angular\">🔴 Angular</MultiSelect.Item>\n * </MultiSelect.List>\n * </MultiSelect.Content>\n * </MultiSelect>\n * ```\n *\n * @example\n * Form integration with validation:\n * ```tsx\n * <form>\n * <MultiSelect\n * values={selectedSkills}\n * onValueChange={setSelectedSkills}\n * required\n * >\n * <MultiSelect.Trigger className=\"min-h-[2.5rem]\">\n * <MultiSelect.Input placeholder=\"Select your skills...\" />\n * </MultiSelect.Trigger>\n * <MultiSelect.Content>\n * <MultiSelect.List>\n * <MultiSelect.Item value=\"javascript\">JavaScript</MultiSelect.Item>\n * <MultiSelect.Item value=\"typescript\">TypeScript</MultiSelect.Item>\n * <MultiSelect.Item value=\"python\">Python</MultiSelect.Item>\n * </MultiSelect.List>\n * </MultiSelect.Content>\n * </MultiSelect>\n * </form>\n * ```\n */\nconst MultiSelectRoot: FC<MultiSelectProps> = ({\n values: valuesProp,\n defaultValues,\n onValueChange,\n loop = false,\n className,\n children,\n dir,\n ...props\n}) => {\n const [value, setValue] = useState<string[]>(defaultValues ?? []);\n const [inputValue, setInputValue] = useState('');\n const [open, setOpen] = useState<boolean>(false);\n const [activeIndex, setActiveIndex] = useState<number>(-1);\n const inputRef = useRef<HTMLInputElement>(null);\n const [isValueSelected, setIsValueSelected] = useState(false);\n const [selectedValue, setSelectedValue] = useState('');\n\n useEffect(() => {\n if (valuesProp) {\n setValue(valuesProp);\n }\n }, [valuesProp]);\n\n const onValueChangeHandler = useCallback(\n (val: string) => {\n if (value.includes(val)) {\n const newValue = value.filter((item) => item !== val);\n setValue(newValue);\n onValueChange?.(newValue);\n } else {\n const newValue = [...value, val];\n setValue(newValue);\n onValueChange?.(newValue);\n }\n },\n\n [value]\n );\n\n const handleSelect = useCallback(\n (e: SyntheticEvent<HTMLInputElement>) => {\n e.preventDefault();\n const target = e.currentTarget;\n const selection = target.value.substring(\n target.selectionStart ?? 0,\n target.selectionEnd ?? 0\n );\n\n setSelectedValue(selection);\n setIsValueSelected(selection === inputValue);\n },\n [inputValue]\n );\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLDivElement>) => {\n e.stopPropagation();\n const target = inputRef.current;\n\n if (!target) return;\n\n const moveNext = () => {\n const nextIndex = activeIndex + 1;\n setActiveIndex(\n nextIndex > value.length - 1 ? (loop ? 0 : -1) : nextIndex\n );\n };\n\n const movePrev = () => {\n const prevIndex = activeIndex - 1;\n setActiveIndex(prevIndex < 0 ? value.length - 1 : prevIndex);\n };\n\n const moveCurrent = () => {\n const newIndex =\n activeIndex - 1 <= 0\n ? value.length - 1 === 0\n ? -1\n : 0\n : activeIndex - 1;\n setActiveIndex(newIndex);\n };\n\n switch (e.key) {\n case 'ArrowLeft':\n if (dir === 'rtl') {\n if (value.length > 0 && (activeIndex !== -1 || loop)) {\n moveNext();\n }\n } else if (value.length > 0 && target.selectionStart === 0) {\n movePrev();\n }\n break;\n\n case 'ArrowRight':\n if (dir === 'rtl') {\n if (value.length > 0 && target.selectionStart === 0) {\n movePrev();\n }\n } else if (value.length > 0 && (activeIndex !== -1 || loop)) {\n moveNext();\n }\n break;\n\n case 'Backspace':\n case 'Delete':\n if (value.length > 0) {\n if (activeIndex !== -1 && activeIndex < value.length) {\n onValueChangeHandler(value[activeIndex]);\n moveCurrent();\n } else if (\n (target.selectionStart === 0 && selectedValue === inputValue) ||\n isValueSelected\n ) {\n onValueChangeHandler(value[value.length - 1]);\n }\n }\n break;\n\n case 'Enter':\n setOpen(true);\n break;\n\n case 'Escape':\n if (activeIndex !== -1) {\n setActiveIndex(-1);\n } else if (open) {\n setOpen(false);\n }\n break;\n }\n },\n\n [value, inputValue, activeIndex, loop]\n );\n\n const memoValue = useMemo(\n () => ({\n value,\n onValueChange: onValueChangeHandler,\n open,\n setOpen,\n inputValue,\n setInputValue,\n activeIndex,\n setActiveIndex,\n ref: inputRef,\n handleSelect,\n }),\n [\n value,\n onValueChangeHandler,\n open,\n setOpen,\n inputValue,\n setInputValue,\n activeIndex,\n setActiveIndex,\n inputRef,\n handleSelect,\n ]\n );\n\n return (\n <MultiSelectContext value={memoValue}>\n <CommandRoot\n onKeyDown={handleKeyDown}\n className={cn(\n 'flex w-full flex-col gap-2 overflow-visible bg-transparent',\n className\n )}\n dir={dir}\n {...props}\n >\n {children}\n </CommandRoot>\n </MultiSelectContext>\n );\n};\n\nconst MultiSelectTrigger: FC<\n HTMLAttributes<HTMLDivElement> & {\n getBadgeValue?: (value: string) => string;\n validationStyleEnabled?: boolean;\n }\n> = ({\n className,\n getBadgeValue = (value) => value,\n validationStyleEnabled = false,\n children,\n ...props\n}) => {\n const { value, onValueChange, activeIndex } = useMultiSelect();\n\n const mousePreventDefault: MouseEventHandler<HTMLButtonElement> = useCallback(\n (e) => {\n e.preventDefault();\n e.stopPropagation();\n },\n []\n );\n\n return (\n <div\n className={cn(\n // Base layout\n 'flex w-full flex-col gap-3',\n 'cursor-pointer select-text text-base shadow-none outline-none md:text-sm',\n\n // Corner shape\n 'rounded-xl [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-2xl',\n\n // Spacing\n 'px-2 py-3 md:py-2',\n\n // Background and text\n 'bg-neutral-50 dark:bg-neutral-950',\n 'text-text',\n\n // Focus ring\n 'ring-0',\n 'focus-within:outline-none',\n 'focus-within:ring-3',\n 'focus-within:ring-neutral-200',\n 'dark:focus-within:ring-neutral-500',\n\n 'focus-within:ring-offset-white',\n 'dark:focus-within:ring-offset-neutral-500',\n\n // Remove box-shadow\n '[box-shadow:none]',\n\n // States\n 'disabled:cursor-not-allowed disabled:opacity-50',\n 'aria-invalid:border-error',\n\n // Validation styles\n validationStyleEnabled && 'valid:border-success invalid:border-error',\n\n className\n )}\n {...props}\n >\n {value.length > 0 && (\n <div className=\"flex w-full flex-wrap gap-1\">\n {value.map((item, index) => (\n <Badge\n key={item}\n className={cn(\n 'flex items-center gap-1 rounded-xl px-1',\n activeIndex === index && 'ring-2 ring-muted-foreground'\n )}\n color={BadgeColor.TEXT}\n >\n <span className=\"text-xs\">{getBadgeValue(item)}</span>\n <button\n aria-label={`Remove ${item} option`}\n aria-roledescription=\"button to remove option\"\n onMouseDown={mousePreventDefault}\n onClick={() => onValueChange(item)}\n >\n <span className=\"sr-only\">Remove {item} option</span>\n <RemoveIcon className=\"size-4 cursor-pointer\" />\n </button>\n </Badge>\n ))}\n </div>\n )}\n {children}\n </div>\n );\n};\n\nconst MultiSelectInput: FC<ComponentProps<typeof Command.Input>> = ({\n className,\n ...props\n}) => {\n const {\n setOpen,\n inputValue,\n setInputValue,\n activeIndex,\n setActiveIndex,\n handleSelect,\n ref: inputRef,\n } = useMultiSelect();\n\n return (\n <Command.Input\n {...props}\n tabIndex={0}\n ref={inputRef as LegacyRef<HTMLInputElement>}\n value={inputValue}\n onValueChange={activeIndex === -1 ? setInputValue : undefined}\n onSelect={handleSelect}\n onBlur={() => setOpen(false)}\n onFocus={() => setOpen(true)}\n onClick={() => setActiveIndex(-1)}\n className={cn(\n 'ml-2 flex-1 cursor-pointer outline-hidden',\n className,\n activeIndex !== -1 && 'caret-transparent'\n )}\n />\n );\n};\n\nconst MultiSelectContent: FC<HTMLAttributes<HTMLDivElement>> = ({\n children,\n}) => {\n const { open } = useMultiSelect();\n return <div className=\"relative\">{open && children}</div>;\n};\n\nconst MultiSelectList: typeof Command.List = ({ className, children }) => (\n <Command.List\n className={cn(\n // Base layout\n 'absolute top-0 z-10 flex w-full flex-col gap-2',\n 'rounded-xl p-2 shadow-md',\n\n // Background and text\n 'bg-white dark:bg-neutral-950',\n 'text-text',\n\n // Border\n 'border border-neutral-200 dark:border-neutral-800',\n\n // Transitions\n 'transition-colors',\n\n className\n )}\n >\n {children}\n <Command.Empty>\n <span className=\"text-muted-foreground\">No results found</span>\n </Command.Empty>\n </Command.List>\n);\n\nconst MultiSelectItem: FC<\n { value: string } & ComponentProps<typeof Command.Item>\n> = ({ className, value, children, ...props }) => {\n const { value: Options, onValueChange, setInputValue } = useMultiSelect();\n\n const mousePreventDefault: MouseEventHandler<HTMLDivElement> = useCallback(\n (e) => {\n e.preventDefault();\n e.stopPropagation();\n },\n []\n );\n\n const isIncluded = Options.includes(value);\n return (\n <Command.Item\n {...props}\n onSelect={() => {\n onValueChange(value);\n setInputValue('');\n }}\n className={cn(\n // Base layout\n 'flex cursor-pointer justify-between',\n 'rounded-lg px-2 py-1',\n\n // Hover and transitions\n 'transition-colors',\n 'hover:bg-neutral/10',\n\n // States\n isIncluded && 'opacity-50',\n props.disabled && 'cursor-not-allowed opacity-50',\n\n className\n )}\n onMouseDown={mousePreventDefault}\n >\n {children}\n {isIncluded && <Check className=\"size-4\" />}\n </Command.Item>\n );\n};\n\ntype MultiSelectType = typeof MultiSelectRoot & {\n Trigger: typeof MultiSelectTrigger;\n Input: typeof MultiSelectInput;\n Content: typeof MultiSelectContent;\n List: typeof MultiSelectList;\n Item: typeof MultiSelectItem;\n};\n\n/**\n *\n * Usage example:\n * ```jsx\n * <MultiSelect\n * values={value}\n * onValuesChange={setValue}\n * loop\n * >\n * <MultiSelect.Trigger>\n * <MultiSelect.Input placeholder=\"Select your framework\" />\n * </MultiSelect.Trigger>\n * <MultiSelect.Content>\n * <MultiSelect.List>\n * <MultiSelect.Item value={\"React\"}>React</MultiSelect.Item>\n * <MultiSelect.Item value={\"Vue\"}>Vue</MultiSelect.Item>\n * <MultiSelect.Item value={\"Svelte\"}>Svelte</MultiSelect.Item>\n * </MultiSelect.List>\n * </MultiSelect.Content>\n * </MultiSelect>\n * ```\n */\nexport const MultiSelect = MultiSelectRoot as MultiSelectType;\nMultiSelect.Trigger = MultiSelectTrigger;\nMultiSelect.Input = MultiSelectInput;\nMultiSelect.Content = MultiSelectContent;\nMultiSelect.List = MultiSelectList;\nMultiSelect.Item = MultiSelectItem;\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"Select.mjs","names":[],"sources":["../../../../src/components/Select/Select.tsx"],"sourcesContent":["'use client';\n\nimport * as SelectPrimitive from '@radix-ui/react-select';\nimport { cn } from '@utils/cn';\nimport {\n CheckIcon,\n ChevronDownIcon,\n ChevronsUpDown,\n ChevronUpIcon,\n} from 'lucide-react';\nimport type { ComponentProps, FC } from 'react';\n\n/**\n * Enum for Select content positioning strategies\n *\n * @enum SelectContentPosition\n */\nexport enum SelectContentPosition {\n /** Position relative to the trigger with automatic placement */\n POPPER = 'popper',\n /** Align content with the selected item */\n ITEM_ALIGNED = 'item-aligned',\n}\n\nconst SelectRoot = SelectPrimitive.Root;\nconst SelectGroup = SelectPrimitive.Group;\nconst SelectValue = SelectPrimitive.Value;\n\n/**\n * Select trigger button component that displays the current selection and opens the dropdown\n *\n * Features comprehensive styling with validation states, focus management, and accessibility support.\n * Uses design tokens for consistent theming across the application.\n *\n * @param validationStyleEnabled - Enables automatic success/error styling based on form validation state\n * @param className - Additional CSS classes for custom styling\n * @param children - Content to display inside the trigger (typically SelectValue)\n *\n * @example\n * ```tsx\n * <Select.Trigger validationStyleEnabled>\n * <Select.Value placeholder=\"Choose option...\" />\n * </Select.Trigger>\n * ```\n */\nconst SelectTrigger: FC<\n ComponentProps<typeof SelectPrimitive.Trigger> & {\n /**\n * Enables success/error border styling based on HTML5 validation state\n * @default false\n * @example\n * ```tsx\n * <Select.Trigger validationStyleEnabled>\n * <Select.Value placeholder=\"Required field\" />\n * </Select.Trigger>\n * ```\n */\n validationStyleEnabled?: boolean;\n }\n> = ({ validationStyleEnabled = false, className, children, ...props }) => (\n <SelectPrimitive.Trigger\n suppressHydrationWarning\n className={cn(\n // Base layout and typography\n 'flex w-full cursor-pointer items-center justify-between whitespace-nowrap',\n 'select-text text-base shadow-none outline-none md:text-sm',\n\n // Corner shape\n 'rounded-xl [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-2xl',\n\n // Spacing\n 'px-2 py-3 md:py-2',\n\n // Background and text\n 'bg-neutral-50 dark:bg-neutral-950',\n 'text-text',\n\n // Focus ring\n 'ring-0',\n 'focus-visible:outline-none',\n 'focus-visible:ring-3',\n 'focus-visible:ring-neutral-200',\n 'dark:focus-visible:ring-neutral-500',\n\n 'focus-visible:ring-offset-white',\n 'dark:focus-visible:ring-offset-neutral-500',\n\n // Remove box-shadow\n '[box-shadow:none] focus:[box-shadow:none]',\n\n // States\n 'disabled:cursor-not-allowed disabled:opacity-50',\n 'aria-invalid:border-error',\n '[&>span]:line-clamp-1',\n\n // Validation styles\n validationStyleEnabled && 'valid:border-success invalid:border-error',\n\n className\n )}\n {...props}\n >\n {children}\n <SelectPrimitive.Icon asChild>\n <ChevronsUpDown className=\"size-4 opacity-50\" />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n);\n\n/**\n * Scroll up button for select content with long lists\n *\n * Automatically appears when content is scrollable upward, providing intuitive navigation\n * for users with large option lists.\n *\n * @param className - Additional CSS classes for custom styling\n */\nconst SelectScrollUpButton: FC<\n ComponentProps<typeof SelectPrimitive.ScrollUpButton>\n> = ({ className, ...props }) => (\n <SelectPrimitive.ScrollUpButton\n className={cn(\n 'flex cursor-default items-center justify-center py-1',\n className\n )}\n {...props}\n >\n <ChevronUpIcon />\n </SelectPrimitive.ScrollUpButton>\n);\n\n/**\n * Scroll down button for select content with long lists\n *\n * Automatically appears when content is scrollable downward, providing clear visual\n * indication of additional options below the current view.\n *\n * @param className - Additional CSS classes for custom styling\n */\nconst SelectScrollDownButton: FC<\n ComponentProps<typeof SelectPrimitive.ScrollDownButton>\n> = ({ className, ...props }) => (\n <SelectPrimitive.ScrollDownButton\n className={cn(\n 'flex cursor-default items-center justify-center py-1',\n className\n )}\n {...props}\n >\n <ChevronDownIcon />\n </SelectPrimitive.ScrollDownButton>\n);\n\n/**\n * Select dropdown content container with positioning and animation\n *\n * Provides the dropdown interface containing all selectable options. Features smooth\n * animations, flexible positioning strategies, and responsive design for optimal UX.\n *\n * @param position - Positioning strategy for the dropdown content\n * @param className - Additional CSS classes for custom styling\n * @param children - Select items, labels, and separators\n *\n * @example\n * ```tsx\n * <Select.Content position={SelectContentPosition.POPPER}>\n * <Select.Item value=\"option1\">Option 1</Select.Item>\n * <Select.Item value=\"option2\">Option 2</Select.Item>\n * </Select.Content>\n * ```\n */\nexport const SelectContent: FC<\n ComponentProps<typeof SelectPrimitive.Content>\n> = ({\n className,\n children,\n position = SelectContentPosition.POPPER,\n ...props\n}) => (\n <SelectPrimitive.Portal>\n <SelectPrimitive.Content\n className={cn(\n // Base styles\n 'relative z-50 max-h-96 min-w-32 overflow-hidden',\n 'rounded-xl shadow-md',\n\n // Background and text\n 'bg-white dark:bg-neutral-950',\n 'text-text',\n\n // Border\n 'border border-neutral-200 dark:border-neutral-800',\n\n // Animations\n 'data-[state=closed]:animate-out data-[state=open]:animate-in',\n 'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',\n 'data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95',\n 'data-[side=bottom]:slide-in-from-top-2',\n 'data-[side=left]:slide-in-from-right-2',\n 'data-[side=right]:slide-in-from-left-2',\n 'data-[side=top]:slide-in-from-bottom-2',\n\n // Positioning adjustments\n position === 'popper' &&\n 'data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=bottom]:translate-y-1 data-[side=top]:-translate-y-1',\n\n className\n )}\n position={position}\n {...props}\n >\n <SelectScrollUpButton />\n <SelectPrimitive.Viewport\n className={cn(\n 'p-1',\n position === 'popper' &&\n 'h-(--radix-select-trigger-height) w-full min-w-(--radix-select-trigger-width)'\n )}\n >\n {children}\n </SelectPrimitive.Viewport>\n <SelectScrollDownButton />\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n);\n\n/**\n * Label component for grouping select options\n *\n * Provides semantic grouping and visual organization of related options within\n * the select dropdown. Enhances accessibility and user experience.\n *\n * @param className - Additional CSS classes for custom styling\n *\n * @example\n * ```tsx\n * <Select.Content>\n * <Select.Label>Fruits</Select.Label>\n * <Select.Item value=\"apple\">Apple</Select.Item>\n * <Select.Item value=\"banana\">Banana</Select.Item>\n * <Select.Separator />\n * <Select.Label>Vegetables</Select.Label>\n * <Select.Item value=\"carrot\">Carrot</Select.Item>\n * </Select.Content>\n * ```\n */\nexport const SelectLabel: FC<ComponentProps<typeof SelectPrimitive.Label>> = ({\n className,\n ...props\n}) => (\n <SelectPrimitive.Label\n className={cn('px-1 py-0.5 font-semibold text-sm', className)}\n {...props}\n />\n);\n\n/**\n * Individual selectable item within the dropdown\n *\n * Represents a single option that users can select. Features hover states,\n * selection indicators, and keyboard navigation support for accessible interaction.\n *\n * @param className - Additional CSS classes for custom styling\n * @param children - The display text/content for the option\n *\n * @example\n * ```tsx\n * <Select.Item value=\"dark-mode\">\n * 🌙 Dark Mode\n * </Select.Item>\n * ```\n */\nconst SelectItem: FC<ComponentProps<typeof SelectPrimitive.Item>> = ({\n className,\n children,\n ...props\n}) => (\n <SelectPrimitive.Item\n className={cn(\n 'relative flex w-full cursor-pointer select-none items-center rounded-lg py-1.5 pr-8 pl-2 text-sm outline-hidden focus:bg-neutral/10 data-disabled:pointer-events-none data-disabled:opacity-50',\n className\n )}\n {...props}\n >\n <span className=\"absolute right-2 flex size-3.5 items-center justify-center\">\n <SelectPrimitive.ItemIndicator>\n <CheckIcon className=\"size-4\" />\n </SelectPrimitive.ItemIndicator>\n </span>\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n </SelectPrimitive.Item>\n);\n\n/**\n * Visual separator for grouping options in the dropdown\n *\n * Creates clear visual division between groups of related options,\n * improving readability and organization in complex select menus.\n *\n * @param className - Additional CSS classes for custom styling\n *\n * @example\n * ```tsx\n * <Select.Content>\n * <Select.Item value=\"recent\">Recent Files</Select.Item>\n * <Select.Separator />\n * <Select.Item value=\"all\">All Files</Select.Item>\n * </Select.Content>\n * ```\n */\nexport const SelectSeparator: FC<\n ComponentProps<typeof SelectPrimitive.Separator>\n> = ({ className, ...props }) => (\n <SelectPrimitive.Separator\n className={cn(\n '-mx-1 my-1 h-px',\n 'bg-neutral-200 dark:bg-neutral-800',\n className\n )}\n {...props}\n />\n);\n\n/**\n * Type definition for the compound Select component with all subcomponents\n */\ntype SelectType = typeof SelectRoot & {\n /** Group container for organizing related options */\n Group: typeof SelectGroup;\n /** Value display component for the trigger */\n Value: typeof SelectValue;\n /** Trigger button that opens the dropdown */\n Trigger: typeof SelectTrigger;\n /** Scroll up button for long lists */\n ScrollUpButton: typeof SelectScrollUpButton;\n /** Scroll down button for long lists */\n ScrollDownButton: typeof SelectScrollDownButton;\n /** Dropdown content container */\n Content: typeof SelectContent;\n /** Label component for option groups */\n Label: typeof SelectLabel;\n /** Individual selectable item */\n Item: typeof SelectItem;\n /** Visual separator between option groups */\n Separator: typeof SelectSeparator;\n};\n\n/**\n * Select - A comprehensive dropdown selection component\n *\n * A fully-featured select component built on Radix UI primitives with extensive customization,\n * accessibility features, and design system integration. Supports single selection with\n * keyboard navigation, validation states, and flexible content positioning.\n *\n * ## Key Features\n * - **Accessibility First**: Full keyboard navigation, screen reader support, and ARIA attributes\n * - **Flexible Positioning**: Multiple positioning strategies for optimal dropdown placement\n * - **Validation Integration**: Built-in support for form validation with visual feedback\n * - **Design System**: Consistent theming with design tokens and style variants\n * - **Responsive Design**: Works seamlessly across desktop and mobile devices\n * - **Rich Content**: Support for icons, separators, labels, and complex option layouts\n *\n * ## Use Cases\n * - Form field selections (theme, language, category)\n * - Settings and configuration options\n * - Filter and sort controls\n * - User preference selections\n * - Any single-choice dropdown interface\n *\n * ## Accessibility\n * - **Keyboard Navigation**: Arrow keys, Enter, Escape, and Home/End support\n * - **Screen Readers**: Proper ARIA labels and state announcements\n * - **Focus Management**: Intuitive focus flow and visual indicators\n * - **High Contrast**: Supports system high contrast modes\n *\n * ## Architecture\n * The Select component follows a compound component pattern with the following structure:\n * - `Select` (root): Manages state and provides context\n * - `Select.Trigger`: Button that displays current value and opens dropdown\n * - `Select.Value`: Displays the selected value with placeholder support\n * - `Select.Content`: Container for the dropdown options\n * - `Select.Item`: Individual selectable options\n * - `Select.Label`: Group labels for organizing options\n * - `Select.Separator`: Visual dividers between option groups\n *\n * @example\n * Basic usage with simple options:\n * ```tsx\n * <Select defaultValue=\"system\">\n * <Select.Trigger>\n * <Select.Value placeholder=\"Choose theme...\" />\n * </Select.Trigger>\n * <Select.Content>\n * <Select.Item value=\"light\">☀️ Light</Select.Item>\n * <Select.Item value=\"dark\">🌙 Dark</Select.Item>\n * <Select.Item value=\"system\">⚙️ System</Select.Item>\n * </Select.Content>\n * </Select>\n * ```\n *\n * @example\n * Advanced usage with groups and labels:\n * ```tsx\n * <Select>\n * <Select.Trigger validationStyleEnabled>\n * <Select.Value placeholder=\"Select category...\" />\n * </Select.Trigger>\n * <Select.Content>\n * <Select.Label>Web Technologies</Select.Label>\n * <Select.Item value=\"react\">React</Select.Item>\n * <Select.Item value=\"vue\">Vue</Select.Item>\n * <Select.Separator />\n * <Select.Label>Mobile</Select.Label>\n * <Select.Item value=\"react-native\">React Native</Select.Item>\n * <Select.Item value=\"flutter\">Flutter</Select.Item>\n * </Select.Content>\n * </Select>\n * ```\n *\n * @example\n * Form integration with validation:\n * ```tsx\n * <form>\n * <Select required name=\"country\">\n * <Select.Trigger validationStyleEnabled aria-invalid={hasError}>\n * <Select.Value placeholder=\"Select country...\" />\n * </Select.Trigger>\n * <Select.Content position={SelectContentPosition.ITEM_ALIGNED}>\n * <Select.Item value=\"us\">United States</Select.Item>\n * <Select.Item value=\"ca\">Canada</Select.Item>\n * <Select.Item value=\"uk\">United Kingdom</Select.Item>\n * </Select.Content>\n * </Select>\n * </form>\n * ```\n */\nexport const Select = SelectRoot as SelectType;\nSelect.Group = SelectGroup;\nSelect.Value = SelectValue;\nSelect.Trigger = SelectTrigger;\nSelect.ScrollUpButton = SelectScrollUpButton;\nSelect.ScrollDownButton = SelectScrollDownButton;\nSelect.Content = SelectContent;\nSelect.Label = SelectLabel;\nSelect.Item = SelectItem;\nSelect.Separator = SelectSeparator;\n"],"mappings":";;;;;;;;;;;;;AAiBA,IAAY,wBAAL;;AAEL;;AAEA;;KACD;AAED,MAAM,aAAa,gBAAgB;AACnC,MAAM,cAAc,gBAAgB;AACpC,MAAM,cAAc,gBAAgB;;;;;;;;;;;;;;;;;;AAmBpC,MAAM,iBAcD,EAAE,yBAAyB,OAAO,WAAW,UAAU,GAAG,YAC7D,qBAAC,gBAAgB,SAAjB;CACE;CACA,WAAW,GAET,6EACA,6DAGA,mFAGA,qBAGA,qCACA,aAGA,UACA,8BACA,wBACA,kCACA,uCAEA,mCACA,8CAGA,6CAGA,mDACA,6BACA,yBAGA,0BAA0B,6CAE1B,UACD;CACD,GAAI;WAxCN,CA0CG,UACD,oBAAC,gBAAgB,MAAjB;EAAsB;YACpB,oBAAC,gBAAD,EAAgB,WAAU,qBAAsB;EAC3B,EACC;;;;;;;;;;AAW5B,MAAM,wBAED,EAAE,WAAW,GAAG,YACnB,oBAAC,gBAAgB,gBAAjB;CACE,WAAW,GACT,wDACA,UACD;CACD,GAAI;WAEJ,oBAAC,eAAD,EAAiB;CACc;;;;;;;;;AAWnC,MAAM,0BAED,EAAE,WAAW,GAAG,YACnB,oBAAC,gBAAgB,kBAAjB;CACE,WAAW,GACT,wDACA,UACD;CACD,GAAI;WAEJ,oBAAC,iBAAD,EAAmB;CACc;;;;;;;;;;;;;;;;;;;AAqBrC,MAAa,iBAER,EACH,WACA,UACA,qBACA,GAAG,YAEH,oBAAC,gBAAgB,QAAjB,YACE,qBAAC,gBAAgB,SAAjB;CACE,WAAW,GAET,mDACA,wBAGA,gCACA,aAGA,qDAGA,gEACA,8DACA,gEACA,0CACA,0CACA,0CACA,0CAGA,aAAa,YACX,mIAEF,UACD;CACS;CACV,GAAI;WA7BN;EA+BE,oBAAC,sBAAD,EAAwB;EACxB,oBAAC,gBAAgB,UAAjB;GACE,WAAW,GACT,OACA,aAAa,YACX,gFACH;GAEA;GACwB;EAC3B,oBAAC,wBAAD,EAA0B;EACF;IACH;;;;;;;;;;;;;;;;;;;;;AAuB3B,MAAa,eAAiE,EAC5E,WACA,GAAG,YAEH,oBAAC,gBAAgB,OAAjB;CACE,WAAW,GAAG,qCAAqC,UAAU;CAC7D,GAAI;CACJ;;;;;;;;;;;;;;;;;AAmBJ,MAAM,cAA+D,EACnE,WACA,UACA,GAAG,YAEH,qBAAC,gBAAgB,MAAjB;CACE,WAAW,GACT,kMACA,UACD;CACD,GAAI;WALN,CAOE,oBAAC,QAAD;EAAM,WAAU;YACd,oBAAC,gBAAgB,eAAjB,YACE,oBAAC,WAAD,EAAW,WAAU,UAAW,GACF;EAC3B,GACP,oBAAC,gBAAgB,UAAjB,EAA2B,UAAoC,EAC1C;;;;;;;;;;;;;;;;;;;AAoBzB,MAAa,mBAER,EAAE,WAAW,GAAG,YACnB,oBAAC,gBAAgB,WAAjB;CACE,WAAW,GACT,mBACA,sCACA,UACD;CACD,GAAI;CACJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoHJ,MAAa,SAAS;AACtB,OAAO,QAAQ;AACf,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,OAAO,iBAAiB;AACxB,OAAO,mBAAmB;AAC1B,OAAO,UAAU;AACjB,OAAO,QAAQ;AACf,OAAO,OAAO;AACd,OAAO,YAAY"}
1
+ {"version":3,"file":"Select.mjs","names":[],"sources":["../../../../src/components/Select/Select.tsx"],"sourcesContent":["'use client';\n\nimport * as SelectPrimitive from '@radix-ui/react-select';\nimport { cn } from '@utils/cn';\nimport {\n CheckIcon,\n ChevronDownIcon,\n ChevronsUpDown,\n ChevronUpIcon,\n} from 'lucide-react';\nimport type { ComponentProps, FC } from 'react';\n\n/**\n * Enum for Select content positioning strategies\n *\n * @enum SelectContentPosition\n */\nexport enum SelectContentPosition {\n /** Position relative to the trigger with automatic placement */\n POPPER = 'popper',\n /** Align content with the selected item */\n ITEM_ALIGNED = 'item-aligned',\n}\n\nconst SelectRoot = SelectPrimitive.Root;\nconst SelectGroup = SelectPrimitive.Group;\nconst SelectValue = SelectPrimitive.Value;\n\n/**\n * Select trigger button component that displays the current selection and opens the dropdown\n *\n * Features comprehensive styling with validation states, focus management, and accessibility support.\n * Uses design tokens for consistent theming across the application.\n *\n * @param validationStyleEnabled - Enables automatic success/error styling based on form validation state\n * @param className - Additional CSS classes for custom styling\n * @param children - Content to display inside the trigger (typically SelectValue)\n *\n * @example\n * ```tsx\n * <Select.Trigger validationStyleEnabled>\n * <Select.Value placeholder=\"Choose option...\" />\n * </Select.Trigger>\n * ```\n */\nconst SelectTrigger: FC<\n ComponentProps<typeof SelectPrimitive.Trigger> & {\n /**\n * Enables success/error border styling based on HTML5 validation state\n * @default false\n * @example\n * ```tsx\n * <Select.Trigger validationStyleEnabled>\n * <Select.Value placeholder=\"Required field\" />\n * </Select.Trigger>\n * ```\n */\n validationStyleEnabled?: boolean;\n }\n> = ({ validationStyleEnabled = false, className, children, ...props }) => (\n <SelectPrimitive.Trigger\n suppressHydrationWarning\n className={cn(\n // Base layout and typography\n 'flex w-full cursor-pointer items-center justify-between whitespace-nowrap',\n 'select-text text-base shadow-none outline-none md:text-sm',\n\n // Corner shape\n 'rounded-xl [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-2xl',\n\n // Spacing\n 'px-2 py-3 md:py-2',\n\n // Background and text\n 'bg-neutral-50 dark:bg-neutral-950',\n 'text-text',\n\n // Focus ring\n 'ring-0',\n 'focus-visible:outline-none',\n 'focus-visible:ring-3',\n 'focus-visible:ring-neutral-200',\n 'dark:focus-visible:ring-neutral-500',\n\n 'focus-visible:ring-offset-white',\n 'dark:focus-visible:ring-offset-neutral-500',\n\n // Remove box-shadow\n '[box-shadow:none] focus:[box-shadow:none]',\n\n // States\n 'disabled:cursor-not-allowed disabled:opacity-50',\n 'aria-invalid:border-error',\n '[&>span]:line-clamp-1',\n\n // Validation styles\n validationStyleEnabled && 'valid:border-success invalid:border-error',\n\n className\n )}\n {...props}\n >\n {children}\n <SelectPrimitive.Icon asChild>\n <ChevronsUpDown className=\"size-4 opacity-50\" />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n);\n\n/**\n * Scroll up button for select content with long lists\n *\n * Automatically appears when content is scrollable upward, providing intuitive navigation\n * for users with large option lists.\n *\n * @param className - Additional CSS classes for custom styling\n */\nconst SelectScrollUpButton: FC<\n ComponentProps<typeof SelectPrimitive.ScrollUpButton>\n> = ({ className, ...props }) => (\n <SelectPrimitive.ScrollUpButton\n className={cn(\n 'flex cursor-default items-center justify-center py-1',\n className\n )}\n {...props}\n >\n <ChevronUpIcon />\n </SelectPrimitive.ScrollUpButton>\n);\n\n/**\n * Scroll down button for select content with long lists\n *\n * Automatically appears when content is scrollable downward, providing clear visual\n * indication of additional options below the current view.\n *\n * @param className - Additional CSS classes for custom styling\n */\nconst SelectScrollDownButton: FC<\n ComponentProps<typeof SelectPrimitive.ScrollDownButton>\n> = ({ className, ...props }) => (\n <SelectPrimitive.ScrollDownButton\n className={cn(\n 'flex cursor-default items-center justify-center py-1',\n className\n )}\n {...props}\n >\n <ChevronDownIcon />\n </SelectPrimitive.ScrollDownButton>\n);\n\n/**\n * Select dropdown content container with positioning and animation\n *\n * Provides the dropdown interface containing all selectable options. Features smooth\n * animations, flexible positioning strategies, and responsive design for optimal UX.\n *\n * @param position - Positioning strategy for the dropdown content\n * @param className - Additional CSS classes for custom styling\n * @param children - Select items, labels, and separators\n *\n * @example\n * ```tsx\n * <Select.Content position={SelectContentPosition.POPPER}>\n * <Select.Item value=\"option1\">Option 1</Select.Item>\n * <Select.Item value=\"option2\">Option 2</Select.Item>\n * </Select.Content>\n * ```\n */\nexport const SelectContent: FC<\n ComponentProps<typeof SelectPrimitive.Content>\n> = ({\n className,\n children,\n position = SelectContentPosition.POPPER,\n ...props\n}) => (\n <SelectPrimitive.Portal>\n <SelectPrimitive.Content\n className={cn(\n // Base styles\n 'relative z-50 max-h-96 min-w-32 overflow-hidden',\n 'rounded-xl shadow-md',\n\n // Background and text\n 'bg-white dark:bg-neutral-950',\n 'text-text',\n\n // Border\n 'border border-neutral-200 dark:border-neutral-800',\n\n // Animations\n 'data-[state=closed]:animate-out data-[state=open]:animate-in',\n 'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',\n 'data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95',\n 'data-[side=bottom]:slide-in-from-top-2',\n 'data-[side=left]:slide-in-from-right-2',\n 'data-[side=right]:slide-in-from-left-2',\n 'data-[side=top]:slide-in-from-bottom-2',\n\n // Positioning adjustments\n position === 'popper' &&\n 'data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=bottom]:translate-y-1 data-[side=top]:-translate-y-1',\n\n className\n )}\n position={position}\n {...props}\n >\n <SelectScrollUpButton />\n <SelectPrimitive.Viewport\n className={cn(\n 'p-1',\n position === 'popper' &&\n 'h-(--radix-select-trigger-height) w-full min-w-(--radix-select-trigger-width)'\n )}\n >\n {children}\n </SelectPrimitive.Viewport>\n <SelectScrollDownButton />\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n);\n\n/**\n * Label component for grouping select options\n *\n * Provides semantic grouping and visual organization of related options within\n * the select dropdown. Enhances accessibility and user experience.\n *\n * @param className - Additional CSS classes for custom styling\n *\n * @example\n * ```tsx\n * <Select.Content>\n * <Select.Label>Fruits</Select.Label>\n * <Select.Item value=\"apple\">Apple</Select.Item>\n * <Select.Item value=\"banana\">Banana</Select.Item>\n * <Select.Separator />\n * <Select.Label>Vegetables</Select.Label>\n * <Select.Item value=\"carrot\">Carrot</Select.Item>\n * </Select.Content>\n * ```\n */\nexport const SelectLabel: FC<ComponentProps<typeof SelectPrimitive.Label>> = ({\n className,\n ...props\n}) => (\n <SelectPrimitive.Label\n className={cn('px-1 py-0.5 font-semibold text-sm', className)}\n {...props}\n />\n);\n\n/**\n * Individual selectable item within the dropdown\n *\n * Represents a single option that users can select. Features hover states,\n * selection indicators, and keyboard navigation support for accessible interaction.\n *\n * @param className - Additional CSS classes for custom styling\n * @param children - The display text/content for the option\n *\n * @example\n * ```tsx\n * <Select.Item value=\"dark-mode\">\n * 🌙 Dark Mode\n * </Select.Item>\n * ```\n */\nconst SelectItem: FC<ComponentProps<typeof SelectPrimitive.Item>> = ({\n className,\n children,\n ...props\n}) => (\n <SelectPrimitive.Item\n className={cn(\n 'relative flex w-full cursor-pointer select-none items-center rounded-lg py-1.5 pr-8 pl-2 text-sm outline-hidden focus:bg-neutral/10 data-disabled:pointer-events-none data-disabled:opacity-50',\n className\n )}\n {...props}\n >\n <span className=\"absolute right-2 flex size-3.5 items-center justify-center\">\n <SelectPrimitive.ItemIndicator>\n <CheckIcon className=\"size-4\" />\n </SelectPrimitive.ItemIndicator>\n </span>\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n </SelectPrimitive.Item>\n);\n\n/**\n * Visual separator for grouping options in the dropdown\n *\n * Creates clear visual division between groups of related options,\n * improving readability and organization in complex select menus.\n *\n * @param className - Additional CSS classes for custom styling\n *\n * @example\n * ```tsx\n * <Select.Content>\n * <Select.Item value=\"recent\">Recent Files</Select.Item>\n * <Select.Separator />\n * <Select.Item value=\"all\">All Files</Select.Item>\n * </Select.Content>\n * ```\n */\nexport const SelectSeparator: FC<\n ComponentProps<typeof SelectPrimitive.Separator>\n> = ({ className, ...props }) => (\n <SelectPrimitive.Separator\n className={cn(\n '-mx-1 my-1 h-px',\n 'bg-neutral-200 dark:bg-neutral-800',\n className\n )}\n {...props}\n />\n);\n\n/**\n * Type definition for the compound Select component with all subcomponents\n */\ntype SelectType = typeof SelectRoot & {\n /** Group container for organizing related options */\n Group: typeof SelectGroup;\n /** Value display component for the trigger */\n Value: typeof SelectValue;\n /** Trigger button that opens the dropdown */\n Trigger: typeof SelectTrigger;\n /** Scroll up button for long lists */\n ScrollUpButton: typeof SelectScrollUpButton;\n /** Scroll down button for long lists */\n ScrollDownButton: typeof SelectScrollDownButton;\n /** Dropdown content container */\n Content: typeof SelectContent;\n /** Label component for option groups */\n Label: typeof SelectLabel;\n /** Individual selectable item */\n Item: typeof SelectItem;\n /** Visual separator between option groups */\n Separator: typeof SelectSeparator;\n};\n\n/**\n * Select - A comprehensive dropdown selection component\n *\n * A fully-featured select component built on Radix UI primitives with extensive customization,\n * accessibility features, and design system integration. Supports single selection with\n * keyboard navigation, validation states, and flexible content positioning.\n *\n * ## Key Features\n * - **Accessibility First**: Full keyboard navigation, screen reader support, and ARIA attributes\n * - **Flexible Positioning**: Multiple positioning strategies for optimal dropdown placement\n * - **Validation Integration**: Built-in support for form validation with visual feedback\n * - **Design System**: Consistent theming with design tokens and style variants\n * - **Responsive Design**: Works seamlessly across desktop and mobile devices\n * - **Rich Content**: Support for icons, separators, labels, and complex option layouts\n *\n * ## Use Cases\n * - Form field selections (theme, language, category)\n * - Settings and configuration options\n * - Filter and sort controls\n * - User preference selections\n * - Any single-choice dropdown interface\n *\n * ## Accessibility\n * - **Keyboard Navigation**: Arrow keys, Enter, Escape, and Home/End support\n * - **Screen Readers**: Proper ARIA labels and state announcements\n * - **Focus Management**: Intuitive focus flow and visual indicators\n * - **High Contrast**: Supports system high contrast modes\n *\n * ## Architecture\n * The Select component follows a compound component pattern with the following structure:\n * - `Select` (root): Manages state and provides context\n * - `Select.Trigger`: Button that displays current value and opens dropdown\n * - `Select.Value`: Displays the selected value with placeholder support\n * - `Select.Content`: Container for the dropdown options\n * - `Select.Item`: Individual selectable options\n * - `Select.Label`: Group labels for organizing options\n * - `Select.Separator`: Visual dividers between option groups\n *\n * @example\n * Basic usage with simple options:\n * ```tsx\n * <Select defaultValue=\"system\">\n * <Select.Trigger>\n * <Select.Value placeholder=\"Choose theme...\" />\n * </Select.Trigger>\n * <Select.Content>\n * <Select.Item value=\"light\">☀️ Light</Select.Item>\n * <Select.Item value=\"dark\">🌙 Dark</Select.Item>\n * <Select.Item value=\"system\">⚙️ System</Select.Item>\n * </Select.Content>\n * </Select>\n * ```\n *\n * @example\n * Advanced usage with groups and labels:\n * ```tsx\n * <Select>\n * <Select.Trigger validationStyleEnabled>\n * <Select.Value placeholder=\"Select category...\" />\n * </Select.Trigger>\n * <Select.Content>\n * <Select.Label>Web Technologies</Select.Label>\n * <Select.Item value=\"react\">React</Select.Item>\n * <Select.Item value=\"vue\">Vue</Select.Item>\n * <Select.Separator />\n * <Select.Label>Mobile</Select.Label>\n * <Select.Item value=\"react-native\">React Native</Select.Item>\n * <Select.Item value=\"flutter\">Flutter</Select.Item>\n * </Select.Content>\n * </Select>\n * ```\n *\n * @example\n * Form integration with validation:\n * ```tsx\n * <form>\n * <Select required name=\"country\">\n * <Select.Trigger validationStyleEnabled aria-invalid={hasError}>\n * <Select.Value placeholder=\"Select country...\" />\n * </Select.Trigger>\n * <Select.Content position={SelectContentPosition.ITEM_ALIGNED}>\n * <Select.Item value=\"us\">United States</Select.Item>\n * <Select.Item value=\"ca\">Canada</Select.Item>\n * <Select.Item value=\"uk\">United Kingdom</Select.Item>\n * </Select.Content>\n * </Select>\n * </form>\n * ```\n */\nexport const Select = SelectRoot as SelectType;\nSelect.Group = SelectGroup;\nSelect.Value = SelectValue;\nSelect.Trigger = SelectTrigger;\nSelect.ScrollUpButton = SelectScrollUpButton;\nSelect.ScrollDownButton = SelectScrollDownButton;\nSelect.Content = SelectContent;\nSelect.Label = SelectLabel;\nSelect.Item = SelectItem;\nSelect.Separator = SelectSeparator;\n"],"mappings":";;;;;;;;;;;;;AAiBA,IAAY,wBAAL;;CAEL;;CAEA;;KACD;AAED,MAAM,aAAa,gBAAgB;AACnC,MAAM,cAAc,gBAAgB;AACpC,MAAM,cAAc,gBAAgB;;;;;;;;;;;;;;;;;;AAmBpC,MAAM,iBAcD,EAAE,yBAAyB,OAAO,WAAW,UAAU,GAAG,YAC7D,qBAAC,gBAAgB,SAAjB;CACE;CACA,WAAW,GAET,6EACA,6DAGA,mFAGA,qBAGA,qCACA,aAGA,UACA,8BACA,wBACA,kCACA,uCAEA,mCACA,8CAGA,6CAGA,mDACA,6BACA,yBAGA,0BAA0B,6CAE1B,UACD;CACD,GAAI;WAxCN,CA0CG,UACD,oBAAC,gBAAgB,MAAjB;EAAsB;YACpB,oBAAC,gBAAD,EAAgB,WAAU,qBAAsB;EAC3B,EACC;;;;;;;;;;AAW5B,MAAM,wBAED,EAAE,WAAW,GAAG,YACnB,oBAAC,gBAAgB,gBAAjB;CACE,WAAW,GACT,wDACA,UACD;CACD,GAAI;WAEJ,oBAAC,eAAD,EAAiB;CACc;;;;;;;;;AAWnC,MAAM,0BAED,EAAE,WAAW,GAAG,YACnB,oBAAC,gBAAgB,kBAAjB;CACE,WAAW,GACT,wDACA,UACD;CACD,GAAI;WAEJ,oBAAC,iBAAD,EAAmB;CACc;;;;;;;;;;;;;;;;;;;AAqBrC,MAAa,iBAER,EACH,WACA,UACA,qBACA,GAAG,YAEH,oBAAC,gBAAgB,QAAjB,YACE,qBAAC,gBAAgB,SAAjB;CACE,WAAW,GAET,mDACA,wBAGA,gCACA,aAGA,qDAGA,gEACA,8DACA,gEACA,0CACA,0CACA,0CACA,0CAGA,aAAa,YACX,mIAEF,UACD;CACS;CACV,GAAI;WA7BN;EA+BE,oBAAC,sBAAD,EAAwB;EACxB,oBAAC,gBAAgB,UAAjB;GACE,WAAW,GACT,OACA,aAAa,YACX,gFACH;GAEA;GACwB;EAC3B,oBAAC,wBAAD,EAA0B;EACF;IACH;;;;;;;;;;;;;;;;;;;;;AAuB3B,MAAa,eAAiE,EAC5E,WACA,GAAG,YAEH,oBAAC,gBAAgB,OAAjB;CACE,WAAW,GAAG,qCAAqC,UAAU;CAC7D,GAAI;CACJ;;;;;;;;;;;;;;;;;AAmBJ,MAAM,cAA+D,EACnE,WACA,UACA,GAAG,YAEH,qBAAC,gBAAgB,MAAjB;CACE,WAAW,GACT,kMACA,UACD;CACD,GAAI;WALN,CAOE,oBAAC,QAAD;EAAM,WAAU;YACd,oBAAC,gBAAgB,eAAjB,YACE,oBAAC,WAAD,EAAW,WAAU,UAAW,GACF;EAC3B,GACP,oBAAC,gBAAgB,UAAjB,EAA2B,UAAoC,EAC1C;;;;;;;;;;;;;;;;;;;AAoBzB,MAAa,mBAER,EAAE,WAAW,GAAG,YACnB,oBAAC,gBAAgB,WAAjB;CACE,WAAW,GACT,mBACA,sCACA,UACD;CACD,GAAI;CACJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoHJ,MAAa,SAAS;AACtB,OAAO,QAAQ;AACf,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,OAAO,iBAAiB;AACxB,OAAO,mBAAmB;AAC1B,OAAO,UAAU;AACjB,OAAO,QAAQ;AACf,OAAO,OAAO;AACd,OAAO,YAAY"}
@@ -1 +1 @@
1
- {"version":3,"file":"SwitchSelector.mjs","names":[],"sources":["../../../../src/components/SwitchSelector/SwitchSelector.tsx"],"sourcesContent":["'use client';\n\nimport { cn } from '@utils/cn';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport type { HTMLAttributes, ReactNode } from 'react';\nimport { useSwitchSelector } from './useSwitchSelector';\n\nexport type SwitchSelectorChoice<T = boolean> = {\n content: ReactNode;\n value: T;\n} & HTMLAttributes<HTMLButtonElement>;\nexport type SwitchSelectorChoices<T> = SwitchSelectorChoice<T>[];\n\nexport const defaultChoices: SwitchSelectorChoices<boolean> = [\n { content: 'Off', value: false },\n { content: 'On', value: true },\n];\n\nexport enum SwitchSelectorColor {\n PRIMARY = 'primary',\n SECONDARY = 'secondary',\n DESTRUCTIVE = 'destructive',\n NEUTRAL = 'neutral',\n LIGHT = 'light',\n DARK = 'dark',\n TEXT = 'text',\n}\n\nexport enum SwitchSelectorSize {\n SM = 'sm',\n MD = 'md',\n LG = 'lg',\n}\n\nexport type SwitchSelectorBaseProps<T = boolean> = {\n choices?: SwitchSelectorChoices<T>;\n value?: T;\n defaultValue?: T;\n onChange?: (choice: T) => void;\n className?: string;\n itemClassName?: string;\n hoverable?: boolean;\n disabled?: boolean;\n [key: string]: any;\n};\n\nexport type SwitchSelectorProps<T = boolean> = SwitchSelectorBaseProps<T> &\n VariantProps<typeof switchSelectorVariant> &\n VariantProps<typeof choiceVariant>;\n\nexport const switchSelectorVariant = cva(\n 'flex h-fit w-fit cursor-pointer flex-row gap-2 rounded-full border-[1.3px] p-[1.5px]',\n {\n variants: {\n color: {\n [`${SwitchSelectorColor.PRIMARY}`]: 'border-primary text-primary',\n [`${SwitchSelectorColor.SECONDARY}`]: 'border-secondary text-secondary',\n [`${SwitchSelectorColor.DESTRUCTIVE}`]:\n 'border-destructive bg-destructive text-destructive',\n [`${SwitchSelectorColor.NEUTRAL}`]: 'border-neutral text-neutral',\n [`${SwitchSelectorColor.LIGHT}`]: 'border-white text-white',\n [`${SwitchSelectorColor.DARK}`]: 'border-neutral-800 text-neutral-800',\n [`${SwitchSelectorColor.TEXT}`]: 'border-text text-text',\n },\n disabled: {\n true: 'cursor-not-allowed opacity-50',\n false: '',\n },\n },\n defaultVariants: {\n color: `${SwitchSelectorColor.PRIMARY}`,\n disabled: false,\n },\n }\n);\n\nexport const choiceVariant = cva(\n 'z-1 flex-1 cursor-pointer font-medium text-sm transition-all duration-300 ease-in-out aria-selected:cursor-default data-[indicator=true]:text-text-opposite motion-reduce:transition-none',\n {\n variants: {\n size: {\n [`${SwitchSelectorSize.SM}`]: 'px-2 py-1 text-xs',\n [`${SwitchSelectorSize.MD}`]: 'p-2 text-sm',\n [`${SwitchSelectorSize.LG}`]: 'p-4 text-base',\n },\n },\n defaultVariants: {\n size: `${SwitchSelectorSize.MD}`,\n },\n }\n);\n\nexport const indicatorVariant = cva(\n 'absolute top-0 z-0 h-full w-auto rounded-full transition-all duration-300 ease-in-out motion-reduce:transition-none',\n {\n variants: {\n color: {\n [`${SwitchSelectorColor.PRIMARY}`]:\n 'bg-primary data-[indicator=true]:text-text',\n [`${SwitchSelectorColor.SECONDARY}`]:\n 'bg-secondary data-[indicator=true]:text-text',\n [`${SwitchSelectorColor.DESTRUCTIVE}`]:\n 'bg-destructive data-[indicator=true]:text-text',\n [`${SwitchSelectorColor.NEUTRAL}`]:\n 'bg-neutral data-[indicator=true]:text-white',\n [`${SwitchSelectorColor.LIGHT}`]:\n 'bg-white data-[indicator=true]:text-black',\n [`${SwitchSelectorColor.DARK}`]:\n 'bg-neutral-800 data-[indicator=true]:text-white',\n [`${SwitchSelectorColor.TEXT}`]:\n 'bg-text data-[indicator=true]:text-text-opposite',\n },\n },\n }\n);\n\n/**\n * Component that allows the user to select one of the provided choices.\n * This component is horizontal.\n */\nexport const SwitchSelector = <T,>(props: SwitchSelectorProps<T>) => {\n const {\n choices = defaultChoices as SwitchSelectorChoices<T>,\n color = SwitchSelectorColor.PRIMARY,\n size = SwitchSelectorSize.MD,\n className,\n itemClassName,\n ...baseProps\n } = props;\n\n const {\n selectedIndex,\n indicatorIndex,\n handleChange,\n optionsRefs,\n indicatorRef,\n choiceIndicatorPosition,\n setHoveredIndex,\n disabled,\n } = useSwitchSelector(\n {\n choices,\n value: props.value,\n defaultValue: props.defaultValue,\n onChange: props.onChange,\n hoverable: props.hoverable,\n disabled: props.disabled,\n },\n 'horizontal'\n );\n\n return (\n <div\n className={switchSelectorVariant({\n color,\n disabled,\n className,\n })}\n role=\"tablist\"\n aria-disabled={disabled ? 'true' : undefined}\n >\n <div className=\"relative flex h-full w-full flex-row items-center justify-center\">\n {choices.map((choice, index) => {\n const { content, value, ...buttonProps } = choice;\n\n const isKeyOfKey =\n typeof value === 'string' || typeof value === 'number';\n\n const isSelected = index === selectedIndex;\n const isIndicatorOwner = index === indicatorIndex;\n\n return (\n <button\n {...buttonProps}\n className={cn(\n choiceVariant({\n size,\n }),\n disabled && 'cursor-not-allowed',\n itemClassName\n )}\n key={isKeyOfKey ? value : index}\n role=\"tab\"\n onClick={() => handleChange(value)}\n aria-selected={isSelected ? 'true' : undefined}\n data-indicator={isIndicatorOwner ? 'true' : undefined}\n disabled={disabled}\n tabIndex={isSelected ? 0 : -1}\n ref={(el) => {\n optionsRefs.current[index] = el!;\n }}\n onMouseEnter={() => !disabled && setHoveredIndex(index)}\n onMouseLeave={() => !disabled && setHoveredIndex(null)}\n >\n {content}\n </button>\n );\n })}\n\n {choiceIndicatorPosition && (\n <div\n className={cn(\n indicatorVariant({\n color,\n })\n )}\n style={choiceIndicatorPosition}\n ref={indicatorRef}\n />\n )}\n </div>\n </div>\n );\n};\n"],"mappings":";;;;;;;;;AAaA,MAAa,iBAAiD,CAC5D;CAAE,SAAS;CAAO,OAAO;CAAO,EAChC;CAAE,SAAS;CAAM,OAAO;CAAM,CAC/B;AAED,IAAY,sBAAL;AACL;AACA;AACA;AACA;AACA;AACA;AACA;;KACD;AAED,IAAY,qBAAL;AACL;AACA;AACA;;KACD;AAkBD,MAAa,wBAAwB,IACnC,wFACA;CACE,UAAU;EACR,OAAO;IACJ,YAAmC;IACnC,cAAqC;IACrC,gBACC;IACD,YAAmC;IACnC,UAAiC;IACjC,SAAgC;IAChC,SAAgC;GAClC;EACD,UAAU;GACR,MAAM;GACN,OAAO;GACR;EACF;CACD,iBAAiB;EACf,OAAO;EACP,UAAU;EACX;CACF,CACF;AAED,MAAa,gBAAgB,IAC3B,6LACA;CACE,UAAU,EACR,MAAM;GACH,OAA6B;GAC7B,OAA6B;GAC7B,OAA6B;EAC/B,EACF;CACD,iBAAiB,EACf,MAAM,MACP;CACF,CACF;AAED,MAAa,mBAAmB,IAC9B,uHACA,EACE,UAAU,EACR,OAAO;EACJ,YACC;EACD,cACC;EACD,gBACC;EACD,YACC;EACD,UACC;EACD,SACC;EACD,SACC;CACH,EACF,EACF,CACF;;;;;AAMD,MAAa,kBAAsB,UAAkC;CACnE,MAAM,EACJ,UAAU,gBACV,mBACA,aACA,WACA,eACA,GAAG,cACD;CAEJ,MAAM,EACJ,eACA,gBACA,cACA,aACA,cACA,yBACA,iBACA,aACE,kBACF;EACE;EACA,OAAO,MAAM;EACb,cAAc,MAAM;EACpB,UAAU,MAAM;EAChB,WAAW,MAAM;EACjB,UAAU,MAAM;EACjB,EACD,aACD;AAED,QACE,oBAAC,OAAD;EACE,WAAW,sBAAsB;GAC/B;GACA;GACA;GACD,CAAC;EACF,MAAK;EACL,iBAAe,WAAW,SAAS;YAEnC,qBAAC,OAAD;GAAK,WAAU;aAAf,CACG,QAAQ,KAAK,QAAQ,UAAU;IAC9B,MAAM,EAAE,SAAS,OAAO,GAAG,gBAAgB;IAE3C,MAAM,aACJ,OAAO,UAAU,YAAY,OAAO,UAAU;IAEhD,MAAM,aAAa,UAAU;IAC7B,MAAM,mBAAmB,UAAU;AAEnC,WACE,8BAAC,UAAD;KACE,GAAI;KACJ,WAAW,GACT,cAAc,EACZ,MACD,CAAC,EACF,YAAY,sBACZ,cACD;KACD,KAAK,aAAa,QAAQ;KAC1B,MAAK;KACL,eAAe,aAAa,MAAM;KAClC,iBAAe,aAAa,SAAS;KACrC,kBAAgB,mBAAmB,SAAS;KAClC;KACV,UAAU,aAAa,IAAI;KAC3B,MAAM,OAAO;AACX,kBAAY,QAAQ,SAAS;;KAE/B,oBAAoB,CAAC,YAAY,gBAAgB,MAAM;KACvD,oBAAoB,CAAC,YAAY,gBAAgB,KAAK;KAG/C,EADN,QACM;KAEX,EAED,2BACC,oBAAC,OAAD;IACE,WAAW,GACT,iBAAiB,EACf,OACD,CAAC,CACH;IACD,OAAO;IACP,KAAK;IACL,EAEA;;EACF"}
1
+ {"version":3,"file":"SwitchSelector.mjs","names":[],"sources":["../../../../src/components/SwitchSelector/SwitchSelector.tsx"],"sourcesContent":["'use client';\n\nimport { cn } from '@utils/cn';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport type { HTMLAttributes, ReactNode } from 'react';\nimport { useSwitchSelector } from './useSwitchSelector';\n\nexport type SwitchSelectorChoice<T = boolean> = {\n content: ReactNode;\n value: T;\n} & HTMLAttributes<HTMLButtonElement>;\nexport type SwitchSelectorChoices<T> = SwitchSelectorChoice<T>[];\n\nexport const defaultChoices: SwitchSelectorChoices<boolean> = [\n { content: 'Off', value: false },\n { content: 'On', value: true },\n];\n\nexport enum SwitchSelectorColor {\n PRIMARY = 'primary',\n SECONDARY = 'secondary',\n DESTRUCTIVE = 'destructive',\n NEUTRAL = 'neutral',\n LIGHT = 'light',\n DARK = 'dark',\n TEXT = 'text',\n}\n\nexport enum SwitchSelectorSize {\n SM = 'sm',\n MD = 'md',\n LG = 'lg',\n}\n\nexport type SwitchSelectorBaseProps<T = boolean> = {\n choices?: SwitchSelectorChoices<T>;\n value?: T;\n defaultValue?: T;\n onChange?: (choice: T) => void;\n className?: string;\n itemClassName?: string;\n hoverable?: boolean;\n disabled?: boolean;\n [key: string]: any;\n};\n\nexport type SwitchSelectorProps<T = boolean> = SwitchSelectorBaseProps<T> &\n VariantProps<typeof switchSelectorVariant> &\n VariantProps<typeof choiceVariant>;\n\nexport const switchSelectorVariant = cva(\n 'flex h-fit w-fit cursor-pointer flex-row gap-2 rounded-full border-[1.3px] p-[1.5px]',\n {\n variants: {\n color: {\n [`${SwitchSelectorColor.PRIMARY}`]: 'border-primary text-primary',\n [`${SwitchSelectorColor.SECONDARY}`]: 'border-secondary text-secondary',\n [`${SwitchSelectorColor.DESTRUCTIVE}`]:\n 'border-destructive bg-destructive text-destructive',\n [`${SwitchSelectorColor.NEUTRAL}`]: 'border-neutral text-neutral',\n [`${SwitchSelectorColor.LIGHT}`]: 'border-white text-white',\n [`${SwitchSelectorColor.DARK}`]: 'border-neutral-800 text-neutral-800',\n [`${SwitchSelectorColor.TEXT}`]: 'border-text text-text',\n },\n disabled: {\n true: 'cursor-not-allowed opacity-50',\n false: '',\n },\n },\n defaultVariants: {\n color: `${SwitchSelectorColor.PRIMARY}`,\n disabled: false,\n },\n }\n);\n\nexport const choiceVariant = cva(\n 'z-1 flex-1 cursor-pointer font-medium text-sm transition-all duration-300 ease-in-out aria-selected:cursor-default data-[indicator=true]:text-text-opposite motion-reduce:transition-none',\n {\n variants: {\n size: {\n [`${SwitchSelectorSize.SM}`]: 'px-2 py-1 text-xs',\n [`${SwitchSelectorSize.MD}`]: 'p-2 text-sm',\n [`${SwitchSelectorSize.LG}`]: 'p-4 text-base',\n },\n },\n defaultVariants: {\n size: `${SwitchSelectorSize.MD}`,\n },\n }\n);\n\nexport const indicatorVariant = cva(\n 'absolute top-0 z-0 h-full w-auto rounded-full transition-all duration-300 ease-in-out motion-reduce:transition-none',\n {\n variants: {\n color: {\n [`${SwitchSelectorColor.PRIMARY}`]:\n 'bg-primary data-[indicator=true]:text-text',\n [`${SwitchSelectorColor.SECONDARY}`]:\n 'bg-secondary data-[indicator=true]:text-text',\n [`${SwitchSelectorColor.DESTRUCTIVE}`]:\n 'bg-destructive data-[indicator=true]:text-text',\n [`${SwitchSelectorColor.NEUTRAL}`]:\n 'bg-neutral data-[indicator=true]:text-white',\n [`${SwitchSelectorColor.LIGHT}`]:\n 'bg-white data-[indicator=true]:text-black',\n [`${SwitchSelectorColor.DARK}`]:\n 'bg-neutral-800 data-[indicator=true]:text-white',\n [`${SwitchSelectorColor.TEXT}`]:\n 'bg-text data-[indicator=true]:text-text-opposite',\n },\n },\n }\n);\n\n/**\n * Component that allows the user to select one of the provided choices.\n * This component is horizontal.\n */\nexport const SwitchSelector = <T,>(props: SwitchSelectorProps<T>) => {\n const {\n choices = defaultChoices as SwitchSelectorChoices<T>,\n color = SwitchSelectorColor.PRIMARY,\n size = SwitchSelectorSize.MD,\n className,\n itemClassName,\n ...baseProps\n } = props;\n\n const {\n selectedIndex,\n indicatorIndex,\n handleChange,\n optionsRefs,\n indicatorRef,\n choiceIndicatorPosition,\n setHoveredIndex,\n disabled,\n } = useSwitchSelector(\n {\n choices,\n value: props.value,\n defaultValue: props.defaultValue,\n onChange: props.onChange,\n hoverable: props.hoverable,\n disabled: props.disabled,\n },\n 'horizontal'\n );\n\n return (\n <div\n className={switchSelectorVariant({\n color,\n disabled,\n className,\n })}\n role=\"tablist\"\n aria-disabled={disabled ? 'true' : undefined}\n >\n <div className=\"relative flex h-full w-full flex-row items-center justify-center\">\n {choices.map((choice, index) => {\n const { content, value, ...buttonProps } = choice;\n\n const isKeyOfKey =\n typeof value === 'string' || typeof value === 'number';\n\n const isSelected = index === selectedIndex;\n const isIndicatorOwner = index === indicatorIndex;\n\n return (\n <button\n {...buttonProps}\n className={cn(\n choiceVariant({\n size,\n }),\n disabled && 'cursor-not-allowed',\n itemClassName\n )}\n key={isKeyOfKey ? value : index}\n role=\"tab\"\n onClick={() => handleChange(value)}\n aria-selected={isSelected ? 'true' : undefined}\n data-indicator={isIndicatorOwner ? 'true' : undefined}\n disabled={disabled}\n tabIndex={isSelected ? 0 : -1}\n ref={(el) => {\n optionsRefs.current[index] = el!;\n }}\n onMouseEnter={() => !disabled && setHoveredIndex(index)}\n onMouseLeave={() => !disabled && setHoveredIndex(null)}\n >\n {content}\n </button>\n );\n })}\n\n {choiceIndicatorPosition && (\n <div\n className={cn(\n indicatorVariant({\n color,\n })\n )}\n style={choiceIndicatorPosition}\n ref={indicatorRef}\n />\n )}\n </div>\n </div>\n );\n};\n"],"mappings":";;;;;;;;;AAaA,MAAa,iBAAiD,CAC5D;CAAE,SAAS;CAAO,OAAO;CAAO,EAChC;CAAE,SAAS;CAAM,OAAO;CAAM,CAC/B;AAED,IAAY,sBAAL;CACL;CACA;CACA;CACA;CACA;CACA;CACA;;KACD;AAED,IAAY,qBAAL;CACL;CACA;CACA;;KACD;AAkBD,MAAa,wBAAwB,IACnC,wFACA;CACE,UAAU;EACR,OAAO;IACJ,YAAmC;IACnC,cAAqC;IACrC,gBACC;IACD,YAAmC;IACnC,UAAiC;IACjC,SAAgC;IAChC,SAAgC;GAClC;EACD,UAAU;GACR,MAAM;GACN,OAAO;GACR;EACF;CACD,iBAAiB;EACf,OAAO;EACP,UAAU;EACX;CACF,CACF;AAED,MAAa,gBAAgB,IAC3B,6LACA;CACE,UAAU,EACR,MAAM;GACH,OAA6B;GAC7B,OAA6B;GAC7B,OAA6B;EAC/B,EACF;CACD,iBAAiB,EACf,MAAM,MACP;CACF,CACF;AAED,MAAa,mBAAmB,IAC9B,uHACA,EACE,UAAU,EACR,OAAO;EACJ,YACC;EACD,cACC;EACD,gBACC;EACD,YACC;EACD,UACC;EACD,SACC;EACD,SACC;CACH,EACF,EACF,CACF;;;;;AAMD,MAAa,kBAAsB,UAAkC;CACnE,MAAM,EACJ,UAAU,gBACV,mBACA,aACA,WACA,eACA,GAAG,cACD;CAEJ,MAAM,EACJ,eACA,gBACA,cACA,aACA,cACA,yBACA,iBACA,aACE,kBACF;EACE;EACA,OAAO,MAAM;EACb,cAAc,MAAM;EACpB,UAAU,MAAM;EAChB,WAAW,MAAM;EACjB,UAAU,MAAM;EACjB,EACD,aACD;CAED,OACE,oBAAC,OAAD;EACE,WAAW,sBAAsB;GAC/B;GACA;GACA;GACD,CAAC;EACF,MAAK;EACL,iBAAe,WAAW,SAAS;YAEnC,qBAAC,OAAD;GAAK,WAAU;aAAf,CACG,QAAQ,KAAK,QAAQ,UAAU;IAC9B,MAAM,EAAE,SAAS,OAAO,GAAG,gBAAgB;IAE3C,MAAM,aACJ,OAAO,UAAU,YAAY,OAAO,UAAU;IAEhD,MAAM,aAAa,UAAU;IAC7B,MAAM,mBAAmB,UAAU;IAEnC,OACE,8BAAC,UAAD;KACE,GAAI;KACJ,WAAW,GACT,cAAc,EACZ,MACD,CAAC,EACF,YAAY,sBACZ,cACD;KACD,KAAK,aAAa,QAAQ;KAC1B,MAAK;KACL,eAAe,aAAa,MAAM;KAClC,iBAAe,aAAa,SAAS;KACrC,kBAAgB,mBAAmB,SAAS;KAClC;KACV,UAAU,aAAa,IAAI;KAC3B,MAAM,OAAO;MACX,YAAY,QAAQ,SAAS;;KAE/B,oBAAoB,CAAC,YAAY,gBAAgB,MAAM;KACvD,oBAAoB,CAAC,YAAY,gBAAgB,KAAK;KAG/C,EADN,QACM;KAEX,EAED,2BACC,oBAAC,OAAD;IACE,WAAW,GACT,iBAAiB,EACf,OACD,CAAC,CACH;IACD,OAAO;IACP,KAAK;IACL,EAEA;;EACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"VerticalSwitchSelector.mjs","names":[],"sources":["../../../../src/components/SwitchSelector/VerticalSwitchSelector.tsx"],"sourcesContent":["'use client';\n\nimport { cn } from '@utils/cn';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport {\n defaultChoices,\n type SwitchSelectorBaseProps,\n type SwitchSelectorChoices,\n SwitchSelectorColor,\n SwitchSelectorSize,\n} from './SwitchSelector';\nimport { useSwitchSelector } from './useSwitchSelector';\n\nconst verticalSwitchSelectorVariant = cva(\n 'flex h-fit w-fit cursor-pointer flex-col gap-2 rounded-2xl border-[1.3px] p-1',\n {\n variants: {\n color: {\n [`${SwitchSelectorColor.PRIMARY}`]: 'border-primary text-primary',\n [`${SwitchSelectorColor.SECONDARY}`]: 'border-secondary text-secondary',\n [`${SwitchSelectorColor.DESTRUCTIVE}`]:\n 'border-destructive bg-destructive text-destructive',\n [`${SwitchSelectorColor.NEUTRAL}`]: 'border-neutral text-neutral',\n [`${SwitchSelectorColor.LIGHT}`]: 'border-white text-white',\n [`${SwitchSelectorColor.DARK}`]: 'border-neutral-800 text-neutral-800',\n [`${SwitchSelectorColor.TEXT}`]: 'border-text text-text',\n },\n disabled: {\n true: 'cursor-not-allowed opacity-50',\n false: '',\n },\n },\n defaultVariants: {\n color: `${SwitchSelectorColor.PRIMARY}`,\n disabled: false,\n },\n }\n);\n\nconst verticalChoiceVariant = cva(\n 'z-1 w-full cursor-pointer font-medium text-sm transition-all duration-300 ease-in-out aria-selected:cursor-default data-[indicator=true]:text-text-opposite motion-reduce:transition-none',\n {\n variants: {\n size: {\n [`${SwitchSelectorSize.SM}`]: 'px-2 py-1 text-xs',\n [`${SwitchSelectorSize.MD}`]: 'p-2 text-sm',\n [`${SwitchSelectorSize.LG}`]: 'p-4 text-base',\n },\n },\n defaultVariants: {\n size: `${SwitchSelectorSize.MD}`,\n },\n }\n);\n\nconst verticalIndicatorVariant = cva(\n 'absolute left-0 z-0 h-auto w-full rounded-xl transition-all duration-300 ease-in-out motion-reduce:transition-none',\n {\n variants: {\n color: {\n [`${SwitchSelectorColor.PRIMARY}`]:\n 'bg-primary data-[indicator=true]:text-text',\n [`${SwitchSelectorColor.SECONDARY}`]:\n 'bg-secondary data-[indicator=true]:text-text',\n [`${SwitchSelectorColor.DESTRUCTIVE}`]:\n 'bg-destructive data-[indicator=true]:text-text',\n [`${SwitchSelectorColor.NEUTRAL}`]:\n 'bg-neutral data-[indicator=true]:text-white',\n [`${SwitchSelectorColor.LIGHT}`]:\n 'bg-white data-[indicator=true]:text-black',\n [`${SwitchSelectorColor.DARK}`]:\n 'bg-neutral-800 data-[indicator=true]:text-white',\n [`${SwitchSelectorColor.TEXT}`]:\n 'bg-text data-[indicator=true]:text-text-opposite',\n },\n },\n }\n);\n\nexport type VerticalSwitchSelectorProps<T = boolean> =\n SwitchSelectorBaseProps<T> &\n VariantProps<typeof verticalSwitchSelectorVariant> &\n VariantProps<typeof verticalChoiceVariant>;\n\n/**\n * Component that allows the user to select one of the provided choices.\n * This component is vertical.\n */\nexport const VerticalSwitchSelector = <T,>(\n props: VerticalSwitchSelectorProps<T>\n) => {\n const {\n choices = defaultChoices as SwitchSelectorChoices<T>,\n color = SwitchSelectorColor.PRIMARY,\n size = SwitchSelectorSize.MD,\n className,\n itemClassName,\n ...baseProps\n } = props;\n\n const {\n selectedIndex,\n indicatorIndex,\n handleChange,\n optionsRefs,\n indicatorRef,\n choiceIndicatorPosition,\n setHoveredIndex,\n disabled,\n } = useSwitchSelector(\n {\n choices,\n value: props.value,\n defaultValue: props.defaultValue,\n onChange: props.onChange,\n hoverable: props.hoverable,\n disabled: props.disabled,\n },\n 'vertical'\n );\n\n return (\n <div\n className={verticalSwitchSelectorVariant({\n color,\n disabled,\n className,\n })}\n role=\"tablist\"\n aria-disabled={disabled ? 'true' : undefined}\n >\n <div className=\"relative flex h-fit w-full flex-col items-center justify-center\">\n {choices.map((choice, index) => {\n const { content, value, ...buttonProps } = choice;\n\n const isKeyOfKey =\n typeof value === 'string' || typeof value === 'number';\n\n const isSelected = index === selectedIndex;\n const isIndicatorOwner = index === indicatorIndex;\n\n return (\n <button\n {...buttonProps}\n className={cn(\n verticalChoiceVariant({\n size,\n }),\n disabled && 'cursor-not-allowed',\n itemClassName\n )}\n key={isKeyOfKey ? value : index}\n role=\"tab\"\n onClick={() => handleChange(value)}\n aria-selected={isSelected ? 'true' : undefined}\n data-indicator={isIndicatorOwner ? 'true' : undefined}\n disabled={disabled || isSelected}\n tabIndex={isSelected ? 0 : -1}\n ref={(el) => {\n optionsRefs.current[index] = el!;\n }}\n onMouseEnter={() => !disabled && setHoveredIndex(index)}\n onMouseLeave={() => !disabled && setHoveredIndex(null)}\n >\n {content}\n </button>\n );\n })}\n\n {choiceIndicatorPosition && (\n <div\n className={cn(\n verticalIndicatorVariant({\n color,\n })\n )}\n style={choiceIndicatorPosition}\n ref={indicatorRef}\n />\n )}\n </div>\n </div>\n );\n};\n"],"mappings":";;;;;;;;;;AAaA,MAAM,gCAAgC,IACpC,iFACA;CACE,UAAU;EACR,OAAO;IACJ,iBAAmC;IACnC,mBAAqC;IACrC,qBACC;IACD,iBAAmC;IACnC,eAAiC;IACjC,cAAgC;IAChC,cAAgC;GAClC;EACD,UAAU;GACR,MAAM;GACN,OAAO;GACR;EACF;CACD,iBAAiB;EACf,OAAO;EACP,UAAU;EACX;CACF,CACF;AAED,MAAM,wBAAwB,IAC5B,6LACA;CACE,UAAU,EACR,MAAM;GACH,YAA6B;GAC7B,YAA6B;GAC7B,YAA6B;EAC/B,EACF;CACD,iBAAiB,EACf,MAAM,WACP;CACF,CACF;AAED,MAAM,2BAA2B,IAC/B,sHACA,EACE,UAAU,EACR,OAAO;EACJ,iBACC;EACD,mBACC;EACD,qBACC;EACD,iBACC;EACD,eACC;EACD,cACC;EACD,cACC;CACH,EACF,EACF,CACF;;;;;AAWD,MAAa,0BACX,UACG;CACH,MAAM,EACJ,UAAU,gBACV,mBACA,aACA,WACA,eACA,GAAG,cACD;CAEJ,MAAM,EACJ,eACA,gBACA,cACA,aACA,cACA,yBACA,iBACA,aACE,kBACF;EACE;EACA,OAAO,MAAM;EACb,cAAc,MAAM;EACpB,UAAU,MAAM;EAChB,WAAW,MAAM;EACjB,UAAU,MAAM;EACjB,EACD,WACD;AAED,QACE,oBAAC,OAAD;EACE,WAAW,8BAA8B;GACvC;GACA;GACA;GACD,CAAC;EACF,MAAK;EACL,iBAAe,WAAW,SAAS;YAEnC,qBAAC,OAAD;GAAK,WAAU;aAAf,CACG,QAAQ,KAAK,QAAQ,UAAU;IAC9B,MAAM,EAAE,SAAS,OAAO,GAAG,gBAAgB;IAE3C,MAAM,aACJ,OAAO,UAAU,YAAY,OAAO,UAAU;IAEhD,MAAM,aAAa,UAAU;IAC7B,MAAM,mBAAmB,UAAU;AAEnC,WACE,8BAAC,UAAD;KACE,GAAI;KACJ,WAAW,GACT,sBAAsB,EACpB,MACD,CAAC,EACF,YAAY,sBACZ,cACD;KACD,KAAK,aAAa,QAAQ;KAC1B,MAAK;KACL,eAAe,aAAa,MAAM;KAClC,iBAAe,aAAa,SAAS;KACrC,kBAAgB,mBAAmB,SAAS;KAC5C,UAAU,YAAY;KACtB,UAAU,aAAa,IAAI;KAC3B,MAAM,OAAO;AACX,kBAAY,QAAQ,SAAS;;KAE/B,oBAAoB,CAAC,YAAY,gBAAgB,MAAM;KACvD,oBAAoB,CAAC,YAAY,gBAAgB,KAAK;KAG/C,EADN,QACM;KAEX,EAED,2BACC,oBAAC,OAAD;IACE,WAAW,GACT,yBAAyB,EACvB,OACD,CAAC,CACH;IACD,OAAO;IACP,KAAK;IACL,EAEA;;EACF"}
1
+ {"version":3,"file":"VerticalSwitchSelector.mjs","names":[],"sources":["../../../../src/components/SwitchSelector/VerticalSwitchSelector.tsx"],"sourcesContent":["'use client';\n\nimport { cn } from '@utils/cn';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport {\n defaultChoices,\n type SwitchSelectorBaseProps,\n type SwitchSelectorChoices,\n SwitchSelectorColor,\n SwitchSelectorSize,\n} from './SwitchSelector';\nimport { useSwitchSelector } from './useSwitchSelector';\n\nconst verticalSwitchSelectorVariant = cva(\n 'flex h-fit w-fit cursor-pointer flex-col gap-2 rounded-2xl border-[1.3px] p-1',\n {\n variants: {\n color: {\n [`${SwitchSelectorColor.PRIMARY}`]: 'border-primary text-primary',\n [`${SwitchSelectorColor.SECONDARY}`]: 'border-secondary text-secondary',\n [`${SwitchSelectorColor.DESTRUCTIVE}`]:\n 'border-destructive bg-destructive text-destructive',\n [`${SwitchSelectorColor.NEUTRAL}`]: 'border-neutral text-neutral',\n [`${SwitchSelectorColor.LIGHT}`]: 'border-white text-white',\n [`${SwitchSelectorColor.DARK}`]: 'border-neutral-800 text-neutral-800',\n [`${SwitchSelectorColor.TEXT}`]: 'border-text text-text',\n },\n disabled: {\n true: 'cursor-not-allowed opacity-50',\n false: '',\n },\n },\n defaultVariants: {\n color: `${SwitchSelectorColor.PRIMARY}`,\n disabled: false,\n },\n }\n);\n\nconst verticalChoiceVariant = cva(\n 'z-1 w-full cursor-pointer font-medium text-sm transition-all duration-300 ease-in-out aria-selected:cursor-default data-[indicator=true]:text-text-opposite motion-reduce:transition-none',\n {\n variants: {\n size: {\n [`${SwitchSelectorSize.SM}`]: 'px-2 py-1 text-xs',\n [`${SwitchSelectorSize.MD}`]: 'p-2 text-sm',\n [`${SwitchSelectorSize.LG}`]: 'p-4 text-base',\n },\n },\n defaultVariants: {\n size: `${SwitchSelectorSize.MD}`,\n },\n }\n);\n\nconst verticalIndicatorVariant = cva(\n 'absolute left-0 z-0 h-auto w-full rounded-xl transition-all duration-300 ease-in-out motion-reduce:transition-none',\n {\n variants: {\n color: {\n [`${SwitchSelectorColor.PRIMARY}`]:\n 'bg-primary data-[indicator=true]:text-text',\n [`${SwitchSelectorColor.SECONDARY}`]:\n 'bg-secondary data-[indicator=true]:text-text',\n [`${SwitchSelectorColor.DESTRUCTIVE}`]:\n 'bg-destructive data-[indicator=true]:text-text',\n [`${SwitchSelectorColor.NEUTRAL}`]:\n 'bg-neutral data-[indicator=true]:text-white',\n [`${SwitchSelectorColor.LIGHT}`]:\n 'bg-white data-[indicator=true]:text-black',\n [`${SwitchSelectorColor.DARK}`]:\n 'bg-neutral-800 data-[indicator=true]:text-white',\n [`${SwitchSelectorColor.TEXT}`]:\n 'bg-text data-[indicator=true]:text-text-opposite',\n },\n },\n }\n);\n\nexport type VerticalSwitchSelectorProps<T = boolean> =\n SwitchSelectorBaseProps<T> &\n VariantProps<typeof verticalSwitchSelectorVariant> &\n VariantProps<typeof verticalChoiceVariant>;\n\n/**\n * Component that allows the user to select one of the provided choices.\n * This component is vertical.\n */\nexport const VerticalSwitchSelector = <T,>(\n props: VerticalSwitchSelectorProps<T>\n) => {\n const {\n choices = defaultChoices as SwitchSelectorChoices<T>,\n color = SwitchSelectorColor.PRIMARY,\n size = SwitchSelectorSize.MD,\n className,\n itemClassName,\n ...baseProps\n } = props;\n\n const {\n selectedIndex,\n indicatorIndex,\n handleChange,\n optionsRefs,\n indicatorRef,\n choiceIndicatorPosition,\n setHoveredIndex,\n disabled,\n } = useSwitchSelector(\n {\n choices,\n value: props.value,\n defaultValue: props.defaultValue,\n onChange: props.onChange,\n hoverable: props.hoverable,\n disabled: props.disabled,\n },\n 'vertical'\n );\n\n return (\n <div\n className={verticalSwitchSelectorVariant({\n color,\n disabled,\n className,\n })}\n role=\"tablist\"\n aria-disabled={disabled ? 'true' : undefined}\n >\n <div className=\"relative flex h-fit w-full flex-col items-center justify-center\">\n {choices.map((choice, index) => {\n const { content, value, ...buttonProps } = choice;\n\n const isKeyOfKey =\n typeof value === 'string' || typeof value === 'number';\n\n const isSelected = index === selectedIndex;\n const isIndicatorOwner = index === indicatorIndex;\n\n return (\n <button\n {...buttonProps}\n className={cn(\n verticalChoiceVariant({\n size,\n }),\n disabled && 'cursor-not-allowed',\n itemClassName\n )}\n key={isKeyOfKey ? value : index}\n role=\"tab\"\n onClick={() => handleChange(value)}\n aria-selected={isSelected ? 'true' : undefined}\n data-indicator={isIndicatorOwner ? 'true' : undefined}\n disabled={disabled || isSelected}\n tabIndex={isSelected ? 0 : -1}\n ref={(el) => {\n optionsRefs.current[index] = el!;\n }}\n onMouseEnter={() => !disabled && setHoveredIndex(index)}\n onMouseLeave={() => !disabled && setHoveredIndex(null)}\n >\n {content}\n </button>\n );\n })}\n\n {choiceIndicatorPosition && (\n <div\n className={cn(\n verticalIndicatorVariant({\n color,\n })\n )}\n style={choiceIndicatorPosition}\n ref={indicatorRef}\n />\n )}\n </div>\n </div>\n );\n};\n"],"mappings":";;;;;;;;;;AAaA,MAAM,gCAAgC,IACpC,iFACA;CACE,UAAU;EACR,OAAO;IACJ,iBAAmC;IACnC,mBAAqC;IACrC,qBACC;IACD,iBAAmC;IACnC,eAAiC;IACjC,cAAgC;IAChC,cAAgC;GAClC;EACD,UAAU;GACR,MAAM;GACN,OAAO;GACR;EACF;CACD,iBAAiB;EACf,OAAO;EACP,UAAU;EACX;CACF,CACF;AAED,MAAM,wBAAwB,IAC5B,6LACA;CACE,UAAU,EACR,MAAM;GACH,YAA6B;GAC7B,YAA6B;GAC7B,YAA6B;EAC/B,EACF;CACD,iBAAiB,EACf,MAAM,WACP;CACF,CACF;AAED,MAAM,2BAA2B,IAC/B,sHACA,EACE,UAAU,EACR,OAAO;EACJ,iBACC;EACD,mBACC;EACD,qBACC;EACD,iBACC;EACD,eACC;EACD,cACC;EACD,cACC;CACH,EACF,EACF,CACF;;;;;AAWD,MAAa,0BACX,UACG;CACH,MAAM,EACJ,UAAU,gBACV,mBACA,aACA,WACA,eACA,GAAG,cACD;CAEJ,MAAM,EACJ,eACA,gBACA,cACA,aACA,cACA,yBACA,iBACA,aACE,kBACF;EACE;EACA,OAAO,MAAM;EACb,cAAc,MAAM;EACpB,UAAU,MAAM;EAChB,WAAW,MAAM;EACjB,UAAU,MAAM;EACjB,EACD,WACD;CAED,OACE,oBAAC,OAAD;EACE,WAAW,8BAA8B;GACvC;GACA;GACA;GACD,CAAC;EACF,MAAK;EACL,iBAAe,WAAW,SAAS;YAEnC,qBAAC,OAAD;GAAK,WAAU;aAAf,CACG,QAAQ,KAAK,QAAQ,UAAU;IAC9B,MAAM,EAAE,SAAS,OAAO,GAAG,gBAAgB;IAE3C,MAAM,aACJ,OAAO,UAAU,YAAY,OAAO,UAAU;IAEhD,MAAM,aAAa,UAAU;IAC7B,MAAM,mBAAmB,UAAU;IAEnC,OACE,8BAAC,UAAD;KACE,GAAI;KACJ,WAAW,GACT,sBAAsB,EACpB,MACD,CAAC,EACF,YAAY,sBACZ,cACD;KACD,KAAK,aAAa,QAAQ;KAC1B,MAAK;KACL,eAAe,aAAa,MAAM;KAClC,iBAAe,aAAa,SAAS;KACrC,kBAAgB,mBAAmB,SAAS;KAC5C,UAAU,YAAY;KACtB,UAAU,aAAa,IAAI;KAC3B,MAAM,OAAO;MACX,YAAY,QAAQ,SAAS;;KAE/B,oBAAoB,CAAC,YAAY,gBAAgB,MAAM;KACvD,oBAAoB,CAAC,YAAY,gBAAgB,KAAK;KAG/C,EADN,QACM;KAEX,EAED,2BACC,oBAAC,OAAD;IACE,WAAW,GACT,yBAAyB,EACvB,OACD,CAAC,CACH;IACD,OAAO;IACP,KAAK;IACL,EAEA;;EACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"useSwitchSelector.mjs","names":[],"sources":["../../../../src/components/SwitchSelector/useSwitchSelector.ts"],"sourcesContent":["'use client';\n\nimport {\n type ItemSelectorOrientation,\n useItemSelector,\n} from '@hooks/useItemSelector';\nimport { useEffect, useRef, useState } from 'react';\nimport type { SwitchSelectorBaseProps } from './SwitchSelector';\n\nexport const useSwitchSelector = <T>(\n {\n choices = [],\n value,\n defaultValue,\n onChange,\n hoverable = true,\n disabled = false,\n }: SwitchSelectorBaseProps<T>,\n orientation: ItemSelectorOrientation\n) => {\n const [valueState, setValue] = useState<T>(\n value ?? defaultValue ?? choices[0]?.value\n );\n const [hoveredIndex, setHoveredIndex] = useState<number | null>(null);\n\n const optionsRefs = useRef<HTMLButtonElement[]>([]);\n const indicatorRef = useRef<HTMLDivElement | null>(null);\n const { choiceIndicatorPosition } = useItemSelector(optionsRefs, {\n selector: (el) => el.getAttribute('data-indicator') === 'true',\n isHoverable: false,\n orientation,\n });\n\n const selectedIndex = choices.findIndex(\n (choice) => choice.value === valueState\n );\n\n // The indicator follows hover if hoverable, otherwise the selected option\n const indicatorIndex =\n hoverable && hoveredIndex !== null ? hoveredIndex : selectedIndex;\n\n const handleChange = (newValue: T) => {\n console.log('useSwitchSelector handleChange', newValue);\n setValue(newValue);\n onChange?.(newValue);\n };\n\n useEffect(() => {\n if (value === undefined) return;\n setValue(value);\n }, [value]);\n\n return {\n valueState,\n hoveredIndex,\n setHoveredIndex,\n optionsRefs,\n indicatorRef,\n choiceIndicatorPosition,\n selectedIndex,\n indicatorIndex,\n handleChange,\n disabled,\n };\n};\n"],"mappings":";;;;;;AASA,MAAa,qBACX,EACE,UAAU,EAAE,EACZ,OACA,cACA,UACA,YAAY,MACZ,WAAW,SAEb,gBACG;CACH,MAAM,CAAC,YAAY,YAAY,SAC7B,SAAS,gBAAgB,QAAQ,IAAI,MACtC;CACD,MAAM,CAAC,cAAc,mBAAmB,SAAwB,KAAK;CAErE,MAAM,cAAc,OAA4B,EAAE,CAAC;CACnD,MAAM,eAAe,OAA8B,KAAK;CACxD,MAAM,EAAE,4BAA4B,gBAAgB,aAAa;EAC/D,WAAW,OAAO,GAAG,aAAa,iBAAiB,KAAK;EACxD,aAAa;EACb;EACD,CAAC;CAEF,MAAM,gBAAgB,QAAQ,WAC3B,WAAW,OAAO,UAAU,WAC9B;CAGD,MAAM,iBACJ,aAAa,iBAAiB,OAAO,eAAe;CAEtD,MAAM,gBAAgB,aAAgB;AACpC,UAAQ,IAAI,kCAAkC,SAAS;AACvD,WAAS,SAAS;AAClB,aAAW,SAAS;;AAGtB,iBAAgB;AACd,MAAI,UAAU,OAAW;AACzB,WAAS,MAAM;IACd,CAAC,MAAM,CAAC;AAEX,QAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD"}
1
+ {"version":3,"file":"useSwitchSelector.mjs","names":[],"sources":["../../../../src/components/SwitchSelector/useSwitchSelector.ts"],"sourcesContent":["'use client';\n\nimport {\n type ItemSelectorOrientation,\n useItemSelector,\n} from '@hooks/useItemSelector';\nimport { useEffect, useRef, useState } from 'react';\nimport type { SwitchSelectorBaseProps } from './SwitchSelector';\n\nexport const useSwitchSelector = <T>(\n {\n choices = [],\n value,\n defaultValue,\n onChange,\n hoverable = true,\n disabled = false,\n }: SwitchSelectorBaseProps<T>,\n orientation: ItemSelectorOrientation\n) => {\n const [valueState, setValue] = useState<T>(\n value ?? defaultValue ?? choices[0]?.value\n );\n const [hoveredIndex, setHoveredIndex] = useState<number | null>(null);\n\n const optionsRefs = useRef<HTMLButtonElement[]>([]);\n const indicatorRef = useRef<HTMLDivElement | null>(null);\n const { choiceIndicatorPosition } = useItemSelector(optionsRefs, {\n selector: (el) => el.getAttribute('data-indicator') === 'true',\n isHoverable: false,\n orientation,\n });\n\n const selectedIndex = choices.findIndex(\n (choice) => choice.value === valueState\n );\n\n // The indicator follows hover if hoverable, otherwise the selected option\n const indicatorIndex =\n hoverable && hoveredIndex !== null ? hoveredIndex : selectedIndex;\n\n const handleChange = (newValue: T) => {\n console.log('useSwitchSelector handleChange', newValue);\n setValue(newValue);\n onChange?.(newValue);\n };\n\n useEffect(() => {\n if (value === undefined) return;\n setValue(value);\n }, [value]);\n\n return {\n valueState,\n hoveredIndex,\n setHoveredIndex,\n optionsRefs,\n indicatorRef,\n choiceIndicatorPosition,\n selectedIndex,\n indicatorIndex,\n handleChange,\n disabled,\n };\n};\n"],"mappings":";;;;;;AASA,MAAa,qBACX,EACE,UAAU,EAAE,EACZ,OACA,cACA,UACA,YAAY,MACZ,WAAW,SAEb,gBACG;CACH,MAAM,CAAC,YAAY,YAAY,SAC7B,SAAS,gBAAgB,QAAQ,IAAI,MACtC;CACD,MAAM,CAAC,cAAc,mBAAmB,SAAwB,KAAK;CAErE,MAAM,cAAc,OAA4B,EAAE,CAAC;CACnD,MAAM,eAAe,OAA8B,KAAK;CACxD,MAAM,EAAE,4BAA4B,gBAAgB,aAAa;EAC/D,WAAW,OAAO,GAAG,aAAa,iBAAiB,KAAK;EACxD,aAAa;EACb;EACD,CAAC;CAEF,MAAM,gBAAgB,QAAQ,WAC3B,WAAW,OAAO,UAAU,WAC9B;CAGD,MAAM,iBACJ,aAAa,iBAAiB,OAAO,eAAe;CAEtD,MAAM,gBAAgB,aAAgB;EACpC,QAAQ,IAAI,kCAAkC,SAAS;EACvD,SAAS,SAAS;EAClB,WAAW,SAAS;;CAGtB,gBAAgB;EACd,IAAI,UAAU,QAAW;EACzB,SAAS,MAAM;IACd,CAAC,MAAM,CAAC;CAEX,OAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD"}
@@ -1 +1 @@
1
- {"version":3,"file":"Tab.mjs","names":[],"sources":["../../../../src/components/Tab/Tab.tsx"],"sourcesContent":["'use client';\n\nimport { useHorizontalSwipe } from '@hooks/useHorizontalSwipe';\nimport { cn } from '@utils/cn';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport {\n Children,\n createContext,\n type HTMLAttributes,\n isValidElement,\n type ReactElement,\n type ReactNode,\n useState,\n} from 'react';\nimport { TabSelector, TabSelectorColor } from '../TabSelector';\nimport { useTabContext } from './TabContext';\n\n// Context for managing tab state\ntype TabContextType = {\n activeTab: string;\n setActiveTab: (tab: string) => void;\n};\n\nconst TabContext = createContext<TabContextType | undefined>(undefined);\n\n// Tab container variants\nconst tabContainerVariant = cva('relative w-full rounded-lg', {\n variants: {\n background: {\n with: 'border border-neutral/20 bg-background/2 shadow-[0_0_10px_-15px_rgba(0,0,0,0.3)] backdrop-blur',\n without: '',\n },\n variant: {\n default: '',\n bordered: 'border-2',\n ghost: 'border-0 bg-transparent shadow-none',\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n});\n\nexport type TabProps = HTMLAttributes<HTMLDivElement> &\n VariantProps<typeof tabContainerVariant> & {\n defaultTab?: string;\n group?: string;\n children: ReactNode;\n headerClassName?: string;\n fullHeight?: boolean;\n };\n\nexport type TabItemProps = HTMLAttributes<HTMLDivElement> & {\n label: string;\n value: string;\n disabled?: boolean;\n children: ReactNode;\n};\n\n/**\n * TabItem component that represents a single tab\n * Must be used as a child of the Tab component\n */\nconst TabItem = ({ children, ...props }: TabItemProps) => (\n // This component is primarily used for its props by the parent Tab component\n // The actual rendering is handled by the Tab component\n <div {...props}>{children}</div>\n);\n\n// Add display name for better debugging\nTabItem.displayName = 'TabItem';\n\n/**\n * Tab container component that manages tab state and renders tab headers and content\n *\n * Example:\n * ```jsx\n * <Tab defaultTab=\"tab1\">\n * <Tab.Item label=\"First Tab\" value=\"tab1\">\n * Content for first tab\n * </Tab.Item>\n * <Tab.Item label=\"Second Tab\" value=\"tab2\">\n * Content for second tab\n * </Tab.Item>\n * </Tab>\n * ```\n */\nconst TabComponent = ({\n defaultTab,\n group,\n variant,\n children,\n className,\n headerClassName,\n fullHeight,\n ...props\n}: TabProps) => {\n // Extract TabItem children to get their props\n const tabItems = Children.toArray(children).filter((child) => {\n return isValidElement(child) && child.type === TabItem;\n }) as ReactElement<TabItemProps>[];\n\n const firstTabValue = tabItems[0]?.props?.value;\n const { tabsValues, setTabsValues } = useTabContext();\n const [activeTab, setActiveTab] = useState(defaultTab ?? firstTabValue ?? '');\n const hasGroup = group && typeof tabsValues === 'object';\n const currentTabValue =\n (hasGroup ? tabsValues?.[group] : activeTab) ?? defaultTab ?? firstTabValue;\n const activeTabIndex = tabItems.findIndex(\n (tab) => tab.props.value === currentTabValue\n );\n\n const tabsCount = tabItems.length;\n\n const { containerProps, dragDeltaPct, isDragging } = useHorizontalSwipe({\n itemIndex: activeTabIndex,\n itemCount: tabsCount,\n onSwipeLeft: () => {\n const targetIndex = Math.min(tabsCount - 1, activeTabIndex + 1);\n const nextValue = tabItems[targetIndex]?.props?.value;\n if (nextValue) handleSetActiveTab(nextValue);\n },\n onSwipeRight: () => {\n const targetIndex = Math.max(0, activeTabIndex - 1);\n const nextValue = tabItems[targetIndex]?.props?.value;\n if (nextValue) handleSetActiveTab(nextValue);\n },\n });\n\n const handleSetActiveTab = (tab: string) => {\n setActiveTab(tab);\n\n if (typeof setTabsValues === 'function') {\n setTabsValues((prev) => ({ ...prev, [group!]: tab }));\n }\n };\n\n const contextValue: TabContextType = {\n activeTab: activeTab ?? firstTabValue ?? '',\n setActiveTab: handleSetActiveTab,\n };\n\n return (\n <TabContext.Provider value={contextValue}>\n <div\n className={cn(\n tabContainerVariant({ variant }),\n fullHeight && 'flex h-full flex-col overflow-hidden',\n className\n )}\n {...props}\n >\n {/* Tab Headers */}\n <div className={cn('flex shrink-0 gap-3 p-3', headerClassName)}>\n <TabSelector\n selectedChoice={currentTabValue}\n tabs={tabItems.map((child) => {\n const { label, value, disabled } = child.props;\n const isActive = currentTabValue === value;\n\n return (\n <button\n key={value}\n className={cn(\n 'cursor-pointer whitespace-nowrap rounded-md px-4 py-1 font-medium text-sm transition-colors focus:outline-none',\n !isActive && 'text-neutral/70'\n )}\n data-active={isActive}\n disabled={disabled}\n onClick={() => !disabled && handleSetActiveTab(value)}\n role=\"tab\"\n aria-selected={isActive}\n aria-controls={`tabpanel-${value}`}\n id={`tab-${value}`}\n type=\"button\"\n >\n {label ?? value}\n </button>\n );\n })}\n hoverable\n color={TabSelectorColor.TEXT}\n />\n </div>\n {/* Tab Content */}\n {/* Clipper: no overflow; uses clip-path */}\n <div\n className={cn(\n 'relative w-full min-w-0 overflow-x-clip [-webkit-clip-path:inset(0)] [clip-path:inset(0)]',\n fullHeight && 'min-h-0 flex-1'\n )}\n {...containerProps}\n >\n {/* Track */}\n <div\n role=\"tablist\"\n aria-orientation=\"horizontal\"\n className={cn(\n 'grid w-full min-w-0',\n fullHeight && 'h-full',\n isDragging\n ? 'transition-none'\n : 'transition-transform duration-300 ease-in-out'\n )}\n style={{\n gridTemplateColumns: `repeat(${tabItems.length}, 100%)`,\n transform: `translateX(-${activeTabIndex * 100 - (isDragging ? dragDeltaPct : 0)}%)`,\n }}\n >\n {tabItems.map(({ props }, index) => {\n const { value, children, className: itemClassName } = props;\n const isActive = index === activeTabIndex;\n\n return (\n <div\n key={value}\n role=\"tabpanel\"\n aria-labelledby={`tab-${value}`}\n id={`tabpanel-${value}`}\n aria-hidden={!isActive}\n tabIndex={isActive ? 0 : -1}\n data-active={isActive}\n className={cn(\n 'w-full min-w-0 p-6 opacity-100 transition-opacity duration-300 ease-in-out',\n fullHeight && 'h-full overflow-y-auto',\n !isActive && 'pointer-events-none opacity-0', // prevent offscreen interaction\n itemClassName\n )}\n >\n <div\n className={cn(\n 'flex w-full min-w-0 flex-col items-stretch gap-6',\n fullHeight && 'min-h-full'\n )}\n >\n {children}\n </div>\n </div>\n );\n })}\n </div>\n </div>\n </div>\n </TabContext.Provider>\n );\n};\n\n// Create the compound component\nexport const Tab = Object.assign(TabComponent, {\n Item: TabItem,\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"Tab.mjs","names":[],"sources":["../../../../src/components/Tab/Tab.tsx"],"sourcesContent":["'use client';\n\nimport { useHorizontalSwipe } from '@hooks/useHorizontalSwipe';\nimport { cn } from '@utils/cn';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport {\n Children,\n createContext,\n type HTMLAttributes,\n isValidElement,\n type ReactElement,\n type ReactNode,\n useState,\n} from 'react';\nimport { TabSelector, TabSelectorColor } from '../TabSelector';\nimport { useTabContext } from './TabContext';\n\n// Context for managing tab state\ntype TabContextType = {\n activeTab: string;\n setActiveTab: (tab: string) => void;\n};\n\nconst TabContext = createContext<TabContextType | undefined>(undefined);\n\n// Tab container variants\nconst tabContainerVariant = cva('relative w-full rounded-lg', {\n variants: {\n background: {\n with: 'border border-neutral/20 bg-background/2 shadow-[0_0_10px_-15px_rgba(0,0,0,0.3)] backdrop-blur',\n without: '',\n },\n variant: {\n default: '',\n bordered: 'border-2',\n ghost: 'border-0 bg-transparent shadow-none',\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n});\n\nexport type TabProps = HTMLAttributes<HTMLDivElement> &\n VariantProps<typeof tabContainerVariant> & {\n defaultTab?: string;\n group?: string;\n children: ReactNode;\n headerClassName?: string;\n fullHeight?: boolean;\n };\n\nexport type TabItemProps = HTMLAttributes<HTMLDivElement> & {\n label: string;\n value: string;\n disabled?: boolean;\n children: ReactNode;\n};\n\n/**\n * TabItem component that represents a single tab\n * Must be used as a child of the Tab component\n */\nconst TabItem = ({ children, ...props }: TabItemProps) => (\n // This component is primarily used for its props by the parent Tab component\n // The actual rendering is handled by the Tab component\n <div {...props}>{children}</div>\n);\n\n// Add display name for better debugging\nTabItem.displayName = 'TabItem';\n\n/**\n * Tab container component that manages tab state and renders tab headers and content\n *\n * Example:\n * ```jsx\n * <Tab defaultTab=\"tab1\">\n * <Tab.Item label=\"First Tab\" value=\"tab1\">\n * Content for first tab\n * </Tab.Item>\n * <Tab.Item label=\"Second Tab\" value=\"tab2\">\n * Content for second tab\n * </Tab.Item>\n * </Tab>\n * ```\n */\nconst TabComponent = ({\n defaultTab,\n group,\n variant,\n children,\n className,\n headerClassName,\n fullHeight,\n ...props\n}: TabProps) => {\n // Extract TabItem children to get their props\n const tabItems = Children.toArray(children).filter((child) => {\n return isValidElement(child) && child.type === TabItem;\n }) as ReactElement<TabItemProps>[];\n\n const firstTabValue = tabItems[0]?.props?.value;\n const { tabsValues, setTabsValues } = useTabContext();\n const [activeTab, setActiveTab] = useState(defaultTab ?? firstTabValue ?? '');\n const hasGroup = group && typeof tabsValues === 'object';\n const currentTabValue =\n (hasGroup ? tabsValues?.[group] : activeTab) ?? defaultTab ?? firstTabValue;\n const activeTabIndex = tabItems.findIndex(\n (tab) => tab.props.value === currentTabValue\n );\n\n const tabsCount = tabItems.length;\n\n const { containerProps, dragDeltaPct, isDragging } = useHorizontalSwipe({\n itemIndex: activeTabIndex,\n itemCount: tabsCount,\n onSwipeLeft: () => {\n const targetIndex = Math.min(tabsCount - 1, activeTabIndex + 1);\n const nextValue = tabItems[targetIndex]?.props?.value;\n if (nextValue) handleSetActiveTab(nextValue);\n },\n onSwipeRight: () => {\n const targetIndex = Math.max(0, activeTabIndex - 1);\n const nextValue = tabItems[targetIndex]?.props?.value;\n if (nextValue) handleSetActiveTab(nextValue);\n },\n });\n\n const handleSetActiveTab = (tab: string) => {\n setActiveTab(tab);\n\n if (typeof setTabsValues === 'function') {\n setTabsValues((prev) => ({ ...prev, [group!]: tab }));\n }\n };\n\n const contextValue: TabContextType = {\n activeTab: activeTab ?? firstTabValue ?? '',\n setActiveTab: handleSetActiveTab,\n };\n\n return (\n <TabContext.Provider value={contextValue}>\n <div\n className={cn(\n tabContainerVariant({ variant }),\n fullHeight && 'flex h-full flex-col overflow-hidden',\n className\n )}\n {...props}\n >\n {/* Tab Headers */}\n <div className={cn('flex shrink-0 gap-3 p-3', headerClassName)}>\n <TabSelector\n selectedChoice={currentTabValue}\n tabs={tabItems.map((child) => {\n const { label, value, disabled } = child.props;\n const isActive = currentTabValue === value;\n\n return (\n <button\n key={value}\n className={cn(\n 'cursor-pointer whitespace-nowrap rounded-md px-4 py-1 font-medium text-sm transition-colors focus:outline-none',\n !isActive && 'text-neutral/70'\n )}\n data-active={isActive}\n disabled={disabled}\n onClick={() => !disabled && handleSetActiveTab(value)}\n role=\"tab\"\n aria-selected={isActive}\n aria-controls={`tabpanel-${value}`}\n id={`tab-${value}`}\n type=\"button\"\n >\n {label ?? value}\n </button>\n );\n })}\n hoverable\n color={TabSelectorColor.TEXT}\n />\n </div>\n {/* Tab Content */}\n {/* Clipper: no overflow; uses clip-path */}\n <div\n className={cn(\n 'relative w-full min-w-0 overflow-x-clip [-webkit-clip-path:inset(0)] [clip-path:inset(0)]',\n fullHeight && 'min-h-0 flex-1'\n )}\n {...containerProps}\n >\n {/* Track */}\n <div\n role=\"tablist\"\n aria-orientation=\"horizontal\"\n className={cn(\n 'grid w-full min-w-0',\n fullHeight && 'h-full',\n isDragging\n ? 'transition-none'\n : 'transition-transform duration-300 ease-in-out'\n )}\n style={{\n gridTemplateColumns: `repeat(${tabItems.length}, 100%)`,\n transform: `translateX(-${activeTabIndex * 100 - (isDragging ? dragDeltaPct : 0)}%)`,\n }}\n >\n {tabItems.map(({ props }, index) => {\n const { value, children, className: itemClassName } = props;\n const isActive = index === activeTabIndex;\n\n return (\n <div\n key={value}\n role=\"tabpanel\"\n aria-labelledby={`tab-${value}`}\n id={`tabpanel-${value}`}\n aria-hidden={!isActive}\n tabIndex={isActive ? 0 : -1}\n data-active={isActive}\n className={cn(\n 'w-full min-w-0 p-6 opacity-100 transition-opacity duration-300 ease-in-out',\n fullHeight && 'h-full overflow-y-auto',\n !isActive && 'pointer-events-none opacity-0', // prevent offscreen interaction\n itemClassName\n )}\n >\n <div\n className={cn(\n 'flex w-full min-w-0 flex-col items-stretch gap-6',\n fullHeight && 'min-h-full'\n )}\n >\n {children}\n </div>\n </div>\n );\n })}\n </div>\n </div>\n </div>\n </TabContext.Provider>\n );\n};\n\n// Create the compound component\nexport const Tab = Object.assign(TabComponent, {\n Item: TabItem,\n});\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"TabContext.mjs","names":[],"sources":["../../../../src/components/Tab/TabContext.tsx"],"sourcesContent":["'use client';\n\nimport {\n createContext,\n type Dispatch,\n type FC,\n type PropsWithChildren,\n type SetStateAction,\n useContext,\n useState,\n} from 'react';\n\ntype TabContextValue = {\n tabsValues: Record<string, any>;\n setTabsValues: Dispatch<SetStateAction<Record<string, any>>>;\n};\n\n/**\n * Context that store the current locale on the client side\n */\nexport const TabContext = createContext<TabContextValue>({\n tabsValues: {},\n setTabsValues: (() => {}) as Dispatch<SetStateAction<Record<string, any>>>,\n});\n\n/**\n * Hook that provides the current locale\n */\nexport const useTabContext = () => useContext(TabContext);\n\n/**\n * Provider that store the current locale on the client side\n */\nexport const TabProvider: FC<PropsWithChildren> = ({ children }) => {\n const [tabsValues, setTabsValues] = useState<Record<string, any>>({});\n\n return (\n <TabContext\n value={{\n tabsValues,\n setTabsValues,\n }}\n >\n {children}\n </TabContext>\n );\n};\n"],"mappings":";;;;;;;;;AAoBA,MAAa,aAAa,cAA+B;CACvD,YAAY,EAAE;CACd,sBAAsB;CACvB,CAAC;;;;AAKF,MAAa,sBAAsB,WAAW,WAAW;;;;AAKzD,MAAa,eAAsC,EAAE,eAAe;CAClE,MAAM,CAAC,YAAY,iBAAiB,SAA8B,EAAE,CAAC;AAErE,QACE,oBAAC,YAAD;EACE,OAAO;GACL;GACA;GACD;EAEA;EACU"}
1
+ {"version":3,"file":"TabContext.mjs","names":[],"sources":["../../../../src/components/Tab/TabContext.tsx"],"sourcesContent":["'use client';\n\nimport {\n createContext,\n type Dispatch,\n type FC,\n type PropsWithChildren,\n type SetStateAction,\n useContext,\n useState,\n} from 'react';\n\ntype TabContextValue = {\n tabsValues: Record<string, any>;\n setTabsValues: Dispatch<SetStateAction<Record<string, any>>>;\n};\n\n/**\n * Context that store the current locale on the client side\n */\nexport const TabContext = createContext<TabContextValue>({\n tabsValues: {},\n setTabsValues: (() => {}) as Dispatch<SetStateAction<Record<string, any>>>,\n});\n\n/**\n * Hook that provides the current locale\n */\nexport const useTabContext = () => useContext(TabContext);\n\n/**\n * Provider that store the current locale on the client side\n */\nexport const TabProvider: FC<PropsWithChildren> = ({ children }) => {\n const [tabsValues, setTabsValues] = useState<Record<string, any>>({});\n\n return (\n <TabContext\n value={{\n tabsValues,\n setTabsValues,\n }}\n >\n {children}\n </TabContext>\n );\n};\n"],"mappings":";;;;;;;;;AAoBA,MAAa,aAAa,cAA+B;CACvD,YAAY,EAAE;CACd,sBAAsB;CACvB,CAAC;;;;AAKF,MAAa,sBAAsB,WAAW,WAAW;;;;AAKzD,MAAa,eAAsC,EAAE,eAAe;CAClE,MAAM,CAAC,YAAY,iBAAiB,SAA8B,EAAE,CAAC;CAErE,OACE,oBAAC,YAAD;EACE,OAAO;GACL;GACA;GACD;EAEA;EACU"}
@@ -1 +1 @@
1
- {"version":3,"file":"TabSelector.mjs","names":[],"sources":["../../../../src/components/TabSelector/TabSelector.tsx"],"sourcesContent":["'use client';\n\nimport {\n type ItemSelectorOrientation,\n useItemSelector,\n} from '@hooks/useItemSelector';\nimport { cn } from '@utils/cn';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport {\n cloneElement,\n type HTMLAttributes,\n type MouseEvent,\n type ReactElement,\n useEffect,\n useRef,\n} from 'react';\n\nexport enum TabSelectorColor {\n PRIMARY = 'primary',\n SECONDARY = 'secondary',\n DESTRUCTIVE = 'destructive',\n NEUTRAL = 'neutral',\n LIGHT = 'light',\n DARK = 'dark',\n TEXT = 'text',\n}\n\nconst tabSelectorVariant = cva(\n 'relative z-0 flex size-full flex-row items-center gap-2',\n {\n variants: {\n color: {\n primary: 'border-primary text-primary',\n secondary: 'border-secondary text-secondary',\n destructive: 'border-destructive bg-destructive text-destructive',\n neutral: 'border-neutral text-neutral',\n light: 'border-white text-white',\n dark: 'border-neutral-800 text-neutral-800',\n text: 'border-text text-text',\n },\n },\n defaultVariants: {\n color: 'primary',\n },\n }\n);\n\nconst indicatorVariant = cva(\n 'absolute -z-1 rounded-lg duration-300 ease-in-out motion-reduce:transition-none',\n {\n variants: {\n color: {\n primary: 'bg-primary/10 aria-selected:text-text',\n secondary: 'bg-secondary/10 aria-selected:text-text',\n destructive: 'bg-destructive/10 aria-selected:text-text',\n neutral: 'bg-neutral/10 aria-selected:text-white/10',\n light: 'bg-white/10 aria-selected:text-black',\n dark: 'bg-neutral-800/10 aria-selected:text-white',\n text: 'bg-text/10 aria-selected:text-text-opposite',\n },\n orientation: {\n horizontal: 'top-0 h-full w-auto transition-[left,width]',\n vertical: 'left-0 h-auto w-full transition-[top,height]',\n },\n },\n defaultVariants: {\n orientation: 'horizontal',\n },\n }\n);\n\nexport type TabSelectorItemProps = HTMLAttributes<HTMLElement> & {\n key: string | number;\n};\n\nexport type TabSelectorProps<T extends TabSelectorItemProps> = {\n tabs: ReactElement<T>[];\n selectedChoice: T['key'];\n onTabClick?: (choice: T['key']) => void;\n hoverable?: boolean;\n orientation?: ItemSelectorOrientation;\n} & HTMLAttributes<HTMLElement> &\n Omit<VariantProps<typeof tabSelectorVariant>, 'color'> & {\n color?: TabSelectorColor | `${TabSelectorColor}`;\n };\n\n/**\n *\n * Component that allows the user to select one of the provided choices.\n *\n * Example:\n * ```jsx\n * <TabSelector\n * selectedChoice=\"option1\"\n * onTabClick={(choice) => console.log(choice)}\n * hoverable={true}\n * >\n * <Button key=\"option1\"/>\n * <Button key=\"option2\"/>\n * <Button key=\"option3\"/>\n * </TabSelector>\n * ```\n */\nexport const TabSelector = <T extends TabSelectorItemProps>({\n tabs,\n selectedChoice,\n onTabClick,\n color = TabSelectorColor.PRIMARY,\n hoverable = false,\n orientation = 'horizontal',\n className,\n}: TabSelectorProps<T>) => {\n const optionsRefs = useRef<HTMLElement[]>([]);\n const indicatorRef = useRef<HTMLDivElement | null>(null);\n const { choiceIndicatorPosition, calculatePosition } = useItemSelector(\n optionsRefs,\n { isHoverable: hoverable, orientation }\n );\n\n useEffect(() => {\n calculatePosition();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [selectedChoice]);\n\n return (\n <div\n className={cn(\n tabSelectorVariant({\n color,\n }),\n className\n )}\n aria-orientation={orientation}\n aria-multiselectable=\"false\"\n role=\"tablist\"\n >\n {tabs.map((Tab, index) => {\n const key = Tab.key!;\n\n const isSelected = selectedChoice === key;\n\n return cloneElement(Tab, {\n key: key ?? index,\n role: 'tab',\n onClick: (e: MouseEvent<HTMLElement>) => {\n Tab.props?.onClick?.(e);\n onTabClick?.(key);\n },\n 'aria-selected': isSelected,\n 'data-active': isSelected as unknown as string,\n tabIndex: isSelected ? 0 : -1,\n ref: (el: HTMLElement) => {\n optionsRefs.current[index] = el!;\n },\n } as unknown as T);\n })}\n {choiceIndicatorPosition && (\n <div\n className={cn(\n indicatorVariant({\n color,\n orientation,\n })\n )}\n style={choiceIndicatorPosition}\n ref={indicatorRef}\n key={`${selectedChoice}${JSON.stringify(tabs.map((tab) => tab.key))}`}\n />\n )}\n </div>\n );\n};\n"],"mappings":";;;;;;;;;AAiBA,IAAY,mBAAL;AACL;AACA;AACA;AACA;AACA;AACA;AACA;;KACD;AAED,MAAM,qBAAqB,IACzB,2DACA;CACE,UAAU,EACR,OAAO;EACL,SAAS;EACT,WAAW;EACX,aAAa;EACb,SAAS;EACT,OAAO;EACP,MAAM;EACN,MAAM;EACP,EACF;CACD,iBAAiB,EACf,OAAO,WACR;CACF,CACF;AAED,MAAM,mBAAmB,IACvB,mFACA;CACE,UAAU;EACR,OAAO;GACL,SAAS;GACT,WAAW;GACX,aAAa;GACb,SAAS;GACT,OAAO;GACP,MAAM;GACN,MAAM;GACP;EACD,aAAa;GACX,YAAY;GACZ,UAAU;GACX;EACF;CACD,iBAAiB,EACf,aAAa,cACd;CACF,CACF;;;;;;;;;;;;;;;;;;AAkCD,MAAa,eAA+C,EAC1D,MACA,gBACA,YACA,mBACA,YAAY,OACZ,cAAc,cACd,gBACyB;CACzB,MAAM,cAAc,OAAsB,EAAE,CAAC;CAC7C,MAAM,eAAe,OAA8B,KAAK;CACxD,MAAM,EAAE,yBAAyB,sBAAsB,gBACrD,aACA;EAAE,aAAa;EAAW;EAAa,CACxC;AAED,iBAAgB;AACd,qBAAmB;IAElB,CAAC,eAAe,CAAC;AAEpB,QACE,qBAAC,OAAD;EACE,WAAW,GACT,mBAAmB,EACjB,OACD,CAAC,EACF,UACD;EACD,oBAAkB;EAClB,wBAAqB;EACrB,MAAK;YATP,CAWG,KAAK,KAAK,KAAK,UAAU;GACxB,MAAM,MAAM,IAAI;GAEhB,MAAM,aAAa,mBAAmB;AAEtC,UAAO,aAAa,KAAK;IACvB,KAAK,OAAO;IACZ,MAAM;IACN,UAAU,MAA+B;AACvC,SAAI,OAAO,UAAU,EAAE;AACvB,kBAAa,IAAI;;IAEnB,iBAAiB;IACjB,eAAe;IACf,UAAU,aAAa,IAAI;IAC3B,MAAM,OAAoB;AACxB,iBAAY,QAAQ,SAAS;;IAEhC,CAAiB;IAClB,EACD,2BACC,oBAAC,OAAD;GACE,WAAW,GACT,iBAAiB;IACf;IACA;IACD,CAAC,CACH;GACD,OAAO;GACP,KAAK;GAEL,EADK,GAAG,iBAAiB,KAAK,UAAU,KAAK,KAAK,QAAQ,IAAI,IAAI,CAAC,GACnE,CAEA"}
1
+ {"version":3,"file":"TabSelector.mjs","names":[],"sources":["../../../../src/components/TabSelector/TabSelector.tsx"],"sourcesContent":["'use client';\n\nimport {\n type ItemSelectorOrientation,\n useItemSelector,\n} from '@hooks/useItemSelector';\nimport { cn } from '@utils/cn';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport {\n cloneElement,\n type HTMLAttributes,\n type MouseEvent,\n type ReactElement,\n useEffect,\n useRef,\n} from 'react';\n\nexport enum TabSelectorColor {\n PRIMARY = 'primary',\n SECONDARY = 'secondary',\n DESTRUCTIVE = 'destructive',\n NEUTRAL = 'neutral',\n LIGHT = 'light',\n DARK = 'dark',\n TEXT = 'text',\n}\n\nconst tabSelectorVariant = cva(\n 'relative z-0 flex size-full flex-row items-center gap-2',\n {\n variants: {\n color: {\n primary: 'border-primary text-primary',\n secondary: 'border-secondary text-secondary',\n destructive: 'border-destructive bg-destructive text-destructive',\n neutral: 'border-neutral text-neutral',\n light: 'border-white text-white',\n dark: 'border-neutral-800 text-neutral-800',\n text: 'border-text text-text',\n },\n },\n defaultVariants: {\n color: 'primary',\n },\n }\n);\n\nconst indicatorVariant = cva(\n 'absolute -z-1 rounded-lg duration-300 ease-in-out motion-reduce:transition-none',\n {\n variants: {\n color: {\n primary: 'bg-primary/10 aria-selected:text-text',\n secondary: 'bg-secondary/10 aria-selected:text-text',\n destructive: 'bg-destructive/10 aria-selected:text-text',\n neutral: 'bg-neutral/10 aria-selected:text-white/10',\n light: 'bg-white/10 aria-selected:text-black',\n dark: 'bg-neutral-800/10 aria-selected:text-white',\n text: 'bg-text/10 aria-selected:text-text-opposite',\n },\n orientation: {\n horizontal: 'top-0 h-full w-auto transition-[left,width]',\n vertical: 'left-0 h-auto w-full transition-[top,height]',\n },\n },\n defaultVariants: {\n orientation: 'horizontal',\n },\n }\n);\n\nexport type TabSelectorItemProps = HTMLAttributes<HTMLElement> & {\n key: string | number;\n};\n\nexport type TabSelectorProps<T extends TabSelectorItemProps> = {\n tabs: ReactElement<T>[];\n selectedChoice: T['key'];\n onTabClick?: (choice: T['key']) => void;\n hoverable?: boolean;\n orientation?: ItemSelectorOrientation;\n} & HTMLAttributes<HTMLElement> &\n Omit<VariantProps<typeof tabSelectorVariant>, 'color'> & {\n color?: TabSelectorColor | `${TabSelectorColor}`;\n };\n\n/**\n *\n * Component that allows the user to select one of the provided choices.\n *\n * Example:\n * ```jsx\n * <TabSelector\n * selectedChoice=\"option1\"\n * onTabClick={(choice) => console.log(choice)}\n * hoverable={true}\n * >\n * <Button key=\"option1\"/>\n * <Button key=\"option2\"/>\n * <Button key=\"option3\"/>\n * </TabSelector>\n * ```\n */\nexport const TabSelector = <T extends TabSelectorItemProps>({\n tabs,\n selectedChoice,\n onTabClick,\n color = TabSelectorColor.PRIMARY,\n hoverable = false,\n orientation = 'horizontal',\n className,\n}: TabSelectorProps<T>) => {\n const optionsRefs = useRef<HTMLElement[]>([]);\n const indicatorRef = useRef<HTMLDivElement | null>(null);\n const { choiceIndicatorPosition, calculatePosition } = useItemSelector(\n optionsRefs,\n { isHoverable: hoverable, orientation }\n );\n\n useEffect(() => {\n calculatePosition();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [selectedChoice]);\n\n return (\n <div\n className={cn(\n tabSelectorVariant({\n color,\n }),\n className\n )}\n aria-orientation={orientation}\n aria-multiselectable=\"false\"\n role=\"tablist\"\n >\n {tabs.map((Tab, index) => {\n const key = Tab.key!;\n\n const isSelected = selectedChoice === key;\n\n return cloneElement(Tab, {\n key: key ?? index,\n role: 'tab',\n onClick: (e: MouseEvent<HTMLElement>) => {\n Tab.props?.onClick?.(e);\n onTabClick?.(key);\n },\n 'aria-selected': isSelected,\n 'data-active': isSelected as unknown as string,\n tabIndex: isSelected ? 0 : -1,\n ref: (el: HTMLElement) => {\n optionsRefs.current[index] = el!;\n },\n } as unknown as T);\n })}\n {choiceIndicatorPosition && (\n <div\n className={cn(\n indicatorVariant({\n color,\n orientation,\n })\n )}\n style={choiceIndicatorPosition}\n ref={indicatorRef}\n key={`${selectedChoice}${JSON.stringify(tabs.map((tab) => tab.key))}`}\n />\n )}\n </div>\n );\n};\n"],"mappings":";;;;;;;;;AAiBA,IAAY,mBAAL;CACL;CACA;CACA;CACA;CACA;CACA;CACA;;KACD;AAED,MAAM,qBAAqB,IACzB,2DACA;CACE,UAAU,EACR,OAAO;EACL,SAAS;EACT,WAAW;EACX,aAAa;EACb,SAAS;EACT,OAAO;EACP,MAAM;EACN,MAAM;EACP,EACF;CACD,iBAAiB,EACf,OAAO,WACR;CACF,CACF;AAED,MAAM,mBAAmB,IACvB,mFACA;CACE,UAAU;EACR,OAAO;GACL,SAAS;GACT,WAAW;GACX,aAAa;GACb,SAAS;GACT,OAAO;GACP,MAAM;GACN,MAAM;GACP;EACD,aAAa;GACX,YAAY;GACZ,UAAU;GACX;EACF;CACD,iBAAiB,EACf,aAAa,cACd;CACF,CACF;;;;;;;;;;;;;;;;;;AAkCD,MAAa,eAA+C,EAC1D,MACA,gBACA,YACA,mBACA,YAAY,OACZ,cAAc,cACd,gBACyB;CACzB,MAAM,cAAc,OAAsB,EAAE,CAAC;CAC7C,MAAM,eAAe,OAA8B,KAAK;CACxD,MAAM,EAAE,yBAAyB,sBAAsB,gBACrD,aACA;EAAE,aAAa;EAAW;EAAa,CACxC;CAED,gBAAgB;EACd,mBAAmB;IAElB,CAAC,eAAe,CAAC;CAEpB,OACE,qBAAC,OAAD;EACE,WAAW,GACT,mBAAmB,EACjB,OACD,CAAC,EACF,UACD;EACD,oBAAkB;EAClB,wBAAqB;EACrB,MAAK;YATP,CAWG,KAAK,KAAK,KAAK,UAAU;GACxB,MAAM,MAAM,IAAI;GAEhB,MAAM,aAAa,mBAAmB;GAEtC,OAAO,aAAa,KAAK;IACvB,KAAK,OAAO;IACZ,MAAM;IACN,UAAU,MAA+B;KACvC,IAAI,OAAO,UAAU,EAAE;KACvB,aAAa,IAAI;;IAEnB,iBAAiB;IACjB,eAAe;IACf,UAAU,aAAa,IAAI;IAC3B,MAAM,OAAoB;KACxB,YAAY,QAAQ,SAAS;;IAEhC,CAAiB;IAClB,EACD,2BACC,oBAAC,OAAD;GACE,WAAW,GACT,iBAAiB;IACf;IACA;IACD,CAAC,CACH;GACD,OAAO;GACP,KAAK;GAEL,EADK,GAAG,iBAAiB,KAAK,UAAU,KAAK,KAAK,QAAQ,IAAI,IAAI,CAAC,GACnE,CAEA"}