eidos-ui 3.8.1 → 4.1.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 (267) hide show
  1. package/README.md +21 -11
  2. package/dist/{SegmentedControl.types-D_gHYL9X.d.cts → SegmentedControl.types-50fprBiO.d.cts} +9 -0
  3. package/dist/{SegmentedControl.types-CHtjABQM.d.ts → SegmentedControl.types-DKlamnBZ.d.ts} +9 -0
  4. package/dist/{ThemeProvider.types-DgXN0gEH.d.cts → ThemeProvider.types-CI9P1anY.d.cts} +53 -2
  5. package/dist/{ThemeProvider.types-DgXN0gEH.d.ts → ThemeProvider.types-CI9P1anY.d.ts} +53 -2
  6. package/dist/alert/index.cjs +5 -5
  7. package/dist/alert/index.js +4 -4
  8. package/dist/button/index.cjs +4 -4
  9. package/dist/button/index.js +3 -3
  10. package/dist/chip/index.cjs +4 -4
  11. package/dist/chip/index.js +3 -3
  12. package/dist/{chunk-V5CM5TH3.js → chunk-2OBOD3GO.js} +3 -3
  13. package/dist/{chunk-CFVUUMQA.cjs → chunk-2URFSWJT.cjs} +6 -8
  14. package/dist/chunk-2URFSWJT.cjs.map +1 -0
  15. package/dist/{chunk-4S57PE43.js → chunk-2WDL2ZVP.js} +6 -7
  16. package/dist/chunk-2WDL2ZVP.js.map +1 -0
  17. package/dist/{chunk-LWCFT5SP.cjs → chunk-3QBMSZSE.cjs} +3 -3
  18. package/dist/{chunk-LWCFT5SP.cjs.map → chunk-3QBMSZSE.cjs.map} +1 -1
  19. package/dist/{chunk-IC2PIK3E.js → chunk-43DJ3GGR.js} +4 -4
  20. package/dist/{chunk-L6ERHCQ2.js → chunk-57BVERWD.js} +3 -3
  21. package/dist/{chunk-AUNDBUHM.cjs → chunk-5HRVHEHE.cjs} +3 -3
  22. package/dist/{chunk-AUNDBUHM.cjs.map → chunk-5HRVHEHE.cjs.map} +1 -1
  23. package/dist/{chunk-6IB27I5K.cjs → chunk-6JYXGRJ3.cjs} +8 -8
  24. package/dist/{chunk-6IB27I5K.cjs.map → chunk-6JYXGRJ3.cjs.map} +1 -1
  25. package/dist/{chunk-NERASTO2.cjs → chunk-6ZFXIYH7.cjs} +3 -3
  26. package/dist/{chunk-NERASTO2.cjs.map → chunk-6ZFXIYH7.cjs.map} +1 -1
  27. package/dist/{chunk-IKXXXVUO.js → chunk-7TQUJ6BJ.js} +3 -3
  28. package/dist/{chunk-544RAXWO.cjs → chunk-7VMF6LIC.cjs} +19 -19
  29. package/dist/{chunk-544RAXWO.cjs.map → chunk-7VMF6LIC.cjs.map} +1 -1
  30. package/dist/{chunk-WTFEMOV5.cjs → chunk-ADB7QRX5.cjs} +16 -16
  31. package/dist/{chunk-WTFEMOV5.cjs.map → chunk-ADB7QRX5.cjs.map} +1 -1
  32. package/dist/{chunk-6CW5QSYV.cjs → chunk-AFGC62AL.cjs} +7 -7
  33. package/dist/{chunk-6CW5QSYV.cjs.map → chunk-AFGC62AL.cjs.map} +1 -1
  34. package/dist/{chunk-U4SVBE2M.js → chunk-AWPJH3UB.js} +4 -4
  35. package/dist/{chunk-V64DICJK.js → chunk-BHZ76J2K.js} +45 -33
  36. package/dist/chunk-BHZ76J2K.js.map +1 -0
  37. package/dist/{chunk-B2OHBIAL.cjs → chunk-BKUZF7CW.cjs} +10 -11
  38. package/dist/chunk-BKUZF7CW.cjs.map +1 -0
  39. package/dist/{chunk-WR77IZUU.cjs → chunk-BPVOQLCA.cjs} +7 -7
  40. package/dist/{chunk-WR77IZUU.cjs.map → chunk-BPVOQLCA.cjs.map} +1 -1
  41. package/dist/{chunk-MCPGI6EI.js → chunk-BUSMGQJ4.js} +2 -2
  42. package/dist/{chunk-H3C6YECZ.js → chunk-D2PXPX56.js} +6 -6
  43. package/dist/{chunk-L6YJ6QTZ.js → chunk-DCUIT7SI.js} +2 -2
  44. package/dist/{chunk-FE7S4RSK.js → chunk-DHOBGYRD.js} +164 -34
  45. package/dist/chunk-DHOBGYRD.js.map +1 -0
  46. package/dist/{chunk-JFV56ISS.cjs → chunk-E7BFBU6K.cjs} +45 -33
  47. package/dist/chunk-E7BFBU6K.cjs.map +1 -0
  48. package/dist/{chunk-HYRLK462.js → chunk-EDPCI2JC.js} +2 -2
  49. package/dist/{chunk-Z3IJWYUD.js → chunk-EJWEG66P.js} +226 -42
  50. package/dist/chunk-EJWEG66P.js.map +1 -0
  51. package/dist/{chunk-DPTTDHZ5.js → chunk-FAGQGGT3.js} +3 -3
  52. package/dist/{chunk-CNTG7OOO.js → chunk-FFYPSLQV.js} +12 -12
  53. package/dist/{chunk-7NUVLVSL.cjs → chunk-FJSK2RT7.cjs} +5 -5
  54. package/dist/{chunk-7NUVLVSL.cjs.map → chunk-FJSK2RT7.cjs.map} +1 -1
  55. package/dist/{chunk-P6OJQ2RN.js → chunk-FSX7DDLO.js} +8 -9
  56. package/dist/chunk-FSX7DDLO.js.map +1 -0
  57. package/dist/{chunk-XIUZT4TO.js → chunk-GE3QCXT7.js} +6 -7
  58. package/dist/chunk-GE3QCXT7.js.map +1 -0
  59. package/dist/{chunk-JY77VJAZ.js → chunk-GHUEVNNU.js} +3 -3
  60. package/dist/{chunk-4V2XYUQL.js → chunk-GLEPKX2R.js} +2 -2
  61. package/dist/{chunk-GZDT2AHJ.cjs → chunk-GRKC4PIX.cjs} +7 -7
  62. package/dist/{chunk-GZDT2AHJ.cjs.map → chunk-GRKC4PIX.cjs.map} +1 -1
  63. package/dist/{chunk-SLHIVEFW.cjs → chunk-HKLLKNRQ.cjs} +6 -9
  64. package/dist/chunk-HKLLKNRQ.cjs.map +1 -0
  65. package/dist/{chunk-2TIMJD4K.js → chunk-IBT535UH.js} +3 -3
  66. package/dist/{chunk-HR5MWA3B.cjs → chunk-IJW6YCJB.cjs} +5 -5
  67. package/dist/{chunk-HR5MWA3B.cjs.map → chunk-IJW6YCJB.cjs.map} +1 -1
  68. package/dist/{chunk-OGGZIFTI.cjs → chunk-JO4NDJRA.cjs} +192 -62
  69. package/dist/chunk-JO4NDJRA.cjs.map +1 -0
  70. package/dist/{chunk-NNAEQR3Y.cjs → chunk-K6VEUJLY.cjs} +30 -30
  71. package/dist/{chunk-NNAEQR3Y.cjs.map → chunk-K6VEUJLY.cjs.map} +1 -1
  72. package/dist/{chunk-F5IRMMZ2.cjs → chunk-K73JO4FK.cjs} +7 -7
  73. package/dist/{chunk-F5IRMMZ2.cjs.map → chunk-K73JO4FK.cjs.map} +1 -1
  74. package/dist/{chunk-4HZIXRAJ.cjs → chunk-KF2OGUAD.cjs} +11 -12
  75. package/dist/chunk-KF2OGUAD.cjs.map +1 -0
  76. package/dist/{chunk-TJQNGJHP.js → chunk-KLHC5BHS.js} +4 -4
  77. package/dist/{chunk-XWMXEJVZ.js → chunk-KZKBZ2AV.js} +5 -7
  78. package/dist/chunk-KZKBZ2AV.js.map +1 -0
  79. package/dist/{chunk-DG3O5NV4.cjs → chunk-LLHR6QW3.cjs} +3 -3
  80. package/dist/{chunk-DG3O5NV4.cjs.map → chunk-LLHR6QW3.cjs.map} +1 -1
  81. package/dist/{chunk-GDRLVX2A.js → chunk-LXRNFQEI.js} +4 -4
  82. package/dist/{chunk-VXC7Z7XB.cjs → chunk-MKQVDEHI.cjs} +5 -6
  83. package/dist/chunk-MKQVDEHI.cjs.map +1 -0
  84. package/dist/{chunk-TNQ2ZZ7W.cjs → chunk-MUMTPMWD.cjs} +7 -7
  85. package/dist/{chunk-TNQ2ZZ7W.cjs.map → chunk-MUMTPMWD.cjs.map} +1 -1
  86. package/dist/{chunk-RHWZX7PB.js → chunk-NONYIHXD.js} +4 -4
  87. package/dist/{chunk-XPG56DLQ.cjs → chunk-NSA7ASZ7.cjs} +8 -8
  88. package/dist/{chunk-XPG56DLQ.cjs.map → chunk-NSA7ASZ7.cjs.map} +1 -1
  89. package/dist/{chunk-6NAOAKII.js → chunk-NWFGXLQP.js} +2 -2
  90. package/dist/{chunk-H46ZLPNJ.cjs → chunk-O45W57Y4.cjs} +233 -49
  91. package/dist/chunk-O45W57Y4.cjs.map +1 -0
  92. package/dist/{chunk-UUT2VEN5.cjs → chunk-OC2OBBGM.cjs} +7 -8
  93. package/dist/chunk-OC2OBBGM.cjs.map +1 -0
  94. package/dist/{chunk-3X6QVHTD.js → chunk-OERK3T7E.js} +3 -4
  95. package/dist/chunk-OERK3T7E.js.map +1 -0
  96. package/dist/{chunk-ZJWQPZ7E.js → chunk-OQWG7NLI.js} +3 -11
  97. package/dist/chunk-OQWG7NLI.js.map +1 -0
  98. package/dist/{chunk-U34INRFO.js → chunk-PP6HS4GR.js} +5 -16
  99. package/dist/chunk-PP6HS4GR.js.map +1 -0
  100. package/dist/{chunk-ENMDOQQO.cjs → chunk-R5WI5IGR.cjs} +6 -17
  101. package/dist/{chunk-ENMDOQQO.cjs.map → chunk-R5WI5IGR.cjs.map} +1 -1
  102. package/dist/{chunk-UTYY35QX.cjs → chunk-RZMQCVAS.cjs} +3 -3
  103. package/dist/{chunk-UTYY35QX.cjs.map → chunk-RZMQCVAS.cjs.map} +1 -1
  104. package/dist/{chunk-7FV2X62W.cjs → chunk-SJKD3WCV.cjs} +7 -7
  105. package/dist/{chunk-7FV2X62W.cjs.map → chunk-SJKD3WCV.cjs.map} +1 -1
  106. package/dist/{chunk-LUDK44NZ.cjs → chunk-SJPCBRKR.cjs} +3 -3
  107. package/dist/{chunk-LUDK44NZ.cjs.map → chunk-SJPCBRKR.cjs.map} +1 -1
  108. package/dist/{chunk-3TF2GZSG.js → chunk-SONL2RCW.js} +7 -7
  109. package/dist/{chunk-2IXCEKLI.js → chunk-SOS4K7VC.js} +2 -2
  110. package/dist/{chunk-WHQGJHMD.js → chunk-TOLNPD7S.js} +4 -4
  111. package/dist/{chunk-FHOD3FUN.js → chunk-UTOTOWPS.js} +4 -4
  112. package/dist/{chunk-YIOHKQ6Y.cjs → chunk-VCG647BY.cjs} +5 -13
  113. package/dist/chunk-VCG647BY.cjs.map +1 -0
  114. package/dist/{chunk-HLI4SOH3.cjs → chunk-VGMRIXW4.cjs} +45 -45
  115. package/dist/{chunk-HLI4SOH3.cjs.map → chunk-VGMRIXW4.cjs.map} +1 -1
  116. package/dist/{chunk-N5NXKVFJ.cjs → chunk-VPN7AR7T.cjs} +10 -10
  117. package/dist/{chunk-N5NXKVFJ.cjs.map → chunk-VPN7AR7T.cjs.map} +1 -1
  118. package/dist/{chunk-6FXFKMJ5.js → chunk-XBIMNWE6.js} +3 -3
  119. package/dist/{chunk-3VXUOAIJ.cjs → chunk-XR72A66Q.cjs} +3 -7
  120. package/dist/chunk-XR72A66Q.cjs.map +1 -0
  121. package/dist/{chunk-ULKWUKD2.cjs → chunk-YHSCUPP6.cjs} +22 -23
  122. package/dist/chunk-YHSCUPP6.cjs.map +1 -0
  123. package/dist/{chunk-S5CMZFX6.js → chunk-YPEJH57Z.js} +6 -7
  124. package/dist/chunk-YPEJH57Z.js.map +1 -0
  125. package/dist/{chunk-BO3KK3ZQ.js → chunk-YPPG7NLW.js} +2 -6
  126. package/dist/chunk-YPPG7NLW.js.map +1 -0
  127. package/dist/{chunk-PE2SLXUS.cjs → chunk-YWXS4IPH.cjs} +5 -5
  128. package/dist/{chunk-PE2SLXUS.cjs.map → chunk-YWXS4IPH.cjs.map} +1 -1
  129. package/dist/{chunk-UC4NYF6T.js → chunk-YYA5SWXD.js} +2 -2
  130. package/dist/{chunk-IHPSRTVW.js → chunk-Z3OEYDNI.js} +4 -7
  131. package/dist/chunk-Z3OEYDNI.js.map +1 -0
  132. package/dist/{chunk-MKC6V3SY.cjs → chunk-Z6FZ7GI5.cjs} +6 -6
  133. package/dist/{chunk-MKC6V3SY.cjs.map → chunk-Z6FZ7GI5.cjs.map} +1 -1
  134. package/dist/{chunk-NFD7MPX4.cjs → chunk-ZVA5KJAJ.cjs} +11 -11
  135. package/dist/{chunk-NFD7MPX4.cjs.map → chunk-ZVA5KJAJ.cjs.map} +1 -1
  136. package/dist/color-picker/index.cjs +4 -4
  137. package/dist/color-picker/index.js +3 -3
  138. package/dist/combobox/index.cjs +6 -6
  139. package/dist/combobox/index.js +5 -5
  140. package/dist/command-palette/index.cjs +3 -3
  141. package/dist/command-palette/index.js +2 -2
  142. package/dist/context-menu/index.cjs +6 -6
  143. package/dist/context-menu/index.js +5 -5
  144. package/dist/conversation/index.cjs +8 -8
  145. package/dist/conversation/index.js +7 -7
  146. package/dist/data-grid/index.cjs +15 -15
  147. package/dist/data-grid/index.d.cts +1 -1
  148. package/dist/data-grid/index.d.ts +1 -1
  149. package/dist/data-grid/index.js +14 -14
  150. package/dist/date-picker/index.cjs +8 -8
  151. package/dist/date-picker/index.js +7 -7
  152. package/dist/drawer/index.cjs +5 -5
  153. package/dist/drawer/index.js +4 -4
  154. package/dist/dropdown/index.cjs +3 -3
  155. package/dist/dropdown/index.js +2 -2
  156. package/dist/header/index.cjs +6 -6
  157. package/dist/header/index.js +5 -5
  158. package/dist/index.cjs +39 -39
  159. package/dist/index.cjs.map +1 -1
  160. package/dist/index.css +345 -205
  161. package/dist/index.d.cts +2 -2
  162. package/dist/index.d.ts +2 -2
  163. package/dist/index.js +40 -40
  164. package/dist/inline-edit/index.cjs +5 -5
  165. package/dist/inline-edit/index.js +4 -4
  166. package/dist/input/index.cjs +4 -4
  167. package/dist/input/index.js +3 -3
  168. package/dist/menu/index.cjs +5 -5
  169. package/dist/menu/index.js +4 -4
  170. package/dist/modal/index.cjs +5 -5
  171. package/dist/modal/index.js +4 -4
  172. package/dist/navigation/index.cjs +5 -5
  173. package/dist/navigation/index.js +4 -4
  174. package/dist/number-input/index.cjs +2 -4
  175. package/dist/number-input/index.cjs.map +1 -1
  176. package/dist/number-input/index.js +1 -3
  177. package/dist/page-layout/index.cjs +12 -12
  178. package/dist/page-layout/index.js +11 -11
  179. package/dist/pagination/index.cjs +8 -8
  180. package/dist/pagination/index.js +7 -7
  181. package/dist/popover/index.cjs +3 -3
  182. package/dist/popover/index.d.cts +1 -3
  183. package/dist/popover/index.d.ts +1 -3
  184. package/dist/popover/index.js +2 -2
  185. package/dist/segmented-control/index.cjs +4 -4
  186. package/dist/segmented-control/index.d.cts +2 -2
  187. package/dist/segmented-control/index.d.ts +2 -2
  188. package/dist/segmented-control/index.js +3 -3
  189. package/dist/select/index.cjs +6 -6
  190. package/dist/select/index.js +5 -5
  191. package/dist/snackbar/index.cjs +5 -5
  192. package/dist/snackbar/index.js +4 -4
  193. package/dist/split-button/index.cjs +6 -6
  194. package/dist/split-button/index.js +5 -5
  195. package/dist/split-chip/index.cjs +5 -5
  196. package/dist/split-chip/index.js +4 -4
  197. package/dist/table/index.cjs +13 -13
  198. package/dist/table/index.js +12 -12
  199. package/dist/tabs/index.cjs +3 -3
  200. package/dist/tabs/index.js +2 -2
  201. package/dist/tag-input/index.cjs +6 -6
  202. package/dist/tag-input/index.js +5 -5
  203. package/dist/textarea/index.cjs +4 -4
  204. package/dist/textarea/index.js +3 -3
  205. package/dist/theme-editor/index.cjs +13 -11
  206. package/dist/theme-editor/index.cjs.map +1 -1
  207. package/dist/theme-editor/index.d.cts +1 -1
  208. package/dist/theme-editor/index.d.ts +1 -1
  209. package/dist/theme-editor/index.js +12 -10
  210. package/dist/theme-provider/index.cjs +3 -3
  211. package/dist/theme-provider/index.d.cts +2 -2
  212. package/dist/theme-provider/index.d.ts +2 -2
  213. package/dist/theme-provider/index.js +2 -2
  214. package/dist/toolbar/index.cjs +8 -8
  215. package/dist/toolbar/index.js +7 -7
  216. package/dist/tooltip/index.cjs +3 -3
  217. package/dist/tooltip/index.js +2 -2
  218. package/package.json +4 -2
  219. package/dist/chunk-3VXUOAIJ.cjs.map +0 -1
  220. package/dist/chunk-3X6QVHTD.js.map +0 -1
  221. package/dist/chunk-4HZIXRAJ.cjs.map +0 -1
  222. package/dist/chunk-4S57PE43.js.map +0 -1
  223. package/dist/chunk-B2OHBIAL.cjs.map +0 -1
  224. package/dist/chunk-BO3KK3ZQ.js.map +0 -1
  225. package/dist/chunk-CFVUUMQA.cjs.map +0 -1
  226. package/dist/chunk-FE7S4RSK.js.map +0 -1
  227. package/dist/chunk-H46ZLPNJ.cjs.map +0 -1
  228. package/dist/chunk-IHPSRTVW.js.map +0 -1
  229. package/dist/chunk-JFV56ISS.cjs.map +0 -1
  230. package/dist/chunk-OGGZIFTI.cjs.map +0 -1
  231. package/dist/chunk-P6OJQ2RN.js.map +0 -1
  232. package/dist/chunk-S5CMZFX6.js.map +0 -1
  233. package/dist/chunk-SLHIVEFW.cjs.map +0 -1
  234. package/dist/chunk-U34INRFO.js.map +0 -1
  235. package/dist/chunk-ULKWUKD2.cjs.map +0 -1
  236. package/dist/chunk-UUT2VEN5.cjs.map +0 -1
  237. package/dist/chunk-V64DICJK.js.map +0 -1
  238. package/dist/chunk-VXC7Z7XB.cjs.map +0 -1
  239. package/dist/chunk-XIUZT4TO.js.map +0 -1
  240. package/dist/chunk-XWMXEJVZ.js.map +0 -1
  241. package/dist/chunk-YIOHKQ6Y.cjs.map +0 -1
  242. package/dist/chunk-Z3IJWYUD.js.map +0 -1
  243. package/dist/chunk-ZJWQPZ7E.js.map +0 -1
  244. /package/dist/{chunk-V5CM5TH3.js.map → chunk-2OBOD3GO.js.map} +0 -0
  245. /package/dist/{chunk-IC2PIK3E.js.map → chunk-43DJ3GGR.js.map} +0 -0
  246. /package/dist/{chunk-L6ERHCQ2.js.map → chunk-57BVERWD.js.map} +0 -0
  247. /package/dist/{chunk-IKXXXVUO.js.map → chunk-7TQUJ6BJ.js.map} +0 -0
  248. /package/dist/{chunk-U4SVBE2M.js.map → chunk-AWPJH3UB.js.map} +0 -0
  249. /package/dist/{chunk-MCPGI6EI.js.map → chunk-BUSMGQJ4.js.map} +0 -0
  250. /package/dist/{chunk-H3C6YECZ.js.map → chunk-D2PXPX56.js.map} +0 -0
  251. /package/dist/{chunk-L6YJ6QTZ.js.map → chunk-DCUIT7SI.js.map} +0 -0
  252. /package/dist/{chunk-HYRLK462.js.map → chunk-EDPCI2JC.js.map} +0 -0
  253. /package/dist/{chunk-DPTTDHZ5.js.map → chunk-FAGQGGT3.js.map} +0 -0
  254. /package/dist/{chunk-CNTG7OOO.js.map → chunk-FFYPSLQV.js.map} +0 -0
  255. /package/dist/{chunk-JY77VJAZ.js.map → chunk-GHUEVNNU.js.map} +0 -0
  256. /package/dist/{chunk-4V2XYUQL.js.map → chunk-GLEPKX2R.js.map} +0 -0
  257. /package/dist/{chunk-2TIMJD4K.js.map → chunk-IBT535UH.js.map} +0 -0
  258. /package/dist/{chunk-TJQNGJHP.js.map → chunk-KLHC5BHS.js.map} +0 -0
  259. /package/dist/{chunk-GDRLVX2A.js.map → chunk-LXRNFQEI.js.map} +0 -0
  260. /package/dist/{chunk-RHWZX7PB.js.map → chunk-NONYIHXD.js.map} +0 -0
  261. /package/dist/{chunk-6NAOAKII.js.map → chunk-NWFGXLQP.js.map} +0 -0
  262. /package/dist/{chunk-3TF2GZSG.js.map → chunk-SONL2RCW.js.map} +0 -0
  263. /package/dist/{chunk-2IXCEKLI.js.map → chunk-SOS4K7VC.js.map} +0 -0
  264. /package/dist/{chunk-WHQGJHMD.js.map → chunk-TOLNPD7S.js.map} +0 -0
  265. /package/dist/{chunk-FHOD3FUN.js.map → chunk-UTOTOWPS.js.map} +0 -0
  266. /package/dist/{chunk-6FXFKMJ5.js.map → chunk-XBIMNWE6.js.map} +0 -0
  267. /package/dist/{chunk-UC4NYF6T.js.map → chunk-YYA5SWXD.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/home/runner/work/eidos-ui/eidos-ui/dist/chunk-O45W57Y4.cjs","../src/components/ThemeProvider/ThemeProvider.component.tsx","../src/components/ThemeProvider/ThemeProvider.context.tsx","../src/components/ThemeProvider/ThemeProvider.color.ts","../src/components/ThemeProvider/ThemeProvider.tokens.ts","../src/components/ThemeProvider/ThemeProvider.fonts.ts"],"names":["value"],"mappings":"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","file":"/home/runner/work/eidos-ui/eidos-ui/dist/chunk-O45W57Y4.cjs","sourcesContent":[null,"import React, {\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n} from 'react';\nimport { devWarn } from '../../utils';\nimport { ThemeContext } from './ThemeProvider.context';\nimport { buildTokens, diffFromDefault, resolveTheme, themeToCss } from './ThemeProvider.tokens';\nimport type {\n ColorScheme,\n ResolvedColorScheme,\n ThemeConfig,\n ThemeContextValue,\n ThemeProviderProps,\n} from './ThemeProvider.types';\n\n/** The attribute `dist/index.css` keys the dark and `system` schemes on. */\nconst SCHEME_ATTRIBUTE = 'data-color-scheme';\n\nconst isColorScheme = (value: string | null): value is ColorScheme =>\n value === 'light' || value === 'dark' || value === 'system';\n\n/** The scheme the page itself declares, for a provider not managing it. */\nconst readPageScheme = (): ColorScheme => {\n const value = document.documentElement.getAttribute(SCHEME_ATTRIBUTE);\n return isColorScheme(value) ? value : 'light';\n};\n\nconst DARK_QUERY = '(prefers-color-scheme: dark)';\n\nconst subscribeToPrefersDark = (onChange: () => void) => {\n const query = window.matchMedia?.(DARK_QUERY);\n query?.addEventListener('change', onChange);\n return () => query?.removeEventListener('change', onChange);\n};\nconst getPrefersDark = () => window.matchMedia?.(DARK_QUERY).matches ?? false;\n// The server cannot know; `light` matches what `dist/index.css` renders for a\n// page without the attribute, so hydration agrees.\nconst getServerPrefersDark = () => false;\n\nconst EMPTY_THEME: ThemeConfig = {};\n\n/**\n * Number of providers currently mounted.\n *\n * Because tokens are written to `document.documentElement` (see the component\n * comment for why), providers do not compose: two of them target the same\n * element, so whichever applied a given token last wins for the entire page -\n * including for the subtree of the other one. That looks like a broken theme\n * rather than a misuse, so it is worth saying out loud.\n */\nlet mountedProviders = 0;\n\n/** Merges `patch` over `base` one level into `colors`/`typography`. */\nconst mergeTheme = (base: ThemeConfig, patch: ThemeConfig): ThemeConfig => ({\n colors: { ...base.colors, ...patch.colors },\n typography: { ...base.typography, ...patch.typography },\n dark: { colors: { ...base.dark?.colors, ...patch.dark?.colors } },\n});\n\n/**\n * Applies a theme by writing CSS custom properties to `document.documentElement`.\n *\n * Two deliberate choices worth knowing:\n *\n * **The target is `documentElement`, not a wrapper element.** Every overlay in\n * this library (`Dropdown`, `Modal`, `Drawer`, `Snackbar`, `Tooltip`, …) portals\n * to `document.body`, so tokens scoped to a wrapper `<div>` would leave every\n * popup rendering the preset instead.\n *\n * **Properties are set through the CSSOM** (`style.setProperty`), which no CSP\n * directive gates - `style-src` and `style-src-attr` only cover the `style`\n * HTML attribute and stylesheet loads. Nothing here needs a nonce, and no\n * `<style>` element is ever created. See `ContentSecurityPolicy.mdx`.\n *\n * Under SSR the server sends the preset from `dist/index.css` and the theme is\n * applied on hydration; use `toCss()` if you need a themed first paint.\n */\nexport const ThemeProvider: React.FC<ThemeProviderProps> = ({\n children,\n theme: controlledTheme,\n defaultTheme: initialTheme,\n onThemeChange,\n colorScheme: controlledScheme,\n defaultColorScheme,\n onColorSchemeChange,\n}) => {\n const isControlled = controlledTheme !== undefined;\n const [uncontrolledTheme, setUncontrolledTheme] = useState<ThemeConfig>(\n initialTheme ?? EMPTY_THEME,\n );\n const theme = isControlled ? controlledTheme : uncontrolledTheme;\n\n useEffect(() => {\n mountedProviders += 1;\n if (mountedProviders > 1) {\n devWarn(\n 'theme-multiple-providers',\n `ThemeProvider: ${mountedProviders} providers are mounted at once. They all write to document.documentElement, so the last one to apply each token wins for the whole page - nested or sibling providers cannot theme separate subtrees. Use a single provider at your app root.`,\n );\n }\n return () => {\n mountedProviders -= 1;\n };\n }, []);\n\n // ── Colour scheme ─────────────────────────────────────────────────────────\n //\n // \"Managed\" once a scheme has been given - by prop, by default, or through\n // `setColorScheme`. Until then the provider never touches the attribute: an\n // app that server-renders `data-color-scheme` to avoid a flash of the wrong\n // scheme must not have it overwritten by a client default. An unmanaged\n // provider follows whatever the page declares instead.\n const [uncontrolledScheme, setUncontrolledScheme] = useState<ColorScheme | undefined>(\n defaultColorScheme,\n );\n const managedScheme = controlledScheme ?? uncontrolledScheme;\n\n const [pageScheme, setPageScheme] = useState<ColorScheme>('light');\n useLayoutEffect(() => {\n if (managedScheme !== undefined) return;\n setPageScheme(readPageScheme());\n // The app owns the attribute in this mode and may change it at any time.\n const observer = new MutationObserver(() => setPageScheme(readPageScheme()));\n observer.observe(document.documentElement, { attributeFilter: [SCHEME_ATTRIBUTE] });\n return () => observer.disconnect();\n }, [managedScheme]);\n\n useLayoutEffect(() => {\n if (managedScheme === undefined) return;\n const root = document.documentElement;\n const previous = root.getAttribute(SCHEME_ATTRIBUTE);\n root.setAttribute(SCHEME_ATTRIBUTE, managedScheme);\n return () => {\n if (previous === null) root.removeAttribute(SCHEME_ATTRIBUTE);\n else root.setAttribute(SCHEME_ATTRIBUTE, previous);\n };\n }, [managedScheme]);\n\n const colorScheme = managedScheme ?? pageScheme;\n const prefersDark = useSyncExternalStore(\n subscribeToPrefersDark,\n getPrefersDark,\n getServerPrefersDark,\n );\n const resolvedColorScheme: ResolvedColorScheme =\n colorScheme === 'system' ? (prefersDark ? 'dark' : 'light') : colorScheme;\n\n const setColorScheme = useCallback(\n (next: ColorScheme) => {\n if (controlledScheme === undefined) setUncontrolledScheme(next);\n onColorSchemeChange?.(next);\n },\n [controlledScheme, onColorSchemeChange],\n );\n\n // ── Tokens ────────────────────────────────────────────────────────────────\n //\n // Written for the scheme *in effect*. They are inline styles on `<html>`,\n // which outrank every stylesheet rule - including the dark and `system`\n // blocks in `dist/index.css` - so a custom colour written for light would\n // pin the light value in dark mode. Hence the scheme-aware build, and the\n // diff against the same scheme's preset: an unthemed provider still writes\n // nothing, in either scheme.\n const resolvedTheme = useMemo(() => resolveTheme(theme), [theme]);\n const tokens = useMemo(\n () => diffFromDefault(buildTokens(resolvedTheme, resolvedColorScheme), resolvedColorScheme),\n [resolvedTheme, resolvedColorScheme],\n );\n const isDefault = useMemo(\n () =>\n Object.keys(diffFromDefault(buildTokens(resolvedTheme, 'light'), 'light')).length === 0 &&\n Object.keys(diffFromDefault(buildTokens(resolvedTheme, 'dark'), 'dark')).length === 0,\n [resolvedTheme],\n );\n\n // Names written on the previous pass, so properties dropped from the theme\n // are removed rather than left behind at their last value.\n const appliedRef = useRef<string[]>([]);\n\n useLayoutEffect(() => {\n if (typeof document === 'undefined') return;\n const root = document.documentElement;\n\n for (const name of appliedRef.current) {\n if (!(name in tokens)) root.style.removeProperty(name);\n }\n for (const [name, value] of Object.entries(tokens)) {\n root.style.setProperty(name, value);\n }\n appliedRef.current = Object.keys(tokens);\n\n return () => {\n for (const name of appliedRef.current) {\n root.style.removeProperty(name);\n }\n appliedRef.current = [];\n };\n }, [tokens]);\n\n const commit = useCallback(\n (next: ThemeConfig) => {\n if (!isControlled) setUncontrolledTheme(next);\n onThemeChange?.(next);\n },\n [isControlled, onThemeChange],\n );\n\n const setTheme = useCallback((next: ThemeConfig) => commit(next), [commit]);\n\n const updateTheme = useCallback(\n (patch: ThemeConfig) => commit(mergeTheme(theme, patch)),\n [commit, theme],\n );\n\n const resetTheme = useCallback(() => commit(EMPTY_THEME), [commit]);\n\n const toCss = useCallback(() => themeToCss(resolvedTheme), [resolvedTheme]);\n\n const value = useMemo<ThemeContextValue>(\n () => ({\n theme,\n resolvedTheme,\n setTheme,\n updateTheme,\n resetTheme,\n isDefault,\n toCss,\n colorScheme,\n resolvedColorScheme,\n setColorScheme,\n }),\n [\n theme,\n resolvedTheme,\n setTheme,\n updateTheme,\n resetTheme,\n isDefault,\n toCss,\n colorScheme,\n resolvedColorScheme,\n setColorScheme,\n ],\n );\n\n return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>;\n};\n\nThemeProvider.displayName = 'ThemeProvider';\n","import { createContext, useContext } from 'react';\nimport type { ThemeContextValue } from './ThemeProvider.types';\n\nexport const ThemeContext = createContext<ThemeContextValue | undefined>(undefined);\n\n/**\n * Reads the active theme. Throws outside a `ThemeProvider`, matching\n * `useSnackbarContext` - a silent fallback would make a missing provider look\n * like a theme that simply is not applying.\n */\nexport const useTheme = (): ThemeContextValue => {\n const context = useContext(ThemeContext);\n if (!context) {\n throw new Error('useTheme must be used within a ThemeProvider');\n }\n return context;\n};\n","/**\n * Colour maths for the theme system.\n *\n * All conversions are done in JS and emitted as `#rrggbb`, so browser support\n * for `oklch()` is irrelevant here - nothing in the generated CSS uses a modern\n * colour function.\n *\n * OKLab is used rather than HSL for every interpolation. HSL lightness\n * interpolation is ~40 lines shorter but produces muddy, desaturated ramps for\n * exactly the saturated brand hues this feature exists to support, because its\n * \"lightness\" is not perceptual.\n */\n\n// ============================================================================\n// sRGB <-> OKLab\n// ============================================================================\n\nexport interface Oklch {\n /** Perceptual lightness, 0-1. */\n l: number;\n /** Chroma (colourfulness), 0 to ~0.4 in sRGB. */\n c: number;\n /** Hue angle in radians. */\n h: number;\n}\n\nconst srgbToLinear = (v: number): number =>\n v <= 0.04045 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);\n\nconst linearToSrgb = (v: number): number =>\n v <= 0.0031308 ? 12.92 * v : 1.055 * Math.pow(v, 1 / 2.4) - 0.055;\n\nconst clamp01 = (v: number): number => (v < 0 ? 0 : v > 1 ? 1 : v);\n\n/** Parses `#rgb` / `#rrggbb` into 0-1 sRGB channels. Returns null if unparseable. */\nexport const parseHex = (hex: string): [number, number, number] | null => {\n if (typeof hex !== 'string') return null;\n const raw = hex.trim().replace(/^#/, '');\n const full =\n raw.length === 3\n ? raw\n .split('')\n .map((c) => c + c)\n .join('')\n : raw;\n if (!/^[0-9a-fA-F]{6}$/.test(full)) return null;\n const n = parseInt(full, 16);\n return [((n >> 16) & 255) / 255, ((n >> 8) & 255) / 255, (n & 255) / 255];\n};\n\nexport const isValidHex = (hex: string): boolean => parseHex(hex) !== null;\n\nconst toHex = ([r, g, b]: [number, number, number]): string =>\n '#' +\n [r, g, b]\n .map((v) =>\n Math.round(clamp01(v) * 255)\n .toString(16)\n .padStart(2, '0'),\n )\n .join('');\n\n/** `#rrggbb` -> the comma-separated triple the `--x-rgb` tokens use. */\nexport const hexToRgbTriple = (hex: string): string => {\n const rgb = parseHex(hex);\n if (!rgb) return '0, 0, 0';\n return rgb.map((v) => Math.round(v * 255)).join(', ');\n};\n\nconst linearToOklab = ([r, g, b]: [number, number, number]): [number, number, number] => {\n const l = Math.cbrt(0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b);\n const m = Math.cbrt(0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b);\n const s = Math.cbrt(0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b);\n return [\n 0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s,\n 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s,\n 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s,\n ];\n};\n\nconst oklabToLinear = ([L, A, B]: [number, number, number]): [number, number, number] => {\n const l = (L + 0.3963377774 * A + 0.2158037573 * B) ** 3;\n const m = (L - 0.1055613458 * A - 0.0638541728 * B) ** 3;\n const s = (L - 0.0894841775 * A - 1.291485548 * B) ** 3;\n return [\n 4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s,\n -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s,\n -0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s,\n ];\n};\n\nexport const hexToOklch = (hex: string): Oklch => {\n const rgb = parseHex(hex) ?? [0, 0, 0];\n const [l, a, b] = linearToOklab(rgb.map(srgbToLinear) as [number, number, number]);\n return { l, c: Math.hypot(a, b), h: Math.atan2(b, a) };\n};\n\nconst inGamut = ([r, g, b]: [number, number, number]): boolean =>\n [r, g, b].every((v) => v >= -1e-4 && v <= 1 + 1e-4);\n\n/**\n * Largest chroma that still fits in sRGB at this lightness and hue.\n *\n * Needed because OKLab is a much larger space than sRGB: naively keeping a\n * colour's chroma while changing its lightness frequently lands outside the\n * gamut, where channels clip and the hue visibly shifts.\n */\nconst maxChroma = (l: number, h: number): number => {\n let lo = 0;\n let hi = 0.45;\n for (let i = 0; i < 24; i++) {\n const mid = (lo + hi) / 2;\n if (inGamut(oklabToLinear([l, mid * Math.cos(h), mid * Math.sin(h)]))) lo = mid;\n else hi = mid;\n }\n return lo;\n};\n\nexport const oklchToHex = ({ l, c, h }: Oklch): string => {\n const lc = clamp01(l);\n const cc = Math.min(Math.max(c, 0), maxChroma(lc, h));\n return toHex(\n oklabToLinear([lc, cc * Math.cos(h), cc * Math.sin(h)]).map(linearToSrgb) as [\n number,\n number,\n number,\n ],\n );\n};\n\n// ============================================================================\n// WCAG 2.1 contrast\n// ============================================================================\n\n/**\n * WCAG 2.1 is used rather than APCA. APCA models perception better but is\n * still a draft (targeted at WCAG 3), while WCAG 2 is what consumers are\n * actually audited against. Its known weakness - mis-ranking some mid-tone\n * blues and greens - is accepted for that reason.\n */\nexport const relativeLuminance = (hex: string): number => {\n const [r, g, b] = (parseHex(hex) ?? [0, 0, 0]).map(srgbToLinear);\n return 0.2126 * r + 0.7152 * g + 0.0722 * b;\n};\n\n/** Contrast ratio between two colours, 1 (identical) to 21 (black on white). */\nexport const contrastRatio = (a: string, b: string): number => {\n const [x, y] = [relativeLuminance(a), relativeLuminance(b)];\n return (Math.max(x, y) + 0.05) / (Math.min(x, y) + 0.05);\n};\n\n/** The two foreground candidates, matching `--white` and `--gray-900`. */\nexport const CONTRAST_LIGHT = '#ffffff';\nexport const CONTRAST_DARK = '#0f172a';\n\n/**\n * Foreground to place on `fill`.\n *\n * White wins unless it drops below 3:1, at which point the better of the two\n * candidates is used. The threshold is deliberately 3:1 rather than \"whichever\n * scores higher\": on mid-tone reds the dark candidate often scores marginally\n * better while looking plainly wrong, and every preset base clears 4.5:1\n * against white anyway.\n */\nexport const pickContrast = (fill: string): string => {\n const onLight = contrastRatio(fill, CONTRAST_LIGHT);\n if (onLight >= 3) return CONTRAST_LIGHT;\n return onLight >= contrastRatio(fill, CONTRAST_DARK) ? CONTRAST_LIGHT : CONTRAST_DARK;\n};\n\n// ============================================================================\n// Ramp generation\n// ============================================================================\n\n/** The ramp steps, in the order `--x-50` … `--x-900` are declared. */\nexport const RAMP_STEPS = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900] as const;\n\nexport type RampStep = (typeof RAMP_STEPS)[number];\n\n/** The step the supplied base colour occupies; the ramp is built around it. */\nconst BASE_STEP = 500;\n\n/**\n * Target lightness per step, and how much of the base's chroma to keep.\n *\n * Measured from the preset indigo ramp, so feeding the preset primary through\n * `buildRamp` lands close to the shipped `--primary-*` values rather than\n * something arbitrary. It is deliberately not an exact reproduction - see the\n * note on `buildRamp`.\n */\nconst RAMP_CURVE: Record<RampStep, { l: number; chroma: number }> = {\n 50: { l: 0.962, chroma: 0.09 },\n 100: { l: 0.93, chroma: 0.16 },\n 200: { l: 0.87, chroma: 0.3 },\n 300: { l: 0.785, chroma: 0.51 },\n 400: { l: 0.68, chroma: 0.77 },\n 500: { l: 0.558, chroma: 1.0 },\n 600: { l: 0.511, chroma: 1.12 },\n 700: { l: 0.457, chroma: 1.05 },\n 800: { l: 0.398, chroma: 0.87 },\n 900: { l: 0.359, chroma: 0.66 },\n};\n\n/** Ceiling/floor the generated ends aim for, leaving the base itself untouched. */\nconst LIGHT_CEILING = 0.985;\nconst DARK_FLOOR = 0.22;\n\n/** Minimum lightness gap between adjacent steps, so none can collapse together. */\nconst MIN_STEP_DELTA = 0.012;\n\n/**\n * Generates a 50-900 ramp around `base`, which is placed at the 500 step.\n *\n * The base's own hue is always preserved, and `--x-500` is returned as the base\n * hex verbatim, so the colour a consumer picked is never silently replaced.\n *\n * The curve above is *rescaled* to whatever lightness headroom the base leaves,\n * rather than being applied absolutely or simply shifted:\n *\n * - Applying it absolutely would reassign the base - pick a pale yellow and\n * `--x-500` would come back a mid-olive, contradicting `--x-color`.\n * - Shifting it so 500 sits at the base's lightness pushes the light end past\n * `l = 1`, where it clips and 50/100/200/300 all come out pure white.\n *\n * The ends are **absolute**, not relative to the base: step 50 lands near-white\n * and step 900 near-dark whatever lightness the base has, with the remaining\n * steps interpolated between the base and those anchors. Only a base that is\n * already past an anchor compresses that side into what headroom is left.\n *\n * Getting this wrong is subtle. An earlier version offset every step *from the\n * base* by the curve's own distances, capped so the preset reproduced exactly.\n * That looks right - and reproduces the preset ramp perfectly - but it makes the\n * tints relative: a dark navy base (`#1a1a2e`) returned `--primary-50: #8a8a8c`,\n * a mid grey rather than a tint, because 50 sits only 0.404 lightness above 500\n * on the curve. Every consumer of the tint end broke visibly - `Navigation`'s\n * active item paints `--primary-50` and turned into a charcoal pill.\n *\n * Two inputs are genuinely degenerate and are handled rather than solved: a\n * base at or above `LIGHT_CEILING` has no room for tints, and one with zero\n * chroma (pure white, black, any gray) has no saturation to separate them with\n * either. For those the light end converges, and `isRampViable` reports it so\n * the caller can warn. Realistic light picks are fine - `#fde047` still yields\n * five distinct tints.\n */\nexport const buildRamp = (base: string): Record<RampStep, string> => {\n const { l: baseL, c: baseC, h } = hexToOklch(base);\n const anchor = RAMP_CURVE[BASE_STEP].l;\n\n // Where the ends of the scale sit, independent of the base. A base already\n // lighter than the curve's own 50 (or darker than its 900) has nowhere left\n // to go, so that side compresses into the remaining headroom instead.\n const curveLight = RAMP_CURVE[50].l;\n const curveDark = RAMP_CURVE[900].l;\n const lightTarget = baseL >= curveLight ? Math.min(LIGHT_CEILING, baseL + 0.02) : curveLight;\n const darkTarget = baseL <= curveDark ? Math.max(DARK_FLOOR * 0.2, baseL - 0.02) : curveDark;\n\n const lightSpan = curveLight - anchor;\n const darkSpan = anchor - curveDark;\n\n const out = {} as Record<RampStep, string>;\n for (const step of RAMP_STEPS) {\n if (step === BASE_STEP) {\n out[step] = base;\n continue;\n }\n const { l: curveL, chroma } = RAMP_CURVE[step];\n const offset = curveL - anchor;\n // How far along its half of the curve this step sits: 0 at the base, 1 at\n // the end. Interpolating that fraction between the base and the target\n // keeps the curve's shape while pinning where it ends up.\n const t = offset > 0 ? offset / lightSpan : -offset / darkSpan;\n const l = offset > 0 ? baseL + t * (lightTarget - baseL) : baseL - t * (baseL - darkTarget);\n out[step] = oklchToHex({ l, c: baseC * chroma, h });\n }\n\n return enforceSeparation(out, h, baseC);\n};\n\n/**\n * Walks outward from the base step, pushing any step that ended up too close to\n * its neighbour further away. Only bites for extreme inputs (near-white,\n * near-black, zero-chroma), where the rescale above has almost no room left.\n */\nconst enforceSeparation = (\n ramp: Record<RampStep, string>,\n h: number,\n baseC: number,\n): Record<RampStep, string> => {\n const baseIndex = RAMP_STEPS.indexOf(BASE_STEP);\n const lightness = RAMP_STEPS.map((s) => hexToOklch(ramp[s]).l);\n\n // Lighter steps: walk from the base toward 50, each must be lighter.\n for (let i = baseIndex - 1; i >= 0; i--) {\n const limit = lightness[i + 1] + MIN_STEP_DELTA;\n if (lightness[i] < limit) lightness[i] = Math.min(1, limit);\n }\n // Darker steps: walk from the base toward 900, each must be darker.\n for (let i = baseIndex + 1; i < RAMP_STEPS.length; i++) {\n const limit = lightness[i - 1] - MIN_STEP_DELTA;\n if (lightness[i] > limit) lightness[i] = Math.max(0, limit);\n }\n\n const out = {} as Record<RampStep, string>;\n RAMP_STEPS.forEach((step, i) => {\n if (step === BASE_STEP) {\n out[step] = ramp[step];\n return;\n }\n out[step] = oklchToHex({\n l: lightness[i],\n c: baseC * RAMP_CURVE[step].chroma,\n h,\n });\n });\n return out;\n};\n\n/** How far `--x-dark` / `--x-light` sit from the base, in OKLab lightness. */\nconst DARK_DELTA = 0.086;\nconst LIGHT_DELTA = 0.169;\n\n/** Below this lightness there is no room left to darken, so the hover lightens. */\nconst HOVER_INVERT_BELOW = DARK_DELTA * 1.5;\n\n/**\n * The hover/active colour. Must differ *visibly* from the base and stay legible\n * as text on white, since `--x-dark` is used both as a fill (Button, Chip\n * hovers) and as text (Snackbar, link hover in `global.scss`).\n *\n * A fixed ramp step is not good enough: for a near-white base the 600 step\n * lands barely darker than the base and the hover reads as no change at all.\n * Hence a guaranteed delta.\n *\n * For a base that is already near-black the delta is applied *upwards* instead.\n * Clamping to a floor would return a colour lighter than the base while still\n * being named \"dark\", and returning the base unchanged would leave the control\n * with no hover affordance at all; lightening is what dark-surface design\n * systems do anyway.\n */\nexport const deriveDark = (base: string): string => {\n const { l, c, h } = hexToOklch(base);\n const target = l < HOVER_INVERT_BELOW ? l + DARK_DELTA : l - DARK_DELTA;\n return oklchToHex({ l: target, c, h });\n};\n\n/**\n * The light companion. Lightening has a hard ceiling, so for an already-pale\n * base this lands very close to it - acceptable, as `--x-light` is a public\n * token that nothing inside the library currently consumes.\n */\nexport const deriveLight = (base: string): string => {\n const { l, c, h } = hexToOklch(base);\n return oklchToHex({ l: Math.min(LIGHT_CEILING, l + LIGHT_DELTA), c, h });\n};\n\n/**\n * Whether `base` leaves enough lightness headroom to generate a usable 50-900\n * ramp. False only for near-white and near-black, where the tint or shade end\n * necessarily converges - the caller surfaces that as a developer warning\n * rather than silently shipping identical tokens.\n *\n * Deliberately does not test chroma: an unsaturated gray separates perfectly\n * well by lightness alone, and a saturated light colour like `#fde047` still\n * produces five distinct tints. Only the extremes genuinely fail.\n */\nexport const isRampViable = (base: string): boolean => {\n const { l } = hexToOklch(base);\n return l < 0.95 && l > 0.12;\n};\n\n// ============================================================================\n// Dark scheme\n// ============================================================================\n//\n// One token cannot be both a fill for white text and readable text on a dark\n// page. White text needs a fill at relative luminance <= 0.18 (4.5:1); coloured\n// text on the dark page needs >= 0.23. The ranges do not overlap, so the dark\n// scheme *tone-shifts* every family instead: `--x-color` becomes a lighter tone\n// that reads as text on the dark surfaces, and `--x-contrast` flips to dark\n// text on it. Every \"fill + `--x-contrast`\" pairing in the library stays valid\n// by construction, and so does every `color: var(--x-color)`.\n//\n// The preset dark palette in `_color-schemes.scss` is produced by exactly these\n// functions from the light preset, and a unit test holds the two in step - so\n// a consumer's own colour is derived by the same rule the preset was.\n\n/** The dark scheme's page surface (`--surface`). Equal to `CONTRAST_DARK`. */\nexport const DARK_SURFACE = '#0f172a';\n\n/** The dark scheme's raised surface (`--surface-raised`): menus, dialogs. */\nexport const DARK_SURFACE_RAISED = '#1e293b';\n\n/**\n * Minimum contrast a dark-scheme base must reach against **both** dark\n * surfaces. 5:1 rather than 4.5:1 for the same reason the light bases sit at\n * ~5:1: a hundredth of headroom is a threshold the next tweak falls through.\n * Against the page this lands at ~6.1:1.\n */\nexport const DARK_BASE_MIN_CONTRAST = 5;\n\n/**\n * The dark-scheme tone of `base`: the same hue and chroma, lightened just far\n * enough to clear `DARK_BASE_MIN_CONTRAST` against both dark surfaces.\n *\n * A base that already clears it is returned unchanged - a consumer who picks a\n * light brand colour gets exactly that colour in dark mode too.\n */\nexport const deriveDarkBase = (base: string): string => {\n const reaches = (hex: string) =>\n contrastRatio(hex, DARK_SURFACE) >= DARK_BASE_MIN_CONTRAST &&\n contrastRatio(hex, DARK_SURFACE_RAISED) >= DARK_BASE_MIN_CONTRAST;\n if (reaches(base)) return base;\n\n const start = hexToOklch(base);\n // 0.005 steps: fine enough that the result lands within a few hundredths of\n // the threshold, coarse enough to be a few dozen iterations at most.\n for (let l = start.l; l <= 1; l += 0.005) {\n const candidate = oklchToHex({ ...start, l });\n if (reaches(candidate)) return candidate;\n }\n return '#ffffff';\n};\n\n/** How far the dark hover sits above its base, in OKLab lightness. */\nconst DARK_HOVER_DELTA = 0.07;\n/** How far the dark `--x-light` companion sits below its base. */\nconst DARK_LIGHT_DELTA = 0.35;\n\n/**\n * The dark-scheme hover (`--x-dark`). *Lighter* than the base, because on a\n * dark surface lightening is what reads as emphasis - and lightening also\n * moves the fill further from the dark `--x-contrast` text on it, so the hover\n * state can only gain contrast, never lose it (~8:1 for the preset).\n */\nexport const deriveDarkHover = (darkBase: string): string => {\n const { l, c, h } = hexToOklch(darkBase);\n return oklchToHex({ l: Math.min(LIGHT_CEILING, l + DARK_HOVER_DELTA), c, h });\n};\n\n/**\n * The dark-scheme `--x-light`: the low-emphasis companion, which on a dark\n * surface means *darker* than the base. Public token; nothing in the library\n * consumes it, matching the light scheme.\n */\nexport const deriveDarkLight = (darkBase: string): string => {\n const { l, c, h } = hexToOklch(darkBase);\n return oklchToHex({ l: Math.max(0.2, l - DARK_LIGHT_DELTA), c, h });\n};\n\n/**\n * Lightness and chroma share per step of the dark `--primary-50…900` ramp.\n *\n * The ramp is **inverted** relative to the light one: step 50 is the faintest\n * tint *on the dark page* - a near-page colour - and 900 is the lightest. That\n * keeps every consumer's intent intact. \"`-50` behind, `-700` as text\" is a\n * quiet tinted surface with strong text in both schemes (9.9:1 in dark).\n */\nconst DARK_RAMP_CURVE: Record<Exclude<RampStep, 500>, { l: number; chroma: number }> = {\n 50: { l: 0.235, chroma: 0.35 },\n 100: { l: 0.27, chroma: 0.45 },\n 200: { l: 0.33, chroma: 0.6 },\n 300: { l: 0.42, chroma: 0.8 },\n 400: { l: 0.55, chroma: 0.95 },\n 600: { l: 0.76, chroma: 0.8 },\n 700: { l: 0.83, chroma: 0.6 },\n 800: { l: 0.89, chroma: 0.4 },\n 900: { l: 0.945, chroma: 0.2 },\n};\n\n/** The dark `--x-50…900` ramp around a dark-scheme base, placed at 500. */\nexport const buildDarkRamp = (darkBase: string): Record<RampStep, string> => {\n const { c, h } = hexToOklch(darkBase);\n const out = {} as Record<RampStep, string>;\n for (const step of RAMP_STEPS) {\n out[step] =\n step === BASE_STEP\n ? darkBase\n : oklchToHex({\n l: DARK_RAMP_CURVE[step as Exclude<RampStep, 500>].l,\n c: c * DARK_RAMP_CURVE[step as Exclude<RampStep, 500>].chroma,\n h,\n });\n }\n return out;\n};\n","import { devWarn } from '../../utils';\nimport {\n DARK_SURFACE,\n DARK_SURFACE_RAISED,\n RAMP_STEPS,\n buildDarkRamp,\n buildRamp,\n contrastRatio,\n deriveDark,\n deriveDarkBase,\n deriveDarkHover,\n deriveDarkLight,\n deriveLight,\n hexToRgbTriple,\n isValidHex,\n isRampViable,\n pickContrast,\n} from './ThemeProvider.color';\nimport type {\n ResolvedColorScheme,\n ResolvedTheme,\n ThemeColorKey,\n ThemeColorValue,\n ThemeConfig,\n} from './ThemeProvider.types';\n\nexport const THEME_COLOR_KEYS: readonly ThemeColorKey[] = [\n 'primary',\n 'secondary',\n 'success',\n 'danger',\n 'warning',\n 'info',\n 'hyperlink',\n] as const;\n\n/**\n * `hyperlink` is link text on a surface, never a fill, so it has no\n * `--hyperlink-contrast` token - nothing in the library would read it.\n */\nconst FILL_COLOR_KEYS: readonly ThemeColorKey[] = [\n 'primary',\n 'secondary',\n 'success',\n 'danger',\n 'warning',\n 'info',\n] as const;\n\n/** Only `primary` has a 50-900 ramp in `variables.scss`. */\nconst RAMP_COLOR_KEY: ThemeColorKey = 'primary';\n\n/** The eight preset `--font-size-*` values, in declaration order. */\nconst FONT_SIZE_STEPS: readonly [string, number][] = [\n ['xs', 0.75],\n ['sm', 0.875],\n ['base', 1],\n ['md', 1.1],\n ['lg', 1.125],\n ['xl', 1.25],\n ['2xl', 1.5],\n ['3xl', 1.875],\n] as const;\n\n/**\n * The shipped values from `src/styles/variables.scss`.\n *\n * This is a literal copy, not something derived: the ramp is hand-tuned and no\n * generator reproduces it byte for byte. Keeping it literal means a theme equal\n * to the preset writes no CSS properties at all, so default rendering is\n * identical to `dist/index.css`.\n *\n * Must be kept in sync with `variables.scss` by hand. The bases are all chosen\n * to clear WCAG AA against white text; see the comment at the top of that file.\n */\nexport const defaultTheme: Required<ThemeConfig> = {\n colors: {\n primary: '#5c5de8',\n secondary: '#617087',\n success: '#007f57',\n danger: '#d6272f',\n warning: '#9c6300',\n info: '#007a90',\n hyperlink: '#007b84',\n },\n typography: {\n fontFamily:\n \"'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif\",\n monoFamily:\n \"'JetBrains Mono', 'SF Mono', 'Monaco', 'Inconsolata', 'Roboto Mono', 'Source Code Pro', monospace\",\n fontScale: 1,\n },\n // Empty on purpose: the preset's dark colours are *derived* from `colors`\n // (see `_color-schemes.scss`), exactly as a consumer's are.\n dark: {},\n};\n\n/** The preset `--primary-*` ramp, needed so an unthemed primary emits nothing. */\nconst DEFAULT_PRIMARY_RAMP: Record<number, string> = {\n 50: '#eef2ff',\n 100: '#e0e7ff',\n 200: '#c7d2fe',\n 300: '#a5b4fc',\n 400: '#818cf8',\n 500: '#5c5de8',\n 600: '#4f46e5',\n 700: '#4338ca',\n 800: '#3730a3',\n 900: '#312e81',\n};\n\nexport const FONT_SCALE_MIN = 0.875;\nexport const FONT_SCALE_MAX = 1.25;\n\nconst normalizeColor = (value: ThemeColorValue): { base: string; contrast?: string } =>\n typeof value === 'string' ? { base: value } : value;\n\ntype ResolvedColor = { base: string; contrast?: string };\n\n/**\n * Validates one supplied colour. `undefined` means \"use the fallback\" - either\n * nothing was supplied or the base was invalid (which warns).\n */\nconst resolveColor = (\n supplied: ThemeColorValue | undefined,\n path: string,\n): ResolvedColor | undefined => {\n if (supplied === undefined) return undefined;\n const { base, contrast } = normalizeColor(supplied);\n if (!isValidHex(base)) {\n devWarn(\n `theme-color-${path}`,\n `ThemeProvider: ${path} is not a valid hex colour (received ${JSON.stringify(base)}). Falling back to the preset.`,\n );\n return undefined;\n }\n if (contrast !== undefined && !isValidHex(contrast)) {\n devWarn(\n `theme-contrast-${path}`,\n `ThemeProvider: ${path}.contrast is not a valid hex colour (received ${JSON.stringify(contrast)}). It will be computed instead.`,\n );\n return { base };\n }\n return contrast === undefined ? { base } : { base, contrast };\n};\n\n/** Fills every absent field from the preset. */\nexport const resolveTheme = (theme: ThemeConfig): ResolvedTheme => {\n const colors = {} as ResolvedTheme['colors'];\n const darkColors = {} as ResolvedTheme['colors'];\n\n for (const key of THEME_COLOR_KEYS) {\n colors[key] =\n resolveColor(theme.colors?.[key], `colors.${key}`) ??\n normalizeColor(defaultTheme.colors[key]!);\n\n // The dark colour: an explicit `dark.colors` entry wins; otherwise the\n // light colour is tone-shifted, exactly as the preset's was. A pinned\n // light `contrast` does not carry over - it was chosen for the light fill.\n const explicitDark = resolveColor(theme.dark?.colors?.[key], `dark.colors.${key}`);\n if (explicitDark) {\n const worst = Math.min(\n contrastRatio(explicitDark.base, DARK_SURFACE),\n contrastRatio(explicitDark.base, DARK_SURFACE_RAISED),\n );\n if (worst < 4.5) {\n devWarn(\n `theme-dark-contrast-${key}`,\n `ThemeProvider: dark.colors.${key} (${explicitDark.base}) is ${worst.toFixed(2)}:1 against the dark surfaces, below the 4.5:1 text needs. It is used as given, but text in it will fail WCAG AA in the dark scheme - omit it to have a compliant tone derived from colors.${key}.`,\n );\n }\n darkColors[key] = explicitDark;\n } else {\n darkColors[key] = { base: deriveDarkBase(colors[key].base) };\n }\n }\n\n const scale = theme.typography?.fontScale;\n let fontScale = defaultTheme.typography.fontScale!;\n if (scale !== undefined) {\n if (!Number.isFinite(scale) || scale < FONT_SCALE_MIN || scale > FONT_SCALE_MAX) {\n devWarn(\n 'theme-font-scale',\n `ThemeProvider: typography.fontScale must be between ${FONT_SCALE_MIN} and ${FONT_SCALE_MAX} (received ${String(scale)}). Falling back to ${fontScale}.`,\n );\n } else {\n fontScale = scale;\n }\n }\n\n return {\n colors,\n typography: {\n fontFamily: theme.typography?.fontFamily || defaultTheme.typography.fontFamily!,\n monoFamily: theme.typography?.monoFamily || defaultTheme.typography.monoFamily!,\n fontScale,\n },\n dark: { colors: darkColors },\n };\n};\n\n/**\n * Expands a resolved theme into the flat `--token: value` map to apply.\n *\n * Every family contributes `--x-color`, `--x-rgb`, `--x-dark` and `--x-light`;\n * the six fill families also get `--x-contrast`, and `primary` additionally\n * gets the full `--primary-50…900` ramp.\n */\nexport const buildTokens = (\n resolved: ResolvedTheme,\n scheme: ResolvedColorScheme = 'light',\n): Record<string, string> => {\n if (scheme === 'dark') return buildDarkTokens(resolved);\n const tokens: Record<string, string> = {};\n\n for (const key of THEME_COLOR_KEYS) {\n const { base, contrast } = resolved.colors[key];\n tokens[`--${key}-color`] = base;\n tokens[`--${key}-rgb`] = hexToRgbTriple(base);\n tokens[`--${key}-dark`] = deriveDark(base);\n tokens[`--${key}-light`] = deriveLight(base);\n\n if (FILL_COLOR_KEYS.includes(key)) {\n tokens[`--${key}-contrast`] = contrast ?? pickContrast(base);\n }\n\n if (key === RAMP_COLOR_KEY) {\n const isPreset = base === normalizeColor(defaultTheme.colors[key]!).base;\n // The preset ramp is hand-tuned, so reuse it verbatim rather than\n // regenerating a near-identical one.\n const ramp = isPreset ? DEFAULT_PRIMARY_RAMP : buildRamp(base);\n if (!isPreset && !isRampViable(base)) {\n devWarn(\n `theme-ramp-${key}`,\n `ThemeProvider: colors.${key} (${base}) is too light or too dark to generate a usable --${key}-50…900 scale; several steps will be identical. Pick a colour with more headroom.`,\n );\n }\n for (const step of RAMP_STEPS) {\n tokens[`--${key}-${step}`] = ramp[step];\n }\n }\n }\n\n Object.assign(tokens, typographyTokens(resolved));\n return tokens;\n};\n\nconst typographyTokens = (resolved: ResolvedTheme): Record<string, string> => {\n const tokens: Record<string, string> = {};\n const { fontFamily, monoFamily, fontScale } = resolved.typography;\n tokens['--font-family-primary'] = fontFamily;\n tokens['--font-family-mono'] = monoFamily;\n for (const [name, rem] of FONT_SIZE_STEPS) {\n // Trailing zeros trimmed so 1 * 0.75 reads as `0.75rem`, not `0.750rem`.\n tokens[`--font-size-${name}`] = `${parseFloat((rem * fontScale).toFixed(4))}rem`;\n }\n return tokens;\n};\n\n/**\n * The dark scheme's colour tokens, from `resolved.dark` - by the same\n * functions that generated the preset dark palette in `_color-schemes.scss`,\n * so an unthemed dark provider reproduces it exactly and writes nothing.\n */\nconst buildDarkTokens = (resolved: ResolvedTheme): Record<string, string> => {\n const tokens: Record<string, string> = {};\n for (const key of THEME_COLOR_KEYS) {\n const { base, contrast } = resolved.dark.colors[key];\n tokens[`--${key}-color`] = base;\n tokens[`--${key}-rgb`] = hexToRgbTriple(base);\n tokens[`--${key}-dark`] = deriveDarkHover(base);\n tokens[`--${key}-light`] = deriveDarkLight(base);\n if (FILL_COLOR_KEYS.includes(key)) {\n tokens[`--${key}-contrast`] = contrast ?? pickContrast(base);\n }\n if (key === RAMP_COLOR_KEY) {\n const ramp = buildDarkRamp(base);\n for (const step of RAMP_STEPS) tokens[`--${key}-${step}`] = ramp[step];\n }\n }\n Object.assign(tokens, typographyTokens(resolved));\n return tokens;\n};\n\n/** Tokens for the preset in each scheme, used to tell which are overrides. */\nconst DEFAULT_TOKENS: Record<ResolvedColorScheme, Record<string, string>> = {\n light: buildTokens(resolveTheme(defaultTheme), 'light'),\n dark: buildTokens(resolveTheme(defaultTheme), 'dark'),\n};\n\n/**\n * Only the tokens that differ from the preset *in the same scheme*.\n *\n * This is what makes an unthemed `ThemeProvider` a no-op in both schemes: it\n * writes nothing, so `dist/index.css` stays authoritative - including its dark\n * and `system` blocks, which inline styles would otherwise override.\n */\nexport const diffFromDefault = (\n tokens: Record<string, string>,\n scheme: ResolvedColorScheme = 'light',\n): Record<string, string> => {\n const diff: Record<string, string> = {};\n for (const [name, value] of Object.entries(tokens)) {\n if (DEFAULT_TOKENS[scheme][name] !== value) diff[name] = value;\n }\n return diff;\n};\n\nconst block = (selector: string, tokens: Record<string, string>, indent = '') =>\n `${indent}${selector} {\\n` +\n Object.entries(tokens)\n .map(([name, value]) => `${indent} ${name}: ${value};`)\n .join('\\n') +\n `\\n${indent}}`;\n\n/**\n * The resolved theme as CSS: `:root` for the light scheme, plus the dark\n * scheme's colours under `[data-color-scheme='dark']` and, inside a\n * `prefers-color-scheme` query, `[data-color-scheme='system']` - the same\n * selectors `dist/index.css` uses, so the pasted theme follows the scheme\n * exactly as the preset does.\n *\n * Paste it into your own stylesheet to bake a theme in at build time - that\n * avoids the brief flash of the preset that any runtime theme has when the\n * value arrives after first paint, and needs no JavaScript at all.\n */\nexport const themeToCss = (resolved: ResolvedTheme): string => {\n const light = buildTokens(resolved, 'light');\n // Typography is scheme-independent, so it is only written once.\n const dark = Object.fromEntries(\n Object.entries(buildTokens(resolved, 'dark')).filter(([name]) => !name.startsWith('--font-')),\n );\n return [\n block(':root', light),\n block(\":root[data-color-scheme='dark']\", dark),\n `@media (prefers-color-scheme: dark) {\\n${block(\":root[data-color-scheme='system']\", dark, ' ')}\\n}`,\n ].join('\\n\\n');\n};\n","/**\n * Runtime font registration for the theme system.\n *\n * `--font-family-primary` only *names* families - it cannot make a font\n * available. Selecting \"Plus Jakarta Sans\" on a machine that doesn't have it\n * installed silently falls through to the next stack entry, which is why a\n * theme needs a way to supply the font data itself.\n *\n * ## Why this is CSP-safe\n *\n * Fonts are registered with the CSS Font Loading API from an `ArrayBuffer`:\n *\n * ```ts\n * document.fonts.add(new FontFace(family, buffer));\n * ```\n *\n * CSP's `font-src` directive governs *fetching* a font resource by URL - it is\n * what gates `@font-face { src: url(...) }` and the string form of the\n * `FontFace` constructor. The binary form performs no fetch at all, so there is\n * no request for `font-src` to check and no allowance to configure. Notably\n * this also avoids `blob:` URLs, which *would* require `font-src blob:`.\n *\n * No `<style>` element is created either, so nothing here needs a nonce - the\n * same position as the rest of the theme system.\n */\n\n/** A font registered at runtime, as listed by the editor. */\nexport interface RegisteredFont {\n /** The family name to reference in a font stack. */\n family: string;\n /** Where it came from, so the UI can distinguish uploads from built-ins. */\n source: 'upload';\n}\n\n/**\n * Turns a filename into a usable CSS family name.\n *\n * Deliberately conservative: the real family name lives in the font's internal\n * `name` table, and parsing SFNT tables to read it would be a disproportionate\n * amount of binary handling for a label. The filename is what the user\n * recognises anyway.\n */\nexport const familyNameFromFile = (filename: string): string => {\n const base = filename.replace(/\\.[^.]+$/, '');\n const cleaned = base\n // Strip the weight/style suffixes font vendors append.\n .replace(/[-_](regular|normal|book|roman)$/i, '')\n .replace(/[-_]+/g, ' ')\n // A quoted family name may contain spaces but not quotes or control chars.\n .replace(/[\"'\\\\]/g, '')\n .replace(/\\s+/g, ' ')\n .trim();\n return cleaned || 'Custom Font';\n};\n\n/** Wraps a family name for use in a CSS font stack if it needs quoting. */\nexport const quoteFamily = (family: string): string =>\n /^[a-zA-Z][a-zA-Z0-9-]*$/.test(family) ? family : `'${family}'`;\n\n/**\n * Builds a full stack from a custom family, keeping sensible fallbacks so the\n * page stays readable if the font is ever unavailable.\n */\nexport const toFontStack = (family: string, mono = false): string =>\n mono\n ? `${quoteFamily(family)}, 'SF Mono', Monaco, monospace`\n : `${quoteFamily(family)}, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif`;\n\n/** Font formats accepted for upload, as an `accept` attribute value. */\nexport const FONT_ACCEPT = '.woff2,.woff,.ttf,.otf';\n\nconst SUPPORTED_EXTENSIONS = /\\.(woff2|woff|ttf|otf)$/i;\n\nexport const isSupportedFontFile = (filename: string): boolean =>\n SUPPORTED_EXTENSIONS.test(filename);\n\n/**\n * Registers font data with the document so a theme can reference its family.\n *\n * Resolves with the family name actually registered. Rejects if the data is not\n * a font the browser can parse, or if the Font Loading API is unavailable\n * (notably during SSR, where there is no `document` to register against).\n */\nexport const registerFontFace = async (family: string, data: ArrayBuffer): Promise<string> => {\n if (typeof document === 'undefined' || !document.fonts) {\n throw new Error('registerFontFace requires a document with the CSS Font Loading API.');\n }\n\n // ArrayBuffer source - no URL is fetched, so CSP's font-src never applies.\n const face = new FontFace(family, data);\n await face.load();\n document.fonts.add(face);\n // No cache invalidation needed: only positive results are cached, and this\n // family could not have been cached positive while it was still unavailable.\n // `document.fonts.add` also fires `loadingdone`, which wakes subscribers.\n return family;\n};\n\n/** Reads a File and registers it, returning the family name it was given. */\nexport const registerFontFile = async (file: File, family?: string): Promise<string> => {\n if (!isSupportedFontFile(file.name)) {\n throw new Error(`Unsupported font format: ${file.name}. Use ${FONT_ACCEPT}.`);\n }\n const buffer = await file.arrayBuffer();\n return registerFontFace(family ?? familyNameFromFile(file.name), buffer);\n};\n\n/**\n * CSS generic families, which always resolve and must never be reported\n * missing. They also cannot be probed by the method below, since asking for\n * `monospace, monospace` measures identically to `monospace` alone.\n */\nconst GENERIC_FAMILIES = new Set([\n 'serif',\n 'sans-serif',\n 'monospace',\n 'cursive',\n 'fantasy',\n 'system-ui',\n 'ui-serif',\n 'ui-sans-serif',\n 'ui-monospace',\n 'ui-rounded',\n 'math',\n 'emoji',\n 'fangsong',\n 'inherit',\n 'initial',\n 'unset',\n]);\n\n/**\n * Mixed-width glyphs, so a real font is very unlikely to measure identically\n * to a fallback by coincidence.\n */\nconst PROBE_TEXT = 'mmmmmmmmmmlliI0OWw@';\n\n/** Two structurally different fallbacks - a font need only differ from one. */\nconst PROBE_FALLBACKS = ['monospace', 'serif'] as const;\n\n/**\n * Cached per family - **positive results only**.\n *\n * A negative answer is not stable: web fonts load asynchronously (always, with\n * `font-display: swap`), so a family probed during the first render is\n * legitimately unavailable and becomes available moments later. Caching that\n * `false` pinned the answer forever, which showed a permanent \"not installed\"\n * warning for fonts that had in fact loaded.\n *\n * A positive answer cannot go stale the same way - a loaded font is not\n * unloaded - so those are worth keeping. Re-probing the misses costs one canvas\n * measurement each.\n */\nconst availabilityCache = new Map<string, true>();\n\n/**\n * Notifies when the set of usable fonts changes, so a caller rendering an\n * availability state can re-check.\n *\n * Both signals are needed: `loadingdone` covers fonts that begin loading after\n * subscription, while `ready` covers those already in flight when the listener\n * was attached - which is the common case for a stylesheet's `@font-face`\n * rules, since they start loading before any component mounts.\n */\nexport const subscribeToFontLoads = (onChange: () => void): (() => void) => {\n if (typeof document === 'undefined' || !document.fonts) return () => {};\n\n let active = true;\n const handler = () => {\n if (active) onChange();\n };\n\n document.fonts.addEventListener('loadingdone', handler);\n void document.fonts.ready.then(handler);\n\n return () => {\n active = false;\n document.fonts.removeEventListener('loadingdone', handler);\n };\n};\n\n/**\n * Whether a font family will actually render, rather than silently falling\n * through to the next entry in the stack.\n *\n * **`document.fonts.check` cannot answer this.** Per spec it reports whether\n * the faces *in the FontFaceSet* matching the query are loaded, so with no\n * matching face it returns `true` vacuously. Verified in a real browser: it\n * answers `true` for `'Totally Not A Real Font 12345'`, and therefore for every\n * uninstalled system font too. Using it here produced a check that could never\n * fail.\n *\n * Instead the family is measured on a canvas against two fallbacks. If it\n * resolves to anything real, the text measures differently from at least one\n * fallback alone; if it does not resolve, the browser renders that fallback and\n * the widths match exactly.\n */\nexport const isFontAvailable = (family: string): boolean => {\n const name = family.trim().replace(/^['\"]|['\"]$/g, '');\n if (!name) return true;\n if (GENERIC_FAMILIES.has(name.toLowerCase())) return true;\n if (typeof document === 'undefined') return true;\n\n if (availabilityCache.get(name)) return true;\n\n try {\n const context = document.createElement('canvas').getContext('2d');\n if (!context) return true;\n\n const available = PROBE_FALLBACKS.some((fallback) => {\n context.font = `100px ${fallback}`;\n const baseline = context.measureText(PROBE_TEXT).width;\n context.font = `100px ${quoteFamily(name)}, ${fallback}`;\n // An invalid font shorthand leaves `font` untouched, which measures as\n // the baseline and correctly reports the family as unavailable.\n return Math.abs(context.measureText(PROBE_TEXT).width - baseline) > 0.5;\n });\n\n if (available) availabilityCache.set(name, true);\n return available;\n } catch {\n // Never report a font missing because probing itself failed - and don't\n // cache a failure, so a later call can still get a real answer.\n return true;\n }\n};\n\n/** Whether the first family in a stack will render. */\nexport const isFontStackAvailable = (stack: string): boolean =>\n isFontAvailable(stack.split(',')[0] ?? '');\n"]}
@@ -1,10 +1,9 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
2
2
 
3
- var _chunkUTYY35QXcjs = require('./chunk-UTYY35QX.cjs');
3
+ var _chunkRZMQCVAScjs = require('./chunk-RZMQCVAS.cjs');
4
4
 
5
5
 
6
-
7
- var _chunkENMDOQQOcjs = require('./chunk-ENMDOQQO.cjs');
6
+ var _chunkR5WI5IGRcjs = require('./chunk-R5WI5IGR.cjs');
8
7
 
9
8
  // src/components/Textarea/Textarea.component.tsx
10
9
  var _react = require('react');
@@ -49,7 +48,7 @@ var Textarea = _react.forwardRef.call(void 0,
49
48
  };
50
49
  const containerClasses = [
51
50
  "eidos-textarea-container",
52
- fullWidth && _chunkENMDOQQOcjs.fullWidthModifier.call(void 0, "eidos-textarea-container"),
51
+ fullWidth && "eidos-textarea-container--full-width",
53
52
  className
54
53
  ].filter(Boolean).join(" ");
55
54
  const wrapperClasses = [
@@ -57,7 +56,7 @@ var Textarea = _react.forwardRef.call(void 0,
57
56
  `eidos-textarea-wrapper--${variant}`,
58
57
  `eidos-textarea-wrapper--${color}`,
59
58
  `eidos-textarea-wrapper--${size}`,
60
- fullWidth && _chunkENMDOQQOcjs.fullWidthModifier.call(void 0, "eidos-textarea-wrapper"),
59
+ fullWidth && "eidos-textarea-wrapper--full-width",
61
60
  loading && "eidos-textarea-wrapper--loading",
62
61
  isFocused && "eidos-textarea-wrapper--focused",
63
62
  error && "eidos-textarea-wrapper--error"
@@ -68,7 +67,7 @@ var Textarea = _react.forwardRef.call(void 0,
68
67
  `eidos-textarea--${color}`,
69
68
  `eidos-textarea--${size}`,
70
69
  `eidos-textarea--resize-${resize}`,
71
- fullWidth && _chunkENMDOQQOcjs.fullWidthModifier.call(void 0, "eidos-textarea"),
70
+ fullWidth && "eidos-textarea--full-width",
72
71
  loading && "eidos-textarea--loading",
73
72
  error && "eidos-textarea--error"
74
73
  ].filter(Boolean).join(" ");
@@ -82,7 +81,7 @@ var Textarea = _react.forwardRef.call(void 0,
82
81
  label && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "label", { htmlFor: textareaId, className: labelClasses, children: [
83
82
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "eidos-textarea-label-text", children: label }),
84
83
  isRequired && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "eidos-textarea-required-asterisk", children: "*" }),
85
- disclaimerIcon && (disclaimerContent ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkUTYY35QXcjs.Tooltip, { message: disclaimerContent, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "eidos-textarea-disclaimer-icon", children: _chunkENMDOQQOcjs.renderIcon.call(void 0, disclaimerIcon, "eidos-textarea-disclaimer-icon-svg") }) }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "eidos-textarea-disclaimer-icon", children: _chunkENMDOQQOcjs.renderIcon.call(void 0, disclaimerIcon, "eidos-textarea-disclaimer-icon-svg") }))
84
+ disclaimerIcon && (disclaimerContent ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkRZMQCVAScjs.Tooltip, { message: disclaimerContent, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "eidos-textarea-disclaimer-icon", children: _chunkR5WI5IGRcjs.renderIcon.call(void 0, disclaimerIcon, "eidos-textarea-disclaimer-icon-svg") }) }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "eidos-textarea-disclaimer-icon", children: _chunkR5WI5IGRcjs.renderIcon.call(void 0, disclaimerIcon, "eidos-textarea-disclaimer-icon-svg") }))
86
85
  ] }),
