@intlayer/design-system 6.1.5 → 6.1.6-canary.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (301) hide show
  1. package/dist/.vite/manifest.json +13 -9
  2. package/dist/Form-CriPBaZk.js.map +1 -1
  3. package/dist/Form-DJrUK3mm.cjs.map +1 -1
  4. package/dist/components/Accordion/Accordion.cjs +51 -15
  5. package/dist/components/Accordion/Accordion.cjs.map +1 -1
  6. package/dist/components/Accordion/Accordion.d.ts +44 -5
  7. package/dist/components/Accordion/Accordion.d.ts.map +1 -1
  8. package/dist/components/Accordion/Accordion.mjs +52 -16
  9. package/dist/components/Accordion/Accordion.mjs.map +1 -1
  10. package/dist/components/Avatar/index.cjs +114 -31
  11. package/dist/components/Avatar/index.cjs.map +1 -1
  12. package/dist/components/Avatar/index.d.ts +46 -2
  13. package/dist/components/Avatar/index.d.ts.map +1 -1
  14. package/dist/components/Avatar/index.mjs +115 -32
  15. package/dist/components/Avatar/index.mjs.map +1 -1
  16. package/dist/components/Badge/index.cjs +88 -9
  17. package/dist/components/Badge/index.cjs.map +1 -1
  18. package/dist/components/Badge/index.d.ts +80 -2
  19. package/dist/components/Badge/index.d.ts.map +1 -1
  20. package/dist/components/Badge/index.mjs +89 -10
  21. package/dist/components/Badge/index.mjs.map +1 -1
  22. package/dist/components/Breadcrumb/index.cjs +124 -59
  23. package/dist/components/Breadcrumb/index.cjs.map +1 -1
  24. package/dist/components/Breadcrumb/index.d.ts +89 -5
  25. package/dist/components/Breadcrumb/index.d.ts.map +1 -1
  26. package/dist/components/Breadcrumb/index.mjs +124 -59
  27. package/dist/components/Breadcrumb/index.mjs.map +1 -1
  28. package/dist/components/Button/Button.cjs +44 -25
  29. package/dist/components/Button/Button.cjs.map +1 -1
  30. package/dist/components/Button/Button.d.ts +95 -1
  31. package/dist/components/Button/Button.d.ts.map +1 -1
  32. package/dist/components/Button/Button.mjs +44 -25
  33. package/dist/components/Button/Button.mjs.map +1 -1
  34. package/dist/components/ClickOutsideDiv/index.cjs +38 -7
  35. package/dist/components/ClickOutsideDiv/index.cjs.map +1 -1
  36. package/dist/components/ClickOutsideDiv/index.d.ts +13 -0
  37. package/dist/components/ClickOutsideDiv/index.d.ts.map +1 -1
  38. package/dist/components/ClickOutsideDiv/index.mjs +39 -8
  39. package/dist/components/ClickOutsideDiv/index.mjs.map +1 -1
  40. package/dist/components/Container/index.cjs +2 -0
  41. package/dist/components/Container/index.cjs.map +1 -1
  42. package/dist/components/Container/index.d.ts +42 -0
  43. package/dist/components/Container/index.d.ts.map +1 -1
  44. package/dist/components/Container/index.mjs +2 -0
  45. package/dist/components/Container/index.mjs.map +1 -1
  46. package/dist/components/ContentEditor/ContentEditor.cjs +80 -33
  47. package/dist/components/ContentEditor/ContentEditor.cjs.map +1 -1
  48. package/dist/components/ContentEditor/ContentEditor.d.ts +29 -0
  49. package/dist/components/ContentEditor/ContentEditor.d.ts.map +1 -1
  50. package/dist/components/ContentEditor/ContentEditor.mjs +80 -33
  51. package/dist/components/ContentEditor/ContentEditor.mjs.map +1 -1
  52. package/dist/components/ContentEditor/ContentEditorInput.cjs +58 -31
  53. package/dist/components/ContentEditor/ContentEditorInput.cjs.map +1 -1
  54. package/dist/components/ContentEditor/ContentEditorInput.d.ts +33 -0
  55. package/dist/components/ContentEditor/ContentEditorInput.d.ts.map +1 -1
  56. package/dist/components/ContentEditor/ContentEditorInput.mjs +58 -31
  57. package/dist/components/ContentEditor/ContentEditorInput.mjs.map +1 -1
  58. package/dist/components/ContentEditor/ContentEditorTextArea.cjs +58 -30
  59. package/dist/components/ContentEditor/ContentEditorTextArea.cjs.map +1 -1
  60. package/dist/components/ContentEditor/ContentEditorTextArea.d.ts +35 -0
  61. package/dist/components/ContentEditor/ContentEditorTextArea.d.ts.map +1 -1
  62. package/dist/components/ContentEditor/ContentEditorTextArea.mjs +59 -31
  63. package/dist/components/ContentEditor/ContentEditorTextArea.mjs.map +1 -1
  64. package/dist/components/ContentEditor/index.cjs +4 -0
  65. package/dist/components/ContentEditor/index.cjs.map +1 -1
  66. package/dist/components/ContentEditor/index.d.ts +2 -0
  67. package/dist/components/ContentEditor/index.d.ts.map +1 -1
  68. package/dist/components/ContentEditor/index.mjs +5 -1
  69. package/dist/components/ContentEditor/index.mjs.map +1 -1
  70. package/dist/components/ContentSelector/ContentSelector.cjs +9 -1
  71. package/dist/components/ContentSelector/ContentSelector.cjs.map +1 -1
  72. package/dist/components/ContentSelector/ContentSelector.d.ts +167 -0
  73. package/dist/components/ContentSelector/ContentSelector.d.ts.map +1 -1
  74. package/dist/components/ContentSelector/ContentSelector.mjs +9 -1
  75. package/dist/components/ContentSelector/ContentSelector.mjs.map +1 -1
  76. package/dist/components/CopyButton/index.cjs +23 -8
  77. package/dist/components/CopyButton/index.cjs.map +1 -1
  78. package/dist/components/CopyButton/index.d.ts +78 -0
  79. package/dist/components/CopyButton/index.d.ts.map +1 -1
  80. package/dist/components/CopyButton/index.mjs +23 -8
  81. package/dist/components/CopyButton/index.mjs.map +1 -1
  82. package/dist/components/CopyToClipboard/index.cjs +58 -22
  83. package/dist/components/CopyToClipboard/index.cjs.map +1 -1
  84. package/dist/components/CopyToClipboard/index.d.ts +68 -2
  85. package/dist/components/CopyToClipboard/index.d.ts.map +1 -1
  86. package/dist/components/CopyToClipboard/index.mjs +59 -23
  87. package/dist/components/CopyToClipboard/index.mjs.map +1 -1
  88. package/dist/components/DropDown/index.cjs +6 -4
  89. package/dist/components/DropDown/index.cjs.map +1 -1
  90. package/dist/components/DropDown/index.d.ts +92 -15
  91. package/dist/components/DropDown/index.d.ts.map +1 -1
  92. package/dist/components/DropDown/index.mjs +6 -4
  93. package/dist/components/DropDown/index.mjs.map +1 -1
  94. package/dist/components/EditableField/EditableFieldInput.cjs.map +1 -1
  95. package/dist/components/EditableField/EditableFieldInput.d.ts +38 -0
  96. package/dist/components/EditableField/EditableFieldInput.d.ts.map +1 -1
  97. package/dist/components/EditableField/EditableFieldInput.mjs.map +1 -1
  98. package/dist/components/EditableField/EditableFieldLayout.cjs +10 -2
  99. package/dist/components/EditableField/EditableFieldLayout.cjs.map +1 -1
  100. package/dist/components/EditableField/EditableFieldLayout.d.ts.map +1 -1
  101. package/dist/components/EditableField/EditableFieldLayout.mjs +10 -2
  102. package/dist/components/EditableField/EditableFieldLayout.mjs.map +1 -1
  103. package/dist/components/EditableField/EditableFieldTextArea.cjs.map +1 -1
  104. package/dist/components/EditableField/EditableFieldTextArea.d.ts +42 -0
  105. package/dist/components/EditableField/EditableFieldTextArea.d.ts.map +1 -1
  106. package/dist/components/EditableField/EditableFieldTextArea.mjs.map +1 -1
  107. package/dist/components/ExpandCollapse/ExpandCollapse.cjs.map +1 -1
  108. package/dist/components/ExpandCollapse/ExpandCollapse.d.ts +58 -0
  109. package/dist/components/ExpandCollapse/ExpandCollapse.d.ts.map +1 -1
  110. package/dist/components/ExpandCollapse/ExpandCollapse.mjs.map +1 -1
  111. package/dist/components/Footer/index.cjs.map +1 -1
  112. package/dist/components/Footer/index.d.ts +101 -0
  113. package/dist/components/Footer/index.d.ts.map +1 -1
  114. package/dist/components/Footer/index.mjs.map +1 -1
  115. package/dist/components/Form/elements/MultiselectElement.d.ts.map +1 -1
  116. package/dist/components/Form/elements/SelectElement.d.ts.map +1 -1
  117. package/dist/components/Form/elements/SwitchSelectorElement.d.ts.map +1 -1
  118. package/dist/components/Headers/index.cjs.map +1 -1
  119. package/dist/components/Headers/index.d.ts +69 -2
  120. package/dist/components/Headers/index.d.ts.map +1 -1
  121. package/dist/components/Headers/index.mjs.map +1 -1
  122. package/dist/components/HeightResizer/index.cjs +10 -7
  123. package/dist/components/HeightResizer/index.cjs.map +1 -1
  124. package/dist/components/HeightResizer/index.d.ts +89 -0
  125. package/dist/components/HeightResizer/index.d.ts.map +1 -1
  126. package/dist/components/HeightResizer/index.mjs +10 -7
  127. package/dist/components/HeightResizer/index.mjs.map +1 -1
  128. package/dist/components/InformationTag/index.cjs.map +1 -1
  129. package/dist/components/InformationTag/index.d.ts +72 -0
  130. package/dist/components/InformationTag/index.d.ts.map +1 -1
  131. package/dist/components/InformationTag/index.mjs.map +1 -1
  132. package/dist/components/KeyboardScreenAdapter/index.cjs.map +1 -1
  133. package/dist/components/KeyboardScreenAdapter/index.d.ts +100 -0
  134. package/dist/components/KeyboardScreenAdapter/index.d.ts.map +1 -1
  135. package/dist/components/KeyboardScreenAdapter/index.mjs.map +1 -1
  136. package/dist/components/Label/index.cjs +25 -3
  137. package/dist/components/Label/index.cjs.map +1 -1
  138. package/dist/components/Label/index.d.ts +65 -1
  139. package/dist/components/Label/index.d.ts.map +1 -1
  140. package/dist/components/Label/index.mjs +26 -4
  141. package/dist/components/Label/index.mjs.map +1 -1
  142. package/dist/components/Link/Link.cjs.map +1 -1
  143. package/dist/components/Link/Link.d.ts +169 -0
  144. package/dist/components/Link/Link.d.ts.map +1 -1
  145. package/dist/components/Link/Link.mjs.map +1 -1
  146. package/dist/components/Loader/index.cjs.map +1 -1
  147. package/dist/components/Loader/index.d.ts +82 -11
  148. package/dist/components/Loader/index.d.ts.map +1 -1
  149. package/dist/components/Loader/index.mjs.map +1 -1
  150. package/dist/components/Loader/spinner.cjs.map +1 -1
  151. package/dist/components/Loader/spinner.d.ts +56 -0
  152. package/dist/components/Loader/spinner.d.ts.map +1 -1
  153. package/dist/components/Loader/spinner.mjs.map +1 -1
  154. package/dist/components/MarkDownRender/MarkDownRender.cjs +0 -1
  155. package/dist/components/MarkDownRender/MarkDownRender.cjs.map +1 -1
  156. package/dist/components/MarkDownRender/MarkDownRender.d.ts +147 -0
  157. package/dist/components/MarkDownRender/MarkDownRender.d.ts.map +1 -1
  158. package/dist/components/MarkDownRender/MarkDownRender.mjs +0 -1
  159. package/dist/components/MarkDownRender/MarkDownRender.mjs.map +1 -1
  160. package/dist/components/MaxHeightSmoother/index.cjs.map +1 -1
  161. package/dist/components/MaxHeightSmoother/index.d.ts +152 -0
  162. package/dist/components/MaxHeightSmoother/index.d.ts.map +1 -1
  163. package/dist/components/MaxHeightSmoother/index.mjs.map +1 -1
  164. package/dist/components/Modal/Modal.cjs +5 -0
  165. package/dist/components/Modal/Modal.cjs.map +1 -1
  166. package/dist/components/Modal/Modal.d.ts +81 -3
  167. package/dist/components/Modal/Modal.d.ts.map +1 -1
  168. package/dist/components/Modal/Modal.mjs +5 -0
  169. package/dist/components/Modal/Modal.mjs.map +1 -1
  170. package/dist/components/Navbar/Burger.cjs.map +1 -1
  171. package/dist/components/Navbar/Burger.d.ts +54 -0
  172. package/dist/components/Navbar/Burger.d.ts.map +1 -1
  173. package/dist/components/Navbar/Burger.mjs.map +1 -1
  174. package/dist/components/Navbar/DesktopNavbar.cjs.map +1 -1
  175. package/dist/components/Navbar/DesktopNavbar.d.ts +78 -0
  176. package/dist/components/Navbar/DesktopNavbar.d.ts.map +1 -1
  177. package/dist/components/Navbar/DesktopNavbar.mjs.map +1 -1
  178. package/dist/components/Navbar/MobileNavbar.cjs.map +1 -1
  179. package/dist/components/Navbar/MobileNavbar.d.ts +88 -0
  180. package/dist/components/Navbar/MobileNavbar.d.ts.map +1 -1
  181. package/dist/components/Navbar/MobileNavbar.mjs.map +1 -1
  182. package/dist/components/Navbar/index.cjs.map +1 -1
  183. package/dist/components/Navbar/index.d.ts +69 -0
  184. package/dist/components/Navbar/index.d.ts.map +1 -1
  185. package/dist/components/Navbar/index.mjs.map +1 -1
  186. package/dist/components/Navbar/useNavigation.cjs +8 -1
  187. package/dist/components/Navbar/useNavigation.cjs.map +1 -1
  188. package/dist/components/Navbar/useNavigation.d.ts +83 -0
  189. package/dist/components/Navbar/useNavigation.d.ts.map +1 -1
  190. package/dist/components/Navbar/useNavigation.mjs +8 -1
  191. package/dist/components/Navbar/useNavigation.mjs.map +1 -1
  192. package/dist/components/Pattern/DotPattern.cjs.map +1 -1
  193. package/dist/components/Pattern/DotPattern.d.ts +101 -0
  194. package/dist/components/Pattern/DotPattern.d.ts.map +1 -1
  195. package/dist/components/Pattern/DotPattern.mjs.map +1 -1
  196. package/dist/components/Pattern/GridPattern.cjs.map +1 -1
  197. package/dist/components/Pattern/GridPattern.d.ts +114 -0
  198. package/dist/components/Pattern/GridPattern.d.ts.map +1 -1
  199. package/dist/components/Pattern/GridPattern.mjs.map +1 -1
  200. package/dist/components/Pattern/SpotLight.cjs.map +1 -1
  201. package/dist/components/Pattern/SpotLight.d.ts +125 -0
  202. package/dist/components/Pattern/SpotLight.d.ts.map +1 -1
  203. package/dist/components/Pattern/SpotLight.mjs.map +1 -1
  204. package/dist/components/Popover/index.cjs +10 -10
  205. package/dist/components/Popover/index.cjs.map +1 -1
  206. package/dist/components/Popover/index.d.ts +110 -15
  207. package/dist/components/Popover/index.d.ts.map +1 -1
  208. package/dist/components/Popover/index.mjs +10 -10
  209. package/dist/components/Popover/index.mjs.map +1 -1
  210. package/dist/components/PressableSpan/PressableSpan.cjs +22 -5
  211. package/dist/components/PressableSpan/PressableSpan.cjs.map +1 -1
  212. package/dist/components/PressableSpan/PressableSpan.d.ts +105 -3
  213. package/dist/components/PressableSpan/PressableSpan.d.ts.map +1 -1
  214. package/dist/components/PressableSpan/PressableSpan.mjs +22 -5
  215. package/dist/components/PressableSpan/PressableSpan.mjs.map +1 -1
  216. package/dist/components/RightDrawer/RightDrawer.cjs.map +1 -1
  217. package/dist/components/RightDrawer/RightDrawer.d.ts +182 -0
  218. package/dist/components/RightDrawer/RightDrawer.d.ts.map +1 -1
  219. package/dist/components/RightDrawer/RightDrawer.mjs.map +1 -1
  220. package/dist/components/RightDrawer/isElementAtTopAndNotCovered.cjs.map +1 -1
  221. package/dist/components/RightDrawer/isElementAtTopAndNotCovered.d.ts +44 -0
  222. package/dist/components/RightDrawer/isElementAtTopAndNotCovered.d.ts.map +1 -1
  223. package/dist/components/RightDrawer/isElementAtTopAndNotCovered.mjs.map +1 -1
  224. package/dist/components/RightDrawer/useRightDrawerStore.cjs.map +1 -1
  225. package/dist/components/RightDrawer/useRightDrawerStore.d.ts +102 -0
  226. package/dist/components/RightDrawer/useRightDrawerStore.d.ts.map +1 -1
  227. package/dist/components/RightDrawer/useRightDrawerStore.mjs.map +1 -1
  228. package/dist/components/Select/Multiselect.cjs.map +1 -1
  229. package/dist/components/Select/Multiselect.d.ts +125 -18
  230. package/dist/components/Select/Multiselect.d.ts.map +1 -1
  231. package/dist/components/Select/Multiselect.mjs.map +1 -1
  232. package/dist/components/Select/Select.cjs.map +1 -1
  233. package/dist/components/Select/Select.d.ts +214 -7
  234. package/dist/components/Select/Select.d.ts.map +1 -1
  235. package/dist/components/Select/Select.mjs.map +1 -1
  236. package/dist/components/SwitchSelector/index.cjs.map +1 -1
  237. package/dist/components/SwitchSelector/index.d.ts +157 -8
  238. package/dist/components/SwitchSelector/index.d.ts.map +1 -1
  239. package/dist/components/SwitchSelector/index.mjs.map +1 -1
  240. package/dist/components/Table/Table.cjs.map +1 -1
  241. package/dist/components/Table/Table.d.ts +184 -0
  242. package/dist/components/Table/Table.d.ts.map +1 -1
  243. package/dist/components/Table/Table.mjs.map +1 -1
  244. package/dist/components/Tag/index.cjs.map +1 -1
  245. package/dist/components/Tag/index.d.ts +223 -0
  246. package/dist/components/Tag/index.d.ts.map +1 -1
  247. package/dist/components/Tag/index.mjs.map +1 -1
  248. package/dist/components/TextArea/AutoSizeTextArea.cjs.map +1 -1
  249. package/dist/components/TextArea/AutoSizeTextArea.d.ts +91 -0
  250. package/dist/components/TextArea/AutoSizeTextArea.d.ts.map +1 -1
  251. package/dist/components/TextArea/AutoSizeTextArea.mjs.map +1 -1
  252. package/dist/components/TextArea/AutocompleteTextArea.cjs.map +1 -1
  253. package/dist/components/TextArea/AutocompleteTextArea.d.ts +145 -0
  254. package/dist/components/TextArea/AutocompleteTextArea.d.ts.map +1 -1
  255. package/dist/components/TextArea/AutocompleteTextArea.mjs.map +1 -1
  256. package/dist/components/TextArea/TextArea.cjs.map +1 -1
  257. package/dist/components/TextArea/TextArea.d.ts +74 -0
  258. package/dist/components/TextArea/TextArea.d.ts.map +1 -1
  259. package/dist/components/TextArea/TextArea.mjs.map +1 -1
  260. package/dist/components/Toaster/Toast.cjs +4 -0
  261. package/dist/components/Toaster/Toast.cjs.map +1 -1
  262. package/dist/components/Toaster/Toast.d.ts +148 -2
  263. package/dist/components/Toaster/Toast.d.ts.map +1 -1
  264. package/dist/components/Toaster/Toast.mjs +4 -0
  265. package/dist/components/Toaster/Toast.mjs.map +1 -1
  266. package/dist/components/Toaster/Toaster.cjs.map +1 -1
  267. package/dist/components/Toaster/Toaster.d.ts +42 -0
  268. package/dist/components/Toaster/Toaster.d.ts.map +1 -1
  269. package/dist/components/Toaster/Toaster.mjs.map +1 -1
  270. package/dist/components/Toaster/useToast.cjs.map +1 -1
  271. package/dist/components/Toaster/useToast.d.ts +199 -2
  272. package/dist/components/Toaster/useToast.d.ts.map +1 -1
  273. package/dist/components/Toaster/useToast.mjs.map +1 -1
  274. package/dist/components/WithResizer/index.cjs.map +1 -1
  275. package/dist/components/WithResizer/index.d.ts +143 -0
  276. package/dist/components/WithResizer/index.d.ts.map +1 -1
  277. package/dist/components/WithResizer/index.mjs.map +1 -1
  278. package/dist/components/index.cjs +2 -2
  279. package/dist/components/index.d.ts +0 -1
  280. package/dist/components/index.d.ts.map +1 -1
  281. package/dist/components/index.mjs +4 -4
  282. package/dist/components/index.mjs.map +1 -1
  283. package/dist/hooks/reactQuery.cjs +2 -1
  284. package/dist/hooks/reactQuery.cjs.map +1 -1
  285. package/dist/hooks/reactQuery.d.ts +1 -1
  286. package/dist/hooks/reactQuery.d.ts.map +1 -1
  287. package/dist/hooks/reactQuery.mjs +2 -1
  288. package/dist/hooks/reactQuery.mjs.map +1 -1
  289. package/dist/utils/image.cjs +30 -0
  290. package/dist/utils/image.cjs.map +1 -0
  291. package/dist/utils/image.d.ts +37 -0
  292. package/dist/utils/image.d.ts.map +1 -0
  293. package/dist/utils/image.mjs +30 -0
  294. package/dist/utils/image.mjs.map +1 -0
  295. package/package.json +20 -18
  296. package/dist/utils/capitalize.cjs +0 -10
  297. package/dist/utils/capitalize.cjs.map +0 -1
  298. package/dist/utils/capitalize.d.ts +0 -2
  299. package/dist/utils/capitalize.d.ts.map +0 -1
  300. package/dist/utils/capitalize.mjs +0 -10
  301. package/dist/utils/capitalize.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../../../src/components/CopyToClipboard/index.tsx"],"sourcesContent":["'use client';\n\nimport { CopyCheck, CopyIcon } from 'lucide-react';\nimport { type FC, type PropsWithChildren, useState } from 'react';\nimport { cn } from '../../utils/cn';\n\nexport type CopyToClipboardProps = PropsWithChildren<{\n text: string;\n className?: string;\n}>;\n\nexport const CopyToClipboard: FC<CopyToClipboardProps> = ({\n text,\n children,\n className,\n}) => {\n const [isCopied, setIsCopied] = useState(false);\n\n const handleCopy = () => {\n navigator.clipboard.writeText(text).then(() => {\n setIsCopied(true);\n setTimeout(() => setIsCopied(false), 1000);\n });\n };\n\n return (\n <span\n className={cn(\n 'inline-block gap-2 hover:cursor-pointer hover:bg-neutral/10 rounded-md p-0.5',\n className\n )}\n onClick={handleCopy}\n >\n {children}\n\n <span className=\"inline-flex\">\n {text &&\n (isCopied ? (\n <CopyCheck\n size={12}\n aria-label=\"copied\"\n role=\"button\"\n data-testid=\"copy-to-clipboard\"\n className=\"ml-1 mt-1\"\n />\n ) : (\n <CopyIcon\n size={12}\n aria-label=\"copy\"\n role=\"button\"\n data-testid=\"copy-to-clipboard\"\n className=\"ml-1 mt-1 cursor-pointer\"\n />\n ))}\n </span>\n </span>\n );\n};\n"],"names":["useState","jsxs","cn","jsx","CopyCheck","CopyIcon"],"mappings":";;;;;;;AAWO,MAAM,kBAA4C,CAAC;AAAA,EACxD;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,CAAC,UAAU,WAAW,IAAIA,aAAAA,SAAS,KAAK;AAE9C,QAAM,aAAa,MAAM;AACvB,cAAU,UAAU,UAAU,IAAI,EAAE,KAAK,MAAM;AAC7C,kBAAY,IAAI;AAChB,iBAAW,MAAM,YAAY,KAAK,GAAG,GAAI;AAAA,IAC3C,CAAC;AAAA,EACH;AAEA,SACEC,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAWC,SAAAA;AAAAA,QACT;AAAA,QACA;AAAA,MAAA;AAAA,MAEF,SAAS;AAAA,MAER,UAAA;AAAA,QAAA;AAAA,QAEDC,2BAAAA,IAAC,QAAA,EAAK,WAAU,eACb,mBACE,WACCA,2BAAAA;AAAAA,UAACC,YAAAA;AAAAA,UAAA;AAAA,YACC,MAAM;AAAA,YACN,cAAW;AAAA,YACX,MAAK;AAAA,YACL,eAAY;AAAA,YACZ,WAAU;AAAA,UAAA;AAAA,QAAA,IAGZD,2BAAAA;AAAAA,UAACE,YAAAA;AAAAA,UAAA;AAAA,YACC,MAAM;AAAA,YACN,cAAW;AAAA,YACX,MAAK;AAAA,YACL,eAAY;AAAA,YACZ,WAAU;AAAA,UAAA;AAAA,QAAA,GACZ,CAEN;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGN;;"}
