eidos-ui 3.7.0 → 3.8.1

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 (409) hide show
  1. package/README.md +10 -0
  2. package/dist/{Avatar.types-BY-C09Ke.d.cts → Avatar.types-DkRznn-7.d.cts} +6 -1
  3. package/dist/{Avatar.types-BY-C09Ke.d.ts → Avatar.types-DkRznn-7.d.ts} +6 -1
  4. package/dist/{Breadcrumb.types-DaykU-C8.d.cts → Breadcrumb.types-C3uADbKU.d.cts} +4 -1
  5. package/dist/{Breadcrumb.types-DaykU-C8.d.ts → Breadcrumb.types-C3uADbKU.d.ts} +4 -1
  6. package/dist/Button.types-BCIK8Qlk.d.ts +59 -0
  7. package/dist/Button.types-DkgWjFsk.d.cts +59 -0
  8. package/dist/{Chip.types-COQfx2Ru.d.ts → Chip.types-BM-UZOCv.d.ts} +10 -1
  9. package/dist/{Chip.types-B6y3Wifa.d.cts → Chip.types-_1bhyKz4.d.cts} +10 -1
  10. package/dist/{Header.types-Ce5Cj301.d.cts → Header.types-a6p0-ZHx.d.cts} +24 -8
  11. package/dist/{Header.types-0XovUp0T.d.ts → Header.types-zbhURbg7.d.ts} +24 -8
  12. package/dist/{Input.types-D7-sWq-q.d.cts → Input.types--K0t_3L2.d.cts} +1 -1
  13. package/dist/{Input.types-CSDMaZNe.d.ts → Input.types--UjucBDd.d.ts} +1 -1
  14. package/dist/{Menu.types-CTnUijv5.d.cts → Menu.types-D6VoK9T9.d.cts} +1 -1
  15. package/dist/{Menu.types-BN4g1-3A.d.ts → Menu.types-tUEhXn52.d.ts} +1 -1
  16. package/dist/{Navigation.types-By5HfPTi.d.ts → Navigation.types-CJRzo9Zo.d.ts} +1 -1
  17. package/dist/{Navigation.types-_MrYqqUI.d.cts → Navigation.types-D95oHZEJ.d.cts} +1 -1
  18. package/dist/{SegmentedControl.types-cjLwwBAm.d.ts → SegmentedControl.types-CHtjABQM.d.ts} +1 -1
  19. package/dist/{SegmentedControl.types-BofrEYyd.d.cts → SegmentedControl.types-D_gHYL9X.d.cts} +1 -1
  20. package/dist/{Select.types-ok-03rLo.d.cts → Select.types-8CGZBgT-.d.cts} +2 -2
  21. package/dist/{Select.types-C2tGy1vj.d.ts → Select.types-CAVh9Gvd.d.ts} +2 -2
  22. package/dist/{Table.types-D8pmgxKA.d.ts → Table.types-BFDE-hhF.d.ts} +2 -2
  23. package/dist/{Table.types-D-9tC0kJ.d.cts → Table.types-Tai7_MTz.d.cts} +2 -2
  24. package/dist/{Toolbar.types-CKnQC_TW.d.ts → Toolbar.types-BqBrPVww.d.ts} +8 -6
  25. package/dist/{Toolbar.types-DUz2mxct.d.cts → Toolbar.types-GCUgzuKW.d.cts} +8 -6
  26. package/dist/alert/index.cjs +8 -5
  27. package/dist/alert/index.cjs.map +1 -1
  28. package/dist/alert/index.d.cts +1 -1
  29. package/dist/alert/index.d.ts +1 -1
  30. package/dist/alert/index.js +7 -4
  31. package/dist/avatar/index.d.cts +2 -2
  32. package/dist/avatar/index.d.ts +2 -2
  33. package/dist/breadcrumb/index.cjs +4 -2
  34. package/dist/breadcrumb/index.cjs.map +1 -1
  35. package/dist/breadcrumb/index.d.cts +2 -2
  36. package/dist/breadcrumb/index.d.ts +2 -2
  37. package/dist/breadcrumb/index.js +3 -1
  38. package/dist/button/index.cjs +7 -4
  39. package/dist/button/index.cjs.map +1 -1
  40. package/dist/button/index.d.cts +5 -5
  41. package/dist/button/index.d.ts +5 -5
  42. package/dist/button/index.js +6 -3
  43. package/dist/button-group/index.d.cts +2 -2
  44. package/dist/button-group/index.d.ts +2 -2
  45. package/dist/chip/index.cjs +7 -4
  46. package/dist/chip/index.cjs.map +1 -1
  47. package/dist/chip/index.d.cts +3 -3
  48. package/dist/chip/index.d.ts +3 -3
  49. package/dist/chip/index.js +6 -3
  50. package/dist/{chunk-DRXPTACG.js → chunk-26PRBZA6.js} +6 -2
  51. package/dist/chunk-26PRBZA6.js.map +1 -0
  52. package/dist/{chunk-L7I5NEGI.js → chunk-2IXCEKLI.js} +2 -2
  53. package/dist/{chunk-GWHZFX2H.js → chunk-2TIMJD4K.js} +29 -6
  54. package/dist/chunk-2TIMJD4K.js.map +1 -0
  55. package/dist/{chunk-RHFD2Z5V.js → chunk-3TF2GZSG.js} +7 -7
  56. package/dist/{chunk-TC5IC6OP.cjs → chunk-3VXUOAIJ.cjs} +3 -3
  57. package/dist/{chunk-TC5IC6OP.cjs.map → chunk-3VXUOAIJ.cjs.map} +1 -1
  58. package/dist/{chunk-JHX6JK3M.js → chunk-3X6QVHTD.js} +2 -2
  59. package/dist/{chunk-7VJCGKVP.cjs → chunk-4HZIXRAJ.cjs} +11 -11
  60. package/dist/{chunk-7VJCGKVP.cjs.map → chunk-4HZIXRAJ.cjs.map} +1 -1
  61. package/dist/{chunk-MQAOXZD4.js → chunk-4S57PE43.js} +4 -4
  62. package/dist/{chunk-JT4KVXJK.js → chunk-4V2XYUQL.js} +2 -2
  63. package/dist/{chunk-PMSENLOA.cjs → chunk-544RAXWO.cjs} +19 -19
  64. package/dist/{chunk-PMSENLOA.cjs.map → chunk-544RAXWO.cjs.map} +1 -1
  65. package/dist/{chunk-4JSTBA4F.cjs → chunk-6CW5QSYV.cjs} +7 -7
  66. package/dist/{chunk-4JSTBA4F.cjs.map → chunk-6CW5QSYV.cjs.map} +1 -1
  67. package/dist/{chunk-AR2ZOO6L.js → chunk-6FXFKMJ5.js} +3 -3
  68. package/dist/{chunk-KREHT4AQ.cjs → chunk-6IB27I5K.cjs} +8 -8
  69. package/dist/{chunk-KREHT4AQ.cjs.map → chunk-6IB27I5K.cjs.map} +1 -1
  70. package/dist/{chunk-YP4HUBKN.js → chunk-6NAOAKII.js} +2 -2
  71. package/dist/chunk-75Q5OS7L.cjs +10 -0
  72. package/dist/chunk-75Q5OS7L.cjs.map +1 -0
  73. package/dist/{chunk-LQXFXXMJ.cjs → chunk-7FV2X62W.cjs} +7 -7
  74. package/dist/{chunk-LQXFXXMJ.cjs.map → chunk-7FV2X62W.cjs.map} +1 -1
  75. package/dist/{chunk-2T7ZMMH5.cjs → chunk-7NUVLVSL.cjs} +5 -5
  76. package/dist/{chunk-2T7ZMMH5.cjs.map → chunk-7NUVLVSL.cjs.map} +1 -1
  77. package/dist/chunk-ACH7SYQ2.js +47 -0
  78. package/dist/chunk-ACH7SYQ2.js.map +1 -0
  79. package/dist/{chunk-HNGFRRVZ.cjs → chunk-AUNDBUHM.cjs} +3 -3
  80. package/dist/{chunk-HNGFRRVZ.cjs.map → chunk-AUNDBUHM.cjs.map} +1 -1
  81. package/dist/{chunk-XZLSHEHE.cjs → chunk-B2OHBIAL.cjs} +10 -10
  82. package/dist/{chunk-XZLSHEHE.cjs.map → chunk-B2OHBIAL.cjs.map} +1 -1
  83. package/dist/chunk-BDH2MXJW.js +46 -0
  84. package/dist/chunk-BDH2MXJW.js.map +1 -0
  85. package/dist/{chunk-D7SQ7LHJ.js → chunk-BO3KK3ZQ.js} +2 -2
  86. package/dist/{chunk-NOQF7UQ5.cjs → chunk-CFVUUMQA.cjs} +6 -6
  87. package/dist/{chunk-NOQF7UQ5.cjs.map → chunk-CFVUUMQA.cjs.map} +1 -1
  88. package/dist/chunk-CJT7L764.cjs +21 -0
  89. package/dist/chunk-CJT7L764.cjs.map +1 -0
  90. package/dist/{chunk-5XH2PHT2.js → chunk-CNTG7OOO.js} +14 -14
  91. package/dist/{chunk-I6M6CVI2.cjs → chunk-DG3O5NV4.cjs} +3 -3
  92. package/dist/{chunk-I6M6CVI2.cjs.map → chunk-DG3O5NV4.cjs.map} +1 -1
  93. package/dist/{chunk-WNDDS367.js → chunk-DPTTDHZ5.js} +3 -3
  94. package/dist/{chunk-35LGEPLP.cjs → chunk-ENMDOQQO.cjs} +29 -14
  95. package/dist/chunk-ENMDOQQO.cjs.map +1 -0
  96. package/dist/{chunk-V4BZWBZT.cjs → chunk-F5IRMMZ2.cjs} +7 -7
  97. package/dist/{chunk-V4BZWBZT.cjs.map → chunk-F5IRMMZ2.cjs.map} +1 -1
  98. package/dist/{chunk-WE2SBWZ6.js → chunk-FE7S4RSK.js} +10 -10
  99. package/dist/chunk-FE7S4RSK.js.map +1 -0
  100. package/dist/{chunk-BFKPJ627.js → chunk-FHOD3FUN.js} +4 -4
  101. package/dist/{chunk-SNRRF64M.js → chunk-GDRLVX2A.js} +31 -10
  102. package/dist/chunk-GDRLVX2A.js.map +1 -0
  103. package/dist/{chunk-5O73AALP.cjs → chunk-GP6EEZH5.cjs} +7 -3
  104. package/dist/chunk-GP6EEZH5.cjs.map +1 -0
  105. package/dist/{chunk-HEXAY6DE.cjs → chunk-GZDT2AHJ.cjs} +24 -24
  106. package/dist/chunk-GZDT2AHJ.cjs.map +1 -0
  107. package/dist/{chunk-SDUGYJGW.js → chunk-H3C6YECZ.js} +6 -6
  108. package/dist/{chunk-RJVHR45I.cjs → chunk-H46ZLPNJ.cjs} +7 -7
  109. package/dist/{chunk-RJVHR45I.cjs.map → chunk-H46ZLPNJ.cjs.map} +1 -1
  110. package/dist/{chunk-66UQTF57.cjs → chunk-HLI4SOH3.cjs} +45 -45
  111. package/dist/{chunk-66UQTF57.cjs.map → chunk-HLI4SOH3.cjs.map} +1 -1
  112. package/dist/{chunk-ZMRINZIO.cjs → chunk-HR5MWA3B.cjs} +5 -5
  113. package/dist/{chunk-ZMRINZIO.cjs.map → chunk-HR5MWA3B.cjs.map} +1 -1
  114. package/dist/{chunk-MPIVBAMY.js → chunk-HYRLK462.js} +2 -2
  115. package/dist/{chunk-LGDODZHI.js → chunk-IC2PIK3E.js} +19 -19
  116. package/dist/chunk-IC2PIK3E.js.map +1 -0
  117. package/dist/{chunk-FIVMMCGM.js → chunk-IHPSRTVW.js} +4 -4
  118. package/dist/{chunk-THCTUBX6.js → chunk-IKXXXVUO.js} +3 -3
  119. package/dist/{chunk-JPYJQ4TF.cjs → chunk-JFV56ISS.cjs} +6 -6
  120. package/dist/{chunk-JPYJQ4TF.cjs.map → chunk-JFV56ISS.cjs.map} +1 -1
  121. package/dist/{chunk-75GFIQRU.js → chunk-JY77VJAZ.js} +30 -15
  122. package/dist/chunk-JY77VJAZ.js.map +1 -0
  123. package/dist/chunk-KXDGW6LJ.cjs +46 -0
  124. package/dist/chunk-KXDGW6LJ.cjs.map +1 -0
  125. package/dist/{chunk-24HKKSKX.js → chunk-L6ERHCQ2.js} +3 -3
  126. package/dist/{chunk-4LNTZPSQ.js → chunk-L6YJ6QTZ.js} +2 -2
  127. package/dist/{chunk-KBQD4JLK.cjs → chunk-LUDK44NZ.cjs} +3 -3
  128. package/dist/{chunk-KBQD4JLK.cjs.map → chunk-LUDK44NZ.cjs.map} +1 -1
  129. package/dist/{chunk-PCTHJZRO.cjs → chunk-LWCFT5SP.cjs} +3 -3
  130. package/dist/{chunk-PCTHJZRO.cjs.map → chunk-LWCFT5SP.cjs.map} +1 -1
  131. package/dist/{chunk-JNY7TUDS.js → chunk-MCPGI6EI.js} +2 -2
  132. package/dist/{chunk-DU5JKTHK.cjs → chunk-MKC6V3SY.cjs} +6 -6
  133. package/dist/{chunk-DU5JKTHK.cjs.map → chunk-MKC6V3SY.cjs.map} +1 -1
  134. package/dist/{chunk-J76JHN7J.cjs → chunk-N5NXKVFJ.cjs} +10 -10
  135. package/dist/{chunk-J76JHN7J.cjs.map → chunk-N5NXKVFJ.cjs.map} +1 -1
  136. package/dist/{chunk-XERBOFYZ.cjs → chunk-NERASTO2.cjs} +3 -3
  137. package/dist/{chunk-XERBOFYZ.cjs.map → chunk-NERASTO2.cjs.map} +1 -1
  138. package/dist/{chunk-3KBBJZHK.cjs → chunk-NFD7MPX4.cjs} +16 -14
  139. package/dist/chunk-NFD7MPX4.cjs.map +1 -0
  140. package/dist/{chunk-3ZRFOKDM.cjs → chunk-NNAEQR3Y.cjs} +30 -30
  141. package/dist/{chunk-3ZRFOKDM.cjs.map → chunk-NNAEQR3Y.cjs.map} +1 -1
  142. package/dist/{chunk-36JFXFM2.cjs → chunk-OGGZIFTI.cjs} +38 -38
  143. package/dist/chunk-OGGZIFTI.cjs.map +1 -0
  144. package/dist/{chunk-2PCCGQOH.js → chunk-P6OJQ2RN.js} +6 -6
  145. package/dist/{chunk-3RWZC6OW.cjs → chunk-PE2SLXUS.cjs} +5 -5
  146. package/dist/{chunk-3RWZC6OW.cjs.map → chunk-PE2SLXUS.cjs.map} +1 -1
  147. package/dist/chunk-QD32IMMH.js +13 -0
  148. package/dist/chunk-QD32IMMH.js.map +1 -0
  149. package/dist/{chunk-OOCCSMWM.js → chunk-RHWZX7PB.js} +9 -7
  150. package/dist/chunk-RHWZX7PB.js.map +1 -0
  151. package/dist/{chunk-YXRKBKFB.js → chunk-S5CMZFX6.js} +3 -3
  152. package/dist/{chunk-4AO5RKV5.cjs → chunk-SLHIVEFW.cjs} +7 -7
  153. package/dist/{chunk-4AO5RKV5.cjs.map → chunk-SLHIVEFW.cjs.map} +1 -1
  154. package/dist/{chunk-HEX4IMLO.js → chunk-TJQNGJHP.js} +4 -4
  155. package/dist/{chunk-JCKGAAPZ.cjs → chunk-TNQ2ZZ7W.cjs} +9 -9
  156. package/dist/{chunk-JCKGAAPZ.cjs.map → chunk-TNQ2ZZ7W.cjs.map} +1 -1
  157. package/dist/chunk-U32K2H3N.js +10 -0
  158. package/dist/chunk-U32K2H3N.js.map +1 -0
  159. package/dist/{chunk-RHHZRTWM.js → chunk-U34INRFO.js} +28 -13
  160. package/dist/chunk-U34INRFO.js.map +1 -0
  161. package/dist/{chunk-SFFKQQ5Z.js → chunk-U4SVBE2M.js} +5 -5
  162. package/dist/{chunk-O3QM3BFE.js → chunk-UC4NYF6T.js} +2 -2
  163. package/dist/{chunk-6JHVXWDV.cjs → chunk-ULKWUKD2.cjs} +22 -22
  164. package/dist/{chunk-6JHVXWDV.cjs.map → chunk-ULKWUKD2.cjs.map} +1 -1
  165. package/dist/{chunk-BEOECPVJ.cjs → chunk-UTYY35QX.cjs} +3 -3
  166. package/dist/{chunk-BEOECPVJ.cjs.map → chunk-UTYY35QX.cjs.map} +1 -1
  167. package/dist/{chunk-7BFODYNL.cjs → chunk-UUT2VEN5.cjs} +7 -7
  168. package/dist/{chunk-7BFODYNL.cjs.map → chunk-UUT2VEN5.cjs.map} +1 -1
  169. package/dist/chunk-V3T7RO4F.js +21 -0
  170. package/dist/chunk-V3T7RO4F.js.map +1 -0
  171. package/dist/{chunk-GIEDIAPD.js → chunk-V5CM5TH3.js} +3 -3
  172. package/dist/{chunk-L65MHFMD.js → chunk-V64DICJK.js} +3 -3
  173. package/dist/{chunk-KIZVY57H.cjs → chunk-VXC7Z7XB.cjs} +5 -5
  174. package/dist/{chunk-KIZVY57H.cjs.map → chunk-VXC7Z7XB.cjs.map} +1 -1
  175. package/dist/chunk-VYF7WV4K.cjs +47 -0
  176. package/dist/chunk-VYF7WV4K.cjs.map +1 -0
  177. package/dist/{chunk-P4XZH3OR.js → chunk-WHQGJHMD.js} +4 -4
  178. package/dist/{chunk-TTLFY76J.cjs → chunk-WR77IZUU.cjs} +32 -9
  179. package/dist/chunk-WR77IZUU.cjs.map +1 -0
  180. package/dist/{chunk-O2BECFXJ.cjs → chunk-WTFEMOV5.cjs} +43 -22
  181. package/dist/chunk-WTFEMOV5.cjs.map +1 -0
  182. package/dist/{chunk-YAKTVIVK.js → chunk-XIUZT4TO.js} +3 -3
  183. package/dist/chunk-XPG56DLQ.cjs +103 -0
  184. package/dist/chunk-XPG56DLQ.cjs.map +1 -0
  185. package/dist/{chunk-GPVGGBIR.js → chunk-XWMXEJVZ.js} +2 -2
  186. package/dist/chunk-XZILHRKG.cjs +13 -0
  187. package/dist/chunk-XZILHRKG.cjs.map +1 -0
  188. package/dist/{chunk-VQGLVBPL.cjs → chunk-YIOHKQ6Y.cjs} +11 -4
  189. package/dist/chunk-YIOHKQ6Y.cjs.map +1 -0
  190. package/dist/{chunk-A3LMUPG3.js → chunk-Z3IJWYUD.js} +2 -2
  191. package/dist/{chunk-4J25XZDI.js → chunk-ZJWQPZ7E.js} +9 -2
  192. package/dist/chunk-ZJWQPZ7E.js.map +1 -0
  193. package/dist/color-picker/index.cjs +5 -4
  194. package/dist/color-picker/index.cjs.map +1 -1
  195. package/dist/color-picker/index.js +4 -3
  196. package/dist/combobox/index.cjs +7 -6
  197. package/dist/combobox/index.cjs.map +1 -1
  198. package/dist/combobox/index.js +6 -5
  199. package/dist/command-palette/index.cjs +4 -3
  200. package/dist/command-palette/index.cjs.map +1 -1
  201. package/dist/command-palette/index.js +3 -2
  202. package/dist/context-menu/index.cjs +7 -6
  203. package/dist/context-menu/index.cjs.map +1 -1
  204. package/dist/context-menu/index.d.cts +2 -2
  205. package/dist/context-menu/index.d.ts +2 -2
  206. package/dist/context-menu/index.js +6 -5
  207. package/dist/conversation/index.cjs +11 -8
  208. package/dist/conversation/index.cjs.map +1 -1
  209. package/dist/conversation/index.d.cts +3 -3
  210. package/dist/conversation/index.d.ts +3 -3
  211. package/dist/conversation/index.js +10 -7
  212. package/dist/data-grid/index.cjs +18 -15
  213. package/dist/data-grid/index.cjs.map +1 -1
  214. package/dist/data-grid/index.d.cts +8 -8
  215. package/dist/data-grid/index.d.ts +8 -8
  216. package/dist/data-grid/index.js +17 -14
  217. package/dist/date-picker/index.cjs +11 -8
  218. package/dist/date-picker/index.cjs.map +1 -1
  219. package/dist/date-picker/index.d.cts +2 -2
  220. package/dist/date-picker/index.d.ts +2 -2
  221. package/dist/date-picker/index.js +10 -7
  222. package/dist/drawer/index.cjs +8 -5
  223. package/dist/drawer/index.cjs.map +1 -1
  224. package/dist/drawer/index.d.cts +5 -4
  225. package/dist/drawer/index.d.ts +5 -4
  226. package/dist/drawer/index.js +7 -4
  227. package/dist/dropdown/index.cjs +4 -3
  228. package/dist/dropdown/index.cjs.map +1 -1
  229. package/dist/dropdown/index.js +3 -2
  230. package/dist/header/index.cjs +9 -6
  231. package/dist/header/index.cjs.map +1 -1
  232. package/dist/header/index.d.cts +10 -10
  233. package/dist/header/index.d.ts +10 -10
  234. package/dist/header/index.js +8 -5
  235. package/dist/index.cjs +56 -43
  236. package/dist/index.cjs.map +1 -1
  237. package/dist/index.css +48 -14
  238. package/dist/index.d.cts +14 -13
  239. package/dist/index.d.ts +14 -13
  240. package/dist/index.js +60 -47
  241. package/dist/inline-edit/index.cjs +6 -5
  242. package/dist/inline-edit/index.cjs.map +1 -1
  243. package/dist/inline-edit/index.js +5 -4
  244. package/dist/input/index.cjs +5 -4
  245. package/dist/input/index.cjs.map +1 -1
  246. package/dist/input/index.d.cts +3 -3
  247. package/dist/input/index.d.ts +3 -3
  248. package/dist/input/index.js +4 -3
  249. package/dist/link-provider/index.cjs +12 -0
  250. package/dist/link-provider/index.cjs.map +1 -0
  251. package/dist/link-provider/index.d.cts +43 -0
  252. package/dist/link-provider/index.d.ts +43 -0
  253. package/dist/link-provider/index.js +12 -0
  254. package/dist/link-provider/index.js.map +1 -0
  255. package/dist/lucide-icons/index.cjs +9 -0
  256. package/dist/lucide-icons/index.cjs.map +1 -0
  257. package/dist/lucide-icons/index.d.cts +2 -0
  258. package/dist/lucide-icons/index.d.ts +2 -0
  259. package/dist/lucide-icons/index.js +9 -0
  260. package/dist/lucide-icons/index.js.map +1 -0
  261. package/dist/menu/index.cjs +6 -5
  262. package/dist/menu/index.cjs.map +1 -1
  263. package/dist/menu/index.d.cts +3 -3
  264. package/dist/menu/index.d.ts +3 -3
  265. package/dist/menu/index.js +5 -4
  266. package/dist/modal/index.cjs +8 -5
  267. package/dist/modal/index.cjs.map +1 -1
  268. package/dist/modal/index.d.cts +2 -2
  269. package/dist/modal/index.d.ts +2 -2
  270. package/dist/modal/index.js +7 -4
  271. package/dist/navigation/index.cjs +8 -5
  272. package/dist/navigation/index.cjs.map +1 -1
  273. package/dist/navigation/index.d.cts +3 -3
  274. package/dist/navigation/index.d.ts +3 -3
  275. package/dist/navigation/index.js +7 -4
  276. package/dist/number-input/index.cjs +4 -3
  277. package/dist/number-input/index.cjs.map +1 -1
  278. package/dist/number-input/index.js +3 -2
  279. package/dist/page-layout/index.cjs +16 -13
  280. package/dist/page-layout/index.cjs.map +1 -1
  281. package/dist/page-layout/index.d.cts +8 -8
  282. package/dist/page-layout/index.d.ts +8 -8
  283. package/dist/page-layout/index.js +15 -12
  284. package/dist/pagination/index.cjs +11 -8
  285. package/dist/pagination/index.cjs.map +1 -1
  286. package/dist/pagination/index.js +10 -7
  287. package/dist/popover/index.cjs +4 -3
  288. package/dist/popover/index.cjs.map +1 -1
  289. package/dist/popover/index.d.cts +1 -1
  290. package/dist/popover/index.d.ts +1 -1
  291. package/dist/popover/index.js +3 -2
  292. package/dist/renderIcon-BW3PUtg8.d.cts +50 -0
  293. package/dist/renderIcon-BW3PUtg8.d.ts +50 -0
  294. package/dist/segmented-control/index.cjs +5 -4
  295. package/dist/segmented-control/index.cjs.map +1 -1
  296. package/dist/segmented-control/index.d.cts +3 -3
  297. package/dist/segmented-control/index.d.ts +3 -3
  298. package/dist/segmented-control/index.js +4 -3
  299. package/dist/select/index.cjs +7 -6
  300. package/dist/select/index.cjs.map +1 -1
  301. package/dist/select/index.d.cts +4 -4
  302. package/dist/select/index.d.ts +4 -4
  303. package/dist/select/index.js +6 -5
  304. package/dist/snackbar/index.cjs +8 -5
  305. package/dist/snackbar/index.cjs.map +1 -1
  306. package/dist/snackbar/index.js +7 -4
  307. package/dist/split-button/index.cjs +7 -6
  308. package/dist/split-button/index.cjs.map +1 -1
  309. package/dist/split-button/index.d.cts +2 -2
  310. package/dist/split-button/index.d.ts +2 -2
  311. package/dist/split-button/index.js +6 -5
  312. package/dist/split-chip/index.cjs +8 -5
  313. package/dist/split-chip/index.cjs.map +1 -1
  314. package/dist/split-chip/index.d.cts +2 -2
  315. package/dist/split-chip/index.d.ts +2 -2
  316. package/dist/split-chip/index.js +7 -4
  317. package/dist/table/index.cjs +16 -13
  318. package/dist/table/index.cjs.map +1 -1
  319. package/dist/table/index.d.cts +4 -4
  320. package/dist/table/index.d.ts +4 -4
  321. package/dist/table/index.js +15 -12
  322. package/dist/tabs/index.cjs +4 -3
  323. package/dist/tabs/index.cjs.map +1 -1
  324. package/dist/tabs/index.d.cts +1 -1
  325. package/dist/tabs/index.d.ts +1 -1
  326. package/dist/tabs/index.js +3 -2
  327. package/dist/tag-input/index.cjs +9 -6
  328. package/dist/tag-input/index.cjs.map +1 -1
  329. package/dist/tag-input/index.js +8 -5
  330. package/dist/textarea/index.cjs +5 -4
  331. package/dist/textarea/index.cjs.map +1 -1
  332. package/dist/textarea/index.d.cts +1 -1
  333. package/dist/textarea/index.d.ts +1 -1
  334. package/dist/textarea/index.js +4 -3
  335. package/dist/theme-editor/index.cjs +14 -11
  336. package/dist/theme-editor/index.cjs.map +1 -1
  337. package/dist/theme-editor/index.js +13 -10
  338. package/dist/theme-provider/index.cjs +4 -3
  339. package/dist/theme-provider/index.cjs.map +1 -1
  340. package/dist/theme-provider/index.js +3 -2
  341. package/dist/timeline/index.cjs +2 -2
  342. package/dist/timeline/index.d.cts +18 -3
  343. package/dist/timeline/index.d.ts +18 -3
  344. package/dist/timeline/index.js +1 -1
  345. package/dist/toolbar/index.cjs +12 -9
  346. package/dist/toolbar/index.cjs.map +1 -1
  347. package/dist/toolbar/index.d.cts +7 -7
  348. package/dist/toolbar/index.d.ts +7 -7
  349. package/dist/toolbar/index.js +11 -8
  350. package/dist/tooltip/index.cjs +4 -3
  351. package/dist/tooltip/index.cjs.map +1 -1
  352. package/dist/tooltip/index.js +3 -2
  353. package/package.json +4 -2
  354. package/dist/Button.types-BH0CPyPx.d.ts +0 -33
  355. package/dist/Button.types-DZRCVqyN.d.cts +0 -33
  356. package/dist/chunk-35LGEPLP.cjs.map +0 -1
  357. package/dist/chunk-36JFXFM2.cjs.map +0 -1
  358. package/dist/chunk-3KBBJZHK.cjs.map +0 -1
  359. package/dist/chunk-4J25XZDI.js.map +0 -1
  360. package/dist/chunk-5O73AALP.cjs.map +0 -1
  361. package/dist/chunk-75GFIQRU.js.map +0 -1
  362. package/dist/chunk-DA375AI6.cjs +0 -88
  363. package/dist/chunk-DA375AI6.cjs.map +0 -1
  364. package/dist/chunk-DRXPTACG.js.map +0 -1
  365. package/dist/chunk-GWHZFX2H.js.map +0 -1
  366. package/dist/chunk-HEXAY6DE.cjs.map +0 -1
  367. package/dist/chunk-LGDODZHI.js.map +0 -1
  368. package/dist/chunk-NEQXEVHM.js +0 -34
  369. package/dist/chunk-NEQXEVHM.js.map +0 -1
  370. package/dist/chunk-O2BECFXJ.cjs.map +0 -1
  371. package/dist/chunk-OOCCSMWM.js.map +0 -1
  372. package/dist/chunk-RHHZRTWM.js.map +0 -1
  373. package/dist/chunk-SNRRF64M.js.map +0 -1
  374. package/dist/chunk-TTLFY76J.cjs.map +0 -1
  375. package/dist/chunk-VQGLVBPL.cjs.map +0 -1
  376. package/dist/chunk-WE2SBWZ6.js.map +0 -1
  377. package/dist/chunk-ZMDZGL5A.cjs +0 -34
  378. package/dist/chunk-ZMDZGL5A.cjs.map +0 -1
  379. package/dist/renderIcon-C2lEMMzb.d.cts +0 -30
  380. package/dist/renderIcon-C2lEMMzb.d.ts +0 -30
  381. /package/dist/{chunk-L7I5NEGI.js.map → chunk-2IXCEKLI.js.map} +0 -0
  382. /package/dist/{chunk-RHFD2Z5V.js.map → chunk-3TF2GZSG.js.map} +0 -0
  383. /package/dist/{chunk-JHX6JK3M.js.map → chunk-3X6QVHTD.js.map} +0 -0
  384. /package/dist/{chunk-MQAOXZD4.js.map → chunk-4S57PE43.js.map} +0 -0
  385. /package/dist/{chunk-JT4KVXJK.js.map → chunk-4V2XYUQL.js.map} +0 -0
  386. /package/dist/{chunk-AR2ZOO6L.js.map → chunk-6FXFKMJ5.js.map} +0 -0
  387. /package/dist/{chunk-YP4HUBKN.js.map → chunk-6NAOAKII.js.map} +0 -0
  388. /package/dist/{chunk-D7SQ7LHJ.js.map → chunk-BO3KK3ZQ.js.map} +0 -0
  389. /package/dist/{chunk-5XH2PHT2.js.map → chunk-CNTG7OOO.js.map} +0 -0
  390. /package/dist/{chunk-WNDDS367.js.map → chunk-DPTTDHZ5.js.map} +0 -0
  391. /package/dist/{chunk-BFKPJ627.js.map → chunk-FHOD3FUN.js.map} +0 -0
  392. /package/dist/{chunk-SDUGYJGW.js.map → chunk-H3C6YECZ.js.map} +0 -0
  393. /package/dist/{chunk-MPIVBAMY.js.map → chunk-HYRLK462.js.map} +0 -0
  394. /package/dist/{chunk-FIVMMCGM.js.map → chunk-IHPSRTVW.js.map} +0 -0
  395. /package/dist/{chunk-THCTUBX6.js.map → chunk-IKXXXVUO.js.map} +0 -0
  396. /package/dist/{chunk-24HKKSKX.js.map → chunk-L6ERHCQ2.js.map} +0 -0
  397. /package/dist/{chunk-4LNTZPSQ.js.map → chunk-L6YJ6QTZ.js.map} +0 -0
  398. /package/dist/{chunk-JNY7TUDS.js.map → chunk-MCPGI6EI.js.map} +0 -0
  399. /package/dist/{chunk-2PCCGQOH.js.map → chunk-P6OJQ2RN.js.map} +0 -0
  400. /package/dist/{chunk-YXRKBKFB.js.map → chunk-S5CMZFX6.js.map} +0 -0
  401. /package/dist/{chunk-HEX4IMLO.js.map → chunk-TJQNGJHP.js.map} +0 -0
  402. /package/dist/{chunk-SFFKQQ5Z.js.map → chunk-U4SVBE2M.js.map} +0 -0
  403. /package/dist/{chunk-O3QM3BFE.js.map → chunk-UC4NYF6T.js.map} +0 -0
  404. /package/dist/{chunk-GIEDIAPD.js.map → chunk-V5CM5TH3.js.map} +0 -0
  405. /package/dist/{chunk-L65MHFMD.js.map → chunk-V64DICJK.js.map} +0 -0
  406. /package/dist/{chunk-P4XZH3OR.js.map → chunk-WHQGJHMD.js.map} +0 -0
  407. /package/dist/{chunk-YAKTVIVK.js.map → chunk-XIUZT4TO.js.map} +0 -0
  408. /package/dist/{chunk-GPVGGBIR.js.map → chunk-XWMXEJVZ.js.map} +0 -0
  409. /package/dist/{chunk-A3LMUPG3.js.map → chunk-Z3IJWYUD.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/Conversation/Chat.component.tsx","../src/components/Conversation/MessageComposer.component.tsx","../src/components/Conversation/Conversation.hooks.ts","../src/components/Conversation/Conversation.utils.ts","../src/components/Conversation/MessageItem.component.tsx","../src/components/Conversation/CommentThread.component.tsx"],"sourcesContent":["import React, { useCallback, useMemo } from 'react';\nimport { ArrowDown, MessagesSquare } from 'lucide-react';\nimport { Button } from '../Button';\nimport { EmptyState } from '../EmptyState';\nimport { Skeleton } from '../Skeleton';\nimport { Spinner } from '../Spinner';\nimport { MessageComposer } from './MessageComposer.component';\nimport { MessageItem } from './MessageItem.component';\nimport type { ChatProps, ConversationMessage } from './Conversation.types';\nimport {\n useLoadMoreOnScrollTop,\n useNewMessageIds,\n useScrollAnchor,\n useStickToBottom,\n} from './Conversation.hooks';\nimport { classNames, continuesRun, formatDateSeparator, isSameDay } from './Conversation.utils';\n\nconst ChatSkeleton: React.FC = () => (\n <div className=\"eidos-chat-skeleton\" aria-hidden=\"true\">\n {[0, 1, 2, 3].map((row) => (\n <div\n key={row}\n className={classNames(\n 'eidos-chat-skeleton-row',\n row % 2 === 1 && 'eidos-chat-skeleton-row--own',\n )}\n >\n <Skeleton variant=\"circular\" width={28} height={28} />\n <Skeleton variant=\"rounded\" height={48} />\n </div>\n ))}\n </div>\n);\n\n/**\n * A bottom-anchored message thread with a composer.\n *\n * Controlled and transport-agnostic: it renders the `messages` it is given and\n * reports intent through `onSend` / `onLoadMore`. It never fetches, so the\n * same array can be persisted and replayed verbatim.\n */\nexport const Chat: React.FC<ChatProps> = ({\n messages,\n currentUserId,\n onSend,\n onRetry,\n readOnly = false,\n readOnlyMessage,\n renderBody,\n messageActions,\n renderMessageFooter,\n loading = false,\n emptyContent,\n hasMore = false,\n loadingMore = false,\n onLoadMore,\n groupConsecutive = true,\n groupWindowMinutes = 5,\n showDateSeparators = true,\n formatTimestamp,\n animateNewMessages = true,\n allowAttachments = false,\n attachmentAccept,\n typing,\n unreadFromId,\n placeholder = 'Write a message...',\n sendOnEnter = true,\n ariaLabel = 'Conversation',\n className = '',\n}) => {\n const { scrollRef, atBottom, scrollToBottom, handleScroll } = useStickToBottom(messages);\n const newIds = useNewMessageIds(messages, animateNewMessages);\n useScrollAnchor(scrollRef, messages);\n\n const loadMoreOnScroll = useLoadMoreOnScrollTop(scrollRef, { hasMore, loadingMore, onLoadMore });\n\n const onScroll = useCallback(() => {\n handleScroll();\n loadMoreOnScroll();\n }, [handleScroll, loadMoreOnScroll]);\n\n const byId = useMemo(() => new Map(messages.map((message) => [message.id, message])), [messages]);\n\n // An id that isn't in the current page must not draw a divider above\n // nothing - it would float at the top of whatever happens to be loaded.\n const unreadIndex = useMemo(() => {\n if (!unreadFromId) return -1;\n return messages.findIndex((message) => message.id === unreadFromId);\n }, [messages, unreadFromId]);\n\n const showComposer = !readOnly && Boolean(onSend);\n const isEmpty = !loading && messages.length === 0;\n\n const renderMessage = (message: ConversationMessage, index: number) => {\n const previous = messages[index - 1];\n const actions = readOnly ? undefined : messageActions?.(message);\n const quoted = message.parentId ? byId.get(message.parentId) : undefined;\n\n const nodes: React.ReactNode[] = [];\n\n if (showDateSeparators && (!previous || !isSameDay(previous.sentAt, message.sentAt))) {\n nodes.push(\n <li key={`date-${message.id}`} className=\"eidos-conversation-separator\">\n <span>{formatDateSeparator(message.sentAt)}</span>\n </li>,\n );\n }\n\n if (index === unreadIndex) {\n nodes.push(\n <li\n key={`unread-${message.id}`}\n className=\"eidos-conversation-separator eidos-conversation-separator--unread\"\n >\n <span>Unread messages</span>\n </li>,\n );\n }\n\n // A separator breaks a run: the message under it needs its own header.\n const grouped =\n groupConsecutive &&\n index !== unreadIndex &&\n nodes.length === 0 &&\n continuesRun(previous, message, groupWindowMinutes);\n\n nodes.push(\n <MessageItem\n key={message.id}\n message={message}\n layout=\"chat\"\n isOwn={Boolean(currentUserId) && message.author.id === currentUserId}\n grouped={grouped}\n isNew={newIds.has(message.id)}\n actions={actions}\n footer={renderMessageFooter?.(message)}\n body={renderBody?.(message)}\n onRetry={!readOnly && onRetry ? () => onRetry(message) : undefined}\n quoted={quoted}\n formatTimestamp={formatTimestamp}\n />,\n );\n\n return nodes;\n };\n\n return (\n <div className={classNames('eidos-chat', className)}>\n <div\n ref={scrollRef}\n className=\"eidos-chat-scroll\"\n onScroll={onScroll}\n role=\"log\"\n aria-live=\"polite\"\n aria-relevant=\"additions\"\n aria-busy={loading}\n aria-label={ariaLabel}\n tabIndex={0}\n >\n {hasMore && (\n <div className=\"eidos-chat-load-more\">\n {loadingMore ? (\n <span className=\"eidos-chat-loading-more\">\n <Spinner size=\"sm\" color=\"secondary\" />\n Loading earlier messages…\n </span>\n ) : (\n <Button variant=\"text\" color=\"secondary\" size=\"sm\" onClick={onLoadMore}>\n Load earlier messages\n </Button>\n )}\n </div>\n )}\n\n {loading && <ChatSkeleton />}\n\n {isEmpty &&\n (emptyContent ?? (\n <EmptyState\n icon={<MessagesSquare />}\n title=\"No messages yet\"\n description={\n showComposer ? 'Send the first message to start the conversation.' : undefined\n }\n size=\"sm\"\n />\n ))}\n\n {!loading && messages.length > 0 && (\n <ol className=\"eidos-conversation-list\">{messages.map(renderMessage)}</ol>\n )}\n\n {typing && typing.length > 0 && (\n <div className=\"eidos-chat-typing\" aria-live=\"polite\">\n <span className=\"eidos-chat-typing-dots\" aria-hidden=\"true\">\n <i />\n <i />\n <i />\n </span>\n {typing.length === 1\n ? `${typing[0].name} is typing…`\n : `${typing.length} people are typing…`}\n </div>\n )}\n </div>\n\n {!atBottom && messages.length > 0 && (\n <div className=\"eidos-chat-jump\">\n <Button\n size=\"sm\"\n variant=\"filled\"\n color=\"secondary\"\n preIcon={ArrowDown}\n onClick={() => scrollToBottom('smooth')}\n >\n Latest\n </Button>\n </div>\n )}\n\n {showComposer && (\n <div className=\"eidos-chat-composer\">\n <MessageComposer\n onSubmit={onSend as NonNullable<typeof onSend>}\n placeholder={placeholder}\n sendOnEnter={sendOnEnter}\n allowAttachments={allowAttachments}\n attachmentAccept={attachmentAccept}\n />\n </div>\n )}\n\n {readOnly && readOnlyMessage && (\n <p className=\"eidos-conversation-readonly\">{readOnlyMessage}</p>\n )}\n </div>\n );\n};\n\nChat.displayName = 'Chat';\n","import React, { useCallback, useId, useRef, useState } from 'react';\nimport { Paperclip, Send, X } from 'lucide-react';\nimport { Avatar } from '../Avatar';\nimport { Button } from '../Button';\nimport { Chip } from '../Chip';\nimport type { MessageComposerProps } from './Conversation.types';\nimport { useAutoGrow } from './Conversation.hooks';\nimport { classNames, formatFileSize } from './Conversation.utils';\n\n/**\n * The authoring half of a conversation - a growing text field, optional\n * attachments, and a submit control.\n *\n * Exported on its own so a consumer building a bespoke list can still reuse\n * the input, and used internally by both `Chat` and `CommentThread`.\n */\nexport const MessageComposer: React.FC<MessageComposerProps> = ({\n value,\n onChange,\n onSubmit,\n onCancel,\n placeholder = 'Write a message...',\n submitLabel = 'Send',\n sendOnEnter = false,\n parentId,\n replyingTo,\n allowAttachments = false,\n attachmentAccept,\n author,\n disabled = false,\n requireBody = true,\n autoFocus = false,\n maxLength,\n className = '',\n}) => {\n const [internalBody, setInternalBody] = useState('');\n const [attachments, setAttachments] = useState<File[]>([]);\n const [pending, setPending] = useState(false);\n\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const fileInputRef = useRef<HTMLInputElement>(null);\n const fileInputId = useId();\n\n const isControlled = value !== undefined;\n const body = isControlled ? value : internalBody;\n\n useAutoGrow(textareaRef, body);\n\n const setBody = useCallback(\n (next: string) => {\n if (!isControlled) setInternalBody(next);\n onChange?.(next);\n },\n [isControlled, onChange],\n );\n\n const canSubmit = !disabled && !pending && (!requireBody || body.trim().length > 0);\n\n const submit = useCallback(async () => {\n if (!canSubmit) return;\n\n const draft = { body: body.trim(), attachments, parentId };\n const result = onSubmit(draft);\n\n // A synchronous handler clears immediately; an async one keeps the draft\n // until it resolves, so a rejected send never loses what was typed.\n if (!(result instanceof Promise)) {\n setBody('');\n setAttachments([]);\n return;\n }\n\n setPending(true);\n try {\n await result;\n setBody('');\n setAttachments([]);\n } catch {\n // Intentionally swallowed: the draft stays put and the consumer owns\n // error reporting (a Snackbar, an Alert, ...). Rethrowing here would\n // surface as an unhandled rejection from a keystroke.\n } finally {\n setPending(false);\n }\n }, [canSubmit, body, attachments, parentId, onSubmit, setBody]);\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (!sendOnEnter) return;\n // Shift+Enter always inserts a newline; the modifier check also leaves\n // IME composition (which fires Enter to commit) alone.\n if (event.key !== 'Enter' || event.shiftKey || event.nativeEvent.isComposing) return;\n event.preventDefault();\n void submit();\n };\n\n const addFiles = (list: FileList | null) => {\n if (!list?.length) return;\n setAttachments((current) => [...current, ...Array.from(list)]);\n // Reset so selecting the same file twice in a row still fires `change`.\n if (fileInputRef.current) fileInputRef.current.value = '';\n };\n\n const removeAttachment = (index: number) =>\n setAttachments((current) => current.filter((_, i) => i !== index));\n\n return (\n <form\n className={classNames('eidos-message-composer', className)}\n onSubmit={(event) => {\n event.preventDefault();\n void submit();\n }}\n >\n {replyingTo && (\n <div className=\"eidos-composer-reply-hint\">\n <span>\n Replying to <strong>{replyingTo}</strong>\n </span>\n {onCancel && (\n <Button\n variant=\"text\"\n color=\"secondary\"\n size=\"sm\"\n icon={X}\n onClick={onCancel}\n tooltip=\"Cancel reply\"\n aria-label=\"Cancel reply\"\n />\n )}\n </div>\n )}\n\n <div className=\"eidos-composer-row\">\n {author && (\n <div className=\"eidos-composer-avatar\">\n <Avatar\n src={author.avatarSrc}\n name={author.name}\n size=\"sm\"\n color={author.avatarColor ?? 'gray'}\n />\n </div>\n )}\n\n <div className=\"eidos-composer-field\">\n <textarea\n ref={textareaRef}\n className=\"eidos-composer-input\"\n value={body}\n onChange={(event) => setBody(event.target.value)}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n disabled={disabled || pending}\n rows={1}\n maxLength={maxLength}\n // Opt-in and off by default. Only the reply composer sets it, where\n // the field appears in direct response to the user pressing Reply -\n // moving focus there is the expected outcome, not a hijack.\n autoFocus={autoFocus}\n aria-label={placeholder}\n />\n\n {attachments.length > 0 && (\n <ul className=\"eidos-composer-attachments\">\n {attachments.map((file, index) => (\n <li key={`${file.name}-${file.size}-${index}`}>\n <Chip\n size=\"sm\"\n variant=\"outlined\"\n color=\"secondary\"\n preIcon={Paperclip}\n onRemove={() => removeAttachment(index)}\n >\n {file.name}\n {file.size > 0 && ` (${formatFileSize(file.size)})`}\n </Chip>\n </li>\n ))}\n </ul>\n )}\n </div>\n </div>\n\n <div className=\"eidos-composer-actions\">\n <div className=\"eidos-composer-actions-start\">\n {allowAttachments && (\n <>\n <input\n ref={fileInputRef}\n id={fileInputId}\n type=\"file\"\n multiple\n accept={attachmentAccept}\n // Hidden from both the tab order and the accessibility\n // tree. It is a proxy: the visible button above opens the\n // file dialog via `.click()`, so this input is an\n // implementation detail, not a control.\n //\n // `visually-hidden` keeps an element *focusable* - that is\n // the point of it, for skip links and screen-reader-only\n // text - so a keyboard user landed on an invisible control\n // and met the same \"Attach files\" action twice. `FileUpload`\n // already gets this right with `display: none` +\n // `tabIndex={-1}`; these two had drifted from it.\n //\n // `aria-hidden` is safe here only *because* of the\n // `tabIndex={-1}` beside it - hiding a focusable element is\n // its own violation.\n className=\"eidos-composer-file-input\"\n tabIndex={-1}\n aria-hidden=\"true\"\n onChange={(event) => addFiles(event.target.files)}\n disabled={disabled || pending}\n />\n <Button\n variant=\"text\"\n color=\"secondary\"\n size=\"sm\"\n icon={Paperclip}\n tooltip=\"Attach files\"\n aria-label=\"Attach files\"\n disabled={disabled || pending}\n onClick={() => fileInputRef.current?.click()}\n />\n </>\n )}\n {sendOnEnter && (\n <span className=\"eidos-composer-hint\">\n <kbd>Enter</kbd> to send · <kbd>Shift</kbd>+<kbd>Enter</kbd> for a new line\n </span>\n )}\n </div>\n\n <div className=\"eidos-composer-actions-end\">\n {onCancel && !replyingTo && (\n <Button\n variant=\"text\"\n color=\"secondary\"\n size=\"sm\"\n onClick={onCancel}\n disabled={pending}\n >\n Cancel\n </Button>\n )}\n <Button\n type=\"submit\"\n size=\"sm\"\n color=\"primary\"\n preIcon={Send}\n loading={pending}\n disabled={!canSubmit}\n >\n {submitLabel}\n </Button>\n </div>\n </div>\n </form>\n );\n};\n\nMessageComposer.displayName = 'MessageComposer';\n","import { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';\nimport type { ConversationMessage } from './Conversation.types';\n\n/**\n * Ids that arrived *after* the first render.\n *\n * Seeded from the first commit so an initial page of history is never\n * animated - otherwise opening a thread fades forty messages in at once,\n * which reads as a glitch rather than as feedback. Only genuinely new ids get\n * the entrance class, and each one only once.\n */\nexport const useNewMessageIds = (\n messages: ConversationMessage[],\n enabled: boolean,\n): Set<string> => {\n const seen = useRef<Set<string> | null>(null);\n const [fresh, setFresh] = useState<Set<string>>(() => new Set());\n\n useEffect(() => {\n // First commit: everything already on screen counts as pre-existing.\n if (seen.current === null) {\n seen.current = new Set(messages.map((message) => message.id));\n return;\n }\n\n if (!enabled) {\n for (const message of messages) seen.current.add(message.id);\n return;\n }\n\n const added = messages.filter((message) => !seen.current?.has(message.id));\n if (!added.length) return;\n\n for (const message of added) seen.current.add(message.id);\n setFresh(new Set(added.map((message) => message.id)));\n }, [messages, enabled]);\n\n return fresh;\n};\n\ninterface StickToBottom {\n scrollRef: React.RefObject<HTMLDivElement | null>;\n /** The viewport is at (or near) the newest message. */\n atBottom: boolean;\n scrollToBottom: (behavior?: ScrollBehavior) => void;\n handleScroll: () => void;\n}\n\n/** Distance from the bottom still counted as \"reading the newest message\". */\nconst BOTTOM_THRESHOLD_PX = 48;\n\n/**\n * Keeps a bottom-anchored list pinned to the newest message - but only while\n * the reader is already there.\n *\n * Scrolling someone back down while they are reading scrollback is the single\n * most common defect in chat UIs, so arrival of a new message only forces a\n * scroll when `atBottom` was already true. Otherwise the caller surfaces a\n * jump-to-latest affordance and leaves the viewport alone.\n */\nexport const useStickToBottom = (messages: ConversationMessage[]): StickToBottom => {\n const scrollRef = useRef<HTMLDivElement>(null);\n const [atBottom, setAtBottom] = useState(true);\n // Read during a layout effect, so it must not be state - it has to be\n // correct for the commit that is happening right now, not the next render.\n const atBottomRef = useRef(true);\n const lastCount = useRef(messages.length);\n\n const scrollToBottom = useCallback((behavior: ScrollBehavior = 'smooth') => {\n const node = scrollRef.current;\n if (!node) return;\n node.scrollTo({ top: node.scrollHeight, behavior });\n }, []);\n\n const handleScroll = useCallback(() => {\n const node = scrollRef.current;\n if (!node) return;\n const distance = node.scrollHeight - node.scrollTop - node.clientHeight;\n const next = distance <= BOTTOM_THRESHOLD_PX;\n atBottomRef.current = next;\n setAtBottom((current) => (current === next ? current : next));\n }, []);\n\n // Jump (not animate) to the bottom on first paint so a thread opens on its\n // newest message instead of visibly scrolling there.\n useLayoutEffect(() => {\n scrollToBottom('auto');\n // eslint-disable-next-line react-hooks/exhaustive-deps -- mount only\n }, []);\n\n useLayoutEffect(() => {\n if (messages.length > lastCount.current && atBottomRef.current) {\n scrollToBottom('smooth');\n }\n lastCount.current = messages.length;\n }, [messages.length, scrollToBottom]);\n\n return { scrollRef, atBottom, scrollToBottom, handleScroll };\n};\n\n/**\n * Preserves the reader's position when older messages are prepended.\n *\n * Without this, inserting a page above the viewport pushes the content the\n * user was reading down by the height of everything added, which reads as the\n * list jumping to a random place. Capturing `scrollHeight` before the DOM\n * mutation and restoring the delta in a *layout* effect corrects it before the\n * browser paints, so there is no visible shift.\n */\nexport const useScrollAnchor = (\n scrollRef: React.RefObject<HTMLDivElement | null>,\n messages: ConversationMessage[],\n): void => {\n const previous = useRef({ height: 0, firstId: '', count: 0 });\n\n useLayoutEffect(() => {\n const node = scrollRef.current;\n if (!node) return;\n\n const firstId = messages[0]?.id ?? '';\n const before = previous.current;\n // A prepend is the only case where the first id changes while the list\n // grows - an append leaves it untouched, and a replacement shrinks it.\n const prepended =\n before.firstId !== '' && before.firstId !== firstId && messages.length > before.count;\n\n if (prepended) {\n node.scrollTop += node.scrollHeight - before.height;\n }\n\n previous.current = { height: node.scrollHeight, firstId, count: messages.length };\n }, [messages, scrollRef]);\n};\n\n/**\n * Fires `onLoadMore` once the reader approaches the top of the history.\n *\n * Latched on the way in and released only after they scroll back out of the\n * trigger zone, so a single pause near the top can't queue a dozen fetches.\n */\nexport const useLoadMoreOnScrollTop = (\n scrollRef: React.RefObject<HTMLDivElement | null>,\n {\n hasMore,\n loadingMore,\n onLoadMore,\n }: {\n hasMore?: boolean;\n loadingMore?: boolean;\n onLoadMore?: () => void;\n },\n thresholdPx = 80,\n): (() => void) => {\n const armed = useRef(true);\n\n return useCallback(() => {\n const node = scrollRef.current;\n if (!node) return;\n\n if (node.scrollTop > thresholdPx) {\n armed.current = true;\n return;\n }\n\n if (!armed.current || !hasMore || loadingMore || !onLoadMore) return;\n armed.current = false;\n onLoadMore();\n }, [scrollRef, hasMore, loadingMore, onLoadMore, thresholdPx]);\n};\n\n/**\n * Grows a textarea to fit its content, up to `maxHeight`.\n *\n * Height is written to `style.height` directly rather than through a React\n * inline style: it is measured from the live DOM after every keystroke, so it\n * cannot be expressed as a class, and routing it through state would add a\n * render per character. Assigning the property imperatively also keeps it out\n * of the server-rendered `style` attribute that CSP's `style-src-attr` gates.\n */\nexport const useAutoGrow = (\n ref: React.RefObject<HTMLTextAreaElement | null>,\n value: string,\n maxHeight = 200,\n): void => {\n useLayoutEffect(() => {\n const node = ref.current;\n if (!node) return;\n\n node.style.height = 'auto';\n const next = Math.min(node.scrollHeight, maxHeight);\n node.style.height = `${next}px`;\n node.style.overflowY = node.scrollHeight > maxHeight ? 'auto' : 'hidden';\n }, [ref, value, maxHeight]);\n};\n","import type { ConversationMessage } from './Conversation.types';\n\n/**\n * Timestamp formatting goes through `Intl` rather than a date library on\n * purpose: `dayjs` is currently bundled only into the `DatePicker` chunk, and\n * pulling it in here would add it to every consumer importing a conversation.\n * `Intl` is built in and already locale-aware.\n */\n\nconst timeFormat = new Intl.DateTimeFormat(undefined, {\n hour: '2-digit',\n minute: '2-digit',\n});\n\nconst dateFormat = new Intl.DateTimeFormat(undefined, {\n day: 'numeric',\n month: 'long',\n year: 'numeric',\n});\n\nconst dateFormatSameYear = new Intl.DateTimeFormat(undefined, {\n day: 'numeric',\n month: 'long',\n});\n\n/** Parses an ISO string, returning null rather than an `Invalid Date`. */\nexport const parseDate = (iso: string): Date | null => {\n const date = new Date(iso);\n return Number.isNaN(date.getTime()) ? null : date;\n};\n\nexport const formatMessageTime = (iso: string): string => {\n const date = parseDate(iso);\n return date ? timeFormat.format(date) : iso;\n};\n\nconst startOfDay = (date: Date): number =>\n new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime();\n\nexport const isSameDay = (a: string, b: string): boolean => {\n const first = parseDate(a);\n const second = parseDate(b);\n if (!first || !second) return false;\n return startOfDay(first) === startOfDay(second);\n};\n\n/** `Today` / `Yesterday` / a full date, for the divider between days. */\nexport const formatDateSeparator = (iso: string): string => {\n const date = parseDate(iso);\n if (!date) return iso;\n\n const now = new Date();\n const dayDelta = Math.round((startOfDay(now) - startOfDay(date)) / 86_400_000);\n\n if (dayDelta === 0) return 'Today';\n if (dayDelta === 1) return 'Yesterday';\n return date.getFullYear() === now.getFullYear()\n ? dateFormatSameYear.format(date)\n : dateFormat.format(date);\n};\n\nconst FILE_UNITS = ['B', 'KB', 'MB', 'GB', 'TB'];\n\nexport const formatFileSize = (bytes: number): string => {\n if (!Number.isFinite(bytes) || bytes < 0) return '';\n if (bytes < 1024) return `${bytes} B`;\n\n let value = bytes;\n let unit = 0;\n while (value >= 1024 && unit < FILE_UNITS.length - 1) {\n value /= 1024;\n unit += 1;\n }\n // One decimal below 10 (9.4 MB), none above it (24 MB) - the extra digit\n // stops carrying information once the integer part is two digits.\n return `${value < 10 ? value.toFixed(1) : Math.round(value)} ${FILE_UNITS[unit]}`;\n};\n\n/**\n * Whether `message` continues a run started by `previous` - same author, same\n * day, and within the grouping window. A grouped message hides its avatar and\n * author line.\n */\nexport const continuesRun = (\n previous: ConversationMessage | undefined,\n message: ConversationMessage,\n windowMinutes: number,\n): boolean => {\n if (!previous) return false;\n if (previous.author.id !== message.author.id) return false;\n if (!isSameDay(previous.sentAt, message.sentAt)) return false;\n\n const before = parseDate(previous.sentAt);\n const after = parseDate(message.sentAt);\n if (!before || !after) return false;\n\n return Math.abs(after.getTime() - before.getTime()) <= windowMinutes * 60_000;\n};\n\nexport const sortBySentAt = (messages: ConversationMessage[]): ConversationMessage[] =>\n [...messages].sort((a, b) => {\n const first = parseDate(a.sentAt)?.getTime() ?? 0;\n const second = parseDate(b.sentAt)?.getTime() ?? 0;\n return first - second;\n });\n\nexport interface ThreadNode {\n message: ConversationMessage;\n replies: ConversationMessage[];\n}\n\n/**\n * Collapses a flat list into one level of nesting.\n *\n * Deeper chains are flattened onto the nearest **top-level** ancestor rather\n * than being dropped or nested further: indentation past one level is\n * unreadable on a phone, and silently discarding a reply-to-a-reply would lose\n * data the consumer stored. `replyingToName` on the rendered reply is what\n * preserves who was actually answered.\n *\n * A `parentId` pointing at a message that isn't present (paged out, deleted)\n * is treated as top-level, so nothing ever disappears from the list.\n */\nexport const buildThread = (messages: ConversationMessage[]): ThreadNode[] => {\n const byId = new Map(messages.map((message) => [message.id, message]));\n\n /** Walks up to the outermost ancestor, guarding against a parentId cycle. */\n const rootIdOf = (message: ConversationMessage): string => {\n const seen = new Set<string>([message.id]);\n let current = message;\n\n while (current.parentId) {\n const parent = byId.get(current.parentId);\n if (!parent || seen.has(parent.id)) break;\n seen.add(parent.id);\n current = parent;\n }\n\n return current.id;\n };\n\n const nodes = new Map<string, ThreadNode>();\n const roots: ThreadNode[] = [];\n\n for (const message of messages) {\n if (message.parentId && byId.has(message.parentId)) continue;\n const node: ThreadNode = { message, replies: [] };\n nodes.set(message.id, node);\n roots.push(node);\n }\n\n for (const message of messages) {\n if (!message.parentId || !byId.has(message.parentId)) continue;\n nodes.get(rootIdOf(message))?.replies.push(message);\n }\n\n for (const node of nodes.values()) {\n node.replies = sortBySentAt(node.replies);\n }\n\n return roots;\n};\n\n/** Name of the author a reply was addressed to, when it isn't its own parent. */\nexport const replyTargetName = (\n message: ConversationMessage,\n byId: Map<string, ConversationMessage>,\n rootId: string,\n): string | undefined => {\n if (!message.parentId || message.parentId === rootId) return undefined;\n return byId.get(message.parentId)?.author.name;\n};\n\n/** Trims a quoted excerpt so a long parent message can't dominate the reply. */\nexport const excerpt = (body: string, maxLength = 120): string => {\n const flat = body.replace(/\\s+/g, ' ').trim();\n return flat.length > maxLength ? `${flat.slice(0, maxLength - 1)}…` : flat;\n};\n\nexport const classNames = (...values: Array<string | false | null | undefined>): string =>\n values.filter(Boolean).join(' ');\n","import React from 'react';\nimport { AlertCircle, MoreHorizontal, Paperclip, RotateCw } from 'lucide-react';\nimport { Avatar } from '../Avatar';\nimport { Button } from '../Button';\nimport { Menu } from '../Menu';\nimport { Pill } from '../Pill';\nimport { Spinner } from '../Spinner';\nimport type { ConversationMessage, MessageAttachment } from './Conversation.types';\nimport type { MenuItemType } from '../Menu';\nimport { classNames, excerpt, formatFileSize, formatMessageTime } from './Conversation.utils';\n\nexport interface MessageItemProps {\n message: ConversationMessage;\n /** 'chat' right-aligns own messages into bubbles; 'comment' renders a flat card. */\n layout: 'chat' | 'comment';\n isOwn: boolean;\n /** Continues a run from the same author - hides the avatar and author line. */\n grouped: boolean;\n /** Plays the entrance animation. */\n isNew: boolean;\n actions?: MenuItemType[];\n footer?: React.ReactNode;\n body?: React.ReactNode;\n onRetry?: () => void;\n /** Author of the message being answered, for a flattened deep reply. */\n replyingToName?: string;\n /** Quoted parent, rendered above the body in chat layout. */\n quoted?: ConversationMessage;\n /** Reply affordance; omitted entirely when the viewer may not reply. */\n onReply?: () => void;\n formatTimestamp?: (iso: string) => string;\n}\n\nconst AttachmentList: React.FC<{ attachments: MessageAttachment[] }> = ({ attachments }) => (\n <ul className=\"eidos-message-attachments\">\n {attachments.map((attachment) => {\n const label = (\n <>\n <Paperclip aria-hidden=\"true\" />\n <span className=\"eidos-message-attachment-name\">{attachment.name}</span>\n {attachment.size !== undefined && (\n <span className=\"eidos-message-attachment-size\">{formatFileSize(attachment.size)}</span>\n )}\n </>\n );\n\n return (\n <li key={attachment.id} className=\"eidos-message-attachment\">\n {attachment.url ? (\n <a\n href={attachment.url}\n className=\"eidos-message-attachment-link\"\n target=\"_blank\"\n rel=\"noreferrer\"\n download={attachment.name}\n >\n {label}\n </a>\n ) : (\n <span className=\"eidos-message-attachment-link\">{label}</span>\n )}\n </li>\n );\n })}\n </ul>\n);\n\nexport const MessageItem: React.FC<MessageItemProps> = ({\n message,\n layout,\n isOwn,\n grouped,\n isNew,\n actions,\n footer,\n body,\n onRetry,\n replyingToName,\n quoted,\n onReply,\n formatTimestamp,\n}) => {\n const { author, status = 'sent' } = message;\n const timestamp = formatTimestamp\n ? formatTimestamp(message.sentAt)\n : formatMessageTime(message.sentAt);\n // An empty action list must not leave a dead trigger behind - see the\n // permissions note in Conversation.types.ts.\n const hasActions = Boolean(actions && actions.length > 0);\n\n // One placement per layout, rather than one per message.\n //\n // `chat` puts the time at the foot of the bubble, where a grouped message\n // already had it; it used to appear in the header for the first message of a\n // group and inside the bubble for the rest, so a single thread showed the\n // same fact in two places. `comment` keeps it in the header, where the row is\n // full width and has space for it.\n const timeInBubble = layout === 'chat';\n\n return (\n <li\n className={classNames(\n 'eidos-message',\n `eidos-message--${layout}`,\n isOwn && 'eidos-message--own',\n grouped && 'eidos-message--grouped',\n status !== 'sent' && `eidos-message--${status}`,\n isNew && 'eidos-message--enter',\n )}\n data-message-id={message.id}\n >\n <div className=\"eidos-message-avatar\">\n {!grouped && (\n <Avatar\n src={author.avatarSrc}\n name={author.name}\n size=\"sm\"\n color={author.avatarColor ?? 'gray'}\n />\n )}\n </div>\n\n <div className=\"eidos-message-main\">\n {!grouped && (\n <div className=\"eidos-message-header\">\n <span className=\"eidos-message-author\">{author.name}</span>\n {author.role && (\n <Pill size=\"sm\" variant=\"outlined\" color=\"secondary\">\n {author.role}\n </Pill>\n )}\n {!timeInBubble && (\n <time className=\"eidos-message-time\" dateTime={message.sentAt}>\n {timestamp}\n </time>\n )}\n {message.edited && <span className=\"eidos-message-edited\">edited</span>}\n </div>\n )}\n\n <div className=\"eidos-message-bubble\">\n {quoted && (\n <blockquote className=\"eidos-message-quote\">\n <span className=\"eidos-message-quote-author\">{quoted.author.name}</span>\n <span className=\"eidos-message-quote-body\">{excerpt(quoted.body)}</span>\n </blockquote>\n )}\n\n {replyingToName && (\n <span className=\"eidos-message-reply-target\">Replying to {replyingToName}</span>\n )}\n\n <div className=\"eidos-message-body\">{body ?? message.body}</div>\n\n {message.attachments && message.attachments.length > 0 && (\n <AttachmentList attachments={message.attachments} />\n )}\n\n {(timeInBubble || grouped) && (\n <time\n className=\"eidos-message-time eidos-message-time--inline\"\n dateTime={message.sentAt}\n >\n {timestamp}\n </time>\n )}\n </div>\n\n {status === 'sending' && (\n <span className=\"eidos-message-status\">\n <Spinner size=\"sm\" color=\"secondary\" />\n Sending…\n </span>\n )}\n\n {status === 'failed' && (\n <span className=\"eidos-message-status eidos-message-status--failed\">\n <AlertCircle aria-hidden=\"true\" />\n Not sent\n {onRetry && (\n <Button variant=\"text\" color=\"danger\" size=\"sm\" preIcon={RotateCw} onClick={onRetry}>\n Retry\n </Button>\n )}\n </span>\n )}\n\n {footer && <div className=\"eidos-message-footer\">{footer}</div>}\n\n {onReply && (\n <div className=\"eidos-message-reply\">\n <Button variant=\"text\" color=\"secondary\" size=\"sm\" onClick={onReply}>\n Reply\n </Button>\n </div>\n )}\n </div>\n\n {hasActions && (\n <div className=\"eidos-message-actions\">\n <Menu\n items={actions ?? []}\n trigger={\n <Button\n variant=\"text\"\n color=\"secondary\"\n size=\"sm\"\n icon={MoreHorizontal}\n aria-label={`Actions for ${author.name}'s message`}\n />\n }\n />\n </div>\n )}\n </li>\n );\n};\n\nMessageItem.displayName = 'MessageItem';\n","import React, { useCallback, useMemo, useState } from 'react';\nimport { MessageSquare } from 'lucide-react';\nimport { Button } from '../Button';\nimport { EmptyState } from '../EmptyState';\nimport { Skeleton } from '../Skeleton';\nimport { Spinner } from '../Spinner';\nimport { MessageComposer } from './MessageComposer.component';\nimport { MessageItem } from './MessageItem.component';\nimport type { CommentThreadProps, ConversationMessage, MessageDraft } from './Conversation.types';\nimport { useNewMessageIds } from './Conversation.hooks';\nimport {\n buildThread,\n classNames,\n continuesRun,\n replyTargetName,\n sortBySentAt,\n} from './Conversation.utils';\n\nconst CommentSkeleton: React.FC = () => (\n <div className=\"eidos-comment-thread-skeleton\" aria-hidden=\"true\">\n {[0, 1, 2].map((row) => (\n <div key={row} className=\"eidos-comment-thread-skeleton-row\">\n <Skeleton variant=\"circular\" width={28} height={28} />\n <Skeleton variant=\"text\" lines={2} />\n </div>\n ))}\n </div>\n);\n\n/**\n * A comment section: document flow, no internal scroll container, one level of\n * nesting.\n *\n * Shares its data model and message rendering with `Chat`, so history captured\n * in one can be displayed in the other. Unlike `Chat` it has no scroll region\n * of its own - it grows with the page and pages *downward* via `onLoadMore`.\n */\nexport const CommentThread: React.FC<CommentThreadProps> = ({\n messages,\n currentUserId,\n onSend,\n onReply,\n onRetry,\n readOnly = false,\n readOnlyMessage,\n renderBody,\n messageActions,\n renderMessageFooter,\n loading = false,\n emptyContent,\n hasMore = false,\n loadingMore = false,\n onLoadMore,\n groupConsecutive = true,\n groupWindowMinutes = 5,\n formatTimestamp,\n animateNewMessages = true,\n allowAttachments = false,\n attachmentAccept,\n order = 'oldest-first',\n composerPosition = 'bottom',\n placeholder = 'Add a comment...',\n sendOnEnter = false,\n title,\n ariaLabel = 'Comments',\n className = '',\n}) => {\n const [replyingToId, setReplyingToId] = useState<string | null>(null);\n const newIds = useNewMessageIds(messages, animateNewMessages);\n\n const byId = useMemo(() => new Map(messages.map((message) => [message.id, message])), [messages]);\n\n const roots = useMemo(() => {\n const thread = buildThread(messages);\n const sorted = sortBySentAt(thread.map((node) => node.message));\n const ordered = order === 'newest-first' ? [...sorted].reverse() : sorted;\n const nodeById = new Map(thread.map((node) => [node.message.id, node]));\n // Replies always read oldest-first, even when roots are reversed - a\n // conversation under a single comment is chronological by nature.\n return ordered.map((message) => nodeById.get(message.id)!);\n }, [messages, order]);\n\n const canReply = !readOnly && Boolean(onReply);\n const showComposer = !readOnly && Boolean(onSend);\n const isEmpty = !loading && messages.length === 0;\n const total = messages.length;\n\n const handleReply = useCallback(\n async (draft: MessageDraft) => {\n await onReply?.(draft);\n setReplyingToId(null);\n },\n [onReply],\n );\n\n const renderComment = (\n message: ConversationMessage,\n options: { rootId: string; previous?: ConversationMessage; isReply: boolean },\n ) => {\n const actions = readOnly ? undefined : messageActions?.(message);\n\n return (\n <MessageItem\n key={message.id}\n message={message}\n layout=\"comment\"\n isOwn={Boolean(currentUserId) && message.author.id === currentUserId}\n grouped={groupConsecutive && continuesRun(options.previous, message, groupWindowMinutes)}\n isNew={newIds.has(message.id)}\n actions={actions}\n footer={renderMessageFooter?.(message)}\n body={renderBody?.(message)}\n onRetry={!readOnly && onRetry ? () => onRetry(message) : undefined}\n replyingToName={\n options.isReply ? replyTargetName(message, byId, options.rootId) : undefined\n }\n onReply={canReply ? () => setReplyingToId(message.id) : undefined}\n formatTimestamp={formatTimestamp}\n />\n );\n };\n\n const composer = showComposer && (\n <MessageComposer\n onSubmit={onSend as NonNullable<typeof onSend>}\n placeholder={placeholder}\n submitLabel=\"Comment\"\n sendOnEnter={sendOnEnter}\n allowAttachments={allowAttachments}\n attachmentAccept={attachmentAccept}\n className=\"eidos-comment-thread-composer\"\n />\n );\n\n return (\n <section className={classNames('eidos-comment-thread', className)} aria-label={ariaLabel}>\n {(title || total > 0) && (\n <header className=\"eidos-comment-thread-header\">\n {title && <h3 className=\"eidos-comment-thread-title\">{title}</h3>}\n {total > 0 && (\n <span className=\"eidos-comment-thread-count\">\n {total} {total === 1 ? 'comment' : 'comments'}\n </span>\n )}\n </header>\n )}\n\n {composerPosition === 'top' && composer}\n\n {loading && <CommentSkeleton />}\n\n {isEmpty &&\n (emptyContent ?? (\n <EmptyState\n icon={<MessageSquare />}\n title=\"No comments yet\"\n description={showComposer ? 'Start the discussion by leaving a comment.' : undefined}\n size=\"sm\"\n />\n ))}\n\n {!loading && roots.length > 0 && (\n <ol className=\"eidos-conversation-list eidos-comment-thread-list\" aria-busy={loadingMore}>\n {roots.map((node) => (\n <li key={node.message.id} className=\"eidos-comment-thread-node\">\n <ol className=\"eidos-conversation-list\">\n {renderComment(node.message, { rootId: node.message.id, isReply: false })}\n </ol>\n\n {node.replies.length > 0 && (\n <ol className=\"eidos-conversation-list eidos-comment-thread-replies\">\n {node.replies.map((reply, index) =>\n renderComment(reply, {\n rootId: node.message.id,\n previous: node.replies[index - 1],\n isReply: true,\n }),\n )}\n </ol>\n )}\n\n {replyingToId &&\n (replyingToId === node.message.id ||\n node.replies.some((reply) => reply.id === replyingToId)) && (\n <div className=\"eidos-comment-thread-reply-composer\">\n <MessageComposer\n onSubmit={handleReply}\n onCancel={() => setReplyingToId(null)}\n parentId={replyingToId}\n replyingTo={byId.get(replyingToId)?.author.name}\n placeholder=\"Write a reply...\"\n submitLabel=\"Reply\"\n sendOnEnter={sendOnEnter}\n allowAttachments={allowAttachments}\n attachmentAccept={attachmentAccept}\n autoFocus\n />\n </div>\n )}\n </li>\n ))}\n </ol>\n )}\n\n {hasMore && (\n <div className=\"eidos-comment-thread-load-more\">\n {loadingMore ? (\n <span className=\"eidos-comment-thread-loading-more\">\n <Spinner size=\"sm\" color=\"secondary\" />\n Loading more comments…\n </span>\n ) : (\n <Button variant=\"outlined\" color=\"secondary\" size=\"sm\" onClick={onLoadMore}>\n Load more comments\n </Button>\n )}\n </div>\n )}\n\n {composerPosition === 'bottom' && composer}\n\n {readOnly && readOnlyMessage && (\n <p className=\"eidos-conversation-readonly\">{readOnlyMessage}</p>\n )}\n </section>\n );\n};\n\nCommentThread.displayName = 'CommentThread';\n"],"mappings":"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","names":["useCallback","useCallback","useRef","useState","useState","useRef","useCallback","Paperclip","Fragment","jsx","jsxs","Paperclip","jsx","jsxs","useCallback","useCallback","useMemo","useState","jsx","jsxs","useState","useMemo","useCallback"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["/home/runner/work/eidos-ui/eidos-ui/dist/chunk-TTLFY76J.cjs","../src/components/Chip/Chip.component.tsx"],"names":[],"mappings":"AAAA;AACE;AACF,wDAA6B;AAC7B;AACE;AACF,wDAA6B;AAC7B;AACA;ACNA,2CAAkB;AAoEd,+CAAA;AA/DG,IAAM,KAAA,EAA4B,CAAC;AAAA,EACxC,QAAA,EAAU,QAAA;AAAA,EACV,MAAA,EAAQ,SAAA;AAAA,EACR,KAAA,EAAO,IAAA;AAAA,EACP,SAAA,EAAW,KAAA;AAAA,EACX,UAAA,EAAY,KAAA;AAAA,EACZ,OAAA;AAAA,EACA,UAAA,EAAY,EAAA;AAAA,EACZ,OAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA;AAAA,EACA,GAAG;AACL,CAAA,EAAA,GAAM;AACJ,EAAA,MAAM,YAAA,EAAc,CAAC,CAAC,OAAA;AACtB,EAAA,MAAM,YAAA,EAAc,CAAC,CAAC,QAAA;AAGtB,EAAA,MAAM,YAAA,EAAc;AAAA,IAClB,YAAA;AAAA,IACA,CAAA,YAAA,EAAe,OAAO,CAAA,CAAA;AACF,IAAA;AACD,IAAA;AACP,IAAA;AACG,IAAA;AACA,IAAA;AACF,IAAA;AACb,IAAA;AAGM,EAAA;AAEY,EAAA;AACD,IAAA;AACT,IAAA;AACV,EAAA;AAEsB,EAAA;AACF,IAAA;AACD,IAAA;AACR,IAAA;AACX,EAAA;AAiBwB,EAAA;AACJ,EAAA;AAGlB,EAAA;AACyB,IAAA;AAEtB,oBAAA;AAEsB,IAAA;AACzB,EAAA;AAIA,EAAA;AAAC,IAAA;AAAA,IAAA;AACY,MAAA;AACD,MAAA;AACD,MAAA;AACL,MAAA;AAEH,MAAA;AACC,QAAA;AAAC,UAAA;AAAA,UAAA;AACM,YAAA;AACK,YAAA;AACD,YAAA;AACT,YAAA;AAEC,YAAA;AAAA,UAAA;AAGH,QAAA;AAIA,QAAA;AAAC,UAAA;AAAA,UAAA;AACW,YAAA;AACD,YAAA;AACT,YAAA;AACW,YAAA;AACN,YAAA;AAEL,YAAA;AAAuC,UAAA;AACzC,QAAA;AAAA,MAAA;AAAA,IAAA;AAEJ,EAAA;AAGe,EAAA;AACnB;ADzB2B;AACA;AACA;AACA","file":"/home/runner/work/eidos-ui/eidos-ui/dist/chunk-TTLFY76J.cjs","sourcesContent":[null,"import React from 'react';\nimport { X } from 'lucide-react';\nimport type { ChipProps } from './Chip.types';\nimport { Tooltip } from '../Tooltip/Tooltip.component';\nimport { renderIcon } from '../../utils';\n\nexport const Chip: React.FC<ChipProps> = ({\n variant = 'filled',\n color = 'primary',\n size = 'md',\n disabled = false,\n fullWidth = false,\n tooltip,\n className = '',\n preIcon,\n posIcon,\n children,\n onClick,\n onRemove,\n ...chipProps\n}) => {\n const isClickable = !!onClick;\n const isRemovable = !!onRemove;\n\n // Build CSS classes\n const chipClasses = [\n 'eidos-chip',\n `eidos-chip--${variant}`,\n `eidos-chip--${color}`,\n `eidos-chip--${size}`,\n disabled && 'eidos-chip--disabled',\n isClickable && 'eidos-chip--clickable',\n isRemovable && 'eidos-chip--removable',\n fullWidth && 'eidos-chip--full-width',\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n const handleClick = () => {\n if (disabled || !onClick) return;\n onClick();\n };\n\n const handleRemove = (e: React.MouseEvent) => {\n e.stopPropagation(); // Prevent chip click when removing\n if (disabled || !onRemove) return;\n onRemove();\n };\n\n // A chip that is both clickable and removable holds *two* controls, so it\n // has to render them as siblings.\n //\n // The previous shape switched the outer element to a `<div>` when\n // removable - the comment said \"to avoid nested buttons\" - and then gave\n // that div `role=\"button\"` and `tabIndex={0}`. That is the same defect\n // wearing a different hat: a button containing a button, which is invalid\n // (`nested-interactive`) and leaves a screen reader announcing a control\n // inside a control. It is the same shape already fixed on `Dropdown` and\n // `DataGrid`'s rows.\n //\n // Now the outer element is a plain container whenever there is a remove\n // button, and the chip's own action moves to an inner `<button>` wrapping\n // just the content. Each control is separately reachable and separately\n // named.\n const hasBothControls = isClickable && isRemovable;\n const ChipElement = isClickable && !isRemovable ? 'button' : 'div';\n\n const body = (\n <>\n {preIcon && renderIcon(preIcon, 'eidos-chip--pre-icon')}\n\n <span className=\"eidos-chip--copy\">{children}</span>\n\n {posIcon && renderIcon(posIcon, 'eidos-chip--pos-icon')}\n </>\n );\n\n const chipContent = (\n <ChipElement\n className={chipClasses}\n disabled={ChipElement === 'button' ? disabled : undefined}\n onClick={isClickable && !hasBothControls ? handleClick : undefined}\n {...chipProps}\n >\n {hasBothControls ? (\n <button\n type=\"button\"\n className=\"eidos-chip--action\"\n onClick={handleClick}\n disabled={disabled}\n >\n {body}\n </button>\n ) : (\n body\n )}\n\n {isRemovable && (\n <button\n className=\"eidos-chip--remove-button\"\n onClick={handleRemove}\n disabled={disabled}\n aria-label=\"Remove\"\n type=\"button\"\n >\n <X className=\"eidos-chip--remove-icon\" />\n </button>\n )}\n </ChipElement>\n );\n\n return tooltip ? <Tooltip message={tooltip}>{chipContent}</Tooltip> : chipContent;\n};\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["/home/runner/work/eidos-ui/eidos-ui/dist/chunk-VQGLVBPL.cjs","../src/components/Popover/Popover.component.tsx"],"names":[],"mappings":"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","file":"/home/runner/work/eidos-ui/eidos-ui/dist/chunk-VQGLVBPL.cjs","sourcesContent":[null,"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 isOpen,\n open: openProp,\n defaultOpen,\n onOpenChange,\n maxWidth = 320,\n className,\n contentClassName,\n}) => {\n // `isOpen`/`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` is the canonical name, matching `Dropdown` and `CommandPalette`.\n // `isOpen` is the original spelling, kept working rather than renamed out\n // from under anyone.\n const controlledOpen = openProp ?? isOpen;\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"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/ThemeEditor/ThemeEditor.component.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useMemo, useReducer, useRef, useState } from 'react';\nimport { CircleCheck, CircleX, TriangleAlert } from 'lucide-react';\nimport { Alert } from '../Alert';\nimport { Button, IconButton } from '../Button';\nimport { Card } from '../Card';\nimport { ColorPicker } from '../ColorPicker';\nimport { Select } from '../Select';\nimport { Slider } from '../Slider';\nimport { Tooltip } from '../Tooltip';\nimport { useTheme } from '../ThemeProvider';\nimport type { ThemeColorKey, ThemeFontOption } from '../ThemeProvider';\nimport {\n THEME_COLOR_KEYS,\n FONT_SCALE_MAX,\n FONT_SCALE_MIN,\n defaultTheme,\n} from '../ThemeProvider/ThemeProvider.tokens';\nimport {\n CONTRAST_DARK,\n CONTRAST_LIGHT,\n contrastRatio,\n pickContrast,\n} from '../ThemeProvider/ThemeProvider.color';\nimport {\n FONT_ACCEPT,\n isFontStackAvailable,\n registerFontFile,\n subscribeToFontLoads,\n toFontStack,\n} from '../ThemeProvider/ThemeProvider.fonts';\nimport type { ThemeEditorProps } from './ThemeEditor.types';\n\n/** The page surface every diagnostic is measured against - `--white`. */\nconst PAGE_SURFACE = CONTRAST_LIGHT;\n\n/** Below this, a fill is effectively invisible against the page behind it. */\nconst EDGE_MIN_RATIO = 1.5;\n\nconst COLOR_LABELS: Record<ThemeColorKey, string> = {\n primary: 'Primary',\n secondary: 'Secondary',\n success: 'Success',\n danger: 'Danger',\n warning: 'Warning',\n info: 'Info',\n hyperlink: 'Hyperlink',\n};\n\n/** `hyperlink` is only ever text on a surface, so it is graded differently. */\nconst isFill = (key: ThemeColorKey): boolean => key !== 'hyperlink';\n\n/**\n * Built-in stacks, deliberately limited to fonts that can be relied on.\n *\n * A dropdown implies its entries are available, but a font stack is only a list\n * of *names* - nothing here can install a font. So the list is restricted to\n * generic families (guaranteed by CSS), `system-ui` (whatever the OS provides),\n * and the handful of genuinely web-safe faces. Fonts like Inter, which are not\n * installed anywhere by default, were removed: offering one is offering a\n * choice that silently does nothing on most machines.\n *\n * The preset is included because it is the shipped default and therefore has to\n * be representable - and note that `eidos-ui` does not ship the Plus Jakarta\n * Sans file either, so it renders only where the consumer provides it. That is\n * exactly why unavailable options are labelled as such.\n *\n * Anything beyond this belongs to the consuming app, via `fontOptions`.\n */\nconst FONT_STACKS: ThemeFontOption[] = [\n // Taken from the preset rather than retyped, so the shipped default always\n // matches an option exactly. A hand-copied shorter stack did not match, and\n // the row fell back to showing a synthetic \"custom\" entry instead of the\n // name of the font actually in use.\n { label: 'Plus Jakarta Sans (theme default)', value: defaultTheme.typography.fontFamily! },\n { label: 'System UI', value: \"system-ui, -apple-system, 'Segoe UI', sans-serif\" },\n { label: 'Helvetica / Arial', value: 'Helvetica, Arial, sans-serif' },\n { label: 'Georgia', value: \"Georgia, 'Times New Roman', serif\" },\n { label: 'Sans-serif (generic)', value: 'sans-serif' },\n { label: 'Serif (generic)', value: 'serif' },\n];\n\nconst MONO_STACKS: ThemeFontOption[] = [\n { label: 'JetBrains Mono (theme default)', value: defaultTheme.typography.monoFamily! },\n { label: 'Menlo / Consolas', value: 'Menlo, Consolas, monospace' },\n { label: 'Courier New', value: \"'Courier New', Courier, monospace\" },\n { label: 'Monospace (generic)', value: 'monospace' },\n];\n\ntype Grade = 'aa' | 'aa-large' | 'fail';\n\nconst gradeFor = (ratio: number): Grade => (ratio >= 4.5 ? 'aa' : ratio >= 3 ? 'aa-large' : 'fail');\n\n/** Spelled out for the middle grade, which is the one that misleads. */\nconst GRADE_CAVEAT: Partial<Record<Grade, string>> = {\n 'aa-large':\n ' WCAG AA needs 4.5:1 for normal text and allows 3:1 only at 24px or larger - button and label text here is around 12px, so this does not pass.',\n fail: ' Below 3:1, which fails WCAG AA at every text size.',\n};\n\n/**\n * Severity is carried by an icon and the label text, not by colour.\n *\n * These badges cannot use `Pill`, or any themed `--x-color`: the theme being\n * edited also styles this editor, so a washed-out `success` colour would render\n * the \"passes AA\" badge illegible at precisely the moment it is reporting that\n * a colour is illegible. The badge styling comes from the gray ramp, which is\n * deliberately not themeable.\n *\n * Not relying on colour alone also satisfies WCAG 1.4.1 (Use of Colour).\n */\nconst GRADE_BADGE: Record<\n Grade,\n { label: string; icon: React.ComponentType<{ className?: string }> }\n> = {\n aa: { label: 'AA', icon: CircleCheck },\n // Named for what it means in practice, not just for the threshold it clears.\n // WCAG's relaxed 3:1 tier applies only to text at 24px (or 18.7px bold) and\n // above, and nothing in this library is that large - `--font-size-sm` is\n // ~12.25px at the default root size. A bare \"AA large only\" reads as a pass\n // when for every component here it is a fail.\n 'aa-large': { label: 'Too low for body text', icon: TriangleAlert },\n fail: { label: 'Fails AA', icon: CircleX },\n};\n\ninterface Diagnostic {\n grade: Grade;\n ratio: number;\n /** What the ratio describes, for the tooltip. */\n detail: string;\n /** Set when the fill is too close to the page surface to be seen. */\n edgeWarning?: string;\n}\n\nconst diagnose = (key: ThemeColorKey, base: string, explicitContrast?: string): Diagnostic => {\n if (!isFill(key)) {\n // Link text sits on the page, so the page is what it must contrast with.\n const ratio = contrastRatio(base, PAGE_SURFACE);\n const grade = gradeFor(ratio);\n return {\n grade,\n ratio,\n detail: `Link text on the page background: ${ratio.toFixed(2)}:1 against white.${GRADE_CAVEAT[grade] ?? ''}`,\n };\n }\n\n const foreground = explicitContrast ?? pickContrast(base);\n const ratio = contrastRatio(base, foreground);\n const name = foreground.toLowerCase() === CONTRAST_DARK ? 'dark' : 'white';\n const edge = contrastRatio(base, PAGE_SURFACE);\n\n const grade = gradeFor(ratio);\n\n return {\n grade,\n ratio,\n detail: `${name === 'white' ? 'White' : 'Near-black'} text on this fill is ${ratio.toFixed(2)}:1.${\n explicitContrast ? ' Foreground pinned via the theme.' : ''\n }${GRADE_CAVEAT[grade] ?? ''}`,\n edgeWarning:\n edge < EDGE_MIN_RATIO\n ? `Only ${edge.toFixed(2)}:1 against the page background - this fill is barely distinguishable from the page it sits on.`\n : undefined,\n };\n};\n\ninterface FontRowProps {\n label: string;\n /** Stack currently applied, used to pick the matching option. */\n value: string;\n options: ThemeFontOption[];\n mono: boolean;\n allowUpload: boolean;\n onChange: (stack: string) => void;\n onUploaded: (option: ThemeFontOption, file: File, family: string) => void;\n}\n\n/** Pulls the first family out of a stack, unquoted. */\nconst firstFamily = (stack: string): string =>\n stack\n .split(',')[0]\n ?.trim()\n .replace(/^['\"]|['\"]$/g, '') || 'Custom';\n\n/**\n * One font row: a `Select` over the known stacks, an optional upload, and an\n * availability warning.\n *\n * Uses `Select` rather than `Combobox` deliberately. `Combobox` filters its\n * options against the text in the field, and the field holds a full font stack\n * (`'Plus Jakarta Sans', -apple-system, …`) which matches no option label - so\n * the list read \"No results found\" until the text was cleared by hand. A font\n * is a choice from a known set, not a search.\n */\nconst FontRow: React.FC<FontRowProps> = ({\n label,\n value,\n options,\n mono,\n allowUpload,\n onChange,\n onUploaded,\n}) => {\n const inputRef = useRef<HTMLInputElement>(null);\n const [error, setError] = useState<string | null>(null);\n\n // Web fonts load asynchronously, so the first render always sees them as\n // unavailable. Without re-checking once they arrive, the row would sit on a\n // stale \"not installed\" warning for a font that is rendering perfectly.\n // The reducer exists only to schedule that re-render; its value is unused.\n const [, onFontsLoaded] = useReducer((count: number) => count + 1, 0);\n useEffect(() => subscribeToFontLoads(onFontsLoaded), [onFontsLoaded]);\n\n const baseOptions = useMemo(() => {\n // A stack the theme carries but that isn't in the list (loaded by the host\n // app, or set programmatically) still needs to be selectable, labelled with\n // its own first family so the row names the font actually in use.\n const known = options.some((o) => o.value === value);\n return known ? options : [...options, { label: `${firstFamily(value)} (custom)`, value }];\n }, [options, value]);\n\n // Probed on every render rather than memoised: availability changes over time\n // as fonts load, so a cached answer is a wrong answer. Four canvas\n // measurements are far cheaper than getting this wrong.\n //\n // Availability is annotated per option rather than filtered or disabled. A\n // theme is shared across machines, so a font present here may be absent for\n // the next user - and vice versa, which would mean hiding a font someone\n // legitimately wants. Annotating keeps every choice selectable while making\n // the list stop implying that a name is a guarantee.\n const selectOptions = baseOptions.map((option) => ({\n id: option.value,\n label: isFontStackAvailable(option.value) ? option.label : `${option.label} - not installed`,\n value: option.value,\n }));\n\n const handleFile = useCallback(\n async (file: File | undefined) => {\n if (!file) return;\n setError(null);\n try {\n const family = await registerFontFile(file);\n const stack = toFontStack(family, mono);\n onUploaded({ label: `${family} (this session)`, value: stack }, file, family);\n onChange(stack);\n } catch (cause) {\n setError(\n cause instanceof Error ? cause.message : 'That file could not be loaded as a font.',\n );\n }\n },\n [mono, onChange, onUploaded],\n );\n\n const unavailable = !isFontStackAvailable(value);\n\n return (\n <div className=\"eidos-theme-editor-row eidos-theme-editor-row--wide\">\n <span className=\"eidos-theme-editor-row__label\">{label}</span>\n\n <div className=\"eidos-theme-editor-row__control\">\n <Select\n options={selectOptions}\n value={value}\n onChange={(next) => onChange(Array.isArray(next) ? next[0] : next)}\n fullWidth\n // The row's visible label is a `<span>`, not a `<label htmlFor>`,\n // so nothing associates it with the control. Naming the input\n // directly keeps the two in step without restructuring the row.\n inputProps={{ 'aria-label': label }}\n />\n </div>\n\n {/* Occasional - lives before the action so it can never displace it. */}\n <div className=\"eidos-theme-editor-row__diagnostics\">\n {unavailable && (\n <Tooltip\n message={`${firstFamily(value)} isn't available here, so the browser is rendering the next family in the stack instead. Upload the file, or have your app serve it, to use it.`}\n >\n <span className=\"eidos-theme-editor-badge eidos-theme-editor-badge--aa-large\">\n <TriangleAlert className=\"eidos-theme-editor-badge__icon\" />\n Not installed\n </span>\n </Tooltip>\n )}\n {error && (\n <Tooltip message={error}>\n <span className=\"eidos-theme-editor-badge eidos-theme-editor-badge--fail\">\n <CircleX className=\"eidos-theme-editor-badge__icon\" />\n Upload failed\n </span>\n </Tooltip>\n )}\n </div>\n\n {allowUpload && (\n <div className=\"eidos-theme-editor-row__actions\">\n <Button\n variant=\"text\"\n color=\"secondary\"\n size=\"sm\"\n preIcon=\"Upload\"\n onClick={() => inputRef.current?.click()}\n tooltip=\"Load a font file to use it right away. Not saved - see onFontUpload to persist it.\"\n >\n Upload\n </Button>\n {/* Plain input rather than FileUpload: this is a single inline\n action in a dense row, not a drop zone. */}\n <input\n ref={inputRef}\n type=\"file\"\n accept={FONT_ACCEPT}\n // Same proxy pattern as `MessageComposer` - see the note there.\n className=\"eidos-theme-editor-file\"\n tabIndex={-1}\n aria-hidden=\"true\"\n onChange={(event) => {\n void handleFile(event.target.files?.[0]);\n // Allow re-picking the same file after a failure.\n event.target.value = '';\n }}\n />\n </div>\n )}\n </div>\n );\n};\n\n/**\n * Live editor for the active `ThemeProvider` theme.\n *\n * Renders no preview of its own: the provider writes tokens to\n * `document.documentElement`, so the surrounding page is the preview.\n *\n * Contrast readouts are diagnostics only - a colour that fails is still\n * applied. Automatically \"correcting\" a chosen colour would mean silently\n * rendering something other than what was picked.\n */\nexport const ThemeEditor: React.FC<ThemeEditorProps> = ({\n colors = THEME_COLOR_KEYS as ThemeColorKey[],\n fontOptions = FONT_STACKS,\n monoFontOptions = MONO_STACKS,\n allowFontUpload = true,\n onFontUpload,\n hideTypography = false,\n hideReset = false,\n hideCssExport = false,\n className,\n}) => {\n const { theme, resolvedTheme, setTheme, updateTheme, resetTheme, isDefault, toCss } = useTheme();\n const [copied, setCopied] = useState(false);\n\n // Fonts registered through the upload control this session. Kept local\n // because font *data* cannot live in a ThemeConfig - see the .mdx.\n const [uploaded, setUploaded] = useState<ThemeFontOption[]>([]);\n const [monoUploaded, setMonoUploaded] = useState<ThemeFontOption[]>([]);\n\n const setColor = useCallback(\n (key: ThemeColorKey, hex: string) => {\n const current = theme.colors?.[key];\n // Only the base is written here. A `contrast` pinned in the theme is\n // preserved rather than dropped, since the editor never sets one.\n const pinned = typeof current === 'object' ? current.contrast : undefined;\n updateTheme({ colors: { [key]: pinned ? { base: hex, contrast: pinned } : hex } });\n },\n [theme.colors, updateTheme],\n );\n\n const resetColor = useCallback(\n (key: ThemeColorKey) => {\n // Must go through setTheme, not updateTheme: updateTheme merges, so a key\n // left out of the patch keeps its existing value instead of being removed.\n // Removal is what restores the preset, since resolveTheme fills gaps.\n const nextColors = { ...theme.colors };\n delete nextColors[key];\n setTheme({ ...theme, colors: nextColors });\n },\n [theme, setTheme],\n );\n\n const diagnostics = useMemo(\n () =>\n colors.map((key) => {\n const { base, contrast } = resolvedTheme.colors[key];\n return { key, base, ...diagnose(key, base, contrast) };\n }),\n [colors, resolvedTheme],\n );\n\n const failing = diagnostics.filter((d) => d.grade === 'fail');\n const invisible = diagnostics.filter((d) => d.edgeWarning);\n\n const copyCss = useCallback(() => {\n const css = toCss();\n const done = () => {\n setCopied(true);\n setTimeout(() => setCopied(false), 1600);\n };\n if (navigator.clipboard?.writeText) {\n navigator.clipboard.writeText(css).then(done, done);\n return;\n }\n done();\n }, [toCss]);\n\n return (\n <div className={['eidos-theme-editor', className].filter(Boolean).join(' ')}>\n {(failing.length > 0 || invisible.length > 0) && (\n <Alert variant=\"warning\" title=\"Contrast issues\">\n {failing.length > 0 && (\n <p>\n Cannot reach WCAG AA (4.5:1) with either foreground:{' '}\n {failing.map((d) => COLOR_LABELS[d.key]).join(', ')}.\n </p>\n )}\n {invisible.length > 0 && (\n <p>\n Too close to the page background to read as a filled surface:{' '}\n {invisible.map((d) => COLOR_LABELS[d.key]).join(', ')}.\n </p>\n )}\n </Alert>\n )}\n\n <Card variant=\"outlined\" padding=\"lg\" className=\"eidos-theme-editor-section\">\n <div className=\"eidos-theme-editor-section__header\">\n <span className=\"eidos-theme-editor-section__title\">Colours</span>\n <span className=\"eidos-theme-editor-section__hint\">\n Shades, tints and foregrounds are derived from each base colour.\n </span>\n </div>\n\n <div className=\"eidos-theme-editor-rows\">\n {diagnostics.map(({ key, base, grade, ratio, detail, edgeWarning }) => {\n const badge = GRADE_BADGE[grade];\n const overridden = theme.colors?.[key] !== undefined;\n return (\n <div className=\"eidos-theme-editor-row\" key={key}>\n <span className=\"eidos-theme-editor-row__label\">{COLOR_LABELS[key]}</span>\n\n {/* `md` rather than `sm`: the size drives the panel's\n saturation/brightness canvas, and 120px is cramped for\n picking a lightness precisely. */}\n <ColorPicker\n value={base}\n onChange={(hex) => setColor(key, hex)}\n size=\"md\"\n // The row draws its own visible label, so the picker must\n // not draw a second one - but without a name of its own\n // every picker here announced as \"Open colour picker\" and\n // they were indistinguishable.\n ariaLabel={COLOR_LABELS[key]}\n />\n\n <div className=\"eidos-theme-editor-row__diagnostics\">\n <Tooltip message={detail}>\n <span className={`eidos-theme-editor-badge eidos-theme-editor-badge--${grade}`}>\n <badge.icon className=\"eidos-theme-editor-badge__icon\" />\n {`${ratio.toFixed(2)}:1 ${badge.label}`}\n </span>\n </Tooltip>\n {edgeWarning && (\n <Tooltip message={edgeWarning}>\n <span className=\"eidos-theme-editor-badge eidos-theme-editor-badge--fail\">\n <CircleX className=\"eidos-theme-editor-badge__icon\" />\n Invisible on page\n </span>\n </Tooltip>\n )}\n </div>\n\n <div className=\"eidos-theme-editor-row__actions\">\n <IconButton\n icon=\"RotateCcw\"\n variant=\"text\"\n color=\"secondary\"\n size=\"sm\"\n disabled={!overridden}\n onClick={() => resetColor(key)}\n tooltip={overridden ? `Reset ${COLOR_LABELS[key]} to the preset` : 'Unchanged'}\n aria-label={`Reset ${COLOR_LABELS[key]}`}\n />\n </div>\n </div>\n );\n })}\n </div>\n </Card>\n\n {!hideTypography && (\n <Card variant=\"outlined\" padding=\"lg\" className=\"eidos-theme-editor-section\">\n <div className=\"eidos-theme-editor-section__header\">\n <span className=\"eidos-theme-editor-section__title\">Typography</span>\n <span className=\"eidos-theme-editor-section__hint\">\n A stack only names a font - upload the file to use one the browser doesn&apos;t\n already have. Spacing is declared in <code>em</code>, so the scale moves padding with\n the text.\n </span>\n </div>\n\n <div className=\"eidos-theme-editor-rows\">\n <FontRow\n label=\"Body font\"\n value={resolvedTheme.typography.fontFamily}\n options={[...fontOptions, ...uploaded]}\n mono={false}\n allowUpload={allowFontUpload}\n onChange={(fontFamily) => updateTheme({ typography: { fontFamily } })}\n onUploaded={(option, file, family) => {\n setUploaded((prev) => [...prev, option]);\n onFontUpload?.(file, family, false);\n }}\n />\n\n <FontRow\n label=\"Mono font\"\n value={resolvedTheme.typography.monoFamily}\n options={[...monoFontOptions, ...monoUploaded]}\n mono\n allowUpload={allowFontUpload}\n onChange={(monoFamily) => updateTheme({ typography: { monoFamily } })}\n onUploaded={(option, file, family) => {\n setMonoUploaded((prev) => [...prev, option]);\n onFontUpload?.(file, family, true);\n }}\n />\n\n <div className=\"eidos-theme-editor-row eidos-theme-editor-row--wide\">\n <span className=\"eidos-theme-editor-row__label\">Scale</span>\n <div className=\"eidos-theme-editor-row__control\">\n <Slider\n value={resolvedTheme.typography.fontScale}\n min={FONT_SCALE_MIN}\n max={FONT_SCALE_MAX}\n step={0.025}\n showValue\n showMinMax\n unit=\"×\"\n onChange={(value) => updateTheme({ typography: { fontScale: value } })}\n />\n </div>\n </div>\n </div>\n </Card>\n )}\n\n {(!hideReset || !hideCssExport) && (\n <div className=\"eidos-theme-editor-actions\">\n {!hideReset && (\n <Button variant=\"outlined\" color=\"secondary\" disabled={isDefault} onClick={resetTheme}>\n Reset all\n </Button>\n )}\n {!hideCssExport && (\n <Button\n variant=\"outlined\"\n preIcon={copied ? 'Check' : 'Clipboard'}\n onClick={copyCss}\n tooltip=\"Copy the resolved tokens as a :root block you can paste into your own stylesheet\"\n >\n {copied ? 'Copied' : 'Copy as CSS'}\n </Button>\n )}\n </div>\n )}\n </div>\n );\n};\n\nThemeEditor.displayName = 'ThemeEditor';\n"],"mappings":"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","names":["ratio","grade"]}
@@ -1,34 +0,0 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }// src/components/Timeline/Timeline.component.tsx
2
- var _jsxruntime = require('react/jsx-runtime');
3
- var Timeline = ({ items, className = "" }) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "ol", { className: ["eidos-timeline", className].filter(Boolean).join(" "), "aria-label": "Timeline", children: items.map((item, index) => {
4
- const isLast = index === items.length - 1;
5
- const color = _nullishCoalesce(item.color, () => ( "default"));
6
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
7
- "li",
8
- {
9
- className: [
10
- "eidos-timeline-item",
11
- `eidos-timeline-item--${color}`,
12
- !isLast && "eidos-timeline-item--has-connector"
13
- ].filter(Boolean).join(" "),
14
- children: [
15
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "eidos-timeline-track", "aria-hidden": "true", children: [
16
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "eidos-timeline-dot", children: item.icon && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "eidos-timeline-dot-icon", children: item.icon }) }),
17
- !isLast && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "eidos-timeline-connector" })
18
- ] }),
19
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "eidos-timeline-content", children: [
20
- item.timestamp && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "eidos-timeline-timestamp", children: item.timestamp }),
21
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "eidos-timeline-title", children: item.title }),
22
- item.description && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "eidos-timeline-description", children: item.description })
23
- ] })
24
- ]
25
- },
26
- item.id
27
- );
28
- }) });
29
- Timeline.displayName = "Timeline";
30
-
31
-
32
-
33
- exports.Timeline = Timeline;
34
- //# sourceMappingURL=chunk-ZMDZGL5A.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["/home/runner/work/eidos-ui/eidos-ui/dist/chunk-ZMDZGL5A.cjs","../src/components/Timeline/Timeline.component.tsx"],"names":[],"mappings":"AAAA;ACqBU,+CAAA;AAlBH,IAAM,SAAA,EAAoC,CAAC,EAAE,KAAA,EAAO,UAAA,EAAY,GAAG,CAAA,EAAA,mBACxE,6BAAA,IAAC,EAAA,EAAG,SAAA,EAAW,CAAC,gBAAA,EAAkB,SAAS,CAAA,CAAE,MAAA,CAAO,OAAO,CAAA,CAAE,IAAA,CAAK,GAAG,CAAA,EAAG,YAAA,EAAW,UAAA,EAChF,QAAA,EAAA,KAAA,CAAM,GAAA,CAAI,CAAC,IAAA,EAAM,KAAA,EAAA,GAAU;AAC1B,EAAA,MAAM,OAAA,EAAS,MAAA,IAAU,KAAA,CAAM,OAAA,EAAS,CAAA;AACxC,EAAA,MAAM,MAAA,mBAAQ,IAAA,CAAK,KAAA,UAAS,WAAA;AAE5B,EAAA,uBACE,8BAAA;AAAA,IAAC,IAAA;AAAA,IAAA;AAAA,MAEC,SAAA,EAAW;AAAA,QACT,qBAAA;AAAA,QACA,CAAA,qBAAA,EAAwB,KAAK,CAAA,CAAA;AAClB,QAAA;AAGF,MAAA;AAGX,MAAA;AAAK,wBAAA;AACF,0BAAA;AAGW,UAAA;AACd,QAAA;AAGK,wBAAA;AACgB,UAAA;AAClB,0BAAA;AACoB,UAAA;AACvB,QAAA;AAAA,MAAA;AAAA,IAAA;AAtBU,IAAA;AAuBZ,EAAA;AAGN;AAGqB;ADXe;AACA;AACA;AACA","file":"/home/runner/work/eidos-ui/eidos-ui/dist/chunk-ZMDZGL5A.cjs","sourcesContent":[null,"import React from 'react';\nimport type { TimelineProps } from './Timeline.types';\n\nexport const Timeline: React.FC<TimelineProps> = ({ items, className = '' }) => (\n <ol className={['eidos-timeline', className].filter(Boolean).join(' ')} aria-label=\"Timeline\">\n {items.map((item, index) => {\n const isLast = index === items.length - 1;\n const color = item.color ?? 'default';\n\n return (\n <li\n key={item.id}\n className={[\n 'eidos-timeline-item',\n `eidos-timeline-item--${color}`,\n !isLast && 'eidos-timeline-item--has-connector',\n ]\n .filter(Boolean)\n .join(' ')}\n >\n {/* Left: dot + connector */}\n <div className=\"eidos-timeline-track\" aria-hidden=\"true\">\n <div className=\"eidos-timeline-dot\">\n {item.icon && <span className=\"eidos-timeline-dot-icon\">{item.icon}</span>}\n </div>\n {!isLast && <div className=\"eidos-timeline-connector\" />}\n </div>\n\n {/* Right: content */}\n <div className=\"eidos-timeline-content\">\n {item.timestamp && <span className=\"eidos-timeline-timestamp\">{item.timestamp}</span>}\n <span className=\"eidos-timeline-title\">{item.title}</span>\n {item.description && <p className=\"eidos-timeline-description\">{item.description}</p>}\n </div>\n </li>\n );\n })}\n </ol>\n);\n\nTimeline.displayName = 'Timeline';\n"]}
@@ -1,30 +0,0 @@
1
- import React__default from 'react';
2
-
3
- type IconType = React__default.ComponentType<{
4
- className?: string;
5
- }> | string;
6
- /**
7
- * Helper function to render icons dynamically
8
- * Supports both React components (Lucide, MUI, etc.) and string-based icon names
9
- *
10
- * @param icon - Icon component or string name (e.g., "heart" or "arrow-right")
11
- * @param className - Optional CSS class name to apply to the icon
12
- * @returns React node representing the icon, or null if no icon provided
13
- *
14
- * @example
15
- * // Component-based icon
16
- * import { Heart } from 'lucide-react';
17
- * renderIcon(Heart, 'my-icon-class');
18
- *
19
- * @example
20
- * // String-based Lucide icon (kebab-case converted to PascalCase)
21
- * renderIcon('heart', 'my-icon-class');
22
- * renderIcon('arrow-right', 'my-icon-class');
23
- *
24
- * @example
25
- * // String-based CSS class (for Font Awesome, Remixicon, etc.)
26
- * renderIcon('fas fa-heart', 'my-icon-class');
27
- */
28
- declare const renderIcon: (icon: IconType | undefined, className?: string) => React__default.ReactNode;
29
-
30
- export { type IconType as I, renderIcon as r };
@@ -1,30 +0,0 @@
1
- import React__default from 'react';
2
-
3
- type IconType = React__default.ComponentType<{
4
- className?: string;
5
- }> | string;
6
- /**
7
- * Helper function to render icons dynamically
8
- * Supports both React components (Lucide, MUI, etc.) and string-based icon names
9
- *
10
- * @param icon - Icon component or string name (e.g., "heart" or "arrow-right")
11
- * @param className - Optional CSS class name to apply to the icon
12
- * @returns React node representing the icon, or null if no icon provided
13
- *
14
- * @example
15
- * // Component-based icon
16
- * import { Heart } from 'lucide-react';
17
- * renderIcon(Heart, 'my-icon-class');
18
- *
19
- * @example
20
- * // String-based Lucide icon (kebab-case converted to PascalCase)
21
- * renderIcon('heart', 'my-icon-class');
22
- * renderIcon('arrow-right', 'my-icon-class');
23
- *
24
- * @example
25
- * // String-based CSS class (for Font Awesome, Remixicon, etc.)
26
- * renderIcon('fas fa-heart', 'my-icon-class');
27
- */
28
- declare const renderIcon: (icon: IconType | undefined, className?: string) => React__default.ReactNode;
29
-
30
- export { type IconType as I, renderIcon as r };