@expressivecss/expressive 0.16.0 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (384) hide show
  1. package/CHANGELOG.md +306 -1
  2. package/README.md +1 -1
  3. package/dist/css/expressive.css +540 -646
  4. package/dist/css/expressive.css.map +1 -1
  5. package/dist/css/expressive.min.css +1 -1
  6. package/dist/css/expressive.min.css.map +1 -1
  7. package/dist/js/chunks/{chunk-PA7NU5AK.mjs → chunk-26VUH75M.mjs} +6 -3
  8. package/dist/js/chunks/chunk-26VUH75M.mjs.map +7 -0
  9. package/dist/js/chunks/{chunk-NBJAUGPP.mjs → chunk-2LFCOGC3.mjs} +12 -23
  10. package/dist/js/chunks/chunk-2LFCOGC3.mjs.map +7 -0
  11. package/dist/js/chunks/{chunk-OP43LLIC.mjs → chunk-36GELQGX.mjs} +4 -4
  12. package/dist/js/chunks/{chunk-OP43LLIC.mjs.map → chunk-36GELQGX.mjs.map} +2 -2
  13. package/dist/js/chunks/{chunk-EC26RU2D.mjs → chunk-3FKWIRHW.mjs} +6 -2
  14. package/dist/js/chunks/chunk-3FKWIRHW.mjs.map +7 -0
  15. package/dist/js/chunks/{chunk-Y6H2X7ZC.mjs → chunk-3KF65KGL.mjs} +3 -3
  16. package/dist/js/chunks/{chunk-4QUCNFSD.mjs → chunk-3KLZRQZI.mjs} +31 -10
  17. package/dist/js/chunks/chunk-3KLZRQZI.mjs.map +7 -0
  18. package/dist/js/chunks/{chunk-75E5EDJF.mjs → chunk-3XORNED5.mjs} +2 -2
  19. package/dist/js/chunks/{chunk-NNHVANQA.mjs → chunk-4WBGAQN3.mjs} +3 -3
  20. package/dist/js/chunks/{chunk-ZJNLAGY5.mjs → chunk-5F4URJHL.mjs} +2 -2
  21. package/dist/js/chunks/{chunk-ZVLOUDIJ.mjs → chunk-67UNY7RH.mjs} +50 -2
  22. package/dist/js/chunks/chunk-67UNY7RH.mjs.map +7 -0
  23. package/dist/js/chunks/{chunk-P6DRQ6KS.mjs → chunk-7CXNATJS.mjs} +6 -5
  24. package/dist/js/chunks/chunk-7CXNATJS.mjs.map +7 -0
  25. package/dist/js/chunks/{chunk-4TRZ2AER.mjs → chunk-7X44MKEQ.mjs} +15 -14
  26. package/dist/js/chunks/chunk-7X44MKEQ.mjs.map +7 -0
  27. package/dist/js/chunks/{chunk-GWZ76SR4.mjs → chunk-7ZAMOMGY.mjs} +12 -7
  28. package/dist/js/chunks/chunk-7ZAMOMGY.mjs.map +7 -0
  29. package/dist/js/chunks/{chunk-GVZQH2H5.mjs → chunk-AEG6LOAJ.mjs} +2 -2
  30. package/dist/js/chunks/{chunk-Y6TLRA3U.mjs → chunk-AQNFCJJ5.mjs} +27 -21
  31. package/dist/js/chunks/chunk-AQNFCJJ5.mjs.map +7 -0
  32. package/dist/js/chunks/{chunk-OUCHKSAW.mjs → chunk-B55LWKBM.mjs} +16 -4
  33. package/dist/js/chunks/chunk-B55LWKBM.mjs.map +7 -0
  34. package/dist/js/chunks/{chunk-AI73GJKG.mjs → chunk-BB5VXYXT.mjs} +2 -2
  35. package/dist/js/chunks/{chunk-2RLBDFH4.mjs → chunk-BDATLH3H.mjs} +4 -4
  36. package/dist/js/chunks/{chunk-2CS6TITK.mjs → chunk-CWMQOT4O.mjs} +23 -10
  37. package/dist/js/chunks/chunk-CWMQOT4O.mjs.map +7 -0
  38. package/dist/js/chunks/{chunk-ZKWUWBUB.mjs → chunk-CY2CTOVM.mjs} +2 -2
  39. package/dist/js/chunks/{chunk-CSYWKEK3.mjs → chunk-DWA5UYLJ.mjs} +58 -27
  40. package/dist/js/chunks/chunk-DWA5UYLJ.mjs.map +7 -0
  41. package/dist/js/chunks/{chunk-CMGXGYUC.mjs → chunk-EB2V4OKL.mjs} +14 -9
  42. package/dist/js/chunks/chunk-EB2V4OKL.mjs.map +7 -0
  43. package/dist/js/chunks/{chunk-Z4GICXR2.mjs → chunk-EWO662ZC.mjs} +5 -7
  44. package/dist/js/chunks/chunk-EWO662ZC.mjs.map +7 -0
  45. package/dist/js/chunks/{chunk-VGY4M57S.mjs → chunk-F7LAKFMX.mjs} +67 -34
  46. package/dist/js/chunks/chunk-F7LAKFMX.mjs.map +7 -0
  47. package/dist/js/chunks/{chunk-67ZPPKXS.mjs → chunk-FNIIH2LU.mjs} +3 -3
  48. package/dist/js/chunks/chunk-GE3YMFS6.mjs +15 -0
  49. package/dist/js/chunks/chunk-GE3YMFS6.mjs.map +7 -0
  50. package/dist/js/chunks/{chunk-DZYVU75J.mjs → chunk-GFWYMWYN.mjs} +18 -14
  51. package/dist/js/chunks/chunk-GFWYMWYN.mjs.map +7 -0
  52. package/dist/js/chunks/{chunk-3L3QIYLC.mjs → chunk-H5ISU45X.mjs} +8 -6
  53. package/dist/js/chunks/chunk-H5ISU45X.mjs.map +7 -0
  54. package/dist/js/chunks/{chunk-QXKWVHBD.mjs → chunk-H6YIKFAQ.mjs} +67 -46
  55. package/dist/js/chunks/chunk-H6YIKFAQ.mjs.map +7 -0
  56. package/dist/js/chunks/{chunk-KZPSAXIU.mjs → chunk-HEH7E3KO.mjs} +22 -12
  57. package/dist/js/chunks/chunk-HEH7E3KO.mjs.map +7 -0
  58. package/dist/js/chunks/{chunk-T3BNSRP3.mjs → chunk-HQRLBTNM.mjs} +3 -3
  59. package/dist/js/chunks/{chunk-NAC72P7R.mjs → chunk-I2F7MLUU.mjs} +2 -2
  60. package/dist/js/chunks/{chunk-ZM3XBHWV.mjs → chunk-IQOTGGHX.mjs} +86 -35
  61. package/dist/js/chunks/chunk-IQOTGGHX.mjs.map +7 -0
  62. package/dist/js/chunks/{chunk-QACZ6TUP.mjs → chunk-JH3YWKA6.mjs} +5 -4
  63. package/dist/js/chunks/chunk-JH3YWKA6.mjs.map +7 -0
  64. package/dist/js/chunks/chunk-JOLJAYIJ.mjs +7 -0
  65. package/dist/js/chunks/{chunk-4IKVPCSU.mjs.map → chunk-JOLJAYIJ.mjs.map} +1 -1
  66. package/dist/js/chunks/{chunk-BPF3I2MN.mjs → chunk-KOTGMCMI.mjs} +9 -2
  67. package/dist/js/chunks/chunk-KOTGMCMI.mjs.map +7 -0
  68. package/dist/js/chunks/{chunk-ANKFWNWT.mjs → chunk-LC4O5LFS.mjs} +3 -3
  69. package/dist/js/chunks/{chunk-4PIXLDNJ.mjs → chunk-LEF33SCP.mjs} +2 -2
  70. package/dist/js/chunks/{chunk-ILDRRG7T.mjs → chunk-LFORZRPH.mjs} +3 -3
  71. package/dist/js/chunks/{chunk-Z4OARDZ7.mjs → chunk-LWLNV5EC.mjs} +26 -17
  72. package/dist/js/chunks/chunk-LWLNV5EC.mjs.map +7 -0
  73. package/dist/js/chunks/{chunk-WU7XJ4RR.mjs → chunk-LXRHUQAX.mjs} +66 -25
  74. package/dist/js/chunks/chunk-LXRHUQAX.mjs.map +7 -0
  75. package/dist/js/chunks/{chunk-VMY55K2X.mjs → chunk-MA2SZZFB.mjs} +11 -7
  76. package/dist/js/chunks/chunk-MA2SZZFB.mjs.map +7 -0
  77. package/dist/js/chunks/{chunk-VJVQIXHC.mjs → chunk-MDBZAMIV.mjs} +8 -10
  78. package/dist/js/chunks/chunk-MDBZAMIV.mjs.map +7 -0
  79. package/dist/js/chunks/{chunk-4EWGD4V2.mjs → chunk-NODZ5VAD.mjs} +2 -2
  80. package/dist/js/chunks/{chunk-UGJHCHXG.mjs → chunk-O2WJB6TH.mjs} +79 -55
  81. package/dist/js/chunks/chunk-O2WJB6TH.mjs.map +7 -0
  82. package/dist/js/chunks/{chunk-7YZ5CN3V.mjs → chunk-PCABY5BN.mjs} +5 -3
  83. package/dist/js/chunks/chunk-PCABY5BN.mjs.map +7 -0
  84. package/dist/js/chunks/{chunk-X7SDA2J5.mjs → chunk-PWKYVMND.mjs} +9 -5
  85. package/dist/js/chunks/{chunk-X7SDA2J5.mjs.map → chunk-PWKYVMND.mjs.map} +2 -2
  86. package/dist/js/chunks/{chunk-SPPHF7YZ.mjs → chunk-QHZZT7YO.mjs} +35 -14
  87. package/dist/js/chunks/chunk-QHZZT7YO.mjs.map +7 -0
  88. package/dist/js/chunks/{chunk-LDXCC2L3.mjs → chunk-QND56EW2.mjs} +5 -4
  89. package/dist/js/chunks/chunk-QND56EW2.mjs.map +7 -0
  90. package/dist/js/chunks/{chunk-NVQ5EHCU.mjs → chunk-QNODAANY.mjs} +4 -4
  91. package/dist/js/chunks/{chunk-7NLUI3RR.mjs → chunk-QRO5FV3I.mjs} +23 -13
  92. package/dist/js/chunks/chunk-QRO5FV3I.mjs.map +7 -0
  93. package/dist/js/chunks/{chunk-FCNF4GRJ.mjs → chunk-R7A7JRC5.mjs} +6 -11
  94. package/dist/js/chunks/chunk-R7A7JRC5.mjs.map +7 -0
  95. package/dist/js/chunks/{chunk-S23RJ3XY.mjs → chunk-RKG2CBFE.mjs} +4 -16
  96. package/dist/js/chunks/chunk-RKG2CBFE.mjs.map +7 -0
  97. package/dist/js/chunks/{chunk-6FSEUFVW.mjs → chunk-RSNS5OYS.mjs} +6 -6
  98. package/dist/js/chunks/chunk-RSNS5OYS.mjs.map +7 -0
  99. package/dist/js/chunks/{chunk-ROH2HDB4.mjs → chunk-RUDYMEJ3.mjs} +2 -2
  100. package/dist/js/chunks/{chunk-BIGU5RCJ.mjs → chunk-STJR62SU.mjs} +13 -5
  101. package/dist/js/chunks/chunk-STJR62SU.mjs.map +7 -0
  102. package/dist/js/chunks/{chunk-752ADW4M.mjs → chunk-SUSD4UTN.mjs} +27 -32
  103. package/dist/js/chunks/chunk-SUSD4UTN.mjs.map +7 -0
  104. package/dist/js/chunks/{chunk-B7DQFHA5.mjs → chunk-SYBOA5HC.mjs} +7 -12
  105. package/dist/js/chunks/chunk-SYBOA5HC.mjs.map +7 -0
  106. package/dist/js/chunks/{chunk-TFABTUAZ.mjs → chunk-T4MOBP3J.mjs} +2 -2
  107. package/dist/js/chunks/{chunk-GCWWEZKO.mjs → chunk-TM7HPGTV.mjs} +3 -3
  108. package/dist/js/chunks/{chunk-5KIHWJI2.mjs → chunk-TMQDZSDC.mjs} +34 -12
  109. package/dist/js/chunks/chunk-TMQDZSDC.mjs.map +7 -0
  110. package/dist/js/chunks/{chunk-ZO6ZLHFF.mjs → chunk-TVSX5YA2.mjs} +3 -3
  111. package/dist/js/chunks/{chunk-INLZWHLY.mjs → chunk-UHO5CV6K.mjs} +2 -2
  112. package/dist/js/chunks/{chunk-INLZWHLY.mjs.map → chunk-UHO5CV6K.mjs.map} +2 -2
  113. package/dist/js/chunks/{chunk-7YQBHTK3.mjs → chunk-UKCNELUN.mjs} +6 -8
  114. package/dist/js/chunks/chunk-UKCNELUN.mjs.map +7 -0
  115. package/dist/js/chunks/{chunk-VH4BMAZS.mjs → chunk-UKQK5GWR.mjs} +13 -13
  116. package/dist/js/chunks/chunk-UKQK5GWR.mjs.map +7 -0
  117. package/dist/js/chunks/{chunk-OYNUDOHR.mjs → chunk-UTSLYQ65.mjs} +7 -6
  118. package/dist/js/chunks/{chunk-OYNUDOHR.mjs.map → chunk-UTSLYQ65.mjs.map} +2 -2
  119. package/dist/js/chunks/{chunk-7W7TV6NY.mjs → chunk-VS5OJBOD.mjs} +2 -2
  120. package/dist/js/chunks/{chunk-7W7TV6NY.mjs.map → chunk-VS5OJBOD.mjs.map} +2 -2
  121. package/dist/js/chunks/{chunk-KYIEG4U3.mjs → chunk-VZMROW5A.mjs} +43 -14
  122. package/dist/js/chunks/chunk-VZMROW5A.mjs.map +7 -0
  123. package/dist/js/chunks/{chunk-VFV75DHF.mjs → chunk-XB6Y7P5W.mjs} +11 -12
  124. package/dist/js/chunks/chunk-XB6Y7P5W.mjs.map +7 -0
  125. package/dist/js/chunks/{chunk-CZSQHXEV.mjs → chunk-XDAMOMVD.mjs} +20 -21
  126. package/dist/js/chunks/chunk-XDAMOMVD.mjs.map +7 -0
  127. package/dist/js/chunks/{chunk-EVCVFEV3.mjs → chunk-XJPMW5SP.mjs} +21 -35
  128. package/dist/js/chunks/chunk-XJPMW5SP.mjs.map +7 -0
  129. package/dist/js/chunks/{chunk-VR3L2WN5.mjs → chunk-YKANQILZ.mjs} +7 -6
  130. package/dist/js/chunks/chunk-YKANQILZ.mjs.map +7 -0
  131. package/dist/js/chunks/{chunk-JUKBBN6P.mjs → chunk-YLZOJLDI.mjs} +2 -2
  132. package/dist/js/chunks/{chunk-U4B3VHFS.mjs → chunk-ZK7YY322.mjs} +28 -21
  133. package/dist/js/chunks/chunk-ZK7YY322.mjs.map +7 -0
  134. package/dist/js/expressive.cjs +2739 -2387
  135. package/dist/js/expressive.cjs.map +4 -4
  136. package/dist/js/expressive.js +2739 -2387
  137. package/dist/js/expressive.js.map +4 -4
  138. package/dist/js/expressive.min.js +7 -7
  139. package/dist/js/expressive.min.js.map +4 -4
  140. package/dist/js/expressive.mjs +76 -75
  141. package/dist/js/expressive.mjs.map +1 -1
  142. package/dist/js/internal/behaviors/bottomSheets.mjs +3 -3
  143. package/dist/js/internal/behaviors/copy.mjs +3 -3
  144. package/dist/js/internal/behaviors/dataTables.mjs +2 -4
  145. package/dist/js/internal/behaviors/dialogs.mjs +2 -2
  146. package/dist/js/internal/behaviors/forms.mjs +2 -2
  147. package/dist/js/internal/behaviors/imageCompare.mjs +2 -2
  148. package/dist/js/internal/behaviors/lists.mjs +2 -2
  149. package/dist/js/internal/behaviors/paneResize.mjs +2 -2
  150. package/dist/js/internal/behaviors/sheetDrag.mjs +2 -2
  151. package/dist/js/internal/behaviors/sideSheets.mjs +3 -3
  152. package/dist/js/internal/behaviors/sortable.mjs +2 -2
  153. package/dist/js/internal/behaviors/theme.mjs +2 -2
  154. package/dist/js/internal/behaviors/tour.mjs +2 -2
  155. package/dist/js/internal/behaviors/transferList.mjs +2 -2
  156. package/dist/js/internal/components/appBar.mjs +3 -3
  157. package/dist/js/internal/components/autocomplete.mjs +5 -4
  158. package/dist/js/internal/components/backToTop.mjs +3 -3
  159. package/dist/js/internal/components/barChart.mjs +5 -5
  160. package/dist/js/internal/components/buttonGroup.mjs +3 -3
  161. package/dist/js/internal/components/buttons.mjs +3 -3
  162. package/dist/js/internal/components/cards.mjs +3 -3
  163. package/dist/js/internal/components/carousel.mjs +3 -3
  164. package/dist/js/internal/components/cascader.mjs +4 -4
  165. package/dist/js/internal/components/characterCounter.mjs +3 -3
  166. package/dist/js/internal/components/chips.mjs +7 -6
  167. package/dist/js/internal/components/colorPicker.mjs +3 -3
  168. package/dist/js/internal/components/columnChart.mjs +4 -4
  169. package/dist/js/internal/components/commandPalette.mjs +3 -3
  170. package/dist/js/internal/components/confetti.mjs +3 -3
  171. package/dist/js/internal/components/currencyInput.mjs +3 -3
  172. package/dist/js/internal/components/datepicker.mjs +8 -7
  173. package/dist/js/internal/components/expandingCard.mjs +3 -3
  174. package/dist/js/internal/components/funnelChart.mjs +4 -4
  175. package/dist/js/internal/components/heatmapChart.mjs +4 -4
  176. package/dist/js/internal/components/hoverCard.mjs +3 -3
  177. package/dist/js/internal/components/index.mjs +60 -59
  178. package/dist/js/internal/components/inputMask.mjs +3 -3
  179. package/dist/js/internal/components/keypad.mjs +3 -3
  180. package/dist/js/internal/components/lightbox.mjs +3 -3
  181. package/dist/js/internal/components/lineChart.mjs +23 -7
  182. package/dist/js/internal/components/loadingOverlay.mjs +3 -3
  183. package/dist/js/internal/components/mapView.mjs +3 -3
  184. package/dist/js/internal/components/menu.mjs +3 -3
  185. package/dist/js/internal/components/menubar.mjs +4 -4
  186. package/dist/js/internal/components/messageScroller.mjs +3 -3
  187. package/dist/js/internal/components/mixedChart.mjs +5 -5
  188. package/dist/js/internal/components/navigationRail.mjs +3 -3
  189. package/dist/js/internal/components/particles.mjs +3 -3
  190. package/dist/js/internal/components/pieChart.mjs +4 -4
  191. package/dist/js/internal/components/pullToRefresh.mjs +3 -3
  192. package/dist/js/internal/components/questionnaire.mjs +3 -3
  193. package/dist/js/internal/components/radarChart.mjs +4 -4
  194. package/dist/js/internal/components/radialChart.mjs +4 -4
  195. package/dist/js/internal/components/registry.mjs +59 -58
  196. package/dist/js/internal/components/richTextEditor.mjs +3 -3
  197. package/dist/js/internal/components/sankeyChart.mjs +4 -4
  198. package/dist/js/internal/components/scatterChart.mjs +4 -4
  199. package/dist/js/internal/components/scrollspy.mjs +3 -3
  200. package/dist/js/internal/components/select.mjs +5 -4
  201. package/dist/js/internal/components/showMore.mjs +3 -3
  202. package/dist/js/internal/components/slider.mjs +3 -3
  203. package/dist/js/internal/components/snackbar.mjs +2 -2
  204. package/dist/js/internal/components/swipeActions.mjs +3 -3
  205. package/dist/js/internal/components/tabs.mjs +3 -3
  206. package/dist/js/internal/components/timepicker.mjs +5 -5
  207. package/dist/js/internal/components/tooltip.mjs +3 -3
  208. package/dist/js/internal/components/treeSelect.mjs +6 -5
  209. package/dist/js/internal/components/treemapChart.mjs +4 -4
  210. package/dist/js/internal/core/component.mjs +6 -4
  211. package/dist/js/internal/core/formControl.mjs +2 -2
  212. package/dist/js/internal/core/imageURL.mjs +7 -0
  213. package/dist/js/internal/core/imageURL.mjs.map +7 -0
  214. package/dist/js/internal/core/utils.mjs +11 -1
  215. package/dist/js/internal/plugins/dockedDisplayPlugin.mjs +2 -2
  216. package/dist/js/internal/plugins/modalDisplayPlugin.mjs +3 -3
  217. package/dist/js/modular.mjs +76 -75
  218. package/dist/types/behaviors/bottomSheets.d.ts +5 -3
  219. package/dist/types/behaviors/dataTables.d.ts +2 -6
  220. package/dist/types/behaviors/forms.d.ts +7 -7
  221. package/dist/types/behaviors/imageCompare.d.ts +2 -1
  222. package/dist/types/behaviors/transferList.d.ts +2 -0
  223. package/dist/types/components/autocomplete.d.ts +14 -3
  224. package/dist/types/components/carousel.d.ts +7 -0
  225. package/dist/types/components/chips.d.ts +15 -0
  226. package/dist/types/components/colorPicker.d.ts +14 -0
  227. package/dist/types/components/currencyInput.d.ts +5 -4
  228. package/dist/types/components/datepicker.d.ts +54 -27
  229. package/dist/types/components/funnelChart.d.ts +1 -4
  230. package/dist/types/components/heatmapChart.d.ts +3 -0
  231. package/dist/types/components/hoverCard.d.ts +1 -0
  232. package/dist/types/components/inputMask.d.ts +0 -2
  233. package/dist/types/components/lineChart.d.ts +43 -5
  234. package/dist/types/components/mapView.d.ts +113 -11
  235. package/dist/types/components/menu.d.ts +14 -0
  236. package/dist/types/components/particles.d.ts +14 -1
  237. package/dist/types/components/pieChart.d.ts +1 -2
  238. package/dist/types/components/richTextEditor.d.ts +40 -9
  239. package/dist/types/components/select.d.ts +1 -3
  240. package/dist/types/components/showMore.d.ts +2 -0
  241. package/dist/types/components/slider.d.ts +0 -1
  242. package/dist/types/components/snackbar.d.ts +7 -1
  243. package/dist/types/components/tabs.d.ts +3 -3
  244. package/dist/types/components/timepicker.d.ts +15 -6
  245. package/dist/types/components/tooltip.d.ts +1 -1
  246. package/dist/types/components/treemapChart.d.ts +2 -2
  247. package/dist/types/core/component.d.ts +9 -3
  248. package/dist/types/core/imageURL.d.ts +2 -0
  249. package/dist/types/core/utils.d.ts +39 -1
  250. package/dist/types/modular.d.ts +1 -1
  251. package/dist/types/plugins/modalDisplayPlugin.d.ts +8 -1
  252. package/package.json +8 -6
  253. package/src/sass/abstracts/_mixins.scss +459 -59
  254. package/src/sass/abstracts/_variables.scss +25 -0
  255. package/src/sass/components/_accordion.scss +1 -3
  256. package/src/sass/components/_aura.scss +1 -0
  257. package/src/sass/components/_back-to-top.scss +3 -3
  258. package/src/sass/components/_bar-chart.scss +2 -83
  259. package/src/sass/components/_bottom-sheet.scss +7 -0
  260. package/src/sass/components/_breadcrumb.scss +1 -7
  261. package/src/sass/components/_button-groups.scss +15 -38
  262. package/src/sass/components/_buttons.scss +24 -74
  263. package/src/sass/components/_calendar.scss +1 -3
  264. package/src/sass/components/_carousel.scss +10 -10
  265. package/src/sass/components/_cascader.scss +3 -14
  266. package/src/sass/components/_column-chart.scss +1 -19
  267. package/src/sass/components/_confetti.scss +3 -4
  268. package/src/sass/components/_data-table.scss +10 -0
  269. package/src/sass/components/_dialog.scss +10 -18
  270. package/src/sass/components/_expanding-card.scss +1 -5
  271. package/src/sass/components/_fab-menu.scss +4 -12
  272. package/src/sass/components/_funnel-chart.scss +1 -62
  273. package/src/sass/components/_heatmap-chart.scss +2 -6
  274. package/src/sass/components/_icon-buttons.scss +1 -4
  275. package/src/sass/components/_line-chart.scss +2 -70
  276. package/src/sass/components/_map.scss +4 -0
  277. package/src/sass/components/_marquee.scss +3 -3
  278. package/src/sass/components/_mega-menu.scss +8 -17
  279. package/src/sass/components/_menu.scss +10 -11
  280. package/src/sass/components/_menubar.scss +1 -13
  281. package/src/sass/components/_mixed-chart.scss +1 -37
  282. package/src/sass/components/_navbar.scss +11 -16
  283. package/src/sass/components/_navigation-bar.scss +2 -5
  284. package/src/sass/components/_navigation-rail.scss +25 -15
  285. package/src/sass/components/_page-footer.scss +1 -3
  286. package/src/sass/components/_pagination.scss +3 -14
  287. package/src/sass/components/_panes.scss +3 -16
  288. package/src/sass/components/_particles.scss +3 -4
  289. package/src/sass/components/_pie-chart.scss +8 -70
  290. package/src/sass/components/_progress.scss +31 -13
  291. package/src/sass/components/_radar-chart.scss +2 -32
  292. package/src/sass/components/_radial-chart.scss +2 -48
  293. package/src/sass/components/_sankey-chart.scss +5 -28
  294. package/src/sass/components/_scatter-chart.scss +2 -11
  295. package/src/sass/components/_search.scss +1 -4
  296. package/src/sass/components/_side-sheet.scss +9 -14
  297. package/src/sass/components/_skeleton.scss +24 -15
  298. package/src/sass/components/_snackbar.scss +11 -13
  299. package/src/sass/components/_table_of_contents.scss +1 -3
  300. package/src/sass/components/_tabs.scss +4 -20
  301. package/src/sass/components/_timepicker.scss +2 -1
  302. package/src/sass/components/_toolbar.scss +1 -4
  303. package/src/sass/components/_tooltip.scss +9 -5
  304. package/src/sass/components/_tree.scss +5 -17
  305. package/src/sass/components/_treemap-chart.scss +2 -26
  306. package/src/sass/components/forms/_checkboxes.scss +2 -21
  307. package/src/sass/components/forms/_drop-zone.scss +1 -4
  308. package/src/sass/components/forms/_fieldset.scss +1 -4
  309. package/src/sass/components/forms/_file-input.scss +6 -0
  310. package/src/sass/components/forms/_input-fields.scss +21 -4
  311. package/src/sass/components/forms/_radio-buttons.scss +2 -24
  312. package/src/sass/components/forms/_select.scss +6 -7
  313. package/src/sass/components/forms/_slider.scss +1 -4
  314. package/src/sass/components/forms/_switches.scss +14 -21
  315. package/src/sass/utilities/_helpers.scss +1 -1
  316. package/src/sass/utilities/_visibility.scss +1 -3
  317. package/dist/js/chunks/chunk-2CS6TITK.mjs.map +0 -7
  318. package/dist/js/chunks/chunk-3L3QIYLC.mjs.map +0 -7
  319. package/dist/js/chunks/chunk-4IKVPCSU.mjs +0 -7
  320. package/dist/js/chunks/chunk-4QUCNFSD.mjs.map +0 -7
  321. package/dist/js/chunks/chunk-4TRZ2AER.mjs.map +0 -7
  322. package/dist/js/chunks/chunk-5KIHWJI2.mjs.map +0 -7
  323. package/dist/js/chunks/chunk-6FSEUFVW.mjs.map +0 -7
  324. package/dist/js/chunks/chunk-752ADW4M.mjs.map +0 -7
  325. package/dist/js/chunks/chunk-7NLUI3RR.mjs.map +0 -7
  326. package/dist/js/chunks/chunk-7YQBHTK3.mjs.map +0 -7
  327. package/dist/js/chunks/chunk-7YZ5CN3V.mjs.map +0 -7
  328. package/dist/js/chunks/chunk-B7DQFHA5.mjs.map +0 -7
  329. package/dist/js/chunks/chunk-BIGU5RCJ.mjs.map +0 -7
  330. package/dist/js/chunks/chunk-BPF3I2MN.mjs.map +0 -7
  331. package/dist/js/chunks/chunk-CMGXGYUC.mjs.map +0 -7
  332. package/dist/js/chunks/chunk-CSYWKEK3.mjs.map +0 -7
  333. package/dist/js/chunks/chunk-CZSQHXEV.mjs.map +0 -7
  334. package/dist/js/chunks/chunk-DZYVU75J.mjs.map +0 -7
  335. package/dist/js/chunks/chunk-EC26RU2D.mjs.map +0 -7
  336. package/dist/js/chunks/chunk-EVCVFEV3.mjs.map +0 -7
  337. package/dist/js/chunks/chunk-FCNF4GRJ.mjs.map +0 -7
  338. package/dist/js/chunks/chunk-GWZ76SR4.mjs.map +0 -7
  339. package/dist/js/chunks/chunk-KYIEG4U3.mjs.map +0 -7
  340. package/dist/js/chunks/chunk-KZPSAXIU.mjs.map +0 -7
  341. package/dist/js/chunks/chunk-LDXCC2L3.mjs.map +0 -7
  342. package/dist/js/chunks/chunk-NBJAUGPP.mjs.map +0 -7
  343. package/dist/js/chunks/chunk-OUCHKSAW.mjs.map +0 -7
  344. package/dist/js/chunks/chunk-P6DRQ6KS.mjs.map +0 -7
  345. package/dist/js/chunks/chunk-PA7NU5AK.mjs.map +0 -7
  346. package/dist/js/chunks/chunk-QACZ6TUP.mjs.map +0 -7
  347. package/dist/js/chunks/chunk-QXKWVHBD.mjs.map +0 -7
  348. package/dist/js/chunks/chunk-S23RJ3XY.mjs.map +0 -7
  349. package/dist/js/chunks/chunk-SPPHF7YZ.mjs.map +0 -7
  350. package/dist/js/chunks/chunk-U4B3VHFS.mjs.map +0 -7
  351. package/dist/js/chunks/chunk-UGJHCHXG.mjs.map +0 -7
  352. package/dist/js/chunks/chunk-VFV75DHF.mjs.map +0 -7
  353. package/dist/js/chunks/chunk-VGY4M57S.mjs.map +0 -7
  354. package/dist/js/chunks/chunk-VH4BMAZS.mjs.map +0 -7
  355. package/dist/js/chunks/chunk-VJVQIXHC.mjs.map +0 -7
  356. package/dist/js/chunks/chunk-VMY55K2X.mjs.map +0 -7
  357. package/dist/js/chunks/chunk-VR3L2WN5.mjs.map +0 -7
  358. package/dist/js/chunks/chunk-WU7XJ4RR.mjs.map +0 -7
  359. package/dist/js/chunks/chunk-Y6TLRA3U.mjs.map +0 -7
  360. package/dist/js/chunks/chunk-Z4GICXR2.mjs.map +0 -7
  361. package/dist/js/chunks/chunk-Z4OARDZ7.mjs.map +0 -7
  362. package/dist/js/chunks/chunk-ZM3XBHWV.mjs.map +0 -7
  363. package/dist/js/chunks/chunk-ZVLOUDIJ.mjs.map +0 -7
  364. /package/dist/js/chunks/{chunk-Y6H2X7ZC.mjs.map → chunk-3KF65KGL.mjs.map} +0 -0
  365. /package/dist/js/chunks/{chunk-75E5EDJF.mjs.map → chunk-3XORNED5.mjs.map} +0 -0
  366. /package/dist/js/chunks/{chunk-NNHVANQA.mjs.map → chunk-4WBGAQN3.mjs.map} +0 -0
  367. /package/dist/js/chunks/{chunk-ZJNLAGY5.mjs.map → chunk-5F4URJHL.mjs.map} +0 -0
  368. /package/dist/js/chunks/{chunk-GVZQH2H5.mjs.map → chunk-AEG6LOAJ.mjs.map} +0 -0
  369. /package/dist/js/chunks/{chunk-AI73GJKG.mjs.map → chunk-BB5VXYXT.mjs.map} +0 -0
  370. /package/dist/js/chunks/{chunk-2RLBDFH4.mjs.map → chunk-BDATLH3H.mjs.map} +0 -0
  371. /package/dist/js/chunks/{chunk-ZKWUWBUB.mjs.map → chunk-CY2CTOVM.mjs.map} +0 -0
  372. /package/dist/js/chunks/{chunk-67ZPPKXS.mjs.map → chunk-FNIIH2LU.mjs.map} +0 -0
  373. /package/dist/js/chunks/{chunk-T3BNSRP3.mjs.map → chunk-HQRLBTNM.mjs.map} +0 -0
  374. /package/dist/js/chunks/{chunk-NAC72P7R.mjs.map → chunk-I2F7MLUU.mjs.map} +0 -0
  375. /package/dist/js/chunks/{chunk-ANKFWNWT.mjs.map → chunk-LC4O5LFS.mjs.map} +0 -0
  376. /package/dist/js/chunks/{chunk-4PIXLDNJ.mjs.map → chunk-LEF33SCP.mjs.map} +0 -0
  377. /package/dist/js/chunks/{chunk-ILDRRG7T.mjs.map → chunk-LFORZRPH.mjs.map} +0 -0
  378. /package/dist/js/chunks/{chunk-4EWGD4V2.mjs.map → chunk-NODZ5VAD.mjs.map} +0 -0
  379. /package/dist/js/chunks/{chunk-NVQ5EHCU.mjs.map → chunk-QNODAANY.mjs.map} +0 -0
  380. /package/dist/js/chunks/{chunk-ROH2HDB4.mjs.map → chunk-RUDYMEJ3.mjs.map} +0 -0
  381. /package/dist/js/chunks/{chunk-TFABTUAZ.mjs.map → chunk-T4MOBP3J.mjs.map} +0 -0
  382. /package/dist/js/chunks/{chunk-GCWWEZKO.mjs.map → chunk-TM7HPGTV.mjs.map} +0 -0
  383. /package/dist/js/chunks/{chunk-ZO6ZLHFF.mjs.map → chunk-TVSX5YA2.mjs.map} +0 -0
  384. /package/dist/js/chunks/{chunk-JUKBBN6P.mjs.map → chunk-YLZOJLDI.mjs.map} +0 -0
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  Utils
3
- } from "./chunk-ZVLOUDIJ.mjs";
3
+ } from "./chunk-67UNY7RH.mjs";
4
4
 