1
+ {"version":3,"file":"index.cjs","sources":["../../../src/components/CopyToClipboard/index.tsx"],"sourcesContent":["'use client';\n\nimport { CopyCheck, CopyIcon } from 'lucide-react';\nimport { type FC, type PropsWithChildren, useState } from 'react';\nimport { cn } from '../../utils/cn';\n\n/**\n * Props for the CopyToClipboard component\n */\nexport interface CopyToClipboardProps extends PropsWithChildren {\n /**\n * The text to copy to the clipboard when clicked\n * @example \"Hello World\"\n * @example \"npm install @intlayer/design-system\"\n */\n text: string;\n\n /**\n * Additional CSS classes for the wrapper element\n * @example \"bg-blue-100 text-blue-800\"\n */\n className?: string;\n\n /**\n * Accessible label for screen readers when copy operation is available\n * @default \"Copy to clipboard\"\n */\n 'aria-label'?: string;\n\n /**\n * Accessible label for screen readers when content has been copied\n * @default \"Copied to clipboard\"\n */\n 'aria-copied-label'?: string;\n\n /**\n * Duration in milliseconds to show the \"copied\" state\n * @default 2000\n */\n feedbackDuration?: number;\n\n /**\n * Callback function called when copy operation succeeds\n */\n onCopySuccess?: () => void;\n\n /**\n * Callback function called when copy operation fails\n */\n onCopyError?: (error: Error) => void;\n}\n\n/**\n * CopyToClipboard Component\n *\n * A versatile component that allows users to copy text to their clipboard with visual feedback.\n * Provides accessibility features, customizable feedback duration, and error handling.\n *\n * @example\n * ```tsx\n * // Basic usage\n * <CopyToClipboard text=\"Hello World\">\n * <span>Click to copy</span>\n * </CopyToClipboard>\n *\n * // With custom styling and callbacks\n * <CopyToClipboard\n * text=\"npm install @intlayer/design-system\"\n * className=\"bg-gray-100 p-2\"\n * feedbackDuration={3000}\n * onCopySuccess={() => console.log('Copied!')}\n * >\n * <code>npm install @intlayer/design-system</code>\n * </CopyToClipboard>\n * ```\n *\n * @component\n * @accessibility\n * - Uses proper ARIA labels for copy and copied states\n * - Supports keyboard navigation (Enter and Space keys)\n * - Announces state changes to screen readers\n * - Provides visual focus indicators\n */\nexport const CopyToClipboard: FC<CopyToClipboardProps> = ({\n text,\n children,\n className,\n 'aria-label': ariaLabel = 'Copy to clipboard',\n 'aria-copied-label': ariaCopiedLabel = 'Copied to clipboard',\n feedbackDuration = 2000,\n onCopySuccess,\n onCopyError,\n}) => {\n const [isCopied, setIsCopied] = useState(false);\n const [copyError, setCopyError] = useState<string | null>(null);\n\n const handleCopy = async () => {\n if (!text) return;\n\n try {\n setCopyError(null);\n\n if (navigator.clipboard && navigator.clipboard.writeText) {\n await navigator.clipboard.writeText(text);\n } else {\n // Fallback for older browsers\n const textArea = document.createElement('textarea');\n textArea.value = text;\n textArea.style.position = 'fixed';\n textArea.style.left = '-999999px';\n textArea.style.top = '-999999px';\n document.body.appendChild(textArea);\n textArea.focus();\n textArea.select();\n document.execCommand('copy');\n document.body.removeChild(textArea);\n }\n\n setIsCopied(true);\n setTimeout(() => setIsCopied(false), feedbackDuration);\n onCopySuccess?.();\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : 'Failed to copy to clipboard';\n setCopyError(errorMessage);\n onCopyError?.(error instanceof Error ? error : new Error(errorMessage));\n\n // Clear error after feedback duration\n setTimeout(() => setCopyError(null), feedbackDuration);\n }\n };\n\n const handleKeyDown = (event: React.KeyboardEvent) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n handleCopy();\n }\n };\n\n const currentAriaLabel = copyError\n ? `Error copying to clipboard: ${copyError}`\n : isCopied\n ? ariaCopiedLabel\n : ariaLabel;\n\n const IconComponent = copyError ? CopyIcon : isCopied ? CopyCheck : CopyIcon;\n\n return (\n <span\n className={cn(\n 'inline-flex gap-2 hover:cursor-pointer hover:bg-neutral/10 rounded-md p-0.5',\n className\n )}\n onClick={handleCopy}\n onKeyDown={handleKeyDown}\n role=\"button\"\n tabIndex={0}\n aria-label={currentAriaLabel}\n aria-pressed={isCopied}\n data-testid=\"copy-to-clipboard\"\n >\n {children}\n\n {text && (\n <IconComponent\n size={12}\n className={cn(\n 'ml-1 transition-colors duration-200',\n copyError && 'text-destructive',\n isCopied && 'text-success',\n !copyError &&\n !isCopied &&\n 'text-muted-foreground hover:text-foreground'\n )}\n aria-hidden=\"true\"\n />\n )}\n </span>\n );\n};\n"],"names":["useState","CopyIcon","CopyCheck","jsxs","cn","jsx"],"mappings":";;;;;;;AAmFO,MAAM,kBAA4C,CAAC;AAAA,EACxD;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc,YAAY;AAAA,EAC1B,qBAAqB,kBAAkB;AAAA,EACvC,mBAAmB;AAAA,EACnB;AAAA,EACA;AACF,MAAM;AACJ,QAAM,CAAC,UAAU,WAAW,IAAIA,aAAAA,SAAS,KAAK;AAC9C,QAAM,CAAC,WAAW,YAAY,IAAIA,aAAAA,SAAwB,IAAI;AAE9D,QAAM,aAAa,YAAY;AAC7B,QAAI,CAAC,KAAM;AAEX,QAAI;AACF,mBAAa,IAAI;AAEjB,UAAI,UAAU,aAAa,UAAU,UAAU,WAAW;AACxD,cAAM,UAAU,UAAU,UAAU,IAAI;AAAA,MAC1C,OAAO;AAEL,cAAM,WAAW,SAAS,cAAc,UAAU;AAClD,iBAAS,QAAQ;AACjB,iBAAS,MAAM,WAAW;AAC1B,iBAAS,MAAM,OAAO;AACtB,iBAAS,MAAM,MAAM;AACrB,iBAAS,KAAK,YAAY,QAAQ;AAClC,iBAAS,MAAA;AACT,iBAAS,OAAA;AACT,iBAAS,YAAY,MAAM;AAC3B,iBAAS,KAAK,YAAY,QAAQ;AAAA,MACpC;AAEA,kBAAY,IAAI;AAChB,iBAAW,MAAM,YAAY,KAAK,GAAG,gBAAgB;AACrD,sBAAA;AAAA,IACF,SAAS,OAAO;AACd,YAAM,eACJ,iBAAiB,QAAQ,MAAM,UAAU;AAC3C,mBAAa,YAAY;AACzB,oBAAc,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,YAAY,CAAC;AAGtE,iBAAW,MAAM,aAAa,IAAI,GAAG,gBAAgB;AAAA,IACvD;AAAA,EACF;AAEA,QAAM,gBAAgB,CAAC,UAA+B;AACpD,QAAI,MAAM,QAAQ,WAAW,MAAM,QAAQ,KAAK;AAC9C,YAAM,eAAA;AACN,iBAAA;AAAA,IACF;AAAA,EACF;AAEA,QAAM,mBAAmB,YACrB,+BAA+B,SAAS,KACxC,WACE,kBACA;AAEN,QAAM,gBAAgB,YAAYC,YAAAA,WAAW,WAAWC,YAAAA,YAAYD,YAAAA;AAEpE,SACEE,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAWC,SAAAA;AAAAA,QACT;AAAA,QACA;AAAA,MAAA;AAAA,MAEF,SAAS;AAAA,MACT,WAAW;AAAA,MACX,MAAK;AAAA,MACL,UAAU;AAAA,MACV,cAAY;AAAA,MACZ,gBAAc;AAAA,MACd,eAAY;AAAA,MAEX,UAAA;AAAA,QAAA;AAAA,QAEA,QACCC,2BAAAA;AAAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAM;AAAA,YACN,WAAWD,SAAAA;AAAAA,cACT;AAAA,cACA,aAAa;AAAA,cACb,YAAY;AAAA,cACZ,CAAC,aACC,CAAC,YACD;AAAA,YAAA;AAAA,YAEJ,eAAY;AAAA,UAAA;AAAA,QAAA;AAAA,MACd;AAAA,IAAA;AAAA,EAAA;AAIR;;"}
@@ -1,7 +1,73 @@
1
1
  import { FC, PropsWithChildren } from 'react';
