@mieweb/ui 0.7.3-dev.9 → 0.8.0-dev.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 (313) hide show
  1. package/dist/brands/index.cjs +12 -12
  2. package/dist/brands/index.js +3 -3
  3. package/dist/chunk-3IMM2PM4.js +259 -0
  4. package/dist/chunk-3IMM2PM4.js.map +1 -0
  5. package/dist/chunk-3SHLOF4V.cjs +128 -0
  6. package/dist/chunk-3SHLOF4V.cjs.map +1 -0
  7. package/dist/chunk-3TXOFAXP.cjs +139 -0
  8. package/dist/chunk-3TXOFAXP.cjs.map +1 -0
  9. package/dist/{chunk-ZBI52NP2.cjs → chunk-56QJHQ5C.cjs} +156 -39
  10. package/dist/chunk-56QJHQ5C.cjs.map +1 -0
  11. package/dist/chunk-5JZIDILK.cjs +164 -0
  12. package/dist/chunk-5JZIDILK.cjs.map +1 -0
  13. package/dist/chunk-5MXO6PEV.cjs +78 -0
  14. package/dist/chunk-5MXO6PEV.cjs.map +1 -0
  15. package/dist/chunk-5QZ73PZC.js +62 -0
  16. package/dist/chunk-5QZ73PZC.js.map +1 -0
  17. package/dist/chunk-6NZXWKUE.js +3 -0
  18. package/dist/chunk-6NZXWKUE.js.map +1 -0
  19. package/dist/chunk-6SCQ7FKT.js +115 -0
  20. package/dist/chunk-6SCQ7FKT.js.map +1 -0
  21. package/dist/{chunk-KFLDXJEE.js → chunk-753Z3NXL.js} +46 -15
  22. package/dist/chunk-753Z3NXL.js.map +1 -0
  23. package/dist/{chunk-S3MKIDYG.cjs → chunk-7AECNMYV.cjs} +46 -15
  24. package/dist/chunk-7AECNMYV.cjs.map +1 -0
  25. package/dist/chunk-7IKLGH3Z.cjs +92 -0
  26. package/dist/chunk-7IKLGH3Z.cjs.map +1 -0
  27. package/dist/chunk-7L7OPISJ.cjs +291 -0
  28. package/dist/chunk-7L7OPISJ.cjs.map +1 -0
  29. package/dist/chunk-7RV6CAP6.cjs +106 -0
  30. package/dist/chunk-7RV6CAP6.cjs.map +1 -0
  31. package/dist/{chunk-LC7YHZXM.js → chunk-A5YOIJKL.js} +5 -5
  32. package/dist/{chunk-LC7YHZXM.js.map → chunk-A5YOIJKL.js.map} +1 -1
  33. package/dist/{chunk-CVZYOMEW.js → chunk-AESFOMSH.js} +325 -3
  34. package/dist/chunk-AESFOMSH.js.map +1 -0
  35. package/dist/{chunk-RBS3GHDZ.cjs → chunk-BOW7ZGI2.cjs} +4 -4
  36. package/dist/{chunk-RBS3GHDZ.cjs.map → chunk-BOW7ZGI2.cjs.map} +1 -1
  37. package/dist/{chunk-WUNWHOLA.cjs → chunk-BSDBI6H7.cjs} +116 -26
  38. package/dist/chunk-BSDBI6H7.cjs.map +1 -0
  39. package/dist/chunk-CG4ZKJLE.js +84 -0
  40. package/dist/chunk-CG4ZKJLE.js.map +1 -0
  41. package/dist/{chunk-Z4PECE5S.js → chunk-DX64KLSN.js} +2 -2
  42. package/dist/{chunk-Z4PECE5S.js.map → chunk-DX64KLSN.js.map} +1 -1
  43. package/dist/chunk-ELYGV32O.cjs +230 -0
  44. package/dist/chunk-ELYGV32O.cjs.map +1 -0
  45. package/dist/{chunk-QUUBTNMH.js → chunk-EPSB4WTL.js} +45 -15
  46. package/dist/chunk-EPSB4WTL.js.map +1 -0
  47. package/dist/chunk-F57VRLKP.js +708 -0
  48. package/dist/chunk-F57VRLKP.js.map +1 -0
  49. package/dist/{chunk-5IDYOJHO.cjs → chunk-G7EQ3JPX.cjs} +45 -15
  50. package/dist/chunk-G7EQ3JPX.cjs.map +1 -0
  51. package/dist/{chunk-FKLUSYFP.cjs → chunk-GQVL2JKQ.cjs} +4 -4
  52. package/dist/{chunk-FKLUSYFP.cjs.map → chunk-GQVL2JKQ.cjs.map} +1 -1
  53. package/dist/{chunk-3D4ITDLO.js → chunk-GXODR6V4.js} +3 -3
  54. package/dist/{chunk-3D4ITDLO.js.map → chunk-GXODR6V4.js.map} +1 -1
  55. package/dist/{chunk-AFGADE3B.js → chunk-H3YO5GBM.js} +117 -27
  56. package/dist/chunk-H3YO5GBM.js.map +1 -0
  57. package/dist/chunk-HK3AMH3Q.cjs +151 -0
  58. package/dist/chunk-HK3AMH3Q.cjs.map +1 -0
  59. package/dist/chunk-HQ3XPCHG.js +114 -0
  60. package/dist/chunk-HQ3XPCHG.js.map +1 -0
  61. package/dist/chunk-I44YNYI6.cjs +4 -0
  62. package/dist/chunk-I44YNYI6.cjs.map +1 -0
  63. package/dist/{chunk-5FAWCLPY.js → chunk-IILJGFI5.js} +40 -29
  64. package/dist/chunk-IILJGFI5.js.map +1 -0
  65. package/dist/{chunk-XFRQFWSY.js → chunk-IYXCFIMP.js} +8 -8
  66. package/dist/{chunk-XFRQFWSY.js.map → chunk-IYXCFIMP.js.map} +1 -1
  67. package/dist/{chunk-6J7UGYT5.cjs → chunk-JHGMZX4I.cjs} +47 -7
  68. package/dist/chunk-JHGMZX4I.cjs.map +1 -0
  69. package/dist/chunk-JHZW3Y62.js +142 -0
  70. package/dist/chunk-JHZW3Y62.js.map +1 -0
  71. package/dist/{chunk-JDHIBJ5K.cjs → chunk-JWTCEWQ4.cjs} +2 -2
  72. package/dist/{chunk-JDHIBJ5K.cjs.map → chunk-JWTCEWQ4.cjs.map} +1 -1
  73. package/dist/{chunk-URHXR5SC.cjs → chunk-KVE7PQ5P.cjs} +7 -7
  74. package/dist/{chunk-URHXR5SC.cjs.map → chunk-KVE7PQ5P.cjs.map} +1 -1
  75. package/dist/{chunk-MJFF4AXH.cjs → chunk-L6D4CKLV.cjs} +325 -3
  76. package/dist/chunk-L6D4CKLV.cjs.map +1 -0
  77. package/dist/chunk-L6MDULYB.js +87 -0
  78. package/dist/chunk-L6MDULYB.js.map +1 -0
  79. package/dist/{chunk-SYIFEJSF.cjs → chunk-LQHI44OZ.cjs} +13 -13
  80. package/dist/{chunk-SYIFEJSF.cjs.map → chunk-LQHI44OZ.cjs.map} +1 -1
  81. package/dist/{chunk-HIDV32ZX.js → chunk-LZU7YBXG.js} +3 -3
  82. package/dist/{chunk-HIDV32ZX.js.map → chunk-LZU7YBXG.js.map} +1 -1
  83. package/dist/chunk-N5O47VGS.cjs +109 -0
  84. package/dist/chunk-N5O47VGS.cjs.map +1 -0
  85. package/dist/chunk-NGSDBWKA.cjs +84 -0
  86. package/dist/chunk-NGSDBWKA.cjs.map +1 -0
  87. package/dist/chunk-NMBYU7D7.cjs +31 -0
  88. package/dist/chunk-NMBYU7D7.cjs.map +1 -0
  89. package/dist/{chunk-P6L74SKG.js → chunk-QGZC43L7.js} +47 -7
  90. package/dist/chunk-QGZC43L7.js.map +1 -0
  91. package/dist/{chunk-FTRGZOVJ.js → chunk-QHTDWIED.js} +3 -3
  92. package/dist/{chunk-FTRGZOVJ.js.map → chunk-QHTDWIED.js.map} +1 -1
  93. package/dist/chunk-RUGHNFQG.js +28 -0
  94. package/dist/chunk-RUGHNFQG.js.map +1 -0
  95. package/dist/{chunk-Q6A4RVAN.cjs → chunk-SK7H3Z67.cjs} +37 -37
  96. package/dist/{chunk-Q6A4RVAN.cjs.map → chunk-SK7H3Z67.cjs.map} +1 -1
  97. package/dist/{chunk-MO65V64I.js → chunk-TXRQQMG5.js} +2 -2
  98. package/dist/{chunk-MO65V64I.js.map → chunk-TXRQQMG5.js.map} +1 -1
  99. package/dist/{chunk-3YDTZUI6.cjs → chunk-U5TTXN45.cjs} +42 -31
  100. package/dist/chunk-U5TTXN45.cjs.map +1 -0
  101. package/dist/chunk-WBGUYSWY.js +90 -0
  102. package/dist/chunk-WBGUYSWY.js.map +1 -0
  103. package/dist/{chunk-LJBWCUKP.cjs → chunk-WIYQI35R.cjs} +2 -2
  104. package/dist/{chunk-LJBWCUKP.cjs.map → chunk-WIYQI35R.cjs.map} +1 -1
  105. package/dist/chunk-WKSUL2ZN.js +56 -0
  106. package/dist/chunk-WKSUL2ZN.js.map +1 -0
  107. package/dist/chunk-X5ZPYYMS.js +105 -0
  108. package/dist/chunk-X5ZPYYMS.js.map +1 -0
  109. package/dist/{chunk-DLBV42JD.js → chunk-XBKOZRDO.js} +156 -39
  110. package/dist/chunk-XBKOZRDO.js.map +1 -0
  111. package/dist/{chunk-XB54G7WS.cjs → chunk-XJTFZLWH.cjs} +2 -86
  112. package/dist/chunk-XJTFZLWH.cjs.map +1 -0
  113. package/dist/chunk-XMECP2MD.js +208 -0
  114. package/dist/chunk-XMECP2MD.js.map +1 -0
  115. package/dist/{chunk-GTHNWP4P.js → chunk-XUVEF2RQ.js} +4 -87
  116. package/dist/chunk-XUVEF2RQ.js.map +1 -0
  117. package/dist/chunk-XWYKLEKG.js +269 -0
  118. package/dist/chunk-XWYKLEKG.js.map +1 -0
  119. package/dist/chunk-Y6YSJPVC.js +129 -0
  120. package/dist/chunk-Y6YSJPVC.js.map +1 -0
  121. package/dist/chunk-YVIH26FG.cjs +736 -0
  122. package/dist/chunk-YVIH26FG.cjs.map +1 -0
  123. package/dist/chunk-Z5S5JEJD.cjs +286 -0
  124. package/dist/chunk-Z5S5JEJD.cjs.map +1 -0
  125. package/dist/chunk-ZO4L6C2Y.cjs +137 -0
  126. package/dist/chunk-ZO4L6C2Y.cjs.map +1 -0
  127. package/dist/{collabKit-QZL4P5T5.js → collabKit-A643VH2I.js} +7 -3
  128. package/dist/collabKit-A643VH2I.js.map +1 -0
  129. package/dist/{collabKit-UF7E6V3N.cjs → collabKit-Q4A36LDA.cjs} +7 -3
  130. package/dist/collabKit-Q4A36LDA.cjs.map +1 -0
  131. package/dist/components/Accordion/index.cjs +13 -0
  132. package/dist/components/Accordion/index.cjs.map +1 -0
  133. package/dist/components/Accordion/index.d.cts +50 -0
  134. package/dist/components/Accordion/index.d.ts +50 -0
  135. package/dist/components/Accordion/index.js +4 -0
  136. package/dist/components/Accordion/index.js.map +1 -0
  137. package/dist/components/Alert/index.d.cts +1 -1
  138. package/dist/components/Alert/index.d.ts +1 -1
  139. package/dist/components/Autocomplete/index.cjs +4 -3
  140. package/dist/components/Autocomplete/index.d.cts +20 -3
  141. package/dist/components/Autocomplete/index.d.ts +20 -3
  142. package/dist/components/Autocomplete/index.js +3 -2
  143. package/dist/components/Badge/index.d.cts +1 -1
  144. package/dist/components/Badge/index.d.ts +1 -1
  145. package/dist/components/Card/index.d.cts +1 -1
  146. package/dist/components/Card/index.d.ts +1 -1
  147. package/dist/components/Checkbox/index.cjs +5 -4
  148. package/dist/components/Checkbox/index.d.cts +9 -1
  149. package/dist/components/Checkbox/index.d.ts +9 -1
  150. package/dist/components/Checkbox/index.js +2 -1
  151. package/dist/components/ClampedText/index.cjs +13 -0
  152. package/dist/components/ClampedText/index.cjs.map +1 -0
  153. package/dist/components/ClampedText/index.d.cts +33 -0
  154. package/dist/components/ClampedText/index.d.ts +33 -0
  155. package/dist/components/ClampedText/index.js +4 -0
  156. package/dist/components/ClampedText/index.js.map +1 -0
  157. package/dist/components/CopyButton/index.cjs +13 -0
  158. package/dist/components/CopyButton/index.cjs.map +1 -0
  159. package/dist/components/CopyButton/index.d.cts +29 -0
  160. package/dist/components/CopyButton/index.d.ts +29 -0
  161. package/dist/components/CopyButton/index.js +4 -0
  162. package/dist/components/CopyButton/index.js.map +1 -0
  163. package/dist/components/CustomizableDashboard/index.cjs +43 -0
  164. package/dist/components/CustomizableDashboard/index.cjs.map +1 -0
  165. package/dist/components/CustomizableDashboard/index.d.cts +195 -0
  166. package/dist/components/CustomizableDashboard/index.d.ts +195 -0
  167. package/dist/components/CustomizableDashboard/index.js +10 -0
  168. package/dist/components/CustomizableDashboard/index.js.map +1 -0
  169. package/dist/components/DateInput/index.cjs +4 -3
  170. package/dist/components/DateInput/index.d.cts +1 -0
  171. package/dist/components/DateInput/index.d.ts +1 -0
  172. package/dist/components/DateInput/index.js +3 -2
  173. package/dist/components/Dropdown/index.cjs +9 -8
  174. package/dist/components/Dropdown/index.js +3 -2
  175. package/dist/components/FilterSummaryBar/index.cjs +13 -0
  176. package/dist/components/FilterSummaryBar/index.cjs.map +1 -0
  177. package/dist/components/FilterSummaryBar/index.d.cts +53 -0
  178. package/dist/components/FilterSummaryBar/index.d.ts +53 -0
  179. package/dist/components/FilterSummaryBar/index.js +4 -0
  180. package/dist/components/FilterSummaryBar/index.js.map +1 -0
  181. package/dist/components/FreshnessBadge/index.cjs +25 -0
  182. package/dist/components/FreshnessBadge/index.cjs.map +1 -0
  183. package/dist/components/FreshnessBadge/index.d.cts +49 -0
  184. package/dist/components/FreshnessBadge/index.d.ts +49 -0
  185. package/dist/components/FreshnessBadge/index.js +4 -0
  186. package/dist/components/FreshnessBadge/index.js.map +1 -0
  187. package/dist/components/GlossaryTooltip/index.cjs +15 -0
  188. package/dist/components/GlossaryTooltip/index.cjs.map +1 -0
  189. package/dist/components/GlossaryTooltip/index.d.cts +64 -0
  190. package/dist/components/GlossaryTooltip/index.d.ts +64 -0
  191. package/dist/components/GlossaryTooltip/index.js +6 -0
  192. package/dist/components/GlossaryTooltip/index.js.map +1 -0
  193. package/dist/components/Input/index.cjs +20 -3
  194. package/dist/components/Input/index.d.cts +37 -2
  195. package/dist/components/Input/index.d.ts +37 -2
  196. package/dist/components/Input/index.js +2 -1
  197. package/dist/components/KeyboardShortcutsOverlay/index.cjs +21 -0
  198. package/dist/components/KeyboardShortcutsOverlay/index.cjs.map +1 -0
  199. package/dist/components/KeyboardShortcutsOverlay/index.d.cts +54 -0
  200. package/dist/components/KeyboardShortcutsOverlay/index.d.ts +54 -0
  201. package/dist/components/KeyboardShortcutsOverlay/index.js +8 -0
  202. package/dist/components/KeyboardShortcutsOverlay/index.js.map +1 -0
  203. package/dist/components/Markdown/index.cjs +10 -10
  204. package/dist/components/Markdown/index.js +2 -2
  205. package/dist/components/MediaEditor/index.cjs +10 -9
  206. package/dist/components/MediaEditor/index.js +5 -4
  207. package/dist/components/PhoneInput/index.cjs +5 -4
  208. package/dist/components/PhoneInput/index.js +3 -2
  209. package/dist/components/Progress/index.d.cts +1 -1
  210. package/dist/components/Progress/index.d.ts +1 -1
  211. package/dist/components/Radio/index.cjs +5 -4
  212. package/dist/components/Radio/index.d.cts +9 -1
  213. package/dist/components/Radio/index.d.ts +9 -1
  214. package/dist/components/Radio/index.js +2 -1
  215. package/dist/components/ReadingProgressBar/index.cjs +13 -0
  216. package/dist/components/ReadingProgressBar/index.cjs.map +1 -0
  217. package/dist/components/ReadingProgressBar/index.d.cts +20 -0
  218. package/dist/components/ReadingProgressBar/index.d.ts +20 -0
  219. package/dist/components/ReadingProgressBar/index.js +4 -0
  220. package/dist/components/ReadingProgressBar/index.js.map +1 -0
  221. package/dist/components/RichTextEditor/index.cjs +7 -6
  222. package/dist/components/RichTextEditor/index.js +4 -3
  223. package/dist/components/SectionSpyNav/index.cjs +15 -0
  224. package/dist/components/SectionSpyNav/index.cjs.map +1 -0
  225. package/dist/components/SectionSpyNav/index.d.cts +63 -0
  226. package/dist/components/SectionSpyNav/index.d.ts +63 -0
  227. package/dist/components/SectionSpyNav/index.js +6 -0
  228. package/dist/components/SectionSpyNav/index.js.map +1 -0
  229. package/dist/components/Select/index.cjs +5 -3
  230. package/dist/components/Select/index.d.cts +56 -9
  231. package/dist/components/Select/index.d.ts +56 -9
  232. package/dist/components/Select/index.js +3 -1
  233. package/dist/components/Slider/index.d.cts +2 -2
  234. package/dist/components/Slider/index.d.ts +2 -2
  235. package/dist/components/SourceTip/index.cjs +15 -0
  236. package/dist/components/SourceTip/index.cjs.map +1 -0
  237. package/dist/components/SourceTip/index.d.cts +58 -0
  238. package/dist/components/SourceTip/index.d.ts +58 -0
  239. package/dist/components/SourceTip/index.js +6 -0
  240. package/dist/components/SourceTip/index.js.map +1 -0
  241. package/dist/components/Sparkline/index.cjs +13 -0
  242. package/dist/components/Sparkline/index.cjs.map +1 -0
  243. package/dist/components/Sparkline/index.d.cts +53 -0
  244. package/dist/components/Sparkline/index.d.ts +53 -0
  245. package/dist/components/Sparkline/index.js +4 -0
  246. package/dist/components/Sparkline/index.js.map +1 -0
  247. package/dist/components/Spinner/index.d.cts +1 -1
  248. package/dist/components/Spinner/index.d.ts +1 -1
  249. package/dist/components/SuperChat/index.cjs +8 -7
  250. package/dist/components/SuperChat/index.cjs.map +1 -1
  251. package/dist/components/SuperChat/index.js +4 -3
  252. package/dist/components/SuperChat/index.js.map +1 -1
  253. package/dist/components/SuperChat/plugins/index.cjs +2 -22
  254. package/dist/components/SuperChat/plugins/index.cjs.map +1 -1
  255. package/dist/components/SuperChat/plugins/index.js +1 -21
  256. package/dist/components/SuperChat/plugins/index.js.map +1 -1
  257. package/dist/components/Text/index.d.cts +1 -1
  258. package/dist/components/Text/index.d.ts +1 -1
  259. package/dist/components/Textarea/index.cjs +5 -3
  260. package/dist/components/Textarea/index.d.cts +19 -1
  261. package/dist/components/Textarea/index.d.ts +19 -1
  262. package/dist/components/Textarea/index.js +3 -1
  263. package/dist/datavis.cjs +1 -1
  264. package/dist/datavis.js +1 -1
  265. package/dist/esheet.cjs +11 -10
  266. package/dist/esheet.cjs.map +1 -1
  267. package/dist/esheet.js +8 -7
  268. package/dist/esheet.js.map +1 -1
  269. package/dist/hooks/index.cjs +27 -17
  270. package/dist/hooks/index.d.cts +16 -1
  271. package/dist/hooks/index.d.ts +16 -1
  272. package/dist/hooks/index.js +3 -1
  273. package/dist/index.cjs +1026 -651
  274. package/dist/index.cjs.map +1 -1
  275. package/dist/index.d.cts +83 -10
  276. package/dist/index.d.ts +83 -10
  277. package/dist/index.js +316 -53
  278. package/dist/index.js.map +1 -1
  279. package/dist/kerebron.cjs +200 -68
  280. package/dist/kerebron.cjs.map +1 -1
  281. package/dist/kerebron.css +129 -0
  282. package/dist/kerebron.d.cts +52 -3
  283. package/dist/kerebron.d.ts +52 -3
  284. package/dist/kerebron.js +201 -69
  285. package/dist/kerebron.js.map +1 -1
  286. package/dist/styles.css +1 -1
  287. package/dist/tailwind-preset.cjs +4 -4
  288. package/dist/tailwind-preset.js +1 -1
  289. package/dist/utils/index.cjs +9 -9
  290. package/dist/utils/index.js +1 -1
  291. package/package.json +9 -4
  292. package/dist/chunk-3YDTZUI6.cjs.map +0 -1
  293. package/dist/chunk-5FAWCLPY.js.map +0 -1
  294. package/dist/chunk-5IDYOJHO.cjs.map +0 -1
  295. package/dist/chunk-6ECKH4DJ.cjs +0 -147
  296. package/dist/chunk-6ECKH4DJ.cjs.map +0 -1
  297. package/dist/chunk-6J7UGYT5.cjs.map +0 -1
  298. package/dist/chunk-AFGADE3B.js.map +0 -1
  299. package/dist/chunk-CVZYOMEW.js.map +0 -1
  300. package/dist/chunk-DLBV42JD.js.map +0 -1
  301. package/dist/chunk-GTHNWP4P.js.map +0 -1
  302. package/dist/chunk-KFLDXJEE.js.map +0 -1
  303. package/dist/chunk-MJFF4AXH.cjs.map +0 -1
  304. package/dist/chunk-P6L74SKG.js.map +0 -1
  305. package/dist/chunk-QUUBTNMH.js.map +0 -1
  306. package/dist/chunk-S3MKIDYG.cjs.map +0 -1
  307. package/dist/chunk-WUNWHOLA.cjs.map +0 -1
  308. package/dist/chunk-XB54G7WS.cjs.map +0 -1
  309. package/dist/chunk-YXCE2HSK.js +0 -124
  310. package/dist/chunk-YXCE2HSK.js.map +0 -1
  311. package/dist/chunk-ZBI52NP2.cjs.map +0 -1
  312. package/dist/collabKit-QZL4P5T5.js.map +0 -1
  313. package/dist/collabKit-UF7E6V3N.cjs.map +0 -1