87
86
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: wrapperClasses, children: [
88
87
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
@@ -127,4 +126,4 @@ Textarea.displayName = "Textarea";
127
126
 
128
127
 
129
128
  exports.Textarea = Textarea;
130
- //# sourceMappingURL=chunk-UUT2VEN5.cjs.map
129
+ //# sourceMappingURL=chunk-OC2OBBGM.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/home/runner/work/eidos-ui/eidos-ui/dist/chunk-OC2OBBGM.cjs","../src/components/Textarea/Textarea.component.tsx"],"names":[],"mappings":"AAAA;AACE;AACF,wDAA6B;AAC7B;AACE;AACF,wDAA6B;AAC7B;AACA;ACPA,8BAAmD;AACnD,2CAA4B;AA8GlB,+CAAA;AAzGH,IAAM,SAAA,EAAW,+BAAA;AAAA,EACtB,CACE;AAAA,IACE,QAAA,EAAU,QAAA;AAAA,IACV,MAAA,EAAQ,SAAA;AAAA,IACR,KAAA,EAAO,IAAA;AAAA,IACP,SAAA,EAAW,KAAA;AAAA,IACX,QAAA,EAAU,KAAA;AAAA,IACV,UAAA,EAAY,EAAA;AAAA,IACZ,UAAA,EAAY,KAAA;AAAA,IACZ,KAAA;AAAA,IACA,KAAA;AAAA,IACA,cAAA;AAAA,IACA,iBAAA;AAAA,IACA,QAAA;AAAA,IACA,KAAA,EAAO,CAAA;AAAA,IACP,OAAA,EAAS,UAAA;AAAA,IACT,UAAA,EAAY,KAAA;AAAA,IACZ,SAAA;AAAA,IACA,EAAA;AAAA,IACA,GAAG;AAAA,EACL,CAAA,EACA,GAAA,EAAA,GACG;AACH,IAAA,MAAM,YAAA,EAAc,0BAAA,CAAM;AAC1B,IAAA,MAAM,WAAA,EAAa,GAAA,GAAM,CAAA,SAAA,EAAY,WAAW,CAAA,CAAA;AAKnB,IAAA;AAKkB,IAAA;AAGE,IAAA;AACJ,IAAA;AACG,IAAA;AAEZ,IAAA;AAGS,IAAA;AAGvB,IAAA;AAE8C,IAAA;AAC/C,MAAA;AACW,QAAA;AAC9B,MAAA;AAC8B,sBAAA;AAChC,IAAA;AAIyB,IAAA;AACvB,MAAA;AACa,MAAA;AACb,MAAA;AAGS,IAAA;AAEY,IAAA;AACrB,MAAA;AACkC,MAAA;AACF,MAAA;AACD,MAAA;AAClB,MAAA;AACF,MAAA;AACE,MAAA;AACJ,MAAA;AAGA,IAAA;AAEa,IAAA;AACtB,MAAA;AAC0B,MAAA;AACF,MAAA;AACD,MAAA;AACS,MAAA;AACnB,MAAA;AACF,MAAA;AACF,MAAA;AAGA,IAAA;AAEU,IAAA;AACnB,MAAA;AACoB,MAAA;AACF,MAAA;AACT,MAAA;AAGA,IAAA;AAGO,IAAA;AAEL,MAAA;AACW,wBAAA;AACK,QAAA;AAGjB,QAAA;AAUN,MAAA;AAGc,sBAAA;AACd,wBAAA;AAAC,UAAA;AAAA,UAAA;AACC,YAAA;AACI,YAAA;AACO,YAAA;AACkB,YAAA;AACO,YAAA;AACpC,YAAA;AACA,YAAA;AACsB,YAAA;AAClB,YAAA;AACG,YAAA;AACS,YAAA;AACG,cAAA;AACY,8BAAA;AAC/B,YAAA;AACe,YAAA;AACK,cAAA;AACU,8BAAA;AAC9B,YAAA;AACU,YAAA;AAAA,UAAA;AACZ,QAAA;AAGE,QAAA;AAC8B,UAAA;AAAO,UAAA;AAAE,UAAA;AACvC,QAAA;AAEJ,MAAA;AAGW,MAAA;AACM,wBAAA;AACN,wBAAA;AACT,MAAA;AAEJ,IAAA;AAEJ,EAAA;AACF;AAEuB;AD9C8B;AACA;AACA;AACA","file":"/home/runner/work/eidos-ui/eidos-ui/dist/chunk-OC2OBBGM.cjs","sourcesContent":[null,"import React, { forwardRef, useState, useId } from 'react';\nimport { CircleAlert } from 'lucide-react';\nimport { renderIcon } from '../../utils';\nimport type { TextareaProps } from './Textarea.types';\nimport { Tooltip } from '../Tooltip/Tooltip.component';\n\nexport const Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(\n (\n {\n variant = 'filled',\n color = 'primary',\n size = 'md',\n disabled = false,\n loading = false,\n className = '',\n fullWidth = false,\n label,\n error,\n disclaimerIcon,\n disclaimerContent,\n required,\n rows = 4,\n resize = 'vertical',\n showCount = false,\n maxLength,\n id,\n ...textareaProps\n },\n ref,\n ) => {\n const generatedId = useId();\n const textareaId = id || `textarea-${generatedId}`;\n // Associates the visible error with the control. Without it the message\n // is just a red line of text sitting near the field - obvious to look\n // at, absent from the accessibility tree (SC 3.3.1). See the fuller\n // note in `Input`.\n const errorId = `${textareaId}-error`;\n\n // Extract defaultValue so it never reaches the native <textarea> alongside `value`.\n // Same reasoning as Input: we always set value={currentValue}, so having defaultValue\n // in the spread as well triggers React's controlled/uncontrolled warning.\n const { defaultValue, ...restTextareaProps } = textareaProps;\n\n // Determine if using controlled or uncontrolled mode\n const isControlled = restTextareaProps.value !== undefined;\n const [localValue, setLocalValue] = useState(defaultValue != null ? String(defaultValue) : '');\n const [isFocused, setIsFocused] = useState(false);\n\n const currentValue = isControlled ? restTextareaProps.value : localValue;\n\n // Label floats when the field has content (same logic as Input)\n const shouldFloatLabel = Boolean(currentValue) || Boolean(defaultValue);\n\n const isRequired =\n required || Boolean('required' in restTextareaProps && restTextareaProps.required);\n\n const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n if (!isControlled) {\n setLocalValue(e.target.value);\n }\n restTextareaProps.onChange?.(e);\n };\n\n // ── Class lists ──────────────────────────────────────────────────────────\n\n const containerClasses = [\n 'eidos-textarea-container',\n fullWidth && 'eidos-textarea-container--full-width',\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n const wrapperClasses = [\n 'eidos-textarea-wrapper',\n `eidos-textarea-wrapper--${variant}`,\n `eidos-textarea-wrapper--${color}`,\n `eidos-textarea-wrapper--${size}`,\n fullWidth && 'eidos-textarea-wrapper--full-width',\n loading && 'eidos-textarea-wrapper--loading',\n isFocused && 'eidos-textarea-wrapper--focused',\n error && 'eidos-textarea-wrapper--error',\n ]\n .filter(Boolean)\n .join(' ');\n\n const textareaClasses = [\n 'eidos-textarea',\n `eidos-textarea--${variant}`,\n `eidos-textarea--${color}`,\n `eidos-textarea--${size}`,\n `eidos-textarea--resize-${resize}`,\n fullWidth && 'eidos-textarea--full-width',\n loading && 'eidos-textarea--loading',\n error && 'eidos-textarea--error',\n ]\n .filter(Boolean)\n .join(' ');\n\n const labelClasses = [\n 'eidos-textarea-label',\n shouldFloatLabel && 'eidos-textarea-label--floating',\n disclaimerIcon && 'eidos-textarea-label--with-icon',\n error && 'eidos-textarea-label--error',\n ]\n .filter(Boolean)\n .join(' ');\n\n return (\n <div className={containerClasses}>\n {label && (\n <label htmlFor={textareaId} className={labelClasses}>\n <span className=\"eidos-textarea-label-text\">{label}</span>\n {isRequired && <span className=\"eidos-textarea-required-asterisk\">*</span>}\n {disclaimerIcon &&\n (disclaimerContent ? (\n <Tooltip message={disclaimerContent}>\n <span className=\"eidos-textarea-disclaimer-icon\">\n {renderIcon(disclaimerIcon, 'eidos-textarea-disclaimer-icon-svg')}\n </span>\n </Tooltip>\n ) : (\n <span className=\"eidos-textarea-disclaimer-icon\">\n {renderIcon(disclaimerIcon, 'eidos-textarea-disclaimer-icon-svg')}\n </span>\n ))}\n </label>\n )}\n\n <div className={wrapperClasses}>\n <textarea\n ref={ref}\n id={textareaId}\n className={textareaClasses}\n aria-invalid={error ? true : undefined}\n aria-describedby={error ? errorId : undefined}\n rows={rows}\n maxLength={maxLength}\n disabled={disabled || loading}\n {...restTextareaProps}\n value={currentValue}\n onFocus={(e) => {\n setIsFocused(true);\n restTextareaProps.onFocus?.(e);\n }}\n onBlur={(e) => {\n setIsFocused(false);\n restTextareaProps.onBlur?.(e);\n }}\n onChange={handleChange}\n />\n\n {showCount && maxLength && (\n <span className=\"eidos-textarea-count\">\n {String(currentValue ?? '').length}/{maxLength}\n </span>\n )}\n </div>\n\n {error && (\n <div id={errorId} className=\"eidos-textarea-error-message\">\n <CircleAlert className=\"eidos-textarea-error-icon\" />\n <span>{error}</span>\n </div>\n )}\n </div>\n );\n },\n);\n\nTextarea.displayName = 'Textarea';\n"]}
@@ -1,8 +1,7 @@
1
1
  import {
2
2
  devWarn,
3
- fullWidthModifier,
4
3
  useIsClient
5
- } from "./chunk-U34INRFO.js";
4
+ } from "./chunk-PP6HS4GR.js";
6
5
 