5
5
  // src/ts/behaviors/dialogs.ts
6
6
  function textElement(tag, text) {
@@ -124,4 +124,4 @@ var Dialogs = _Dialogs;
124
124
  export {
125
125
  Dialogs
126
126
  };
127
- //# sourceMappingURL=chunk-4PIXLDNJ.mjs.map
127
+ //# sourceMappingURL=chunk-LEF33SCP.mjs.map
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  Component
3
- } from "./chunk-CMGXGYUC.mjs";
3
+ } from "./chunk-EB2V4OKL.mjs";
4
4
  import {
5
5
  restoreAttribute
6
- } from "./chunk-ZVLOUDIJ.mjs";
6
+ } from "./chunk-67UNY7RH.mjs";
7
7
 
8
8
  // src/ts/components/buttons.ts
9
9
  var _defaults = {};
@@ -89,4 +89,4 @@ FloatingActionButton.key = "Expressive_FloatingActionButton";
89
89
  export {
90
90
  FloatingActionButton
91
91
  };
92
- //# sourceMappingURL=chunk-ILDRRG7T.mjs.map
92
+ //# sourceMappingURL=chunk-LFORZRPH.mjs.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  Utils
3
- } from "./chunk-ZVLOUDIJ.mjs";
3
+ } from "./chunk-67UNY7RH.mjs";
4
4
 