@@ -0,0 +1,56 @@
1
+ import { cn } from './chunk-TQONQSJO.js';
2
+ import * as React from 'react';
3
+ import { jsx } from 'react/jsx-runtime';
4
+
5
+ var ReadingProgressBar = React.forwardRef(function ReadingProgressBar2({ className, barClassName, ...props }, ref) {
6
+ const [pct, setPct] = React.useState(0);
7
+ React.useEffect(() => {
8
+ let rafId = 0;
9
+ const update = () => {
10
+ const el = document.documentElement;
11
+ const max = el.scrollHeight - el.clientHeight;
12
+ setPct(
13
+ max > 0 ? Math.min(100, Math.max(0, el.scrollTop / max * 100)) : 0
14
+ );
15
+ };
16
+ const schedule = () => {
17
+ cancelAnimationFrame(rafId);
18
+ rafId = requestAnimationFrame(update);
19
+ };
20
+ update();
21
+ window.addEventListener("scroll", schedule, { passive: true });
22
+ window.addEventListener("resize", schedule);
23
+ return () => {
24
+ cancelAnimationFrame(rafId);
25
+ window.removeEventListener("scroll", schedule);
26
+ window.removeEventListener("resize", schedule);
27
+ };
28
+ }, []);
29
+ return /* @__PURE__ */ jsx(
30
+ "div",
31
+ {
32
+ ref,
33
+ ...props,
34
+ "aria-hidden": "true",
35
+ className: cn(
36
+ "pointer-events-none fixed inset-x-0 top-0 z-50 h-1 bg-transparent",
37
+ className
38
+ ),
39
+ children: /* @__PURE__ */ jsx(
40
+ "div",
41
+ {
42
+ "data-slot": "reading-progress-fill",
43
+ className: cn(
44
+ "h-full transition-[width] duration-150",
45
+ barClassName ?? "bg-primary-500"
46
+ ),
47
+ style: { width: `${pct}%` }
48
+ }
49
+ )
50
+ }
51
+ );
52
+ });
53
+
54
+ export { ReadingProgressBar };
55
+ //# sourceMappingURL=chunk-WKSUL2ZN.js.map
56
+ //# sourceMappingURL=chunk-WKSUL2ZN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/ReadingProgressBar/ReadingProgressBar.tsx"],"names":["ReadingProgressBar"],"mappings":";;;;AAwBO,IAAM,kBAAA,GAA2B,KAAA,CAAA,UAAA,CAGtC,SAASA,mBAAAA,CAAmB,EAAE,WAAW,YAAA,EAAc,GAAG,KAAA,EAAM,EAAG,GAAA,EAAK;AACxE,EAAA,MAAM,CAAC,GAAA,EAAK,MAAM,CAAA,GAAU,eAAS,CAAC,CAAA;AAEtC,EAAM,gBAAU,MAAM;AACpB,IAAA,IAAI,KAAA,GAAQ,CAAA;AAEZ,IAAA,MAAM,SAAS,MAAM;AACnB,MAAA,MAAM,KAAK,QAAA,CAAS,eAAA;AACpB,MAAA,MAAM,GAAA,GAAM,EAAA,CAAG,YAAA,GAAe,EAAA,CAAG,YAAA;AACjC,MAAA,MAAA;AAAA,QACE,GAAA,GAAM,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,GAAA,EAAK,IAAA,CAAK,GAAA,CAAI,CAAA,EAAI,EAAA,CAAG,SAAA,GAAY,GAAA,GAAO,GAAG,CAAC,CAAA,GAAI;AAAA,OACrE;AAAA,IACF,CAAA;AAGA,IAAA,MAAM,WAAW,MAAM;AACrB,MAAA,oBAAA,CAAqB,KAAK,CAAA;AAC1B,MAAA,KAAA,GAAQ,sBAAsB,MAAM,CAAA;AAAA,IACtC,CAAA;AAEA,IAAA,MAAA,EAAO;AACP,IAAA,MAAA,CAAO,iBAAiB,QAAA,EAAU,QAAA,EAAU,EAAE,OAAA,EAAS,MAAM,CAAA;AAC7D,IAAA,MAAA,CAAO,gBAAA,CAAiB,UAAU,QAAQ,CAAA;AAC1C,IAAA,OAAO,MAAM;AACX,MAAA,oBAAA,CAAqB,KAAK,CAAA;AAC1B,MAAA,MAAA,CAAO,mBAAA,CAAoB,UAAU,QAAQ,CAAA;AAC7C,MAAA,MAAA,CAAO,mBAAA,CAAoB,UAAU,QAAQ,CAAA;AAAA,IAC/C,CAAA;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,uBACE,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,GAAA;AAAA,MACC,GAAG,KAAA;AAAA,MACJ,aAAA,EAAY,MAAA;AAAA,MACZ,SAAA,EAAW,EAAA;AAAA,QACT,mEAAA;AAAA,QACA;AAAA,OACF;AAAA,MAEA,QAAA,kBAAA,GAAA;AAAA,QAAC,KAAA;AAAA,QAAA;AAAA,UACC,WAAA,EAAU,uBAAA;AAAA,UACV,SAAA,EAAW,EAAA;AAAA,YACT,wCAAA;AAAA,YACA,YAAA,IAAgB;AAAA,WAClB;AAAA,UACA,KAAA,EAAO,EAAE,KAAA,EAAO,CAAA,EAAG,GAAG,CAAA,CAAA,CAAA;AAAI;AAAA;AAC5B;AAAA,GACF;AAEJ,CAAC","file":"chunk-WKSUL2ZN.js","sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { cn } from '../../utils/cn';\n\nexport interface ReadingProgressBarProps extends Omit<\n React.HTMLAttributes<HTMLDivElement>,\n 'children'\n> {\n /** Class for the filled bar (default `bg-primary-500`). */\n barClassName?: string;\n}\n\n/**\n * A thin progress bar pinned to the top of the viewport, tracking how far\n * the reader has scrolled through the document. Purely decorative\n * (`aria-hidden`) — long-form articles, guides, reports.\n *\n * @example\n * ```tsx\n * <ReadingProgressBar />\n * <ReadingProgressBar barClassName=\"bg-warning\" className=\"h-0.5\" />\n * ```\n */\nexport const ReadingProgressBar = React.forwardRef<\n HTMLDivElement,\n ReadingProgressBarProps\n>(function ReadingProgressBar({ className, barClassName, ...props }, ref) {\n const [pct, setPct] = React.useState(0);\n\n React.useEffect(() => {\n let rafId = 0;\n\n const update = () => {\n const el = document.documentElement;\n const max = el.scrollHeight - el.clientHeight;\n setPct(\n max > 0 ? Math.min(100, Math.max(0, (el.scrollTop / max) * 100)) : 0\n );\n };\n\n // Coalesce bursty scroll events to one state update per frame\n const schedule = () => {\n cancelAnimationFrame(rafId);\n rafId = requestAnimationFrame(update);\n };\n\n update();\n window.addEventListener('scroll', schedule, { passive: true });\n window.addEventListener('resize', schedule);\n return () => {\n cancelAnimationFrame(rafId);\n window.removeEventListener('scroll', schedule);\n window.removeEventListener('resize', schedule);\n };\n }, []);\n\n return (\n <div\n ref={ref}\n {...props}\n aria-hidden=\"true\"\n className={cn(\n 'pointer-events-none fixed inset-x-0 top-0 z-50 h-1 bg-transparent',\n className\n )}\n >\n <div\n data-slot=\"reading-progress-fill\"\n className={cn(\n 'h-full transition-[width] duration-150',\n barClassName ?? 'bg-primary-500'\n )}\n style={{ width: `${pct}%` }}\n />\n </div>\n );\n});\n"]}
@@ -0,0 +1,105 @@
1
+ import { Modal, ModalHeader, ModalTitle, ModalClose, ModalBody, ModalFooter } from './chunk-XMCIXHGH.js';
2
+ import { cn } from './chunk-TQONQSJO.js';
3
+ import * as React from 'react';
4
+ import { Keyboard } from 'lucide-react';
5
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
6
+
7
+ var Kbd = React.forwardRef(function Kbd2({ className, ...props }, ref) {
8
+ return /* @__PURE__ */ jsx(
9
+ "kbd",
10
+ {
11
+ ref,
12
+ className: cn(
13
+ "border-border bg-muted text-foreground rounded border px-1.5 py-0.5 font-mono text-[11px]",
14
+ className
15
+ ),
16
+ ...props
17
+ }
18
+ );
19
+ });
20
+ function Keys({
21
+ keys,
22
+ alternativesLabel
23
+ }) {
24
+ const list = Array.isArray(keys) ? keys : keys.split(" / ");
25
+ return /* @__PURE__ */ jsx("span", { className: "flex shrink-0 items-center gap-1", children: list.map((k, i) => /* @__PURE__ */ jsxs(React.Fragment, { children: [
26
+ /* @__PURE__ */ jsx(Kbd, { children: k }),
27
+ i < list.length - 1 && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground mx-0.5 text-xs", children: alternativesLabel })
28
+ ] }, `${k}-${i}`)) });
29
+ }
30
+ function ShortcutList({
31
+ shortcuts,
32
+ alternativesLabel
33
+ }) {
34
+ return /* @__PURE__ */ jsx("ul", { className: "flex list-none flex-col gap-2 p-0", children: shortcuts.map((s) => /* @__PURE__ */ jsxs(
35
+ "li",
36
+ {
37
+ className: "text-foreground flex items-center justify-between gap-4 text-sm",
38
+ children: [
39
+ /* @__PURE__ */ jsx("span", { className: "min-w-0", children: s.description }),
40
+ /* @__PURE__ */ jsx(Keys, { keys: s.keys, alternativesLabel })
41
+ ]
42
+ },
43
+ `${s.description}-${String(s.keys)}`
44
+ )) });
45
+ }
46
+ function KeyboardShortcutsOverlay({
47
+ open,
48
+ onClose,
49
+ shortcuts,
50
+ groups,
51
+ title = "Keyboard shortcuts",
52
+ hint,
53
+ alternativesLabel = "or"
54
+ }) {
55
+ const defaultHint = /* @__PURE__ */ jsxs(Fragment, { children: [
56
+ "Press ",
57
+ /* @__PURE__ */ jsx(Kbd, { children: "?" }),
58
+ " anytime to toggle this help"
59
+ ] });
60
+ const footer = hint === null ? null : hint ?? defaultHint;
61
+ return /* @__PURE__ */ jsxs(
62
+ Modal,
63
+ {
64
+ open,
65
+ onOpenChange: (o) => {
66
+ if (!o) onClose();
67
+ },
68
+ size: "sm",
69
+ "aria-label": title,
70
+ children: [
71
+ /* @__PURE__ */ jsxs(ModalHeader, { children: [
72
+ /* @__PURE__ */ jsxs(ModalTitle, { className: "flex items-center gap-2 text-sm", children: [
73
+ /* @__PURE__ */ jsx(Keyboard, { "aria-hidden": "true", className: "text-primary-500 h-4 w-4" }),
74
+ title
75
+ ] }),
76
+ /* @__PURE__ */ jsx(ModalClose, {})
77
+ ] }),
78
+ /* @__PURE__ */ jsxs(ModalBody, { className: "flex flex-col gap-4", children: [
79
+ shortcuts && /* @__PURE__ */ jsx(
80
+ ShortcutList,
81
+ {
82
+ shortcuts,
83
+ alternativesLabel
84
+ }
85
+ ),
86
+ groups?.map((group) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
87
+ /* @__PURE__ */ jsx("h3", { className: "text-muted-foreground text-xs font-semibold tracking-wide uppercase", children: group.title }),
88
+ /* @__PURE__ */ jsx(
89
+ ShortcutList,
90
+ {
91
+ shortcuts: group.shortcuts,
92
+ alternativesLabel
93
+ }
94
+ )
95
+ ] }, group.title))
96
+ ] }),
97
+ footer && /* @__PURE__ */ jsx(ModalFooter, { className: "text-muted-foreground justify-center text-[11px]", children: /* @__PURE__ */ jsx("span", { children: footer }) })
98
+ ]
99
+ }
100
+ );
101
+ }
102
+
103
+ export { Kbd, KeyboardShortcutsOverlay };
104
+ //# sourceMappingURL=chunk-X5ZPYYMS.js.map
105
+ //# sourceMappingURL=chunk-X5ZPYYMS.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/KeyboardShortcutsOverlay/KeyboardShortcutsOverlay.tsx"],"names":["Kbd","Fragment"],"mappings":"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","file":"chunk-X5ZPYYMS.js","sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { Keyboard } from 'lucide-react';\nimport { cn } from '../../utils/cn';\nimport {\n Modal,\n ModalHeader,\n ModalTitle,\n ModalClose,\n ModalBody,\n ModalFooter,\n} from '../Modal';\n\n// =============================================================================\n// Kbd\n// =============================================================================\n\nexport type KbdProps = React.HTMLAttributes<HTMLElement>;\n\n/** A keyboard-key chip: `<Kbd>⌘K</Kbd>`. */\nexport const Kbd = React.forwardRef<HTMLElement, KbdProps>(function Kbd(\n { className, ...props },\n ref\n) {\n return (\n <kbd\n ref={ref}\n className={cn(\n 'border-border bg-muted text-foreground rounded border px-1.5 py-0.5 font-mono text-[11px]',\n className\n )}\n {...props}\n />\n );\n});\n\n// =============================================================================\n// KeyboardShortcutsOverlay\n// =============================================================================\n\nexport interface ShortcutDef {\n /** Key or alternatives — `\"j\"`, `[\"j\", \"↓\"]`, `\"⌘K\"`. */\n keys: string | string[];\n description: string;\n}\n\nexport interface ShortcutGroup {\n title: string;\n shortcuts: ShortcutDef[];\n}\n\nexport interface KeyboardShortcutsOverlayProps {\n open: boolean;\n onClose: () => void;\n /** Flat list of shortcuts, or use `groups` for sectioned help. */\n shortcuts?: ShortcutDef[];\n /** Sectioned shortcuts with group headings. */\n groups?: ShortcutGroup[];\n title?: string;\n /** Footer hint. Pass `null` to hide it. */\n hint?: React.ReactNode | null;\n /** Joins key alternatives (default \"or\"), overridable for i18n. */\n alternativesLabel?: string;\n}\n\nfunction Keys({\n keys,\n alternativesLabel,\n}: {\n keys: string | string[];\n alternativesLabel: string;\n}) {\n const list = Array.isArray(keys) ? keys : keys.split(' / ');\n return (\n <span className=\"flex shrink-0 items-center gap-1\">\n {list.map((k, i) => (\n <React.Fragment key={`${k}-${i}`}>\n <Kbd>{k}</Kbd>\n {i < list.length - 1 && (\n <span className=\"text-muted-foreground mx-0.5 text-xs\">\n {alternativesLabel}\n </span>\n )}\n </React.Fragment>\n ))}\n </span>\n );\n}\n\nfunction ShortcutList({\n shortcuts,\n alternativesLabel,\n}: {\n shortcuts: ShortcutDef[];\n alternativesLabel: string;\n}) {\n return (\n <ul className=\"flex list-none flex-col gap-2 p-0\">\n {shortcuts.map((s) => (\n <li\n key={`${s.description}-${String(s.keys)}`}\n className=\"text-foreground flex items-center justify-between gap-4 text-sm\"\n >\n <span className=\"min-w-0\">{s.description}</span>\n <Keys keys={s.keys} alternativesLabel={alternativesLabel} />\n </li>\n ))}\n </ul>\n );\n}\n\n/**\n * The `?` keyboard-shortcuts help dialog: a list of shortcut rows\n * (optionally grouped) with `Kbd` chips for each key. Pairs with the\n * `useKeyboardShortcut` hook, which handles the binding — this component\n * only renders the help.\n *\n * @example\n * ```tsx\n * const [open, setOpen] = useState(false);\n * useKeyboardShortcut('?', () => setOpen((v) => !v), {\n * modifiers: { shift: true },\n * });\n *\n * <KeyboardShortcutsOverlay\n * open={open}\n * onClose={() => setOpen(false)}\n * shortcuts={[\n * { keys: ['j', '↓'], description: 'Next record' },\n * { keys: '⌘K', description: 'Command palette' },\n * ]}\n * />\n * ```\n */\nexport function KeyboardShortcutsOverlay({\n open,\n onClose,\n shortcuts,\n groups,\n title = 'Keyboard shortcuts',\n hint,\n alternativesLabel = 'or',\n}: KeyboardShortcutsOverlayProps) {\n const defaultHint = (\n <>\n Press <Kbd>?</Kbd> anytime to toggle this help\n </>\n );\n const footer = hint === null ? null : (hint ?? defaultHint);\n\n return (\n <Modal\n open={open}\n onOpenChange={(o) => {\n if (!o) onClose();\n }}\n size=\"sm\"\n aria-label={title}\n >\n <ModalHeader>\n <ModalTitle className=\"flex items-center gap-2 text-sm\">\n <Keyboard aria-hidden=\"true\" className=\"text-primary-500 h-4 w-4\" />\n {title}\n </ModalTitle>\n <ModalClose />\n </ModalHeader>\n <ModalBody className=\"flex flex-col gap-4\">\n {shortcuts && (\n <ShortcutList\n shortcuts={shortcuts}\n alternativesLabel={alternativesLabel}\n />\n )}\n {groups?.map((group) => (\n <div key={group.title} className=\"flex flex-col gap-2\">\n <h3 className=\"text-muted-foreground text-xs font-semibold tracking-wide uppercase\">\n {group.title}\n </h3>\n <ShortcutList\n shortcuts={group.shortcuts}\n alternativesLabel={alternativesLabel}\n />\n </div>\n ))}\n </ModalBody>\n {footer && (\n <ModalFooter className=\"text-muted-foreground justify-center text-[11px]\">\n <span>{footer}</span>\n </ModalFooter>\n )}\n </Modal>\n );\n}\n"]}
@@ -1,3 +1,4 @@
1
+ import { RequiredMark } from './chunk-3IMM2PM4.js';
1
2
  import { useEscapeKey } from './chunk-T4ME7QCT.js';