7
6
  // src/components/Dropdown/Dropdown.context.types.ts
8
7
  import { createContext } from "react";
@@ -366,7 +365,7 @@ var DropdownInternal = ({
366
365
  {
367
366
  ref: triggerRef,
368
367
  onClick: handleTriggerClick,
369
- className: `eidos-dropdown-trigger ${fullWidth ? fullWidthModifier("eidos-dropdown-trigger") : ""} ${triggerClassName}`,
368
+ className: `eidos-dropdown-trigger ${fullWidth ? "eidos-dropdown-trigger--full-width" : ""} ${triggerClassName}`,
370
369
  children: trigger
371
370
  }
372
371
  ),
@@ -404,4 +403,4 @@ export {
404
403
  useDropdownContext,
405
404
  Dropdown
406
405
  };
407
- //# sourceMappingURL=chunk-3X6QVHTD.js.map
406
+ //# sourceMappingURL=chunk-OERK3T7E.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/Dropdown/Dropdown.context.types.ts","../src/components/Dropdown/Dropdown.context.tsx","../src/components/Dropdown/Dropdown.hooks.ts","../src/components/Dropdown/Dropdown.component.tsx"],"sourcesContent":["import { createContext } from 'react';\n\nexport interface DropdownContextValue {\n level: number;\n}\n\nexport const DropdownContext = createContext<DropdownContextValue>({ level: 0 });\n","import React from 'react';\nimport { DropdownContext } from './Dropdown.context.types';\n\nexport const DropdownProvider: React.FC<{ children: React.ReactNode; level?: number }> = ({\n children,\n level = 0,\n}) => {\n return <DropdownContext.Provider value={{ level }}>{children}</DropdownContext.Provider>;\n};\n","import { useContext } from 'react';\nimport { DropdownContext } from './Dropdown.context.types';\n\nexport const useDropdownContext = () => {\n return useContext(DropdownContext);\n};\n","import React, { useState, useRef, useCallback, useEffect } from 'react';\nimport { createPortal } from 'react-dom';\nimport { devWarn, useIsClient } from '../../utils';\nimport type { DropdownProps, DropdownState } from './Dropdown.types';\nimport { DropdownProvider } from './Dropdown.context';\nimport { useDropdownContext } from './Dropdown.hooks';\n\nconst DropdownInternal: React.FC<DropdownProps> = ({\n trigger,\n content,\n placement: preferredPlacement = 'bottom',\n align = 'start',\n delay = 0,\n disabled = false,\n defaultOpen = false,\n open,\n onOpenChange,\n triggerClassName = '',\n contentClassName = '',\n role,\n closeOnClickOutside = true,\n closeOnEscape = true,\n minWidth,\n maxWidth,\n minHeight,\n maxHeight,\n autoWidth = true,\n fullWidth = false,\n triggerRef: externalTriggerRef,\n isNested = false,\n dropdownLevel,\n dropdownGroup,\n}) => {\n const context = useDropdownContext();\n const actualLevel = dropdownLevel !== undefined ? dropdownLevel : context.level;\n // `defaultOpen` makes the portal reachable on the first render, which cannot\n // happen on a server - see `useIsClient`.\n const isClient = useIsClient();\n const [dropdownState, setDropdownState] = useState<DropdownState>({\n isVisible: defaultOpen,\n isPositioned: false,\n position: { top: 0, left: 0, placement: preferredPlacement },\n });\n\n // ── Controlled / uncontrolled open state ──────────────────────────────────\n //\n // `dropdownState.isVisible` stays the *uncontrolled* value and is kept in\n // step even while controlled, so removing `open` later leaves coherent state.\n // Everything downstream reads `isVisible` below, never the field directly.\n //\n // `DropdownState` is exported from the package root, so it keeps its shape:\n // splitting `isVisible` out of it would be a breaking type change for a\n // consumer who imports it, in exchange for nothing a reader of this file\n // needs.\n const isControlled = open !== undefined;\n const isVisible = isControlled ? open : dropdownState.isVisible;\n\n const wasControlled = useRef(isControlled);\n if (wasControlled.current !== isControlled) {\n devWarn(\n 'dropdown-controlled-switch',\n 'Dropdown: `open` switched between controlled and uncontrolled. Pick one for the lifetime of the component - the dropdown keeps its own state as a fallback, so switching makes it jump to whatever that happens to be.',\n );\n wasControlled.current = isControlled;\n }\n\n /**\n * The single place the open state changes. Every route - trigger click,\n * click-outside, Escape, a group sibling, the `delay` timer - goes through\n * here, so a controlled consumer sees all of them and cannot desync.\n */\n const setOpen = useCallback(\n (next: boolean) => {\n setDropdownState((prev) => ({ ...prev, isVisible: next, isPositioned: false }));\n onOpenChange?.(next);\n },\n [onOpenChange],\n );\n\n // A controlled caller can flip `open` without going through `setOpen`, which\n // would leave `isPositioned` true from the previous open and paint the panel\n // at its old coordinates for a frame. Re-arm the positioning pass from the\n // transition itself.\n useEffect(() => {\n if (!isVisible) {\n setDropdownState((prev) => (prev.isPositioned ? { ...prev, isPositioned: false } : prev));\n }\n }, [isVisible]);\n\n // A pending `delay` timer outlives a controlled close otherwise, and reopens\n // the panel a moment after the consumer closed it.\n useEffect(() => {\n if (!isVisible && timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n timeoutRef.current = undefined;\n }\n }, [isVisible]);\n const triggerRef = useRef<HTMLDivElement>(null);\n const contentRef = useRef<HTMLDivElement>(null);\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n const animationFrameRef = useRef<number | undefined>(undefined);\n const isScrollingRef = useRef(false);\n\n // The element to actually measure/anchor against. When a consumer passes\n // `triggerRef`, that's an explicit statement of \"this is what I want the\n // dropdown positioned relative to\" - it must win over the internal wrapper\n // div, not just inform sizing. Consumers occasionally need `trigger` to be\n // a small anchor node (e.g. a 0-height span) sitting inside a larger,\n // variable-content field (chips, wrapped text); anchoring position to the\n // wrapper instead of that field silently drifts as soon as the field's\n // internal layout changes, since the wrapper only ever contains `trigger`\n // itself, never the field around it.\n const getTriggerElement = useCallback(\n (): HTMLElement | null => externalTriggerRef?.current ?? triggerRef.current,\n [externalTriggerRef],\n );\n\n const calculateDynamicSizing = useCallback(\n // Only the width is read, so the parameter is the narrowest shape that\n // satisfies it rather than a `DOMRect`. The caller used to fall back to\n // `new DOMRect()`, which is a browser-only global evaluated *during\n // render* - it was the first thing to throw when an open dropdown was\n // server-rendered, before `document.body` ever got a chance to.\n (triggerRect: { width: number } | null) => {\n // Shrink the panel to its content by default. This prevents the\n // position:fixed element from expanding to viewport width when children\n // use `width:100%` or `flex:1`. `minWidth` (set below) still wins when\n // the trigger is wider than the content, as CSS min-width overrides width.\n const styles: Record<string, string | number> = { width: 'max-content' };\n\n if (autoWidth && triggerRect && (externalTriggerRef?.current || triggerRef.current)) {\n const triggerWidth = triggerRect.width;\n styles.minWidth = triggerWidth;\n }\n\n if (minWidth !== undefined) {\n styles.minWidth = typeof minWidth === 'number' ? `${minWidth}px` : minWidth;\n }\n if (maxWidth !== undefined) {\n if (maxWidth === 'auto') {\n styles.maxWidth = 'none';\n } else {\n styles.maxWidth = typeof maxWidth === 'number' ? `${maxWidth}px` : maxWidth;\n }\n }\n if (minHeight !== undefined) {\n styles.minHeight = typeof minHeight === 'number' ? `${minHeight}px` : minHeight;\n }\n if (maxHeight !== undefined) {\n if (maxHeight === 'auto') {\n styles.maxHeight = 'none';\n } else {\n styles.maxHeight = typeof maxHeight === 'number' ? `${maxHeight}px` : maxHeight;\n }\n }\n\n const hasHeightConstraint = minHeight !== undefined || maxHeight !== undefined;\n if (hasHeightConstraint) {\n styles.overflowY = 'auto';\n } else {\n styles.overflowY = 'visible';\n }\n\n return styles;\n },\n [autoWidth, externalTriggerRef, minWidth, maxWidth, minHeight, maxHeight],\n );\n\n const calculateOptimalPosition = useCallback(\n (triggerRect: DOMRect, contentRect: DOMRect) => {\n const viewportWidth = window.innerWidth;\n const viewportHeight = window.innerHeight;\n const gap = 8;\n\n let placement: 'top' | 'bottom' | 'left' | 'right' = preferredPlacement;\n let top = 0;\n let left = 0;\n\n // Helpers for cross-axis alignment\n const alignedLeft = (() => {\n switch (align) {\n case 'end':\n return triggerRect.right - contentRect.width;\n case 'center':\n return triggerRect.left + (triggerRect.width - contentRect.width) / 2;\n default:\n return triggerRect.left; // \"start\"\n }\n })();\n const alignedTop = (() => {\n switch (align) {\n case 'end':\n return triggerRect.bottom - contentRect.height;\n case 'center':\n return triggerRect.top + (triggerRect.height - contentRect.height) / 2;\n default:\n return triggerRect.top; // \"start\"\n }\n })();\n\n switch (preferredPlacement) {\n case 'top':\n top = triggerRect.top - contentRect.height - gap;\n left = alignedLeft;\n break;\n case 'bottom':\n top = triggerRect.bottom + gap;\n left = alignedLeft;\n break;\n case 'left':\n top = alignedTop;\n left = triggerRect.left - contentRect.width - gap;\n break;\n case 'right':\n top = alignedTop;\n left = triggerRect.right + gap;\n break;\n }\n\n if (placement === 'top' && top < gap) {\n placement = 'bottom';\n top = triggerRect.bottom + gap;\n } else if (placement === 'bottom' && top + contentRect.height > viewportHeight - gap) {\n placement = 'top';\n top = triggerRect.top - contentRect.height - gap;\n } else if (placement === 'left' && left < gap) {\n placement = 'right';\n left = triggerRect.right + gap;\n } else if (placement === 'right' && left + contentRect.width > viewportWidth - gap) {\n placement = 'left';\n left = triggerRect.left - contentRect.width - gap;\n }\n\n // Always clamp to both viewport edges - not just the near one - regardless\n // of whether an explicit min/max size was passed. `autoWidth` consumers\n // (Combobox, Select, TagInput suggestions, Menu, ...) never set\n // minWidth/maxWidth, so gating this on those props left the far edge\n // (right/bottom) completely unclamped and let content overflow the\n // viewport whenever it rendered wider/taller than its trigger.\n top = Math.max(gap, Math.min(top, viewportHeight - contentRect.height - gap));\n\n left = Math.max(gap, Math.min(left, viewportWidth - contentRect.width - gap));\n\n return { top, left, placement };\n },\n [preferredPlacement, align],\n );\n\n const handleScroll = useCallback(() => {\n if (!isVisible || !dropdownState.isPositioned || isScrollingRef.current) return;\n\n isScrollingRef.current = true;\n\n animationFrameRef.current = requestAnimationFrame(() => {\n const triggerElement = getTriggerElement();\n if (triggerElement && contentRef.current) {\n const triggerRect = triggerElement.getBoundingClientRect();\n const contentRect = contentRef.current.getBoundingClientRect();\n\n const { top, left, placement } = calculateOptimalPosition(triggerRect, contentRect);\n\n setDropdownState((prev) => ({\n ...prev,\n position: { top, left, placement },\n }));\n }\n\n isScrollingRef.current = false;\n });\n }, [isVisible, dropdownState.isPositioned, calculateOptimalPosition, getTriggerElement]);\n\n const handleTriggerClick = useCallback(() => {\n if (disabled) return;\n\n if (isVisible) {\n setOpen(false);\n } else {\n if (dropdownGroup) {\n const siblingDropdowns = document.querySelectorAll(\n `[data-dropdown-group=\"${dropdownGroup}\"][data-dropdown-content]`,\n );\n siblingDropdowns.forEach((dropdown) => {\n const dropdownElement = dropdown as HTMLElement;\n\n dropdownElement.dispatchEvent(new CustomEvent('closeSibling'));\n });\n }\n\n if (delay > 0) {\n timeoutRef.current = setTimeout(() => setOpen(true), delay);\n } else {\n setOpen(true);\n }\n }\n }, [disabled, isVisible, delay, dropdownGroup, setOpen]);\n\n useEffect(() => {\n const handleCloseSibling = () => {\n if (isVisible) setOpen(false);\n };\n\n const currentContentRef = contentRef.current;\n if (currentContentRef) {\n currentContentRef.addEventListener('closeSibling', handleCloseSibling);\n }\n\n return () => {\n if (currentContentRef) {\n currentContentRef.removeEventListener('closeSibling', handleCloseSibling);\n }\n };\n }, [isVisible, setOpen]);\n\n const handleClickOutside = useCallback(\n (event: MouseEvent) => {\n if (!closeOnClickOutside || !isVisible) return;\n\n const target = event.target as Node;\n\n if (contentRef.current?.contains(target)) {\n return;\n }\n\n if (getTriggerElement()?.contains(target)) {\n return;\n }\n\n const allDropdowns = document.querySelectorAll('[data-dropdown-content]');\n for (const dropdown of allDropdowns) {\n if (dropdown === contentRef.current) continue;\n\n if (dropdown.contains(target)) {\n const clickedDropdownLevel = parseInt(\n dropdown.getAttribute('data-dropdown-level') || '0',\n );\n\n if (clickedDropdownLevel > actualLevel) {\n return;\n }\n }\n }\n\n setOpen(false);\n },\n [closeOnClickOutside, isVisible, actualLevel, getTriggerElement, setOpen],\n );\n\n const handleEscapeKey = useCallback(\n (event: KeyboardEvent) => {\n if (closeOnEscape && event.key === 'Escape' && isVisible) {\n setOpen(false);\n }\n },\n [closeOnEscape, isVisible, setOpen],\n );\n\n useEffect(() => {\n const triggerElement = getTriggerElement();\n if (isVisible && !dropdownState.isPositioned && contentRef.current && triggerElement) {\n const triggerRect = triggerElement.getBoundingClientRect();\n const contentRect = contentRef.current.getBoundingClientRect();\n\n const { top, left, placement } = calculateOptimalPosition(triggerRect, contentRect);\n\n setDropdownState((prev) => ({\n ...prev,\n position: { top, left, placement },\n isPositioned: true,\n }));\n }\n }, [\n isVisible,\n dropdownState.isPositioned,\n calculateOptimalPosition,\n getTriggerElement,\n // Load-bearing, not incidental. With `defaultOpen` the panel is \"visible\"\n // from the first render, but the portal is deferred one render for SSR\n // safety - so this effect's first run finds `contentRef.current` still\n // null, measures nothing, and without `isClient` in the deps it would never\n // run again. The panel then stays `visibility: hidden` forever: mounted,\n // unpositioned, invisible. Caught by `OpensOnMountWithDefaultOpen`.\n isClient,\n ]);\n\n useEffect(() => {\n const handleResize = () => {\n const triggerElement = getTriggerElement();\n if (isVisible && dropdownState.isPositioned && contentRef.current && triggerElement) {\n const triggerRect = triggerElement.getBoundingClientRect();\n const contentRect = contentRef.current.getBoundingClientRect();\n\n const { top, left, placement } = calculateOptimalPosition(triggerRect, contentRect);\n\n setDropdownState((prev) => ({\n ...prev,\n position: { top, left, placement },\n }));\n }\n };\n\n window.addEventListener('resize', handleResize);\n return () => window.removeEventListener('resize', handleResize);\n }, [isVisible, dropdownState.isPositioned, calculateOptimalPosition, getTriggerElement]);\n\n useEffect(() => {\n if (isVisible) {\n // Capture phase on `document`, which is the only way to see scrolling in\n // an arbitrary ancestor: `scroll` does not bubble from an element, so the\n // previous listeners on `window` and `document.body` only ever fired for\n // the page itself. Any other scroll container - `PageLayout`'s\n // `&__content` is the layout's scrollport, so this is every dropdown\n // inside it - moved the trigger while the portaled, `position: fixed`\n // content stayed at its original viewport coordinates.\n document.addEventListener('scroll', handleScroll, { capture: true, passive: true });\n }\n\n return () => {\n document.removeEventListener('scroll', handleScroll, { capture: true });\n };\n }, [isVisible, handleScroll]);\n\n useEffect(() => {\n if (isVisible) {\n document.addEventListener('mousedown', handleClickOutside);\n document.addEventListener('keydown', handleEscapeKey);\n }\n\n return () => {\n document.removeEventListener('mousedown', handleClickOutside);\n document.removeEventListener('keydown', handleEscapeKey);\n };\n }, [isVisible, handleClickOutside, handleEscapeKey]);\n\n useEffect(() => {\n return () => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n if (animationFrameRef.current) {\n cancelAnimationFrame(animationFrameRef.current);\n }\n };\n }, []);\n\n return (\n <>\n {/*\n A positioning and click-capturing wrapper, and nothing more - it\n deliberately carries no `role` and no `tabIndex`.\n\n It used to be `role=\"button\" tabIndex={-1}`, which was wrong in both\n directions at once. `tabIndex={-1}` with no key handler meant the\n wrapper was never keyboard-operable, so the button role it advertised\n could not be activated by anyone using a keyboard - it promised a\n control that did not exist. Meanwhile, because `trigger` is virtually\n always a real control (Select and Combobox pass an `<input>`, Menu and\n SplitButton a `<button>`, ...), the role wrapped an interactive element\n in another interactive element: invalid ARIA, flagged by axe as\n `nested-interactive`, and announced by screen readers as a button\n inside a button. One attribute did this across every component built\n on Dropdown - Select, Combobox, Menu, Popover, ContextMenu,\n ColorPicker and TagInput - 212 violations in a single axe run.\n\n Semantics belong to whatever is passed as `trigger`, which is the only\n element that can actually own them. A consumer passing a\n non-interactive node should pass a `<button>` instead; it was never\n keyboard-accessible under the old markup either.\n */}\n <div\n ref={triggerRef}\n onClick={handleTriggerClick}\n className={`eidos-dropdown-trigger ${fullWidth ? 'eidos-dropdown-trigger--full-width' : ''} ${triggerClassName}`}\n >\n {trigger}\n </div>\n {isClient &&\n isVisible &&\n createPortal(\n <div\n ref={contentRef}\n data-dropdown-content\n data-dropdown-level={actualLevel}\n data-dropdown-group={dropdownGroup || ''}\n className={`eidos-dropdown-content eidos-dropdown-content--${dropdownState.position.placement} ${isNested ? 'eidos-dropdown-content--nested' : ''} ${dropdownState.isPositioned ? 'eidos-dropdown-content--positioned' : ''} ${contentClassName || ''}`}\n style={{\n top: dropdownState.position.top,\n left: dropdownState.position.left,\n ...calculateDynamicSizing(getTriggerElement()?.getBoundingClientRect() ?? null),\n }}\n // No default role: see the `role` prop's note in `Dropdown.types`.\n // This was `role=\"menu\"` unconditionally, which made a menu out of\n // every `Select` listbox, date picker and toolbar panel in the\n // library.\n role={role}\n >\n {content}\n </div>,\n document.body,\n )}\n </>\n );\n};\n\nexport const Dropdown: React.FC<DropdownProps> = (props) => {\n const context = useDropdownContext();\n const nextLevel = props.dropdownLevel !== undefined ? props.dropdownLevel : context.level + 1;\n\n return (\n <DropdownProvider level={nextLevel}>\n <DropdownInternal {...props} />\n </DropdownProvider>\n );\n};\n\nDropdown.displayName = 'Dropdown';\n"],"mappings":"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","names":["jsx"]}
@@ -1,8 +1,7 @@
1
1
  import {
2
- devWarn,
3
2
  useDialogFocus,
4
3
  useIsClient
5
- } from "./chunk-U34INRFO.js";
4
+ } from "./chunk-PP6HS4GR.js";
6
5
 