5
5
  // src/ts/behaviors/forms.ts
6
6
  var FILE_RULES = '.drop-zone input[type="file"]:is([data-validate-types], [data-max-size], [data-max-files])';
@@ -102,7 +102,7 @@ var _Forms = class _Forms {
102
102
  }
103
103
  static _validateFiles(input) {
104
104
  if (input.matches(":disabled")) return;
105
- _Forms._bindFileReset(input);
105
+ _Forms._bindShadowForm(input);
106
106
  const failure = _Forms._checkFiles(input);
107
107
  _Forms._showFileError(input, failure?.message ?? input.validationMessage);
108
108
  return failure;
@@ -170,7 +170,7 @@ var _Forms = class _Forms {
170
170
  error.hidden = !message;
171
171
  }
172
172
  static _updateDropZone(input) {
173
- _Forms._bindFileReset(input);
173
+ _Forms._bindShadowForm(input);
174
174
  const zone = input.closest(".drop-zone");
175
175
  const files = Array.from(input.files ?? []);
176
176
  const failure = _Forms._validateDropZone(input);
@@ -196,12 +196,11 @@ var _Forms = class _Forms {
196
196
  _Forms._fileSelections.set(input, { files, constraints });
197
197
  return !previous || previous.constraints !== constraints || previous.files.length !== files.length || !previous.files.every((file, index) => file === files[index]);
198
198
  }
199
- static _bindFileReset(input) {
199
+ // Submit and reset do not leave a shadow root, so the document never hears
200
+ // them. Adding the same listener again does nothing.
201
+ static _bindShadowForm(input) {
200
202
  if (!input.getRootNode().host) return;
201
- const form = input.form;
202
- if (!form || _Forms._fileResetForms.has(form)) return;
203
- _Forms._fileResetForms.add(form);
204
- form.addEventListener("reset", _Forms.resetFormExtras);
203
+ for (const type of ["submit", "reset"]) input.form?.addEventListener(type, _Forms.resetFormExtras, true);
205
204
  }
206
205
  static _resetFileInput(input) {
207
206
  if (input.files?.length) return;
@@ -222,8 +221,15 @@ var _Forms = class _Forms {
222
221
  _Forms._fileErrors.delete(input);
223
222
  _Forms._showFileError(input, input.validationMessage);
224
223
  }
225
- static _resetDropZones(form) {
226
- Array.from(form.elements).filter((field) => field instanceof HTMLInputElement && field.type === "file").forEach(_Forms._resetFileInput);
224
+ static _afterReset(form) {
225
+ const fields = Array.from(form.elements);
226
+ fields.filter((field) => field instanceof HTMLInputElement && field.type === "file").forEach(_Forms._resetFileInput);
227
+ fields.filter((field) => field.classList.contains("validate")).forEach((field) => _Forms._markInvalid(field, false));
228
+ fields.filter((field) => field.classList.contains("expressive-textarea")).forEach(_Forms.textareaAutoResize);
229
+ const summary = form.querySelector(".error-summary");
230
+ if (!summary) return;
231
+ summary.hidden = true;
232
+ summary.querySelector("ul, ol")?.replaceChildren();
227
233
  }
228
234
  /**
229
235
  * Safe to call more than once: the root entry calls it on import, and a page
@@ -271,6 +277,7 @@ var _Forms = class _Forms {
271
277
  'input[type="password"], input[data-password]'
272
278
  );
273
279
  if (!input) return;
280
+ _Forms._bindShadowForm(input);
274
281
  const show = input.type === "password";
275
282
  input.toggleAttribute("data-password", show);
276
283
  input.type = show ? "text" : "password";
@@ -279,7 +286,7 @@ var _Forms = class _Forms {
279
286
  /**
280
287
  * A [data-step="up"] or [data-step="down"] button in a .field steps the
281
288
  * field's number input as the arrow keys would, within min, max and step,
282
- * and fires input and change. A disabled, read-only or step="any" input
289
+ * and fires input and change if the value moved. A disabled, read-only or step="any" input
283
290
  * is left alone; stepUp() would throw on step="any".
284
291
  */
285
292
  static stepNumber(e) {
@@ -288,16 +295,19 @@ var _Forms = class _Forms {
288
295
  ':scope > input[type="number"]:not(:disabled, [readonly], [step="any"])'
289
296
  );
290
297
  if (!input) return;
298
+ const before = input.value;
291
299
  input[button.dataset.step === "down" ? "stepDown" : "stepUp"]();
300
+ if (input.value === before) return;
292
301
  input.dispatchEvent(new Event("input", { bubbles: true, composed: true }));
293
302
  input.dispatchEvent(new Event("change", { bubbles: true }));
294
303
  }
295
304
  /**
296
305
  * A revealed password goes back to type="password" when its form is
297
306
  * submitted or reset, so it is never sent or autofilled as plain text and
298
- * a reset field does not stay revealed. A reset form also drops the file
299
- * lists it would otherwise leave showing: reset fires no change event.
300
- * File cleanup waits for native reset and respects later cancellation.
307
+ * a reset field does not stay revealed. Reset fires no input or change
308
+ * event, so a reset form also drops its file lists, `.validate` errors and
309
+ * error summary, and fits each auto-resizing textarea to its restored text.
310
+ * That cleanup waits for the native reset and respects later cancellation.
301
311
  */
302
312
  static resetFormExtras(e) {
303
313
  const form = e.target;
@@ -309,7 +319,7 @@ var _Forms = class _Forms {
309
319
  });
310
320
  if (e.type === "reset") {
311
321
  setTimeout(() => {
312
- if (!e.defaultPrevented) _Forms._resetDropZones(form);
322
+ if (!e.defaultPrevented) _Forms._afterReset(form);
313
323
  }, 0);
314
324
  }
315
325
  }
@@ -427,7 +437,6 @@ var _Forms = class _Forms {
427
437
  _Forms._initialized = false;
428
438
  _Forms._fileErrors = /* @__PURE__ */ new WeakMap();
429
439
  _Forms._fileSelections = /* @__PURE__ */ new WeakMap();
430
- _Forms._fileResetForms = /* @__PURE__ */ new WeakSet();
431
440
  _Forms._onFileInput = (event) => {
432
441
  const input = Utils.closestInPath(event, '.drop-zone input[type="file"]');
433
442
  if (!input) return;
@@ -439,4 +448,4 @@ var Forms = _Forms;
439
448
  export {
440
449
  Forms
441
450
  };
442
- //# sourceMappingURL=chunk-Z4OARDZ7.mjs.map
451
+ //# sourceMappingURL=chunk-LWLNV5EC.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/ts/behaviors/forms.ts"],
4
+ "sourcesContent": ["import { Utils } from '../core/utils';\n\nconst FILE_RULES = '.drop-zone input[type=\"file\"]:is([data-validate-types], [data-max-size], [data-max-files])';\n\ninterface FileFailure {\n rejected: File[];\n reason: 'type' | 'size' | 'count';\n message: string;\n}\n\nfunction fileLimit(input: HTMLInputElement, attribute: string) {\n const value = (input.getAttribute(attribute) || '').trim();\n if (!/^\\d+$/.test(value)) return 0;\n const limit = Number(value);\n return Number.isSafeInteger(limit) ? limit : 0;\n}\n\nfunction fileSpecifier(value: string) {\n if (value.endsWith('/*')) return /^(image|audio|video)\\/\\*$/.test(value);\n return /^\\.[^\\s/\\\\]+$/.test(value) ||\n /^[!#$%&'*+.^_`|~0-9a-z-]+\\/[!#$%&'*+.^_`|~0-9a-z-]+$/.test(value);\n}\n\nfunction fileMatches(file: File, specifier: string) {\n if (specifier.startsWith('.')) return file.name.toLowerCase().endsWith(specifier);\n if (specifier.endsWith('/*')) return file.type.toLowerCase().startsWith(specifier.slice(0, -1));\n return file.type.toLowerCase() === specifier;\n}\n\nexport class Forms {\n /**\n * Validates a `.validate` field: marks it `invalid` and `aria-invalid`\n * when it fails its constraints or `data-length`, and clears both when it\n * passes. An empty optional field never fails. The field is described by\n * its `[data-error]` supporting text, so the error the CSS shows there is\n * read with it.\n * Marked drop-zone file inputs also validate type/size rules and synchronize their\n * native custom validity and zone-level error text, without emitting events.\n * @param textfield\n */\n static validateField(textfield: HTMLInputElement) {\n if (!textfield) {\n console.error('No text field element found');\n return;\n }\n if (Forms._validatedFile(textfield)) {\n Forms._validateFiles(textfield);\n return;\n }\n if (!textfield.classList.contains('validate')) return;\n Forms._markInvalid(textfield, Forms._fails(textfield));\n Forms._describeByError(textfield);\n }\n\n private static _markInvalid(field: HTMLInputElement, invalid: boolean) {\n field.classList.toggle('invalid', invalid);\n if (invalid) field.setAttribute('aria-invalid', 'true');\n else field.removeAttribute('aria-invalid');\n }\n\n /** Whether a field fails its constraints or is longer than `data-length`. */\n private static _fails(field: HTMLInputElement) {\n return !Forms._blankOptional(field) && (!field.validity.valid || field.value.length > parseInt(field.getAttribute('data-length')));\n }\n\n /** An empty field that is not required, and holds no half-typed number or date, never fails. */\n private static _blankOptional(field: HTMLInputElement) {\n return field.value.length === 0 && !field.validity.badInput && !field.required;\n }\n\n /** Adds the field's `[data-error]` supporting text to its aria-describedby. */\n private static _describeByError(field: HTMLInputElement) {\n const error = field.parentElement?.querySelector(':scope > [data-error]');\n if (error) Forms._addDescription(field, Forms._idOf(error));\n }\n\n private static _idOf(el: Element) {\n if (!el.id) el.id = `field-error-${Utils.guid()}`;\n return el.id;\n }\n\n /** Adds an id to a field's aria-describedby once, after the page's own. */\n private static _addDescription(field: HTMLInputElement, id: string) {\n const ids = (field.getAttribute('aria-describedby') ?? '').split(/\\s+/).filter(Boolean);\n if (!ids.includes(id)) field.setAttribute('aria-describedby', [...ids, id].join(' '));\n }\n\n /**\n * Resizes the given TextArea after updating the\n * value content dynamically.\n * @param e EventTarget\n */\n static textareaAutoResize(e: EventTarget) {\n const textarea = e as HTMLTextAreaElement;\n if (!textarea) return;\n\n // Measure the textarea against itself: collapse it to its natural height,\n // then read the content height back. `.expressive-textarea` is\n // `overflow-y: hidden`, so scrollHeight is the full content height and\n // offsetHeight - clientHeight is exactly the borders (no scrollbar to\n // account for) - which border-box sizing needs added back.\n //\n // This replaces a mirror div that the value was copied into via\n // `innerHTML = innerHTML.replace(...)` - a full serialize and reparse of\n // the text on every keystroke, plus getComputedStyle and seven style\n // writes, run twice per keystroke because it was bound to keydown and\n // keyup both.\n if (!textarea.hasAttribute('original-height')) Forms._measureTextarea(textarea);\n // Not measured yet when it was hidden.\n const originalHeight = parseInt(textarea.getAttribute('original-height'));\n if (isNaN(originalHeight)) return;\n\n textarea.style.height = 'auto';\n // Three reads after a single write: one layout flush for the whole resize.\n const borders = textarea.offsetHeight - textarea.clientHeight;\n const contentHeight = textarea.scrollHeight + borders;\n textarea.style.height = Math.max(originalHeight, contentHeight) + 'px';\n }\n\n // A hidden textarea (closed dialog, inactive tab) measures 0. Storing that\n // would pin it collapsed, so it waits for a focus or input to measure.\n private static _measureTextarea(textarea: HTMLTextAreaElement) {\n const height = textarea.getBoundingClientRect().height;\n if (height) textarea.setAttribute('original-height', height.toString());\n }\n\n private static _initialized = false;\n private static _fileErrors = new WeakMap<HTMLInputElement, string>();\n private static _fileSelections = new WeakMap<HTMLInputElement, { files: File[]; constraints: string }>();\n\n private static _validatedFile(input: HTMLInputElement) {\n return input.matches(FILE_RULES) || Forms._fileErrors.has(input);\n }\n\n private static _rejectedTypes(input: HTMLInputElement) {\n const accepted = input.accept.split(',').map((value) => value.trim().toLowerCase()).filter(fileSpecifier);\n if (!accepted.length) return [];\n return Array.from(input.files ?? []).filter((file) => !accepted.some((specifier) => fileMatches(file, specifier)));\n }\n\n private static _validateFiles(input: HTMLInputElement) {\n if (input.matches(':disabled')) return;\n Forms._bindShadowForm(input);\n const failure = Forms._checkFiles(input);\n Forms._showFileError(input, failure?.message ?? input.validationMessage);\n return failure;\n }\n\n private static _checkFiles(input: HTMLInputElement) {\n Forms._clearFileError(input);\n if (!input.matches(FILE_RULES)) {\n Forms._fileErrors.delete(input);\n return;\n }\n Forms._fileErrors.set(input, '');\n const failure = Forms._fileFailure(input);\n if (failure) Forms._setFileError(input, failure.message);\n return failure;\n }\n\n private static _fileFailure(input: HTMLInputElement) {\n return Forms._typeFailure(input) ?? Forms._sizeFailure(input) ?? Forms._countFailure(input);\n }\n\n private static _typeFailure(input: HTMLInputElement): FileFailure | undefined {\n if (!input.hasAttribute('data-validate-types')) return;\n const rejected = Forms._rejectedTypes(input);\n if (rejected.length) return { rejected, reason: 'type', message: Forms._fileTypeMessage(input) };\n }\n\n private static _sizeFailure(input: HTMLInputElement): FileFailure | undefined {\n const limit = fileLimit(input, 'data-max-size');\n if (!limit) return;\n const rejected = Array.from(input.files ?? []).filter((file) => file.size > limit);\n if (!rejected.length) return;\n return { rejected, reason: 'size', message: Forms._fileSizeMessage(input, limit) };\n }\n\n private static _fileSizeMessage(input: HTMLInputElement, limit: number) {\n return Forms._fileError(input)?.getAttribute('data-error-size')?.trim() || `Maximum file size: ${limit} bytes.`;\n }\n\n private static _countFailure(input: HTMLInputElement): FileFailure | undefined {\n const limit = fileLimit(input, 'data-max-files');\n if (!limit) return;\n const rejected = Array.from(input.files ?? []);\n if (rejected.length > limit) return { rejected, reason: 'count', message: Forms._fileCountMessage(input, limit) };\n }\n\n private static _fileCountMessage(input: HTMLInputElement, limit: number) {\n return Forms._fileError(input)?.getAttribute('data-error-count')?.trim() || `Maximum file count: ${limit}.`;\n }\n\n private static _clearFileError(input: HTMLInputElement) {\n const owned = Forms._fileErrors.get(input);\n if (owned && owned === input.validationMessage) input.setCustomValidity('');\n }\n\n private static _setFileError(input: HTMLInputElement, message: string) {\n if (input.validity.customError) return;\n input.setCustomValidity(message);\n Forms._fileErrors.set(input, message);\n }\n\n private static _fileTypeMessage(input: HTMLInputElement) {\n const error = Forms._fileError(input);\n return error?.getAttribute('data-error')?.trim() || `Choose files matching: ${input.accept}.`;\n }\n\n private static _fileError(input: HTMLInputElement) {\n return Array.from(input.closest('.drop-zone')?.children ?? [])\n .find((child) => child.hasAttribute('data-error')) as HTMLElement | undefined;\n }\n\n private static _showFileError(input: HTMLInputElement, message: string) {\n Forms._markInvalid(input, !input.validity.valid);\n const error = Forms._fileError(input);\n if (!error) return;\n Forms._addDescription(input, Forms._idOf(error));\n error.textContent = message;\n error.hidden = !message;\n }\n\n private static _onFileInput = (event: Event) => {\n const input = Utils.closestInPath<HTMLInputElement>(event, '.drop-zone input[type=\"file\"]');\n if (!input) return;\n if (input.matches(':disabled')) return;\n Forms._updateDropZone(input);\n };\n\n private static _updateDropZone(input: HTMLInputElement) {\n Forms._bindShadowForm(input);\n const zone = input.closest('.drop-zone');\n const files = Array.from(input.files ?? []);\n const failure = Forms._validateDropZone(input);\n Forms.listDropZoneFiles(zone, input);\n Forms._reportFileRejection(input, files, failure);\n }\n\n private static _validateDropZone(input: HTMLInputElement) {\n if (Forms._validatedFile(input)) return Forms._validateFiles(input);\n Forms.validateField(input);\n }\n\n private static _reportFileRejection(input: HTMLInputElement, files: File[], failure?: FileFailure) {\n if (!input.matches(FILE_RULES)) {\n Forms._fileSelections.delete(input);\n return;\n }\n if (!Forms._newFileSelection(input, files)) return;\n if (!failure) return;\n Utils.emit(input.closest('.drop-zone'), 'reject', { input, files: files.slice(), rejected: failure.rejected.slice(), reason: failure.reason });\n }\n\n private static _newFileSelection(input: HTMLInputElement, files: File[]) {\n const constraints = JSON.stringify([input.hasAttribute('data-validate-types'), input.accept, fileLimit(input, 'data-max-size'), fileLimit(input, 'data-max-files')]);\n const previous = Forms._fileSelections.get(input);\n Forms._fileSelections.set(input, { files, constraints });\n return !previous || previous.constraints !== constraints || previous.files.length !== files.length ||\n !previous.files.every((file, index) => file === files[index]);\n }\n\n // Submit and reset do not leave a shadow root, so the document never hears\n // them. Adding the same listener again does nothing.\n private static _bindShadowForm(input: HTMLInputElement) {\n if (!(input.getRootNode() as ShadowRoot).host) return;\n for (const type of ['submit', 'reset']) input.form?.addEventListener(type, Forms.resetFormExtras, true);\n }\n\n private static _resetFileInput(input: HTMLInputElement) {\n if (input.files?.length) return;\n Forms._fileSelections.delete(input);\n Forms._resetFileList(input);\n Forms._resetFileValidity(input);\n }\n\n private static _resetFileList(input: HTMLInputElement) {\n const zone = input.closest('.drop-zone');\n if (!zone) return;\n Forms.listDropZoneFiles(zone, input);\n zone.classList.remove('dragover');\n }\n\n private static _resetFileValidity(input: HTMLInputElement) {\n if (input.matches(':disabled')) return;\n if (!Forms._validatedFile(input)) return;\n Forms._clearFileError(input);\n Forms._fileErrors.delete(input);\n Forms._showFileError(input, input.validationMessage);\n }\n\n private static _afterReset(form: HTMLFormElement) {\n const fields = Array.from(form.elements);\n fields.filter((field): field is HTMLInputElement =>\n field instanceof HTMLInputElement && field.type === 'file').forEach(Forms._resetFileInput);\n fields.filter((field) => field.classList.contains('validate'))\n .forEach((field: HTMLInputElement) => Forms._markInvalid(field, false));\n fields.filter((field) => field.classList.contains('expressive-textarea')).forEach(Forms.textareaAutoResize);\n const summary = form.querySelector<HTMLElement>('.error-summary');\n if (!summary) return;\n summary.hidden = true;\n summary.querySelector('ul, ol')?.replaceChildren();\n }\n\n /**\n * Safe to call more than once: the root entry calls it on import, and a page\n * that also loads the modular entry may call it again.\n */\n static Init() {\n if (Forms._initialized) return;\n Forms._initialized = true;\n Utils.onDocumentReady(() => {\n document.addEventListener('input', Forms._onFileInput);\n document.addEventListener('change', (e: Event) => {\n const target = Utils.eventTarget(e);\n if (!(target instanceof HTMLInputElement)) return;\n if (target.matches('.drop-zone input[type=\"file\"]')) {\n Forms._onFileInput(e);\n return;\n }\n // The sibling-label loop that used to live here compared\n // `tagName == 'label'` (tagName is uppercase) so it never matched,\n // and no rule in the Sass styles `label.active` anyway - the\n // floating label is driven by CSS, not by a class from here.\n Forms.validateField(target);\n });\n\n document.addEventListener('click', Forms.togglePassword);\n document.addEventListener('click', Forms.stepNumber);\n // Capture, so the password is hidden again before any submit handler\n // reads the form or the browser offers to save it.\n document.addEventListener('submit', Forms.resetFormExtras, true);\n document.addEventListener('submit', Forms.summarizeErrors, true);\n document.addEventListener('click', Forms.focusSummaryField);\n document.addEventListener('reset', Forms.resetFormExtras, true);\n for (const type of ['dragenter', 'dragover', 'dragleave', 'drop']) {\n document.addEventListener(type, Forms.markDropZone);\n }\n\n document.querySelectorAll('.expressive-textarea').forEach((textArea: HTMLTextAreaElement) => {\n Forms.InitTextarea(textArea);\n });\n\n // File Input Path\n document\n .querySelectorAll('.file-field input[type=\"file\"]')\n .forEach((fileInput: HTMLInputElement) => {\n Forms.InitFileInputPath(fileInput);\n });\n });\n }\n\n /**\n * A .password-toggle button shows or hides the password in its field. The\n * button's own name stays put (\"Show password\"); aria-pressed carries the\n * state, so there is no generated text to translate.\n */\n static togglePassword(e: MouseEvent) {\n const button = Utils.closestInPath(e, '.password-toggle');\n const input = button?.closest('.field')?.querySelector<HTMLInputElement>(\n 'input[type=\"password\"], input[data-password]'\n );\n if (!input) return;\n Forms._bindShadowForm(input);\n const show = input.type === 'password';\n // Marked so the input is still found once it has become type=\"text\".\n input.toggleAttribute('data-password', show);\n input.type = show ? 'text' : 'password';\n button.setAttribute('aria-pressed', String(show));\n }\n\n /**\n * A [data-step=\"up\"] or [data-step=\"down\"] button in a .field steps the\n * field's number input as the arrow keys would, within min, max and step,\n * and fires input and change if the value moved. A disabled, read-only or step=\"any\" input\n * is left alone; stepUp() would throw on step=\"any\".\n */\n static stepNumber(e: MouseEvent) {\n const button = Utils.closestInPath(e, '.field > [data-step]:not(:disabled)') as HTMLElement | null;\n const input = button?.parentElement!.querySelector<HTMLInputElement>(\n ':scope > input[type=\"number\"]:not(:disabled, [readonly], [step=\"any\"])'\n );\n if (!input) return;\n const before = input.value;\n input[button!.dataset.step === 'down' ? 'stepDown' : 'stepUp']();\n if (input.value === before) return;\n input.dispatchEvent(new Event('input', { bubbles: true, composed: true }));\n input.dispatchEvent(new Event('change', { bubbles: true }));\n }\n\n /**\n * A revealed password goes back to type=\"password\" when its form is\n * submitted or reset, so it is never sent or autofilled as plain text and\n * a reset field does not stay revealed. Reset fires no input or change\n * event, so a reset form also drops its file lists, `.validate` errors and\n * error summary, and fits each auto-resizing textarea to its restored text.\n * That cleanup waits for the native reset and respects later cancellation.\n */\n static resetFormExtras(e: Event) {\n const form = e.target;\n if (!(form instanceof HTMLFormElement)) return;\n form.querySelectorAll<HTMLInputElement>('input[data-password]').forEach((input) => {\n input.removeAttribute('data-password');\n input.type = 'password';\n input.closest('.field')?.querySelector('.password-toggle')?.setAttribute('aria-pressed', 'false');\n });\n if (e.type === 'reset') {\n // Native events can run microtasks between listeners, before a later cancellation.\n setTimeout(() => {\n if (!e.defaultPrevented) Forms._afterReset(form);\n }, 0);\n }\n }\n\n /**\n * Error summary. A `novalidate` form holding a `.error-summary` is checked\n * when it is submitted. While any field is invalid the submit stops, as it\n * would natively, and the summary's list gets one link per invalid field,\n * \"Label: browser message\", before the summary is shown and focused. A\n * valid submit hides it again. A submitter with `formnovalidate` skips the\n * check.\n */\n static summarizeErrors(e: SubmitEvent) {\n const form = e.target;\n if (!(form instanceof HTMLFormElement)) return;\n const summary = form.querySelector<HTMLElement>('.error-summary');\n const list = summary?.querySelector('ul, ol');\n if (!list || e.submitter?.hasAttribute('formnovalidate')) return;\n // checkValidity fires `invalid` on each field, which FormSelect needs to\n // mark its generated field.\n if (form.checkValidity()) {\n summary.hidden = true;\n list.replaceChildren();\n return;\n }\n e.preventDefault();\n // Stop here, in the capture phase, so the page's own submit handlers do\n // not run for a form the browser would not have submitted.\n e.stopPropagation();\n const seen = new Set<string>();\n const items = [...form.elements].flatMap((field: HTMLInputElement) => {\n if (!field.willValidate || field.validity.valid) return [];\n // One entry per radio group.\n if (field.type === 'radio') {\n if (seen.has(field.name)) return [];\n seen.add(field.name);\n }\n if (!field.id) field.id = `field-${Utils.guid()}`;\n const group = field.type === 'radio' ? field.closest('fieldset')?.querySelector('legend') : null;\n // An enhanced select's label names the generated input, so fall back to\n // the label in the same .field.\n const named = group ?? field.labels?.[0] ?? field.closest('.field')?.querySelector('label');\n // A label can wrap its control; a select's options are not its name.\n const text = named?.cloneNode(true) as Element;\n text?.querySelectorAll('select, textarea').forEach((control) => control.remove());\n const label = text?.textContent ?? field.getAttribute('aria-label') ?? '';\n const link = document.createElement('a');\n link.href = `#${field.id}`;\n link.textContent = [label.replace(/\\s+/g, ' ').trim(), field.validationMessage].filter(Boolean).join(': ');\n const item = document.createElement('li');\n item.append(link);\n return [item];\n });\n list.replaceChildren(...items);\n if (!summary.hasAttribute('tabindex')) summary.tabIndex = -1;\n summary.hidden = false;\n summary.focus();\n }\n\n /**\n * A summary link focuses its field instead of only scrolling to it. An\n * enhanced select passes that focus on to its generated input itself.\n */\n static focusSummaryField(e: MouseEvent) {\n const link = Utils.closestInPath(e, '.error-summary a[href^=\"#\"]');\n const field = link && Utils.getElementById(link, link.getAttribute('href').slice(1));\n if (!field) return;\n e.preventDefault();\n field.focus();\n }\n\n /**\n * The native file input covers its .drop-zone, so the browser already takes\n * a dropped file. This only shows the drag: the input is the topmost\n * element, so every drag event over the zone targets it and leaving it is\n * leaving the zone.\n */\n static markDropZone(e: DragEvent) {\n const input = Utils.eventTarget(e);\n if (!(input instanceof HTMLInputElement) || input.type !== 'file') return;\n const zone = input.closest('.drop-zone');\n if (!zone) return;\n const over = e.type === 'dragenter' || e.type === 'dragover';\n zone.classList.toggle('dragover', over && !input.disabled);\n }\n\n /** Lists the chosen files, name and size, in the zone's .drop-zone-files. */\n static listDropZoneFiles(zone: Element, input: HTMLInputElement) {\n const list = Array.from(zone.querySelectorAll('.drop-zone-files')).find((list) => list.closest('.drop-zone') === zone);\n if (!list) return;\n const size = (bytes: number) => {\n const [value, unit] =\n bytes >= 1e6 ? [bytes / 1e6, 'megabyte'] : bytes >= 1e3 ? [bytes / 1e3, 'kilobyte'] : [bytes, 'byte'];\n return new Intl.NumberFormat(undefined, { style: 'unit', unit, maximumFractionDigits: 1 }).format(value);\n };\n list.replaceChildren(\n ...Array.from(input.files ?? [], (file) => {\n const item = document.createElement('li');\n const name = document.createElement('span');\n const meta = document.createElement('span');\n name.textContent = file.name;\n meta.textContent = size(file.size);\n item.append(name, meta);\n return item;\n })\n );\n }\n\n static InitTextarea(textarea: HTMLTextAreaElement) {\n // Measured afresh by textareaAutoResize, which skips a hidden textarea.\n textarea.removeAttribute('original-height');\n Forms.textareaAutoResize(textarea);\n // `input` rather than keydown + keyup: it fires once per actual value\n // change and also covers paste, drag-drop and IME composition, which the\n // key events missed.\n textarea.addEventListener('input', (e) => Forms.textareaAutoResize(e.target));\n // One that was hidden at init gets its first measurement once shown.\n textarea.addEventListener('focus', () => {\n if (!textarea.hasAttribute('original-height')) Forms.textareaAutoResize(textarea);\n });\n }\n\n static InitFileInputPath(fileInput: HTMLInputElement) {\n fileInput.addEventListener('change', () => {\n const fileField = fileInput.closest('.file-field');\n const pathInput = fileField?.querySelector<HTMLInputElement>('input.file-path');\n if (!pathInput) return;\n pathInput.value = Array.from(fileInput.files, (f) => f.name).join(', ');\n pathInput.dispatchEvent(\n new Event('change', { bubbles: true, cancelable: true, composed: true })\n );\n });\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["list"]
7
+ }
@@ -2,19 +2,20 @@ import {
2
2
  formAssociated,
3
3
  unwrapControl,
4
4
  wrapInControl
5
- } from "./chunk-INLZWHLY.mjs";
5
+ } from "./chunk-UHO5CV6K.mjs";
6
6
  import {
7
7
  Autocomplete
8
- } from "./chunk-VGY4M57S.mjs";
8
+ } from "./chunk-F7LAKFMX.mjs";
9
9
  import {
10
10
  Component
11
- } from "./chunk-CMGXGYUC.mjs";
11
+ } from "./chunk-EB2V4OKL.mjs";
12
12
  import {
13
13
  Utils,
14
14
  restoreAttribute
15
- } from "./chunk-ZVLOUDIJ.mjs";
15
+ } from "./chunk-67UNY7RH.mjs";
16
16
 
17
17
  // src/ts/components/chips.ts
18
+ var isMoveKey = (e) => (e.key === "ArrowLeft" || e.key === "ArrowRight") && Utils.plainKey(e);
18
19
  var CONTROL = "expressive-chips-control";
19
20
  var pastedValues = (e) => (e.clipboardData?.getData("text") ?? "").split(/[,\t\n]/).map((value) => value.trim()).filter(Boolean);
20
21
  var _defaults = {
@@ -38,6 +39,8 @@ var _Chips = class _Chips extends Component {
38
39
  this._name = "";
39
40
  /** The chips the field started with, which a form reset puts back. */
40
41
  this._initialData = [];
42
+ /** Undoes each change setup made to the markup, newest last. */
43
+ this._undo = [];
41
44
  /** The input's own aria-required, or null, put back on destroy. */
42
45
  this._ariaRequired = null;
43
46
  /** The form control wrapping a named input, which the form reads instead of it. */
@@ -90,25 +93,23 @@ var _Chips = class _Chips extends Component {
90
93
  }
91
94
  e.preventDefault();
92
95
  if (!this.hasAutocomplete || !this.options.autocompleteOnly) {
93
- this.addChip({ id: this._input.value });
96
+ this.addChip({ id: this._input.value.trim() });
94
97
  }
95
98
  this._input.value = "";
96
99
  this.autocomplete?.close();
97
- } else if (this._input.value === "" && this.chipsData.length && ["Backspace", _Chips._backKey(this.el)].includes(e.key)) {
100
+ } else if (this._leavesInput(e)) {
98
101
  e.preventDefault();
99
102
  this.selectChip(this.chipsData.length - 1);
100
103
  }
101
104
  };
102
- this.el.classList.add("chips");
105
+ this._addClass(this.el, "chips");
103
106
  this.chipsData = [];
104
107
  this._chips = [];
105
108
  this._takeName();
106
- if (this.options.data.length) {
107
- this.chipsData = [...this.options.data];
108
- this._renderChips();
109
- }
109
+ this._takeInitialData(this.options.data);
110
+ if (this.chipsData.length) this._renderChips();
110
111
  if (this.options.allowUserInput) {
111
- this.el.classList.add("field");
112
+ this._addClass(this.el, "field");
112
113
  this._setupInput();
113
114
  this._setupEventHandlers();
114
115
  this.el.append(this._end);
@@ -145,6 +146,9 @@ var _Chips = class _Chips extends Component {
145
146
  this._chips.forEach((c) => c.remove());
146
147
  this._chips = [];
147
148
  this._giveNameBack();
149
+ this.el.classList.remove("focus");
150
+ this._undo.reverse().forEach((undo) => undo());
151
+ this._undo = [];
148
152
  super.destroy();
149
153
  }
150
154
  _setupEventHandlers() {
@@ -258,14 +262,14 @@ var _Chips = class _Chips extends Component {
258
262
  const chips = e.target.closest(".chips");
259
263
  const tag = e.target.tagName;
260
264
  if (tag === "INPUT" || tag === "TEXTAREA" || !chips) return;
261
- const currChips = chips["Expressive_Chips"];
265
+ const currChips = _Chips.getInstance(chips);
262
266
  if (!currChips) return;
263
267
  if (e.key === "Backspace" || e.key === "Delete") {
264
268
  const index = currChips._chips.indexOf(e.target.closest(".chip"));
265
269
  if (index < 0) return;
266
270
  e.preventDefault();
267
271
  currChips._deleteChip(index, "previous");
268
- } else if (e.key === "ArrowLeft" || e.key === "ArrowRight") {
272
+ } else if (isMoveKey(e)) {
269
273
  const current = e.target.closest(".chip") ?? currChips._selectedChip;
270
274
  const index = currChips._chips.indexOf(current);
271
275
  if (index < 0) return;
@@ -280,6 +284,10 @@ var _Chips = class _Chips extends Component {
280
284
  }
281
285
  }
282
286
  }
287
+ /** Whether a key moves from the empty input back to the last chip. */
288
+ _leavesInput(e) {
289
+ return this._input.value === "" && this.chipsData.length > 0 && Utils.plainKey(e) && ["Backspace", _Chips._backKey(this.el)].includes(e.key);
290
+ }
283
291
  _renderChip(chip) {
284
292
  if (!chip.id && chip.id !== 0) return;
285
293
  const label = chip.text || chip.id;
@@ -305,6 +313,17 @@ var _Chips = class _Chips extends Component {
305
313
  }
306
314
  return renderedChip;
307
315
  }
316
+ /**
317
+ * Copies the starting chips, so adding or deleting one does not edit the
318
+ * caller's array and a batch init does not share one list. Blank ids,
319
+ * duplicates and chips past the limit are dropped, as addChip drops them: a
320
+ * blank id used to render nothing and throw from the constructor.
321
+ */
322
+ _takeInitialData(data) {
323
+ for (const chip of data) {
324
+ if (this.chipsData.length < this.options.limit && this._isValidAndNotExist(chip)) this.chipsData.push(chip);
325
+ }
326
+ }
308
327
  _renderChips() {
309
328
  this._chips = [];
310
329
  for (let i = 0; i < this.chipsData.length; i++) {
@@ -338,25 +357,47 @@ var _Chips = class _Chips extends Component {
338
357
  /** The "Add" row is a deliberate choice, so it adds a chip even in an autocompleteOnly field. */
339
358
  _addTyped(text) {
340
359
  if (_Chips.getInstance(this.el) !== this) return;
341
- this.addChip({ id: text });
360
+ this.addChip({ id: text.trim() });
342
361
  this._input.value = "";
343
362
  this._input.focus();
344
363
  }
345
364
  _setupInput() {
346
365
  this._input = this.el.querySelector("input");
347
366
  if (!this._input) {
348
- this._input = document.createElement("input");
349
- this.el.append(this._input);
367
+ const input = this._input = document.createElement("input");
368
+ this.el.append(input);
369
+ this._undo.push(() => input.remove());
350
370
  }
351
- this._input.classList.add("input");
371
+ this._addClass(this._input, "input");
372
+ this._keepAttribute(this._input, "placeholder");
352
373
  this.hasAutocomplete = Object.keys(this.options.autocompleteOptions).length > 0;
353
374
  if (this.hasAutocomplete) this._setupAutocomplete();
354
375
  this._setPlaceholder();
355
- if (!this._input.getAttribute("id")) this._input.setAttribute("id", Utils.guid());
376
+ if (!this._input.getAttribute("id")) {
377
+ this._keepAttribute(this._input, "id");
378
+ this._input.setAttribute("id", Utils.guid());
379
+ }
356
380
  }
357
381
  _setupLabel() {
358
382
  this._label = this.el.querySelector("label");
359
- if (this._label && this._input) this._label.setAttribute("for", this._input.getAttribute("id"));
383
+ if (!this._label || !this._input) return;
384
+ this._keepAttribute(this._label, "for");
385
+ this._label.setAttribute("for", this._input.getAttribute("id"));
386
+ }
387
+ /** Adds a class the markup did not have, for destroy() to take off. */
388
+ _addClass(el, name) {
389
+ if (el.classList.contains(name)) return;
390
+ const hadClass = el.hasAttribute("class");
391
+ el.classList.add(name);
392
+ this._undo.push(() => {
393
+ el.classList.remove(name);
394
+ if (!hadClass && !el.classList.length) el.removeAttribute("class");
395
+ });
396
+ }
397
+ /** Keeps an attribute's value for destroy() to put back. */
398
+ _keepAttribute(el, name) {
399
+ const value = el.getAttribute(name);
400
+ this._undo.push(() => restoreAttribute(el, name, value));
360
401
  }
361
402
  _setPlaceholder() {
362
403
  if (!this._input) return;
@@ -367,8 +408,8 @@ var _Chips = class _Chips extends Component {
367
408
  }
368
409
  }
369
410
  _isValidAndNotExist(chip) {
370
- const isValid = !!chip.id || chip.id === 0;
371
- const doesNotExist = !this.chipsData.some((item) => item.id == chip.id);
411
+ const isValid = (!!chip.id || chip.id === 0) && String(chip.id).trim() !== "";
412
+ const doesNotExist = !this.chipsData.some((item) => String(item.id) === String(chip.id));
372
413
  return isValid && doesNotExist;
373
414
  }
374
415
  /**
@@ -410,7 +451,7 @@ var _Chips = class _Chips extends Component {
410
451
  root = "host" in root ? root.host.getRootNode() : null;
411
452
  }
412
453
  this._notify("chip-delete", this.options.onChipDelete, { args: [this.el, chip], detail: { chip }, current: () => !this._chips.includes(chip) });
413
- if (!focus || focusPath.some(({ root: root2, element }) => root2.activeElement !== element) || this.el["Expressive_Chips"] !== this) return;
454
+ if (!focus || focusPath.some(({ root: root2, element }) => root2.activeElement !== element) || _Chips.getInstance(this.el) !== this) return;
414
455
  if (focus === "previous" && this._chips.length) this.selectChip(Math.max(chipIndex - 1, 0));
415
456
  else {
416
457
  this._setSelected(null);
@@ -435,7 +476,7 @@ var _Chips = class _Chips extends Component {
435
476
  el.addEventListener("click", (e) => {
436
477
  if (!e.target.closest(".close")) return;
437
478
  const chip = e.target.closest(".chip");
438
- if (chip && !el["Expressive_Chips"]?._chips.includes(chip)) chip.remove();
479
+ if (chip && !_Chips.getInstance(el)?._chips.includes(chip)) chip.remove();
439
480
  });
440
481
  });
441
482
  });
@@ -447,4 +488,4 @@ var Chips = _Chips;
447
488
  export {
448
489
  Chips
449
490
  };
450
- //# sourceMappingURL=chunk-WU7XJ4RR.mjs.map
491
+ //# sourceMappingURL=chunk-LXRHUQAX.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/ts/components/chips.ts"],
4
+ "sourcesContent": ["import { Utils, restoreAttribute } from '../core/utils';\nimport { Autocomplete, AutocompleteOptions } from './autocomplete';\nimport { Component, BaseOptions } from '../core/component';\nimport { FormControl, formAssociated, wrapInControl, unwrapControl } from '../core/formControl';\n\n/** Whether a key moves between chips. Alt, Ctrl and Meta stay the browser's. */\nconst isMoveKey = (e: KeyboardEvent) => (e.key === 'ArrowLeft' || e.key === 'ArrowRight') && Utils.plainKey(e);\n\nexport interface ChipData {\n /**\n * Unique identifier.\n */\n id: number | string;\n /**\n * Chip text. If not specified, \"id\" will be used.\n */\n text?: string;\n /**\n * Chip image (URL).\n */\n image?: string;\n}\n\n/** The form control a named field submits through, wrapping its input. */\nconst CONTROL = 'expressive-chips-control';\n\n/** The values in pasted text, split by commas, tabs or lines. */\nconst pastedValues = (e: ClipboardEvent) =>\n (e.clipboardData?.getData('text') ?? '').split(/[,\\t\\n]/).map((value) => value.trim()).filter(Boolean);\n\nexport interface ChipsI18nOptions {\n /** Prefix for the delete button's accessible name. */\n remove: string;\n /** What a required field says while it has no chips. */\n required: string;\n}\n\nexport interface ChipsOptions extends BaseOptions {\n /**\n * Set the chip data.\n * @default []\n */\n data: ChipData[];\n /**\n * Set first placeholder when there are no tags.\n * @default \"\"\n */\n placeholder: string;\n /**\n * Set second placeholder when adding additional tags.\n * @default \"\"\n */\n secondaryPlaceholder: string;\n /**\n * Set autocomplete options.\n * @default {}\n */\n autocompleteOptions: Partial<AutocompleteOptions>;\n /**\n * Toggles abililty to add custom value not in autocomplete list.\n * @default false\n */\n autocompleteOnly: boolean;\n /**\n * Set chips limit.\n * @default Infinity\n */\n limit: number;\n /**\n * Specifies class to be used in \"close\" button.\n * @default 'material-symbols'\n */\n closeIconClass: string;\n /**\n * Specifies option to render user input field\n * @default false;\n */\n allowUserInput: boolean;\n /**\n * Strings the component generates. `remove` prefixes the delete button's\n * accessible name, giving \"Remove Apple\". `required` is what a required\n * field says while it has no chips.\n * @default { remove: 'Remove', required: 'Add at least one item.' }\n */\n i18n: Partial<ChipsI18nOptions>;\n /**\n * Callback for chip add.\n * @default null\n */\n onChipAdd: (element: HTMLElement, chip: HTMLElement) => void;\n /**\n * Callback for chip select.\n * @default null\n */\n onChipSelect: (element: HTMLElement, chip: HTMLElement) => void;\n /**\n * Callback for chip delete.\n * @default null\n */\n onChipDelete: (element: HTMLElement, chip: HTMLElement) => void;\n}\n\nconst _defaults: ChipsOptions = {\n data: [],\n placeholder: '',\n secondaryPlaceholder: '',\n closeIconClass: 'material-symbols',\n autocompleteOptions: {},\n autocompleteOnly: false,\n limit: Infinity,\n allowUserInput: false,\n i18n: { remove: 'Remove', required: 'Add at least one item.' },\n onChipAdd: null,\n onChipSelect: null,\n onChipDelete: null\n};\n\nexport class Chips extends Component<ChipsOptions> {\n /** Array of the current chips data. */\n chipsData: ChipData[];\n /** If the chips has autocomplete enabled. */\n hasAutocomplete: boolean;\n /** Autocomplete instance, if any. */\n autocomplete: Autocomplete;\n _input: HTMLInputElement;\n _label: HTMLLabelElement;\n _chips: HTMLElement[];\n private _selectedChip: HTMLElement;\n /** The form name the text input had, which the chips submit instead. */\n private _name = '';\n /** The chips the field started with, which a form reset puts back. */\n private _initialData: ChipData[] = [];\n /** Undoes each change setup made to the markup, newest last. */\n private _undo: (() => void)[] = [];\n /** The input's own aria-required, or null, put back on destroy. */\n private _ariaRequired: string | null = null;\n /** The form control wrapping a named input, which the form reads instead of it. */\n private _control: FormControl | null = null;\n /** The named text input, whose form, disabled state and required the chips take over. */\n private _source: HTMLInputElement | null = null;\n private _required = false;\n\n /**\n * Selection is drawn by a class now, not by `:focus`, so it does not clear\n * itself when focus moves - every path that changes the selection has to go\n * through here or the class and the field drift apart.\n *\n * Deliberately no `aria-selected`: the chip is not an option in a listbox,\n * and putting the attribute on an element with no such role is the same\n * defect the semantics standard exists to remove.\n */\n private _setSelected(chip: HTMLElement | null) {\n this._selectedChip?.classList.remove('selected');\n this._selectedChip = chip;\n chip?.classList.add('selected');\n }\n\n constructor(el: HTMLElement, options: Partial<ChipsOptions>) {\n super(el, options);\n\n this._addClass(this.el, 'chips');\n this.chipsData = [];\n this._chips = [];\n this._takeName();\n\n // Render initial chips\n this._takeInitialData(this.options.data);\n if (this.chipsData.length) this._renderChips();\n\n // Render input element, setup event handlers\n if (this.options.allowUserInput) {\n this._addClass(this.el, 'field');\n this._setupInput();\n this._setupEventHandlers();\n // move input to end, inside its control when it has one\n this.el.append(this._end);\n }\n // After _setupInput: the label points at the input's id, which is only\n // assigned there. Running this first threw on any .chips with a <label>.\n this._setupLabel();\n this._sync();\n // After autocomplete, which can turn the input's value into a chip.\n this._initialData = [...this.chipsData];\n }\n\n static get defaults() {\n return _defaults;\n }\n\n static key = 'Expressive_Chips';\n\n getData() {\n return this.chipsData;\n }\n\n destroy() {\n if (this.autocomplete && Autocomplete.getInstance(this._input) === this.autocomplete) {\n this.autocomplete.destroy();\n }\n this._events.abort();\n this._chips.forEach((c) => c.remove());\n this._chips = [];\n this._giveNameBack();\n this.el.classList.remove('focus');\n this._undo.reverse().forEach((undo) => undo());\n this._undo = [];\n super.destroy();\n }\n\n _setupEventHandlers() {\n const { signal } = this._events;\n this.el.addEventListener('click', this._handleChipClick, { signal });\n this.el.addEventListener('keydown', Chips._handleChipsKeydown, { signal });\n this.el.addEventListener('focusin', this._handleFocusIn, { signal });\n this.el.addEventListener('focusout', this._handleFocusOut, { signal });\n this._input.addEventListener('focus', this._handleInputFocus, { signal });\n this._input.addEventListener('blur', this._handleInputBlur, { signal });\n this._input.addEventListener('keydown', this._handleInputKeydown, { signal });\n this._input.addEventListener('paste', this._handleInputPaste, { signal });\n }\n\n /**\n * A text input with a `name` would submit whatever is half typed. The chips\n * submit under that name instead, one value per chip, as a multiple select\n * does, so the input gives its name up until destroy().\n */\n private _takeName() {\n const input = this._editorInput();\n this._name = input?.getAttribute('name') ?? '';\n // ponytail: without form-associated custom elements (jsdom) the input keeps its name and submits its text.\n if (this._name && formAssociated()) this._wrap(input);\n }\n\n /**\n * Wraps the input in the form control, which takes its name and required.\n * `display: contents` lays the input out as a child of the field still.\n */\n private _wrap(input: HTMLInputElement) {\n this._source = input;\n this._takeRequired(input);\n // The control follows the input's disabled state and form; a read-only input is not validated, so its required no longer counts.\n this._control = wrapInControl(CONTROL, input, () => this._validate());\n this._control.onFormReset = () => this._resetChips();\n this._validate();\n }\n\n /**\n * The editor's text field, or null. A static .chips of filter checkboxes,\n * which AutoInit also starts, keeps its own native form values.\n */\n private _editorInput() {\n return this.options.allowUserInput ? this.el.querySelector<HTMLInputElement>('input:is(:not([type]), [type=\"text\"])') : null;\n }\n\n /** Where the text field ends: chips go before it, and it goes last. */\n private get _end() {\n return this._control ?? this._input;\n }\n\n /** After the chips change: give the form one value per chip and update a required field's validity. */\n private _sync() {\n if (!this._control) return;\n const data = new FormData();\n this.chipsData.forEach((chip) => data.append(this._name, String(chip.id)));\n this._control.internals.setFormValue(data);\n this._validate();\n }\n\n /**\n * The chips are what is required, not the text, so `required` moves to the\n * control, and aria-required keeps telling assistive technology.\n */\n private _takeRequired(input: HTMLInputElement) {\n this._required = input.required;\n if (!this._required) return;\n this._ariaRequired = input.getAttribute('aria-required');\n input.required = false;\n input.setAttribute('aria-required', 'true');\n }\n\n /**\n * A required field is valid once it has a chip, whatever is half typed. The\n * control holds this validity, apart from any error the page sets on the\n * input, and anchors it at the input, which a submit then focuses.\n */\n private _validate() {\n const internals = this._control.internals;\n if (this._required && !this._source.readOnly && !this.chipsData.length) {\n internals.setValidity({ valueMissing: true }, this._requiredMessage, this._anchor);\n } else internals.setValidity({});\n }\n\n /** The input, unless page script moved it out of the control, where it cannot anchor the message. */\n private get _anchor() {\n return this._control.contains(this._source) ? this._source : undefined;\n }\n\n /** A validity flag needs a message, so an empty i18n.required falls back to the default. */\n private get _requiredMessage() {\n return this.options.i18n.required || _defaults.i18n.required;\n }\n\n private _resetChips() {\n this._setSelected(null);\n this._chips.forEach((chip) => chip.remove());\n this.chipsData = [...this._initialData];\n this._chips = this.chipsData.map((chip) => this._renderChip(chip));\n this._control.before(...this._chips);\n this._setPlaceholder();\n this._sync();\n }\n\n /** Unwraps the input, with whatever else went in the control, and gives it its name and required back. */\n private _giveNameBack() {\n if (!this._control) return;\n unwrapControl(this._control, this._source);\n this._control = null;\n if (!this._required) return;\n this._source.required = true;\n restoreAttribute(this._source, 'aria-required', this._ariaRequired);\n }\n\n /** Whether only an autocomplete suggestion can become a chip. */\n private get _suggestionsOnly() {\n return this.hasAutocomplete && this.options.autocompleteOnly;\n }\n\n /** Pasted text that lists several values, split by commas, tabs or lines, adds a chip for each. */\n _handleInputPaste = (e: ClipboardEvent) => {\n const values = pastedValues(e);\n if (values.length < 2 || this._suggestionsOnly) return;\n e.preventDefault();\n // An add callback can destroy or replace the instance; the rest of the paste is its.\n values.every((id) => (this.addChip({ id }), Chips.getInstance(this.el) === this));\n };\n\n _handleChipClick = (e: MouseEvent) => {\n const _chip = (<HTMLElement>e.target).closest('.chip');\n // closest, not classList: the close button now wraps an icon span, so a\n // click on the glyph reports the span as the target.\n const clickedClose = !!(<HTMLElement>e.target).closest('.close');\n if (_chip) {\n // Index into the chip list, not into the container's children: the\n // container also holds the label and the input, so counting children\n // gave an index that did not line up with chipsData.\n const index = this._chips.indexOf(_chip as HTMLElement);\n if (index < 0) return;\n if (clickedClose) {\n this._deleteChip(index, 'input');\n } else {\n this.selectChip(index);\n }\n // Default handle click to focus on input\n } else {\n this._input.focus();\n }\n };\n\n /** The arrow that points back towards the first chip, which in RTL is Right. */\n private static _backKey(el: Element) {\n return getComputedStyle(el).direction === 'rtl' ? 'ArrowRight' : 'ArrowLeft';\n }\n\n static _handleChipsKeydown(e: KeyboardEvent) {\n const chips = (<HTMLElement>e.target).closest('.chips');\n\n // Don't handle keydown inputs on input and textarea\n const tag = (<HTMLElement>e.target).tagName;\n if (tag === 'INPUT' || tag === 'TEXTAREA' || !chips) return;\n\n const currChips = Chips.getInstance(chips);\n if (!currChips) return; // .chips markup without an instance behind it\n\n if (e.key === 'Backspace' || e.key === 'Delete') {\n const index = currChips._chips.indexOf((e.target as HTMLElement).closest('.chip'));\n if (index < 0) return;\n e.preventDefault();\n currChips._deleteChip(index, 'previous');\n } else if (isMoveKey(e)) {\n // Move from the chip that has focus, the same one Backspace deletes.\n const current = (e.target as HTMLElement).closest<HTMLElement>('.chip') ?? currChips._selectedChip;\n const index = currChips._chips.indexOf(current);\n if (index < 0) return;\n if (e.key === Chips._backKey(chips)) {\n if (index > 0) currChips.selectChip(index - 1);\n } else {\n const selectIndex = index + 1;\n if (selectIndex >= currChips.chipsData.length) {\n // Walking off the end returns to the input, so nothing is selected\n // any more - without this the last chip kept the class.\n currChips._setSelected(null);\n currChips._input.focus();\n }\n else currChips.selectChip(selectIndex);\n }\n }\n }\n\n // Selection follows focus: a chip is selected while focus is inside it, and\n // none is once focus moves to the input or out of the field.\n _handleFocusIn = (e: FocusEvent) => {\n const chip = (e.target as HTMLElement).closest<HTMLElement>('.chip');\n this._setSelected(chip && this._chips.includes(chip) ? chip : null);\n };\n\n _handleFocusOut = (e: FocusEvent) => {\n if (!this.el.contains(e.relatedTarget as Node | null)) this._setSelected(null);\n };\n\n _handleInputFocus = () => {\n this.el.classList.add('focus');\n };\n\n _handleInputBlur = () => {\n this.el.classList.remove('focus');\n };\n\n _handleInputKeydown = (e: KeyboardEvent) => {\n // Enter that confirms an IME composition is not a request to add a chip.\n if (Utils.isComposing(e)) return;\n if (e.key === 'Enter') {\n // Override enter if autocompleting.\n if (this.hasAutocomplete && this.autocomplete?.isOpen &&\n this.autocomplete.container.querySelector('[role=\"option\"]')) {\n return;\n }\n e.preventDefault();\n if (!this.hasAutocomplete || !this.options.autocompleteOnly) {\n this.addChip({ id: this._input.value.trim() });\n }\n this._input.value = '';\n // The list answered the text Enter just used up.\n this.autocomplete?.close();\n } else if (this._leavesInput(e)) {\n e.preventDefault();\n this.selectChip(this.chipsData.length - 1);\n }\n };\n\n /** Whether a key moves from the empty input back to the last chip. */\n private _leavesInput(e: KeyboardEvent) {\n return this._input.value === '' && this.chipsData.length > 0 && Utils.plainKey(e) &&\n ['Backspace', Chips._backKey(this.el)].includes(e.key);\n }\n\n _renderChip(chip: ChipData): HTMLElement {\n if (!chip.id && chip.id !== 0) return;\n const label = chip.text || <string>chip.id;\n // <span>, not <div>: a chip is inline, and the container itself is not a\n // control. It used to be a <div tabindex=\"0\"> with no role - focusable,\n // and announcing nothing.\n const renderedChip = document.createElement('span');\n renderedChip.classList.add('chip');\n renderedChip.innerText = label;\n // attach image if needed\n if (chip.image) {\n const img = document.createElement('img');\n img.setAttribute('src', chip.image);\n renderedChip.insertBefore(img, renderedChip.firstChild);\n }\n if (this.options.allowUserInput) {\n // The delete affordance is the control, so it is the <button> and it\n // carries the name. `type` is explicit because a bare button inside a\n // form submits it.\n const closeButton = document.createElement('button');\n closeButton.type = 'button';\n closeButton.classList.add('close');\n closeButton.setAttribute('aria-label', `${this.options.i18n.remove} ${label}`);\n // The ligature is text and is read out, so the glyph is hidden and the\n // button's own label is what gets announced.\n const closeIcon = document.createElement('span');\n closeIcon.classList.add(this.options.closeIconClass);\n closeIcon.setAttribute('aria-hidden', 'true');\n closeIcon.innerText = 'close';\n closeButton.appendChild(closeIcon);\n renderedChip.appendChild(closeButton);\n }\n return renderedChip;\n }\n\n /**\n * Copies the starting chips, so adding or deleting one does not edit the\n * caller's array and a batch init does not share one list. Blank ids,\n * duplicates and chips past the limit are dropped, as addChip drops them: a\n * blank id used to render nothing and throw from the constructor.\n */\n private _takeInitialData(data: ChipData[]) {\n for (const chip of data) {\n if (this.chipsData.length < this.options.limit && this._isValidAndNotExist(chip)) this.chipsData.push(chip);\n }\n }\n\n _renderChips() {\n this._chips = []; //.remove();\n for (let i = 0; i < this.chipsData.length; i++) {\n const chipElem = this._renderChip(this.chipsData[i]);\n this.el.appendChild(chipElem);\n this._chips.push(chipElem);\n }\n }\n\n _setupAutocomplete() {\n this.options.autocompleteOptions.onAutocomplete = (items) => {\n if (Chips.getInstance(this.el) !== this) return;\n if (items.length > 0) {\n this.addChip({\n id: items[0].id,\n text: items[0].text,\n image: items[0].image\n });\n this._input.value = '';\n this._input.focus();\n }\n };\n // A new object, so a second Chips given the same options does not wrap this wrapper.\n const pageOnCreate = this.options.autocompleteOptions.onCreate;\n this.autocomplete = Autocomplete.init(this._input, {\n ...this.options.autocompleteOptions,\n onCreate: (text, autocomplete) => {\n this._addTyped(text);\n if (typeof pageOnCreate === 'function') pageOnCreate.call(autocomplete, text, autocomplete);\n }\n });\n }\n\n /** The \"Add\" row is a deliberate choice, so it adds a chip even in an autocompleteOnly field. */\n private _addTyped(text: string) {\n if (Chips.getInstance(this.el) !== this) return;\n this.addChip({ id: text.trim() });\n this._input.value = '';\n this._input.focus();\n }\n\n _setupInput() {\n this._input = this.el.querySelector('input');\n if (!this._input) {\n const input = (this._input = document.createElement('input'));\n this.el.append(input);\n this._undo.push(() => input.remove());\n }\n this._addClass(this._input, 'input');\n this._keepAttribute(this._input, 'placeholder');\n this.hasAutocomplete = Object.keys(this.options.autocompleteOptions).length > 0;\n // Setup autocomplete if needed\n if (this.hasAutocomplete) this._setupAutocomplete();\n this._setPlaceholder();\n // Set input id\n if (!this._input.getAttribute('id')) {\n this._keepAttribute(this._input, 'id');\n this._input.setAttribute('id', Utils.guid());\n }\n }\n\n _setupLabel() {\n this._label = this.el.querySelector('label');\n // No input to point at when allowUserInput is off.\n if (!this._label || !this._input) return;\n this._keepAttribute(this._label, 'for');\n this._label.setAttribute('for', this._input.getAttribute('id'));\n }\n\n /** Adds a class the markup did not have, for destroy() to take off. */\n private _addClass(el: Element, name: string) {\n if (el.classList.contains(name)) return;\n const hadClass = el.hasAttribute('class');\n el.classList.add(name);\n this._undo.push(() => {\n el.classList.remove(name);\n if (!hadClass && !el.classList.length) el.removeAttribute('class');\n });\n }\n\n /** Keeps an attribute's value for destroy() to put back. */\n private _keepAttribute(el: Element, name: string) {\n const value = el.getAttribute(name);\n this._undo.push(() => restoreAttribute(el, name, value));\n }\n\n _setPlaceholder() {\n if (!this._input) return;\n if (!this.chipsData.length && this.options.placeholder) {\n this._input.placeholder = this.options.placeholder;\n } else if (this.chipsData.length && this.options.secondaryPlaceholder) {\n this._input.placeholder = this.options.secondaryPlaceholder;\n }\n }\n\n _isValidAndNotExist(chip: ChipData) {\n // A blank or whitespace-only label is no chip.\n const isValid = (!!chip.id || chip.id === 0) && String(chip.id).trim() !== '';\n const doesNotExist = !this.chipsData.some((item) => String(item.id) === String(chip.id));\n return isValid && doesNotExist;\n }\n\n /**\n * Add chip to input.\n * @param chip Chip data object\n */\n addChip(chip: ChipData) {\n if (!this._isValidAndNotExist(chip) || this.chipsData.length >= this.options.limit) return;\n const renderedChip = this._renderChip(chip);\n this._chips.push(renderedChip);\n this.chipsData.push(chip);\n if (this._end) this._end.before(renderedChip);\n else this.el.append(renderedChip);\n this._setPlaceholder();\n this._sync();\n this._notify('chip-add', this.options.onChipAdd, { args: [this.el, renderedChip], detail: { chip: renderedChip }, current: () => this._chips.includes(renderedChip) });\n }\n\n /**\n * Delete nth chip.\n * @param chipIndex Index of chip\n */\n deleteChip(chipIndex: number) {\n const root = this.el.getRootNode() as Document | ShadowRoot;\n this._deleteChip(chipIndex, this._chips[chipIndex]?.contains(root.activeElement) ? 'input' : null);\n }\n\n private _deleteChip(chipIndex: number, focus: 'input' | 'previous' | null) {\n const chip = this._chips[chipIndex];\n if (!chip) return;\n if (this._selectedChip === chip) this._setSelected(null);\n chip.remove();\n this._chips.splice(chipIndex, 1);\n this.chipsData.splice(chipIndex, 1);\n this._setPlaceholder();\n this._sync();\n const focusPath: { root: Document | ShadowRoot; element: Element | null }[] = [];\n let root = this.el.getRootNode() as Document | ShadowRoot;\n while (root) {\n focusPath.push({ root, element: root.activeElement });\n root = 'host' in root ? root.host.getRootNode() as Document | ShadowRoot : null;\n }\n this._notify('chip-delete', this.options.onChipDelete, { args: [this.el, chip], detail: { chip }, current: () => !this._chips.includes(chip) });\n if (!focus || focusPath.some(({ root, element }) => root.activeElement !== element) || Chips.getInstance(this.el) !== this) return;\n if (focus === 'previous' && this._chips.length) this.selectChip(Math.max(chipIndex - 1, 0));\n else {\n this._setSelected(null);\n this._input?.focus();\n }\n }\n\n /**\n * Select nth chip.\n * @param chipIndex Index of chip\n */\n selectChip(chipIndex: number) {\n const chip = this._chips[chipIndex];\n if (!chip) return;\n this._setSelected(chip);\n // The chip is not a control any more, so focus goes to the one thing in it\n // that is - the delete button.\n (chip.querySelector('.close') as HTMLElement | null)?.focus();\n this._notify('chip-select', this.options.onChipSelect, { args: [this.el, chip], detail: { chip }, current: () => this._selectedChip === chip });\n }\n\n static Init() {\n // Handle removal of static chips - markup written by hand, which no Chips\n // instance tracks even when one sits on the container (AutoInit gives every\n // .chips one, usually without allowUserInput and so without a click\n // handler). A chip the instance rendered belongs to _handleChipClick:\n // removing the node here as well left chipsData holding an entry whose\n // element was gone.\n Utils.onDocumentReady(() => {\n const chips = document.querySelectorAll('.chips');\n chips.forEach((el) => {\n el.addEventListener('click', (e) => {\n // closest: the close button wraps an icon span, so a click on the\n // glyph reports the span.\n if (!(<HTMLElement>e.target).closest('.close')) return;\n const chip = (<HTMLElement>e.target).closest<HTMLElement>('.chip');\n if (chip && !Chips.getInstance(el)?._chips.includes(chip)) chip.remove();\n });\n });\n });\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["root"]
7
+ }
@@ -1,11 +1,12 @@
1
1
  import {
2
2
  Component
3
- } from "./chunk-CMGXGYUC.mjs";
3
+ } from "./chunk-EB2V4OKL.mjs";
4
4
  import {
5
5
  Utils,
6
6
  controllerFor,
7
+ deepActiveElement,
7
8
  restoreAttribute
8
- } from "./chunk-ZVLOUDIJ.mjs";
9
+ } from "./chunk-67UNY7RH.mjs";
9
10
 
10
11
  // src/ts/components/lightbox.ts
11
12
  var _defaults = {
@@ -52,8 +53,12 @@ var Lightbox = class extends Component {
52
53
  this._handleWindowChange = () => {
53
54
  if (this.overlayActive) this.close();
54
55
  };
56
+ // On keydown, and taken, so a dialog around the lightbox does not close on
57
+ // the same press.
55
58
  this._handleWindowEscape = (e) => {
56
- if (e.key === "Escape") this.close();
59
+ if (e.key !== "Escape") return;
60
+ e.preventDefault();
61
+ this.close();
57
62
  };
58
63
  // The image zooms in place, not in a modal, so Tab would reach the page
59
64
  // behind the overlay. Tab closes it instead, then moves focus as usual.
@@ -115,7 +120,7 @@ var Lightbox = class extends Component {
115
120
  const { signal } = this._windowEvents;
116
121
  window.addEventListener("scroll", this._handleWindowChange, { passive: true, signal });
117
122
  window.addEventListener("resize", this._handleWindowChange, { passive: true, signal });
118
- window.addEventListener("keyup", this._handleWindowEscape, { signal });
123
+ window.addEventListener("keydown", this._handleWindowEscape, { signal });
119
124
  window.addEventListener("keydown", this._handleWindowTab, { signal });
120
125
  this._animateImageIn();
121
126
  };
@@ -168,8 +173,7 @@ var Lightbox = class extends Component {
168
173
  // a click on the overlay, which cannot take focus, leaves it.
169
174
  _restoreFocus() {
170
175
  const root = this.el.getRootNode();
171
- let active = document.activeElement;
172
- while (active?.shadowRoot?.activeElement) active = active.shadowRoot.activeElement;
176
+ const active = deepActiveElement(document);
173
177
  if ([document.body, root.host].includes(active)) this._trigger.focus({ preventScroll: true });
174
178
  }
175
179
  _reset() {
@@ -313,4 +317,4 @@ Lightbox.key = "Expressive_Lightbox";
313
317
  export {
314
318
  Lightbox
315
319
  };
316
- //# sourceMappingURL=chunk-VMY55K2X.mjs.map
320
+ //# sourceMappingURL=chunk-MA2SZZFB.mjs.map