2
3
  import { useClickOutside } from './chunk-62ZOA6PX.js';
3
4
  import { useAnchoredPosition } from './chunk-BOOJDRJO.js';
@@ -26,37 +27,97 @@ var selectTriggerVariants = cva(
26
27
  hasError: {
27
28
  true: "border-destructive focus:ring-destructive",
28
29
  false: ""
30
+ },
31
+ labelVariant: {
32
+ stacked: "",
33
+ floating: "peer"
34
+ }
35
+ },
36
+ compoundVariants: [
37
+ { labelVariant: "floating", size: "sm", className: "h-11" },
38
+ { labelVariant: "floating", size: "md", className: "h-14" },
39
+ { labelVariant: "floating", size: "lg", className: "h-16" }
40
+ ],
41
+ defaultVariants: {
42
+ size: "md",
43
+ hasError: false,
44
+ labelVariant: "stacked"
45
+ }
46
+ }
47
+ );
48
+ var floatingLabelVariants = cva(
49
+ [
50
+ "absolute start-3 pointer-events-none select-none",
51
+ "transition-all duration-200 ease-out"
52
+ ],
53
+ {
54
+ variants: {
55
+ size: {
56
+ sm: [
57
+ "peer-focus:top-0.5 peer-focus:translate-y-0 peer-focus:text-[0.65rem]"
58
+ ],
59
+ md: ["peer-focus:top-1 peer-focus:translate-y-0 peer-focus:text-xs"],
60
+ lg: ["peer-focus:top-1.5 peer-focus:translate-y-0 peer-focus:text-sm"]
61
+ },
62
+ floated: {
63
+ true: "",
64
+ false: "top-1/2 -translate-y-1/2"
65
+ },
66
+ hasError: {
67
+ true: "text-destructive",
68
+ false: "text-muted-foreground"
29
69
  }
30
70
  },
71
+ compoundVariants: [
72
+ { size: "sm", floated: false, className: "text-sm" },
73
+ { size: "md", floated: false, className: "text-base" },
74
+ { size: "lg", floated: false, className: "text-lg" },
75
+ {
76
+ size: "sm",
77
+ floated: true,
78
+ className: "top-0.5 translate-y-0 text-[0.65rem]"
79
+ },
80
+ { size: "md", floated: true, className: "top-1 translate-y-0 text-xs" },
81
+ { size: "lg", floated: true, className: "top-1.5 translate-y-0 text-sm" }
82
+ ],
31
83
  defaultVariants: {
32
84
  size: "md",
85
+ floated: false,
33
86
  hasError: false
34
87
  }
35
88
  }
36
89
  );