7
6
  // src/components/Popover/Popover.component.tsx
8
7
  import React, { useState, useRef, useCallback, useEffect, useId } from "react";
@@ -18,7 +17,6 @@ var Popover = ({
18
17
  closeOnClickOutside = true,
19
18
  closeOnEscape = true,
20
19
  disabled = false,
21
- isOpen,
22
20
  open: openProp,
23
21
  defaultOpen,
24
22
  onOpenChange,
@@ -27,13 +25,7 @@ var Popover = ({
27
25
  contentClassName
28
26
  }) => {
29
27
  const isClient = useIsClient();
30
- if (isOpen !== void 0) {
31
- devWarn(
32
- "popover-is-open",
33
- "Popover: `isOpen` is deprecated - pass `open` instead, the name `Dropdown` and `CommandPalette` use."
34
- );
35
- }
36
- const controlledOpen = openProp ?? isOpen;
28
+ const controlledOpen = openProp;
37
29
  const isControlled = controlledOpen !== void 0;
38
30
  const [localOpen, setLocalOpen] = useState(defaultOpen ?? false);
39
31
  const isVisible = isControlled ? controlledOpen : localOpen;
@@ -275,4 +267,4 @@ Popover.displayName = "Popover";
275
267
  export {
276
268
  Popover
277
269
  };
278
- //# sourceMappingURL=chunk-ZJWQPZ7E.js.map
270
+ //# sourceMappingURL=chunk-OQWG7NLI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/Popover/Popover.component.tsx"],"sourcesContent":["import React, { useState, useRef, useCallback, useEffect, useId } from 'react';\nimport { createPortal } from 'react-dom';\nimport { X } from 'lucide-react';\nimport type { PopoverProps, PopoverState, PopoverPlacement } from './Popover.types';\nimport { useDialogFocus, useIsClient } from '../../utils';\n\nexport const Popover: React.FC<PopoverProps> = ({\n trigger,\n children,\n title,\n placement: preferredPlacement = 'bottom',\n showCloseButton = false,\n closeOnClickOutside = true,\n closeOnEscape = true,\n disabled = false,\n open: openProp,\n defaultOpen,\n onOpenChange,\n maxWidth = 320,\n className,\n contentClassName,\n}) => {\n // `open`/`defaultOpen` make the portal reachable on the first render,\n // which cannot happen on a server - see `useIsClient`.\n const isClient = useIsClient();\n\n // ── Controlled / uncontrolled bridge ──────────────────────────────────────\n //\n // `open` matches `Dropdown` and `CommandPalette`. The original spelling,\n // `isOpen`, was deprecated in 3.8 and removed in 4.0.\n const controlledOpen = openProp;\n const isControlled = controlledOpen !== undefined;\n const [localOpen, setLocalOpen] = useState(defaultOpen ?? false);\n const isVisible = isControlled ? controlledOpen! : localOpen;\n\n // ── Positioning state ─────────────────────────────────────────────────────\n const [popoverState, setPopoverState] = useState<PopoverState>({\n isVisible: false,\n isPositioned: false,\n position: { top: 0, left: 0, placement: preferredPlacement },\n });\n\n // Names the dialog by pointing at the rendered title, the same way `Modal`\n // and `Drawer` do. This was an `aria-label={title ?? 'Popover'}`, which\n // both duplicated the visible text into a second, invisible copy and hard\n // limited `title` to a string - `aria-label` takes only a string, so a\n // `ReactNode` title would have been stringified to \"[object Object]\" and\n // silently destroyed the accessible name.\n const titleId = useId();\n\n // ── Refs ──────────────────────────────────────────────────────────────────\n const triggerRef = useRef<HTMLDivElement>(null);\n const contentRef = useRef<HTMLDivElement>(null);\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n const animationFrameRef = useRef<number | undefined>(undefined);\n const isScrollingRef = useRef(false);\n\n // ── Open / close helpers ──────────────────────────────────────────────────\n const open = useCallback(() => {\n if (disabled) return;\n if (!isControlled) setLocalOpen(true);\n onOpenChange?.(true);\n }, [disabled, isControlled, onOpenChange]);\n\n const close = useCallback(() => {\n if (!isControlled) setLocalOpen(false);\n onOpenChange?.(false);\n }, [isControlled, onOpenChange]);\n\n const toggle = useCallback(() => {\n if (isVisible) {\n close();\n } else {\n open();\n }\n }, [isVisible, open, close]);\n\n // ── Positioning calculation ───────────────────────────────────────────────\n const calculateOptimalPosition = useCallback(\n (triggerRect: DOMRect, contentRect: DOMRect) => {\n const viewportWidth = window.innerWidth;\n const viewportHeight = window.innerHeight;\n const gap = 8;\n\n let placement: PopoverPlacement = preferredPlacement;\n let top = 0;\n let left = 0;\n\n switch (preferredPlacement) {\n case 'top':\n top = triggerRect.top - contentRect.height - gap;\n left = triggerRect.left + triggerRect.width / 2 - contentRect.width / 2;\n break;\n case 'bottom':\n top = triggerRect.bottom + gap;\n left = triggerRect.left + triggerRect.width / 2 - contentRect.width / 2;\n break;\n case 'left':\n top = triggerRect.top + triggerRect.height / 2 - contentRect.height / 2;\n left = triggerRect.left - contentRect.width - gap;\n break;\n case 'right':\n top = triggerRect.top + triggerRect.height / 2 - contentRect.height / 2;\n left = triggerRect.right + gap;\n break;\n }\n\n // Flip if it doesn't fit in the preferred direction\n if (placement === 'top' && top < gap) {\n placement = 'bottom';\n top = triggerRect.bottom + gap;\n left = triggerRect.left + triggerRect.width / 2 - contentRect.width / 2;\n } else if (placement === 'bottom' && top + contentRect.height > viewportHeight - gap) {\n placement = 'top';\n top = triggerRect.top - contentRect.height - gap;\n left = triggerRect.left + triggerRect.width / 2 - contentRect.width / 2;\n } else if (placement === 'left' && left < gap) {\n placement = 'right';\n top = triggerRect.top + triggerRect.height / 2 - contentRect.height / 2;\n left = triggerRect.right + gap;\n } else if (placement === 'right' && left + contentRect.width > viewportWidth - gap) {\n placement = 'left';\n top = triggerRect.top + triggerRect.height / 2 - contentRect.height / 2;\n left = triggerRect.left - contentRect.width - gap;\n }\n\n // Clamp to viewport\n top = Math.max(gap, Math.min(top, viewportHeight - contentRect.height - gap));\n left = Math.max(gap, Math.min(left, viewportWidth - contentRect.width - gap));\n\n return { top, left, placement };\n },\n [preferredPlacement],\n );\n\n // ── Sync isVisible → popoverState ─────────────────────────────────────────\n useEffect(() => {\n if (isVisible) {\n setPopoverState((prev) => ({ ...prev, isVisible: true, isPositioned: false }));\n } else {\n setPopoverState((prev) => ({ ...prev, isVisible: false, isPositioned: false }));\n }\n }, [isVisible]);\n\n // ── Two-pass positioning (Pass 2: measure then commit) ────────────────────\n useEffect(() => {\n if (\n popoverState.isVisible &&\n !popoverState.isPositioned &&\n contentRef.current &&\n triggerRef.current\n ) {\n const triggerRect = triggerRef.current.getBoundingClientRect();\n const contentRect = contentRef.current.getBoundingClientRect();\n\n const { top, left, placement } = calculateOptimalPosition(triggerRect, contentRect);\n\n setPopoverState((prev) => ({\n ...prev,\n position: { top, left, placement },\n isPositioned: true,\n }));\n }\n // `isClient` for the same reason as `Dropdown`: with `defaultOpen` the\n // portal arrives one render after this effect first runs, and without it in\n // the deps the panel is never measured and never becomes visible.\n }, [popoverState.isVisible, popoverState.isPositioned, calculateOptimalPosition, isClient]);\n\n // ── Scroll repositioning ─────────────────────────────────────────────────\n const handleScroll = useCallback(() => {\n if (!popoverState.isVisible || !popoverState.isPositioned || isScrollingRef.current) return;\n\n isScrollingRef.current = true;\n\n animationFrameRef.current = requestAnimationFrame(() => {\n if (triggerRef.current && contentRef.current) {\n const triggerRect = triggerRef.current.getBoundingClientRect();\n const contentRect = contentRef.current.getBoundingClientRect();\n\n const { top, left, placement } = calculateOptimalPosition(triggerRect, contentRect);\n\n setPopoverState((prev) => ({\n ...prev,\n position: { top, left, placement },\n }));\n }\n\n isScrollingRef.current = false;\n });\n }, [popoverState.isVisible, popoverState.isPositioned, calculateOptimalPosition]);\n\n // ── Resize repositioning ──────────────────────────────────────────────────\n useEffect(() => {\n const handleResize = () => {\n if (\n popoverState.isVisible &&\n popoverState.isPositioned &&\n contentRef.current &&\n triggerRef.current\n ) {\n const triggerRect = triggerRef.current.getBoundingClientRect();\n const contentRect = contentRef.current.getBoundingClientRect();\n\n const { top, left, placement } = calculateOptimalPosition(triggerRect, contentRect);\n\n setPopoverState((prev) => ({\n ...prev,\n position: { top, left, placement },\n }));\n }\n };\n\n window.addEventListener('resize', handleResize);\n return () => window.removeEventListener('resize', handleResize);\n }, [popoverState.isVisible, popoverState.isPositioned, calculateOptimalPosition]);\n\n // ── Scroll listener registration ─────────────────────────────────────────\n useEffect(() => {\n if (popoverState.isVisible) {\n // Capture phase on `document` - see the note in `Dropdown`. `scroll` does\n // not bubble, so listeners on `window`/`document.body` miss every\n // ancestor scroll container and the portaled panel detaches from its\n // trigger.\n document.addEventListener('scroll', handleScroll, { capture: true, passive: true });\n }\n\n return () => {\n document.removeEventListener('scroll', handleScroll, { capture: true });\n };\n }, [popoverState.isVisible, handleScroll]);\n\n // ── Click-outside handler ─────────────────────────────────────────────────\n const handleClickOutside = useCallback(\n (event: MouseEvent) => {\n if (!closeOnClickOutside || !popoverState.isVisible) return;\n\n const target = event.target as Node;\n\n if (contentRef.current?.contains(target) || triggerRef.current?.contains(target)) {\n return;\n }\n\n close();\n },\n [closeOnClickOutside, popoverState.isVisible, close],\n );\n\n // ── Escape key handler ────────────────────────────────────────────────────\n const handleEscapeKey = useCallback(\n (event: KeyboardEvent) => {\n if (closeOnEscape && event.key === 'Escape' && popoverState.isVisible) {\n close();\n }\n },\n [closeOnEscape, popoverState.isVisible, close],\n );\n\n // ── Register global event listeners ──────────────────────────────────────\n useEffect(() => {\n if (popoverState.isVisible) {\n document.addEventListener('mousedown', handleClickOutside);\n document.addEventListener('keydown', handleEscapeKey);\n }\n\n return () => {\n document.removeEventListener('mousedown', handleClickOutside);\n document.removeEventListener('keydown', handleEscapeKey);\n };\n }, [popoverState.isVisible, handleClickOutside, handleEscapeKey]);\n\n // ── Cleanup on unmount ────────────────────────────────────────────────────\n useEffect(() => {\n const timeoutId = timeoutRef.current;\n const animationFrameId = animationFrameRef.current;\n return () => {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n if (animationFrameId) {\n cancelAnimationFrame(animationFrameId);\n }\n };\n }, []);\n\n // Non-modal focus handling: move focus into the panel and return it to the\n // trigger on close, but leave Tab free.\n //\n // `trapTab: false` because this dialog is honestly `aria-modal=\"false\"` -\n // the rest of the page stays available, so confining Tab would strand the\n // user. Moving focus in is still required: the panel is portaled to\n // `document.body`, so Tab from the trigger continues into whatever follows\n // it in the page and the panel's own controls cannot be reached at all.\n //\n // Keyed to `isPositioned`, not `isVisible`: the panel renders off-screen\n // for one frame while its placement is measured, and focusing it in that\n // state scrolls the page to wherever it was parked.\n useDialogFocus(popoverState.isVisible && popoverState.isPositioned, contentRef, {\n trapTab: false,\n });\n\n // ── Render ────────────────────────────────────────────────────────────────\n return (\n <>\n {/* Trigger wrapper.\n\n The wrapper carries no ARIA. It had `aria-expanded` and\n `aria-haspopup` while having no role, which is invalid - both need\n a role that supports them, and adding `role=\"button\"` here would be\n worse still, since the trigger inside is usually a real button\n (that is the `nested-interactive` shape already fixed on\n `Dropdown`).\n\n Instead the state is cloned onto the trigger element, which is the\n thing a user actually activates. Guarded by `isValidElement`\n because `trigger` is typed as `ReactNode` and may be a bare string,\n in which case there is nothing to annotate and the wrapper stays\n exactly as it was. */}\n <div\n ref={triggerRef}\n className={['eidos-popover-trigger', className].filter(Boolean).join(' ')}\n onClick={toggle}\n >\n {React.isValidElement(trigger)\n ? React.cloneElement(trigger as React.ReactElement<Record<string, unknown>>, {\n 'aria-expanded': popoverState.isVisible,\n 'aria-haspopup': 'dialog',\n })\n : trigger}\n </div>\n\n {/* Portal: floating panel */}\n {isClient &&\n popoverState.isVisible &&\n createPortal(\n <div\n ref={contentRef}\n role=\"dialog\"\n aria-modal=\"false\"\n aria-labelledby={title ? titleId : undefined}\n // Only the untitled case still needs a literal label - there is\n // no visible text to point at.\n aria-label={title ? undefined : 'Popover'}\n className={[\n 'eidos-popover-content',\n `eidos-popover-content--${popoverState.position.placement}`,\n popoverState.isPositioned ? 'eidos-popover-content--visible' : '',\n contentClassName,\n ]\n .filter(Boolean)\n .join(' ')}\n style={{\n top: popoverState.position.top,\n left: popoverState.position.left,\n maxWidth: maxWidth,\n }}\n >\n {(title || showCloseButton) && (\n <div className=\"eidos-popover-header\">\n {title && (\n <span id={titleId} className=\"eidos-popover-title\">\n {title}\n </span>\n )}\n {showCloseButton && (\n <button\n type=\"button\"\n className=\"eidos-popover-close\"\n onClick={close}\n aria-label=\"Close popover\"\n >\n <X aria-hidden=\"true\" />\n </button>\n )}\n </div>\n )}\n <div className=\"eidos-popover-body\">{children}</div>\n </div>,\n document.body,\n )}\n </>\n );\n};\n\nPopover.displayName = 'Popover';\n"],"mappings":";;;;;;AAAA,OAAO,SAAS,UAAU,QAAQ,aAAa,WAAW,aAAa;AACvE,SAAS,oBAAoB;AAC7B,SAAS,SAAS;AA4Sd,mBAeE,KAwCQ,YAvDV;AAxSG,IAAM,UAAkC,CAAC;AAAA,EAC9C;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAW,qBAAqB;AAAA,EAChC,kBAAkB;AAAA,EAClB,sBAAsB;AAAA,EACtB,gBAAgB;AAAA,EAChB,WAAW;AAAA,EACX,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX;AAAA,EACA;AACF,MAAM;AAGJ,QAAM,WAAW,YAAY;AAM7B,QAAM,iBAAiB;AACvB,QAAM,eAAe,mBAAmB;AACxC,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,eAAe,KAAK;AAC/D,QAAM,YAAY,eAAe,iBAAkB;AAGnD,QAAM,CAAC,cAAc,eAAe,IAAI,SAAuB;AAAA,IAC7D,WAAW;AAAA,IACX,cAAc;AAAA,IACd,UAAU,EAAE,KAAK,GAAG,MAAM,GAAG,WAAW,mBAAmB;AAAA,EAC7D,CAAC;AAQD,QAAM,UAAU,MAAM;AAGtB,QAAM,aAAa,OAAuB,IAAI;AAC9C,QAAM,aAAa,OAAuB,IAAI;AAC9C,QAAM,aAAa,OAAkD,MAAS;AAC9E,QAAM,oBAAoB,OAA2B,MAAS;AAC9D,QAAM,iBAAiB,OAAO,KAAK;AAGnC,QAAM,OAAO,YAAY,MAAM;AAC7B,QAAI,SAAU;AACd,QAAI,CAAC,aAAc,cAAa,IAAI;AACpC,mBAAe,IAAI;AAAA,EACrB,GAAG,CAAC,UAAU,cAAc,YAAY,CAAC;AAEzC,QAAM,QAAQ,YAAY,MAAM;AAC9B,QAAI,CAAC,aAAc,cAAa,KAAK;AACrC,mBAAe,KAAK;AAAA,EACtB,GAAG,CAAC,cAAc,YAAY,CAAC;AAE/B,QAAM,SAAS,YAAY,MAAM;AAC/B,QAAI,WAAW;AACb,YAAM;AAAA,IACR,OAAO;AACL,WAAK;AAAA,IACP;AAAA,EACF,GAAG,CAAC,WAAW,MAAM,KAAK,CAAC;AAG3B,QAAM,2BAA2B;AAAA,IAC/B,CAAC,aAAsB,gBAAyB;AAC9C,YAAM,gBAAgB,OAAO;AAC7B,YAAM,iBAAiB,OAAO;AAC9B,YAAM,MAAM;AAEZ,UAAI,YAA8B;AAClC,UAAI,MAAM;AACV,UAAI,OAAO;AAEX,cAAQ,oBAAoB;AAAA,QAC1B,KAAK;AACH,gBAAM,YAAY,MAAM,YAAY,SAAS;AAC7C,iBAAO,YAAY,OAAO,YAAY,QAAQ,IAAI,YAAY,QAAQ;AACtE;AAAA,QACF,KAAK;AACH,gBAAM,YAAY,SAAS;AAC3B,iBAAO,YAAY,OAAO,YAAY,QAAQ,IAAI,YAAY,QAAQ;AACtE;AAAA,QACF,KAAK;AACH,gBAAM,YAAY,MAAM,YAAY,SAAS,IAAI,YAAY,SAAS;AACtE,iBAAO,YAAY,OAAO,YAAY,QAAQ;AAC9C;AAAA,QACF,KAAK;AACH,gBAAM,YAAY,MAAM,YAAY,SAAS,IAAI,YAAY,SAAS;AACtE,iBAAO,YAAY,QAAQ;AAC3B;AAAA,MACJ;AAGA,UAAI,cAAc,SAAS,MAAM,KAAK;AACpC,oBAAY;AACZ,cAAM,YAAY,SAAS;AAC3B,eAAO,YAAY,OAAO,YAAY,QAAQ,IAAI,YAAY,QAAQ;AAAA,MACxE,WAAW,cAAc,YAAY,MAAM,YAAY,SAAS,iBAAiB,KAAK;AACpF,oBAAY;AACZ,cAAM,YAAY,MAAM,YAAY,SAAS;AAC7C,eAAO,YAAY,OAAO,YAAY,QAAQ,IAAI,YAAY,QAAQ;AAAA,MACxE,WAAW,cAAc,UAAU,OAAO,KAAK;AAC7C,oBAAY;AACZ,cAAM,YAAY,MAAM,YAAY,SAAS,IAAI,YAAY,SAAS;AACtE,eAAO,YAAY,QAAQ;AAAA,MAC7B,WAAW,cAAc,WAAW,OAAO,YAAY,QAAQ,gBAAgB,KAAK;AAClF,oBAAY;AACZ,cAAM,YAAY,MAAM,YAAY,SAAS,IAAI,YAAY,SAAS;AACtE,eAAO,YAAY,OAAO,YAAY,QAAQ;AAAA,MAChD;AAGA,YAAM,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,iBAAiB,YAAY,SAAS,GAAG,CAAC;AAC5E,aAAO,KAAK,IAAI,KAAK,KAAK,IAAI,MAAM,gBAAgB,YAAY,QAAQ,GAAG,CAAC;AAE5E,aAAO,EAAE,KAAK,MAAM,UAAU;AAAA,IAChC;AAAA,IACA,CAAC,kBAAkB;AAAA,EACrB;AAGA,YAAU,MAAM;AACd,QAAI,WAAW;AACb,sBAAgB,CAAC,UAAU,EAAE,GAAG,MAAM,WAAW,MAAM,cAAc,MAAM,EAAE;AAAA,IAC/E,OAAO;AACL,sBAAgB,CAAC,UAAU,EAAE,GAAG,MAAM,WAAW,OAAO,cAAc,MAAM,EAAE;AAAA,IAChF;AAAA,EACF,GAAG,CAAC,SAAS,CAAC;AAGd,YAAU,MAAM;AACd,QACE,aAAa,aACb,CAAC,aAAa,gBACd,WAAW,WACX,WAAW,SACX;AACA,YAAM,cAAc,WAAW,QAAQ,sBAAsB;AAC7D,YAAM,cAAc,WAAW,QAAQ,sBAAsB;AAE7D,YAAM,EAAE,KAAK,MAAM,UAAU,IAAI,yBAAyB,aAAa,WAAW;AAElF,sBAAgB,CAAC,UAAU;AAAA,QACzB,GAAG;AAAA,QACH,UAAU,EAAE,KAAK,MAAM,UAAU;AAAA,QACjC,cAAc;AAAA,MAChB,EAAE;AAAA,IACJ;AAAA,EAIF,GAAG,CAAC,aAAa,WAAW,aAAa,cAAc,0BAA0B,QAAQ,CAAC;AAG1F,QAAM,eAAe,YAAY,MAAM;AACrC,QAAI,CAAC,aAAa,aAAa,CAAC,aAAa,gBAAgB,eAAe,QAAS;AAErF,mBAAe,UAAU;AAEzB,sBAAkB,UAAU,sBAAsB,MAAM;AACtD,UAAI,WAAW,WAAW,WAAW,SAAS;AAC5C,cAAM,cAAc,WAAW,QAAQ,sBAAsB;AAC7D,cAAM,cAAc,WAAW,QAAQ,sBAAsB;AAE7D,cAAM,EAAE,KAAK,MAAM,UAAU,IAAI,yBAAyB,aAAa,WAAW;AAElF,wBAAgB,CAAC,UAAU;AAAA,UACzB,GAAG;AAAA,UACH,UAAU,EAAE,KAAK,MAAM,UAAU;AAAA,QACnC,EAAE;AAAA,MACJ;AAEA,qBAAe,UAAU;AAAA,IAC3B,CAAC;AAAA,EACH,GAAG,CAAC,aAAa,WAAW,aAAa,cAAc,wBAAwB,CAAC;AAGhF,YAAU,MAAM;AACd,UAAM,eAAe,MAAM;AACzB,UACE,aAAa,aACb,aAAa,gBACb,WAAW,WACX,WAAW,SACX;AACA,cAAM,cAAc,WAAW,QAAQ,sBAAsB;AAC7D,cAAM,cAAc,WAAW,QAAQ,sBAAsB;AAE7D,cAAM,EAAE,KAAK,MAAM,UAAU,IAAI,yBAAyB,aAAa,WAAW;AAElF,wBAAgB,CAAC,UAAU;AAAA,UACzB,GAAG;AAAA,UACH,UAAU,EAAE,KAAK,MAAM,UAAU;AAAA,QACnC,EAAE;AAAA,MACJ;AAAA,IACF;AAEA,WAAO,iBAAiB,UAAU,YAAY;AAC9C,WAAO,MAAM,OAAO,oBAAoB,UAAU,YAAY;AAAA,EAChE,GAAG,CAAC,aAAa,WAAW,aAAa,cAAc,wBAAwB,CAAC;AAGhF,YAAU,MAAM;AACd,QAAI,aAAa,WAAW;AAK1B,eAAS,iBAAiB,UAAU,cAAc,EAAE,SAAS,MAAM,SAAS,KAAK,CAAC;AAAA,IACpF;AAEA,WAAO,MAAM;AACX,eAAS,oBAAoB,UAAU,cAAc,EAAE,SAAS,KAAK,CAAC;AAAA,IACxE;AAAA,EACF,GAAG,CAAC,aAAa,WAAW,YAAY,CAAC;AAGzC,QAAM,qBAAqB;AAAA,IACzB,CAAC,UAAsB;AACrB,UAAI,CAAC,uBAAuB,CAAC,aAAa,UAAW;AAErD,YAAM,SAAS,MAAM;AAErB,UAAI,WAAW,SAAS,SAAS,MAAM,KAAK,WAAW,SAAS,SAAS,MAAM,GAAG;AAChF;AAAA,MACF;AAEA,YAAM;AAAA,IACR;AAAA,IACA,CAAC,qBAAqB,aAAa,WAAW,KAAK;AAAA,EACrD;AAGA,QAAM,kBAAkB;AAAA,IACtB,CAAC,UAAyB;AACxB,UAAI,iBAAiB,MAAM,QAAQ,YAAY,aAAa,WAAW;AACrE,cAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,CAAC,eAAe,aAAa,WAAW,KAAK;AAAA,EAC/C;AAGA,YAAU,MAAM;AACd,QAAI,aAAa,WAAW;AAC1B,eAAS,iBAAiB,aAAa,kBAAkB;AACzD,eAAS,iBAAiB,WAAW,eAAe;AAAA,IACtD;AAEA,WAAO,MAAM;AACX,eAAS,oBAAoB,aAAa,kBAAkB;AAC5D,eAAS,oBAAoB,WAAW,eAAe;AAAA,IACzD;AAAA,EACF,GAAG,CAAC,aAAa,WAAW,oBAAoB,eAAe,CAAC;AAGhE,YAAU,MAAM;AACd,UAAM,YAAY,WAAW;AAC7B,UAAM,mBAAmB,kBAAkB;AAC3C,WAAO,MAAM;AACX,UAAI,WAAW;AACb,qBAAa,SAAS;AAAA,MACxB;AACA,UAAI,kBAAkB;AACpB,6BAAqB,gBAAgB;AAAA,MACvC;AAAA,IACF;AAAA,EACF,GAAG,CAAC,CAAC;AAcL,iBAAe,aAAa,aAAa,aAAa,cAAc,YAAY;AAAA,IAC9E,SAAS;AAAA,EACX,CAAC;AAGD,SACE,iCAeE;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,KAAK;AAAA,QACL,WAAW,CAAC,yBAAyB,SAAS,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AAAA,QACxE,SAAS;AAAA,QAER,gBAAM,eAAe,OAAO,IACzB,MAAM,aAAa,SAAwD;AAAA,UACzE,iBAAiB,aAAa;AAAA,UAC9B,iBAAiB;AAAA,QACnB,CAAC,IACD;AAAA;AAAA,IACN;AAAA,IAGC,YACC,aAAa,aACb;AAAA,MACE;AAAA,QAAC;AAAA;AAAA,UACC,KAAK;AAAA,UACL,MAAK;AAAA,UACL,cAAW;AAAA,UACX,mBAAiB,QAAQ,UAAU;AAAA,UAGnC,cAAY,QAAQ,SAAY;AAAA,UAChC,WAAW;AAAA,YACT;AAAA,YACA,0BAA0B,aAAa,SAAS,SAAS;AAAA,YACzD,aAAa,eAAe,mCAAmC;AAAA,YAC/D;AAAA,UACF,EACG,OAAO,OAAO,EACd,KAAK,GAAG;AAAA,UACX,OAAO;AAAA,YACL,KAAK,aAAa,SAAS;AAAA,YAC3B,MAAM,aAAa,SAAS;AAAA,YAC5B;AAAA,UACF;AAAA,UAEE;AAAA,sBAAS,oBACT,qBAAC,SAAI,WAAU,wBACZ;AAAA,uBACC,oBAAC,UAAK,IAAI,SAAS,WAAU,uBAC1B,iBACH;AAAA,cAED,mBACC;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAK;AAAA,kBACL,WAAU;AAAA,kBACV,SAAS;AAAA,kBACT,cAAW;AAAA,kBAEX,8BAAC,KAAE,eAAY,QAAO;AAAA;AAAA,cACxB;AAAA,eAEJ;AAAA,YAEF,oBAAC,SAAI,WAAU,sBAAsB,UAAS;AAAA;AAAA;AAAA,MAChD;AAAA,MACA,SAAS;AAAA,IACX;AAAA,KACJ;AAEJ;AAEA,QAAQ,cAAc;","names":[]}
@@ -3,9 +3,6 @@ import {
3
3
  toIconKey
4
4
  } from "./chunk-V3T7RO4F.js";
5
5
 
6
- // src/utils/renderIcon.tsx
7
- import { icons } from "lucide-react";
8
-
9
6
  // src/utils/devWarn.ts
10
7
  var warned = /* @__PURE__ */ new Set();
11
8
  function devWarn(key, message) {
@@ -25,14 +22,12 @@ var renderIcon = (icon, className) => {
25
22
  if (Registered) {
26
23
  return /* @__PURE__ */ jsx(Registered, { className, "aria-hidden": "true" });
27
24
  }
28
- const iconName = toIconKey(icon);
29
- const LucideIcon = icons[iconName];
30
- if (LucideIcon) {
25
+ if (!/\s/.test(icon)) {
26
+ const iconName = toIconKey(icon);
31
27
  devWarn(
32
- `icon-string-fallback-${iconName}`,
33
- `Icon "${icon}" was resolved by name from the full Lucide icon set. That lookup is deprecated and is removed in 4.0, because it bundles every Lucide icon. Pass the component instead (\`import { ${iconName} } from 'lucide-react'\`), register it once with \`registerIcons({ ${iconName} })\`, or \`import 'eidos-ui/lucide-icons'\` to register them all.`
28
+ `icon-unregistered-${iconName}`,
29
+ `Icon "${icon}" is not registered, so it is rendered as the CSS class "${icon}". If it is a Lucide icon, pass the component (\`import { ${iconName} } from 'lucide-react'\`), register it once with \`registerIcons({ ${iconName} })\`, or \`import 'eidos-ui/lucide-icons'\` to register them all. If it is an icon-font class, ignore this.`
34
30
  );
35
- return /* @__PURE__ */ jsx(LucideIcon, { className, "aria-hidden": "true" });
36
31
  }
37
32
  return /* @__PURE__ */ jsx("i", { className: `${icon} ${className || ""}`, "aria-hidden": "true" });
38
33
  }
@@ -40,10 +35,6 @@ var renderIcon = (icon, className) => {
40
35
  return /* @__PURE__ */ jsx(IconComponent, { className, "aria-hidden": "true" });
41
36
  };
42
37
 
43
- // src/utils/dualModifier.ts
44
- var dualModifier = (block, canonical, legacy) => `${block}--${canonical} ${block}--${legacy}`;
45
- var fullWidthModifier = (block) => dualModifier(block, "full-width", "fullWidth");
46
-
47
38
  // src/utils/useDialogFocus.ts
48
39
  import { useEffect } from "react";
49
40
  var FOCUSABLE_SELECTOR = [
@@ -140,10 +131,8 @@ var useIsClient = () => {
140
131
  export {
141
132
  devWarn,
142
133
  renderIcon,
143
- dualModifier,
144
- fullWidthModifier,
145
134
  FOCUSABLE_SELECTOR,
146
135
  useDialogFocus,
147
136
  useIsClient
148
137
  };
149
- //# sourceMappingURL=chunk-U34INRFO.js.map
138
+ //# sourceMappingURL=chunk-PP6HS4GR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/devWarn.ts","../src/utils/renderIcon.tsx","../src/utils/useDialogFocus.ts","../src/utils/useIsClient.ts"],"sourcesContent":["/**\n * Logs a misconfiguration warning, once per `key`, and never in production.\n *\n * Deliberately reads `process.env.NODE_ENV` off `globalThis` behind a cast\n * rather than referencing `process` directly: this is a browser library, and\n * a bare `process` reference fails the `tsup` dts build (its worker resolves\n * without node types, so `npm run typecheck` passing is not enough) as well\n * as throwing at runtime anywhere a bundler hasn't substituted it. The\n * optional chaining covers every case - no `process`, no `env`, no value.\n *\n * Because the check is dynamic rather than a statically replaceable\n * `process.env.NODE_ENV` expression, the message text stays in production\n * bundles; only the logging is skipped. That is the trade for not shipping a\n * `process` reference at all, and these strings are small.\n */\nconst warned = new Set<string>();\n\nexport function devWarn(key: string, message: string): void {\n const nodeEnv = (globalThis as { process?: { env?: { NODE_ENV?: string } } }).process?.env\n ?.NODE_ENV;\n if (nodeEnv === 'production') return;\n if (warned.has(key)) return;\n warned.add(key);\n console.warn(`[eidos-ui] ${message}`);\n}\n","import React from 'react';\nimport { devWarn } from './devWarn';\nimport { resolveRegisteredIcon, toIconKey, type IconComponent } from './iconRegistry';\n\nexport type IconType = IconComponent | string;\n\n/**\n * Renders an icon prop.\n *\n * @param icon - An icon component, or a string: a name registered with\n * `registerIcons`, or CSS classes for an icon font.\n * @param className - Optional CSS class name to apply to the icon.\n * @returns React node representing the icon, or null if no icon provided.\n *\n * @example\n * // Component - the recommended form; only the icons you import are bundled\n * import { Heart } from 'lucide-react';\n * renderIcon(Heart, 'my-icon-class');\n *\n * @example\n * // Registered name\n * registerIcons({ Heart });\n * renderIcon('heart', 'my-icon-class');\n *\n * @example\n * // CSS classes for an icon font (Font Awesome, Remixicon, ...)\n * renderIcon('fas fa-heart', 'my-icon-class');\n */\nexport const renderIcon = (icon: IconType | undefined, className?: string): React.ReactNode => {\n if (!icon) return null;\n\n if (typeof icon === 'string') {\n const Registered = resolveRegisteredIcon(icon);\n if (Registered) {\n return <Registered className={className} aria-hidden=\"true\" />;\n }\n\n // No lookup against Lucide's full `icons` map. There was one until 4.0,\n // and referencing that map put every Lucide icon (~1,800 modules) into\n // every consumer's bundle, however few they used - no bundler can\n // tree-shake a lookup by a runtime string. Do not reintroduce it: a\n // consumer who wants every name opts in with `eidos-ui/lucide-icons`.\n //\n // An unregistered string is treated as icon-font classes. A single token\n // with no space is far more often a forgotten registration than a font\n // class, so it warns - once per name. The cost is one dev-only warning\n // for single-class fonts (Remixicon's `ri-home-line`); the alternative is\n // an upgrade that silently renders empty `<i>` elements where icons were.\n if (!/\\s/.test(icon)) {\n const iconName = toIconKey(icon);\n devWarn(\n `icon-unregistered-${iconName}`,\n `Icon \"${icon}\" is not registered, so it is rendered as the CSS class \"${icon}\". If it is a Lucide icon, pass the component (\\`import { ${iconName} } from 'lucide-react'\\`), register it once with \\`registerIcons({ ${iconName} })\\`, or \\`import 'eidos-ui/lucide-icons'\\` to register them all. If it is an icon-font class, ignore this.`,\n );\n }\n\n return <i className={`${icon} ${className || ''}`} aria-hidden=\"true\" />;\n }\n\n // It's a React component\n const IconComponent = icon;\n return <IconComponent className={className} aria-hidden=\"true\" />;\n};\n","import { useEffect, type RefObject } from 'react';\n\n/**\n * Focus management for a dialog: move focus in on open, optionally trap Tab\n * inside it, and restore focus to the opener on close.\n *\n * Named for the job rather than the mechanism because the trap is optional.\n * `Popover` declares `aria-modal=\"false\"` - an honest non-modal dialog - so\n * trapping Tab in it would be wrong, but it still needs the other two: its\n * panel is portaled to `document.body`, so without moving focus in, Tab from\n * the trigger goes to whatever follows it in the page and the panel's own\n * controls are unreachable by keyboard entirely.\n *\n * ## Why this exists\n *\n * `Modal`, `Drawer` and `CommandPalette` all rendered\n * `role=\"dialog\" aria-modal=\"true\"` with no focus management whatsoever. That\n * attribute is a **promise to assistive technology that the rest of the page\n * is inert**, and it was false: measured in a browser, focus never entered the\n * dialog, and Tab moved to the page behind the scrim on the first press\n * (Drawer on the second). Drawer additionally dropped focus onto `<body>` when\n * it closed, so a keyboard user was returned to the top of the document.\n *\n * That is WCAG 2.4.3 Focus Order (Level A), and it is invisible to axe - a\n * static snapshot of the DOM looks perfectly correct.\n *\n * ## Nesting\n *\n * Traps register on a module-level stack and only the innermost one acts, so a\n * dialog opened from a dialog behaves correctly. Without this, both listeners\n * fire for the same Tab and fight over where focus lands.\n *\n * ## What this does *not* do\n *\n * It does not mark the background `inert`. A trap plus `aria-modal` is the\n * widely-supported approach and is what screen readers act on; `inert` on\n * every sibling of the portal root would be stronger, but it needs the\n * component to know about DOM it does not own. Worth revisiting if a\n * consumer reports a screen reader escaping the dialog in browse mode.\n */\n\n/**\n * Deliberately not `[tabindex]` in general - that would match `tabindex=\"-1\"`,\n * which is programmatically focusable but explicitly removed from the Tab\n * sequence, so including it would make Tab stop somewhere the user cannot\n * reach by tabbing in the first place.\n */\nexport const FOCUSABLE_SELECTOR = [\n 'a[href]',\n 'area[href]',\n 'button:not([disabled])',\n 'input:not([disabled]):not([type=\"hidden\"])',\n 'select:not([disabled])',\n 'textarea:not([disabled])',\n 'details > summary:first-of-type',\n 'iframe',\n 'audio[controls]',\n 'video[controls]',\n '[contenteditable]:not([contenteditable=\"false\"])',\n '[tabindex]:not([tabindex^=\"-\"])',\n].join(',');\n\n/**\n * `offsetParent === null` is the usual visibility check and is wrong here: it\n * is also null for `position: fixed` elements, which is exactly what a modal\n * is. `getClientRects()` is empty only when the element genuinely does not\n * render.\n */\nconst isVisible = (element: HTMLElement): boolean =>\n element.getClientRects().length > 0 && getComputedStyle(element).visibility !== 'hidden';\n\nconst getFocusable = (container: HTMLElement): HTMLElement[] =>\n Array.from(container.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR)).filter(\n (element) => isVisible(element) && element.closest('[aria-hidden=\"true\"]') === null,\n );\n\n/** Innermost trap last. Only the last entry responds to Tab. */\nconst trapStack: HTMLElement[] = [];\n\nexport interface UseDialogFocusOptions {\n /** Focused when the trap activates. Defaults to the first focusable child. */\n initialFocus?: RefObject<HTMLElement | null>;\n /**\n * Whether to return focus to whatever had it when the trap activated.\n * Defaults to `true`; pass `false` when the caller restores focus itself.\n */\n restoreFocus?: boolean;\n /**\n * Whether Tab is confined to the container. Defaults to `true`.\n *\n * Set `false` for a non-modal dialog (`aria-modal=\"false\"`), where the rest\n * of the page stays available and trapping would strand the user.\n */\n trapTab?: boolean;\n}\n\nexport const useDialogFocus = (\n active: boolean,\n containerRef: RefObject<HTMLElement | null>,\n { initialFocus, restoreFocus = true, trapTab = true }: UseDialogFocusOptions = {},\n): void => {\n useEffect(() => {\n const container = containerRef.current;\n if (!active || !container) return;\n\n // Captured before focus moves. The caller must only flip `active` to true\n // once the container is in the DOM - for the animated overlays that means\n // `isOpen && isMounted`, since `isMounted` is set in an effect one render\n // later and the container does not exist before it.\n const previouslyFocused = document.activeElement as HTMLElement | null;\n\n trapStack.push(container);\n\n // Moving focus in is retried across a few frames rather than attempted\n // once.\n //\n // These overlays animate open, and `.focus()` on an element that is still\n // `visibility: hidden` is a silent no-op - it does not throw, it just\n // leaves focus where it was. `Modal` sets its `--is-open` class two\n // animation frames after mounting, and the computed style has not caught\n // up at the moment the effect runs, so a single attempt focused nothing\n // and the trap looked broken.\n //\n // Retrying is better than keying off any particular animation: the hook\n // stays ignorant of each component's transition duration, and simply\n // stops as soon as focus has actually landed inside.\n const MAX_FRAMES = 10;\n let frame = 0;\n let attempts = 0;\n\n const tryFocus = () => {\n const target = initialFocus?.current ?? getFocusable(container)[0];\n if (target) {\n target.focus();\n } else {\n // A dialog with nothing focusable in it still must not leave focus on\n // the page behind, so the container takes it. `tabindex=\"-1\"` keeps\n // it out of the Tab sequence while allowing `.focus()`.\n if (!container.hasAttribute('tabindex')) container.setAttribute('tabindex', '-1');\n container.focus();\n }\n\n if (!container.contains(document.activeElement) && attempts < MAX_FRAMES) {\n attempts += 1;\n frame = requestAnimationFrame(tryFocus);\n }\n };\n\n tryFocus();\n\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key !== 'Tab') return;\n // Only the innermost trap acts.\n if (trapStack[trapStack.length - 1] !== container) return;\n\n // Re-queried on every Tab rather than cached: dialog contents change\n // (a disabled Confirm button becoming enabled, a list filtering down),\n // and a stale list sends focus to an element that is no longer there.\n const focusable = getFocusable(container);\n if (focusable.length === 0) {\n event.preventDefault();\n return;\n }\n\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n const activeElement = document.activeElement as HTMLElement | null;\n\n // Focus outside the container - e.g. a click landed on the backdrop.\n // Pull it back in rather than letting Tab continue through the page.\n if (!activeElement || !container.contains(activeElement)) {\n event.preventDefault();\n (event.shiftKey ? last : first).focus();\n return;\n }\n\n if (event.shiftKey && activeElement === first) {\n event.preventDefault();\n last.focus();\n } else if (!event.shiftKey && activeElement === last) {\n event.preventDefault();\n first.focus();\n }\n };\n\n if (trapTab) document.addEventListener('keydown', onKeyDown, true);\n\n return () => {\n cancelAnimationFrame(frame);\n document.removeEventListener('keydown', onKeyDown, true);\n\n const index = trapStack.lastIndexOf(container);\n if (index !== -1) trapStack.splice(index, 1);\n\n // Restore only if focus still belongs to the closing dialog.\n //\n // Two cases count as \"belongs\":\n //\n // 1. Focus is still inside the container.\n // 2. Focus has been lost to `<body>`. When the overlay hides, the\n // browser blurs whatever was focused inside it, so by the time this\n // cleanup runs `activeElement` is often already `<body>` - checking\n // only case 1 meant `CommandPalette` never restored at all.\n //\n // Anything else means something took focus deliberately - a confirm\n // action moving to a new region, say - and stealing it back would be\n // worse than doing nothing.\n const active = document.activeElement;\n const focusIsOurs = container.contains(active) || active === document.body || active === null;\n\n if (restoreFocus && focusIsOurs && previouslyFocused?.isConnected) {\n previouslyFocused.focus();\n }\n };\n }, [active, containerRef, initialFocus, restoreFocus, trapTab]);\n};\n","import { useEffect, useState } from 'react';\n\n/**\n * `false` on the server and on the very first client render, `true` from the\n * first effect onwards.\n *\n * ## Why this exists\n *\n * Every overlay in this library renders through `createPortal(…,\n * document.body)`. A portal is a client-only construct: there is no\n * `document` during `renderToString`, so any overlay that is *already open on\n * its first render* does not merely render oddly - it throws, and takes the\n * whole server render down with it. Measured against the built package:\n *\n * ```\n * renderToString(<Modal isOpen>) ReferenceError: document is not defined\n * renderToString(<Dropdown defaultOpen>) ReferenceError: DOMRect is not defined\n * renderToString(<Select autoOpen>) ReferenceError: DOMRect is not defined\n * ```\n *\n * `Modal`, `Drawer` and `CommandPalette` each keep an `isMounted` flag, which\n * looks like it would prevent this and does not: it is initialised to\n * `useState(isOpen)`, so it is already `true` on the first render. It exists\n * to sequence the open/close *animation*, not to defer the portal.\n *\n * With this hook the server renders nothing for the panel, and the portal\n * appears on the client after mount.\n *\n * ## Why a state flag rather than `typeof document !== 'undefined'`\n *\n * That check is `true` during hydration, so the client's first render would\n * produce the portal while the server's produced nothing - a hydration\n * mismatch, which React resolves by discarding and re-rendering the subtree.\n * A state flag set in an effect makes the first client render agree with the\n * server by construction, and the portal arrive one render later.\n *\n * ## Scope\n *\n * Only for components that can be open on their first render - `Dropdown`\n * (`defaultOpen`), `Popover`, `Modal`, `Drawer`, `CommandPalette`. `Tooltip`,\n * `ContextMenu` and `Snackbar` can only open in response to an event, which\n * cannot happen during a server render, so they need nothing. `check-ssr.js`\n * asserts all of them either way.\n */\nexport const useIsClient = (): boolean => {\n const [isClient, setIsClient] = useState(false);\n\n useEffect(() => {\n setIsClient(true);\n }, []);\n\n return isClient;\n};\n"],"mappings":"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","names":["active","useEffect"]}
@@ -3,9 +3,6 @@
3
3
 
4
4
  var _chunkCJT7L764cjs = require('./chunk-CJT7L764.cjs');
5
5
 
6
- // src/utils/renderIcon.tsx
7
- var _lucidereact = require('lucide-react');
8
-
9
6
  // src/utils/devWarn.ts
10
7
  var warned = /* @__PURE__ */ new Set();
11
8
  function devWarn(key, message) {
@@ -25,14 +22,12 @@ var renderIcon = (icon, className) => {
25
22
  if (Registered) {
26
23
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Registered, { className, "aria-hidden": "true" });
27
24
  }
28
- const iconName = _chunkCJT7L764cjs.toIconKey.call(void 0, icon);
29
- const LucideIcon = _lucidereact.icons[iconName];
30
- if (LucideIcon) {
25
+ if (!/\s/.test(icon)) {
26
+ const iconName = _chunkCJT7L764cjs.toIconKey.call(void 0, icon);
31
27
  devWarn(
32
- `icon-string-fallback-${iconName}`,
33
- `Icon "${icon}" was resolved by name from the full Lucide icon set. That lookup is deprecated and is removed in 4.0, because it bundles every Lucide icon. Pass the component instead (\`import { ${iconName} } from 'lucide-react'\`), register it once with \`registerIcons({ ${iconName} })\`, or \`import 'eidos-ui/lucide-icons'\` to register them all.`
28
+ `icon-unregistered-${iconName}`,
29
+ `Icon "${icon}" is not registered, so it is rendered as the CSS class "${icon}". If it is a Lucide icon, pass the component (\`import { ${iconName} } from 'lucide-react'\`), register it once with \`registerIcons({ ${iconName} })\`, or \`import 'eidos-ui/lucide-icons'\` to register them all. If it is an icon-font class, ignore this.`
34
30
  );
35
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, LucideIcon, { className, "aria-hidden": "true" });
36
31
  }
37
32
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "i", { className: `${icon} ${className || ""}`, "aria-hidden": "true" });
38
33
  }
@@ -40,10 +35,6 @@ var renderIcon = (icon, className) => {
40
35
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, IconComponent, { className, "aria-hidden": "true" });
41
36
  };
42
37
 
43
- // src/utils/dualModifier.ts
44
- var dualModifier = (block, canonical, legacy) => `${block}--${canonical} ${block}--${legacy}`;
45
- var fullWidthModifier = (block) => dualModifier(block, "full-width", "fullWidth");
46
-
47
38
  // src/utils/useDialogFocus.ts
48
39
  var _react = require('react');
49
40
  var FOCUSABLE_SELECTOR = [
@@ -143,7 +134,5 @@ var useIsClient = () => {
143
134
 
144
135
 
145
136
 
146
-
147
-
148
- exports.devWarn = devWarn; exports.renderIcon = renderIcon; exports.dualModifier = dualModifier; exports.fullWidthModifier = fullWidthModifier; exports.FOCUSABLE_SELECTOR = FOCUSABLE_SELECTOR; exports.useDialogFocus = useDialogFocus; exports.useIsClient = useIsClient;
149
- //# sourceMappingURL=chunk-ENMDOQQO.cjs.map
137
+ exports.devWarn = devWarn; exports.renderIcon = renderIcon; exports.FOCUSABLE_SELECTOR = FOCUSABLE_SELECTOR; exports.useDialogFocus = useDialogFocus; exports.useIsClient = useIsClient;
138
+ //# sourceMappingURL=chunk-R5WI5IGR.cjs.map