2
- export type CopyToClipboardProps = PropsWithChildren<{
2
+ /**
3
+ * Props for the CopyToClipboard component
4
+ */
5
+ export interface CopyToClipboardProps extends PropsWithChildren {
6
+ /**
7
+ * The text to copy to the clipboard when clicked
8
+ * @example "Hello World"
9
+ * @example "npm install @intlayer/design-system"
10
+ */
3
11
  text: string;
12
+ /**
13
+ * Additional CSS classes for the wrapper element
14
+ * @example "bg-blue-100 text-blue-800"
15
+ */
4
16
  className?: string;
5
- }>;
17
+ /**
18
+ * Accessible label for screen readers when copy operation is available
19
+ * @default "Copy to clipboard"
20
+ */
21
+ 'aria-label'?: string;
22
+ /**
23
+ * Accessible label for screen readers when content has been copied
24
+ * @default "Copied to clipboard"
25
+ */
26
+ 'aria-copied-label'?: string;
27
+ /**
28
+ * Duration in milliseconds to show the "copied" state
29
+ * @default 2000
30
+ */
31
+ feedbackDuration?: number;
32
+ /**
33
+ * Callback function called when copy operation succeeds
34
+ */
35
+ onCopySuccess?: () => void;
36
+ /**
37
+ * Callback function called when copy operation fails
38
+ */
39
+ onCopyError?: (error: Error) => void;
40
+ }
41
+ /**
42
+ * CopyToClipboard Component
43
+ *
44
+ * A versatile component that allows users to copy text to their clipboard with visual feedback.
45
+ * Provides accessibility features, customizable feedback duration, and error handling.
46
+ *
47
+ * @example
48
+ * ```tsx
49
+ * // Basic usage
50
+ * <CopyToClipboard text="Hello World">
51
+ * <span>Click to copy</span>
52
+ * </CopyToClipboard>
53
+ *
54
+ * // With custom styling and callbacks
55
+ * <CopyToClipboard
56
+ * text="npm install @intlayer/design-system"
57
+ * className="bg-gray-100 p-2"
58
+ * feedbackDuration={3000}
59
+ * onCopySuccess={() => console.log('Copied!')}
60
+ * >
61
+ * <code>npm install @intlayer/design-system</code>
62
+ * </CopyToClipboard>
63
+ * ```
64
+ *
65
+ * @component
66
+ * @accessibility
67
+ * - Uses proper ARIA labels for copy and copied states
68
+ * - Supports keyboard navigation (Enter and Space keys)
69
+ * - Announces state changes to screen readers
70
+ * - Provides visual focus indicators
71
+ */
6
72
  export declare const CopyToClipboard: FC<CopyToClipboardProps>;
7
73
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/CopyToClipboard/index.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,EAAE,EAAE,KAAK,iBAAiB,EAAY,MAAM,OAAO,CAAC;AAGlE,MAAM,MAAM,oBAAoB,GAAG,iBAAiB,CAAC;IACnD,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC,CAAC;AAEH,eAAO,MAAM,eAAe,EAAE,EAAE,CAAC,oBAAoB,CA8CpD,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/CopyToClipboard/index.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,EAAE,EAAE,KAAK,iBAAiB,EAAY,MAAM,OAAO,CAAC;AAGlE;;GAEG;AACH,MAAM,WAAW,oBAAqB,SAAQ,iBAAiB;IAC7D;;;;OAIG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAE7B;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAE3B;;OAEG;IACH,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CACtC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,eAAO,MAAM,eAAe,EAAE,EAAE,CAAC,oBAAoB,CAgGpD,CAAC"}
@@ -1,49 +1,85 @@
1
1
  "use client";
2
2
  import { jsxs, jsx } from "react/jsx-runtime";
3
- import { CopyCheck, CopyIcon } from "lucide-react";
3
+ import { CopyIcon, CopyCheck } from "lucide-react";
4
4
  import { useState } from "react";
5
5
  import { cn } from "../../utils/cn.mjs";