37
- function Select({
38
- options,
39
- value: controlledValue,
40
- defaultValue,
41
- onValueChange,
42
- placeholder = "Select an option",
43
- disabled = false,
44
- label,
45
- hideLabel = false,
46
- error,
47
- helperText,
48
- size,
49
- hasError,
50
- "aria-label": ariaLabel,
51
- searchable = false,
52
- searchPlaceholder = "Search...",
53
- noResultsText = "No results found",
54
- className,
55
- id
56
- }) {
90
+ var floatingValuePadding = {
91
+ sm: "pt-4 pb-1",
92
+ md: "pt-5 pb-1.5",
93
+ lg: "pt-6 pb-2"
94
+ };
95
+ function Select(props) {
96
+ const {
97
+ options,
98
+ placeholder = "Select an option",
99
+ disabled = false,
100
+ label,
101
+ hideLabel = false,
102
+ labelVariant = "stacked",
103
+ error,
104
+ helperText,
105
+ required = false,
106
+ requiredVariant,
107
+ size,
108
+ hasError,
109
+ "aria-label": ariaLabel,
110
+ searchable = false,
111
+ searchPlaceholder = "Search...",
112
+ noResultsText = "No results found",
113
+ className,
114
+ id
115
+ } = props;
116
+ const multiple = props.multiple === true;
117
+ const onValueChange = props.onValueChange;
57
118
  const [isOpen, setIsOpen] = React.useState(false);
58
- const [uncontrolledValue, setUncontrolledValue] = React.useState(
59
- defaultValue || ""
119
+ const [uncontrolledValues, setUncontrolledValues] = React.useState(
120
+ () => toValueArray(props.defaultValue)
60
121
  );
61
122
  const [searchQuery, setSearchQuery] = React.useState("");
62
123
  const [highlightedIndex, setHighlightedIndex] = React.useState(-1);
@@ -74,8 +135,13 @@ function Select({
74
135
  const listboxId = `${selectId}-listbox`;
75
136
  const errorId = `${selectId}-error`;
76
137
  const helperId = `${selectId}-helper`;
77
- const isControlled = controlledValue !== void 0;
78
- const value = isControlled ? controlledValue : uncontrolledValue;
138
+ const isControlled = props.value !== void 0;
139
+ const controlledValue = props.value;
140
+ const controlledValues = React.useMemo(
141
+ () => toValueArray(controlledValue),
142
+ [controlledValue]
143
+ );
144
+ const selectedValues = isControlled ? controlledValues : uncontrolledValues;
79
145
  const flatOptions = React.useMemo(() => {
80
146
  const result = [];
81
147
  for (const item of options) {
@@ -118,7 +184,9 @@ function Select({
118
184
  }
119
185
  return result;
120
186
  }, [filteredOptions]);
121
- const selectedOption = flatOptions.find((opt) => opt.value === value);
187
+ const selectedOptions = selectedValues.map((v) => flatOptions.find((opt) => opt.value === v)).filter((opt) => opt !== void 0);
188
+ const hasSelection = selectedOptions.length > 0;
189
+ const displayLabel = selectedOptions.map((opt) => opt.label).join(", ");
122
190
  const outsideRefs = React.useMemo(() => [containerRef, dropdownRef], []);
123
191
  useClickOutside(outsideRefs, () => setIsOpen(false), isOpen);
124
192
  useEscapeKey(() => {
@@ -137,16 +205,29 @@ function Select({
137
205
  maxHeight: 300
138
206
  });
139
207
  const handleValueChange = React.useCallback(
140
- (newValue) => {
208
+ (optionValue) => {
209
+ if (multiple) {
210
+ const next = selectedValues.includes(optionValue) ? selectedValues.filter((v) => v !== optionValue) : [...selectedValues, optionValue];
211
+ if (!isControlled) {
212
+ setUncontrolledValues(next);
213
+ }
214
+ onValueChange?.(next);
215
+ if (searchable) {
216
+ searchInputRef.current?.focus();
217
+ } else {
218
+ triggerRef.current?.focus();
219
+ }
220
+ return;
221
+ }
141
222
  if (!isControlled) {
142
- setUncontrolledValue(newValue);
223
+ setUncontrolledValues([optionValue]);
143
224
  }
144
- onValueChange?.(newValue);
225
+ onValueChange?.(optionValue);
145
226
  setIsOpen(false);
146
227
  setSearchQuery("");
147
228
  triggerRef.current?.focus();
148
229
  },
149
- [isControlled, onValueChange]
230
+ [isControlled, multiple, onValueChange, searchable, selectedValues]
150
231
  );
151
232
  const handleKeyDown = React.useCallback(
152
233
  (e) => {
@@ -267,13 +348,17 @@ function Select({
267
348
  error ? errorId : null,
268
349
  helperText && !error ? helperId : null
269
350
  ].filter(Boolean).join(" ");
351
+ const isFloating = labelVariant === "floating" && !!label && !hideLabel;
352
+ const isFloated = isOpen || hasSelection;
353
+ const resolvedSize = size ?? "md";
354
+ const requiredMark = required && /* @__PURE__ */ jsx(RequiredMark, { variant: requiredVariant });
270
355
  return /* @__PURE__ */ jsxs(
271
356
  "div",
272
357
  {
273
358
  "data-slot": "select-wrapper",
274
359
  className: cn("flex flex-col gap-1.5", className),
275
360
  children: [
276
- label && /* @__PURE__ */ jsx(
361
+ label && !isFloating && /* @__PURE__ */ jsxs(
277
362
  "label",
278
363
  {
279
364
  "data-slot": "select-label",
@@ -282,7 +367,10 @@ function Select({
282
367
  "text-foreground text-sm font-medium",
283
368
  hideLabel && "sr-only"
284
369
  ),
285
- children: label
370
+ children: [
371
+ label,
372
+ requiredMark
373
+ ]
286
374
  }
287
375
  ),
288
376
  /* @__PURE__ */ jsxs("div", { ref: containerRef, className: "relative", children: [
@@ -299,15 +387,20 @@ function Select({
299
387
  role: "combobox",
300
388
  "aria-haspopup": "listbox",
301
389
  "aria-expanded": isOpen,
302
- "aria-controls": listboxId,
390
+ "aria-controls": isOpen ? listboxId : void 0,
303
391
  "aria-invalid": hasError || !!error,
392
+ "aria-required": required || void 0,
304
393
  "aria-label": !label ? ariaLabel : void 0,
305
394
  "aria-describedby": describedByIds || void 0,
306
395
  disabled,
307
396
  onClick: () => setIsOpen(!isOpen),
308
397
  onKeyDown: handleKeyDown,
309
398
  className: cn(
310
- selectTriggerVariants({ size, hasError: hasError || !!error })
399
+ selectTriggerVariants({
400
+ size,
401
+ hasError: hasError || !!error,
402
+ labelVariant: isFloating ? "floating" : "stacked"
403
+ })
311
404
  ),
312
405
  children: [
313
406
  /* @__PURE__ */ jsx(
@@ -315,9 +408,10 @@ function Select({
315
408
  {
316
409
  className: cn(
317
410
  "truncate",
318
- !selectedOption && "text-muted-foreground"
411
+ !hasSelection && "text-muted-foreground",
412
+ isFloating && floatingValuePadding[resolvedSize]
319
413
  ),
320
- children: selectedOption?.label || placeholder
414
+ children: isFloating ? hasSelection ? displayLabel : "\xA0" : hasSelection ? displayLabel : placeholder
321
415
  }
322
416
  ),
323
417
  /* @__PURE__ */ jsx(
@@ -332,6 +426,22 @@ function Select({
332
426
  ]
333
427
  }
334
428
  ),
429
+ isFloating && /* @__PURE__ */ jsxs(
430
+ "label",
431
+ {
432
+ "data-slot": "select-label",
433
+ htmlFor: selectId,
434
+ className: floatingLabelVariants({
435
+ size: resolvedSize,
436
+ floated: isFloated,
437
+ hasError: hasError || !!error
438
+ }),
439
+ children: [
440
+ label,
441
+ requiredMark
442
+ ]
443
+ }
444
+ ),
335
445
  isOpen && createPortal(
336
446
  /* @__PURE__ */ jsxs(
337
447
  "div",
@@ -379,6 +489,7 @@ function Select({
379
489
  id: listboxId,
380
490
  role: "listbox",
381
491
  "aria-label": label || "Options",
492
+ "aria-multiselectable": multiple || void 0,
382
493
  "data-slot": "select-listbox",
383
494
  className: "flex-1 overflow-auto p-1",
384
495
  children: filteredFlatOptions.length === 0 ? /* @__PURE__ */ jsx("li", { className: "text-muted-foreground px-3 py-2 text-center text-sm", children: noResultsText }) : filteredOptions.map((item) => {
@@ -396,7 +507,9 @@ function Select({
396
507
  SelectOptionItem,
397
508
  {
398
509
  option,
399
- isSelected: option.value === value,
510
+ isSelected: selectedValues.includes(
511
+ option.value
512
+ ),
400
513
  isHighlighted: filteredFlatOptions[highlightedIndex]?.value === option.value,
401
514
  onSelect: () => handleValueChange(option.value),
402
515
  onMouseEnter: () => {
@@ -414,7 +527,7 @@ function Select({
414
527
  SelectOptionItem,
415
528
  {
416
529
  option: item,
417
- isSelected: item.value === value,
530
+ isSelected: selectedValues.includes(item.value),
418
531
  isHighlighted: filteredFlatOptions[highlightedIndex]?.value === item.value,
419
532
  onSelect: () => handleValueChange(item.value),
420
533
  onMouseEnter: () => {
@@ -459,6 +572,10 @@ function Select({
459
572
  );
460
573
  }
461
574
  Select.displayName = "Select";
575
+ function toValueArray(value) {
576
+ if (value === void 0 || value === "") return [];
577
+ return Array.isArray(value) ? value : [value];
578
+ }
462
579
  function SelectOptionItem({
463
580
  option,
464
581
  isSelected,
@@ -541,5 +658,5 @@ function CheckIcon({ className }) {
541
658
  }
542
659
 
543
660
  export { Select, selectTriggerVariants };
544
- //# sourceMappingURL=chunk-DLBV42JD.js.map
545
- //# sourceMappingURL=chunk-DLBV42JD.js.map
661
+ //# sourceMappingURL=chunk-XBKOZRDO.js.map
662
+ //# sourceMappingURL=chunk-XBKOZRDO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/Select/Select.tsx"],"names":[],"mappings":"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","file":"chunk-XBKOZRDO.js","sourcesContent":["import * as React from 'react';\nimport { createPortal } from 'react-dom';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { cn } from '../../utils/cn';\nimport { useEscapeKey } from '../../hooks/useEscapeKey';\nimport { useClickOutside } from '../../hooks/useClickOutside';\nimport { useAnchoredPosition } from '../../hooks/useAnchoredPosition';\nimport { RequiredMark, type RequiredMarkVariant } from '../Input';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface SelectOption {\n /** Unique value for the option */\n value: string;\n /** Display label for the option */\n label: string;\n /** Whether the option is disabled */\n disabled?: boolean;\n /** Optional group this option belongs to */\n group?: string;\n}\n\nexport interface SelectGroup {\n /** Group label */\n label: string;\n /** Options in this group */\n options: SelectOption[];\n}\n\n// ============================================================================\n// Variants\n// ============================================================================\n\nconst selectTriggerVariants = cva(\n [\n 'flex w-full items-center justify-between gap-2',\n 'border border-input rounded-lg',\n 'bg-background text-foreground',\n 'transition-colors duration-200',\n 'focus:outline-none focus:ring-2 focus:ring-ring focus:border-transparent',\n 'disabled:cursor-not-allowed disabled:opacity-50',\n ],\n {\n variants: {\n size: {\n sm: 'h-8 px-3 text-sm',\n md: 'h-10 px-3 text-base',\n lg: 'h-12 px-4 text-lg',\n },\n hasError: {\n true: 'border-destructive focus:ring-destructive',\n false: '',\n },\n labelVariant: {\n stacked: '',\n floating: 'peer',\n },\n },\n compoundVariants: [\n { labelVariant: 'floating', size: 'sm', className: 'h-11' },\n { labelVariant: 'floating', size: 'md', className: 'h-14' },\n { labelVariant: 'floating', size: 'lg', className: 'h-16' },\n ],\n defaultVariants: {\n size: 'md',\n hasError: false,\n labelVariant: 'stacked',\n },\n }\n);\n\nconst floatingLabelVariants = cva(\n [\n 'absolute start-3 pointer-events-none select-none',\n 'transition-all duration-200 ease-out',\n ],\n {\n variants: {\n size: {\n sm: [\n 'peer-focus:top-0.5 peer-focus:translate-y-0 peer-focus:text-[0.65rem]',\n ],\n md: ['peer-focus:top-1 peer-focus:translate-y-0 peer-focus:text-xs'],\n lg: ['peer-focus:top-1.5 peer-focus:translate-y-0 peer-focus:text-sm'],\n },\n floated: {\n true: '',\n false: 'top-1/2 -translate-y-1/2',\n },\n hasError: {\n true: 'text-destructive',\n false: 'text-muted-foreground',\n },\n },\n compoundVariants: [\n { size: 'sm', floated: false, className: 'text-sm' },\n { size: 'md', floated: false, className: 'text-base' },\n { size: 'lg', floated: false, className: 'text-lg' },\n {\n size: 'sm',\n floated: true,\n className: 'top-0.5 translate-y-0 text-[0.65rem]',\n },\n { size: 'md', floated: true, className: 'top-1 translate-y-0 text-xs' },\n { size: 'lg', floated: true, className: 'top-1.5 translate-y-0 text-sm' },\n ],\n defaultVariants: {\n size: 'md',\n floated: false,\n hasError: false,\n },\n }\n);\n\nconst floatingValuePadding = {\n sm: 'pt-4 pb-1',\n md: 'pt-5 pb-1.5',\n lg: 'pt-6 pb-2',\n} as const;\n\n// ============================================================================\n// Select Component\n// ============================================================================\n\n/**\n * Props shared by both single- and multiple-selection modes. Exported so\n * wrapper components can extend the common shape (`SelectProps` itself is a\n * discriminated union, which interfaces cannot extend).\n */\nexport interface SelectBaseProps extends Omit<\n VariantProps<typeof selectTriggerVariants>,\n 'labelVariant'\n> {\n /** Array of options or groups */\n options: (SelectOption | SelectGroup)[];\n /** Placeholder text */\n placeholder?: string;\n /** Whether the select is disabled */\n disabled?: boolean;\n /** Label for the select */\n label?: string;\n /** Hide the label visually */\n hideLabel?: boolean;\n /**\n * Visual style of the label.\n * - `stacked` (default): label sits above the trigger.\n * - `floating`: label rests inside the trigger like a placeholder and\n * floats up (staying inside the trigger) when open or a value is\n * selected. The `placeholder` prop is ignored in this mode.\n */\n labelVariant?: 'stacked' | 'floating';\n /** Error message */\n error?: string;\n /** Helper text */\n helperText?: string;\n /** Whether a selection is required (shows an asterisk next to the label) */\n required?: boolean;\n /**\n * Color of the required asterisk.\n * - `default`: destructive (hard requirement).\n * - `warning`: warning color (soft requirement / recommended).\n */\n requiredVariant?: RequiredMarkVariant;\n /** Enable search/filter */\n searchable?: boolean;\n /** Search placeholder */\n searchPlaceholder?: string;\n /** No results text */\n noResultsText?: string;\n /** Accessible label for the trigger (used when no `label` prop is provided) */\n 'aria-label'?: string;\n /** Additional class name */\n className?: string;\n /** ID for the select */\n id?: string;\n}\n\nexport interface SelectSingleProps extends SelectBaseProps {\n /** Single-selection mode (default). */\n multiple?: false;\n /** Controlled value */\n value?: string;\n /** Default value (uncontrolled) */\n defaultValue?: string;\n /** Callback when value changes */\n onValueChange?: (value: string) => void;\n}\n\nexport interface SelectMultipleProps extends SelectBaseProps {\n /** Multiple-selection mode: selecting an option toggles it and keeps the dropdown open. */\n multiple: true;\n /** Controlled values */\n value?: string[];\n /** Default values (uncontrolled) */\n defaultValue?: string[];\n /** Callback when values change */\n onValueChange?: (value: string[]) => void;\n}\n\nexport type SelectProps = SelectSingleProps | SelectMultipleProps;\n\n/**\n * An accessible select/dropdown component with search support.\n *\n * @example\n * ```tsx\n * <Select\n * label=\"Country\"\n * placeholder=\"Select a country\"\n * options={[\n * { value: 'us', label: 'United States' },\n * { value: 'ca', label: 'Canada' },\n * { value: 'uk', label: 'United Kingdom' },\n * ]}\n * onValueChange={(value) => console.log(value)}\n * />\n *\n * // Multiple selection — value/onValueChange use string[]\n * <Select\n * multiple\n * label=\"Symptoms\"\n * options={options}\n * onValueChange={(values) => console.log(values)}\n * />\n * ```\n */\nfunction Select(props: SelectProps) {\n const {\n options,\n placeholder = 'Select an option',\n disabled = false,\n label,\n hideLabel = false,\n labelVariant = 'stacked',\n error,\n helperText,\n required = false,\n requiredVariant,\n size,\n hasError,\n 'aria-label': ariaLabel,\n searchable = false,\n searchPlaceholder = 'Search...',\n noResultsText = 'No results found',\n className,\n id,\n } = props;\n const multiple = props.multiple === true;\n // The discriminated union types onValueChange as either a string or string[]\n // callback; widen it once here so handlers can use it without referencing\n // the whole `props` object. Runtime calls stay consistent with `multiple`.\n const onValueChange = props.onValueChange as\n | ((value: string | string[]) => void)\n | undefined;\n const [isOpen, setIsOpen] = React.useState(false);\n const [uncontrolledValues, setUncontrolledValues] = React.useState<string[]>(\n () => toValueArray(props.defaultValue)\n );\n const [searchQuery, setSearchQuery] = React.useState('');\n const [highlightedIndex, setHighlightedIndex] = React.useState(-1);\n\n const containerRef = React.useRef<HTMLDivElement>(null);\n const triggerRef = React.useRef<HTMLButtonElement>(null);\n const searchInputRef = React.useRef<HTMLInputElement>(null);\n const listRef = React.useRef<HTMLUListElement>(null);\n const dropdownRef = React.useRef<HTMLDivElement>(null);\n const typeaheadRef = React.useRef<{ query: string; timer: number | null }>({\n query: '',\n timer: null,\n });\n\n const generatedId = React.useId();\n const selectId = id || generatedId;\n const listboxId = `${selectId}-listbox`;\n const errorId = `${selectId}-error`;\n const helperId = `${selectId}-helper`;\n\n const isControlled = props.value !== undefined;\n const controlledValue = props.value;\n // Memoize the controlled normalization: toValueArray allocates a fresh\n // array when value is a string, which would otherwise churn callback\n // identities (handleValueChange depends on selectedValues) every render.\n const controlledValues = React.useMemo(\n () => toValueArray(controlledValue),\n [controlledValue]\n );\n const selectedValues = isControlled ? controlledValues : uncontrolledValues;\n\n // Flatten options for easy access\n const flatOptions = React.useMemo(() => {\n const result: SelectOption[] = [];\n for (const item of options) {\n if ('options' in item) {\n result.push(...item.options);\n } else {\n result.push(item);\n }\n }\n return result;\n }, [options]);\n\n // Filter options based on search query\n const filteredOptions = React.useMemo(() => {\n if (!searchQuery) return options;\n\n const query = searchQuery.toLowerCase();\n const result: (SelectOption | SelectGroup)[] = [];\n\n for (const item of options) {\n if ('options' in item) {\n const filteredGroupOptions = item.options.filter((opt) =>\n opt.label.toLowerCase().includes(query)\n );\n if (filteredGroupOptions.length > 0) {\n result.push({ ...item, options: filteredGroupOptions });\n }\n } else {\n if (item.label.toLowerCase().includes(query)) {\n result.push(item);\n }\n }\n }\n\n return result;\n }, [options, searchQuery]);\n\n // Get filtered flat options for keyboard navigation\n const filteredFlatOptions = React.useMemo(() => {\n const result: SelectOption[] = [];\n for (const item of filteredOptions) {\n if ('options' in item) {\n result.push(...item.options.filter((opt) => !opt.disabled));\n } else if (!item.disabled) {\n result.push(item);\n }\n }\n return result;\n }, [filteredOptions]);\n\n // Get selected options (in selection order)\n const selectedOptions = selectedValues\n .map((v) => flatOptions.find((opt) => opt.value === v))\n .filter((opt): opt is SelectOption => opt !== undefined);\n const hasSelection = selectedOptions.length > 0;\n const displayLabel = selectedOptions.map((opt) => opt.label).join(', ');\n\n // Close dropdown on click outside (handles both container and portaled dropdown)\n const outsideRefs = React.useMemo(() => [containerRef, dropdownRef], []);\n useClickOutside(outsideRefs, () => setIsOpen(false), isOpen);\n\n useEscapeKey(() => {\n if (isOpen) {\n setIsOpen(false);\n triggerRef.current?.focus();\n }\n }, isOpen);\n\n // Track trigger position for portal dropdown\n const {\n anchorRef,\n floatingRef,\n style: dropdownStyle,\n } = useAnchoredPosition<HTMLButtonElement, HTMLDivElement>({\n open: isOpen,\n matchWidth: true,\n maxHeight: 300,\n });\n\n // Handle option selection: single mode replaces and closes; multiple mode\n // toggles the option and keeps the dropdown open.\n const handleValueChange = React.useCallback(\n (optionValue: string) => {\n if (multiple) {\n const next = selectedValues.includes(optionValue)\n ? selectedValues.filter((v) => v !== optionValue)\n : [...selectedValues, optionValue];\n if (!isControlled) {\n setUncontrolledValues(next);\n }\n onValueChange?.(next);\n // The dropdown stays open; a mouse click focuses the option <li>,\n // which only handles Enter/Space. Restore focus so arrow-key\n // navigation and typeahead keep working.\n if (searchable) {\n searchInputRef.current?.focus();\n } else {\n triggerRef.current?.focus();\n }\n return;\n }\n if (!isControlled) {\n setUncontrolledValues([optionValue]);\n }\n onValueChange?.(optionValue);\n setIsOpen(false);\n setSearchQuery('');\n triggerRef.current?.focus();\n },\n [isControlled, multiple, onValueChange, searchable, selectedValues]\n );\n\n // Handle keyboard navigation\n const handleKeyDown = React.useCallback(\n (e: React.KeyboardEvent) => {\n // Typeahead (native-select style): when not using the dedicated search\n // input, typing printable characters jumps to the first option whose\n // label starts with the typed string. Repeating the same key cycles\n // through matches. The buffer clears after a short pause.\n if (\n !searchable &&\n e.key.length === 1 &&\n e.key !== ' ' &&\n !e.metaKey &&\n !e.ctrlKey &&\n !e.altKey\n ) {\n e.preventDefault();\n if (!isOpen) setIsOpen(true);\n\n const hadPendingQuery = typeaheadRef.current.query !== '';\n if (typeaheadRef.current.timer !== null) {\n window.clearTimeout(typeaheadRef.current.timer);\n }\n const query = (typeaheadRef.current.query + e.key).toLowerCase();\n typeaheadRef.current.query = query;\n typeaheadRef.current.timer = window.setTimeout(() => {\n typeaheadRef.current.query = '';\n typeaheadRef.current.timer = null;\n }, 600);\n\n const len = filteredFlatOptions.length;\n if (len > 0) {\n const allSameChar = query.split('').every((c) => c === query[0]);\n const needle = allSameChar ? query[0] : query;\n const matches = (opt: SelectOption) =>\n opt.label.toLowerCase().startsWith(needle);\n\n // A fresh keystroke (or refining a multi-char query) searches from\n // the current option inclusive so typing \"car\" stays on \"Cardiology\";\n // repeating the same key cycles to the next match.\n const startInclusive = !hadPendingQuery || !allSameChar;\n const base = startInclusive\n ? Math.max(highlightedIndex, 0)\n : highlightedIndex + 1;\n\n for (let i = 0; i < len; i++) {\n const idx = (base + i) % len;\n if (matches(filteredFlatOptions[idx])) {\n setHighlightedIndex(idx);\n break;\n }\n }\n }\n return;\n }\n\n // Let Space type normally in the search input (e.g. \"new york\")\n // instead of being captured by the open/select handler below.\n if (e.key === ' ' && e.target === searchInputRef.current) {\n return;\n }\n\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault();\n if (!isOpen) {\n setIsOpen(true);\n } else {\n setHighlightedIndex((prev) =>\n prev < filteredFlatOptions.length - 1 ? prev + 1 : 0\n );\n }\n break;\n case 'ArrowUp':\n e.preventDefault();\n if (!isOpen) {\n setIsOpen(true);\n } else {\n setHighlightedIndex((prev) =>\n prev > 0 ? prev - 1 : filteredFlatOptions.length - 1\n );\n }\n break;\n case 'Enter':\n case ' ':\n e.preventDefault();\n if (isOpen && highlightedIndex >= 0) {\n handleValueChange(filteredFlatOptions[highlightedIndex].value);\n } else if (!isOpen) {\n setIsOpen(true);\n }\n break;\n case 'Home':\n e.preventDefault();\n setHighlightedIndex(0);\n break;\n case 'End':\n e.preventDefault();\n setHighlightedIndex(filteredFlatOptions.length - 1);\n break;\n }\n },\n [\n isOpen,\n highlightedIndex,\n filteredFlatOptions,\n handleValueChange,\n searchable,\n ]\n );\n\n // Focus search input when dropdown opens\n React.useEffect(() => {\n if (isOpen && searchable && searchInputRef.current) {\n searchInputRef.current.focus();\n }\n }, [isOpen, searchable]);\n\n // Reset highlighted index when search changes\n React.useEffect(() => {\n setHighlightedIndex(filteredFlatOptions.length > 0 ? 0 : -1);\n }, [searchQuery, filteredFlatOptions.length]);\n\n // Keep the highlighted option visible within the listbox during keyboard\n // navigation. We adjust only the list's own scrollTop instead of calling the\n // native scrollIntoView: the dropdown is portaled to <body> with\n // position: fixed, and scrollIntoView would also scroll ancestor/window,\n // yanking the whole page.\n React.useEffect(() => {\n if (!isOpen || highlightedIndex < 0) return;\n const list = listRef.current;\n const el = list?.querySelector<HTMLElement>('[data-highlighted=\"true\"]');\n if (!list || !el) return;\n const listRect = list.getBoundingClientRect();\n const elRect = el.getBoundingClientRect();\n if (elRect.top < listRect.top) {\n list.scrollTop -= listRect.top - elRect.top;\n } else if (elRect.bottom > listRect.bottom) {\n list.scrollTop += elRect.bottom - listRect.bottom;\n }\n }, [highlightedIndex, isOpen]);\n\n // Reset the typeahead buffer whenever the dropdown closes (Escape, click\n // outside, selection) so a stale query doesn't carry over on a quick reopen,\n // and clear any pending timer on unmount.\n const resetTypeahead = React.useCallback(() => {\n if (typeaheadRef.current.timer !== null) {\n window.clearTimeout(typeaheadRef.current.timer);\n typeaheadRef.current.timer = null;\n }\n typeaheadRef.current.query = '';\n }, []);\n\n React.useEffect(() => {\n if (!isOpen) resetTypeahead();\n }, [isOpen, resetTypeahead]);\n\n React.useEffect(() => resetTypeahead, [resetTypeahead]);\n\n // Build aria-describedby\n const describedByIds = [\n error ? errorId : null,\n helperText && !error ? helperId : null,\n ]\n .filter(Boolean)\n .join(' ');\n\n const isFloating = labelVariant === 'floating' && !!label && !hideLabel;\n const isFloated = isOpen || hasSelection;\n const resolvedSize = size ?? 'md';\n\n const requiredMark = required && <RequiredMark variant={requiredVariant} />;\n\n return (\n <div\n data-slot=\"select-wrapper\"\n className={cn('flex flex-col gap-1.5', className)}\n >\n {label && !isFloating && (\n <label\n data-slot=\"select-label\"\n htmlFor={selectId}\n className={cn(\n 'text-foreground text-sm font-medium',\n hideLabel && 'sr-only'\n )}\n >\n {label}\n {requiredMark}\n </label>\n )}\n\n <div ref={containerRef} className=\"relative\">\n {/* Trigger Button */}\n <button\n data-slot=\"select-trigger\"\n ref={(node) => {\n triggerRef.current = node;\n anchorRef.current = node;\n }}\n id={selectId}\n type=\"button\"\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n aria-expanded={isOpen}\n // Only reference the listbox while it exists in the DOM (it is\n // portaled and unmounted when closed) so the ID is always valid.\n aria-controls={isOpen ? listboxId : undefined}\n aria-invalid={hasError || !!error}\n aria-required={required || undefined}\n aria-label={!label ? ariaLabel : undefined}\n aria-describedby={describedByIds || undefined}\n disabled={disabled}\n onClick={() => setIsOpen(!isOpen)}\n onKeyDown={handleKeyDown}\n className={cn(\n selectTriggerVariants({\n size,\n hasError: hasError || !!error,\n labelVariant: isFloating ? 'floating' : 'stacked',\n })\n )}\n >\n <span\n className={cn(\n 'truncate',\n !hasSelection && 'text-muted-foreground',\n isFloating && floatingValuePadding[resolvedSize]\n )}\n >\n {isFloating\n ? hasSelection\n ? displayLabel\n : '\\u00A0'\n : hasSelection\n ? displayLabel\n : placeholder}\n </span>\n <ChevronDownIcon\n className={cn(\n 'text-muted-foreground h-4 w-4 shrink-0 transition-transform',\n isOpen && 'rotate-180'\n )}\n />\n </button>\n\n {/* Floating label (rendered after the trigger so `peer-focus` applies) */}\n {isFloating && (\n <label\n data-slot=\"select-label\"\n htmlFor={selectId}\n className={floatingLabelVariants({\n size: resolvedSize,\n floated: isFloated,\n hasError: hasError || !!error,\n })}\n >\n {label}\n {requiredMark}\n </label>\n )}\n\n {/* Dropdown (portaled to body to avoid overflow clipping) */}\n {isOpen &&\n createPortal(\n <div\n data-slot=\"select-dropdown\"\n ref={(node) => {\n dropdownRef.current = node;\n floatingRef.current = node;\n }}\n style={dropdownStyle}\n className={cn(\n 'border-border bg-card rounded-lg border shadow-lg',\n 'flex flex-col overflow-hidden',\n 'animate-in fade-in zoom-in-95 duration-100'\n )}\n >\n {/* Search Input */}\n {searchable && (\n <div\n data-slot=\"select-search\"\n className=\"border-border border-b p-2\"\n >\n <input\n ref={searchInputRef}\n type=\"text\"\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder={searchPlaceholder}\n className={cn(\n 'border-input bg-background w-full rounded-md border px-3 py-2 text-sm',\n 'placeholder:text-muted-foreground',\n 'focus:ring-ring focus:ring-2 focus:outline-none'\n )}\n aria-label=\"Search options\"\n />\n </div>\n )}\n\n {/* Options List */}\n <ul\n ref={listRef}\n id={listboxId}\n role=\"listbox\"\n aria-label={label || 'Options'}\n aria-multiselectable={multiple || undefined}\n data-slot=\"select-listbox\"\n className=\"flex-1 overflow-auto p-1\"\n >\n {filteredFlatOptions.length === 0 ? (\n <li className=\"text-muted-foreground px-3 py-2 text-center text-sm\">\n {noResultsText}\n </li>\n ) : (\n filteredOptions.map((item) => {\n if ('options' in item) {\n // Render group\n return (\n <li key={`group-${item.label}`} role=\"presentation\">\n <div\n data-slot=\"select-group-label\"\n className=\"text-muted-foreground px-3 py-1.5 text-xs font-semibold tracking-wider uppercase\"\n >\n {item.label}\n </div>\n <ul role=\"group\" aria-label={item.label}>\n {item.options.map((option) => (\n <SelectOptionItem\n key={option.value}\n option={option}\n isSelected={selectedValues.includes(\n option.value\n )}\n isHighlighted={\n filteredFlatOptions[highlightedIndex]\n ?.value === option.value\n }\n onSelect={() => handleValueChange(option.value)}\n onMouseEnter={() => {\n const idx = filteredFlatOptions.findIndex(\n (o) => o.value === option.value\n );\n setHighlightedIndex(idx);\n }}\n />\n ))}\n </ul>\n </li>\n );\n }\n\n // Render single option\n return (\n <SelectOptionItem\n key={item.value}\n option={item}\n isSelected={selectedValues.includes(item.value)}\n isHighlighted={\n filteredFlatOptions[highlightedIndex]?.value ===\n item.value\n }\n onSelect={() => handleValueChange(item.value)}\n onMouseEnter={() => {\n const idx = filteredFlatOptions.findIndex(\n (o) => o.value === item.value\n );\n setHighlightedIndex(idx);\n }}\n />\n );\n })\n )}\n </ul>\n </div>,\n document.body\n )}\n </div>\n\n {/* Error Message */}\n {error && (\n <p\n id={errorId}\n data-slot=\"select-error\"\n className=\"text-destructive-700 dark:text-destructive-400 text-sm\"\n role=\"alert\"\n >\n {error}\n </p>\n )}\n\n {/* Helper Text */}\n {helperText && !error && (\n <p\n id={helperId}\n data-slot=\"select-helper\"\n className=\"text-muted-foreground text-sm\"\n >\n {helperText}\n </p>\n )}\n </div>\n );\n}\n\nSelect.displayName = 'Select';\n\n/** Normalize a single/multiple value prop into an array of selected values. */\nfunction toValueArray(value: string | string[] | undefined): string[] {\n if (value === undefined || value === '') return [];\n return Array.isArray(value) ? value : [value];\n}\n\n// ============================================================================\n// Select Option Item (Internal)\n// ============================================================================\n\ninterface SelectOptionItemProps {\n option: SelectOption;\n isSelected: boolean;\n isHighlighted: boolean;\n onSelect: () => void;\n onMouseEnter: () => void;\n}\n\nfunction SelectOptionItem({\n option,\n isSelected,\n isHighlighted,\n onSelect,\n onMouseEnter,\n}: SelectOptionItemProps) {\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n if (!option.disabled) {\n onSelect();\n }\n }\n };\n\n return (\n <li\n data-slot=\"select-option\"\n role=\"option\"\n aria-selected={isSelected}\n aria-disabled={option.disabled}\n data-highlighted={isHighlighted}\n data-disabled={option.disabled}\n tabIndex={isHighlighted ? 0 : -1}\n onClick={option.disabled ? undefined : onSelect}\n onKeyDown={handleKeyDown}\n onMouseEnter={option.disabled ? undefined : onMouseEnter}\n className={cn(\n 'flex cursor-pointer items-center gap-2 rounded-md px-3 py-2 text-sm',\n 'transition-colors outline-none',\n isHighlighted && 'bg-muted',\n isSelected &&\n 'bg-primary-50 text-primary-900 dark:bg-primary-950 dark:text-primary-100',\n option.disabled && 'cursor-not-allowed opacity-50'\n )}\n >\n <span className=\"flex-1 truncate\">{option.label}</span>\n {isSelected && (\n <CheckIcon className=\"text-primary-800 h-4 w-4 shrink-0\" />\n )}\n </li>\n );\n}\n\n// ============================================================================\n// Icons\n// ============================================================================\n\nfunction ChevronDownIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n aria-hidden=\"true\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n );\n}\n\nfunction CheckIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n aria-hidden=\"true\"\n >\n <path d=\"M20 6 9 17l-5-5\" />\n </svg>\n );\n}\n\nexport { Select, selectTriggerVariants };\n"]}