se-design 1.0.63-dev → 1.0.64

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 (376) hide show
  1. package/dist/assets/colors.css +22 -9
  2. package/dist/assets/icons/ai-off.svg +4 -4
  3. package/dist/assets/icons/center-align.svg +3 -0
  4. package/dist/assets/icons/command.svg +1 -1
  5. package/dist/assets/icons/left-align.svg +3 -0
  6. package/dist/assets/icons/right-align.svg +3 -0
  7. package/dist/assets/style.css +1 -1
  8. package/dist/components/BreadCrumbs/index.d.ts +2 -0
  9. package/dist/components/Button/index.d.ts +5 -1
  10. package/dist/components/InfoTooltip/index.d.ts +5 -1
  11. package/dist/index.js +23 -21
  12. package/dist/index.js.map +1 -1
  13. package/dist/index100.js +2 -2
  14. package/dist/index100.js.map +1 -1
  15. package/dist/index101.js +1 -1
  16. package/dist/index101.js.map +1 -1
  17. package/dist/index102.js +2 -2
  18. package/dist/index102.js.map +1 -1
  19. package/dist/index103.js +2 -2
  20. package/dist/index103.js.map +1 -1
  21. package/dist/index104.js +2 -2
  22. package/dist/index104.js.map +1 -1
  23. package/dist/index105.js +2 -2
  24. package/dist/index105.js.map +1 -1
  25. package/dist/index106.js +1 -1
  26. package/dist/index106.js.map +1 -1
  27. package/dist/index107.js +1 -1
  28. package/dist/index107.js.map +1 -1
  29. package/dist/index108.js +2 -2
  30. package/dist/index108.js.map +1 -1
  31. package/dist/index109.js +2 -2
  32. package/dist/index109.js.map +1 -1
  33. package/dist/index110.js +2 -2
  34. package/dist/index110.js.map +1 -1
  35. package/dist/index111.js +2 -2
  36. package/dist/index111.js.map +1 -1
  37. package/dist/index112.js +1 -1
  38. package/dist/index112.js.map +1 -1
  39. package/dist/index113.js +1 -1
  40. package/dist/index113.js.map +1 -1
  41. package/dist/index114.js +2 -2
  42. package/dist/index114.js.map +1 -1
  43. package/dist/index115.js +1 -1
  44. package/dist/index115.js.map +1 -1
  45. package/dist/index116.js +1 -1
  46. package/dist/index116.js.map +1 -1
  47. package/dist/index117.js +2 -2
  48. package/dist/index117.js.map +1 -1
  49. package/dist/index118.js +2 -2
  50. package/dist/index118.js.map +1 -1
  51. package/dist/index119.js +2 -2
  52. package/dist/index119.js.map +1 -1
  53. package/dist/index120.js +2 -2
  54. package/dist/index120.js.map +1 -1
  55. package/dist/index121.js +1 -1
  56. package/dist/index121.js.map +1 -1
  57. package/dist/index122.js +1 -1
  58. package/dist/index122.js.map +1 -1
  59. package/dist/index123.js +1 -1
  60. package/dist/index123.js.map +1 -1
  61. package/dist/index124.js +1 -1
  62. package/dist/index124.js.map +1 -1
  63. package/dist/index125.js +1 -1
  64. package/dist/index125.js.map +1 -1
  65. package/dist/index126.js +1 -1
  66. package/dist/index126.js.map +1 -1
  67. package/dist/index127.js +1 -1
  68. package/dist/index127.js.map +1 -1
  69. package/dist/index128.js +2 -2
  70. package/dist/index128.js.map +1 -1
  71. package/dist/index129.js +1 -1
  72. package/dist/index129.js.map +1 -1
  73. package/dist/index130.js +2 -2
  74. package/dist/index130.js.map +1 -1
  75. package/dist/index131.js +1 -1
  76. package/dist/index131.js.map +1 -1
  77. package/dist/index132.js +1 -1
  78. package/dist/index132.js.map +1 -1
  79. package/dist/index133.js +1 -1
  80. package/dist/index133.js.map +1 -1
  81. package/dist/index134.js +1 -1
  82. package/dist/index134.js.map +1 -1
  83. package/dist/index135.js +1 -1
  84. package/dist/index135.js.map +1 -1
  85. package/dist/index136.js +2 -2
  86. package/dist/index136.js.map +1 -1
  87. package/dist/index137.js +2 -2
  88. package/dist/index137.js.map +1 -1
  89. package/dist/index138.js +1 -1
  90. package/dist/index138.js.map +1 -1
  91. package/dist/index139.js +2 -2
  92. package/dist/index139.js.map +1 -1
  93. package/dist/index140.js +1 -1
  94. package/dist/index140.js.map +1 -1
  95. package/dist/index141.js +1 -1
  96. package/dist/index141.js.map +1 -1
  97. package/dist/index142.js +2 -2
  98. package/dist/index142.js.map +1 -1
  99. package/dist/index143.js +2 -2
  100. package/dist/index143.js.map +1 -1
  101. package/dist/index144.js +1 -1
  102. package/dist/index144.js.map +1 -1
  103. package/dist/index145.js +1 -1
  104. package/dist/index145.js.map +1 -1
  105. package/dist/index146.js +1 -1
  106. package/dist/index146.js.map +1 -1
  107. package/dist/index147.js +1 -1
  108. package/dist/index147.js.map +1 -1
  109. package/dist/index148.js +1 -1
  110. package/dist/index148.js.map +1 -1
  111. package/dist/index149.js +1 -1
  112. package/dist/index149.js.map +1 -1
  113. package/dist/index15.js +2 -2
  114. package/dist/index150.js +1 -1
  115. package/dist/index150.js.map +1 -1
  116. package/dist/index151.js +1 -1
  117. package/dist/index151.js.map +1 -1
  118. package/dist/index152.js +1 -1
  119. package/dist/index152.js.map +1 -1
  120. package/dist/index153.js +1 -1
  121. package/dist/index153.js.map +1 -1
  122. package/dist/index154.js +1 -1
  123. package/dist/index154.js.map +1 -1
  124. package/dist/index155.js +1 -1
  125. package/dist/index155.js.map +1 -1
  126. package/dist/index156.js +1 -1
  127. package/dist/index156.js.map +1 -1
  128. package/dist/index157.js +1 -1
  129. package/dist/index157.js.map +1 -1
  130. package/dist/index158.js +1 -1
  131. package/dist/index158.js.map +1 -1
  132. package/dist/index159.js +1 -1
  133. package/dist/index159.js.map +1 -1
  134. package/dist/index160.js +1 -1
  135. package/dist/index160.js.map +1 -1
  136. package/dist/index161.js +1 -1
  137. package/dist/index161.js.map +1 -1
  138. package/dist/index162.js +1 -1
  139. package/dist/index162.js.map +1 -1
  140. package/dist/index163.js +1 -1
  141. package/dist/index163.js.map +1 -1
  142. package/dist/index164.js +1 -1
  143. package/dist/index164.js.map +1 -1
  144. package/dist/index165.js +2 -2
  145. package/dist/index165.js.map +1 -1
  146. package/dist/index166.js +1 -1
  147. package/dist/index166.js.map +1 -1
  148. package/dist/index167.js +1 -1
  149. package/dist/index167.js.map +1 -1
  150. package/dist/index168.js +1 -1
  151. package/dist/index168.js.map +1 -1
  152. package/dist/index169.js +2 -2
  153. package/dist/index169.js.map +1 -1
  154. package/dist/index17.js +1 -1
  155. package/dist/index170.js +1 -1
  156. package/dist/index170.js.map +1 -1
  157. package/dist/index171.js +1 -1
  158. package/dist/index171.js.map +1 -1
  159. package/dist/index172.js +1 -1
  160. package/dist/index172.js.map +1 -1
  161. package/dist/index173.js +2 -2
  162. package/dist/index173.js.map +1 -1
  163. package/dist/index174.js +1 -1
  164. package/dist/index174.js.map +1 -1
  165. package/dist/index175.js +1 -1
  166. package/dist/index175.js.map +1 -1
  167. package/dist/index176.js +1 -1
  168. package/dist/index176.js.map +1 -1
  169. package/dist/index177.js +1 -1
  170. package/dist/index177.js.map +1 -1
  171. package/dist/index178.js +1 -1
  172. package/dist/index178.js.map +1 -1
  173. package/dist/index179.js +2 -2
  174. package/dist/index179.js.map +1 -1
  175. package/dist/index18.js +2 -2
  176. package/dist/index180.js +1 -1
  177. package/dist/index180.js.map +1 -1
  178. package/dist/index181.js +2 -2
  179. package/dist/index181.js.map +1 -1
  180. package/dist/index182.js +2 -149
  181. package/dist/index182.js.map +1 -1
  182. package/dist/index183.js +2 -9
  183. package/dist/index183.js.map +1 -1
  184. package/dist/index184.js +2 -6
  185. package/dist/index184.js.map +1 -1
  186. package/dist/index185.js +2 -5
  187. package/dist/index185.js.map +1 -1
  188. package/dist/index186.js +152 -0
  189. package/dist/index186.js.map +1 -0
  190. package/dist/index187.js +12 -0
  191. package/dist/index187.js.map +1 -0
  192. package/dist/index188.js +5 -23
  193. package/dist/index188.js.map +1 -1
  194. package/dist/index189.js +4 -61
  195. package/dist/index189.js.map +1 -1
  196. package/dist/index192.js +27 -0
  197. package/dist/index192.js.map +1 -0
  198. package/dist/{index191.js → index194.js} +3 -3
  199. package/dist/{index191.js.map → index194.js.map} +1 -1
  200. package/dist/{index193.js → index196.js} +1 -1
  201. package/dist/{index193.js.map → index196.js.map} +1 -1
  202. package/dist/{index201.js → index204.js} +1 -1
  203. package/dist/{index201.js.map → index204.js.map} +1 -1
  204. package/dist/index212.js +1233 -41
  205. package/dist/index212.js.map +1 -1
  206. package/dist/{index211.js → index214.js} +1 -1
  207. package/dist/{index211.js.map → index214.js.map} +1 -1
  208. package/dist/index215.js +44 -0
  209. package/dist/index215.js.map +1 -0
  210. package/dist/index22.js +3 -3
  211. package/dist/index225.js +3 -53
  212. package/dist/index225.js.map +1 -1
  213. package/dist/index227.js +55 -15
  214. package/dist/index227.js.map +1 -1
  215. package/dist/index228.js +53 -9
  216. package/dist/index228.js.map +1 -1
  217. package/dist/index229.js +21 -9
  218. package/dist/index229.js.map +1 -1
  219. package/dist/index230.js +18 -4
  220. package/dist/index230.js.map +1 -1
  221. package/dist/index231.js +9 -169
  222. package/dist/index231.js.map +1 -1
  223. package/dist/index232.js +10 -11
  224. package/dist/index232.js.map +1 -1
  225. package/dist/index233.js +4 -5
  226. package/dist/index233.js.map +1 -1
  227. package/dist/index234.js +170 -6
  228. package/dist/index234.js.map +1 -1
  229. package/dist/index235.js +11 -38
  230. package/dist/index235.js.map +1 -1
  231. package/dist/index236.js +6 -2
  232. package/dist/index236.js.map +1 -1
  233. package/dist/index237.js +5 -7
  234. package/dist/index237.js.map +1 -1
  235. package/dist/index238.js +36 -325
  236. package/dist/index238.js.map +1 -1
  237. package/dist/index239.js +2 -50
  238. package/dist/index239.js.map +1 -1
  239. package/dist/index24.js +3 -3
  240. package/dist/index24.js.map +1 -1
  241. package/dist/index240.js +8 -2
  242. package/dist/index240.js.map +1 -1
  243. package/dist/index241.js +323 -72
  244. package/dist/index241.js.map +1 -1
  245. package/dist/index242.js +47 -90
  246. package/dist/index242.js.map +1 -1
  247. package/dist/index243.js +2 -52
  248. package/dist/index243.js.map +1 -1
  249. package/dist/index244.js +75 -7
  250. package/dist/index244.js.map +1 -1
  251. package/dist/index245.js +92 -4
  252. package/dist/index245.js.map +1 -1
  253. package/dist/index246.js +48 -48
  254. package/dist/index246.js.map +1 -1
  255. package/dist/index247.js +8 -2
  256. package/dist/index247.js.map +1 -1
  257. package/dist/index248.js +5 -2
  258. package/dist/index248.js.map +1 -1
  259. package/dist/index249.js +55 -0
  260. package/dist/index249.js.map +1 -0
  261. package/dist/index250.js +5 -0
  262. package/dist/index250.js.map +1 -0
  263. package/dist/index251.js +5 -0
  264. package/dist/index251.js.map +1 -0
  265. package/dist/index27.js +2 -2
  266. package/dist/index29.js +1 -1
  267. package/dist/index3.js +23 -21
  268. package/dist/index3.js.map +1 -1
  269. package/dist/index31.js +11 -10
  270. package/dist/index34.js +1 -1
  271. package/dist/index36.js +35 -38
  272. package/dist/index36.js.map +1 -1
  273. package/dist/index37.js +5 -6
  274. package/dist/index37.js.map +1 -1
  275. package/dist/index38.js +3 -3
  276. package/dist/index39.js +1 -1
  277. package/dist/index41.js +8 -7
  278. package/dist/index42.js +7 -6
  279. package/dist/index43.js +16 -16
  280. package/dist/index43.js.map +1 -1
  281. package/dist/index44.js +3 -3
  282. package/dist/index45.js +4 -4
  283. package/dist/index48.js +3 -3
  284. package/dist/index49.js +48 -30
  285. package/dist/index49.js.map +1 -1
  286. package/dist/index5.js +229 -223
  287. package/dist/index5.js.map +1 -1
  288. package/dist/index50.js +2 -2
  289. package/dist/index50.js.map +1 -1
  290. package/dist/index52.js +1 -1
  291. package/dist/index54.js +22 -21
  292. package/dist/index56.js +2 -2
  293. package/dist/index56.js.map +1 -1
  294. package/dist/index6.js +3 -2
  295. package/dist/index60.js +45 -39
  296. package/dist/index60.js.map +1 -1
  297. package/dist/index62.js +1 -1
  298. package/dist/index63.js +1 -1
  299. package/dist/index64.js +4 -3
  300. package/dist/index66.js +19 -17
  301. package/dist/index66.js.map +1 -1
  302. package/dist/index68.js +55 -5
  303. package/dist/index68.js.map +1 -1
  304. package/dist/index69.js +5 -9
  305. package/dist/index69.js.map +1 -1
  306. package/dist/index70.js +12 -0
  307. package/dist/index70.js.map +1 -0
  308. package/dist/index72.js +2 -2
  309. package/dist/index72.js.map +1 -1
  310. package/dist/index73.js +2 -2
  311. package/dist/index73.js.map +1 -1
  312. package/dist/index74.js +2 -2
  313. package/dist/index74.js.map +1 -1
  314. package/dist/index75.js +1 -1
  315. package/dist/index75.js.map +1 -1
  316. package/dist/index76.js +1 -1
  317. package/dist/index76.js.map +1 -1
  318. package/dist/index77.js +1 -1
  319. package/dist/index77.js.map +1 -1
  320. package/dist/index78.js +1 -1
  321. package/dist/index78.js.map +1 -1
  322. package/dist/index79.js +1 -1
  323. package/dist/index79.js.map +1 -1
  324. package/dist/index8.js +5 -5
  325. package/dist/index8.js.map +1 -1
  326. package/dist/index80.js +1 -1
  327. package/dist/index80.js.map +1 -1
  328. package/dist/index81.js +1 -1
  329. package/dist/index81.js.map +1 -1
  330. package/dist/index82.js +1 -1
  331. package/dist/index82.js.map +1 -1
  332. package/dist/index83.js +1 -1
  333. package/dist/index83.js.map +1 -1
  334. package/dist/index84.js +1 -1
  335. package/dist/index84.js.map +1 -1
  336. package/dist/index85.js +1 -1
  337. package/dist/index85.js.map +1 -1
  338. package/dist/index86.js +1 -1
  339. package/dist/index86.js.map +1 -1
  340. package/dist/index87.js +1 -1
  341. package/dist/index87.js.map +1 -1
  342. package/dist/index88.js +1 -1
  343. package/dist/index88.js.map +1 -1
  344. package/dist/index89.js +1 -1
  345. package/dist/index89.js.map +1 -1
  346. package/dist/index90.js +1 -1
  347. package/dist/index90.js.map +1 -1
  348. package/dist/index91.js +1 -1
  349. package/dist/index91.js.map +1 -1
  350. package/dist/index92.js +1 -1
  351. package/dist/index92.js.map +1 -1
  352. package/dist/index93.js +1 -1
  353. package/dist/index93.js.map +1 -1
  354. package/dist/index94.js +1 -1
  355. package/dist/index94.js.map +1 -1
  356. package/dist/index95.js +1 -1
  357. package/dist/index95.js.map +1 -1
  358. package/dist/index96.js +1 -1
  359. package/dist/index96.js.map +1 -1
  360. package/dist/index97.js +2 -2
  361. package/dist/index97.js.map +1 -1
  362. package/dist/index98.js +2 -2
  363. package/dist/index98.js.map +1 -1
  364. package/dist/index99.js +2 -2
  365. package/dist/index99.js.map +1 -1
  366. package/package.json +1 -1
  367. package/dist/index209.js +0 -1236
  368. package/dist/index209.js.map +0 -1
  369. package/dist/index222.js +0 -7
  370. package/dist/index222.js.map +0 -1
  371. package/dist/index224.js +0 -62
  372. package/dist/index224.js.map +0 -1
  373. package/dist/index226.js +0 -25
  374. package/dist/index226.js.map +0 -1
  375. package/dist/index71.js +0 -5
  376. package/dist/index71.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index191.js","sources":["../src/utils/a11y/useCombobox.ts"],"sourcesContent":["import { useRef, useCallback, useEffect } from 'react';\nimport type { RefObject } from 'react';\nimport { useComboboxNavigation } from './useComboboxNavigation';\nimport { useDismissOnFocusOut } from './useDismissOnFocusOut';\nimport type { UseDismissOnFocusOutReturn } from './useDismissOnFocusOut';\n\nexport interface UseComboboxOptions<T = any> {\n /**\n * Array of items to navigate through\n */\n items: T[];\n \n /**\n * Whether the dropdown is currently open\n */\n isOpen: boolean;\n \n /**\n * Callback to change the open state\n */\n onOpenChange: (open: boolean) => void;\n \n /**\n * Callback when an item is selected (Enter key)\n */\n onSelect: (item: T, index: number) => void;\n \n /**\n * Stable ID for the listbox element\n */\n listboxId: string;\n \n /**\n * Whether to wrap around at the ends of the list.\n * Default: true\n */\n loop?: boolean;\n \n /**\n * Whether keyboard navigation is disabled\n * (e.g., for custom rendered content)\n */\n disabled?: boolean;\n \n /**\n * CSS selector for option elements (default: '[role=\"option\"]')\n */\n optionSelector?: string;\n \n /**\n * Whether the listbox has any items to show\n * Used for aria-expanded logic\n * Default: items.length > 0\n */\n hasItems?: boolean;\n}\n\nexport interface UseComboboxReturn {\n /**\n * Props to spread on the container element (handles dismiss on focus out)\n */\n containerProps: UseDismissOnFocusOutReturn<HTMLElement>;\n \n /**\n * Props to spread on the combobox input element\n */\n inputProps: {\n role: 'combobox';\n 'aria-expanded': boolean;\n 'aria-haspopup': 'listbox';\n 'aria-controls': string | undefined;\n 'aria-autocomplete': 'list';\n 'aria-activedescendant': string | undefined;\n onKeyDown: (e: React.KeyboardEvent) => void;\n };\n \n /**\n * Props to spread on the listbox element\n */\n listboxProps: {\n id: string;\n role: 'listbox';\n ref: RefObject<HTMLDivElement | null>;\n onMouseDownCapture: (e: React.MouseEvent) => void;\n onMouseUpCapture: (e: React.MouseEvent) => void;\n onMouseLeave: (e: React.MouseEvent) => void;\n };\n \n /**\n * Generate props for an option element at the given index\n * @param selected - Whether this option is the currently selected/chosen value (not keyboard highlight)\n */\n getOptionProps: (index: number, selected?: boolean) => {\n id: string;\n role: 'option';\n 'aria-selected': boolean;\n };\n \n /**\n * Currently highlighted index (-1 if none)\n */\n highlightedIndex: number;\n \n /**\n * Set the highlighted index manually\n */\n setHighlightedIndex: (index: number | ((prev: number) => number)) => void;\n \n /**\n * Generate stable ID for an option\n */\n getOptionId: (listboxId: string, index: number) => string;\n}\n\n/**\n * Comprehensive hook for implementing WAI-ARIA combobox pattern.\n * \n * Combines:\n * - Keyboard navigation (Arrow Up/Down, Enter, Escape, Tab)\n * - Focus management and dismissal\n * - ARIA attributes for accessibility\n * - Auto-scroll highlighted item into view\n * \n * This hook provides a complete, batteries-included solution for building\n * accessible combobox components (autocomplete, select, search with suggestions, etc.)\n * \n * @example Basic usage\n * ```tsx\n * const MyCombobox = () => {\n * const [isOpen, setIsOpen] = useState(false);\n * const [items, setItems] = useState(['Apple', 'Banana', 'Cherry']);\n * \n * const {\n * containerProps,\n * inputProps,\n * listboxProps,\n * getOptionProps,\n * highlightedIndex\n * } = useCombobox({\n * items,\n * isOpen,\n * onOpenChange: setIsOpen,\n * onSelect: (item) => console.log('Selected:', item),\n * listboxId: 'my-listbox'\n * });\n * \n * return (\n * <div {...containerProps}>\n * <input {...inputProps} />\n * {isOpen && (\n * <div {...listboxProps}>\n * {items.map((item, i) => (\n * <div key={i} {...getOptionProps(i)}>\n * {item}\n * </div>\n * ))}\n * </div>\n * )}\n * </div>\n * );\n * };\n * ```\n * \n * @example With custom ARIA labels and handlers\n * ```tsx\n * const MySearchBox = () => {\n * const [query, setQuery] = useState('');\n * const [suggestions, setSuggestions] = useState([]);\n * const [isOpen, setIsOpen] = useState(false);\n * \n * const { containerProps, inputProps, listboxProps, getOptionProps } = useCombobox({\n * items: suggestions,\n * isOpen,\n * onOpenChange: setIsOpen,\n * onSelect: (suggestion) => {\n * setQuery(suggestion);\n * setIsOpen(false);\n * },\n * listboxId: 'search-suggestions'\n * });\n * \n * return (\n * <div {...containerProps}>\n * <input\n * {...inputProps}\n * value={query}\n * onChange={(e) => setQuery(e.target.value)}\n * aria-label=\"Search\"\n * />\n * {isOpen && suggestions.length > 0 && (\n * <div {...listboxProps} aria-label=\"Search suggestions\">\n * {suggestions.map((suggestion, i) => (\n * <div\n * key={i}\n * {...getOptionProps(i)}\n * onClick={() => {\n * setQuery(suggestion);\n * setIsOpen(false);\n * }}\n * >\n * {suggestion}\n * </div>\n * ))}\n * </div>\n * )}\n * </div>\n * );\n * };\n * ```\n */\nexport function useCombobox<T = any>({\n items,\n isOpen,\n onOpenChange,\n onSelect,\n listboxId,\n loop = true,\n disabled = false,\n optionSelector = '[role=\"option\"]',\n hasItems\n}: UseComboboxOptions<T>): UseComboboxReturn {\n const listboxRef = useRef<HTMLDivElement | null>(null);\n const pointerDownInListboxRef = useRef(false);\n const tabKeyPressedRef = useRef(false);\n \n // Determine if we should show as expanded\n const shouldShowExpanded = hasItems !== undefined ? hasItems : items.length > 0;\n \n // Close dropdown callback\n const closeDropdown = useCallback(() => {\n onOpenChange(false);\n }, [onOpenChange]);\n\n // Ensure pointer state doesn't get stuck when listbox unmounts\n useEffect(() => {\n if (!isOpen) {\n pointerDownInListboxRef.current = false;\n }\n }, [isOpen]);\n \n // Keyboard navigation with aria-activedescendant\n const navigation = useComboboxNavigation<T>({\n items,\n isOpen,\n onSelect,\n onClose: closeDropdown,\n onOpen: () => onOpenChange(true),\n loop,\n disabled,\n listboxRef,\n optionSelector\n });\n \n // Focus out / Escape dismissal\n const dismissHandlers = useDismissOnFocusOut({\n onFocusOut: closeDropdown,\n onEscape: closeDropdown,\n disabled: !isOpen\n });\n\n const containerProps: UseDismissOnFocusOutReturn<HTMLElement> = {\n ...dismissHandlers,\n onBlurCapture: (e) => {\n // Clicking inside a listbox option can blur the input (relatedTarget is null),\n // which would dismiss before the click handler runs. Prevent that.\n if (pointerDownInListboxRef.current) return;\n \n // Tab key pressed - let Tab handler close dropdown, skip blur detection\n if (tabKeyPressedRef.current) {\n tabKeyPressedRef.current = false;\n return;\n }\n \n dismissHandlers.onBlurCapture(e);\n }\n };\n \n // Build input props\n const inputProps = {\n role: 'combobox' as const,\n 'aria-expanded': isOpen && shouldShowExpanded,\n 'aria-haspopup': 'listbox' as const,\n 'aria-controls': isOpen ? listboxId : undefined,\n 'aria-autocomplete': 'list' as const,\n 'aria-activedescendant': \n navigation.highlightedIndex >= 0 \n ? navigation.getOptionId(listboxId, navigation.highlightedIndex) \n : undefined,\n onKeyDown: (e: React.KeyboardEvent) => {\n // Set flag when Tab is pressed (before blur fires)\n if (e.key === 'Tab') {\n tabKeyPressedRef.current = true;\n }\n navigation.handleKeyDown(e);\n }\n };\n \n // Build listbox props\n const listboxProps = {\n id: listboxId,\n role: 'listbox' as const,\n ref: listboxRef,\n onMouseDownCapture: (_e: React.MouseEvent) => {\n pointerDownInListboxRef.current = true;\n },\n onMouseUpCapture: (_e: React.MouseEvent) => {\n pointerDownInListboxRef.current = false;\n },\n onMouseLeave: (_e: React.MouseEvent) => {\n pointerDownInListboxRef.current = false;\n }\n };\n \n // Option props generator\n const getOptionProps = useCallback(\n (index: number, selected: boolean = false) => ({\n id: navigation.getOptionId(listboxId, index),\n role: 'option' as const,\n 'aria-selected': selected\n }),\n [navigation.getOptionId, listboxId]\n );\n \n return {\n containerProps,\n inputProps,\n listboxProps,\n getOptionProps,\n highlightedIndex: navigation.highlightedIndex,\n setHighlightedIndex: navigation.setHighlightedIndex,\n getOptionId: navigation.getOptionId\n };\n}\n"],"names":["useRef","useCallback","useEffect","useComboboxNavigation","useDismissOnFocusOut","useCombobox","items","isOpen","onOpenChange","onSelect","listboxId","loop","disabled","optionSelector","hasItems","listboxRef","pointerDownInListboxRef","tabKeyPressedRef","shouldShowExpanded","undefined","length","closeDropdown","current","navigation","onClose","onOpen","dismissHandlers","onFocusOut","onEscape","containerProps","onBlurCapture","e","inputProps","role","highlightedIndex","getOptionId","onKeyDown","key","handleKeyDown","listboxProps","id","ref","onMouseDownCapture","_e","onMouseUpCapture","onMouseLeave","getOptionProps","index","selected","setHighlightedIndex"],"mappings":"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"}
1
+ {"version":3,"file":"index194.js","sources":["../src/utils/a11y/useCombobox.ts"],"sourcesContent":["import { useRef, useCallback, useEffect } from 'react';\nimport type { RefObject } from 'react';\nimport { useComboboxNavigation } from './useComboboxNavigation';\nimport { useDismissOnFocusOut } from './useDismissOnFocusOut';\nimport type { UseDismissOnFocusOutReturn } from './useDismissOnFocusOut';\n\nexport interface UseComboboxOptions<T = any> {\n /**\n * Array of items to navigate through\n */\n items: T[];\n \n /**\n * Whether the dropdown is currently open\n */\n isOpen: boolean;\n \n /**\n * Callback to change the open state\n */\n onOpenChange: (open: boolean) => void;\n \n /**\n * Callback when an item is selected (Enter key)\n */\n onSelect: (item: T, index: number) => void;\n \n /**\n * Stable ID for the listbox element\n */\n listboxId: string;\n \n /**\n * Whether to wrap around at the ends of the list.\n * Default: true\n */\n loop?: boolean;\n \n /**\n * Whether keyboard navigation is disabled\n * (e.g., for custom rendered content)\n */\n disabled?: boolean;\n \n /**\n * CSS selector for option elements (default: '[role=\"option\"]')\n */\n optionSelector?: string;\n \n /**\n * Whether the listbox has any items to show\n * Used for aria-expanded logic\n * Default: items.length > 0\n */\n hasItems?: boolean;\n}\n\nexport interface UseComboboxReturn {\n /**\n * Props to spread on the container element (handles dismiss on focus out)\n */\n containerProps: UseDismissOnFocusOutReturn<HTMLElement>;\n \n /**\n * Props to spread on the combobox input element\n */\n inputProps: {\n role: 'combobox';\n 'aria-expanded': boolean;\n 'aria-haspopup': 'listbox';\n 'aria-controls': string | undefined;\n 'aria-autocomplete': 'list';\n 'aria-activedescendant': string | undefined;\n onKeyDown: (e: React.KeyboardEvent) => void;\n };\n \n /**\n * Props to spread on the listbox element\n */\n listboxProps: {\n id: string;\n role: 'listbox';\n ref: RefObject<HTMLDivElement | null>;\n onMouseDownCapture: (e: React.MouseEvent) => void;\n onMouseUpCapture: (e: React.MouseEvent) => void;\n onMouseLeave: (e: React.MouseEvent) => void;\n };\n \n /**\n * Generate props for an option element at the given index\n * @param selected - Whether this option is the currently selected/chosen value (not keyboard highlight)\n */\n getOptionProps: (index: number, selected?: boolean) => {\n id: string;\n role: 'option';\n 'aria-selected': boolean;\n };\n \n /**\n * Currently highlighted index (-1 if none)\n */\n highlightedIndex: number;\n \n /**\n * Set the highlighted index manually\n */\n setHighlightedIndex: (index: number | ((prev: number) => number)) => void;\n \n /**\n * Generate stable ID for an option\n */\n getOptionId: (listboxId: string, index: number) => string;\n}\n\n/**\n * Comprehensive hook for implementing WAI-ARIA combobox pattern.\n * \n * Combines:\n * - Keyboard navigation (Arrow Up/Down, Enter, Escape, Tab)\n * - Focus management and dismissal\n * - ARIA attributes for accessibility\n * - Auto-scroll highlighted item into view\n * \n * This hook provides a complete, batteries-included solution for building\n * accessible combobox components (autocomplete, select, search with suggestions, etc.)\n * \n * @example Basic usage\n * ```tsx\n * const MyCombobox = () => {\n * const [isOpen, setIsOpen] = useState(false);\n * const [items, setItems] = useState(['Apple', 'Banana', 'Cherry']);\n * \n * const {\n * containerProps,\n * inputProps,\n * listboxProps,\n * getOptionProps,\n * highlightedIndex\n * } = useCombobox({\n * items,\n * isOpen,\n * onOpenChange: setIsOpen,\n * onSelect: (item) => console.log('Selected:', item),\n * listboxId: 'my-listbox'\n * });\n * \n * return (\n * <div {...containerProps}>\n * <input {...inputProps} />\n * {isOpen && (\n * <div {...listboxProps}>\n * {items.map((item, i) => (\n * <div key={i} {...getOptionProps(i)}>\n * {item}\n * </div>\n * ))}\n * </div>\n * )}\n * </div>\n * );\n * };\n * ```\n * \n * @example With custom ARIA labels and handlers\n * ```tsx\n * const MySearchBox = () => {\n * const [query, setQuery] = useState('');\n * const [suggestions, setSuggestions] = useState([]);\n * const [isOpen, setIsOpen] = useState(false);\n * \n * const { containerProps, inputProps, listboxProps, getOptionProps } = useCombobox({\n * items: suggestions,\n * isOpen,\n * onOpenChange: setIsOpen,\n * onSelect: (suggestion) => {\n * setQuery(suggestion);\n * setIsOpen(false);\n * },\n * listboxId: 'search-suggestions'\n * });\n * \n * return (\n * <div {...containerProps}>\n * <input\n * {...inputProps}\n * value={query}\n * onChange={(e) => setQuery(e.target.value)}\n * aria-label=\"Search\"\n * />\n * {isOpen && suggestions.length > 0 && (\n * <div {...listboxProps} aria-label=\"Search suggestions\">\n * {suggestions.map((suggestion, i) => (\n * <div\n * key={i}\n * {...getOptionProps(i)}\n * onClick={() => {\n * setQuery(suggestion);\n * setIsOpen(false);\n * }}\n * >\n * {suggestion}\n * </div>\n * ))}\n * </div>\n * )}\n * </div>\n * );\n * };\n * ```\n */\nexport function useCombobox<T = any>({\n items,\n isOpen,\n onOpenChange,\n onSelect,\n listboxId,\n loop = true,\n disabled = false,\n optionSelector = '[role=\"option\"]',\n hasItems\n}: UseComboboxOptions<T>): UseComboboxReturn {\n const listboxRef = useRef<HTMLDivElement | null>(null);\n const pointerDownInListboxRef = useRef(false);\n const tabKeyPressedRef = useRef(false);\n \n // Determine if we should show as expanded\n const shouldShowExpanded = hasItems !== undefined ? hasItems : items.length > 0;\n \n // Close dropdown callback\n const closeDropdown = useCallback(() => {\n onOpenChange(false);\n }, [onOpenChange]);\n\n // Ensure pointer state doesn't get stuck when listbox unmounts\n useEffect(() => {\n if (!isOpen) {\n pointerDownInListboxRef.current = false;\n }\n }, [isOpen]);\n \n // Keyboard navigation with aria-activedescendant\n const navigation = useComboboxNavigation<T>({\n items,\n isOpen,\n onSelect,\n onClose: closeDropdown,\n onOpen: () => onOpenChange(true),\n loop,\n disabled,\n listboxRef,\n optionSelector\n });\n \n // Focus out / Escape dismissal\n const dismissHandlers = useDismissOnFocusOut({\n onFocusOut: closeDropdown,\n onEscape: closeDropdown,\n disabled: !isOpen\n });\n\n const containerProps: UseDismissOnFocusOutReturn<HTMLElement> = {\n ...dismissHandlers,\n onBlurCapture: (e) => {\n // Clicking inside a listbox option can blur the input (relatedTarget is null),\n // which would dismiss before the click handler runs. Prevent that.\n if (pointerDownInListboxRef.current) return;\n \n // Tab key pressed - let Tab handler close dropdown, skip blur detection\n if (tabKeyPressedRef.current) {\n tabKeyPressedRef.current = false;\n return;\n }\n \n dismissHandlers.onBlurCapture(e);\n }\n };\n \n // Build input props\n const inputProps = {\n role: 'combobox' as const,\n 'aria-expanded': isOpen && shouldShowExpanded,\n 'aria-haspopup': 'listbox' as const,\n 'aria-controls': isOpen ? listboxId : undefined,\n 'aria-autocomplete': 'list' as const,\n 'aria-activedescendant': \n navigation.highlightedIndex >= 0 \n ? navigation.getOptionId(listboxId, navigation.highlightedIndex) \n : undefined,\n onKeyDown: (e: React.KeyboardEvent) => {\n // Set flag when Tab is pressed (before blur fires)\n if (e.key === 'Tab') {\n tabKeyPressedRef.current = true;\n }\n navigation.handleKeyDown(e);\n }\n };\n \n // Build listbox props\n const listboxProps = {\n id: listboxId,\n role: 'listbox' as const,\n ref: listboxRef,\n onMouseDownCapture: (_e: React.MouseEvent) => {\n pointerDownInListboxRef.current = true;\n },\n onMouseUpCapture: (_e: React.MouseEvent) => {\n pointerDownInListboxRef.current = false;\n },\n onMouseLeave: (_e: React.MouseEvent) => {\n pointerDownInListboxRef.current = false;\n }\n };\n \n // Option props generator\n const getOptionProps = useCallback(\n (index: number, selected: boolean = false) => ({\n id: navigation.getOptionId(listboxId, index),\n role: 'option' as const,\n 'aria-selected': selected\n }),\n [navigation.getOptionId, listboxId]\n );\n \n return {\n containerProps,\n inputProps,\n listboxProps,\n getOptionProps,\n highlightedIndex: navigation.highlightedIndex,\n setHighlightedIndex: navigation.setHighlightedIndex,\n getOptionId: navigation.getOptionId\n };\n}\n"],"names":["useRef","useCallback","useEffect","useComboboxNavigation","useDismissOnFocusOut","useCombobox","items","isOpen","onOpenChange","onSelect","listboxId","loop","disabled","optionSelector","hasItems","listboxRef","pointerDownInListboxRef","tabKeyPressedRef","shouldShowExpanded","undefined","length","closeDropdown","current","navigation","onClose","onOpen","dismissHandlers","onFocusOut","onEscape","containerProps","onBlurCapture","e","inputProps","role","highlightedIndex","getOptionId","onKeyDown","key","handleKeyDown","listboxProps","id","ref","onMouseDownCapture","_e","onMouseUpCapture","onMouseLeave","getOptionProps","index","selected","setHighlightedIndex"],"mappings":"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"}
@@ -23,4 +23,4 @@ function p({
23
23
  export {
24
24
  p as useDismissOnEscape
25
25
  };
26
- //# sourceMappingURL=index193.js.map
26
+ //# sourceMappingURL=index196.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index193.js","sources":["../src/utils/a11y/useDismissOnEscape.ts"],"sourcesContent":["import { useEffect } from 'react';\nimport type { RefObject } from 'react';\n\nexport interface UseDismissOnEscapeOptions<T extends HTMLElement = HTMLElement> {\n /**\n * Container element ref to check if focus is within.\n * Escape will only trigger if focus is within this container.\n */\n containerRef: RefObject<T | null>;\n /**\n * Callback when Escape key is pressed and focus is within container.\n */\n onDismiss?: () => void;\n /**\n * Whether the Escape handler is active.\n * Default: true\n */\n enabled?: boolean;\n /**\n * Whether to call preventDefault() when handling Escape.\n * Default: true\n */\n preventDefault?: boolean;\n /**\n * Whether to call stopPropagation() when handling Escape.\n * Default: true\n */\n stopPropagation?: boolean;\n}\n\n/**\n * Hook to handle Escape key dismissal when focus is within a container.\n * \n * This is a UX pattern: if user is interacting with an overlay/sidebar\n * (indicated by focus being within it), Escape should close it.\n * \n * @example\n * ```tsx\n * const MySidebar = ({ isOpen, onClose }) => {\n * const containerRef = useRef<HTMLDivElement>(null);\n * \n * useDismissOnEscape({\n * containerRef,\n * onDismiss: onClose,\n * enabled: isOpen\n * });\n * \n * return <div ref={containerRef}>...</div>;\n * };\n * ```\n */\nexport function useDismissOnEscape<T extends HTMLElement = HTMLElement>({\n containerRef,\n onDismiss,\n enabled = true,\n preventDefault = true,\n stopPropagation = true\n}: UseDismissOnEscapeOptions<T>): void {\n useEffect(() => {\n if (!enabled || !onDismiss) return;\n \n const container = containerRef.current;\n if (!container) return;\n\n const handleEscape = (e: KeyboardEvent) => {\n if (e.key === 'Escape' && container.contains(document.activeElement)) {\n preventDefault && e.preventDefault();\n stopPropagation && e.stopPropagation();\n onDismiss();\n }\n };\n\n document.addEventListener('keydown', handleEscape, { capture: true });\n return () => document.removeEventListener('keydown', handleEscape, { capture: true });\n }, [enabled, onDismiss, containerRef, preventDefault, stopPropagation]);\n}\n"],"names":["useEffect","useDismissOnEscape","containerRef","onDismiss","enabled","preventDefault","stopPropagation","container","current","handleEscape","e","key","contains","document","activeElement","addEventListener","capture","removeEventListener"],"mappings":"AAmDO,SAAA,aAAAA,SAAA;AAAA,SAASC,EAAwD;AAAA,EACtEC,cAAAA;AAAAA,EACAC,WAAAA;AAAAA,EACAC,SAAAA,IAAU;AAAA,EACVC,gBAAAA,IAAiB;AAAA,EACjBC,iBAAAA,IAAkB;AACU,GAAS;AACrCN,EAAAA,EAAU,MAAM;AACd,QAAI,CAACI,KAAW,CAACD,EAAW;AAE5B,UAAMI,IAAYL,EAAaM;AAC/B,QAAI,CAACD,EAAW;AAEhB,UAAME,IAAeA,CAACC,MAAqB;AACzC,MAAIA,EAAEC,QAAQ,YAAYJ,EAAUK,SAASC,SAASC,aAAa,MACjET,KAAkBK,EAAEL,eAAAA,GACpBC,KAAmBI,EAAEJ,gBAAAA,GACrBH,EAAAA;AAAAA,IAEJ;AAEAU,oBAASE,iBAAiB,WAAWN,GAAc;AAAA,MAAEO,SAAS;AAAA,IAAA,CAAM,GAC7D,MAAMH,SAASI,oBAAoB,WAAWR,GAAc;AAAA,MAAEO,SAAS;AAAA,IAAA,CAAM;AAAA,EACtF,GAAG,CAACZ,GAASD,GAAWD,GAAcG,GAAgBC,CAAe,CAAC;AACxE;"}
1
+ {"version":3,"file":"index196.js","sources":["../src/utils/a11y/useDismissOnEscape.ts"],"sourcesContent":["import { useEffect } from 'react';\nimport type { RefObject } from 'react';\n\nexport interface UseDismissOnEscapeOptions<T extends HTMLElement = HTMLElement> {\n /**\n * Container element ref to check if focus is within.\n * Escape will only trigger if focus is within this container.\n */\n containerRef: RefObject<T | null>;\n /**\n * Callback when Escape key is pressed and focus is within container.\n */\n onDismiss?: () => void;\n /**\n * Whether the Escape handler is active.\n * Default: true\n */\n enabled?: boolean;\n /**\n * Whether to call preventDefault() when handling Escape.\n * Default: true\n */\n preventDefault?: boolean;\n /**\n * Whether to call stopPropagation() when handling Escape.\n * Default: true\n */\n stopPropagation?: boolean;\n}\n\n/**\n * Hook to handle Escape key dismissal when focus is within a container.\n * \n * This is a UX pattern: if user is interacting with an overlay/sidebar\n * (indicated by focus being within it), Escape should close it.\n * \n * @example\n * ```tsx\n * const MySidebar = ({ isOpen, onClose }) => {\n * const containerRef = useRef<HTMLDivElement>(null);\n * \n * useDismissOnEscape({\n * containerRef,\n * onDismiss: onClose,\n * enabled: isOpen\n * });\n * \n * return <div ref={containerRef}>...</div>;\n * };\n * ```\n */\nexport function useDismissOnEscape<T extends HTMLElement = HTMLElement>({\n containerRef,\n onDismiss,\n enabled = true,\n preventDefault = true,\n stopPropagation = true\n}: UseDismissOnEscapeOptions<T>): void {\n useEffect(() => {\n if (!enabled || !onDismiss) return;\n \n const container = containerRef.current;\n if (!container) return;\n\n const handleEscape = (e: KeyboardEvent) => {\n if (e.key === 'Escape' && container.contains(document.activeElement)) {\n preventDefault && e.preventDefault();\n stopPropagation && e.stopPropagation();\n onDismiss();\n }\n };\n\n document.addEventListener('keydown', handleEscape, { capture: true });\n return () => document.removeEventListener('keydown', handleEscape, { capture: true });\n }, [enabled, onDismiss, containerRef, preventDefault, stopPropagation]);\n}\n"],"names":["useEffect","useDismissOnEscape","containerRef","onDismiss","enabled","preventDefault","stopPropagation","container","current","handleEscape","e","key","contains","document","activeElement","addEventListener","capture","removeEventListener"],"mappings":"AAmDO,SAAA,aAAAA,SAAA;AAAA,SAASC,EAAwD;AAAA,EACtEC,cAAAA;AAAAA,EACAC,WAAAA;AAAAA,EACAC,SAAAA,IAAU;AAAA,EACVC,gBAAAA,IAAiB;AAAA,EACjBC,iBAAAA,IAAkB;AACU,GAAS;AACrCN,EAAAA,EAAU,MAAM;AACd,QAAI,CAACI,KAAW,CAACD,EAAW;AAE5B,UAAMI,IAAYL,EAAaM;AAC/B,QAAI,CAACD,EAAW;AAEhB,UAAME,IAAeA,CAACC,MAAqB;AACzC,MAAIA,EAAEC,QAAQ,YAAYJ,EAAUK,SAASC,SAASC,aAAa,MACjET,KAAkBK,EAAEL,eAAAA,GACpBC,KAAmBI,EAAEJ,gBAAAA,GACrBH,EAAAA;AAAAA,IAEJ;AAEAU,oBAASE,iBAAiB,WAAWN,GAAc;AAAA,MAAEO,SAAS;AAAA,IAAA,CAAM,GAC7D,MAAMH,SAASI,oBAAoB,WAAWR,GAAc;AAAA,MAAEO,SAAS;AAAA,IAAA,CAAM;AAAA,EACtF,GAAG,CAACZ,GAASD,GAAWD,GAAcG,GAAgBC,CAAe,CAAC;AACxE;"}
@@ -12,4 +12,4 @@ function n(o, u) {
12
12
  export {
13
13
  n as debounce
14
14
  };
15
- //# sourceMappingURL=index201.js.map
15
+ //# sourceMappingURL=index204.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index201.js","sources":["../src/utils/debounce.ts"],"sourcesContent":["export function debounce<T extends (...args: any[]) => void>(func: T, wait: number) {\n let timeout: ReturnType<typeof setTimeout> | null;\n const debounced = (...args: Parameters<T>) => {\n if (timeout) clearTimeout(timeout);\n timeout = setTimeout(() => {\n func(...args);\n }, wait);\n };\n debounced.cancel = () => {\n if (timeout) clearTimeout(timeout);\n timeout = null;\n };\n return debounced as T & { cancel: () => void };\n }"],"names":["debounce","func","wait","timeout","debounced","args","setTimeout","cancel"],"mappings":"AAAO,SAASA,EAA6CC,GAASC,GAAc;AAChF,MAAIC;AACJ,QAAMC,IAAYA,IAAIC,MAAwB;AAC5C,IAAIF,kBAAsBA,CAAO,GACjCA,IAAUG,WAAW,MAAM;AACzBL,MAAAA,EAAK,GAAGI,CAAI;AAAA,IACd,GAAGH,CAAI;AAAA,EACT;AACAE,SAAAA,EAAUG,SAAS,MAAM;AACvB,IAAIJ,kBAAsBA,CAAO,GACjCA,IAAU;AAAA,EACZ,GACOC;AACT;"}
1
+ {"version":3,"file":"index204.js","sources":["../src/utils/debounce.ts"],"sourcesContent":["export function debounce<T extends (...args: any[]) => void>(func: T, wait: number) {\n let timeout: ReturnType<typeof setTimeout> | null;\n const debounced = (...args: Parameters<T>) => {\n if (timeout) clearTimeout(timeout);\n timeout = setTimeout(() => {\n func(...args);\n }, wait);\n };\n debounced.cancel = () => {\n if (timeout) clearTimeout(timeout);\n timeout = null;\n };\n return debounced as T & { cancel: () => void };\n }"],"names":["debounce","func","wait","timeout","debounced","args","setTimeout","cancel"],"mappings":"AAAO,SAASA,EAA6CC,GAASC,GAAc;AAChF,MAAIC;AACJ,QAAMC,IAAYA,IAAIC,MAAwB;AAC5C,IAAIF,kBAAsBA,CAAO,GACjCA,IAAUG,WAAW,MAAM;AACzBL,MAAAA,EAAK,GAAGI,CAAI;AAAA,IACd,GAAGH,CAAI;AAAA,EACT;AACAE,SAAAA,EAAUG,SAAS,MAAM;AACvB,IAAIJ,kBAAsBA,CAAO,GACjCA,IAAU;AAAA,EACZ,GACOC;AACT;"}