@expressivecss/expressive 0.15.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 (609) hide show
  1. package/CHANGELOG.md +1807 -1
  2. package/README.md +9 -8
  3. package/dist/css/expressive.css +19176 -11958
  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/fonts/LICENSE-noto-sans-arabic +93 -0
  8. package/dist/fonts/LICENSE-noto-sans-hebrew +93 -0
  9. package/dist/fonts/LICENSE-noto-sans-thai +93 -0
  10. package/dist/fonts/material-symbols-outlined.woff2 +0 -0
  11. package/dist/fonts/material-symbols-rounded.woff2 +0 -0
  12. package/dist/fonts/material-symbols-sharp.woff2 +0 -0
  13. package/dist/fonts/noto-sans-arabic-arabic-400.woff2 +0 -0
  14. package/dist/fonts/noto-sans-arabic-arabic-500.woff2 +0 -0
  15. package/dist/fonts/noto-sans-arabic-arabic-700.woff2 +0 -0
  16. package/dist/fonts/noto-sans-cyrillic-400.woff2 +0 -0
  17. package/dist/fonts/noto-sans-cyrillic-500.woff2 +0 -0
  18. package/dist/fonts/noto-sans-cyrillic-700.woff2 +0 -0
  19. package/dist/fonts/noto-sans-cyrillic-ext-400.woff2 +0 -0
  20. package/dist/fonts/noto-sans-cyrillic-ext-500.woff2 +0 -0
  21. package/dist/fonts/noto-sans-cyrillic-ext-700.woff2 +0 -0
  22. package/dist/fonts/noto-sans-devanagari-400.woff2 +0 -0
  23. package/dist/fonts/noto-sans-devanagari-500.woff2 +0 -0
  24. package/dist/fonts/noto-sans-devanagari-700.woff2 +0 -0
  25. package/dist/fonts/noto-sans-greek-400.woff2 +0 -0
  26. package/dist/fonts/noto-sans-greek-500.woff2 +0 -0
  27. package/dist/fonts/noto-sans-greek-700.woff2 +0 -0
  28. package/dist/fonts/noto-sans-greek-ext-400.woff2 +0 -0
  29. package/dist/fonts/noto-sans-greek-ext-500.woff2 +0 -0
  30. package/dist/fonts/noto-sans-greek-ext-700.woff2 +0 -0
  31. package/dist/fonts/noto-sans-hebrew-hebrew-400.woff2 +0 -0
  32. package/dist/fonts/noto-sans-hebrew-hebrew-500.woff2 +0 -0
  33. package/dist/fonts/noto-sans-hebrew-hebrew-700.woff2 +0 -0
  34. package/dist/fonts/noto-sans-latin-700.woff2 +0 -0
  35. package/dist/fonts/noto-sans-latin-ext-400.woff2 +0 -0
  36. package/dist/fonts/noto-sans-latin-ext-500.woff2 +0 -0
  37. package/dist/fonts/noto-sans-latin-ext-700.woff2 +0 -0
  38. package/dist/fonts/noto-sans-thai-thai-400.woff2 +0 -0
  39. package/dist/fonts/noto-sans-thai-thai-500.woff2 +0 -0
  40. package/dist/fonts/noto-sans-thai-thai-700.woff2 +0 -0
  41. package/dist/fonts/noto-sans-vietnamese-400.woff2 +0 -0
  42. package/dist/fonts/noto-sans-vietnamese-500.woff2 +0 -0
  43. package/dist/fonts/noto-sans-vietnamese-700.woff2 +0 -0
  44. package/dist/fonts/roboto-cyrillic-400.woff2 +0 -0
  45. package/dist/fonts/roboto-cyrillic-500.woff2 +0 -0
  46. package/dist/fonts/roboto-cyrillic-700.woff2 +0 -0
  47. package/dist/fonts/roboto-cyrillic-ext-400.woff2 +0 -0
  48. package/dist/fonts/roboto-cyrillic-ext-500.woff2 +0 -0
  49. package/dist/fonts/roboto-cyrillic-ext-700.woff2 +0 -0
  50. package/dist/fonts/roboto-greek-400.woff2 +0 -0
  51. package/dist/fonts/roboto-greek-500.woff2 +0 -0
  52. package/dist/fonts/roboto-greek-700.woff2 +0 -0
  53. package/dist/fonts/roboto-greek-ext-400.woff2 +0 -0
  54. package/dist/fonts/roboto-greek-ext-500.woff2 +0 -0
  55. package/dist/fonts/roboto-greek-ext-700.woff2 +0 -0
  56. package/dist/fonts/roboto-latin-700.woff2 +0 -0
  57. package/dist/fonts/roboto-latin-ext-400.woff2 +0 -0
  58. package/dist/fonts/roboto-latin-ext-500.woff2 +0 -0
  59. package/dist/fonts/roboto-latin-ext-700.woff2 +0 -0
  60. package/dist/fonts/roboto-vietnamese-400.woff2 +0 -0
  61. package/dist/fonts/roboto-vietnamese-500.woff2 +0 -0
  62. package/dist/fonts/roboto-vietnamese-700.woff2 +0 -0
  63. package/dist/js/chunks/chunk-26VUH75M.mjs +102 -0
  64. package/dist/js/chunks/chunk-26VUH75M.mjs.map +7 -0
  65. package/dist/js/chunks/chunk-2LFCOGC3.mjs +233 -0
  66. package/dist/js/chunks/chunk-2LFCOGC3.mjs.map +7 -0
  67. package/dist/js/chunks/{chunk-DXGRXYYL.mjs → chunk-36GELQGX.mjs} +29 -46
  68. package/dist/js/chunks/chunk-36GELQGX.mjs.map +7 -0
  69. package/dist/js/chunks/{chunk-74MXKKLN.mjs → chunk-3FKWIRHW.mjs} +15 -29
  70. package/dist/js/chunks/chunk-3FKWIRHW.mjs.map +7 -0
  71. package/dist/js/chunks/chunk-3KF65KGL.mjs +209 -0
  72. package/dist/js/chunks/chunk-3KF65KGL.mjs.map +7 -0
  73. package/dist/js/chunks/{chunk-KVJAVDBC.mjs → chunk-3KLZRQZI.mjs} +88 -116
  74. package/dist/js/chunks/chunk-3KLZRQZI.mjs.map +7 -0
  75. package/dist/js/chunks/{chunk-CK2XCICY.mjs → chunk-3XORNED5.mjs} +3 -11
  76. package/dist/js/chunks/chunk-3XORNED5.mjs.map +7 -0
  77. package/dist/js/chunks/chunk-4WBGAQN3.mjs +113 -0
  78. package/dist/js/chunks/chunk-4WBGAQN3.mjs.map +7 -0
  79. package/dist/js/chunks/{chunk-FM5CZOUB.mjs → chunk-5F4URJHL.mjs} +19 -30
  80. package/dist/js/chunks/chunk-5F4URJHL.mjs.map +7 -0
  81. package/dist/js/chunks/chunk-67UNY7RH.mjs +299 -0
  82. package/dist/js/chunks/chunk-67UNY7RH.mjs.map +7 -0
  83. package/dist/js/chunks/chunk-7CXNATJS.mjs +97 -0
  84. package/dist/js/chunks/chunk-7CXNATJS.mjs.map +7 -0
  85. package/dist/js/chunks/{chunk-UETTGDLI.mjs → chunk-7X44MKEQ.mjs} +43 -48
  86. package/dist/js/chunks/chunk-7X44MKEQ.mjs.map +7 -0
  87. package/dist/js/chunks/chunk-7ZAMOMGY.mjs +440 -0
  88. package/dist/js/chunks/chunk-7ZAMOMGY.mjs.map +7 -0
  89. package/dist/js/chunks/chunk-AEG6LOAJ.mjs +54 -0
  90. package/dist/js/chunks/chunk-AEG6LOAJ.mjs.map +7 -0
  91. package/dist/js/chunks/chunk-AQNFCJJ5.mjs +135 -0
  92. package/dist/js/chunks/chunk-AQNFCJJ5.mjs.map +7 -0
  93. package/dist/js/chunks/chunk-B55LWKBM.mjs +75 -0
  94. package/dist/js/chunks/chunk-B55LWKBM.mjs.map +7 -0
  95. package/dist/js/chunks/chunk-BB5VXYXT.mjs +28 -0
  96. package/dist/js/chunks/chunk-BB5VXYXT.mjs.map +7 -0
  97. package/dist/js/chunks/chunk-BDATLH3H.mjs +108 -0
  98. package/dist/js/chunks/chunk-BDATLH3H.mjs.map +7 -0
  99. package/dist/js/chunks/chunk-CWMQOT4O.mjs +232 -0
  100. package/dist/js/chunks/chunk-CWMQOT4O.mjs.map +7 -0
  101. package/dist/js/chunks/chunk-CY2CTOVM.mjs +81 -0
  102. package/dist/js/chunks/chunk-CY2CTOVM.mjs.map +7 -0
  103. package/dist/js/chunks/{chunk-NUHMOAOY.mjs → chunk-DWA5UYLJ.mjs} +363 -218
  104. package/dist/js/chunks/chunk-DWA5UYLJ.mjs.map +7 -0
  105. package/dist/js/chunks/chunk-EB2V4OKL.mjs +79 -0
  106. package/dist/js/chunks/chunk-EB2V4OKL.mjs.map +7 -0
  107. package/dist/js/chunks/chunk-EWO662ZC.mjs +188 -0
  108. package/dist/js/chunks/chunk-EWO662ZC.mjs.map +7 -0
  109. package/dist/js/chunks/{chunk-ZX6M7SWO.mjs → chunk-F7LAKFMX.mjs} +320 -141
  110. package/dist/js/chunks/chunk-F7LAKFMX.mjs.map +7 -0
  111. package/dist/js/chunks/{chunk-L27Q6ZMI.mjs → chunk-FNIIH2LU.mjs} +20 -33
  112. package/dist/js/chunks/chunk-FNIIH2LU.mjs.map +7 -0
  113. package/dist/js/chunks/chunk-GE3YMFS6.mjs +15 -0
  114. package/dist/js/chunks/chunk-GE3YMFS6.mjs.map +7 -0
  115. package/dist/js/chunks/chunk-GFWYMWYN.mjs +125 -0
  116. package/dist/js/chunks/chunk-GFWYMWYN.mjs.map +7 -0
  117. package/dist/js/chunks/chunk-GNRSYMVH.mjs +1 -0
  118. package/dist/js/chunks/chunk-H5ISU45X.mjs +87 -0
  119. package/dist/js/chunks/chunk-H5ISU45X.mjs.map +7 -0
  120. package/dist/js/chunks/{chunk-GJL6GCIU.mjs → chunk-H6YIKFAQ.mjs} +311 -186
  121. package/dist/js/chunks/chunk-H6YIKFAQ.mjs.map +7 -0
  122. package/dist/js/chunks/{chunk-BGZLF6JZ.mjs → chunk-HEH7E3KO.mjs} +155 -35
  123. package/dist/js/chunks/chunk-HEH7E3KO.mjs.map +7 -0
  124. package/dist/js/chunks/chunk-HQRLBTNM.mjs +152 -0
  125. package/dist/js/chunks/chunk-HQRLBTNM.mjs.map +7 -0
  126. package/dist/js/chunks/chunk-I2F7MLUU.mjs +137 -0
  127. package/dist/js/chunks/chunk-I2F7MLUU.mjs.map +7 -0
  128. package/dist/js/chunks/chunk-IQOTGGHX.mjs +797 -0
  129. package/dist/js/chunks/chunk-IQOTGGHX.mjs.map +7 -0
  130. package/dist/js/chunks/chunk-JH3YWKA6.mjs +225 -0
  131. package/dist/js/chunks/chunk-JH3YWKA6.mjs.map +7 -0
  132. package/dist/js/chunks/chunk-JOLJAYIJ.mjs +7 -0
  133. package/dist/js/chunks/chunk-JOLJAYIJ.mjs.map +7 -0
  134. package/dist/js/chunks/{chunk-VGNYF6FB.mjs → chunk-KOTGMCMI.mjs} +116 -24
  135. package/dist/js/chunks/chunk-KOTGMCMI.mjs.map +7 -0
  136. package/dist/js/chunks/{chunk-LQWUDNHZ.mjs → chunk-LC4O5LFS.mjs} +21 -45
  137. package/dist/js/chunks/chunk-LC4O5LFS.mjs.map +7 -0
  138. package/dist/js/chunks/chunk-LEF33SCP.mjs +127 -0
  139. package/dist/js/chunks/chunk-LEF33SCP.mjs.map +7 -0
  140. package/dist/js/chunks/{chunk-PDG64UHF.mjs → chunk-LFORZRPH.mjs} +21 -23
  141. package/dist/js/chunks/chunk-LFORZRPH.mjs.map +7 -0
  142. package/dist/js/chunks/chunk-LWLNV5EC.mjs +451 -0
  143. package/dist/js/chunks/chunk-LWLNV5EC.mjs.map +7 -0
  144. package/dist/js/chunks/chunk-LXRHUQAX.mjs +491 -0
  145. package/dist/js/chunks/chunk-LXRHUQAX.mjs.map +7 -0
  146. package/dist/js/chunks/{chunk-SFI2U4YW.mjs → chunk-MA2SZZFB.mjs} +82 -111
  147. package/dist/js/chunks/chunk-MA2SZZFB.mjs.map +7 -0
  148. package/dist/js/chunks/chunk-MDBZAMIV.mjs +121 -0
  149. package/dist/js/chunks/chunk-MDBZAMIV.mjs.map +7 -0
  150. package/dist/js/chunks/chunk-NODZ5VAD.mjs +75 -0
  151. package/dist/js/chunks/chunk-NODZ5VAD.mjs.map +7 -0
  152. package/dist/js/chunks/chunk-O2WJB6TH.mjs +365 -0
  153. package/dist/js/chunks/chunk-O2WJB6TH.mjs.map +7 -0
  154. package/dist/js/chunks/chunk-PCABY5BN.mjs +35 -0
  155. package/dist/js/chunks/chunk-PCABY5BN.mjs.map +7 -0
  156. package/dist/js/chunks/chunk-PWKYVMND.mjs +120 -0
  157. package/dist/js/chunks/chunk-PWKYVMND.mjs.map +7 -0
  158. package/dist/js/chunks/{chunk-SMY7GJSS.mjs → chunk-QHZZT7YO.mjs} +66 -38
  159. package/dist/js/chunks/chunk-QHZZT7YO.mjs.map +7 -0
  160. package/dist/js/chunks/chunk-QND56EW2.mjs +439 -0
  161. package/dist/js/chunks/chunk-QND56EW2.mjs.map +7 -0
  162. package/dist/js/chunks/chunk-QNODAANY.mjs +376 -0
  163. package/dist/js/chunks/chunk-QNODAANY.mjs.map +7 -0
  164. package/dist/js/chunks/{chunk-KHXZ2A4K.mjs → chunk-QRO5FV3I.mjs} +156 -73
  165. package/dist/js/chunks/chunk-QRO5FV3I.mjs.map +7 -0
  166. package/dist/js/chunks/chunk-R7A7JRC5.mjs +440 -0
  167. package/dist/js/chunks/chunk-R7A7JRC5.mjs.map +7 -0
  168. package/dist/js/chunks/chunk-RKG2CBFE.mjs +74 -0
  169. package/dist/js/chunks/chunk-RKG2CBFE.mjs.map +7 -0
  170. package/dist/js/chunks/{chunk-XAEAEHIX.mjs → chunk-RSNS5OYS.mjs} +38 -25
  171. package/dist/js/chunks/chunk-RSNS5OYS.mjs.map +7 -0
  172. package/dist/js/chunks/{chunk-X4ISMKE2.mjs → chunk-RUDYMEJ3.mjs} +7 -6
  173. package/dist/js/chunks/chunk-RUDYMEJ3.mjs.map +7 -0
  174. package/dist/js/chunks/chunk-STJR62SU.mjs +161 -0
  175. package/dist/js/chunks/chunk-STJR62SU.mjs.map +7 -0
  176. package/dist/js/chunks/chunk-SUSD4UTN.mjs +220 -0
  177. package/dist/js/chunks/chunk-SUSD4UTN.mjs.map +7 -0
  178. package/dist/js/chunks/{chunk-5CEAOLUA.mjs → chunk-SYBOA5HC.mjs} +26 -48
  179. package/dist/js/chunks/chunk-SYBOA5HC.mjs.map +7 -0
  180. package/dist/js/chunks/chunk-T4MOBP3J.mjs +108 -0
  181. package/dist/js/chunks/chunk-T4MOBP3J.mjs.map +7 -0
  182. package/dist/js/chunks/chunk-TM7HPGTV.mjs +342 -0
  183. package/dist/js/chunks/chunk-TM7HPGTV.mjs.map +7 -0
  184. package/dist/js/chunks/{chunk-C6CHEWYP.mjs → chunk-TMQDZSDC.mjs} +71 -35
  185. package/dist/js/chunks/chunk-TMQDZSDC.mjs.map +7 -0
  186. package/dist/js/chunks/chunk-TVSX5YA2.mjs +48 -0
  187. package/dist/js/chunks/chunk-TVSX5YA2.mjs.map +7 -0
  188. package/dist/js/chunks/chunk-UHO5CV6K.mjs +80 -0
  189. package/dist/js/chunks/chunk-UHO5CV6K.mjs.map +7 -0
  190. package/dist/js/chunks/chunk-UKCNELUN.mjs +223 -0
  191. package/dist/js/chunks/chunk-UKCNELUN.mjs.map +7 -0
  192. package/dist/js/chunks/chunk-UKQK5GWR.mjs +167 -0
  193. package/dist/js/chunks/chunk-UKQK5GWR.mjs.map +7 -0
  194. package/dist/js/chunks/{chunk-TSZYSW7F.mjs → chunk-UTSLYQ65.mjs} +21 -48
  195. package/dist/js/chunks/chunk-UTSLYQ65.mjs.map +7 -0
  196. package/dist/js/chunks/chunk-VS5OJBOD.mjs +108 -0
  197. package/dist/js/chunks/chunk-VS5OJBOD.mjs.map +7 -0
  198. package/dist/js/chunks/chunk-VZMROW5A.mjs +759 -0
  199. package/dist/js/chunks/chunk-VZMROW5A.mjs.map +7 -0
  200. package/dist/js/chunks/chunk-W6FAL3TI.mjs +38 -0
  201. package/dist/js/chunks/chunk-W6FAL3TI.mjs.map +7 -0
  202. package/dist/js/chunks/chunk-XB6Y7P5W.mjs +69 -0
  203. package/dist/js/chunks/chunk-XB6Y7P5W.mjs.map +7 -0
  204. package/dist/js/chunks/chunk-XDAMOMVD.mjs +226 -0
  205. package/dist/js/chunks/chunk-XDAMOMVD.mjs.map +7 -0
  206. package/dist/js/chunks/{chunk-WDK4T63U.mjs → chunk-XJPMW5SP.mjs} +247 -172
  207. package/dist/js/chunks/chunk-XJPMW5SP.mjs.map +7 -0
  208. package/dist/js/chunks/{chunk-KUFHW3DS.mjs → chunk-YKANQILZ.mjs} +16 -21
  209. package/dist/js/chunks/chunk-YKANQILZ.mjs.map +7 -0
  210. package/dist/js/chunks/chunk-YLZOJLDI.mjs +175 -0
  211. package/dist/js/chunks/chunk-YLZOJLDI.mjs.map +7 -0
  212. package/dist/js/chunks/chunk-ZK7YY322.mjs +514 -0
  213. package/dist/js/chunks/chunk-ZK7YY322.mjs.map +7 -0
  214. package/dist/js/expressive.cjs +10266 -3628
  215. package/dist/js/expressive.cjs.map +4 -4
  216. package/dist/js/expressive.js +10266 -3628
  217. package/dist/js/expressive.js.map +4 -4
  218. package/dist/js/expressive.min.js +23 -22
  219. package/dist/js/expressive.min.js.map +4 -4
  220. package/dist/js/expressive.mjs +181 -69
  221. package/dist/js/expressive.mjs.map +2 -2
  222. package/dist/js/internal/behaviors/bottomSheets.mjs +4 -3
  223. package/dist/js/internal/behaviors/copy.mjs +9 -0
  224. package/dist/js/internal/behaviors/copy.mjs.map +7 -0
  225. package/dist/js/internal/behaviors/dataTables.mjs +8 -0
  226. package/dist/js/internal/behaviors/dataTables.mjs.map +7 -0
  227. package/dist/js/internal/behaviors/dialogs.mjs +2 -2
  228. package/dist/js/internal/behaviors/forms.mjs +2 -2
  229. package/dist/js/internal/behaviors/imageCompare.mjs +8 -0
  230. package/dist/js/internal/behaviors/imageCompare.mjs.map +7 -0
  231. package/dist/js/internal/behaviors/lists.mjs +8 -0
  232. package/dist/js/internal/behaviors/lists.mjs.map +7 -0
  233. package/dist/js/internal/behaviors/paneResize.mjs +8 -0
  234. package/dist/js/internal/behaviors/paneResize.mjs.map +7 -0
  235. package/dist/js/internal/behaviors/sheetDrag.mjs +7 -2
  236. package/dist/js/internal/behaviors/sideSheets.mjs +4 -3
  237. package/dist/js/internal/behaviors/sortable.mjs +8 -0
  238. package/dist/js/internal/behaviors/sortable.mjs.map +7 -0
  239. package/dist/js/internal/behaviors/theme.mjs +8 -0
  240. package/dist/js/internal/behaviors/theme.mjs.map +7 -0
  241. package/dist/js/internal/behaviors/tour.mjs +8 -0
  242. package/dist/js/internal/behaviors/tour.mjs.map +7 -0
  243. package/dist/js/internal/behaviors/transferList.mjs +8 -0
  244. package/dist/js/internal/behaviors/transferList.mjs.map +7 -0
  245. package/dist/js/internal/components/appBar.mjs +3 -2
  246. package/dist/js/internal/components/autocomplete.mjs +5 -4
  247. package/dist/js/internal/components/backToTop.mjs +9 -0
  248. package/dist/js/internal/components/backToTop.mjs.map +7 -0
  249. package/dist/js/internal/components/barChart.mjs +5 -4
  250. package/dist/js/internal/components/buttonGroup.mjs +3 -2
  251. package/dist/js/internal/components/buttons.mjs +3 -3
  252. package/dist/js/internal/components/cards.mjs +3 -3
  253. package/dist/js/internal/components/carousel.mjs +3 -3
  254. package/dist/js/internal/components/cascader.mjs +10 -0
  255. package/dist/js/internal/components/cascader.mjs.map +7 -0
  256. package/dist/js/internal/components/characterCounter.mjs +3 -2
  257. package/dist/js/internal/components/chips.mjs +7 -5
  258. package/dist/js/internal/components/colorPicker.mjs +9 -0
  259. package/dist/js/internal/components/colorPicker.mjs.map +7 -0
  260. package/dist/js/internal/components/columnChart.mjs +4 -3
  261. package/dist/js/internal/components/commandPalette.mjs +3 -3
  262. package/dist/js/internal/components/confetti.mjs +3 -2
  263. package/dist/js/internal/components/currencyInput.mjs +9 -0
  264. package/dist/js/internal/components/currencyInput.mjs.map +7 -0
  265. package/dist/js/internal/components/datepicker.mjs +12 -8
  266. package/dist/js/internal/components/expandingCard.mjs +3 -3
  267. package/dist/js/internal/components/funnelChart.mjs +10 -0
  268. package/dist/js/internal/components/funnelChart.mjs.map +7 -0
  269. package/dist/js/internal/components/heatmapChart.mjs +4 -3
  270. package/dist/js/internal/components/hoverCard.mjs +9 -0
  271. package/dist/js/internal/components/hoverCard.mjs.map +7 -0
  272. package/dist/js/internal/components/index.mjs +131 -65
  273. package/dist/js/internal/components/inputMask.mjs +9 -0
  274. package/dist/js/internal/components/inputMask.mjs.map +7 -0
  275. package/dist/js/internal/components/keypad.mjs +3 -3
  276. package/dist/js/internal/components/lightbox.mjs +3 -3
  277. package/dist/js/internal/components/lineChart.mjs +41 -4
  278. package/dist/js/internal/components/loadingOverlay.mjs +9 -0
  279. package/dist/js/internal/components/loadingOverlay.mjs.map +7 -0
  280. package/dist/js/internal/components/mapView.mjs +3 -3
  281. package/dist/js/internal/components/menu.mjs +3 -3
  282. package/dist/js/internal/components/menubar.mjs +10 -0
  283. package/dist/js/internal/components/menubar.mjs.map +7 -0
  284. package/dist/js/internal/components/messageScroller.mjs +3 -3
  285. package/dist/js/internal/components/mixedChart.mjs +5 -4
  286. package/dist/js/internal/components/navigationRail.mjs +3 -2
  287. package/dist/js/internal/components/particles.mjs +3 -2
  288. package/dist/js/internal/components/pieChart.mjs +4 -3
  289. package/dist/js/internal/components/pullToRefresh.mjs +9 -0
  290. package/dist/js/internal/components/pullToRefresh.mjs.map +7 -0
  291. package/dist/js/internal/components/questionnaire.mjs +3 -3
  292. package/dist/js/internal/components/radarChart.mjs +4 -3
  293. package/dist/js/internal/components/radialChart.mjs +4 -3
  294. package/dist/js/internal/components/registry.mjs +60 -41
  295. package/dist/js/internal/components/richTextEditor.mjs +3 -3
  296. package/dist/js/internal/components/sankeyChart.mjs +10 -0
  297. package/dist/js/internal/components/sankeyChart.mjs.map +7 -0
  298. package/dist/js/internal/components/scatterChart.mjs +10 -0
  299. package/dist/js/internal/components/scatterChart.mjs.map +7 -0
  300. package/dist/js/internal/components/scrollspy.mjs +3 -2
  301. package/dist/js/internal/components/select.mjs +5 -4
  302. package/dist/js/internal/components/showMore.mjs +9 -0
  303. package/dist/js/internal/components/showMore.mjs.map +7 -0
  304. package/dist/js/internal/components/slider.mjs +3 -3
  305. package/dist/js/internal/components/snackbar.mjs +2 -2
  306. package/dist/js/internal/components/swipeActions.mjs +9 -0
  307. package/dist/js/internal/components/swipeActions.mjs.map +7 -0
  308. package/dist/js/internal/components/tabs.mjs +3 -4
  309. package/dist/js/internal/components/timepicker.mjs +5 -4
  310. package/dist/js/internal/components/tooltip.mjs +3 -3
  311. package/dist/js/internal/components/treeSelect.mjs +14 -0
  312. package/dist/js/internal/components/treeSelect.mjs.map +7 -0
  313. package/dist/js/internal/components/treemapChart.mjs +10 -0
  314. package/dist/js/internal/components/treemapChart.mjs.map +7 -0
  315. package/dist/js/internal/core/component.mjs +6 -3
  316. package/dist/js/internal/core/formControl.mjs +12 -0
  317. package/dist/js/internal/core/formControl.mjs.map +7 -0
  318. package/dist/js/internal/core/imageURL.mjs +7 -0
  319. package/dist/js/internal/core/imageURL.mjs.map +7 -0
  320. package/dist/js/internal/core/spring.mjs +11 -0
  321. package/dist/js/internal/core/spring.mjs.map +7 -0
  322. package/dist/js/internal/core/utils.mjs +21 -3
  323. package/dist/js/internal/plugins/dockedDisplayPlugin.mjs +2 -2
  324. package/dist/js/internal/plugins/modalDisplayPlugin.mjs +13 -0
  325. package/dist/js/internal/plugins/modalDisplayPlugin.mjs.map +7 -0
  326. package/dist/js/modular.mjs +172 -69
  327. package/dist/types/behaviors/bottomSheets.d.ts +23 -5
  328. package/dist/types/behaviors/copy.d.ts +18 -0
  329. package/dist/types/behaviors/dataTables.d.ts +125 -0
  330. package/dist/types/behaviors/dialogs.d.ts +27 -1
  331. package/dist/types/behaviors/forms.d.ts +70 -4
  332. package/dist/types/behaviors/imageCompare.d.ts +13 -0
  333. package/dist/types/behaviors/lists.d.ts +12 -0
  334. package/dist/types/behaviors/paneResize.d.ts +29 -0
  335. package/dist/types/behaviors/sheetDrag.d.ts +18 -0
  336. package/dist/types/behaviors/sideSheets.d.ts +1 -1
  337. package/dist/types/behaviors/sortable.d.ts +28 -0
  338. package/dist/types/behaviors/theme.d.ts +22 -0
  339. package/dist/types/behaviors/tour.d.ts +36 -0
  340. package/dist/types/behaviors/transferList.d.ts +53 -0
  341. package/dist/types/components/appBar.d.ts +5 -6
  342. package/dist/types/components/autocomplete.d.ts +105 -20
  343. package/dist/types/components/backToTop.d.ts +36 -0
  344. package/dist/types/components/barChart.d.ts +3 -6
  345. package/dist/types/components/buttonGroup.d.ts +2 -4
  346. package/dist/types/components/buttons.d.ts +5 -5
  347. package/dist/types/components/cards.d.ts +3 -16
  348. package/dist/types/components/carousel.d.ts +16 -15
  349. package/dist/types/components/cascader.d.ts +130 -0
  350. package/dist/types/components/characterCounter.d.ts +2 -15
  351. package/dist/types/components/chips.d.ts +80 -19
  352. package/dist/types/components/colorPicker.d.ts +56 -0
  353. package/dist/types/components/columnChart.d.ts +23 -10
  354. package/dist/types/components/commandPalette.d.ts +11 -16
  355. package/dist/types/components/confetti.d.ts +2 -4
  356. package/dist/types/components/currencyInput.d.ts +60 -0
  357. package/dist/types/components/datepicker.d.ts +107 -56
  358. package/dist/types/components/expandingCard.d.ts +4 -6
  359. package/dist/types/components/funnelChart.d.ts +35 -0
  360. package/dist/types/components/heatmapChart.d.ts +42 -8
  361. package/dist/types/components/hoverCard.d.ts +59 -0
  362. package/dist/types/components/index.d.ts +16 -1
  363. package/dist/types/components/inputMask.d.ts +28 -0
  364. package/dist/types/components/keypad.d.ts +38 -6
  365. package/dist/types/components/lightbox.d.ts +14 -20
  366. package/dist/types/components/lineChart.d.ts +212 -12
  367. package/dist/types/components/loadingOverlay.d.ts +42 -0
  368. package/dist/types/components/mapView.d.ts +138 -27
  369. package/dist/types/components/menu.d.ts +74 -22
  370. package/dist/types/components/menubar.d.ts +37 -0
  371. package/dist/types/components/messageScroller.d.ts +2 -14
  372. package/dist/types/components/mixedChart.d.ts +15 -6
  373. package/dist/types/components/navigationRail.d.ts +16 -5
  374. package/dist/types/components/particles.d.ts +22 -5
  375. package/dist/types/components/pieChart.d.ts +33 -9
  376. package/dist/types/components/pullToRefresh.d.ts +80 -0
  377. package/dist/types/components/questionnaire.d.ts +58 -16
  378. package/dist/types/components/radarChart.d.ts +10 -6
  379. package/dist/types/components/radialChart.d.ts +58 -7
  380. package/dist/types/components/registry.d.ts +73 -3
  381. package/dist/types/components/richTextEditor.d.ts +45 -22
  382. package/dist/types/components/sankeyChart.d.ts +72 -0
  383. package/dist/types/components/scatterChart.d.ts +102 -0
  384. package/dist/types/components/scrollspy.d.ts +3 -5
  385. package/dist/types/components/select.d.ts +44 -33
  386. package/dist/types/components/showMore.d.ts +53 -0
  387. package/dist/types/components/slider.d.ts +2 -15
  388. package/dist/types/components/snackbar.d.ts +68 -1
  389. package/dist/types/components/swipeActions.d.ts +81 -0
  390. package/dist/types/components/tabs.d.ts +92 -30
  391. package/dist/types/components/timepicker.d.ts +128 -27
  392. package/dist/types/components/tooltip.d.ts +57 -21
  393. package/dist/types/components/treeSelect.d.ts +106 -0
  394. package/dist/types/components/treemapChart.d.ts +56 -0
  395. package/dist/types/core/component.d.ts +49 -25
  396. package/dist/types/core/formControl.d.ts +21 -0
  397. package/dist/types/core/imageURL.d.ts +2 -0
  398. package/dist/types/core/spring.d.ts +20 -0
  399. package/dist/types/core/utils.d.ts +123 -72
  400. package/dist/types/modular.d.ts +33 -1
  401. package/dist/types/plugins/dockedDisplayPlugin.d.ts +10 -8
  402. package/dist/types/plugins/modalDisplayPlugin.d.ts +39 -0
  403. package/package.json +17 -13
  404. package/src/sass/README.md +27 -18
  405. package/src/sass/abstracts/_elevation.scss +13 -7
  406. package/src/sass/abstracts/_index.scss +1 -0
  407. package/src/sass/abstracts/_mixins.scss +864 -78
  408. package/src/sass/abstracts/_spring.scss +63 -0
  409. package/src/sass/abstracts/_variables.scss +64 -21
  410. package/src/sass/base/_fonts.scss +61 -48
  411. package/src/sass/base/_global.scss +104 -24
  412. package/src/sass/base/_index.scss +2 -0
  413. package/src/sass/base/_normalize.scss +59 -114
  414. package/src/sass/base/_print.scss +21 -0
  415. package/src/sass/base/_prose.scss +68 -0
  416. package/src/sass/base/_typography.scss +9 -5
  417. package/src/sass/components/_accordion.scss +10 -19
  418. package/src/sass/components/_alert.scss +102 -0
  419. package/src/sass/components/_aura.scss +9 -3
  420. package/src/sass/components/_avatar.scss +3 -3
  421. package/src/sass/components/_back-to-top.scss +38 -0
  422. package/src/sass/components/_badges.scss +6 -5
  423. package/src/sass/components/_bar-chart.scss +31 -90
  424. package/src/sass/components/_bottom-sheet.scss +51 -16
  425. package/src/sass/components/_breadcrumb.scss +8 -7
  426. package/src/sass/components/_button-groups.scss +30 -63
  427. package/src/sass/components/_buttons.scss +137 -94
  428. package/src/sass/components/_calendar.scss +244 -0
  429. package/src/sass/components/_cards.scss +36 -44
  430. package/src/sass/components/_carousel.scss +37 -113
  431. package/src/sass/components/_cascader.scss +131 -0
  432. package/src/sass/components/_chips.scss +36 -46
  433. package/src/sass/components/_column-chart.scss +15 -26
  434. package/src/sass/components/_command-palette.scss +4 -7
  435. package/src/sass/components/_confetti.scss +1 -4
  436. package/src/sass/components/_countdown.scss +1 -1
  437. package/src/sass/components/_data-table.scss +172 -25
  438. package/src/sass/components/_datepicker.scss +54 -40
  439. package/src/sass/components/_description-list.scss +85 -0
  440. package/src/sass/components/_dialog.scss +48 -55
  441. package/src/sass/components/_docked-display.scss +1 -3
  442. package/src/sass/components/_drag-handle.scss +16 -20
  443. package/src/sass/components/_expanding-card.scss +21 -14
  444. package/src/sass/components/_fab-menu.scss +43 -39
  445. package/src/sass/components/_funnel-chart.scss +63 -0
  446. package/src/sass/components/_heatmap-chart.scss +114 -29
  447. package/src/sass/components/_icon-buttons.scss +8 -11
  448. package/src/sass/components/_icons-material-design.scss +2 -2
  449. package/src/sass/components/_image-compare.scss +108 -0
  450. package/src/sass/components/_index.scss +20 -0
  451. package/src/sass/components/_keypad.scss +39 -19
  452. package/src/sass/components/_kpi.scss +6 -11
  453. package/src/sass/components/_lightbox.scss +24 -13
  454. package/src/sass/components/_line-chart.scss +9 -63
  455. package/src/sass/components/_list.scss +59 -14
  456. package/src/sass/components/_loading-indicator.scss +1 -0
  457. package/src/sass/components/_loading-overlay.scss +105 -0
  458. package/src/sass/components/_map.scss +37 -11
  459. package/src/sass/components/_marquee.scss +4 -3
  460. package/src/sass/components/_mega-menu.scss +128 -0
  461. package/src/sass/components/_menu.scss +146 -127
  462. package/src/sass/components/_menubar.scss +47 -0
  463. package/src/sass/components/_message-scroller.scss +2 -2
  464. package/src/sass/components/_message.scss +3 -3
  465. package/src/sass/components/_mixed-chart.scss +27 -35
  466. package/src/sass/components/_modal-display.scss +21 -0
  467. package/src/sass/components/_navbar.scss +45 -36
  468. package/src/sass/components/_navigation-bar.scss +12 -77
  469. package/src/sass/components/_navigation-rail.scss +161 -92
  470. package/src/sass/components/_org-chart.scss +192 -0
  471. package/src/sass/components/_page-footer.scss +2 -4
  472. package/src/sass/components/_pagination.scss +9 -27
  473. package/src/sass/components/_panes.scss +35 -42
  474. package/src/sass/components/_particles.scss +1 -4
  475. package/src/sass/components/_pie-chart.scss +86 -68
  476. package/src/sass/components/_popover.scss +18 -5
  477. package/src/sass/components/_progress.scss +183 -44
  478. package/src/sass/components/_pull-to-refresh.scss +90 -0
  479. package/src/sass/components/_questionnaire.scss +74 -3
  480. package/src/sass/components/_radar-chart.scss +40 -42
  481. package/src/sass/components/_radial-chart.scss +108 -46
  482. package/src/sass/components/_rich-text-editor.scss +2 -2
  483. package/src/sass/components/_sankey-chart.scss +91 -0
  484. package/src/sass/components/_scatter-chart.scss +144 -0
  485. package/src/sass/components/_scrim.scss +0 -2
  486. package/src/sass/components/_scrollspy.scss +0 -2
  487. package/src/sass/components/_search.scss +27 -26
  488. package/src/sass/components/_show-more.scss +8 -0
  489. package/src/sass/components/_side-sheet.scss +32 -51
  490. package/src/sass/components/_skeleton.scss +26 -19
  491. package/src/sass/components/_snackbar.scss +25 -21
  492. package/src/sass/components/_split-button.scss +5 -5
  493. package/src/sass/components/_stat.scss +3 -8
  494. package/src/sass/components/_stepper.scss +1 -1
  495. package/src/sass/components/_swipe-actions.scss +71 -0
  496. package/src/sass/components/_table_of_contents.scss +1 -3
  497. package/src/sass/components/_tabs.scss +49 -46
  498. package/src/sass/components/_timeline.scss +12 -12
  499. package/src/sass/components/_timepicker.scss +111 -79
  500. package/src/sass/components/_toolbar.scss +36 -47
  501. package/src/sass/components/_tooltip.scss +25 -12
  502. package/src/sass/components/_tour.scss +89 -0
  503. package/src/sass/components/_transfer-list.scss +73 -0
  504. package/src/sass/components/_transitions.scss +4 -4
  505. package/src/sass/components/_tree.scss +7 -32
  506. package/src/sass/components/_treemap-chart.scss +98 -0
  507. package/src/sass/components/forms/_checkboxes.scss +107 -44
  508. package/src/sass/components/forms/_color-picker.scss +135 -0
  509. package/src/sass/components/forms/_color-swatches.scss +85 -0
  510. package/src/sass/components/forms/_drop-zone.scss +16 -13
  511. package/src/sass/components/forms/_fieldset.scss +4 -7
  512. package/src/sass/components/forms/_file-input.scss +12 -8
  513. package/src/sass/components/forms/_index.scss +3 -1
  514. package/src/sass/components/forms/_input-fields.scss +271 -90
  515. package/src/sass/components/forms/_radio-buttons.scss +34 -117
  516. package/src/sass/components/forms/_rating.scss +2 -32
  517. package/src/sass/components/forms/_select.scss +198 -20
  518. package/src/sass/components/forms/_slider.scss +92 -98
  519. package/src/sass/components/forms/_switches.scss +62 -180
  520. package/src/sass/custom.scss +10 -1
  521. package/src/sass/expressive.scss +3 -63
  522. package/src/sass/tokens/_contrast.scss +94 -0
  523. package/src/sass/tokens/_elevation.scss +16 -0
  524. package/src/sass/tokens/_index.scss +5 -0
  525. package/src/sass/tokens/_motion.scss +109 -0
  526. package/src/sass/tokens/_reference.scss +72 -141
  527. package/src/sass/tokens/_shape.scss +38 -0
  528. package/src/sass/tokens/_stacking.scss +27 -0
  529. package/src/sass/tokens/_state.scss +0 -2
  530. package/src/sass/tokens/_theme.scss +10 -1
  531. package/src/sass/tokens/_vibrant.scss +2 -5
  532. package/src/sass/utilities/_defer-render.scss +17 -0
  533. package/src/sass/utilities/_helpers.scss +184 -27
  534. package/src/sass/utilities/_index.scss +1 -0
  535. package/src/sass/utilities/_scroll-area.scss +0 -2
  536. package/src/sass/utilities/_spacing.scss +52 -34
  537. package/src/sass/utilities/_typescale.scss +8 -1
  538. package/src/sass/utilities/_visibility.scss +46 -77
  539. package/src/sass/utilities/_z-depth.scss +7 -4
  540. package/dist/js/chunks/chunk-33QVDDGR.mjs +0 -270
  541. package/dist/js/chunks/chunk-33QVDDGR.mjs.map +0 -7
  542. package/dist/js/chunks/chunk-45FER6RI.mjs +0 -59
  543. package/dist/js/chunks/chunk-45FER6RI.mjs.map +0 -7
  544. package/dist/js/chunks/chunk-5CEAOLUA.mjs.map +0 -7
  545. package/dist/js/chunks/chunk-6VATUZC6.mjs +0 -295
  546. package/dist/js/chunks/chunk-6VATUZC6.mjs.map +0 -7
  547. package/dist/js/chunks/chunk-74MXKKLN.mjs.map +0 -7
  548. package/dist/js/chunks/chunk-AIURVCG6.mjs +0 -55
  549. package/dist/js/chunks/chunk-AIURVCG6.mjs.map +0 -7
  550. package/dist/js/chunks/chunk-BGZLF6JZ.mjs.map +0 -7
  551. package/dist/js/chunks/chunk-C6CHEWYP.mjs.map +0 -7
  552. package/dist/js/chunks/chunk-CK2XCICY.mjs.map +0 -7
  553. package/dist/js/chunks/chunk-CXXM2L4F.mjs +0 -344
  554. package/dist/js/chunks/chunk-CXXM2L4F.mjs.map +0 -7
  555. package/dist/js/chunks/chunk-DXGRXYYL.mjs.map +0 -7
  556. package/dist/js/chunks/chunk-FM5CZOUB.mjs.map +0 -7
  557. package/dist/js/chunks/chunk-GJL6GCIU.mjs.map +0 -7
  558. package/dist/js/chunks/chunk-K3HZMFMD.mjs +0 -135
  559. package/dist/js/chunks/chunk-K3HZMFMD.mjs.map +0 -7
  560. package/dist/js/chunks/chunk-KHXZ2A4K.mjs.map +0 -7
  561. package/dist/js/chunks/chunk-KQACNQ22.mjs +0 -7
  562. package/dist/js/chunks/chunk-KQACNQ22.mjs.map +0 -7
  563. package/dist/js/chunks/chunk-KUFHW3DS.mjs.map +0 -7
  564. package/dist/js/chunks/chunk-KVJAVDBC.mjs.map +0 -7
  565. package/dist/js/chunks/chunk-L27Q6ZMI.mjs.map +0 -7
  566. package/dist/js/chunks/chunk-LQWUDNHZ.mjs.map +0 -7
  567. package/dist/js/chunks/chunk-M372EDXD.mjs +0 -322
  568. package/dist/js/chunks/chunk-M372EDXD.mjs.map +0 -7
  569. package/dist/js/chunks/chunk-M3MURWMB.mjs +0 -82
  570. package/dist/js/chunks/chunk-M3MURWMB.mjs.map +0 -7
  571. package/dist/js/chunks/chunk-NUHMOAOY.mjs.map +0 -7
  572. package/dist/js/chunks/chunk-OWG3LMUL.mjs +0 -169
  573. package/dist/js/chunks/chunk-OWG3LMUL.mjs.map +0 -7
  574. package/dist/js/chunks/chunk-PD6HYHAE.mjs +0 -48
  575. package/dist/js/chunks/chunk-PD6HYHAE.mjs.map +0 -7
  576. package/dist/js/chunks/chunk-PDG64UHF.mjs.map +0 -7
  577. package/dist/js/chunks/chunk-PO3AXVR3.mjs +0 -546
  578. package/dist/js/chunks/chunk-PO3AXVR3.mjs.map +0 -7
  579. package/dist/js/chunks/chunk-QYGK36OG.mjs +0 -181
  580. package/dist/js/chunks/chunk-QYGK36OG.mjs.map +0 -7
  581. package/dist/js/chunks/chunk-SFI2U4YW.mjs.map +0 -7
  582. package/dist/js/chunks/chunk-SMY7GJSS.mjs.map +0 -7
  583. package/dist/js/chunks/chunk-TCCA2HDG.mjs +0 -414
  584. package/dist/js/chunks/chunk-TCCA2HDG.mjs.map +0 -7
  585. package/dist/js/chunks/chunk-TSZYSW7F.mjs.map +0 -7
  586. package/dist/js/chunks/chunk-UAZSDUVP.mjs +0 -90
  587. package/dist/js/chunks/chunk-UAZSDUVP.mjs.map +0 -7
  588. package/dist/js/chunks/chunk-UBRZZWRA.mjs +0 -127
  589. package/dist/js/chunks/chunk-UBRZZWRA.mjs.map +0 -7
  590. package/dist/js/chunks/chunk-UCOE7ZDL.mjs +0 -287
  591. package/dist/js/chunks/chunk-UCOE7ZDL.mjs.map +0 -7
  592. package/dist/js/chunks/chunk-UETTGDLI.mjs.map +0 -7
  593. package/dist/js/chunks/chunk-UNCRDLP6.mjs +0 -136
  594. package/dist/js/chunks/chunk-UNCRDLP6.mjs.map +0 -7
  595. package/dist/js/chunks/chunk-VGNYF6FB.mjs.map +0 -7
  596. package/dist/js/chunks/chunk-VGPGBNGL.mjs +0 -68
  597. package/dist/js/chunks/chunk-VGPGBNGL.mjs.map +0 -7
  598. package/dist/js/chunks/chunk-VKAUVTQY.mjs +0 -1
  599. package/dist/js/chunks/chunk-VM4FTS7L.mjs +0 -48
  600. package/dist/js/chunks/chunk-VM4FTS7L.mjs.map +0 -7
  601. package/dist/js/chunks/chunk-WDK4T63U.mjs.map +0 -7
  602. package/dist/js/chunks/chunk-WOCCTVUF.mjs +0 -185
  603. package/dist/js/chunks/chunk-WOCCTVUF.mjs.map +0 -7
  604. package/dist/js/chunks/chunk-WQYN5L4E.mjs +0 -107
  605. package/dist/js/chunks/chunk-WQYN5L4E.mjs.map +0 -7
  606. package/dist/js/chunks/chunk-X4ISMKE2.mjs.map +0 -7
  607. package/dist/js/chunks/chunk-XAEAEHIX.mjs.map +0 -7
  608. package/dist/js/chunks/chunk-ZX6M7SWO.mjs.map +0 -7
  609. /package/dist/js/chunks/{chunk-VKAUVTQY.mjs.map → chunk-GNRSYMVH.mjs.map} +0 -0