6
6
  const CopyToClipboard = ({
7
7
  text,
8
8
  children,
9
- className
9
+ className,
10
+ "aria-label": ariaLabel = "Copy to clipboard",
11
+ "aria-copied-label": ariaCopiedLabel = "Copied to clipboard",
12
+ feedbackDuration = 2e3,
13
+ onCopySuccess,
14
+ onCopyError
10
15
  }) => {
11
16
  const [isCopied, setIsCopied] = useState(false);
12
- const handleCopy = () => {
13
- navigator.clipboard.writeText(text).then(() => {
17
+ const [copyError, setCopyError] = useState(null);
18
+ const handleCopy = async () => {
19
+ if (!text) return;
20
+ try {
21
+ setCopyError(null);
22
+ if (navigator.clipboard && navigator.clipboard.writeText) {
23
+ await navigator.clipboard.writeText(text);
24
+ } else {
25
+ const textArea = document.createElement("textarea");
26
+ textArea.value = text;
27
+ textArea.style.position = "fixed";
28
+ textArea.style.left = "-999999px";
29
+ textArea.style.top = "-999999px";
30
+ document.body.appendChild(textArea);
31
+ textArea.focus();
32
+ textArea.select();
33
+ document.execCommand("copy");
34
+ document.body.removeChild(textArea);
35
+ }
14
36
  setIsCopied(true);
15
- setTimeout(() => setIsCopied(false), 1e3);
16
- });
37
+ setTimeout(() => setIsCopied(false), feedbackDuration);
38
+ onCopySuccess?.();
39
+ } catch (error) {
40
+ const errorMessage = error instanceof Error ? error.message : "Failed to copy to clipboard";
41
+ setCopyError(errorMessage);
42
+ onCopyError?.(error instanceof Error ? error : new Error(errorMessage));
43
+ setTimeout(() => setCopyError(null), feedbackDuration);
44
+ }
45
+ };
46
+ const handleKeyDown = (event) => {
47
+ if (event.key === "Enter" || event.key === " ") {
48
+ event.preventDefault();
49
+ handleCopy();
50
+ }
17
51
  };
52
+ const currentAriaLabel = copyError ? `Error copying to clipboard: ${copyError}` : isCopied ? ariaCopiedLabel : ariaLabel;
53
+ const IconComponent = copyError ? CopyIcon : isCopied ? CopyCheck : CopyIcon;
18
54
  return /* @__PURE__ */ jsxs(
19
55
  "span",
20
56
  {
21
57
  className: cn(
22
- "inline-block gap-2 hover:cursor-pointer hover:bg-neutral/10 rounded-md p-0.5",
58
+ "inline-flex gap-2 hover:cursor-pointer hover:bg-neutral/10 rounded-md p-0.5",
23
59
  className
24
60
  ),
25
61
  onClick: handleCopy,
62
+ onKeyDown: handleKeyDown,
63
+ role: "button",
64
+ tabIndex: 0,
65
+ "aria-label": currentAriaLabel,
66
+ "aria-pressed": isCopied,
67
+ "data-testid": "copy-to-clipboard",
26
68
  children: [
27
69
  children,
28
- /* @__PURE__ */ jsx("span", { className: "inline-flex", children: text && (isCopied ? /* @__PURE__ */ jsx(
29
- CopyCheck,
30
- {
31
- size: 12,
32
- "aria-label": "copied",
33
- role: "button",
34
- "data-testid": "copy-to-clipboard",
35
- className: "ml-1 mt-1"
36
- }
37
- ) : /* @__PURE__ */ jsx(
38
- CopyIcon,
70
+ text && /* @__PURE__ */ jsx(
71
+ IconComponent,
39
72
  {
40
73
  size: 12,
41
- "aria-label": "copy",
42
- role: "button",
43
- "data-testid": "copy-to-clipboard",
44
- className: "ml-1 mt-1 cursor-pointer"
74
+ className: cn(
75
+ "ml-1 transition-colors duration-200",
76
+ copyError && "text-destructive",
77
+ isCopied && "text-success",
78
+ !copyError && !isCopied && "text-muted-foreground hover:text-foreground"
79
+ ),
80
+ "aria-hidden": "true"
45
81
  }
46
- )) })
82
+ )
47
83
  ]
48
84
  }
49
85
  );
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../../../src/components/CopyToClipboard/index.tsx"],"sourcesContent":["'use client';\n\nimport { CopyCheck, CopyIcon } from 'lucide-react';\nimport { type FC, type PropsWithChildren, useState } from 'react';\nimport { cn } from '../../utils/cn';\n\nexport type CopyToClipboardProps = PropsWithChildren<{\n text: string;\n className?: string;\n}>;\n\nexport const CopyToClipboard: FC<CopyToClipboardProps> = ({\n text,\n children,\n className,\n}) => {\n const [isCopied, setIsCopied] = useState(false);\n\n const handleCopy = () => {\n navigator.clipboard.writeText(text).then(() => {\n setIsCopied(true);\n setTimeout(() => setIsCopied(false), 1000);\n });\n };\n\n return (\n <span\n className={cn(\n 'inline-block gap-2 hover:cursor-pointer hover:bg-neutral/10 rounded-md p-0.5',\n className\n )}\n onClick={handleCopy}\n >\n {children}\n\n <span className=\"inline-flex\">\n {text &&\n (isCopied ? (\n <CopyCheck\n size={12}\n aria-label=\"copied\"\n role=\"button\"\n data-testid=\"copy-to-clipboard\"\n className=\"ml-1 mt-1\"\n />\n ) : (\n <CopyIcon\n size={12}\n aria-label=\"copy\"\n role=\"button\"\n data-testid=\"copy-to-clipboard\"\n className=\"ml-1 mt-1 cursor-pointer\"\n />\n ))}\n </span>\n </span>\n );\n};\n"],"names":[],"mappings":";;;;;AAWO,MAAM,kBAA4C,CAAC;AAAA,EACxD;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,KAAK;AAE9C,QAAM,aAAa,MAAM;AACvB,cAAU,UAAU,UAAU,IAAI,EAAE,KAAK,MAAM;AAC7C,kBAAY,IAAI;AAChB,iBAAW,MAAM,YAAY,KAAK,GAAG,GAAI;AAAA,IAC3C,CAAC;AAAA,EACH;AAEA,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MAAA;AAAA,MAEF,SAAS;AAAA,MAER,UAAA;AAAA,QAAA;AAAA,QAED,oBAAC,QAAA,EAAK,WAAU,eACb,mBACE,WACC;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAM;AAAA,YACN,cAAW;AAAA,YACX,MAAK;AAAA,YACL,eAAY;AAAA,YACZ,WAAU;AAAA,UAAA;AAAA,QAAA,IAGZ;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAM;AAAA,YACN,cAAW;AAAA,YACX,MAAK;AAAA,YACL,eAAY;AAAA,YACZ,WAAU;AAAA,UAAA;AAAA,QAAA,GACZ,CAEN;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGN;"}
1
+ {"version":3,"file":"index.mjs","sources":["../../../src/components/CopyToClipboard/index.tsx"],"sourcesContent":["'use client';\n\nimport { CopyCheck, CopyIcon } from 'lucide-react';\nimport { type FC, type PropsWithChildren, useState } from 'react';\nimport { cn } from '../../utils/cn';\n\n/**\n * Props for the CopyToClipboard component\n */\nexport interface CopyToClipboardProps extends PropsWithChildren {\n /**\n * The text to copy to the clipboard when clicked\n * @example \"Hello World\"\n * @example \"npm install @intlayer/design-system\"\n */\n text: string;\n\n /**\n * Additional CSS classes for the wrapper element\n * @example \"bg-blue-100 text-blue-800\"\n */\n className?: string;\n\n /**\n * Accessible label for screen readers when copy operation is available\n * @default \"Copy to clipboard\"\n */\n 'aria-label'?: string;\n\n /**\n * Accessible label for screen readers when content has been copied\n * @default \"Copied to clipboard\"\n */\n 'aria-copied-label'?: string;\n\n /**\n * Duration in milliseconds to show the \"copied\" state\n * @default 2000\n */\n feedbackDuration?: number;\n\n /**\n * Callback function called when copy operation succeeds\n */\n onCopySuccess?: () => void;\n\n /**\n * Callback function called when copy operation fails\n */\n onCopyError?: (error: Error) => void;\n}\n\n/**\n * CopyToClipboard Component\n *\n * A versatile component that allows users to copy text to their clipboard with visual feedback.\n * Provides accessibility features, customizable feedback duration, and error handling.\n *\n * @example\n * ```tsx\n * // Basic usage\n * <CopyToClipboard text=\"Hello World\">\n * <span>Click to copy</span>\n * </CopyToClipboard>\n *\n * // With custom styling and callbacks\n * <CopyToClipboard\n * text=\"npm install @intlayer/design-system\"\n * className=\"bg-gray-100 p-2\"\n * feedbackDuration={3000}\n * onCopySuccess={() => console.log('Copied!')}\n * >\n * <code>npm install @intlayer/design-system</code>\n * </CopyToClipboard>\n * ```\n *\n * @component\n * @accessibility\n * - Uses proper ARIA labels for copy and copied states\n * - Supports keyboard navigation (Enter and Space keys)\n * - Announces state changes to screen readers\n * - Provides visual focus indicators\n */\nexport const CopyToClipboard: FC<CopyToClipboardProps> = ({\n text,\n children,\n className,\n 'aria-label': ariaLabel = 'Copy to clipboard',\n 'aria-copied-label': ariaCopiedLabel = 'Copied to clipboard',\n feedbackDuration = 2000,\n onCopySuccess,\n onCopyError,\n}) => {\n const [isCopied, setIsCopied] = useState(false);\n const [copyError, setCopyError] = useState<string | null>(null);\n\n const handleCopy = async () => {\n if (!text) return;\n\n try {\n setCopyError(null);\n\n if (navigator.clipboard && navigator.clipboard.writeText) {\n await navigator.clipboard.writeText(text);\n } else {\n // Fallback for older browsers\n const textArea = document.createElement('textarea');\n textArea.value = text;\n textArea.style.position = 'fixed';\n textArea.style.left = '-999999px';\n textArea.style.top = '-999999px';\n document.body.appendChild(textArea);\n textArea.focus();\n textArea.select();\n document.execCommand('copy');\n document.body.removeChild(textArea);\n }\n\n setIsCopied(true);\n setTimeout(() => setIsCopied(false), feedbackDuration);\n onCopySuccess?.();\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : 'Failed to copy to clipboard';\n setCopyError(errorMessage);\n onCopyError?.(error instanceof Error ? error : new Error(errorMessage));\n\n // Clear error after feedback duration\n setTimeout(() => setCopyError(null), feedbackDuration);\n }\n };\n\n const handleKeyDown = (event: React.KeyboardEvent) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n handleCopy();\n }\n };\n\n const currentAriaLabel = copyError\n ? `Error copying to clipboard: ${copyError}`\n : isCopied\n ? ariaCopiedLabel\n : ariaLabel;\n\n const IconComponent = copyError ? CopyIcon : isCopied ? CopyCheck : CopyIcon;\n\n return (\n <span\n className={cn(\n 'inline-flex gap-2 hover:cursor-pointer hover:bg-neutral/10 rounded-md p-0.5',\n className\n )}\n onClick={handleCopy}\n onKeyDown={handleKeyDown}\n role=\"button\"\n tabIndex={0}\n aria-label={currentAriaLabel}\n aria-pressed={isCopied}\n data-testid=\"copy-to-clipboard\"\n >\n {children}\n\n {text && (\n <IconComponent\n size={12}\n className={cn(\n 'ml-1 transition-colors duration-200',\n copyError && 'text-destructive',\n isCopied && 'text-success',\n !copyError &&\n !isCopied &&\n 'text-muted-foreground hover:text-foreground'\n )}\n aria-hidden=\"true\"\n />\n )}\n </span>\n );\n};\n"],"names":[],"mappings":";;;;;AAmFO,MAAM,kBAA4C,CAAC;AAAA,EACxD;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc,YAAY;AAAA,EAC1B,qBAAqB,kBAAkB;AAAA,EACvC,mBAAmB;AAAA,EACnB;AAAA,EACA;AACF,MAAM;AACJ,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,KAAK;AAC9C,QAAM,CAAC,WAAW,YAAY,IAAI,SAAwB,IAAI;AAE9D,QAAM,aAAa,YAAY;AAC7B,QAAI,CAAC,KAAM;AAEX,QAAI;AACF,mBAAa,IAAI;AAEjB,UAAI,UAAU,aAAa,UAAU,UAAU,WAAW;AACxD,cAAM,UAAU,UAAU,UAAU,IAAI;AAAA,MAC1C,OAAO;AAEL,cAAM,WAAW,SAAS,cAAc,UAAU;AAClD,iBAAS,QAAQ;AACjB,iBAAS,MAAM,WAAW;AAC1B,iBAAS,MAAM,OAAO;AACtB,iBAAS,MAAM,MAAM;AACrB,iBAAS,KAAK,YAAY,QAAQ;AAClC,iBAAS,MAAA;AACT,iBAAS,OAAA;AACT,iBAAS,YAAY,MAAM;AAC3B,iBAAS,KAAK,YAAY,QAAQ;AAAA,MACpC;AAEA,kBAAY,IAAI;AAChB,iBAAW,MAAM,YAAY,KAAK,GAAG,gBAAgB;AACrD,sBAAA;AAAA,IACF,SAAS,OAAO;AACd,YAAM,eACJ,iBAAiB,QAAQ,MAAM,UAAU;AAC3C,mBAAa,YAAY;AACzB,oBAAc,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,YAAY,CAAC;AAGtE,iBAAW,MAAM,aAAa,IAAI,GAAG,gBAAgB;AAAA,IACvD;AAAA,EACF;AAEA,QAAM,gBAAgB,CAAC,UAA+B;AACpD,QAAI,MAAM,QAAQ,WAAW,MAAM,QAAQ,KAAK;AAC9C,YAAM,eAAA;AACN,iBAAA;AAAA,IACF;AAAA,EACF;AAEA,QAAM,mBAAmB,YACrB,+BAA+B,SAAS,KACxC,WACE,kBACA;AAEN,QAAM,gBAAgB,YAAY,WAAW,WAAW,YAAY;AAEpE,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MAAA;AAAA,MAEF,SAAS;AAAA,MACT,WAAW;AAAA,MACX,MAAK;AAAA,MACL,UAAU;AAAA,MACV,cAAY;AAAA,MACZ,gBAAc;AAAA,MACd,eAAY;AAAA,MAEX,UAAA;AAAA,QAAA;AAAA,QAEA,QACC;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAM;AAAA,YACN,WAAW;AAAA,cACT;AAAA,cACA,aAAa;AAAA,cACb,YAAY;AAAA,cACZ,CAAC,aACC,CAAC,YACD;AAAA,YAAA;AAAA,YAEJ,eAAY;AAAA,UAAA;AAAA,QAAA;AAAA,MACd;AAAA,IAAA;AAAA,EAAA;AAIR;"}
@@ -14,8 +14,7 @@ const DropDown = ({
14
14
  {
15
15
  className: utils_cn.cn(`group/dropdown relative flex`, className),
16
16
  "aria-label": `DropDown ${identifier}`,
17
- id: `unrollable-panel-button-${identifier}`,
18
- "aria-haspopup": true,
17
+ id: `dropdown-container-${identifier}`,
19
18
  ...props,
20
19
  children
21
20
  }
@@ -31,6 +30,9 @@ const Trigger = ({
31
30
  {
32
31
  className: utils_cn.cn("w-full cursor-pointer", className),
33
32
  label: label ?? `Open panel ${identifier}`,
33
+ "aria-haspopup": "true",
34
+ "aria-controls": `dropdown-panel-${identifier}`,
35
+ id: `dropdown-trigger-${identifier}`,
34
36
  onClick: (e) => {
35
37
  e.currentTarget.focus();
36
38
  },
@@ -64,8 +66,8 @@ const Panel = ({
64
66
  ),
65
67
  "aria-hidden": isHidden,
66
68
  role: "region",
67
- "aria-labelledby": `unrollable-panel-button-${identifier}`,
68
- id: `unrollable-panel-${identifier}`,
69
+ "aria-labelledby": `dropdown-trigger-${identifier}`,
70
+ id: `dropdown-panel-${identifier}`,
69
71
  children: /* @__PURE__ */ jsxRuntime.jsx(
70
72
  components_MaxHeightSmoother_index.MaxHeightSmoother,
71
73
  {
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../../../src/components/DropDown/index.tsx"],"sourcesContent":["import type { FC, HTMLAttributes } from 'react';\nimport { cn } from '../../utils/cn';\nimport { Button, ButtonProps } from '../Button';\nimport { MaxHeightSmoother } from '../MaxHeightSmoother';\n\nexport type DropDownProps = HTMLAttributes<HTMLDivElement> & {\n identifier: string;\n};\n\nexport type DropDownType = FC<DropDownProps> & {\n Trigger: FC<TriggerProps>;\n Panel: FC<PanelProps>;\n};\n\n/**\n * Trigger allowing to open a dropdown menu.\n *\n * Example:\n * ```jsx\n * <DropDown identifier=\"dropdown\">\n * <DropDown.Trigger>\n * Open dropdown\n * </DropDown.Trigger>\n *\n * <DropDown.Panel identifier=\"dropdown\">\n * <div>Content</div>\n * </DropDown.Panel>\n * </DropDown>\n * ```\n *\n * > Note DropDown.Trigger can be replaced by a button. Don't add a button inside the trigger.\n */\nexport const DropDown: DropDownType = ({\n children,\n className,\n identifier,\n ...props\n}) => (\n <div\n className={cn(`group/dropdown relative flex`, className)}\n aria-label={`DropDown ${identifier}`}\n id={`unrollable-panel-button-${identifier}`}\n aria-haspopup\n {...props}\n >\n {children}\n </div>\n);\n\nexport type TriggerProps = Partial<ButtonProps> & {\n identifier: string;\n};\n\n/**\n * Trigger allowing to open a dropdown menu.\n *\n * Example:\n * ```jsx\n * <DropDown.Trigger identifier=\"dropdown\">\n * <div>Open dropdown</div>\n * </DropDown.Trigger>\n * ```\n *\n * > Note DropDown.Trigger can be replaced by a button. Don't add a button inside the trigger.\n */\nconst Trigger: FC<TriggerProps> = ({\n children,\n identifier,\n className,\n label,\n ...props\n}) => (\n <Button\n className={cn('w-full cursor-pointer', className)}\n label={label ?? `Open panel ${identifier}`}\n onClick={(e) => {\n // Ensure focus behavior is consistent across all mobile browsers\n (e.currentTarget as HTMLButtonElement).focus();\n }}\n // onBlur={(e) => {\n // // Default behavior: ensure the trigger is unfocused when leaving the dropdown\n // e.currentTarget.blur();\n // }}\n variant=\"none\"\n {...props}\n >\n {children}\n </Button>\n);\n\nexport enum DropDownAlign {\n START = 'start',\n END = 'end',\n}\n\nexport type PanelProps = HTMLAttributes<HTMLDivElement> & {\n isFocusable?: boolean;\n isHidden?: boolean;\n isOverable?: boolean;\n identifier: string;\n align?: DropDownAlign | `${DropDownAlign}`;\n};\n\n/**\n * Component that opens a dropdown menu when the trigger is clicked.\n *\n * Example:\n * ```jsx\n * <DropDown.Panel identifier=\"dropdown\">\n * <div>Content</div>\n * </DropDown.Panel>\n * ```\n */\nconst Panel: FC<PanelProps> = ({\n children,\n isHidden = undefined,\n isOverable = false,\n isFocusable = false,\n align = DropDownAlign.START,\n identifier,\n className,\n ...props\n}) => (\n <div\n className={cn(\n 'absolute top-[calc(100%+0.5rem)] z-[1000] min-w-full',\n align === DropDownAlign.START && 'left-0',\n align === DropDownAlign.END && 'right-0',\n className\n )}\n aria-hidden={isHidden}\n role=\"region\"\n aria-labelledby={`unrollable-panel-button-${identifier}`}\n id={`unrollable-panel-${identifier}`}\n >\n <MaxHeightSmoother\n isHidden={isHidden}\n className={cn(\n 'overflow-x-visible',\n isHidden === false && 'invisible',\n isHidden === true && 'visible',\n isOverable &&\n 'group-hover/dropdown:visible group-hover/dropdown:grid-rows-[1fr]',\n isFocusable &&\n 'group-focus-within/dropdown:visible group-focus-within/dropdown:grid-rows-[1fr]'\n )}\n {...props}\n >\n {children}\n </MaxHeightSmoother>\n </div>\n);\n\nDropDown.Trigger = Trigger;\nDropDown.Panel = Panel;\n"],"names":["jsx","cn","Button","DropDownAlign","MaxHeightSmoother"],"mappings":";;;;;;AAgCO,MAAM,WAAyB,CAAC;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,MACEA,2BAAAA;AAAAA,EAAC;AAAA,EAAA;AAAA,IACC,WAAWC,SAAAA,GAAG,gCAAgC,SAAS;AAAA,IACvD,cAAY,YAAY,UAAU;AAAA,IAClC,IAAI,2BAA2B,UAAU;AAAA,IACzC,iBAAa;AAAA,IACZ,GAAG;AAAA,IAEH;AAAA,EAAA;AACH;AAmBF,MAAM,UAA4B,CAAC;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,MACED,2BAAAA;AAAAA,EAACE,yBAAAA;AAAAA,EAAA;AAAA,IACC,WAAWD,SAAAA,GAAG,yBAAyB,SAAS;AAAA,IAChD,OAAO,SAAS,cAAc,UAAU;AAAA,IACxC,SAAS,CAAC,MAAM;AAEb,QAAE,cAAoC,MAAA;AAAA,IACzC;AAAA,IAKA,SAAQ;AAAA,IACP,GAAG;AAAA,IAEH;AAAA,EAAA;AACH;AAGK,IAAK,kCAAAE,mBAAL;AACLA,iBAAA,OAAA,IAAQ;AACRA,iBAAA,KAAA,IAAM;AAFI,SAAAA;AAAA,GAAA,iBAAA,CAAA,CAAA;AAuBZ,MAAM,QAAwB,CAAC;AAAA,EAC7B;AAAA,EACA,WAAW;AAAA,EACX,aAAa;AAAA,EACb,cAAc;AAAA,EACd,QAAQ;AAAA,EACR;AAAA,EACA;AAAA,EACA,GAAG;AACL,MACEH,2BAAAA;AAAAA,EAAC;AAAA,EAAA;AAAA,IACC,WAAWC,SAAAA;AAAAA,MACT;AAAA,MACA,UAAU,WAAuB;AAAA,MACjC,UAAU,SAAqB;AAAA,MAC/B;AAAA,IAAA;AAAA,IAEF,eAAa;AAAA,IACb,MAAK;AAAA,IACL,mBAAiB,2BAA2B,UAAU;AAAA,IACtD,IAAI,oBAAoB,UAAU;AAAA,IAElC,UAAAD,2BAAAA;AAAAA,MAACI,mCAAAA;AAAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAWH,SAAAA;AAAAA,UACT;AAAA,UACA,aAAa,SAAS;AAAA,UACtB,aAAa,QAAQ;AAAA,UACrB,cACE;AAAA,UACF,eACE;AAAA,QAAA;AAAA,QAEH,GAAG;AAAA,QAEH;AAAA,MAAA;AAAA,IAAA;AAAA,EACH;AACF;AAGF,SAAS,UAAU;AACnB,SAAS,QAAQ;;;"}
1
+ {"version":3,"file":"index.cjs","sources":["../../../src/components/DropDown/index.tsx"],"sourcesContent":["import type { FC, HTMLAttributes } from 'react';\nimport { cn } from '../../utils/cn';\nimport { Button, ButtonProps } from '../Button';\nimport { MaxHeightSmoother } from '../MaxHeightSmoother';\n\n/**\n * Props for the DropDown component\n */\nexport interface DropDownProps extends HTMLAttributes<HTMLDivElement> {\n /**\n * Unique identifier that links the trigger and panel for accessibility.\n * This is used to generate proper ARIA attributes.\n * @example \"user-menu\"\n * @example \"language-selector\"\n */\n identifier: string;\n}\n\nexport type DropDownType = FC<DropDownProps> & {\n Trigger: FC<TriggerProps>;\n Panel: FC<PanelProps>;\n};\n\n/**\n * DropDown Component\n *\n * A compound component that provides dropdown/popover functionality with flexible trigger mechanisms.\n * Supports hover, focus, and controlled visibility states with proper accessibility features.\n *\n * @example\n * ```tsx\n * // Basic hover dropdown\n * <DropDown identifier=\"menu\">\n * <DropDown.Trigger identifier=\"menu\">\n * Open Menu\n * </DropDown.Trigger>\n * <DropDown.Panel identifier=\"menu\" isOverable>\n * <div>Menu content</div>\n * </DropDown.Panel>\n * </DropDown>\n *\n * // Focus-based dropdown for accessibility\n * <DropDown identifier=\"accessible-menu\">\n * <DropDown.Trigger identifier=\"accessible-menu\">\n * Keyboard Accessible Menu\n * </DropDown.Trigger>\n * <DropDown.Panel identifier=\"accessible-menu\" isFocusable>\n * <div>Accessible content</div>\n * </DropDown.Panel>\n * </DropDown>\n *\n * // Controlled dropdown\n * <DropDown identifier=\"controlled\">\n * <DropDown.Trigger identifier=\"controlled\">\n * Controlled Menu\n * </DropDown.Trigger>\n * <DropDown.Panel identifier=\"controlled\" isHidden={!isOpen}>\n * <div>Controlled content</div>\n * </DropDown.Panel>\n * </DropDown>\n * ```\n *\n * @component\n * @accessibility\n * - Uses proper ARIA attributes (aria-haspopup, aria-labelledby, etc.)\n * - Supports keyboard navigation with focus management\n * - Screen reader compatible with proper role and labeling\n * - Maintains focus trap within dropdown when needed\n */\nexport const DropDown: DropDownType = ({\n children,\n className,\n identifier,\n ...props\n}) => (\n <div\n className={cn(`group/dropdown relative flex`, className)}\n aria-label={`DropDown ${identifier}`}\n id={`dropdown-container-${identifier}`}\n {...props}\n >\n {children}\n </div>\n);\n\n/**\n * Props for the DropDown.Trigger component\n */\nexport interface TriggerProps extends Partial<ButtonProps> {\n /**\n * Unique identifier that matches the parent DropDown identifier\n * @example \"user-menu\"\n */\n identifier: string;\n}\n\n/**\n * DropDown.Trigger Component\n *\n * The clickable/focusable element that controls the dropdown panel visibility.\n * Built on top of the Button component with enhanced dropdown-specific behaviors.\n *\n * @example\n * ```tsx\n * <DropDown.Trigger identifier=\"menu\">\n * <div>Click to open</div>\n * </DropDown.Trigger>\n * ```\n *\n * @component\n * @accessibility\n * - Automatically generates appropriate ARIA attributes\n * - Maintains proper focus management across browsers\n * - Works with keyboard navigation (Tab, Enter, Space)\n * - Announces dropdown state to screen readers\n *\n * @note Don't nest Button components inside the Trigger - it's already a button\n */\nconst Trigger: FC<TriggerProps> = ({\n children,\n identifier,\n className,\n label,\n ...props\n}) => (\n <Button\n className={cn('w-full cursor-pointer', className)}\n label={label ?? `Open panel ${identifier}`}\n aria-haspopup=\"true\"\n aria-controls={`dropdown-panel-${identifier}`}\n id={`dropdown-trigger-${identifier}`}\n onClick={(e) => {\n // Ensure focus behavior is consistent across all mobile browsers\n (e.currentTarget as HTMLButtonElement).focus();\n }}\n // onBlur={(e) => {\n // // Default behavior: ensure the trigger is unfocused when leaving the dropdown\n // e.currentTarget.blur();\n // }}\n variant=\"none\"\n {...props}\n >\n {children}\n </Button>\n);\n\n/**\n * Alignment options for the dropdown panel relative to the trigger\n */\nexport enum DropDownAlign {\n /** Align panel to the start (left in LTR, right in RTL) of the trigger */\n START = 'start',\n /** Align panel to the end (right in LTR, left in RTL) of the trigger */\n END = 'end',\n}\n\n/**\n * Props for the DropDown.Panel component\n */\nexport interface PanelProps extends HTMLAttributes<HTMLDivElement> {\n /**\n * Whether the panel should be visible when the trigger is focused.\n * Enables keyboard accessibility for the dropdown.\n * @default false\n */\n isFocusable?: boolean;\n\n /**\n * Controls panel visibility explicitly.\n * - `true`: Panel is hidden\n * - `false`: Panel is visible\n * - `undefined`: Panel visibility controlled by hover/focus states\n * @default undefined\n */\n isHidden?: boolean;\n\n /**\n * Whether the panel should be visible when hovering over the trigger.\n * Provides quick access via mouse interaction.\n * @default false\n */\n isOverable?: boolean;\n\n /**\n * Unique identifier that matches the parent DropDown identifier\n * @example \"user-menu\"\n */\n identifier: string;\n\n /**\n * Horizontal alignment of the panel relative to the trigger\n * @default DropDownAlign.START\n */\n align?: DropDownAlign | `${DropDownAlign}`;\n}\n\n/**\n * DropDown.Panel Component\n *\n * The content area that appears when the dropdown is triggered.\n * Supports multiple trigger methods (hover, focus, controlled) with smooth animations.\n *\n * @example\n * ```tsx\n * // Hover-triggered panel\n * <DropDown.Panel identifier=\"menu\" isOverable>\n * <div>Content appears on hover</div>\n * </DropDown.Panel>\n *\n * // Focus-triggered panel (accessible)\n * <DropDown.Panel identifier=\"menu\" isFocusable>\n * <div>Content appears on focus</div>\n * </DropDown.Panel>\n *\n * // Controlled panel\n * <DropDown.Panel identifier=\"menu\" isHidden={!isOpen}>\n * <div>Content visibility controlled externally</div>\n * </DropDown.Panel>\n *\n * // Right-aligned panel\n * <DropDown.Panel identifier=\"menu\" align={DropDownAlign.END} isOverable>\n * <div>Right-aligned content</div>\n * </DropDown.Panel>\n * ```\n *\n * @component\n * @accessibility\n * - Proper ARIA attributes (role, aria-labelledby, aria-hidden)\n * - Smooth height transitions with MaxHeightSmoother\n * - Keyboard navigation support when isFocusable is enabled\n * - Screen reader announcements for state changes\n */\nconst Panel: FC<PanelProps> = ({\n children,\n isHidden = undefined,\n isOverable = false,\n isFocusable = false,\n align = DropDownAlign.START,\n identifier,\n className,\n ...props\n}) => (\n <div\n className={cn(\n 'absolute top-[calc(100%+0.5rem)] z-[1000] min-w-full',\n align === DropDownAlign.START && 'left-0',\n align === DropDownAlign.END && 'right-0',\n className\n )}\n aria-hidden={isHidden}\n role=\"region\"\n aria-labelledby={`dropdown-trigger-${identifier}`}\n id={`dropdown-panel-${identifier}`}\n >\n <MaxHeightSmoother\n isHidden={isHidden}\n className={cn(\n 'overflow-x-visible',\n isHidden === false && 'invisible',\n isHidden === true && 'visible',\n isOverable &&\n 'group-hover/dropdown:visible group-hover/dropdown:grid-rows-[1fr]',\n isFocusable &&\n 'group-focus-within/dropdown:visible group-focus-within/dropdown:grid-rows-[1fr]'\n )}\n {...props}\n >\n {children}\n </MaxHeightSmoother>\n </div>\n);\n\nDropDown.Trigger = Trigger;\nDropDown.Panel = Panel;\n"],"names":["jsx","cn","Button","DropDownAlign","MaxHeightSmoother"],"mappings":";;;;;;AAqEO,MAAM,WAAyB,CAAC;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,MACEA,2BAAAA;AAAAA,EAAC;AAAA,EAAA;AAAA,IACC,WAAWC,SAAAA,GAAG,gCAAgC,SAAS;AAAA,IACvD,cAAY,YAAY,UAAU;AAAA,IAClC,IAAI,sBAAsB,UAAU;AAAA,IACnC,GAAG;AAAA,IAEH;AAAA,EAAA;AACH;AAoCF,MAAM,UAA4B,CAAC;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,MACED,2BAAAA;AAAAA,EAACE,yBAAAA;AAAAA,EAAA;AAAA,IACC,WAAWD,SAAAA,GAAG,yBAAyB,SAAS;AAAA,IAChD,OAAO,SAAS,cAAc,UAAU;AAAA,IACxC,iBAAc;AAAA,IACd,iBAAe,kBAAkB,UAAU;AAAA,IAC3C,IAAI,oBAAoB,UAAU;AAAA,IAClC,SAAS,CAAC,MAAM;AAEb,QAAE,cAAoC,MAAA;AAAA,IACzC;AAAA,IAKA,SAAQ;AAAA,IACP,GAAG;AAAA,IAEH;AAAA,EAAA;AACH;AAMK,IAAK,kCAAAE,mBAAL;AAELA,iBAAA,OAAA,IAAQ;AAERA,iBAAA,KAAA,IAAM;AAJI,SAAAA;AAAA,GAAA,iBAAA,CAAA,CAAA;AAmFZ,MAAM,QAAwB,CAAC;AAAA,EAC7B;AAAA,EACA,WAAW;AAAA,EACX,aAAa;AAAA,EACb,cAAc;AAAA,EACd,QAAQ;AAAA,EACR;AAAA,EACA;AAAA,EACA,GAAG;AACL,MACEH,2BAAAA;AAAAA,EAAC;AAAA,EAAA;AAAA,IACC,WAAWC,SAAAA;AAAAA,MACT;AAAA,MACA,UAAU,WAAuB;AAAA,MACjC,UAAU,SAAqB;AAAA,MAC/B;AAAA,IAAA;AAAA,IAEF,eAAa;AAAA,IACb,MAAK;AAAA,IACL,mBAAiB,oBAAoB,UAAU;AAAA,IAC/C,IAAI,kBAAkB,UAAU;AAAA,IAEhC,UAAAD,2BAAAA;AAAAA,MAACI,mCAAAA;AAAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAWH,SAAAA;AAAAA,UACT;AAAA,UACA,aAAa,SAAS;AAAA,UACtB,aAAa,QAAQ;AAAA,UACrB,cACE;AAAA,UACF,eACE;AAAA,QAAA;AAAA,QAEH,GAAG;AAAA,QAEH;AAAA,MAAA;AAAA,IAAA;AAAA,EACH;AACF;AAGF,SAAS,UAAU;AACnB,SAAS,QAAQ;;;"}
@@ -1,43 +1,120 @@
1
1
  import { FC, HTMLAttributes } from 'react';
2
2
  import { ButtonProps } from '../Button';
3
- export type DropDownProps = HTMLAttributes<HTMLDivElement> & {
3
+ /**
4
+ * Props for the DropDown component
5
+ */
6
+ export interface DropDownProps extends HTMLAttributes<HTMLDivElement> {
7
+ /**
8
+ * Unique identifier that links the trigger and panel for accessibility.
9
+ * This is used to generate proper ARIA attributes.
10
+ * @example "user-menu"
11
+ * @example "language-selector"
12
+ */
4
13
  identifier: string;
5
- };
14
+ }
6
15
  export type DropDownType = FC<DropDownProps> & {
7
16
  Trigger: FC<TriggerProps>;
8
17
  Panel: FC<PanelProps>;
9
18
  };
10
19
  /**
11
- * Trigger allowing to open a dropdown menu.
20
+ * DropDown Component
21
+ *
22
+ * A compound component that provides dropdown/popover functionality with flexible trigger mechanisms.
23
+ * Supports hover, focus, and controlled visibility states with proper accessibility features.
12
24
  *
13
- * Example:
14
- * ```jsx
15
- * <DropDown identifier="dropdown">
16
- * <DropDown.Trigger>
17
- * Open dropdown
25
+ * @example
26
+ * ```tsx
27
+ * // Basic hover dropdown
28
+ * <DropDown identifier="menu">
29
+ * <DropDown.Trigger identifier="menu">
30
+ * Open Menu
18
31
  * </DropDown.Trigger>
32
+ * <DropDown.Panel identifier="menu" isOverable>
33
+ * <div>Menu content</div>
34
+ * </DropDown.Panel>
35
+ * </DropDown>
36
+ *
37
+ * // Focus-based dropdown for accessibility
38
+ * <DropDown identifier="accessible-menu">
39
+ * <DropDown.Trigger identifier="accessible-menu">
40
+ * Keyboard Accessible Menu
41
+ * </DropDown.Trigger>
42
+ * <DropDown.Panel identifier="accessible-menu" isFocusable>
43
+ * <div>Accessible content</div>
44
+ * </DropDown.Panel>
45
+ * </DropDown>
19
46
  *
20
- * <DropDown.Panel identifier="dropdown">
21
- * <div>Content</div>
47
+ * // Controlled dropdown
48
+ * <DropDown identifier="controlled">
49
+ * <DropDown.Trigger identifier="controlled">
50
+ * Controlled Menu
51
+ * </DropDown.Trigger>
52
+ * <DropDown.Panel identifier="controlled" isHidden={!isOpen}>
53
+ * <div>Controlled content</div>
22
54
  * </DropDown.Panel>
23
55
  * </DropDown>
24
56
  * ```
25
57
  *
26
- * > Note DropDown.Trigger can be replaced by a button. Don't add a button inside the trigger.
58
+ * @component
59
+ * @accessibility
60
+ * - Uses proper ARIA attributes (aria-haspopup, aria-labelledby, etc.)
61
+ * - Supports keyboard navigation with focus management
62
+ * - Screen reader compatible with proper role and labeling
63
+ * - Maintains focus trap within dropdown when needed
27
64
  */
28
65
  export declare const DropDown: DropDownType;
29
- export type TriggerProps = Partial<ButtonProps> & {
66
+ /**
67
+ * Props for the DropDown.Trigger component
68
+ */
69
+ export interface TriggerProps extends Partial<ButtonProps> {
70
+ /**
71
+ * Unique identifier that matches the parent DropDown identifier
72
+ * @example "user-menu"
73
+ */
30
74
  identifier: string;
31
- };
75
+ }
76
+ /**
77
+ * Alignment options for the dropdown panel relative to the trigger
78
+ */
32
79
  export declare enum DropDownAlign {
80
+ /** Align panel to the start (left in LTR, right in RTL) of the trigger */
33
81
  START = "start",
82
+ /** Align panel to the end (right in LTR, left in RTL) of the trigger */
34
83
  END = "end"
35
84
  }
36
- export type PanelProps = HTMLAttributes<HTMLDivElement> & {
85
+ /**
86
+ * Props for the DropDown.Panel component
87
+ */
88
+ export interface PanelProps extends HTMLAttributes<HTMLDivElement> {
89
+ /**
90
+ * Whether the panel should be visible when the trigger is focused.
91
+ * Enables keyboard accessibility for the dropdown.
92
+ * @default false
93
+ */
37
94
  isFocusable?: boolean;
95
+ /**
96
+ * Controls panel visibility explicitly.
97
+ * - `true`: Panel is hidden
98
+ * - `false`: Panel is visible
99
+ * - `undefined`: Panel visibility controlled by hover/focus states
100
+ * @default undefined
101
+ */
38
102
  isHidden?: boolean;
103
+ /**
104
+ * Whether the panel should be visible when hovering over the trigger.
105
+ * Provides quick access via mouse interaction.
106
+ * @default false
107
+ */
39
108
  isOverable?: boolean;
109
+ /**
110
+ * Unique identifier that matches the parent DropDown identifier
111
+ * @example "user-menu"
112
+ */
40
113
  identifier: string;
114
+ /**
115
+ * Horizontal alignment of the panel relative to the trigger
116
+ * @default DropDownAlign.START
117
+ */
41
118
  align?: DropDownAlign | `${DropDownAlign}`;
42
- };
119
+ }
43
120
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/DropDown/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAEhD,OAAO,EAAU,WAAW,EAAE,MAAM,WAAW,CAAC;AAGhD,MAAM,MAAM,aAAa,GAAG,cAAc,CAAC,cAAc,CAAC,GAAG;IAC3D,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,EAAE,CAAC,aAAa,CAAC,GAAG;IAC7C,OAAO,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC;IAC1B,KAAK,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC;CACvB,CAAC;AAEF;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,QAAQ,EAAE,YAetB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,GAAG;IAChD,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAuCF,oBAAY,aAAa;IACvB,KAAK,UAAU;IACf,GAAG,QAAQ;CACZ;AAED,MAAM,MAAM,UAAU,GAAG,cAAc,CAAC,cAAc,CAAC,GAAG;IACxD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,GAAG,GAAG,aAAa,EAAE,CAAC;CAC5C,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/DropDown/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAEhD,OAAO,EAAU,WAAW,EAAE,MAAM,WAAW,CAAC;AAGhD;;GAEG;AACH,MAAM,WAAW,aAAc,SAAQ,cAAc,CAAC,cAAc,CAAC;IACnE;;;;;OAKG;IACH,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,YAAY,GAAG,EAAE,CAAC,aAAa,CAAC,GAAG;IAC7C,OAAO,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC;IAC1B,KAAK,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC;CACvB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,eAAO,MAAM,QAAQ,EAAE,YActB,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,YAAa,SAAQ,OAAO,CAAC,WAAW,CAAC;IACxD;;;OAGG;IACH,UAAU,EAAE,MAAM,CAAC;CACpB;AAoDD;;GAEG;AACH,oBAAY,aAAa;IACvB,0EAA0E;IAC1E,KAAK,UAAU;IACf,wEAAwE;IACxE,GAAG,QAAQ;CACZ;AAED;;GAEG;AACH,MAAM,WAAW,UAAW,SAAQ,cAAc,CAAC,cAAc,CAAC;IAChE;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;OAGG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,KAAK,CAAC,EAAE,aAAa,GAAG,GAAG,aAAa,EAAE,CAAC;CAC5C"}
@@ -12,8 +12,7 @@ const DropDown = ({
12
12
  {
13
13
  className: cn(`group/dropdown relative flex`, className),
14
14
  "aria-label": `DropDown ${identifier}`,
15
- id: `unrollable-panel-button-${identifier}`,
16
- "aria-haspopup": true,
15
+ id: `dropdown-container-${identifier}`,
17
16
  ...props,
18
17
  children
19
18
  }
@@ -29,6 +28,9 @@ const Trigger = ({
29
28
  {
30
29
  className: cn("w-full cursor-pointer", className),
31
30
  label: label ?? `Open panel ${identifier}`,
31
+ "aria-haspopup": "true",
32
+ "aria-controls": `dropdown-panel-${identifier}`,
33
+ id: `dropdown-trigger-${identifier}`,
32
34
  onClick: (e) => {
33
35
  e.currentTarget.focus();
34
36
  },
@@ -62,8 +64,8 @@ const Panel = ({
62
64
  ),
63
65
  "aria-hidden": isHidden,
64
66
  role: "region",
65
- "aria-labelledby": `unrollable-panel-button-${identifier}`,
66
- id: `unrollable-panel-${identifier}`,
67
+ "aria-labelledby": `dropdown-trigger-${identifier}`,
68
+ id: `dropdown-panel-${identifier}`,
67
69
  children: /* @__PURE__ */ jsx(
68
70
  MaxHeightSmoother,
69
71
  {
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../../../src/components/DropDown/index.tsx"],"sourcesContent":["import type { FC, HTMLAttributes } from 'react';\nimport { cn } from '../../utils/cn';\nimport { Button, ButtonProps } from '../Button';\nimport { MaxHeightSmoother } from '../MaxHeightSmoother';\n\nexport type DropDownProps = HTMLAttributes<HTMLDivElement> & {\n identifier: string;\n};\n\nexport type DropDownType = FC<DropDownProps> & {\n Trigger: FC<TriggerProps>;\n Panel: FC<PanelProps>;\n};\n\n/**\n * Trigger allowing to open a dropdown menu.\n *\n * Example:\n * ```jsx\n * <DropDown identifier=\"dropdown\">\n * <DropDown.Trigger>\n * Open dropdown\n * </DropDown.Trigger>\n *\n * <DropDown.Panel identifier=\"dropdown\">\n * <div>Content</div>\n * </DropDown.Panel>\n * </DropDown>\n * ```\n *\n * > Note DropDown.Trigger can be replaced by a button. Don't add a button inside the trigger.\n */\nexport const DropDown: DropDownType = ({\n children,\n className,\n identifier,\n ...props\n}) => (\n <div\n className={cn(`group/dropdown relative flex`, className)}\n aria-label={`DropDown ${identifier}`}\n id={`unrollable-panel-button-${identifier}`}\n aria-haspopup\n {...props}\n >\n {children}\n </div>\n);\n\nexport type TriggerProps = Partial<ButtonProps> & {\n identifier: string;\n};\n\n/**\n * Trigger allowing to open a dropdown menu.\n *\n * Example:\n * ```jsx\n * <DropDown.Trigger identifier=\"dropdown\">\n * <div>Open dropdown</div>\n * </DropDown.Trigger>\n * ```\n *\n * > Note DropDown.Trigger can be replaced by a button. Don't add a button inside the trigger.\n */\nconst Trigger: FC<TriggerProps> = ({\n children,\n identifier,\n className,\n label,\n ...props\n}) => (\n <Button\n className={cn('w-full cursor-pointer', className)}\n label={label ?? `Open panel ${identifier}`}\n onClick={(e) => {\n // Ensure focus behavior is consistent across all mobile browsers\n (e.currentTarget as HTMLButtonElement).focus();\n }}\n // onBlur={(e) => {\n // // Default behavior: ensure the trigger is unfocused when leaving the dropdown\n // e.currentTarget.blur();\n // }}\n variant=\"none\"\n {...props}\n >\n {children}\n </Button>\n);\n\nexport enum DropDownAlign {\n START = 'start',\n END = 'end',\n}\n\nexport type PanelProps = HTMLAttributes<HTMLDivElement> & {\n isFocusable?: boolean;\n isHidden?: boolean;\n isOverable?: boolean;\n identifier: string;\n align?: DropDownAlign | `${DropDownAlign}`;\n};\n\n/**\n * Component that opens a dropdown menu when the trigger is clicked.\n *\n * Example:\n * ```jsx\n * <DropDown.Panel identifier=\"dropdown\">\n * <div>Content</div>\n * </DropDown.Panel>\n * ```\n */\nconst Panel: FC<PanelProps> = ({\n children,\n isHidden = undefined,\n isOverable = false,\n isFocusable = false,\n align = DropDownAlign.START,\n identifier,\n className,\n ...props\n}) => (\n <div\n className={cn(\n 'absolute top-[calc(100%+0.5rem)] z-[1000] min-w-full',\n align === DropDownAlign.START && 'left-0',\n align === DropDownAlign.END && 'right-0',\n className\n )}\n aria-hidden={isHidden}\n role=\"region\"\n aria-labelledby={`unrollable-panel-button-${identifier}`}\n id={`unrollable-panel-${identifier}`}\n >\n <MaxHeightSmoother\n isHidden={isHidden}\n className={cn(\n 'overflow-x-visible',\n isHidden === false && 'invisible',\n isHidden === true && 'visible',\n isOverable &&\n 'group-hover/dropdown:visible group-hover/dropdown:grid-rows-[1fr]',\n isFocusable &&\n 'group-focus-within/dropdown:visible group-focus-within/dropdown:grid-rows-[1fr]'\n )}\n {...props}\n >\n {children}\n </MaxHeightSmoother>\n </div>\n);\n\nDropDown.Trigger = Trigger;\nDropDown.Panel = Panel;\n"],"names":["DropDownAlign"],"mappings":";;;;AAgCO,MAAM,WAAyB,CAAC;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,MACE;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,WAAW,GAAG,gCAAgC,SAAS;AAAA,IACvD,cAAY,YAAY,UAAU;AAAA,IAClC,IAAI,2BAA2B,UAAU;AAAA,IACzC,iBAAa;AAAA,IACZ,GAAG;AAAA,IAEH;AAAA,EAAA;AACH;AAmBF,MAAM,UAA4B,CAAC;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,MACE;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,WAAW,GAAG,yBAAyB,SAAS;AAAA,IAChD,OAAO,SAAS,cAAc,UAAU;AAAA,IACxC,SAAS,CAAC,MAAM;AAEb,QAAE,cAAoC,MAAA;AAAA,IACzC;AAAA,IAKA,SAAQ;AAAA,IACP,GAAG;AAAA,IAEH;AAAA,EAAA;AACH;AAGK,IAAK,kCAAAA,mBAAL;AACLA,iBAAA,OAAA,IAAQ;AACRA,iBAAA,KAAA,IAAM;AAFI,SAAAA;AAAA,GAAA,iBAAA,CAAA,CAAA;AAuBZ,MAAM,QAAwB,CAAC;AAAA,EAC7B;AAAA,EACA,WAAW;AAAA,EACX,aAAa;AAAA,EACb,cAAc;AAAA,EACd,QAAQ;AAAA,EACR;AAAA,EACA;AAAA,EACA,GAAG;AACL,MACE;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,WAAW;AAAA,MACT;AAAA,MACA,UAAU,WAAuB;AAAA,MACjC,UAAU,SAAqB;AAAA,MAC/B;AAAA,IAAA;AAAA,IAEF,eAAa;AAAA,IACb,MAAK;AAAA,IACL,mBAAiB,2BAA2B,UAAU;AAAA,IACtD,IAAI,oBAAoB,UAAU;AAAA,IAElC,UAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAW;AAAA,UACT;AAAA,UACA,aAAa,SAAS;AAAA,UACtB,aAAa,QAAQ;AAAA,UACrB,cACE;AAAA,UACF,eACE;AAAA,QAAA;AAAA,QAEH,GAAG;AAAA,QAEH;AAAA,MAAA;AAAA,IAAA;AAAA,EACH;AACF;AAGF,SAAS,UAAU;AACnB,SAAS,QAAQ;"}
1
+ {"version":3,"file":"index.mjs","sources":["../../../src/components/DropDown/index.tsx"],"sourcesContent":["import type { FC, HTMLAttributes } from 'react';\nimport { cn } from '../../utils/cn';\nimport { Button, ButtonProps } from '../Button';\nimport { MaxHeightSmoother } from '../MaxHeightSmoother';\n\n/**\n * Props for the DropDown component\n */\nexport interface DropDownProps extends HTMLAttributes<HTMLDivElement> {\n /**\n * Unique identifier that links the trigger and panel for accessibility.\n * This is used to generate proper ARIA attributes.\n * @example \"user-menu\"\n * @example \"language-selector\"\n */\n identifier: string;\n}\n\nexport type DropDownType = FC<DropDownProps> & {\n Trigger: FC<TriggerProps>;\n Panel: FC<PanelProps>;\n};\n\n/**\n * DropDown Component\n *\n * A compound component that provides dropdown/popover functionality with flexible trigger mechanisms.\n * Supports hover, focus, and controlled visibility states with proper accessibility features.\n *\n * @example\n * ```tsx\n * // Basic hover dropdown\n * <DropDown identifier=\"menu\">\n * <DropDown.Trigger identifier=\"menu\">\n * Open Menu\n * </DropDown.Trigger>\n * <DropDown.Panel identifier=\"menu\" isOverable>\n * <div>Menu content</div>\n * </DropDown.Panel>\n * </DropDown>\n *\n * // Focus-based dropdown for accessibility\n * <DropDown identifier=\"accessible-menu\">\n * <DropDown.Trigger identifier=\"accessible-menu\">\n * Keyboard Accessible Menu\n * </DropDown.Trigger>\n * <DropDown.Panel identifier=\"accessible-menu\" isFocusable>\n * <div>Accessible content</div>\n * </DropDown.Panel>\n * </DropDown>\n *\n * // Controlled dropdown\n * <DropDown identifier=\"controlled\">\n * <DropDown.Trigger identifier=\"controlled\">\n * Controlled Menu\n * </DropDown.Trigger>\n * <DropDown.Panel identifier=\"controlled\" isHidden={!isOpen}>\n * <div>Controlled content</div>\n * </DropDown.Panel>\n * </DropDown>\n * ```\n *\n * @component\n * @accessibility\n * - Uses proper ARIA attributes (aria-haspopup, aria-labelledby, etc.)\n * - Supports keyboard navigation with focus management\n * - Screen reader compatible with proper role and labeling\n * - Maintains focus trap within dropdown when needed\n */\nexport const DropDown: DropDownType = ({\n children,\n className,\n identifier,\n ...props\n}) => (\n <div\n className={cn(`group/dropdown relative flex`, className)}\n aria-label={`DropDown ${identifier}`}\n id={`dropdown-container-${identifier}`}\n {...props}\n >\n {children}\n </div>\n);\n\n/**\n * Props for the DropDown.Trigger component\n */\nexport interface TriggerProps extends Partial<ButtonProps> {\n /**\n * Unique identifier that matches the parent DropDown identifier\n * @example \"user-menu\"\n */\n identifier: string;\n}\n\n/**\n * DropDown.Trigger Component\n *\n * The clickable/focusable element that controls the dropdown panel visibility.\n * Built on top of the Button component with enhanced dropdown-specific behaviors.\n *\n * @example\n * ```tsx\n * <DropDown.Trigger identifier=\"menu\">\n * <div>Click to open</div>\n * </DropDown.Trigger>\n * ```\n *\n * @component\n * @accessibility\n * - Automatically generates appropriate ARIA attributes\n * - Maintains proper focus management across browsers\n * - Works with keyboard navigation (Tab, Enter, Space)\n * - Announces dropdown state to screen readers\n *\n * @note Don't nest Button components inside the Trigger - it's already a button\n */\nconst Trigger: FC<TriggerProps> = ({\n children,\n identifier,\n className,\n label,\n ...props\n}) => (\n <Button\n className={cn('w-full cursor-pointer', className)}\n label={label ?? `Open panel ${identifier}`}\n aria-haspopup=\"true\"\n aria-controls={`dropdown-panel-${identifier}`}\n id={`dropdown-trigger-${identifier}`}\n onClick={(e) => {\n // Ensure focus behavior is consistent across all mobile browsers\n (e.currentTarget as HTMLButtonElement).focus();\n }}\n // onBlur={(e) => {\n // // Default behavior: ensure the trigger is unfocused when leaving the dropdown\n // e.currentTarget.blur();\n // }}\n variant=\"none\"\n {...props}\n >\n {children}\n </Button>\n);\n\n/**\n * Alignment options for the dropdown panel relative to the trigger\n */\nexport enum DropDownAlign {\n /** Align panel to the start (left in LTR, right in RTL) of the trigger */\n START = 'start',\n /** Align panel to the end (right in LTR, left in RTL) of the trigger */\n END = 'end',\n}\n\n/**\n * Props for the DropDown.Panel component\n */\nexport interface PanelProps extends HTMLAttributes<HTMLDivElement> {\n /**\n * Whether the panel should be visible when the trigger is focused.\n * Enables keyboard accessibility for the dropdown.\n * @default false\n */\n isFocusable?: boolean;\n\n /**\n * Controls panel visibility explicitly.\n * - `true`: Panel is hidden\n * - `false`: Panel is visible\n * - `undefined`: Panel visibility controlled by hover/focus states\n * @default undefined\n */\n isHidden?: boolean;\n\n /**\n * Whether the panel should be visible when hovering over the trigger.\n * Provides quick access via mouse interaction.\n * @default false\n */\n isOverable?: boolean;\n\n /**\n * Unique identifier that matches the parent DropDown identifier\n * @example \"user-menu\"\n */\n identifier: string;\n\n /**\n * Horizontal alignment of the panel relative to the trigger\n * @default DropDownAlign.START\n */\n align?: DropDownAlign | `${DropDownAlign}`;\n}\n\n/**\n * DropDown.Panel Component\n *\n * The content area that appears when the dropdown is triggered.\n * Supports multiple trigger methods (hover, focus, controlled) with smooth animations.\n *\n * @example\n * ```tsx\n * // Hover-triggered panel\n * <DropDown.Panel identifier=\"menu\" isOverable>\n * <div>Content appears on hover</div>\n * </DropDown.Panel>\n *\n * // Focus-triggered panel (accessible)\n * <DropDown.Panel identifier=\"menu\" isFocusable>\n * <div>Content appears on focus</div>\n * </DropDown.Panel>\n *\n * // Controlled panel\n * <DropDown.Panel identifier=\"menu\" isHidden={!isOpen}>\n * <div>Content visibility controlled externally</div>\n * </DropDown.Panel>\n *\n * // Right-aligned panel\n * <DropDown.Panel identifier=\"menu\" align={DropDownAlign.END} isOverable>\n * <div>Right-aligned content</div>\n * </DropDown.Panel>\n * ```\n *\n * @component\n * @accessibility\n * - Proper ARIA attributes (role, aria-labelledby, aria-hidden)\n * - Smooth height transitions with MaxHeightSmoother\n * - Keyboard navigation support when isFocusable is enabled\n * - Screen reader announcements for state changes\n */\nconst Panel: FC<PanelProps> = ({\n children,\n isHidden = undefined,\n isOverable = false,\n isFocusable = false,\n align = DropDownAlign.START,\n identifier,\n className,\n ...props\n}) => (\n <div\n className={cn(\n 'absolute top-[calc(100%+0.5rem)] z-[1000] min-w-full',\n align === DropDownAlign.START && 'left-0',\n align === DropDownAlign.END && 'right-0',\n className\n )}\n aria-hidden={isHidden}\n role=\"region\"\n aria-labelledby={`dropdown-trigger-${identifier}`}\n id={`dropdown-panel-${identifier}`}\n >\n <MaxHeightSmoother\n isHidden={isHidden}\n className={cn(\n 'overflow-x-visible',\n isHidden === false && 'invisible',\n isHidden === true && 'visible',\n isOverable &&\n 'group-hover/dropdown:visible group-hover/dropdown:grid-rows-[1fr]',\n isFocusable &&\n 'group-focus-within/dropdown:visible group-focus-within/dropdown:grid-rows-[1fr]'\n )}\n {...props}\n >\n {children}\n </MaxHeightSmoother>\n </div>\n);\n\nDropDown.Trigger = Trigger;\nDropDown.Panel = Panel;\n"],"names":["DropDownAlign"],"mappings":";;;;AAqEO,MAAM,WAAyB,CAAC;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,MACE;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,WAAW,GAAG,gCAAgC,SAAS;AAAA,IACvD,cAAY,YAAY,UAAU;AAAA,IAClC,IAAI,sBAAsB,UAAU;AAAA,IACnC,GAAG;AAAA,IAEH;AAAA,EAAA;AACH;AAoCF,MAAM,UAA4B,CAAC;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,MACE;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,WAAW,GAAG,yBAAyB,SAAS;AAAA,IAChD,OAAO,SAAS,cAAc,UAAU;AAAA,IACxC,iBAAc;AAAA,IACd,iBAAe,kBAAkB,UAAU;AAAA,IAC3C,IAAI,oBAAoB,UAAU;AAAA,IAClC,SAAS,CAAC,MAAM;AAEb,QAAE,cAAoC,MAAA;AAAA,IACzC;AAAA,IAKA,SAAQ;AAAA,IACP,GAAG;AAAA,IAEH;AAAA,EAAA;AACH;AAMK,IAAK,kCAAAA,mBAAL;AAELA,iBAAA,OAAA,IAAQ;AAERA,iBAAA,KAAA,IAAM;AAJI,SAAAA;AAAA,GAAA,iBAAA,CAAA,CAAA;AAmFZ,MAAM,QAAwB,CAAC;AAAA,EAC7B;AAAA,EACA,WAAW;AAAA,EACX,aAAa;AAAA,EACb,cAAc;AAAA,EACd,QAAQ;AAAA,EACR;AAAA,EACA;AAAA,EACA,GAAG;AACL,MACE;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,WAAW;AAAA,MACT;AAAA,MACA,UAAU,WAAuB;AAAA,MACjC,UAAU,SAAqB;AAAA,MAC/B;AAAA,IAAA;AAAA,IAEF,eAAa;AAAA,IACb,MAAK;AAAA,IACL,mBAAiB,oBAAoB,UAAU;AAAA,IAC/C,IAAI,kBAAkB,UAAU;AAAA,IAEhC,UAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAW;AAAA,UACT;AAAA,UACA,aAAa,SAAS;AAAA,UACtB,aAAa,QAAQ;AAAA,UACrB,cACE;AAAA,UACF,eACE;AAAA,QAAA;AAAA,QAEH,GAAG;AAAA,QAEH;AAAA,MAAA;AAAA,IAAA;AAAA,EACH;AACF;AAGF,SAAS,UAAU;AACnB,SAAS,QAAQ;"}
@@ -1 +1 @@
1
- {"version":3,"file":"EditableFieldInput.cjs","sources":["../../../src/components/EditableField/EditableFieldInput.tsx"],"sourcesContent":["'use client';\n\nimport { type FC, type Ref, useImperativeHandle, useMemo, useRef } from 'react';\nimport { Input, type InputProps } from '../Input';\nimport { EditableFieldLayout } from './EditableFieldLayout';\n\ntype EditableFieldInputProps = InputProps & {\n onSave?: (value: string) => void;\n onCancel?: () => void;\n};\n\nexport const EditableFieldInput: FC<EditableFieldInputProps> = ({\n onSave,\n onCancel,\n ref,\n ...props\n}) => {\n const inputRef = useRef<HTMLInputElement>(null);\n\n const handleSave = () => {\n // Your save logic here\n onSave?.(inputRef.current?.value ?? '');\n };\n\n const handleCancel = () => {\n if (inputRef.current) {\n inputRef.current.value = inputRef.current.defaultValue ?? '';\n }\n onCancel?.();\n };\n\n // Expose the input ref to parent components\n useImperativeHandle(ref as Ref<HTMLElement>, () => inputRef.current!);\n\n const value = useMemo(\n () =>\n (props.value as string) ??\n inputRef.current?.value ??\n (props.defaultValue as string),\n\n [props.value, props.defaultValue, inputRef.current?.value]\n );\n\n return (\n <EditableFieldLayout\n value={value}\n onCancel={handleCancel}\n onSave={handleSave}\n >\n <Input ref={inputRef} {...props} />\n </EditableFieldLayout>\n );\n};\n"],"names":["useRef","useImperativeHandle","useMemo","jsx","EditableFieldLayout","Input"],"mappings":";;;;;;;;;AAWO,MAAM,qBAAkD,CAAC;AAAA,EAC9D;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAAM;AACJ,QAAM,WAAWA,aAAAA,OAAyB,IAAI;AAE9C,QAAM,aAAa,MAAM;AAEvB,aAAS,SAAS,SAAS,SAAS,EAAE;AAAA,EACxC;AAEA,QAAM,eAAe,MAAM;AACzB,QAAI,SAAS,SAAS;AACpB,eAAS,QAAQ,QAAQ,SAAS,QAAQ,gBAAgB;AAAA,IAC5D;AACA,eAAA;AAAA,EACF;AAGAC,eAAAA,oBAAoB,KAAyB,MAAM,SAAS,OAAQ;AAEpE,QAAM,QAAQC,aAAAA;AAAAA,IACZ,MACG,MAAM,SACP,SAAS,SAAS,SACjB,MAAM;AAAA,IAET,CAAC,MAAM,OAAO,MAAM,cAAc,SAAS,SAAS,KAAK;AAAA,EAAA;AAG3D,SACEC,2BAAAA;AAAAA,IAACC,6CAAAA;AAAAA,IAAA;AAAA,MACC;AAAA,MACA,UAAU;AAAA,MACV,QAAQ;AAAA,MAER,UAAAD,2BAAAA,IAACE,uBAAAA,OAAA,EAAM,KAAK,UAAW,GAAG,MAAA,CAAO;AAAA,IAAA;AAAA,EAAA;AAGvC;;"}
1
+ {"version":3,"file":"EditableFieldInput.cjs","sources":["../../../src/components/EditableField/EditableFieldInput.tsx"],"sourcesContent":["'use client';\n\nimport { type FC, type Ref, useImperativeHandle, useMemo, useRef } from 'react';\nimport { Input, type InputProps } from '../Input';\nimport { EditableFieldLayout } from './EditableFieldLayout';\n\n/**\n * Props for the EditableFieldInput component, extending standard Input props\n */\ntype EditableFieldInputProps = InputProps & {\n /** Callback function called when the user saves the edited value */\n onSave?: (value: string) => void;\n /** Callback function called when the user cancels the edit operation */\n onCancel?: () => void;\n};\n\n/**\n * EditableFieldInput Component\n *\n * An inline editable input field that displays as read-only text until clicked.\n * When activated, it shows an input field with save and cancel buttons.\n *\n * @example\n * ```tsx\n * <EditableFieldInput\n * defaultValue=\"Edit me\"\n * placeholder=\"Click to edit...\"\n * onSave={(value) => console.log('Saved:', value)}\n * onCancel={() => console.log('Cancelled')}\n * />\n * ```\n *\n * ## Features\n * - **Inline Editing**: Click to edit, displays as text when not editing\n * - **Save/Cancel Actions**: Built-in save and cancel buttons with callbacks\n * - **Keyboard Support**: Accessible keyboard navigation\n * - **Input Variants**: Supports all Input component variants and sizes\n * - **Auto-save on Click Away**: Saves automatically when clicking outside\n * - **Ref Forwarding**: Exposes the underlying input element reference\n *\n * ## Accessibility\n * - Uses semantic HTML with proper ARIA attributes\n * - Keyboard accessible with tab navigation\n * - Screen reader friendly with descriptive labels\n * - Focus management for edit mode transitions\n *\n * @param props - EditableFieldInputProps extending InputProps\n * @returns React functional component\n */\nexport const EditableFieldInput: FC<EditableFieldInputProps> = ({\n onSave,\n onCancel,\n ref,\n ...props\n}) => {\n const inputRef = useRef<HTMLInputElement>(null);\n\n const handleSave = () => {\n // Your save logic here\n onSave?.(inputRef.current?.value ?? '');\n };\n\n const handleCancel = () => {\n if (inputRef.current) {\n inputRef.current.value = inputRef.current.defaultValue ?? '';\n }\n onCancel?.();\n };\n\n // Expose the input ref to parent components\n useImperativeHandle(ref as Ref<HTMLElement>, () => inputRef.current!);\n\n const value = useMemo(\n () =>\n (props.value as string) ??\n inputRef.current?.value ??\n (props.defaultValue as string),\n\n [props.value, props.defaultValue, inputRef.current?.value]\n );\n\n return (\n <EditableFieldLayout\n value={value}\n onCancel={handleCancel}\n onSave={handleSave}\n >\n <Input ref={inputRef} {...props} />\n </EditableFieldLayout>\n );\n};\n"],"names":["useRef","useImperativeHandle","useMemo","jsx","EditableFieldLayout","Input"],"mappings":";;;;;;;;;AAiDO,MAAM,qBAAkD,CAAC;AAAA,EAC9D;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAAM;AACJ,QAAM,WAAWA,aAAAA,OAAyB,IAAI;AAE9C,QAAM,aAAa,MAAM;AAEvB,aAAS,SAAS,SAAS,SAAS,EAAE;AAAA,EACxC;AAEA,QAAM,eAAe,MAAM;AACzB,QAAI,SAAS,SAAS;AACpB,eAAS,QAAQ,QAAQ,SAAS,QAAQ,gBAAgB;AAAA,IAC5D;AACA,eAAA;AAAA,EACF;AAGAC,eAAAA,oBAAoB,KAAyB,MAAM,SAAS,OAAQ;AAEpE,QAAM,QAAQC,aAAAA;AAAAA,IACZ,MACG,MAAM,SACP,SAAS,SAAS,SACjB,MAAM;AAAA,IAET,CAAC,MAAM,OAAO,MAAM,cAAc,SAAS,SAAS,KAAK;AAAA,EAAA;AAG3D,SACEC,2BAAAA;AAAAA,IAACC,6CAAAA;AAAAA,IAAA;AAAA,MACC;AAAA,MACA,UAAU;AAAA,MACV,QAAQ;AAAA,MAER,UAAAD,2BAAAA,IAACE,uBAAAA,OAAA,EAAM,KAAK,UAAW,GAAG,MAAA,CAAO;AAAA,IAAA;AAAA,EAAA;AAGvC;;"}
@@ -1,9 +1,47 @@
1
1
  import { FC } from 'react';
2
2
  import { InputProps } from '../Input';
3
+ /**
4
+ * Props for the EditableFieldInput component, extending standard Input props
5
+ */
3
6
  type EditableFieldInputProps = InputProps & {
7
+ /** Callback function called when the user saves the edited value */
4
8
  onSave?: (value: string) => void;
9
+ /** Callback function called when the user cancels the edit operation */
5
10
  onCancel?: () => void;
6
11
  };
12
+ /**
13
+ * EditableFieldInput Component
14
+ *
15
+ * An inline editable input field that displays as read-only text until clicked.
16
+ * When activated, it shows an input field with save and cancel buttons.
17
+ *
18
+ * @example
19
+ * ```tsx
20
+ * <EditableFieldInput
21
+ * defaultValue="Edit me"
22
+ * placeholder="Click to edit..."
23
+ * onSave={(value) => console.log('Saved:', value)}
24
+ * onCancel={() => console.log('Cancelled')}
25
+ * />
26
+ * ```
27
+ *
28
+ * ## Features
29
+ * - **Inline Editing**: Click to edit, displays as text when not editing
30
+ * - **Save/Cancel Actions**: Built-in save and cancel buttons with callbacks
31
+ * - **Keyboard Support**: Accessible keyboard navigation
32
+ * - **Input Variants**: Supports all Input component variants and sizes
33
+ * - **Auto-save on Click Away**: Saves automatically when clicking outside
34
+ * - **Ref Forwarding**: Exposes the underlying input element reference
35
+ *
36
+ * ## Accessibility
37
+ * - Uses semantic HTML with proper ARIA attributes
38
+ * - Keyboard accessible with tab navigation
39
+ * - Screen reader friendly with descriptive labels
40
+ * - Focus management for edit mode transitions
41
+ *
42
+ * @param props - EditableFieldInputProps extending InputProps
43
+ * @returns React functional component
44
+ */
7
45
  export declare const EditableFieldInput: FC<EditableFieldInputProps>;
8
46
  export {};
9
47
  //# sourceMappingURL=EditableFieldInput.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"EditableFieldInput.d.ts","sourceRoot":"","sources":["../../../src/components/EditableField/EditableFieldInput.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,EAAE,EAAkD,MAAM,OAAO,CAAC;AAChF,OAAO,EAAS,KAAK,UAAU,EAAE,MAAM,UAAU,CAAC;AAGlD,KAAK,uBAAuB,GAAG,UAAU,GAAG;IAC1C,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,EAAE,CAAC,uBAAuB,CAyC1D,CAAC"}
1
+ {"version":3,"file":"EditableFieldInput.d.ts","sourceRoot":"","sources":["../../../src/components/EditableField/EditableFieldInput.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,EAAE,EAAkD,MAAM,OAAO,CAAC;AAChF,OAAO,EAAS,KAAK,UAAU,EAAE,MAAM,UAAU,CAAC;AAGlD;;GAEG;AACH,KAAK,uBAAuB,GAAG,UAAU,GAAG;IAC1C,oEAAoE;IACpE,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,wEAAwE;IACxE,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,eAAO,MAAM,kBAAkB,EAAE,EAAE,CAAC,uBAAuB,CAyC1D,CAAC"}