@@ -1,30 +1,67 @@
1
1
  import {
2
2
  LineChart
3
- } from "./chunk-TCCA2HDG.mjs";
3
+ } from "./chunk-IQOTGGHX.mjs";
4
4
 
5
5
  // src/ts/components/heatmapChart.ts
6
+ function band(level, steps) {
7
+ return Math.sign(level) * Math.min(steps - 1, Math.floor(Math.abs(level) * steps)) / (steps - 1);
8
+ }
6
9
  var HeatmapChart = class extends LineChart {
7
10
  get _type() {
8
11
  return "heatmap-chart";
9
12
  }
10
- get _key() {
11
- return "Expressive_HeatmapChart";
13
+ /** Color carries the value, so there is no value axis. */
14
+ get _axis() {
15
+ return false;
12
16
  }
13
- static init(els, options = {}) {
14
- return super.init(els, options);
17
+ get _count() {
18
+ return this.labels.length * this.series.length;
15
19
  }
16
- static getInstance(el) {
17
- return el["Expressive_HeatmapChart"];
20
+ destroy() {
21
+ this._resizes?.disconnect();
22
+ super.destroy();
23
+ }
24
+ /** Redraws the grid, scrolled where it was. */
25
+ update() {
26
+ const left = this._scroll?.scrollLeft;
27
+ super.update();
28
+ if (this._scroll && left) this._scroll.scrollLeft = left;
18
29
  }
19
30
  /** Highlights one cell, numbered row by row. Pass -1 to hide the tooltip. */
20
31
  show(index) {
21
32
  if (!this._tooltip || index === this.activeIndex) return;
22
- const cell = this._cells[index];
23
- const [left, top, width, plotWidth] = cell ? [cell.offsetLeft, cell.offsetTop, cell.offsetWidth, this._plot.clientWidth] : [];
33
+ this._activate(this._cells[index], index);
34
+ }
35
+ _activate(cell, index) {
36
+ const box = cell ? this._box(cell) : null;
24
37
  this._cells[this.activeIndex]?.classList.remove("active");
25
38
  this.activeIndex = index;
26
- this._tooltip.hidden = !cell;
39
+ this._tooltip.hidden = !box;
40
+ if (box) this._fill(cell, index, box);
41
+ }
42
+ /**
43
+ * A cell's left, top and width in the plot, past any scrolling of the
44
+ * grid, and the plot's width. A key can move to a cell scrolled out of a
45
+ * wide grid, so it scrolls into view first.
46
+ */
47
+ _box(cell) {
48
+ if (this._plot.matches(":focus-visible")) cell.scrollIntoView({ block: "nearest", inline: "nearest" });
49
+ return this._measure(cell);
50
+ }
51
+ _measure(cell) {
52
+ const [box, plot] = [cell.getBoundingClientRect(), this._plot.getBoundingClientRect()];
53
+ return [box.left - plot.left, box.top - plot.top, box.width, this._plot.clientWidth];
54
+ }
55
+ /** Keeps the tooltip on its cell as the grid scrolls, and hides it once the cell scrolls out. */
56
+ _follow(scroll) {
57
+ const cell = this._cells[this.activeIndex];
27
58
  if (!cell) return;
59
+ const [view, box] = [scroll.getBoundingClientRect(), cell.getBoundingClientRect()];
60
+ if (box.right <= view.left || box.left >= view.right) this.show(-1);
61
+ else this._position(this._measure(cell));
62
+ }
63
+ /** Marks the cell and fills the tooltip beside it, on the side with more room. */
64
+ _fill(cell, index, [left, top, width, plotWidth]) {
28
65
  cell.classList.add("active");
29
66
  const columns = this.series.length;
30
67
  const [row, series] = [Math.floor(index / columns), this.series[index % columns]];
@@ -36,6 +73,9 @@ var HeatmapChart = class extends LineChart {
36
73
  else name.style.setProperty("--level", String(this._levels[index]));
37
74
  text.textContent = series.text[row];
38
75
  this._tooltip.replaceChildren(title, name, text);
76
+ this._position([left, top, width, plotWidth]);
77
+ }
78
+ _position([left, top, width, plotWidth]) {
39
79
  const end = left + width / 2 > plotWidth / 2;
40
80
  this._tooltip.classList.toggle("end", end);
41
81
  this._tooltip.style.left = `${left + (end ? 0 : width)}px`;
@@ -73,10 +113,15 @@ var HeatmapChart = class extends LineChart {
73
113
  const last = this._cells[this._cells.length - 1].getBoundingClientRect();
74
114
  const [left, right] = [Math.min(first.left, last.left), Math.max(first.right, last.right)];
75
115
  const [x, y] = [e.clientX, e.clientY];
76
- if (x < left || x > right || y < first.top || y > last.bottom) return -1;
77
- const band = (offset, size, count) => Math.min(count - 1, Math.floor(offset / (size || 1) * count));
78
- const column = band(x - left, right - left, columns);
79
- return band(y - first.top, last.bottom - first.top, rows) * columns + (this._reversed ? columns - 1 - column : column);
116
+ if (this._off(x, y, [left, right, first.top, last.bottom])) return -1;
117
+ const band2 = (offset, size, count) => Math.min(count - 1, Math.floor(offset / (size || 1) * count));
118
+ const column = band2(x - left, right - left, columns);
119
+ return band2(y - first.top, last.bottom - first.top, rows) * columns + (this._reversed ? columns - 1 - column : column);
120
+ }
121
+ /** Whether a point is off the cells, or on cells scrolled out of view under the row labels. */
122
+ _off(x, y, [left, right, top, bottom]) {
123
+ const view = this._scroll.getBoundingClientRect();
124
+ return x < Math.max(left, view.left) || x > Math.min(right, view.right) || y < top || y > bottom;
80
125
  }
81
126
  /**
82
127
  * The legend: a gradient from the lowest cell's shade to the highest's,
@@ -91,11 +136,43 @@ var HeatmapChart = class extends LineChart {
91
136
  [low.textContent, high.textContent] = this._ends;
92
137
  scale.className = "heatmap-chart-scale";
93
138
  if (this._reversed) scale.style.setProperty("--heatmap-chart-to", "left");
94
- scale.style.setProperty("--low", String(this._endLevels[0]));
95
- scale.style.setProperty("--high", String(this._endLevels[1]));
139
+ const [from, to] = this._endLevels;
140
+ scale.style.setProperty("--low", String(from));
141
+ scale.style.setProperty("--high", String(to));
142
+ scale.classList.toggle("diverging", from < 0 && to > 0);
143
+ scale.style.setProperty("--mid", `${-from / (to - from || 1) * 100}%`);
144
+ scale.append(...this._bands().filter((level) => level >= from && level <= to).map((level) => {
145
+ const swatch = document.createElement("span");
146
+ swatch.style.setProperty("--level", String(level));
147
+ return swatch;
148
+ }));
96
149
  legend.append(low, scale, high);
97
150
  return [legend];
98
151
  }
152
+ /** With data-steps, every band's shade from the lowest to the highest; otherwise none. */
153
+ _bands() {
154
+ const steps = this._steps;
155
+ if (!steps) return [];
156
+ return Array.from({ length: 2 * steps - 1 }, (_, k) => (k - steps + 1) / (steps - 1));
157
+ }
158
+ /** The number of bands data-steps asks for, or 0 for a smooth scale. */
159
+ get _steps() {
160
+ const steps = Math.round(this._number("steps") ?? 0);
161
+ return steps > 1 ? steps : 0;
162
+ }
163
+ /**
164
+ * How a value shades its cell: from 0 at the scale's low end to 1 at its
165
+ * high end, or with data-mid from -1 to 1 either side of that midpoint,
166
+ * as far as the further end. With data-steps the shades fall into bands.
167
+ */
168
+ _shade(low, high) {
169
+ const option = (name, fallback) => this._number(name) ?? this.options[name] ?? fallback;
170
+ const [min, max, mid] = [option("min", low), option("max", high), this._number("mid")];
171
+ const clamp = (value, floor) => Math.min(1, Math.max(floor, value));
172
+ const level = mid === null ? (value) => clamp((value - min) / (max - min || 1), 0) : (value) => clamp((Math.min(max, Math.max(min, value)) - mid) / (Math.max(max - mid, mid - min) || 1), -1);
173
+ const steps = this._steps;
174
+ return steps ? (value) => band(level(value), steps) : level;
175
+ }
99
176
  /**
100
177
  * A grid of the row headers and cells, row by row, with the column headers
101
178
  * below. Each cell's --level shades it in CSS.
@@ -109,9 +186,7 @@ var HeatmapChart = class extends LineChart {
109
186
  if (value < low) [low, this._ends[0]] = [value, series.text[row]];
110
187
  if (value > high) [high, this._ends[1]] = [value, series.text[row]];
111
188
  }));
112
- const option = (name) => this._number(name) ?? this.options[name];
113
- const [min, max] = [option("min") ?? low, option("max") ?? high];
114
- const shade = (value) => Math.min(1, Math.max(0, (value - min) / (max - min || 1)));
189
+ const shade = this._shade(low, high);
115
190
  this._endLevels = [shade(low), shade(high)];
116
191
  const grid = document.createElement("div");
117
192
  grid.className = "heatmap-chart-grid";
@@ -128,8 +203,11 @@ var HeatmapChart = class extends LineChart {
128
203
  const values = this.el.classList.contains("values");
129
204
  this._cells = [];
130
205
  this._levels = [];
206
+ const [rows, cells] = [document.createElement("div"), document.createElement("div")];
207
+ rows.className = "heatmap-chart-rows";
208
+ cells.className = "heatmap-chart-cells";
131
209
  this.labels.forEach((_, row) => {
132
- grid.append(span("heatmap-chart-row", label(this._rows[row].cells[0])));
210
+ rows.append(span("heatmap-chart-row", label(this._rows[row].cells[0])));
133
211
  this.series.forEach((series) => {
134
212
  const value = series.values[row];
135
213
  const level = value === null ? null : shade(value);
@@ -138,24 +216,38 @@ var HeatmapChart = class extends LineChart {
138
216
  else cell.style.setProperty("--level", String(level));
139
217
  this._cells.push(cell);
140
218
  this._levels.push(level);
141
- grid.append(cell);
219
+ cells.append(cell);
142
220
  });
143
221
  });
144
222
  const labels = this._header.slice(1, columns + 1).map(label);
223
+ const columnLabels = [];
145
224
  labels.forEach((text, column) => {
146
225
  if (!text) return;
147
226
  let end = column + 1;
148
227
  while (end < columns && !labels[end]) end++;
149
228
  const element = span("heatmap-chart-column", text);
150
229
  element.classList.toggle("run", end > column + 1);
151
- element.style.gridArea = `${this.labels.length + 1} / ${column + 2} / auto / ${end + 2}`;
152
- grid.append(element);
230
+ element.style.gridArea = `${this.labels.length + 1} / ${column + 1} / auto / ${end + 1}`;
231
+ cells.append(element);
232
+ columnLabels.push(element);
153
233
  });
234
+ this._observeLabels(cells, columnLabels.some((element) => element.classList.contains("run")) ? [] : columnLabels);
235
+ const scroll = this._scroll = document.createElement("div");
236
+ scroll.className = "heatmap-chart-scroll";
237
+ scroll.tabIndex = -1;
238
+ scroll.addEventListener("focus", () => this._plot.focus());
239
+ scroll.addEventListener("scroll", () => this._follow(scroll), { passive: true });
240
+ this._resizes?.disconnect();
241
+ this._resizes = new ResizeObserver(() => this._follow(scroll));
242
+ this._resizes.observe(scroll);
243
+ scroll.append(cells);
244
+ grid.append(rows, scroll);
154
245
  return grid;
155
246
  }
156
247
  };
248
+ HeatmapChart.key = "Expressive_HeatmapChart";
157
249
 
158
250
  export {
159
251
  HeatmapChart
160
252
  };
161
- //# sourceMappingURL=chunk-VGNYF6FB.mjs.map
253
+ //# sourceMappingURL=chunk-KOTGMCMI.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/ts/components/heatmapChart.ts"],
4
+ "sourcesContent": ["import { LineChart, LineChartOptions } from './lineChart';\n\nexport type HeatmapChartOptions = LineChartOptions;\n\n/**\n * A shade in one of `steps` bands, each side of zero on a diverging scale:\n * the lowest band is the empty color, and the highest is the full color.\n */\nfunction band(level: number, steps: number) {\n return (Math.sign(level) * Math.min(steps - 1, Math.floor(Math.abs(level) * steps))) / (steps - 1);\n}\n\n/**\n * Heatmap chart. It reads its <table> like LineChart, but draws every cell\n * as a square of the grid, shaded from the lowest value to the highest, with\n * the row headers beside it and the column headers below. A `data-label` on\n * a header cell replaces its text on the grid; an empty one hides it. The\n * tooltip shows one cell, and the arrow keys move round the grid. With\n * `data-mid` the scale diverges either side of that value, and with\n * `data-steps` the shades fall into that many bands.\n *\n * Call `update()` after changing the table, or start it with `watch` or\n * `data-watch`.\n */\nexport class HeatmapChart extends LineChart {\n // No initializers: LineChart's constructor draws before they would run.\n /** Every cell, row by row. */\n private _cells: HTMLElement[];\n /** Each cell's shade from 0 to 1, or -1 to 1 on a diverging scale, or null for a gap. */\n private _levels: (number | null)[];\n /** The text of the lowest and highest cells, for the legend. */\n private _ends: [string, string];\n /** The shades of the lowest and highest cells, where the legend's gradient runs. */\n private _endLevels: [number, number];\n /** The box the cells scroll in, beside the row labels. */\n private _scroll: HTMLElement;\n /** Keeps the tooltip on its cell when the chart changes size. */\n private _resizes: ResizeObserver;\n\n protected get _type() {\n return 'heatmap-chart';\n }\n\n /** Color carries the value, so there is no value axis. */\n protected get _axis() {\n return false;\n }\n\n static key = 'Expressive_HeatmapChart';\n\n protected get _count() {\n return this.labels.length * this.series.length;\n }\n\n destroy() {\n this._resizes?.disconnect();\n super.destroy();\n }\n\n /** Redraws the grid, scrolled where it was. */\n update() {\n const left = this._scroll?.scrollLeft;\n super.update();\n if (this._scroll && left) this._scroll.scrollLeft = left;\n }\n\n /** Highlights one cell, numbered row by row. Pass -1 to hide the tooltip. */\n show(index: number) {\n if (!this._tooltip || index === this.activeIndex) return;\n this._activate(this._cells[index], index);\n }\n\n private _activate(cell: HTMLElement | undefined, index: number) {\n // Measure before the writes below, which would otherwise force a layout.\n const box = cell ? this._box(cell) : null;\n this._cells[this.activeIndex]?.classList.remove('active');\n this.activeIndex = index;\n this._tooltip.hidden = !box;\n if (box) this._fill(cell!, index, box);\n }\n\n /**\n * A cell's left, top and width in the plot, past any scrolling of the\n * grid, and the plot's width. A key can move to a cell scrolled out of a\n * wide grid, so it scrolls into view first.\n */\n private _box(cell: HTMLElement) {\n if (this._plot.matches(':focus-visible')) cell.scrollIntoView({ block: 'nearest', inline: 'nearest' });\n return this._measure(cell);\n }\n\n private _measure(cell: HTMLElement) {\n const [box, plot] = [cell.getBoundingClientRect(), this._plot.getBoundingClientRect()];\n return [box.left - plot.left, box.top - plot.top, box.width, this._plot.clientWidth];\n }\n\n /** Keeps the tooltip on its cell as the grid scrolls, and hides it once the cell scrolls out. */\n private _follow(scroll: HTMLElement) {\n const cell = this._cells[this.activeIndex];\n if (!cell) return;\n const [view, box] = [scroll.getBoundingClientRect(), cell.getBoundingClientRect()];\n if (box.right <= view.left || box.left >= view.right) this.show(-1);\n else this._position(this._measure(cell));\n }\n\n /** Marks the cell and fills the tooltip beside it, on the side with more room. */\n private _fill(cell: HTMLElement, index: number, [left, top, width, plotWidth]: number[]) {\n cell.classList.add('active');\n const columns = this.series.length;\n const [row, series] = [Math.floor(index / columns), this.series[index % columns]];\n const title = document.createElement('strong');\n title.textContent = this.labels[row];\n const [name, text] = [document.createElement('span'), document.createElement('span')];\n name.textContent = series.name;\n // A gap's swatch is outlined like its cell.\n if (this._levels[index] === null) name.className = 'gap';\n else name.style.setProperty('--level', String(this._levels[index]));\n text.textContent = series.text[row];\n this._tooltip.replaceChildren(title, name, text);\n this._position([left, top, width, plotWidth]);\n }\n\n private _position([left, top, width, plotWidth]: number[]) {\n const end = left + width / 2 > plotWidth / 2;\n this._tooltip.classList.toggle('end', end);\n this._tooltip.style.left = `${left + (end ? 0 : width)}px`;\n this._tooltip.style.top = `${top}px`;\n }\n\n /** Arrows move the way they point, so left and right swap in RTL. */\n protected _keyTarget(key: string): number | undefined {\n // With nothing shown, Escape is left to a dialog or sheet around the chart.\n if (key === 'Escape') return this.activeIndex < 0 ? undefined : -1;\n const [columns, last] = [this.series.length, this.labels.length - 1];\n const index = Math.max(0, this.activeIndex);\n const [row, column] = [Math.floor(index / columns), index % columns];\n const [next, back] = this._reversed ? ['ArrowLeft', 'ArrowRight'] : ['ArrowRight', 'ArrowLeft'];\n const to = {\n [next]: [row, column + 1],\n [back]: [row, column - 1],\n ArrowDown: [row + 1, column],\n ArrowUp: [row - 1, column],\n Home: [row, 0],\n End: [row, columns - 1]\n }[key];\n if (!to) return undefined;\n // The first key after focus or Escape shows the first cell.\n if (this.activeIndex < 0) return 0;\n const clamp = (value: number, max: number) => Math.min(max, Math.max(0, value));\n return clamp(to[0], last) * columns + clamp(to[1], columns - 1);\n }\n\n /**\n * The cell under the pointer by its position, or -1 off the grid. A touch\n * keeps its first target while it drags, so the target cannot be used. The\n * cells and gaps are even, so each band's edge falls in a gap and a gap\n * counts as the nearer cell.\n */\n protected _indexAt(e: PointerEvent) {\n const [columns, rows] = [this.series.length, this.labels.length];\n const first = this._cells[0].getBoundingClientRect();\n const last = this._cells[this._cells.length - 1].getBoundingClientRect();\n const [left, right] = [Math.min(first.left, last.left), Math.max(first.right, last.right)];\n const [x, y] = [e.clientX, e.clientY];\n if (this._off(x, y, [left, right, first.top, last.bottom])) return -1;\n const band = (offset: number, size: number, count: number) =>\n Math.min(count - 1, Math.floor((offset / (size || 1)) * count));\n const column = band(x - left, right - left, columns);\n return band(y - first.top, last.bottom - first.top, rows) * columns + (this._reversed ? columns - 1 - column : column);\n }\n\n /** Whether a point is off the cells, or on cells scrolled out of view under the row labels. */\n private _off(x: number, y: number, [left, right, top, bottom]: number[]) {\n const view = this._scroll.getBoundingClientRect();\n return x < Math.max(left, view.left) || x > Math.min(right, view.right) || y < top || y > bottom;\n }\n\n /**\n * The legend: a gradient from the lowest cell's shade to the highest's,\n * labelled with their text. A fixed scale wider than the data shows only\n * the part the data uses.\n */\n protected _guides(): Element[] {\n const legend = document.createElement('div');\n legend.className = 'heatmap-chart-legend';\n legend.setAttribute('aria-hidden', 'true');\n const [low, scale, high] = ['span', 'span', 'span'].map((tag) => document.createElement(tag));\n [low.textContent, high.textContent] = this._ends;\n scale.className = 'heatmap-chart-scale';\n if (this._reversed) scale.style.setProperty('--heatmap-chart-to', 'left');\n const [from, to] = this._endLevels;\n scale.style.setProperty('--low', String(from));\n scale.style.setProperty('--high', String(to));\n // A diverging scale whose data crosses the midpoint passes its empty color.\n scale.classList.toggle('diverging', from < 0 && to > 0);\n scale.style.setProperty('--mid', `${(-from / (to - from || 1)) * 100}%`);\n scale.append(...this._bands().filter((level) => level >= from && level <= to).map((level) => {\n const swatch = document.createElement('span');\n swatch.style.setProperty('--level', String(level));\n return swatch;\n }));\n legend.append(low, scale, high);\n return [legend];\n }\n\n /** With data-steps, every band's shade from the lowest to the highest; otherwise none. */\n private _bands() {\n const steps = this._steps;\n if (!steps) return [];\n return Array.from({ length: 2 * steps - 1 }, (_, k) => (k - steps + 1) / (steps - 1));\n }\n\n /** The number of bands data-steps asks for, or 0 for a smooth scale. */\n private get _steps() {\n const steps = Math.round(this._number('steps') ?? 0);\n return steps > 1 ? steps : 0;\n }\n\n /**\n * How a value shades its cell: from 0 at the scale's low end to 1 at its\n * high end, or with data-mid from -1 to 1 either side of that midpoint,\n * as far as the further end. With data-steps the shades fall into bands.\n */\n private _shade(low: number, high: number) {\n const option = (name: 'min' | 'max', fallback: number) => this._number(name) ?? this.options[name] ?? fallback;\n const [min, max, mid] = [option('min', low), option('max', high), this._number('mid')];\n const clamp = (value: number, floor: number) => Math.min(1, Math.max(floor, value));\n const level = mid === null\n ? (value: number) => clamp((value - min) / (max - min || 1), 0)\n : (value: number) => clamp((Math.min(max, Math.max(min, value)) - mid) / (Math.max(max - mid, mid - min) || 1), -1);\n const steps = this._steps;\n return steps ? (value: number) => band(level(value), steps) : level;\n }\n\n /**\n * A grid of the row headers and cells, row by row, with the column headers\n * below. Each cell's --level shades it in CSS.\n */\n protected _draw(): Element {\n const columns = this.series.length;\n let [low, high] = [Infinity, -Infinity];\n this._ends = ['', ''];\n this.series.forEach((series) => series.values.forEach((value, row) => {\n if (value === null) return;\n if (value < low) [low, this._ends[0]] = [value, series.text[row]];\n if (value > high) [high, this._ends[1]] = [value, series.text[row]];\n }));\n const shade = this._shade(low, high);\n this._endLevels = [shade(low), shade(high)];\n\n const grid = document.createElement('div');\n grid.className = 'heatmap-chart-grid';\n grid.setAttribute('aria-hidden', 'true');\n grid.style.setProperty('--columns', String(columns));\n grid.style.setProperty('--rows', String(this.labels.length));\n const span = (className: string, text = '') => {\n const element = document.createElement('span');\n element.className = className;\n element.textContent = text;\n return element;\n };\n const label = (cell: HTMLTableCellElement | undefined) =>\n cell?.dataset.label ?? cell?.textContent.trim() ?? '';\n const values = this.el.classList.contains('values');\n\n this._cells = [];\n this._levels = [];\n // The row labels stay put beside the cells, which scroll when they are too narrow.\n const [rows, cells] = [document.createElement('div'), document.createElement('div')];\n rows.className = 'heatmap-chart-rows';\n cells.className = 'heatmap-chart-cells';\n this.labels.forEach((_, row) => {\n rows.append(span('heatmap-chart-row', label(this._rows[row].cells[0])));\n this.series.forEach((series) => {\n const value = series.values[row];\n const level = value === null ? null : shade(value);\n const cell = span('heatmap-chart-cell', values ? series.text[row] : '');\n if (level === null) cell.classList.add('gap');\n else cell.style.setProperty('--level', String(level));\n this._cells.push(cell);\n this._levels.push(level);\n cells.append(cell);\n });\n });\n\n // A column label runs on over the empty labels after it.\n const labels = this._header.slice(1, columns + 1).map(label);\n const columnLabels: HTMLElement[] = [];\n labels.forEach((text, column) => {\n if (!text) return;\n let end = column + 1;\n while (end < columns && !labels[end]) end++;\n const element = span('heatmap-chart-column', text);\n element.classList.toggle('run', end > column + 1);\n element.style.gridArea = `${this.labels.length + 1} / ${column + 1} / auto / ${end + 1}`;\n cells.append(element);\n columnLabels.push(element);\n });\n // Labels the author already spaced out with empty ones are left as written.\n this._observeLabels(cells, columnLabels.some((element) => element.classList.contains('run')) ? [] : columnLabels);\n\n // The plot is the one Tab stop, so the scroll box is not another, and a\n // press that focuses it hands focus on to the plot.\n const scroll = (this._scroll = document.createElement('div'));\n scroll.className = 'heatmap-chart-scroll';\n scroll.tabIndex = -1;\n scroll.addEventListener('focus', () => this._plot.focus());\n scroll.addEventListener('scroll', () => this._follow(scroll), { passive: true });\n this._resizes?.disconnect();\n this._resizes = new ResizeObserver(() => this._follow(scroll));\n this._resizes.observe(scroll);\n scroll.append(cells);\n grid.append(rows, scroll);\n return grid;\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["band"]
7
+ }
@@ -1,9 +1,9 @@
1
- import {
2
- Utils
3
- } from "./chunk-M372EDXD.mjs";
4
1
  import {
5
2
  Component
6
- } from "./chunk-PD6HYHAE.mjs";
3
+ } from "./chunk-EB2V4OKL.mjs";
4
+ import {
5
+ Utils
6
+ } from "./chunk-67UNY7RH.mjs";
7
7
 
8
8
  // src/ts/components/messageScroller.ts
9
9
  var _defaults = {
@@ -14,9 +14,9 @@ var _defaults = {
14
14
  var EDGE = 2;
15
15
  var UP_KEYS = /* @__PURE__ */ new Set(["ArrowUp", "PageUp", "Home"]);
16
16
  var RELEASE_EVENTS = ["pointerup", "pointercancel", "touchend", "touchcancel"];
17
- var MessageScroller = class _MessageScroller extends Component {
17
+ var MessageScroller = class extends Component {
18
18
  constructor(el, options) {
19
- super(el, options, _MessageScroller);
19
+ super(el, options);
20
20
  this._opened = false;
21
21
  this._following = false;
22
22
  /** A press is down: it may be a tap or a scrollbar drag. */
@@ -65,10 +65,10 @@ var MessageScroller = class _MessageScroller extends Component {
65
65
  this._handleMutations = (records) => {
66
66
  for (const record of records) {
67
67
  record.addedNodes.forEach((node) => {
68
- if (node instanceof Element) this._resizeObserver?.observe(node);
68
+ if (node instanceof Element) this._resizeObserver.observe(node);
69
69
  });
70
70
  record.removedNodes.forEach((node) => {
71
- if (node instanceof Element) this._resizeObserver?.unobserve(node);
71
+ if (node instanceof Element) this._resizeObserver.unobserve(node);
72
72
  });
73
73
  }
74
74
  const previous = this._last;
@@ -101,11 +101,6 @@ var MessageScroller = class _MessageScroller extends Component {
101
101
  }
102
102
  this._sync();
103
103
  };
104
- this.el["Expressive_MessageScroller"] = this;
105
- this.options = {
106
- ..._MessageScroller.defaults,
107
- ...options
108
- };
109
104
  this.viewport = el.querySelector(":scope > .message-scroller-viewport");
110
105
  this.button = el.querySelector(":scope > .message-scroller-button");
111
106
  if (!this.viewport) {
@@ -114,49 +109,29 @@ var MessageScroller = class _MessageScroller extends Component {
114
109
  }
115
110
  this._last = this.viewport.lastElementChild;
116
111
  if (this.viewport.clientHeight > 0) this._open();
117
- if (typeof ResizeObserver !== "undefined") {
118
- this._resizeObserver = new ResizeObserver(this._handleResize);
119
- this._resizeObserver.observe(this.viewport, { box: "border-box" });
120
- for (const item of Array.from(this.viewport.children)) this._resizeObserver.observe(item);
121
- }
112
+ this._resizeObserver = new ResizeObserver(this._handleResize);
113
+ this._resizeObserver.observe(this.viewport, { box: "border-box" });
114
+ for (const item of Array.from(this.viewport.children)) this._resizeObserver.observe(item);
122
115
  this._mutationObserver = new MutationObserver(this._handleMutations);
123
116
  this._mutationObserver.observe(this.viewport, { childList: true });
124
- this.viewport.addEventListener("scroll", this._handleScroll, { passive: true });
117
+ const { signal } = this._events;
118
+ this.viewport.addEventListener("scroll", this._handleScroll, { passive: true, signal });
125
119
  for (const type of ["wheel", "touchstart", "pointerdown", "keydown"]) {
126
- this.viewport.addEventListener(type, this._handleUserScroll, { passive: true });
120
+ this.viewport.addEventListener(type, this._handleUserScroll, { passive: true, signal });
127
121
  }
128
- for (const type of RELEASE_EVENTS) document.addEventListener(type, this._handleRelease);
129
- this.button?.addEventListener("click", this._handleButtonClick);
122
+ for (const type of RELEASE_EVENTS) document.addEventListener(type, this._handleRelease, { signal });
123
+ this.button?.addEventListener("click", this._handleButtonClick, { signal });
130
124
  }
131
125
  static get defaults() {
132
126
  return _defaults;
133
127
  }
134
- /**
135
- * Initializes instances of MessageScroller.
136
- * @param els HTML elements.
137
- * @param options Component options.
138
- */
139
- static init(els, options = {}) {
140
- return super.init(els, options, _MessageScroller);
141
- }
142
- static getInstance(el) {
143
- return el["Expressive_MessageScroller"];
144
- }
145
128
  destroy() {
146
- this.el["Expressive_MessageScroller"] = void 0;
129
+ super.destroy();
147
130
  if (!this.viewport) return;
148
131
  this._resizeObserver?.disconnect();
149
132
  this._mutationObserver?.disconnect();
150
- this.viewport.removeEventListener("scroll", this._handleScroll);
151
- for (const type of ["wheel", "touchstart", "pointerdown", "keydown"]) {
152
- this.viewport.removeEventListener(type, this._handleUserScroll);
153
- }
154
- for (const type of RELEASE_EVENTS) document.removeEventListener(type, this._handleRelease);
155
133
  this.viewport.style.removeProperty("--md-comp-message-scroller-spacer");
156
- if (this.button) {
157
- this.button.removeEventListener("click", this._handleButtonClick);
158
- this.button.inert = false;
159
- }
134
+ if (this.button) this.button.inert = false;
160
135
  }
161
136
  /** Scrolls to the latest message and resumes following. */
162
137
  scrollToEnd() {
@@ -214,7 +189,7 @@ var MessageScroller = class _MessageScroller extends Component {
214
189
  }
215
190
  this._target = target;
216
191
  this._distance = Infinity;
217
- const reduce = typeof matchMedia === "function" && matchMedia("(prefers-reduced-motion: reduce)").matches;
192
+ const reduce = matchMedia("(prefers-reduced-motion: reduce)").matches;
218
193
  v.scrollTo({
219
194
  top: target === "end" ? v.scrollHeight : target,
220
195
  behavior: reduce ? "auto" : "smooth"
@@ -285,8 +260,9 @@ var MessageScroller = class _MessageScroller extends Component {
285
260
  this.button.inert = idle;
286
261
  }
287
262
  };
263
+ MessageScroller.key = "Expressive_MessageScroller";
288
264
 
289
265
  export {
290
266
  MessageScroller
291
267
  };
292
- //# sourceMappingURL=chunk-LQWUDNHZ.mjs.map
268
+ //# sourceMappingURL=chunk-LC4O5LFS.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/ts/components/messageScroller.ts"],
4
+ "sourcesContent": ["import { Utils } from '../core/utils';\nimport { Component, BaseOptions } from '../core/component';\n\nexport interface MessageScrollerOptions extends BaseOptions {\n /**\n * If true, the viewport follows new content while the reader is at the\n * end, and a newly appended scroll anchor is brought to the top.\n * @default true\n */\n autoScroll: boolean;\n /**\n * Where the transcript opens: `'end'`, `'start'`, or `'last-anchor'`, the\n * start of the last anchored turn. `'last-anchor'` opens at the end when\n * that turn already fits in the viewport.\n * @default 'end'\n */\n defaultScrollPosition: 'start' | 'end' | 'last-anchor';\n /**\n * Pixels of the previous message left visible above an anchored turn or a\n * message reached with `scrollToMessage()`.\n * @default 64\n */\n peek: number;\n}\n\nconst _defaults: MessageScrollerOptions = {\n autoScroll: true,\n defaultScrollPosition: 'end',\n peek: 64\n};\n\n// Distance from a scroll target, in px, that still counts as reaching it.\n// Fractional layouts rarely land on the exact pixel.\nconst EDGE = 2;\n\n// Keys that scroll toward the start. They release following at once, before\n// the next streamed chunk can pull the viewport back to the end.\nconst UP_KEYS = new Set(['ArrowUp', 'PageUp', 'Home']);\n\n// Listened on the document: a scrollbar drag can end outside the viewport.\nconst RELEASE_EVENTS = ['pointerup', 'pointercancel', 'touchend', 'touchcancel'];\n\ntype Target = number | 'end';\n\n/**\n * A chat scroll container: a `.message-scroller` frame holding a scrolling\n * `.message-scroller-viewport` of messages and an optional\n * `.message-scroller-button`. Every child of the viewport is one message.\n *\n * While the reader is at the end, the viewport follows streamed output.\n * Scrolling toward the start releases it; reaching the end again, or the\n * button, resumes it. An appended message marked `data-scroll-anchor` starts a\n * turn and is scrolled to the top, with blank space below it until the reply\n * fills the viewport. Messages added above keep the reader's place.\n */\nexport class MessageScroller extends Component<MessageScrollerOptions> {\n /** The scrolling element. */\n viewport: HTMLElement;\n /** The scroll-to-latest button, if present. */\n button: HTMLButtonElement | null;\n private _opened = false;\n private _following = false;\n /** A press is down: it may be a tap or a scrollbar drag. */\n private _holding = false;\n private _lastTop = 0;\n /** Where a programmatic scroll is heading; null when none is running. */\n private _target: Target | null = null;\n /** Distance left to the target at the last scroll event. */\n private _distance = Infinity;\n /** The first visible message and its offset from the viewport top. */\n private _ref: Element | null = null;\n private _refOffset = 0;\n /** The latest anchored turn, which the spacer lets reach the top. */\n private _anchor: Element | null = null;\n private _spacer = 0;\n private _last: Element | null = null;\n private _resizeObserver: ResizeObserver | null = null;\n private _mutationObserver: MutationObserver | null = null;\n\n constructor(el: HTMLElement, options: Partial<MessageScrollerOptions>) {\n super(el, options);\n this.viewport = el.querySelector(':scope > .message-scroller-viewport');\n this.button = el.querySelector(':scope > .message-scroller-button');\n if (!this.viewport) {\n console.error('MessageScroller needs a .message-scroller-viewport child.');\n return;\n }\n this._last = this.viewport.lastElementChild;\n // A viewport that is not rendered yet (a closed dialog, a hidden tab)\n // has no size to position against; it opens on its first resize.\n if (this.viewport.clientHeight > 0) this._open();\n this._resizeObserver = new ResizeObserver(this._handleResize);\n // Border box: the spacer changes the padding, which must not count.\n this._resizeObserver.observe(this.viewport, { box: 'border-box' });\n for (const item of Array.from(this.viewport.children)) this._resizeObserver.observe(item);\n this._mutationObserver = new MutationObserver(this._handleMutations);\n this._mutationObserver.observe(this.viewport, { childList: true });\n const { signal } = this._events;\n this.viewport.addEventListener('scroll', this._handleScroll, { passive: true, signal });\n for (const type of ['wheel', 'touchstart', 'pointerdown', 'keydown']) {\n this.viewport.addEventListener(type, this._handleUserScroll, { passive: true, signal });\n }\n for (const type of RELEASE_EVENTS) document.addEventListener(type, this._handleRelease, { signal });\n this.button?.addEventListener('click', this._handleButtonClick, { signal });\n }\n\n static get defaults(): MessageScrollerOptions {\n return _defaults;\n }\n\n static key = 'Expressive_MessageScroller';\n\n destroy() {\n super.destroy();\n if (!this.viewport) return;\n this._resizeObserver?.disconnect();\n this._mutationObserver?.disconnect();\n this.viewport.style.removeProperty('--md-comp-message-scroller-spacer');\n if (this.button) this.button.inert = false;\n }\n\n /** Scrolls to the latest message and resumes following. */\n scrollToEnd() {\n // Set now: output streaming faster than the scroll can end it early.\n this._following = this.options.autoScroll;\n this._scrollTo('end');\n }\n\n /** Scrolls to the first message. */\n scrollToStart() {\n this._following = false;\n this._scrollTo(0);\n }\n\n /**\n * Scrolls the element with this id to the top of the viewport, below the\n * peek, and stops following.\n * @returns false when no such element is inside the viewport.\n */\n scrollToMessage(id: string): boolean {\n const target = Utils.getElementById(this.viewport, id);\n if (!target || !this.viewport.contains(target)) return false;\n this._following = false;\n this._scrollTo(this._top(target) - this.options.peek);\n return true;\n }\n\n private _open() {\n this._opened = true;\n const v = this.viewport;\n const position = this.options.defaultScrollPosition;\n const anchors = v.querySelectorAll(':scope > [data-scroll-anchor]');\n const anchor = position === 'last-anchor' ? anchors[anchors.length - 1] : null;\n if (position === 'start') v.scrollTop = 0;\n else if (anchor && this._contentEnd() - this._top(anchor) + this.options.peek > v.clientHeight) {\n v.scrollTop = this._top(anchor) - this.options.peek;\n } else v.scrollTop = v.scrollHeight;\n this._settle();\n }\n\n /**\n * Records where the reader is once no programmatic scroll is running.\n * Content can grow between a scroll and the resize that re-pins the end,\n * so only moving toward the start releases following.\n */\n private _settle() {\n const top = this.viewport.scrollTop;\n const kept = this._following && top >= this._lastTop - EDGE;\n this._following = this.options.autoScroll && (kept || this._atEnd());\n this._lastTop = top;\n this._capture();\n this._sync();\n }\n\n // A programmatic scroll ends when it arrives, or when a scroll moves away\n // from its target because something else took over.\n private _handleScroll = () => {\n if (this._target !== null) {\n const distance = Math.abs(this.viewport.scrollTop - this._resolve(this._target));\n if (distance > EDGE && distance < this._distance) {\n this._distance = distance;\n return;\n }\n this._target = null;\n }\n this._settle();\n };\n\n private _handleUserScroll = (e: Event) => {\n if (e.type === 'wheel' && (e as WheelEvent).deltaY >= 0) return;\n if (e.type === 'keydown' && !UP_KEYS.has((e as KeyboardEvent).key)) return;\n this._target = null;\n // A press may be a tap on a message or the start of a drag. Hold the end\n // until it is released; a scroll toward the start releases following.\n if (e.type === 'pointerdown' || e.type === 'touchstart') this._holding = true;\n else this._following = false;\n };\n\n private _handleRelease = () => {\n if (!this._holding) return;\n this._holding = false;\n if (this._following) this.viewport.scrollTop = this.viewport.scrollHeight;\n this._sync();\n };\n\n private _handleButtonClick = () => this.scrollToEnd();\n\n private _handleMutations = (records: MutationRecord[]) => {\n for (const record of records) {\n record.addedNodes.forEach((node) => {\n if (node instanceof Element) this._resizeObserver.observe(node);\n });\n record.removedNodes.forEach((node) => {\n if (node instanceof Element) this._resizeObserver.unobserve(node);\n });\n }\n const previous = this._last;\n this._last = this.viewport.lastElementChild;\n if (!this._opened) return;\n // Restore here, not only on resize: this runs before any scroll event\n // that could record the shifted position as the reader's place.\n if (!this._following && this._target === null) this._restore();\n if (!this.options.autoScroll) return;\n // Only messages appended after the previous last one start a new turn;\n // anchors in prepended history do not. If the last one was removed, the\n // list was replaced and nothing counts as appended.\n if (previous && previous.parentElement !== this.viewport) return;\n for (let item = this._last; item && item !== previous; item = item.previousElementSibling) {\n if (item.hasAttribute('data-scroll-anchor')) {\n this._anchor = item;\n this._updateSpacer();\n // Follow the reply once the turn reaches the top, unless the reader\n // scrolls away first. _settle keeps it because the scroll went down.\n this._following = true;\n this._scrollTo(this._top(item) - this.options.peek);\n return;\n }\n }\n };\n\n private _handleResize = () => {\n if (!this._opened) {\n if (this.viewport.clientHeight > 0) this._open();\n return;\n }\n this._updateSpacer();\n const v = this.viewport;\n if (this._target === 'end') this._scrollTo('end');\n else if (this._target === null) {\n if (this._following && !this._holding) v.scrollTop = v.scrollHeight;\n else this._restore();\n }\n this._sync();\n };\n\n private _scrollTo(target: Target) {\n const v = this.viewport;\n if (Math.abs(v.scrollTop - this._resolve(target)) <= EDGE) {\n this._target = null;\n this._settle();\n return;\n }\n this._target = target;\n this._distance = Infinity;\n const reduce = matchMedia('(prefers-reduced-motion: reduce)').matches;\n v.scrollTo({\n top: target === 'end' ? v.scrollHeight : target,\n behavior: reduce ? 'auto' : 'smooth'\n });\n }\n\n private _resolve(target: Target) {\n const max = this.viewport.scrollHeight - this.viewport.clientHeight;\n return target === 'end' ? max : Math.max(0, Math.min(target, max));\n }\n\n private _atEnd() {\n const v = this.viewport;\n return v.scrollHeight - v.scrollTop - v.clientHeight <= EDGE;\n }\n\n /** Offset of an element from the top of the scrolled content. */\n private _top(el: Element) {\n const v = this.viewport;\n return el.getBoundingClientRect().top - v.getBoundingClientRect().top - v.clientTop + v.scrollTop;\n }\n\n /** Bottom of the content without the spacer, padding included. */\n private _contentEnd() {\n const last = this.viewport.lastElementChild;\n if (!last) return 0;\n const padding = parseFloat(getComputedStyle(this.viewport).paddingBlockEnd) - this._spacer;\n return this._top(last) + last.getBoundingClientRect().height + padding;\n }\n\n /** Remembers the first visible message so prepends can keep it in place. */\n private _capture() {\n const items = this.viewport.children;\n const top = this.viewport.getBoundingClientRect().top + this.viewport.clientTop;\n let low = 0;\n let high = items.length - 1;\n while (low < high) {\n const mid = (low + high) >> 1;\n if (items[mid].getBoundingClientRect().bottom > top) high = mid;\n else low = mid + 1;\n }\n this._ref = items[low] ?? null;\n this._refOffset = this._ref ? this._ref.getBoundingClientRect().top - top : 0;\n }\n\n /** Moves the remembered message back to where the reader last saw it. */\n private _restore() {\n if (this._ref?.parentElement !== this.viewport) {\n this._capture();\n return;\n }\n const top = this.viewport.getBoundingClientRect().top + this.viewport.clientTop;\n const delta = this._ref.getBoundingClientRect().top - top - this._refOffset;\n if (Math.abs(delta) >= 1) this.viewport.scrollTop += delta;\n }\n\n /** Sizes the blank space that lets the latest anchored turn reach the top. */\n private _updateSpacer() {\n let space = 0;\n if (this._anchor?.parentElement === this.viewport) {\n const room = this._top(this._anchor) - this.options.peek + this.viewport.clientHeight;\n space = Math.max(0, Math.ceil(room - this._contentEnd()));\n } else this._anchor = null;\n if (space === this._spacer) return;\n this._spacer = space;\n if (space) this.viewport.style.setProperty('--md-comp-message-scroller-spacer', `${space}px`);\n else this.viewport.style.removeProperty('--md-comp-message-scroller-spacer');\n }\n\n /** The button is inert while there is nothing below. */\n private _sync() {\n if (!this.button) return;\n const idle = this._atEnd();\n // The button's own root: inside a shadow root, document.activeElement is the host.\n const root = this.button.getRootNode() as Document | ShadowRoot;\n if (idle && root.activeElement === this.button) this.viewport.focus({ preventScroll: true });\n this.button.inert = idle;\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,127 @@
1
+ import {
2
+ Utils
3
+ } from "./chunk-67UNY7RH.mjs";
4
+
5
+ // src/ts/behaviors/dialogs.ts
6
+ function textElement(tag, text) {
7
+ const el = document.createElement(tag);
8
+ el.textContent = text;
9
+ return el;
10
+ }
11
+ function actionButton(label, value) {
12
+ const button = textElement("button", label);
13
+ button.type = "submit";
14
+ button.value = value;
15
+ return button;
16
+ }
17
+ var _Dialogs = class _Dialogs {
18
+ /**
19
+ * Asks a yes-or-no question in a modal alert dialog. Resolves true on the
20
+ * confirm button and false on Cancel, Escape or a scrim tap, then removes
21
+ * the dialog. The browser returns focus to the element that had it.
22
+ */
23
+ static confirm(options) {
24
+ const dialog = _Dialogs._confirmDialog(options);
25
+ document.body.append(dialog);
26
+ dialog.showModal();
27
+ return new Promise((resolve) => {
28
+ const removed = new MutationObserver(() => {
29
+ if (!dialog.isConnected) settle(false);
30
+ });
31
+ const settle = (answer) => {
32
+ removed.disconnect();
33
+ dialog.remove();
34
+ resolve(answer);
35
+ };
36
+ removed.observe(document, { childList: true, subtree: true });
37
+ dialog.addEventListener("close", () => settle(dialog.returnValue === "confirm"), { once: true });
38
+ });
39
+ }
40
+ static _confirmDialog({ text, headline, confirm, cancel }) {
41
+ const dialog = document.createElement("dialog");
42
+ dialog.setAttribute("role", "alertdialog");
43
+ const id = `expressive-confirm-${++_Dialogs._confirms}`;
44
+ const body = textElement("p", text);
45
+ body.id = `${id}-text`;
46
+ const cancelButton = actionButton(cancel ?? _Dialogs.i18n.cancel, "");
47
+ cancelButton.className = "text";
48
+ cancelButton.autofocus = true;
49
+ const form = document.createElement("form");
50
+ form.method = "dialog";
51
+ form.append(cancelButton, actionButton(confirm ?? _Dialogs.i18n.confirm, "confirm"));
52
+ dialog.append(body, form);
53
+ _Dialogs._name(dialog, body, id, headline);
54
+ return dialog;
55
+ }
56
+ /** Names the dialog by its headline and describes it by the text, or names it by the text alone. */
57
+ static _name(dialog, body, id, headline) {
58
+ if (!headline) {
59
+ dialog.setAttribute("aria-labelledby", body.id);
60
+ return;
61
+ }
62
+ const heading = textElement("h2", headline);
63
+ heading.id = `${id}-headline`;
64
+ dialog.prepend(heading);
65
+ dialog.setAttribute("aria-labelledby", heading.id);
66
+ dialog.setAttribute("aria-describedby", body.id);
67
+ }
68
+ static Init() {
69
+ Utils.onDocumentReady(() => {
70
+ document.addEventListener("pointerdown", _Dialogs._onPointerDown, { passive: true });
71
+ document.addEventListener("pointerup", _Dialogs._onPointerUp, { passive: true });
72
+ document.addEventListener("pointercancel", _Dialogs._onPointerCancel, { passive: true });
73
+ });
74
+ }
75
+ static _onPointerDown(event) {
76
+ const dialog = _Dialogs._isPrimaryPress(event) ? _Dialogs._backdropDialog(event) : null;
77
+ _Dialogs._down = dialog && _Dialogs._lightDismissible(dialog) && _Dialogs._outside(event, dialog) ? { dialog, pointerId: event.pointerId } : null;
78
+ }
79
+ static _onPointerUp(event) {
80
+ const started = _Dialogs._down;
81
+ _Dialogs._down = null;
82
+ if (!started || started.pointerId !== event.pointerId) return;
83
+ if (!started.dialog.isConnected || !started.dialog.open) return;
84
+ if (!_Dialogs._lightDismissible(started.dialog)) return;
85
+ if (_Dialogs._backdropDialog(event) !== started.dialog) return;
86
+ if (_Dialogs._outside(event, started.dialog)) {
87
+ started.dialog.close();
88
+ }
89
+ }
90
+ static _onPointerCancel() {
91
+ _Dialogs._down = null;
92
+ }
93
+ /** Backdrop hits retarget to the dialog itself, never a child. */
94
+ static _backdropDialog(event) {
95
+ const target = Utils.eventTarget(event);
96
+ if (!(target instanceof HTMLDialogElement) || !target.open) return null;
97
+ return target;
98
+ }
99
+ static _outside(event, dialog) {
100
+ const rect = dialog.getBoundingClientRect();
101
+ return event.clientX < rect.left || event.clientX > rect.right || event.clientY < rect.top || event.clientY > rect.bottom;
102
+ }
103
+ static _isPrimaryPress(event) {
104
+ if (!event.isPrimary) return false;
105
+ return event.pointerType !== "mouse" || event.button === 0;
106
+ }
107
+ // Read the attribute only. The IDL default for an unset closedby is
108
+ // "closerequest" (Escape, no light dismiss) — treating that as an
109
+ // author opt-out made every dialog undismissable from the scrim.
110
+ // Native closedby="any" already light-dismisses with the same "both ends
111
+ // outside" rule, so leave it to the browser where it has one.
112
+ static _lightDismissible(dialog) {
113
+ const value = dialog.getAttribute("closedby");
114
+ if (value === "any") return !("closedBy" in HTMLDialogElement.prototype);
115
+ return value !== "none" && value !== "closerequest";
116
+ }
117
+ };
118
+ /** The confirm dialog's default button labels. */
119
+ _Dialogs.i18n = { confirm: "OK", cancel: "Cancel" };
120
+ _Dialogs._down = null;
121
+ _Dialogs._confirms = 0;
122
+ var Dialogs = _Dialogs;
123
+
124
+ export {
125
+ Dialogs
126
+ };
127
+ //# sourceMappingURL=chunk-LEF33SCP.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/ts/behaviors/dialogs.ts"],
4
+ "sourcesContent": ["import { Utils } from '../core/utils';\n\nexport interface ConfirmOptions {\n /** The question, shown as the supporting text. */\n text: string;\n /** An optional headline above the text. */\n headline?: string;\n /** The confirm button's label. Defaults to `Dialogs.i18n.confirm`. */\n confirm?: string;\n /** The cancel button's label. Defaults to `Dialogs.i18n.cancel`. */\n cancel?: string;\n}\n\n/** An element holding `text`, set as text so markup in it is never parsed. */\nfunction textElement<K extends keyof HTMLElementTagNameMap>(tag: K, text: string): HTMLElementTagNameMap[K] {\n const el = document.createElement(tag);\n el.textContent = text;\n return el;\n}\n\n/** A submit button that closes its dialog with `value` as the return value. */\nfunction actionButton(label: string, value: string): HTMLButtonElement {\n const button = textElement('button', label);\n button.type = 'submit';\n button.value = value;\n return button;\n}\n\n/**\n * Light-dismiss for native `<dialog>` elements.\n *\n * `showModal()` does not close on a backdrop tap. A naive `click` listener\n * on the dialog (where `::backdrop` events retarget) also fires when the\n * user starts a gesture on the dialog and releases on the scrim \u2014 selecting\n * text, missing a button, dragging a thumb. Both ends of the pointer\n * gesture must land outside the dialog's border box.\n *\n * Default is on. Opt out with `closedby=\"none\"` or `closedby=\"closerequest\"`.\n * If the browser already honours `closedby=\"any\"`, we leave that alone.\n *\n * `Dialogs.confirm()` asks a yes-or-no question from script and needs no Init.\n */\nexport class Dialogs {\n /** The confirm dialog's default button labels. */\n static i18n = { confirm: 'OK', cancel: 'Cancel' };\n private static _down: { dialog: HTMLDialogElement; pointerId: number } | null = null;\n private static _confirms = 0;\n\n /**\n * Asks a yes-or-no question in a modal alert dialog. Resolves true on the\n * confirm button and false on Cancel, Escape or a scrim tap, then removes\n * the dialog. The browser returns focus to the element that had it.\n */\n static confirm(options: ConfirmOptions): Promise<boolean> {\n const dialog = Dialogs._confirmDialog(options);\n document.body.append(dialog);\n // A new dialog's returnValue is '', and Escape and close() leave it alone,\n // so only the confirm button sets it.\n dialog.showModal();\n return new Promise((resolve) => {\n // Removing an open dialog fires no close event, so watch for page code\n // that removes it, such as a route change, and answer false.\n const removed = new MutationObserver(() => {\n if (!dialog.isConnected) settle(false);\n });\n const settle = (answer: boolean) => {\n removed.disconnect();\n dialog.remove();\n resolve(answer);\n };\n removed.observe(document, { childList: true, subtree: true });\n dialog.addEventListener('close', () => settle(dialog.returnValue === 'confirm'), { once: true });\n });\n }\n\n private static _confirmDialog({ text, headline, confirm, cancel }: ConfirmOptions): HTMLDialogElement {\n const dialog = document.createElement('dialog');\n dialog.setAttribute('role', 'alertdialog');\n const id = `expressive-confirm-${++Dialogs._confirms}`;\n const body = textElement('p', text);\n body.id = `${id}-text`;\n const cancelButton = actionButton(cancel ?? Dialogs.i18n.cancel, '');\n cancelButton.className = 'text';\n // The less destructive action takes focus when the dialog opens.\n cancelButton.autofocus = true;\n const form = document.createElement('form');\n form.method = 'dialog';\n form.append(cancelButton, actionButton(confirm ?? Dialogs.i18n.confirm, 'confirm'));\n dialog.append(body, form);\n Dialogs._name(dialog, body, id, headline);\n return dialog;\n }\n\n /** Names the dialog by its headline and describes it by the text, or names it by the text alone. */\n private static _name(dialog: HTMLDialogElement, body: HTMLElement, id: string, headline?: string) {\n if (!headline) {\n dialog.setAttribute('aria-labelledby', body.id);\n return;\n }\n const heading = textElement('h2', headline);\n heading.id = `${id}-headline`;\n dialog.prepend(heading);\n dialog.setAttribute('aria-labelledby', heading.id);\n dialog.setAttribute('aria-describedby', body.id);\n }\n\n static Init() {\n Utils.onDocumentReady(() => {\n document.addEventListener('pointerdown', Dialogs._onPointerDown, { passive: true });\n document.addEventListener('pointerup', Dialogs._onPointerUp, { passive: true });\n document.addEventListener('pointercancel', Dialogs._onPointerCancel, { passive: true });\n });\n }\n\n static _onPointerDown(event: PointerEvent) {\n const dialog = Dialogs._isPrimaryPress(event) ? Dialogs._backdropDialog(event) : null;\n Dialogs._down =\n dialog && Dialogs._lightDismissible(dialog) && Dialogs._outside(event, dialog)\n ? { dialog, pointerId: event.pointerId }\n : null;\n }\n\n static _onPointerUp(event: PointerEvent) {\n const started = Dialogs._down;\n Dialogs._down = null;\n if (!started || started.pointerId !== event.pointerId) return;\n if (!started.dialog.isConnected || !started.dialog.open) return;\n if (!Dialogs._lightDismissible(started.dialog)) return;\n if (Dialogs._backdropDialog(event) !== started.dialog) return;\n if (Dialogs._outside(event, started.dialog)) {\n started.dialog.close();\n }\n }\n\n static _onPointerCancel() {\n Dialogs._down = null;\n }\n\n /** Backdrop hits retarget to the dialog itself, never a child. */\n private static _backdropDialog(event: Event): HTMLDialogElement | null {\n const target = Utils.eventTarget(event);\n if (!(target instanceof HTMLDialogElement) || !target.open) return null;\n return target;\n }\n\n private static _outside(event: PointerEvent, dialog: HTMLDialogElement): boolean {\n const rect = dialog.getBoundingClientRect();\n return (\n event.clientX < rect.left ||\n event.clientX > rect.right ||\n event.clientY < rect.top ||\n event.clientY > rect.bottom\n );\n }\n\n private static _isPrimaryPress(event: PointerEvent): boolean {\n if (!event.isPrimary) return false;\n return event.pointerType !== 'mouse' || event.button === 0;\n }\n\n // Read the attribute only. The IDL default for an unset closedby is\n // \"closerequest\" (Escape, no light dismiss) \u2014 treating that as an\n // author opt-out made every dialog undismissable from the scrim.\n // Native closedby=\"any\" already light-dismisses with the same \"both ends\n // outside\" rule, so leave it to the browser where it has one.\n private static _lightDismissible(dialog: HTMLDialogElement): boolean {\n const value = dialog.getAttribute('closedby');\n if (value === 'any') return !('closedBy' in HTMLDialogElement.prototype);\n return value !== 'none' && value !== 'closerequest';\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }