@expressivecss/expressive 0.15.0 → 0.16.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.
- package/CHANGELOG.md +1502 -1
- package/README.md +9 -8
- package/dist/css/expressive.css +19247 -11923
- package/dist/css/expressive.css.map +1 -1
- package/dist/css/expressive.min.css +1 -1
- package/dist/css/expressive.min.css.map +1 -1
- package/dist/fonts/LICENSE-noto-sans-arabic +93 -0
- package/dist/fonts/LICENSE-noto-sans-hebrew +93 -0
- package/dist/fonts/LICENSE-noto-sans-thai +93 -0
- package/dist/fonts/material-symbols-outlined.woff2 +0 -0
- package/dist/fonts/material-symbols-rounded.woff2 +0 -0
- package/dist/fonts/material-symbols-sharp.woff2 +0 -0
- package/dist/fonts/noto-sans-arabic-arabic-400.woff2 +0 -0
- package/dist/fonts/noto-sans-arabic-arabic-500.woff2 +0 -0
- package/dist/fonts/noto-sans-arabic-arabic-700.woff2 +0 -0
- package/dist/fonts/noto-sans-cyrillic-400.woff2 +0 -0
- package/dist/fonts/noto-sans-cyrillic-500.woff2 +0 -0
- package/dist/fonts/noto-sans-cyrillic-700.woff2 +0 -0
- package/dist/fonts/noto-sans-cyrillic-ext-400.woff2 +0 -0
- package/dist/fonts/noto-sans-cyrillic-ext-500.woff2 +0 -0
- package/dist/fonts/noto-sans-cyrillic-ext-700.woff2 +0 -0
- package/dist/fonts/noto-sans-devanagari-400.woff2 +0 -0
- package/dist/fonts/noto-sans-devanagari-500.woff2 +0 -0
- package/dist/fonts/noto-sans-devanagari-700.woff2 +0 -0
- package/dist/fonts/noto-sans-greek-400.woff2 +0 -0
- package/dist/fonts/noto-sans-greek-500.woff2 +0 -0
- package/dist/fonts/noto-sans-greek-700.woff2 +0 -0
- package/dist/fonts/noto-sans-greek-ext-400.woff2 +0 -0
- package/dist/fonts/noto-sans-greek-ext-500.woff2 +0 -0
- package/dist/fonts/noto-sans-greek-ext-700.woff2 +0 -0
- package/dist/fonts/noto-sans-hebrew-hebrew-400.woff2 +0 -0
- package/dist/fonts/noto-sans-hebrew-hebrew-500.woff2 +0 -0
- package/dist/fonts/noto-sans-hebrew-hebrew-700.woff2 +0 -0
- package/dist/fonts/noto-sans-latin-700.woff2 +0 -0
- package/dist/fonts/noto-sans-latin-ext-400.woff2 +0 -0
- package/dist/fonts/noto-sans-latin-ext-500.woff2 +0 -0
- package/dist/fonts/noto-sans-latin-ext-700.woff2 +0 -0
- package/dist/fonts/noto-sans-thai-thai-400.woff2 +0 -0
- package/dist/fonts/noto-sans-thai-thai-500.woff2 +0 -0
- package/dist/fonts/noto-sans-thai-thai-700.woff2 +0 -0
- package/dist/fonts/noto-sans-vietnamese-400.woff2 +0 -0
- package/dist/fonts/noto-sans-vietnamese-500.woff2 +0 -0
- package/dist/fonts/noto-sans-vietnamese-700.woff2 +0 -0
- package/dist/fonts/roboto-cyrillic-400.woff2 +0 -0
- package/dist/fonts/roboto-cyrillic-500.woff2 +0 -0
- package/dist/fonts/roboto-cyrillic-700.woff2 +0 -0
- package/dist/fonts/roboto-cyrillic-ext-400.woff2 +0 -0
- package/dist/fonts/roboto-cyrillic-ext-500.woff2 +0 -0
- package/dist/fonts/roboto-cyrillic-ext-700.woff2 +0 -0
- package/dist/fonts/roboto-greek-400.woff2 +0 -0
- package/dist/fonts/roboto-greek-500.woff2 +0 -0
- package/dist/fonts/roboto-greek-700.woff2 +0 -0
- package/dist/fonts/roboto-greek-ext-400.woff2 +0 -0
- package/dist/fonts/roboto-greek-ext-500.woff2 +0 -0
- package/dist/fonts/roboto-greek-ext-700.woff2 +0 -0
- package/dist/fonts/roboto-latin-700.woff2 +0 -0
- package/dist/fonts/roboto-latin-ext-400.woff2 +0 -0
- package/dist/fonts/roboto-latin-ext-500.woff2 +0 -0
- package/dist/fonts/roboto-latin-ext-700.woff2 +0 -0
- package/dist/fonts/roboto-vietnamese-400.woff2 +0 -0
- package/dist/fonts/roboto-vietnamese-500.woff2 +0 -0
- package/dist/fonts/roboto-vietnamese-700.woff2 +0 -0
- package/dist/js/chunks/chunk-2CS6TITK.mjs +219 -0
- package/dist/js/chunks/chunk-2CS6TITK.mjs.map +7 -0
- package/dist/js/chunks/chunk-2RLBDFH4.mjs +108 -0
- package/dist/js/chunks/chunk-2RLBDFH4.mjs.map +7 -0
- package/dist/js/chunks/chunk-3L3QIYLC.mjs +85 -0
- package/dist/js/chunks/chunk-3L3QIYLC.mjs.map +7 -0
- package/dist/js/chunks/chunk-4EWGD4V2.mjs +75 -0
- package/dist/js/chunks/chunk-4EWGD4V2.mjs.map +7 -0
- package/dist/js/chunks/chunk-4IKVPCSU.mjs +7 -0
- package/dist/js/chunks/chunk-4IKVPCSU.mjs.map +7 -0
- package/dist/js/chunks/chunk-4PIXLDNJ.mjs +127 -0
- package/dist/js/chunks/chunk-4PIXLDNJ.mjs.map +7 -0
- package/dist/js/chunks/{chunk-KVJAVDBC.mjs → chunk-4QUCNFSD.mjs} +64 -113
- package/dist/js/chunks/chunk-4QUCNFSD.mjs.map +7 -0
- package/dist/js/chunks/{chunk-UETTGDLI.mjs → chunk-4TRZ2AER.mjs} +35 -41
- package/dist/js/chunks/chunk-4TRZ2AER.mjs.map +7 -0
- package/dist/js/chunks/{chunk-C6CHEWYP.mjs → chunk-5KIHWJI2.mjs} +40 -26
- package/dist/js/chunks/chunk-5KIHWJI2.mjs.map +7 -0
- package/dist/js/chunks/{chunk-L27Q6ZMI.mjs → chunk-67ZPPKXS.mjs} +20 -33
- package/dist/js/chunks/chunk-67ZPPKXS.mjs.map +7 -0
- package/dist/js/chunks/{chunk-XAEAEHIX.mjs → chunk-6FSEUFVW.mjs} +39 -26
- package/dist/js/chunks/chunk-6FSEUFVW.mjs.map +7 -0
- package/dist/js/chunks/chunk-752ADW4M.mjs +225 -0
- package/dist/js/chunks/chunk-752ADW4M.mjs.map +7 -0
- package/dist/js/chunks/{chunk-CK2XCICY.mjs → chunk-75E5EDJF.mjs} +3 -11
- package/dist/js/chunks/chunk-75E5EDJF.mjs.map +7 -0
- package/dist/js/chunks/{chunk-KHXZ2A4K.mjs → chunk-7NLUI3RR.mjs} +139 -66
- package/dist/js/chunks/chunk-7NLUI3RR.mjs.map +7 -0
- package/dist/js/chunks/chunk-7W7TV6NY.mjs +108 -0
- package/dist/js/chunks/chunk-7W7TV6NY.mjs.map +7 -0
- package/dist/js/chunks/chunk-7YQBHTK3.mjs +225 -0
- package/dist/js/chunks/chunk-7YQBHTK3.mjs.map +7 -0
- package/dist/js/chunks/chunk-7YZ5CN3V.mjs +33 -0
- package/dist/js/chunks/chunk-7YZ5CN3V.mjs.map +7 -0
- package/dist/js/chunks/chunk-AI73GJKG.mjs +28 -0
- package/dist/js/chunks/chunk-AI73GJKG.mjs.map +7 -0
- package/dist/js/chunks/{chunk-LQWUDNHZ.mjs → chunk-ANKFWNWT.mjs} +21 -45
- package/dist/js/chunks/chunk-ANKFWNWT.mjs.map +7 -0
- package/dist/js/chunks/{chunk-5CEAOLUA.mjs → chunk-B7DQFHA5.mjs} +30 -47
- package/dist/js/chunks/chunk-B7DQFHA5.mjs.map +7 -0
- package/dist/js/chunks/chunk-BIGU5RCJ.mjs +153 -0
- package/dist/js/chunks/chunk-BIGU5RCJ.mjs.map +7 -0
- package/dist/js/chunks/{chunk-VGNYF6FB.mjs → chunk-BPF3I2MN.mjs} +109 -24
- package/dist/js/chunks/chunk-BPF3I2MN.mjs.map +7 -0
- package/dist/js/chunks/chunk-CMGXGYUC.mjs +74 -0
- package/dist/js/chunks/chunk-CMGXGYUC.mjs.map +7 -0
- package/dist/js/chunks/{chunk-NUHMOAOY.mjs → chunk-CSYWKEK3.mjs} +310 -196
- package/dist/js/chunks/chunk-CSYWKEK3.mjs.map +7 -0
- package/dist/js/chunks/chunk-CZSQHXEV.mjs +227 -0
- package/dist/js/chunks/chunk-CZSQHXEV.mjs.map +7 -0
- package/dist/js/chunks/chunk-DZYVU75J.mjs +121 -0
- package/dist/js/chunks/chunk-DZYVU75J.mjs.map +7 -0
- package/dist/js/chunks/{chunk-74MXKKLN.mjs → chunk-EC26RU2D.mjs} +11 -29
- package/dist/js/chunks/chunk-EC26RU2D.mjs.map +7 -0
- package/dist/js/chunks/{chunk-WDK4T63U.mjs → chunk-EVCVFEV3.mjs} +235 -146
- package/dist/js/chunks/chunk-EVCVFEV3.mjs.map +7 -0
- package/dist/js/chunks/chunk-FCNF4GRJ.mjs +445 -0
- package/dist/js/chunks/chunk-FCNF4GRJ.mjs.map +7 -0
- package/dist/js/chunks/chunk-GCWWEZKO.mjs +342 -0
- package/dist/js/chunks/chunk-GCWWEZKO.mjs.map +7 -0
- package/dist/js/chunks/chunk-GNRSYMVH.mjs +1 -0
- package/dist/js/chunks/chunk-GVZQH2H5.mjs +54 -0
- package/dist/js/chunks/chunk-GVZQH2H5.mjs.map +7 -0
- package/dist/js/chunks/chunk-GWZ76SR4.mjs +435 -0
- package/dist/js/chunks/chunk-GWZ76SR4.mjs.map +7 -0
- package/dist/js/chunks/{chunk-PDG64UHF.mjs → chunk-ILDRRG7T.mjs} +21 -23
- package/dist/js/chunks/chunk-ILDRRG7T.mjs.map +7 -0
- package/dist/js/chunks/chunk-INLZWHLY.mjs +80 -0
- package/dist/js/chunks/chunk-INLZWHLY.mjs.map +7 -0
- package/dist/js/chunks/chunk-JUKBBN6P.mjs +175 -0
- package/dist/js/chunks/chunk-JUKBBN6P.mjs.map +7 -0
- package/dist/js/chunks/chunk-KYIEG4U3.mjs +730 -0
- package/dist/js/chunks/chunk-KYIEG4U3.mjs.map +7 -0
- package/dist/js/chunks/{chunk-BGZLF6JZ.mjs → chunk-KZPSAXIU.mjs} +142 -32
- package/dist/js/chunks/chunk-KZPSAXIU.mjs.map +7 -0
- package/dist/js/chunks/chunk-LDXCC2L3.mjs +438 -0
- package/dist/js/chunks/chunk-LDXCC2L3.mjs.map +7 -0
- package/dist/js/chunks/chunk-NAC72P7R.mjs +137 -0
- package/dist/js/chunks/chunk-NAC72P7R.mjs.map +7 -0
- package/dist/js/chunks/chunk-NBJAUGPP.mjs +244 -0
- package/dist/js/chunks/chunk-NBJAUGPP.mjs.map +7 -0
- package/dist/js/chunks/chunk-NNHVANQA.mjs +113 -0
- package/dist/js/chunks/chunk-NNHVANQA.mjs.map +7 -0
- package/dist/js/chunks/chunk-NVQ5EHCU.mjs +376 -0
- package/dist/js/chunks/chunk-NVQ5EHCU.mjs.map +7 -0
- package/dist/js/chunks/{chunk-DXGRXYYL.mjs → chunk-OP43LLIC.mjs} +28 -45
- package/dist/js/chunks/chunk-OP43LLIC.mjs.map +7 -0
- package/dist/js/chunks/chunk-OUCHKSAW.mjs +63 -0
- package/dist/js/chunks/chunk-OUCHKSAW.mjs.map +7 -0
- package/dist/js/chunks/{chunk-TSZYSW7F.mjs → chunk-OYNUDOHR.mjs} +19 -47
- package/dist/js/chunks/chunk-OYNUDOHR.mjs.map +7 -0
- package/dist/js/chunks/{chunk-UAZSDUVP.mjs → chunk-P6DRQ6KS.mjs} +36 -30
- package/dist/js/chunks/chunk-P6DRQ6KS.mjs.map +7 -0
- package/dist/js/chunks/chunk-PA7NU5AK.mjs +99 -0
- package/dist/js/chunks/chunk-PA7NU5AK.mjs.map +7 -0
- package/dist/js/chunks/chunk-QACZ6TUP.mjs +224 -0
- package/dist/js/chunks/chunk-QACZ6TUP.mjs.map +7 -0
- package/dist/js/chunks/{chunk-GJL6GCIU.mjs → chunk-QXKWVHBD.mjs} +265 -161
- package/dist/js/chunks/chunk-QXKWVHBD.mjs.map +7 -0
- package/dist/js/chunks/{chunk-X4ISMKE2.mjs → chunk-ROH2HDB4.mjs} +7 -6
- package/dist/js/chunks/chunk-ROH2HDB4.mjs.map +7 -0
- package/dist/js/chunks/chunk-S23RJ3XY.mjs +86 -0
- package/dist/js/chunks/chunk-S23RJ3XY.mjs.map +7 -0
- package/dist/js/chunks/{chunk-SMY7GJSS.mjs → chunk-SPPHF7YZ.mjs} +36 -29
- package/dist/js/chunks/chunk-SPPHF7YZ.mjs.map +7 -0
- package/dist/js/chunks/chunk-T3BNSRP3.mjs +152 -0
- package/dist/js/chunks/chunk-T3BNSRP3.mjs.map +7 -0
- package/dist/js/chunks/chunk-TFABTUAZ.mjs +108 -0
- package/dist/js/chunks/chunk-TFABTUAZ.mjs.map +7 -0
- package/dist/js/chunks/chunk-U4B3VHFS.mjs +507 -0
- package/dist/js/chunks/chunk-U4B3VHFS.mjs.map +7 -0
- package/dist/js/chunks/chunk-UGJHCHXG.mjs +341 -0
- package/dist/js/chunks/chunk-UGJHCHXG.mjs.map +7 -0
- package/dist/js/chunks/chunk-VFV75DHF.mjs +70 -0
- package/dist/js/chunks/chunk-VFV75DHF.mjs.map +7 -0
- package/dist/js/chunks/{chunk-ZX6M7SWO.mjs → chunk-VGY4M57S.mjs} +266 -120
- package/dist/js/chunks/chunk-VGY4M57S.mjs.map +7 -0
- package/dist/js/chunks/chunk-VH4BMAZS.mjs +167 -0
- package/dist/js/chunks/chunk-VH4BMAZS.mjs.map +7 -0
- package/dist/js/chunks/chunk-VJVQIXHC.mjs +123 -0
- package/dist/js/chunks/chunk-VJVQIXHC.mjs.map +7 -0
- package/dist/js/chunks/{chunk-SFI2U4YW.mjs → chunk-VMY55K2X.mjs} +76 -109
- package/dist/js/chunks/chunk-VMY55K2X.mjs.map +7 -0
- package/dist/js/chunks/{chunk-KUFHW3DS.mjs → chunk-VR3L2WN5.mjs} +11 -17
- package/dist/js/chunks/chunk-VR3L2WN5.mjs.map +7 -0
- package/dist/js/chunks/chunk-W6FAL3TI.mjs +38 -0
- package/dist/js/chunks/chunk-W6FAL3TI.mjs.map +7 -0
- package/dist/js/chunks/chunk-WU7XJ4RR.mjs +450 -0
- package/dist/js/chunks/chunk-WU7XJ4RR.mjs.map +7 -0
- package/dist/js/chunks/chunk-X7SDA2J5.mjs +116 -0
- package/dist/js/chunks/chunk-X7SDA2J5.mjs.map +7 -0
- package/dist/js/chunks/chunk-Y6H2X7ZC.mjs +209 -0
- package/dist/js/chunks/chunk-Y6H2X7ZC.mjs.map +7 -0
- package/dist/js/chunks/chunk-Y6TLRA3U.mjs +129 -0
- package/dist/js/chunks/chunk-Y6TLRA3U.mjs.map +7 -0
- package/dist/js/chunks/chunk-Z4GICXR2.mjs +190 -0
- package/dist/js/chunks/chunk-Z4GICXR2.mjs.map +7 -0
- package/dist/js/chunks/chunk-Z4OARDZ7.mjs +442 -0
- package/dist/js/chunks/chunk-Z4OARDZ7.mjs.map +7 -0
- package/dist/js/chunks/{chunk-FM5CZOUB.mjs → chunk-ZJNLAGY5.mjs} +19 -30
- package/dist/js/chunks/chunk-ZJNLAGY5.mjs.map +7 -0
- package/dist/js/chunks/chunk-ZKWUWBUB.mjs +81 -0
- package/dist/js/chunks/chunk-ZKWUWBUB.mjs.map +7 -0
- package/dist/js/chunks/chunk-ZM3XBHWV.mjs +746 -0
- package/dist/js/chunks/chunk-ZM3XBHWV.mjs.map +7 -0
- package/dist/js/chunks/chunk-ZO6ZLHFF.mjs +48 -0
- package/dist/js/chunks/chunk-ZO6ZLHFF.mjs.map +7 -0
- package/dist/js/chunks/chunk-ZVLOUDIJ.mjs +251 -0
- package/dist/js/chunks/chunk-ZVLOUDIJ.mjs.map +7 -0
- package/dist/js/expressive.cjs +10613 -4327
- package/dist/js/expressive.cjs.map +4 -4
- package/dist/js/expressive.js +10613 -4327
- package/dist/js/expressive.js.map +4 -4
- package/dist/js/expressive.min.js +23 -22
- package/dist/js/expressive.min.js.map +4 -4
- package/dist/js/expressive.mjs +182 -71
- package/dist/js/expressive.mjs.map +2 -2
- package/dist/js/internal/behaviors/bottomSheets.mjs +4 -3
- package/dist/js/internal/behaviors/copy.mjs +9 -0
- package/dist/js/internal/behaviors/copy.mjs.map +7 -0
- package/dist/js/internal/behaviors/dataTables.mjs +10 -0
- package/dist/js/internal/behaviors/dataTables.mjs.map +7 -0
- package/dist/js/internal/behaviors/dialogs.mjs +2 -2
- package/dist/js/internal/behaviors/forms.mjs +2 -2
- package/dist/js/internal/behaviors/imageCompare.mjs +8 -0
- package/dist/js/internal/behaviors/imageCompare.mjs.map +7 -0
- package/dist/js/internal/behaviors/lists.mjs +8 -0
- package/dist/js/internal/behaviors/lists.mjs.map +7 -0
- package/dist/js/internal/behaviors/paneResize.mjs +8 -0
- package/dist/js/internal/behaviors/paneResize.mjs.map +7 -0
- package/dist/js/internal/behaviors/sheetDrag.mjs +7 -2
- package/dist/js/internal/behaviors/sideSheets.mjs +4 -3
- package/dist/js/internal/behaviors/sortable.mjs +8 -0
- package/dist/js/internal/behaviors/sortable.mjs.map +7 -0
- package/dist/js/internal/behaviors/theme.mjs +8 -0
- package/dist/js/internal/behaviors/theme.mjs.map +7 -0
- package/dist/js/internal/behaviors/tour.mjs +8 -0
- package/dist/js/internal/behaviors/tour.mjs.map +7 -0
- package/dist/js/internal/behaviors/transferList.mjs +8 -0
- package/dist/js/internal/behaviors/transferList.mjs.map +7 -0
- package/dist/js/internal/components/appBar.mjs +3 -2
- package/dist/js/internal/components/autocomplete.mjs +4 -4
- package/dist/js/internal/components/backToTop.mjs +9 -0
- package/dist/js/internal/components/backToTop.mjs.map +7 -0
- package/dist/js/internal/components/barChart.mjs +5 -4
- package/dist/js/internal/components/buttonGroup.mjs +3 -2
- package/dist/js/internal/components/buttons.mjs +3 -3
- package/dist/js/internal/components/cards.mjs +3 -3
- package/dist/js/internal/components/carousel.mjs +3 -3
- package/dist/js/internal/components/cascader.mjs +10 -0
- package/dist/js/internal/components/cascader.mjs.map +7 -0
- package/dist/js/internal/components/characterCounter.mjs +3 -2
- package/dist/js/internal/components/chips.mjs +6 -5
- package/dist/js/internal/components/colorPicker.mjs +9 -0
- package/dist/js/internal/components/colorPicker.mjs.map +7 -0
- package/dist/js/internal/components/columnChart.mjs +4 -3
- package/dist/js/internal/components/commandPalette.mjs +3 -3
- package/dist/js/internal/components/confetti.mjs +3 -2
- package/dist/js/internal/components/currencyInput.mjs +9 -0
- package/dist/js/internal/components/currencyInput.mjs.map +7 -0
- package/dist/js/internal/components/datepicker.mjs +11 -8
- package/dist/js/internal/components/expandingCard.mjs +3 -3
- package/dist/js/internal/components/funnelChart.mjs +10 -0
- package/dist/js/internal/components/funnelChart.mjs.map +7 -0
- package/dist/js/internal/components/heatmapChart.mjs +4 -3
- package/dist/js/internal/components/hoverCard.mjs +9 -0
- package/dist/js/internal/components/hoverCard.mjs.map +7 -0
- package/dist/js/internal/components/index.mjs +131 -66
- package/dist/js/internal/components/inputMask.mjs +9 -0
- package/dist/js/internal/components/inputMask.mjs.map +7 -0
- package/dist/js/internal/components/keypad.mjs +3 -3
- package/dist/js/internal/components/lightbox.mjs +3 -3
- package/dist/js/internal/components/lineChart.mjs +25 -4
- package/dist/js/internal/components/loadingOverlay.mjs +9 -0
- package/dist/js/internal/components/loadingOverlay.mjs.map +7 -0
- package/dist/js/internal/components/mapView.mjs +3 -3
- package/dist/js/internal/components/menu.mjs +3 -3
- package/dist/js/internal/components/menubar.mjs +10 -0
- package/dist/js/internal/components/menubar.mjs.map +7 -0
- package/dist/js/internal/components/messageScroller.mjs +3 -3
- package/dist/js/internal/components/mixedChart.mjs +5 -4
- package/dist/js/internal/components/navigationRail.mjs +3 -2
- package/dist/js/internal/components/particles.mjs +3 -2
- package/dist/js/internal/components/pieChart.mjs +4 -3
- package/dist/js/internal/components/pullToRefresh.mjs +9 -0
- package/dist/js/internal/components/pullToRefresh.mjs.map +7 -0
- package/dist/js/internal/components/questionnaire.mjs +3 -3
- package/dist/js/internal/components/radarChart.mjs +4 -3
- package/dist/js/internal/components/radialChart.mjs +4 -3
- package/dist/js/internal/components/registry.mjs +59 -41
- package/dist/js/internal/components/richTextEditor.mjs +3 -3
- package/dist/js/internal/components/sankeyChart.mjs +10 -0
- package/dist/js/internal/components/sankeyChart.mjs.map +7 -0
- package/dist/js/internal/components/scatterChart.mjs +10 -0
- package/dist/js/internal/components/scatterChart.mjs.map +7 -0
- package/dist/js/internal/components/scrollspy.mjs +3 -2
- package/dist/js/internal/components/select.mjs +4 -4
- package/dist/js/internal/components/showMore.mjs +9 -0
- package/dist/js/internal/components/showMore.mjs.map +7 -0
- package/dist/js/internal/components/slider.mjs +3 -3
- package/dist/js/internal/components/snackbar.mjs +2 -2
- package/dist/js/internal/components/swipeActions.mjs +9 -0
- package/dist/js/internal/components/swipeActions.mjs.map +7 -0
- package/dist/js/internal/components/tabs.mjs +3 -4
- package/dist/js/internal/components/timepicker.mjs +5 -4
- package/dist/js/internal/components/tooltip.mjs +3 -3
- package/dist/js/internal/components/treeSelect.mjs +13 -0
- package/dist/js/internal/components/treeSelect.mjs.map +7 -0
- package/dist/js/internal/components/treemapChart.mjs +10 -0
- package/dist/js/internal/components/treemapChart.mjs.map +7 -0
- package/dist/js/internal/core/component.mjs +2 -1
- package/dist/js/internal/core/formControl.mjs +12 -0
- package/dist/js/internal/core/formControl.mjs.map +7 -0
- package/dist/js/internal/core/spring.mjs +11 -0
- package/dist/js/internal/core/spring.mjs.map +7 -0
- package/dist/js/internal/core/utils.mjs +11 -3
- package/dist/js/internal/plugins/dockedDisplayPlugin.mjs +2 -2
- package/dist/js/internal/plugins/modalDisplayPlugin.mjs +13 -0
- package/dist/js/internal/plugins/modalDisplayPlugin.mjs.map +7 -0
- package/dist/js/modular.mjs +173 -71
- package/dist/types/behaviors/bottomSheets.d.ts +19 -3
- package/dist/types/behaviors/copy.d.ts +18 -0
- package/dist/types/behaviors/dataTables.d.ts +129 -0
- package/dist/types/behaviors/dialogs.d.ts +27 -1
- package/dist/types/behaviors/forms.d.ts +68 -2
- package/dist/types/behaviors/imageCompare.d.ts +12 -0
- package/dist/types/behaviors/lists.d.ts +12 -0
- package/dist/types/behaviors/paneResize.d.ts +29 -0
- package/dist/types/behaviors/sheetDrag.d.ts +18 -0
- package/dist/types/behaviors/sideSheets.d.ts +1 -1
- package/dist/types/behaviors/sortable.d.ts +28 -0
- package/dist/types/behaviors/theme.d.ts +22 -0
- package/dist/types/behaviors/tour.d.ts +36 -0
- package/dist/types/behaviors/transferList.d.ts +51 -0
- package/dist/types/components/appBar.d.ts +5 -6
- package/dist/types/components/autocomplete.d.ts +91 -17
- package/dist/types/components/backToTop.d.ts +36 -0
- package/dist/types/components/barChart.d.ts +3 -6
- package/dist/types/components/buttonGroup.d.ts +2 -4
- package/dist/types/components/buttons.d.ts +5 -5
- package/dist/types/components/cards.d.ts +3 -16
- package/dist/types/components/carousel.d.ts +9 -15
- package/dist/types/components/cascader.d.ts +130 -0
- package/dist/types/components/characterCounter.d.ts +2 -15
- package/dist/types/components/chips.d.ts +65 -19
- package/dist/types/components/colorPicker.d.ts +42 -0
- package/dist/types/components/columnChart.d.ts +23 -10
- package/dist/types/components/commandPalette.d.ts +11 -16
- package/dist/types/components/confetti.d.ts +2 -4
- package/dist/types/components/currencyInput.d.ts +59 -0
- package/dist/types/components/datepicker.d.ts +56 -32
- package/dist/types/components/expandingCard.d.ts +4 -6
- package/dist/types/components/funnelChart.d.ts +38 -0
- package/dist/types/components/heatmapChart.d.ts +39 -8
- package/dist/types/components/hoverCard.d.ts +58 -0
- package/dist/types/components/index.d.ts +16 -1
- package/dist/types/components/inputMask.d.ts +30 -0
- package/dist/types/components/keypad.d.ts +38 -6
- package/dist/types/components/lightbox.d.ts +14 -20
- package/dist/types/components/lineChart.d.ts +172 -10
- package/dist/types/components/loadingOverlay.d.ts +42 -0
- package/dist/types/components/mapView.d.ts +26 -17
- package/dist/types/components/menu.d.ts +60 -22
- package/dist/types/components/menubar.d.ts +37 -0
- package/dist/types/components/messageScroller.d.ts +2 -14
- package/dist/types/components/mixedChart.d.ts +15 -6
- package/dist/types/components/navigationRail.d.ts +16 -5
- package/dist/types/components/particles.d.ts +8 -4
- package/dist/types/components/pieChart.d.ts +32 -7
- package/dist/types/components/pullToRefresh.d.ts +80 -0
- package/dist/types/components/questionnaire.d.ts +58 -16
- package/dist/types/components/radarChart.d.ts +10 -6
- package/dist/types/components/radialChart.d.ts +58 -7
- package/dist/types/components/registry.d.ts +73 -3
- package/dist/types/components/richTextEditor.d.ts +6 -14
- package/dist/types/components/sankeyChart.d.ts +72 -0
- package/dist/types/components/scatterChart.d.ts +102 -0
- package/dist/types/components/scrollspy.d.ts +3 -5
- package/dist/types/components/select.d.ts +43 -30
- package/dist/types/components/showMore.d.ts +51 -0
- package/dist/types/components/slider.d.ts +3 -15
- package/dist/types/components/snackbar.d.ts +61 -0
- package/dist/types/components/swipeActions.d.ts +81 -0
- package/dist/types/components/tabs.d.ts +89 -27
- package/dist/types/components/timepicker.d.ts +113 -21
- package/dist/types/components/tooltip.d.ts +56 -20
- package/dist/types/components/treeSelect.d.ts +106 -0
- package/dist/types/components/treemapChart.d.ts +56 -0
- package/dist/types/core/component.d.ts +43 -25
- package/dist/types/core/formControl.d.ts +21 -0
- package/dist/types/core/spring.d.ts +20 -0
- package/dist/types/core/utils.d.ts +85 -72
- package/dist/types/modular.d.ts +33 -1
- package/dist/types/plugins/dockedDisplayPlugin.d.ts +10 -8
- package/dist/types/plugins/modalDisplayPlugin.d.ts +32 -0
- package/package.json +10 -8
- package/src/sass/README.md +27 -18
- package/src/sass/abstracts/_elevation.scss +13 -7
- package/src/sass/abstracts/_index.scss +1 -0
- package/src/sass/abstracts/_mixins.scss +422 -36
- package/src/sass/abstracts/_spring.scss +63 -0
- package/src/sass/abstracts/_variables.scss +39 -21
- package/src/sass/base/_fonts.scss +61 -48
- package/src/sass/base/_global.scss +104 -24
- package/src/sass/base/_index.scss +2 -0
- package/src/sass/base/_normalize.scss +59 -114
- package/src/sass/base/_print.scss +21 -0
- package/src/sass/base/_prose.scss +68 -0
- package/src/sass/base/_typography.scss +9 -5
- package/src/sass/components/_accordion.scss +9 -16
- package/src/sass/components/_alert.scss +102 -0
- package/src/sass/components/_aura.scss +8 -3
- package/src/sass/components/_avatar.scss +3 -3
- package/src/sass/components/_back-to-top.scss +38 -0
- package/src/sass/components/_badges.scss +6 -5
- package/src/sass/components/_bar-chart.scss +41 -19
- package/src/sass/components/_bottom-sheet.scss +44 -16
- package/src/sass/components/_breadcrumb.scss +8 -1
- package/src/sass/components/_button-groups.scss +15 -25
- package/src/sass/components/_buttons.scss +156 -63
- package/src/sass/components/_calendar.scss +246 -0
- package/src/sass/components/_cards.scss +36 -44
- package/src/sass/components/_carousel.scss +27 -103
- package/src/sass/components/_cascader.scss +142 -0
- package/src/sass/components/_chips.scss +36 -46
- package/src/sass/components/_column-chart.scss +19 -12
- package/src/sass/components/_command-palette.scss +4 -7
- package/src/sass/components/_confetti.scss +0 -2
- package/src/sass/components/_countdown.scss +1 -1
- package/src/sass/components/_data-table.scss +162 -25
- package/src/sass/components/_datepicker.scss +54 -40
- package/src/sass/components/_description-list.scss +85 -0
- package/src/sass/components/_dialog.scss +42 -41
- package/src/sass/components/_docked-display.scss +1 -3
- package/src/sass/components/_drag-handle.scss +16 -20
- package/src/sass/components/_expanding-card.scss +20 -9
- package/src/sass/components/_fab-menu.scss +44 -32
- package/src/sass/components/_funnel-chart.scss +124 -0
- package/src/sass/components/_heatmap-chart.scss +111 -22
- package/src/sass/components/_icon-buttons.scss +7 -7
- package/src/sass/components/_icons-material-design.scss +2 -2
- package/src/sass/components/_image-compare.scss +108 -0
- package/src/sass/components/_index.scss +20 -0
- package/src/sass/components/_keypad.scss +39 -19
- package/src/sass/components/_kpi.scss +6 -11
- package/src/sass/components/_lightbox.scss +24 -13
- package/src/sass/components/_line-chart.scss +16 -2
- package/src/sass/components/_list.scss +59 -14
- package/src/sass/components/_loading-indicator.scss +1 -0
- package/src/sass/components/_loading-overlay.scss +105 -0
- package/src/sass/components/_map.scss +33 -11
- package/src/sass/components/_marquee.scss +3 -2
- package/src/sass/components/_mega-menu.scss +137 -0
- package/src/sass/components/_menu.scss +143 -123
- package/src/sass/components/_menubar.scss +59 -0
- package/src/sass/components/_message-scroller.scss +2 -2
- package/src/sass/components/_message.scss +3 -3
- package/src/sass/components/_mixed-chart.scss +37 -9
- package/src/sass/components/_modal-display.scss +21 -0
- package/src/sass/components/_navbar.scss +34 -20
- package/src/sass/components/_navigation-bar.scss +15 -77
- package/src/sass/components/_navigation-rail.scss +151 -92
- package/src/sass/components/_org-chart.scss +192 -0
- package/src/sass/components/_page-footer.scss +1 -1
- package/src/sass/components/_pagination.scss +6 -13
- package/src/sass/components/_panes.scss +32 -26
- package/src/sass/components/_particles.scss +0 -2
- package/src/sass/components/_pie-chart.scss +91 -11
- package/src/sass/components/_popover.scss +18 -5
- package/src/sass/components/_progress.scss +152 -31
- package/src/sass/components/_pull-to-refresh.scss +90 -0
- package/src/sass/components/_questionnaire.scss +74 -3
- package/src/sass/components/_radar-chart.scss +38 -10
- package/src/sass/components/_radial-chart.scss +113 -5
- package/src/sass/components/_rich-text-editor.scss +2 -2
- package/src/sass/components/_sankey-chart.scss +114 -0
- package/src/sass/components/_scatter-chart.scss +153 -0
- package/src/sass/components/_scrim.scss +0 -2
- package/src/sass/components/_scrollspy.scss +0 -2
- package/src/sass/components/_search.scss +26 -22
- package/src/sass/components/_show-more.scss +8 -0
- package/src/sass/components/_side-sheet.scss +23 -37
- package/src/sass/components/_skeleton.scss +2 -4
- package/src/sass/components/_snackbar.scss +27 -21
- package/src/sass/components/_split-button.scss +5 -5
- package/src/sass/components/_stat.scss +3 -8
- package/src/sass/components/_stepper.scss +1 -1
- package/src/sass/components/_swipe-actions.scss +71 -0
- package/src/sass/components/_tabs.scss +51 -32
- package/src/sass/components/_timeline.scss +12 -12
- package/src/sass/components/_timepicker.scss +109 -78
- package/src/sass/components/_toolbar.scss +35 -43
- package/src/sass/components/_tooltip.scss +21 -12
- package/src/sass/components/_tour.scss +89 -0
- package/src/sass/components/_transfer-list.scss +73 -0
- package/src/sass/components/_transitions.scss +4 -4
- package/src/sass/components/_tree.scss +3 -16
- package/src/sass/components/_treemap-chart.scss +122 -0
- package/src/sass/components/forms/_checkboxes.scss +106 -24
- package/src/sass/components/forms/_color-picker.scss +135 -0
- package/src/sass/components/forms/_color-swatches.scss +85 -0
- package/src/sass/components/forms/_drop-zone.scss +15 -9
- package/src/sass/components/forms/_fieldset.scss +7 -7
- package/src/sass/components/forms/_file-input.scss +6 -8
- package/src/sass/components/forms/_index.scss +3 -1
- package/src/sass/components/forms/_input-fields.scss +254 -90
- package/src/sass/components/forms/_radio-buttons.scss +33 -94
- package/src/sass/components/forms/_rating.scss +2 -32
- package/src/sass/components/forms/_select.scss +199 -20
- package/src/sass/components/forms/_slider.scss +91 -94
- package/src/sass/components/forms/_switches.scss +53 -164
- package/src/sass/custom.scss +10 -1
- package/src/sass/expressive.scss +3 -63
- package/src/sass/tokens/_contrast.scss +94 -0
- package/src/sass/tokens/_elevation.scss +16 -0
- package/src/sass/tokens/_index.scss +5 -0
- package/src/sass/tokens/_motion.scss +109 -0
- package/src/sass/tokens/_reference.scss +72 -141
- package/src/sass/tokens/_shape.scss +38 -0
- package/src/sass/tokens/_stacking.scss +27 -0
- package/src/sass/tokens/_state.scss +0 -2
- package/src/sass/tokens/_theme.scss +10 -1
- package/src/sass/tokens/_vibrant.scss +2 -5
- package/src/sass/utilities/_defer-render.scss +17 -0
- package/src/sass/utilities/_helpers.scss +183 -26
- package/src/sass/utilities/_index.scss +1 -0
- package/src/sass/utilities/_scroll-area.scss +0 -2
- package/src/sass/utilities/_spacing.scss +52 -34
- package/src/sass/utilities/_typescale.scss +8 -1
- package/src/sass/utilities/_visibility.scss +47 -76
- package/src/sass/utilities/_z-depth.scss +7 -4
- package/dist/js/chunks/chunk-33QVDDGR.mjs +0 -270
- package/dist/js/chunks/chunk-33QVDDGR.mjs.map +0 -7
- package/dist/js/chunks/chunk-45FER6RI.mjs +0 -59
- package/dist/js/chunks/chunk-45FER6RI.mjs.map +0 -7
- package/dist/js/chunks/chunk-5CEAOLUA.mjs.map +0 -7
- package/dist/js/chunks/chunk-6VATUZC6.mjs +0 -295
- package/dist/js/chunks/chunk-6VATUZC6.mjs.map +0 -7
- package/dist/js/chunks/chunk-74MXKKLN.mjs.map +0 -7
- package/dist/js/chunks/chunk-AIURVCG6.mjs +0 -55
- package/dist/js/chunks/chunk-AIURVCG6.mjs.map +0 -7
- package/dist/js/chunks/chunk-BGZLF6JZ.mjs.map +0 -7
- package/dist/js/chunks/chunk-C6CHEWYP.mjs.map +0 -7
- package/dist/js/chunks/chunk-CK2XCICY.mjs.map +0 -7
- package/dist/js/chunks/chunk-CXXM2L4F.mjs +0 -344
- package/dist/js/chunks/chunk-CXXM2L4F.mjs.map +0 -7
- package/dist/js/chunks/chunk-DXGRXYYL.mjs.map +0 -7
- package/dist/js/chunks/chunk-FM5CZOUB.mjs.map +0 -7
- package/dist/js/chunks/chunk-GJL6GCIU.mjs.map +0 -7
- package/dist/js/chunks/chunk-K3HZMFMD.mjs +0 -135
- package/dist/js/chunks/chunk-K3HZMFMD.mjs.map +0 -7
- package/dist/js/chunks/chunk-KHXZ2A4K.mjs.map +0 -7
- package/dist/js/chunks/chunk-KQACNQ22.mjs +0 -7
- package/dist/js/chunks/chunk-KQACNQ22.mjs.map +0 -7
- package/dist/js/chunks/chunk-KUFHW3DS.mjs.map +0 -7
- package/dist/js/chunks/chunk-KVJAVDBC.mjs.map +0 -7
- package/dist/js/chunks/chunk-L27Q6ZMI.mjs.map +0 -7
- package/dist/js/chunks/chunk-LQWUDNHZ.mjs.map +0 -7
- package/dist/js/chunks/chunk-M372EDXD.mjs +0 -322
- package/dist/js/chunks/chunk-M372EDXD.mjs.map +0 -7
- package/dist/js/chunks/chunk-M3MURWMB.mjs +0 -82
- package/dist/js/chunks/chunk-M3MURWMB.mjs.map +0 -7
- package/dist/js/chunks/chunk-NUHMOAOY.mjs.map +0 -7
- package/dist/js/chunks/chunk-OWG3LMUL.mjs +0 -169
- package/dist/js/chunks/chunk-OWG3LMUL.mjs.map +0 -7
- package/dist/js/chunks/chunk-PD6HYHAE.mjs +0 -48
- package/dist/js/chunks/chunk-PD6HYHAE.mjs.map +0 -7
- package/dist/js/chunks/chunk-PDG64UHF.mjs.map +0 -7
- package/dist/js/chunks/chunk-PO3AXVR3.mjs +0 -546
- package/dist/js/chunks/chunk-PO3AXVR3.mjs.map +0 -7
- package/dist/js/chunks/chunk-QYGK36OG.mjs +0 -181
- package/dist/js/chunks/chunk-QYGK36OG.mjs.map +0 -7
- package/dist/js/chunks/chunk-SFI2U4YW.mjs.map +0 -7
- package/dist/js/chunks/chunk-SMY7GJSS.mjs.map +0 -7
- package/dist/js/chunks/chunk-TCCA2HDG.mjs +0 -414
- package/dist/js/chunks/chunk-TCCA2HDG.mjs.map +0 -7
- package/dist/js/chunks/chunk-TSZYSW7F.mjs.map +0 -7
- package/dist/js/chunks/chunk-UAZSDUVP.mjs.map +0 -7
- package/dist/js/chunks/chunk-UBRZZWRA.mjs +0 -127
- package/dist/js/chunks/chunk-UBRZZWRA.mjs.map +0 -7
- package/dist/js/chunks/chunk-UCOE7ZDL.mjs +0 -287
- package/dist/js/chunks/chunk-UCOE7ZDL.mjs.map +0 -7
- package/dist/js/chunks/chunk-UETTGDLI.mjs.map +0 -7
- package/dist/js/chunks/chunk-UNCRDLP6.mjs +0 -136
- package/dist/js/chunks/chunk-UNCRDLP6.mjs.map +0 -7
- package/dist/js/chunks/chunk-VGNYF6FB.mjs.map +0 -7
- package/dist/js/chunks/chunk-VGPGBNGL.mjs +0 -68
- package/dist/js/chunks/chunk-VGPGBNGL.mjs.map +0 -7
- package/dist/js/chunks/chunk-VKAUVTQY.mjs +0 -1
- package/dist/js/chunks/chunk-VM4FTS7L.mjs +0 -48
- package/dist/js/chunks/chunk-VM4FTS7L.mjs.map +0 -7
- package/dist/js/chunks/chunk-WDK4T63U.mjs.map +0 -7
- package/dist/js/chunks/chunk-WOCCTVUF.mjs +0 -185
- package/dist/js/chunks/chunk-WOCCTVUF.mjs.map +0 -7
- package/dist/js/chunks/chunk-WQYN5L4E.mjs +0 -107
- package/dist/js/chunks/chunk-WQYN5L4E.mjs.map +0 -7
- package/dist/js/chunks/chunk-X4ISMKE2.mjs.map +0 -7
- package/dist/js/chunks/chunk-XAEAEHIX.mjs.map +0 -7
- package/dist/js/chunks/chunk-ZX6M7SWO.mjs.map +0 -7
- /package/dist/js/chunks/{chunk-VKAUVTQY.mjs.map → chunk-GNRSYMVH.mjs.map} +0 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/ts/components/autocomplete.ts"],
|
|
4
|
+
"sourcesContent": ["import { Utils } from '../core/utils';\nimport { Menu, MenuOptions } from './menu';\nimport { Component, BaseOptions } from '../core/component';\n\nexport interface AutocompleteData {\n /**\n * A primitive value that can be converted to string.\n * If \"text\" is not provided, it will also be used as \"option text\" as well\n */\n id: string | number;\n /**\n * This optional attribute is used as \"display value\" for the current entry.\n * When provided, it will also be taken into consideration by the standard search function.\n */\n text?: string;\n /**\n * This optional attribute is used to provide a valid image URL to the current option.\n */\n image?: string;\n /**\n * Optional attributes which describes the option.\n */\n description?: string;\n /**\n * Shows the entry dimmed and keeps every selection path from choosing or\n * removing it. The arrow keys skip it, and the result count leaves it out.\n * The `selected` option and `setMenuItems()` can still select it.\n */\n disabled?: boolean;\n /**\n * Lists the entry under this heading. Entries with the same group gather\n * where the group first appears in the results; entries without one stay\n * outside every group.\n */\n group?: string;\n}\n\nexport interface AutocompleteOptions extends BaseOptions {\n i18n: Partial<{\n loading: string;\n noResults: string;\n results: (count: number) => string;\n selected: (count: number) => string;\n create: (text: string) => string;\n }>;\n /**\n * Data object defining autocomplete options with\n * optional icon strings.\n */\n data: AutocompleteData[];\n /**\n * Flag which can be set if multiple values can be selected. The Result will be an Array.\n * @default false\n */\n isMultiSelect: boolean;\n /**\n * Callback for when autocompleted.\n */\n onAutocomplete: (entries: AutocompleteData[]) => void;\n /**\n * Minimum number of characters before autocomplete starts.\n * @default 1\n */\n minLength: number;\n /**\n * The height of the Menu which can be set via css-property.\n * @default '300px'\n */\n maxMenuHeight: string;\n /**\n * Function is called when the input text is altered and data can also be loaded asynchronously.\n * If the results are collected the items in the list can be updated via the function setMenuItems(collectedItems).\n * @param text Searched text.\n * @param autocomplete Current autocomplete instance.\n * @param signal Aborted when a newer search starts or the autocomplete is\n * destroyed. Pass it to `fetch()` so a slow, stale response never replaces\n * newer results.\n */\n onSearch: (text: string, autocomplete: Autocomplete, signal: AbortSignal) => void;\n /**\n * Milliseconds to wait after typing pauses before calling `onSearch`, so\n * remote data is fetched once per pause rather than once per key. A search\n * on focus never waits. `0` searches on every input.\n * @default 0\n */\n searchDelay: number;\n /**\n * Ends the list in an \"Add\" row when the typed text matches no suggestion\n * exactly. Choosing the row calls `onCreate` and fires `expressive:create`;\n * the selection does not change.\n * @default false\n */\n allowCreate: boolean;\n /**\n * Called when the person chooses the \"Add\" row.\n * @param text The typed text, trimmed.\n * @param autocomplete Current autocomplete instance.\n * @default null\n */\n onCreate: (text: string, autocomplete: Autocomplete) => void;\n /**\n * If true will render the key from each item directly as HTML.\n * User input MUST be properly sanitized first.\n * @default false\n */\n allowUnsafeHTML: boolean;\n /**\n * Pass options object to select menu initialization.\n * @default {}\n */\n menuOptions: Partial<MenuOptions>;\n /**\n * Predefined selected values\n */\n selected: number[] | string[];\n}\n\nconst _defaults: AutocompleteOptions = {\n i18n: {\n loading: 'Loading results.',\n noResults: 'No results.',\n results: count => `${count} ${count === 1 ? 'result' : 'results'} available.`,\n selected: count => `${count} ${count === 1 ? 'item' : 'items'} selected.`,\n create: text => `Add \"${text}\"`\n },\n data: [], // Autocomplete data set\n onAutocomplete: null, // Callback for when autocompleted\n menuOptions: {\n // Default menu options\n autoFocus: false,\n closeOnClick: false,\n coverTrigger: false\n },\n minLength: 1, // Min characters before autocomplete starts\n searchDelay: 0,\n allowCreate: false,\n onCreate: null,\n isMultiSelect: false,\n onSearch: (text: string, autocomplete: Autocomplete) => {\n const normSearch = text.toLocaleLowerCase();\n autocomplete.setMenuItems(\n autocomplete.options.data.filter((option) =>\n option.id.toString().toLocaleLowerCase().includes(normSearch)\n || option.text?.toLocaleLowerCase().includes(normSearch)\n )\n );\n },\n maxMenuHeight: '300px',\n allowUnsafeHTML: false,\n selected: []\n};\n\nexport class Autocomplete extends Component<AutocompleteOptions> {\n declare el: HTMLInputElement;\n /** If the autocomplete is open. */\n isOpen: boolean;\n /**\n * Whether the user left or dismissed the field since the last search, so\n * late results must not reopen it. A field nobody has focused yet counts.\n */\n private _left = true;\n /** Number of matching autocomplete options. */\n count: number;\n /** Index of the current selected option. */\n activeIndex: number;\n private oldVal: string;\n private $active: HTMLElement | null;\n private _openTimer: ReturnType<typeof setTimeout> | undefined;\n /** Aborts the running search when a newer one starts. */\n private _searchAbort: AbortController | undefined;\n /** The search waiting for typing to pause. */\n private _searchTimer: ReturnType<typeof setTimeout> | undefined;\n // Counts selections, so a callback that selects again silences the stale event.\n private _selection = 0;\n private _statusInfo: HTMLElement;\n private _announcer: HTMLElement;\n /** The last search returned no suggestions. A text change clears it until the next one returns. */\n private _noResults = false;\n\n /**\n * The active entry, for both the eye and the screen reader. The class alone\n * was invisible to assistive technology; aria-activedescendant on the input\n * is what reports the move.\n *\n * Deliberately does not touch aria-selected. Active and selected are two\n * different things - in a multi-select the checkboxes track real choices,\n * and folding the highlight into aria-selected would announce a committed\n * choice as unselected the moment the user arrowed past it.\n */\n private _setActive(item: HTMLElement | null) {\n this.$active?.classList.remove('active');\n this.$active = item;\n if (item) {\n item.classList.add('active');\n this.el.setAttribute('aria-activedescendant', item.id);\n } else {\n this.el.removeAttribute('aria-activedescendant');\n }\n }\n private _pointerDown: boolean;\n container: HTMLElement;\n /** Instance of the menu plugin for this autocomplete. */\n menu: Menu;\n static _keydown: boolean;\n selectedValues: AutocompleteData[];\n menuItems: AutocompleteData[];\n\n constructor(el: HTMLInputElement, options: Partial<AutocompleteOptions>) {\n super(el, options);\n\n this.isOpen = false;\n this.count = 0;\n this.activeIndex = -1;\n this.oldVal = '';\n this.selectedValues = this.options.selected.map((id) => this.options.data.find(entry => entry.id === id) ?? { id });\n this.menuItems = this.options.data || [];\n this.$active = null;\n this._pointerDown = false;\n this._setupMenu();\n this._setupEventHandlers();\n }\n\n static get defaults(): AutocompleteOptions {\n return _defaults;\n }\n\n static key = 'Expressive_Autocomplete';\n\n /**\n * The three-dot loading indicator, parsed once and cloned thereafter.\n *\n * It is shown on every input change, and it used to be assigned as an\n * innerHTML string each time - re-running the HTML parser over the same\n * fixed markup on every keystroke.\n */\n private static _loadingTemplate: HTMLElement = null;\n\n private static _loadingIndicator(): HTMLElement {\n if (!Autocomplete._loadingTemplate) {\n const template = document.createElement('template');\n template.innerHTML = `<div style=\"height:100%;width:50px;\"><svg version=\"1.1\" id=\"L4\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\" viewBox=\"0 0 100 100\" enable-background=\"new 0 0 0 0\" xml:space=\"preserve\">\n <circle fill=\"#888c\" stroke=\"none\" cx=\"6\" cy=\"50\" r=\"6\"><animate attributeName=\"opacity\" dur=\"1s\" values=\"0;1;0\" repeatCount=\"indefinite\" begin=\"0.1\"/></circle>\n <circle fill=\"#888c\" stroke=\"none\" cx=\"26\" cy=\"50\" r=\"6\"><animate attributeName=\"opacity\" dur=\"1s\" values=\"0;1;0\" repeatCount=\"indefinite\" begin=\"0.2\"/></circle>\n <circle fill=\"#888c\" stroke=\"none\" cx=\"46\" cy=\"50\" r=\"6\"><animate attributeName=\"opacity\" dur=\"1s\" values=\"0;1;0\" repeatCount=\"indefinite\" begin=\"0.3\"/></circle>\n </svg></div>`;\n Autocomplete._loadingTemplate = template.content.firstElementChild as HTMLElement;\n }\n return Autocomplete._loadingTemplate.cloneNode(true) as HTMLElement;\n }\n\n destroy() {\n // open() defers menu.open() to a timer. Without cancelling it, destroying\n // an autocomplete that was opened in the same tick let the callback run\n // against a menu whose element had already been removed.\n if (this._openTimer !== undefined) {\n clearTimeout(this._openTimer);\n this._openTimer = undefined;\n }\n this._cancelPendingSearch();\n this._searchAbort?.abort();\n this._events.abort();\n this.menu.destroy();\n this.isOpen = false;\n this._removeMenu();\n for (const name of ['role', 'aria-autocomplete', 'aria-controls', 'data-target', 'aria-haspopup', 'aria-expanded', 'aria-activedescendant']) {\n this.el.removeAttribute(name);\n }\n this._statusInfo.remove();\n this._announcer.remove();\n super.destroy();\n }\n\n _setupEventHandlers() {\n const { signal } = this._events;\n this.el.addEventListener('blur', this._handleInputBlur, { signal });\n this.el.addEventListener('input', this._handleInput, { signal });\n this.el.addEventListener('keyup', this._handleInputKeyup, { signal });\n this.el.addEventListener('focus', this._handleInputFocus, { signal });\n this.el.addEventListener('keydown', this._handleInputKeydown, { signal });\n this.el.addEventListener('click', this._handleInputClick, { signal });\n // One pair, not two. These used to be a mouse pair plus a touch pair behind\n // a `window.ontouchstart` feature detect; a pointer event covers both, and\n // the detect covered nothing the browser does not report itself.\n this.container.addEventListener('pointerdown', this._handleContainerPointerDown, { signal });\n this.container.addEventListener('pointerup', this._handleContainerPointerUp, { signal });\n this.container.addEventListener('pointercancel', this._handleContainerPointerUp, { signal });\n this.container.addEventListener('mousedown', this._handleInertRowPress, { capture: true, signal });\n this.container.addEventListener('click', this._handleInertRowPress, { capture: true, signal });\n }\n\n _setupMenu() {\n this.container = document.createElement('menu');\n this.container.style.maxHeight = this.options.maxMenuHeight;\n this.container.id = `autocomplete-options-${Utils.guid()}`;\n this.container.classList.add('autocomplete-content');\n this.container.ariaExpanded = 'true';\n // An autocomplete is the textbook combobox, and this one already\n // implements the keyboard contract the roles promise - Up and Down move\n // the active entry, Enter commits it - so it is allowed to claim them.\n // It had none: the suggestions were an unlabelled list of <li>, and the\n // highlight moved with a class no assistive technology could see.\n this.container.setAttribute('role', 'listbox');\n this.el.setAttribute('role', 'combobox');\n this.el.setAttribute('aria-autocomplete', 'list');\n this.el.setAttribute('aria-controls', this.container.id);\n this.el.setAttribute('data-target', this.container.id);\n\n this.menuItems.forEach((menuItem) => {\n const itemElement = this._createMenuItem(menuItem);\n this.container.append(itemElement);\n });\n\n // ! Issue in Component Menu: _placeMenu moves dom-position\n this.el.parentElement.appendChild(this.container);\n\n // Initialize menu\n const menuOptions = {\n ...Autocomplete.defaults.menuOptions,\n ...this.options.menuOptions\n };\n const userOnOpenStart = menuOptions.onOpenStart;\n const userOnCloseStart = menuOptions.onCloseStart;\n menuOptions.onOpenStart = (el) => {\n this.isOpen = true;\n if (typeof userOnOpenStart === 'function') userOnOpenStart.call(this.menu, el);\n };\n menuOptions.onCloseStart = (el) => {\n this.isOpen = false;\n if (typeof userOnCloseStart === 'function') userOnCloseStart.call(this.menu, el);\n };\n // The wrapper is installed unconditionally: selecting the clicked entry is\n // how the autocomplete works, not an optional extra. Only the forwarding to\n // a user-supplied handler is conditional, and it hands over exactly what\n // Menu would have (the clicked `li`, called on the Menu instance).\n const userOnItemClick = menuOptions.onItemClick;\n menuOptions.onItemClick = (li) => {\n if (!li) return;\n this._choose(li);\n if (typeof userOnItemClick === 'function') userOnItemClick.call(this.menu, li);\n };\n this.menu = Menu.init(this.el, menuOptions);\n this.el.setAttribute('aria-haspopup', 'listbox');\n\n // ! Workaround for Label: move label up again\n // TODO: Just use PopperJS in future!\n const label = this.el.parentElement.querySelector('label');\n if (label) this.el.after(label);\n\n // Menu's trigger handlers open the list without rendering it, and its\n // keydown cancels Space and Enter, which a text field needs.\n this.el.removeEventListener('click', this.menu._handleClick);\n this.el.removeEventListener('keydown', this.menu._handleTriggerKeydown);\n if (!this.options.isMultiSelect) this._refreshInputText();\n // Set Value if already set in HTML\n if (this.el.value) this.selectOption(this.el.value);\n // Add StatusInfo\n const div = document.createElement('div');\n div.classList.add('status-info');\n div.setAttribute('aria-hidden', 'true');\n div.setAttribute('style', 'position: absolute;right:0;top:0;');\n this.el.parentElement.appendChild(div);\n this._statusInfo = div;\n this._announcer = document.createElement('div');\n this._announcer.classList.add('autocomplete-status');\n this._announcer.setAttribute('role', 'status');\n this._announcer.setAttribute('aria-live', 'polite');\n this._announcer.setAttribute('aria-atomic', 'true');\n this.el.parentElement.appendChild(this._announcer);\n this._updateSelectedInfo();\n }\n\n _removeMenu() {\n this.container.ariaExpanded = 'false';\n this.container.parentNode.removeChild(this.container);\n }\n\n _handleInputBlur = () => {\n if (!this._pointerDown) {\n this._left = true;\n this._cancelPendingSearch();\n this.close();\n this._resetAutocomplete();\n }\n };\n\n _handleInputKeyup = () => {\n Autocomplete._keydown = false;\n };\n\n _handleInput = () => {\n this._left = false;\n this.count = 0;\n const actualValue = this.el.value.toLocaleLowerCase();\n // Check if the input isn't empty, and that focus arrived by keyboard -\n // which is what `:focus-visible` means, and used to be a global flag this\n // bundle maintained from four capture-phase document listeners. An open\n // menu is not re-rendered with the old results here: setMenuItems renders\n // the new ones. Below minLength, open() still runs to clear the list.\n if (this.oldVal !== actualValue) {\n // The old results can stay on screen until setMenuItems replaces them,\n // but none may stay active: Enter would select a result for the\n // previous query.\n this._resetCurrentElementPosition();\n // open() renders before the new search starts, so the old answer goes first.\n this._noResults = false;\n if (this.el.matches(':focus-visible')\n && (!this.menu.isOpen || actualValue.length < this.options.minLength)) this.open();\n }\n this._inputChangeDetection(actualValue, true);\n };\n\n _handleInputFocus = () => {\n this._left = false;\n this.count = 0;\n const actualValue = this.el.value.toLocaleLowerCase();\n this._inputChangeDetection(actualValue);\n };\n\n _inputChangeDetection = (value: string, typed?: boolean) => {\n // Editing or clearing a single selection's text deselects it.\n const deselected = !this.options.isMultiSelect && this.selectedValues.length > 0\n && this.el.value !== (this.selectedValues[0].text || String(this.selectedValues[0].id));\n if (deselected) this.selectedValues = [];\n // Value has changed!\n if (this.oldVal !== value) {\n this._noResults = false;\n this._setStatusLoading();\n this._queueSearch(typed);\n }\n if (deselected) this._triggerChanged();\n this.oldVal = value;\n };\n\n /** Searches now, or once typing pauses for `searchDelay`. Focus never waits. */\n private _queueSearch(typed?: boolean) {\n this._cancelPendingSearch();\n const delay = this.options.searchDelay;\n if (!typed || !(delay > 0 && delay < Infinity)) return this._search(this.el.value);\n // The running search is for text the field no longer holds.\n this._searchAbort?.abort();\n this._searchTimer = setTimeout(() => {\n this._searchTimer = undefined;\n this._search(this.el.value);\n }, delay);\n }\n\n private _cancelPendingSearch() {\n clearTimeout(this._searchTimer);\n this._searchTimer = undefined;\n }\n\n /** Starts a search and aborts the one before, whose response is now stale. */\n private _search(text: string) {\n this._searchAbort?.abort();\n this._searchAbort = new AbortController();\n this.options.onSearch(text, this, this._searchAbort.signal);\n }\n\n _handleInputKeydown = Utils.ignoringComposition((e: KeyboardEvent) => {\n Autocomplete._keydown = true;\n if (e.key === 'Escape' || e.key === 'Tab') {\n this._dismiss(e);\n return;\n }\n // Arrow keys and enter key usage\n const options = this._options();\n const numItems = options.length;\n // select element on Enter\n if (e.key === 'Enter' && this.activeIndex >= 0) {\n const liElement = options[this.activeIndex];\n if (liElement) {\n this._choose(liElement);\n e.preventDefault();\n }\n return;\n }\n // Capture up and down key\n if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {\n e.preventDefault();\n // A list that is already opening keeps its rendered results.\n if (!this.menu.isOpen && this._openTimer === undefined) {\n this.open();\n return;\n }\n if (e.key === 'ArrowUp' && this.activeIndex > 0) this.activeIndex--;\n if (e.key === 'ArrowDown' && this.activeIndex < numItems - 1)\n this.activeIndex++;\n this._setActive(null);\n if (this.activeIndex >= 0) {\n this._setActive(options[this.activeIndex]);\n // Focus selected\n options[this.activeIndex].scrollIntoView({\n behavior: 'smooth',\n block: 'nearest',\n inline: 'nearest'\n });\n }\n }\n });\n\n private _dismiss(e: KeyboardEvent) {\n if (e.key === 'Escape') {\n // Take the key only when it closes something, or a surrounding <dialog>\n // would cancel too. A dismissed list stays shut for late results.\n if (this.menu.isOpen || this._openTimer !== undefined) e.preventDefault();\n this._left = true;\n }\n this.close();\n this._resetCurrentElementPosition();\n }\n\n _handleInputClick = () => {\n this.open();\n };\n\n // The flag says \"a press is in flight inside the option list\", so that a blur\n // caused by that press does not close the list out from under it. Without the\n // cancel half, a cancelled gesture left the flag set and the next blur could\n // not close the list at all.\n _handleContainerPointerDown = (e: PointerEvent) => {\n if (!e.isPrimary) return;\n if (e.pointerType === 'mouse' && e.button !== 0) return;\n this._pointerDown = true;\n };\n\n _handleContainerPointerUp = () => {\n this._pointerDown = false;\n };\n\n // The no-results row and group headings are not options, and a disabled row\n // cannot be chosen. A press on any of them would move focus to the list,\n // which nothing hands back, and Menu would report the row as chosen.\n _handleInertRowPress = (e: MouseEvent) => {\n if (!(e.target instanceof Element) || !e.target.closest('.autocomplete-no-results, .autocomplete-group-label, [aria-disabled=\"true\"]')) return;\n e.preventDefault();\n e.stopPropagation();\n };\n\n /** The rows that can be chosen. The no-results row and disabled rows are not. */\n private _options() {\n return this.container.querySelectorAll<HTMLElement>('li[role=\"option\"]:not([aria-disabled=\"true\"])');\n }\n\n _resetCurrentElementPosition() {\n this.activeIndex = -1;\n this._setActive(null);\n }\n\n _resetAutocomplete() {\n this.container.replaceChildren();\n this._resetCurrentElementPosition();\n this.oldVal = null;\n this._pointerDown = false;\n }\n\n _highlightPartialText(input: string, label: string) {\n const start = label.toLocaleLowerCase().indexOf(input.toLocaleLowerCase());\n const end = start + input.length - 1;\n //custom filters may return results where the string does not match any part\n if (start == -1 || end == -1) {\n return [label, '', ''];\n }\n return [label.slice(0, start), label.slice(start, end + 1), label.slice(end + 1)];\n }\n\n _createMenuItem(entry: AutocompleteData) {\n const item = document.createElement('li');\n item.id = `autocomplete-option-${Utils.guid()}`;\n item.setAttribute('role', 'option');\n // role=option promises a selection state on every entry, not just the\n // chosen one - and it has to be the *real* one. A multi-select entry that\n // is already committed is selected whether or not it is the highlighted\n // row.\n const isSelected = this.selectedValues.some((sel) => sel.id === entry.id);\n item.setAttribute('aria-selected', isSelected ? 'true' : 'false');\n item.setAttribute('data-id', <string>entry.id);\n Autocomplete._markDisabled(item, entry);\n item.setAttribute(\n 'style',\n 'display:grid; grid-auto-flow: column; user-select: none; align-items: center;'\n );\n item.tabIndex = -1;\n // Checkbox\n if (this.options.isMultiSelect) {\n const selection = document.createElement('div');\n selection.classList.add('item-selection');\n selection.style.textAlign = 'center';\n const checkbox = document.createElement('input');\n checkbox.type = 'checkbox';\n checkbox.tabIndex = -1;\n checkbox.checked = isSelected;\n checkbox.disabled = entry.disabled === true;\n const spacer = document.createElement('span');\n spacer.style.paddingLeft = '21px';\n selection.append(checkbox, spacer);\n item.appendChild(selection);\n }\n // Image\n if (entry.image) {\n const img = document.createElement('img');\n img.classList.add('circle');\n img.src = entry.image;\n item.appendChild(img);\n }\n\n const div = this._createLabel(entry);\n\n const itemText = document.createElement('div');\n itemText.classList.add('item-text');\n itemText.setAttribute('style', 'padding:5px;overflow:hidden;');\n item.appendChild(itemText);\n itemText.appendChild(div);\n // Description\n if (\n typeof entry.description === 'string' ||\n (typeof entry.description === 'number' && !isNaN(entry.description))\n ) {\n const description = document.createElement('small');\n description.setAttribute(\n 'style',\n 'line-height:1.3;color:grey;white-space:nowrap;text-overflow:ellipsis;display:block;width:90%;overflow:hidden;'\n );\n description.innerText = entry.description;\n itemText.appendChild(description);\n }\n // Set Grid\n const getGridConfig = () => {\n if (this.options.isMultiSelect) {\n if (entry.image) return '40px min-content auto'; // cb-img-txt\n return '40px auto'; // cb-txt\n }\n if (entry.image) return 'min-content auto'; // img-txt\n return 'auto'; // txt\n };\n item.style.gridTemplateColumns = getGridConfig();\n return item;\n }\n\n /** Menu already ignores a click on an aria-disabled row. */\n private static _markDisabled(item: HTMLElement, entry: AutocompleteData) {\n if (entry.disabled === true) item.setAttribute('aria-disabled', 'true');\n }\n\n _createLabel(entry: AutocompleteData) {\n const inputText = this.el.value.toLocaleLowerCase();\n const label = (entry.text || entry.id).toString();\n const div = document.createElement('div');\n div.setAttribute('style', 'line-height:1.2;font-weight:500;');\n // Only a script-supplied text is HTML. An id can come from markup's\n // `selected`, which AutoInit treats as untrusted, so it stays text.\n if (this.options.allowUnsafeHTML && entry.text) this._highlightHTML(div, label, inputText);\n else this._highlightText(div, this._highlightPartialText(inputText, label));\n return div;\n }\n\n _highlightHTML(div: HTMLElement, label: string, inputText: string) {\n // Highlight inside a parsed text node. Splicing the span into the HTML\n // string put its quotes inside any attribute the match landed in, which\n // closed that attribute and let the rest of it become markup.\n div.innerHTML = label;\n const walker = document.createTreeWalker(div, NodeFilter.SHOW_TEXT);\n for (let node = walker.nextNode() as Text; node; node = walker.nextNode() as Text) {\n const [before, match] = this._highlightPartialText(inputText, node.data);\n if (!match) continue;\n const matched = node.splitText(before.length);\n matched.splitText(match.length);\n const highlight = document.createElement('span');\n highlight.classList.add('highlight');\n matched.replaceWith(highlight);\n highlight.append(matched);\n break;\n }\n }\n\n _highlightText(div: HTMLElement, parts: string[]) {\n div.appendChild(document.createTextNode(parts[0]));\n if (parts[1]) {\n const highlight = document.createElement('span');\n highlight.textContent = parts[1];\n highlight.classList.add('highlight');\n div.appendChild(highlight);\n div.appendChild(document.createTextNode(parts[2]));\n }\n }\n\n _renderMenu() {\n this._resetAutocomplete();\n if (this._noResults) this.container.append(this._createNoResultsRow());\n // Check if Data is empty\n if (this.menuItems.length === 0) {\n this.menuItems = this.selectedValues; // Show selected Items\n }\n const groups = new Map<string, HTMLElement>();\n this.menuItems.forEach((entry) => this._groupList(entry.group, groups).append(this._createMenuItem(entry)));\n const createText = this._createText();\n if (createText) this.container.append(this._createRow(createText));\n }\n\n /** The list a row goes in: the listbox, or its group's list, made where the group first appears. */\n private _groupList(name: string | undefined, groups: Map<string, HTMLElement>) {\n if (!name) return this.container;\n if (!groups.has(name)) groups.set(name, this._createGroup(name));\n return groups.get(name);\n }\n\n /**\n * A labelled group of options, as the APG grouped listbox nests it. The\n * heading is not an option, so the arrow keys and the count pass over it.\n * Its name is set as text: only an entry's own `text` may be HTML.\n */\n private _createGroup(name: string) {\n const heading = document.createElement('li');\n heading.id = `autocomplete-group-${Utils.guid()}`;\n heading.setAttribute('role', 'presentation');\n heading.classList.add('label', 'autocomplete-group-label');\n heading.textContent = name;\n const list = document.createElement('ul');\n list.setAttribute('role', 'group');\n list.setAttribute('aria-labelledby', heading.id);\n list.append(heading);\n const wrapper = document.createElement('li');\n wrapper.setAttribute('role', 'none');\n wrapper.append(list);\n this.container.append(wrapper);\n return list;\n }\n\n /** The typed text to offer as a new value, or '' when the option is off, the text is short or a suggestion matches it. */\n private _createText() {\n const text = this.el.value.trim();\n if (!this.options.allowCreate || text.length < this.options.minLength) return '';\n const typed = text.toLocaleLowerCase();\n return this.menuItems.some((entry) => (entry.text || String(entry.id)).toLocaleLowerCase() === typed) ? '' : text;\n }\n\n /** The \"Add\" row. Its label is what the person typed, so it is set as text, never as HTML. */\n private _createRow(text: string) {\n const item = document.createElement('li');\n item.id = `autocomplete-option-${Utils.guid()}`;\n item.setAttribute('role', 'option');\n item.setAttribute('aria-selected', 'false');\n // Not data-id, which an entry's id could equal. The text is kept on the\n // row because the field can change before newer results replace it.\n item.setAttribute('data-create', text);\n item.classList.add('autocomplete-create');\n item.setAttribute('style', 'display:grid; user-select: none; align-items: center;');\n item.tabIndex = -1;\n const label = document.createElement('div');\n label.classList.add('item-text');\n label.setAttribute('style', 'padding:5px;overflow:hidden;line-height:1.2;font-weight:500;');\n label.textContent = this.options.i18n.create(text);\n item.append(label);\n return item;\n }\n\n /**\n * Shows sighted users the `i18n.noResults` that the live region announces.\n * Screen readers already hear that, and a listbox may only own options, so\n * the row is hidden from them.\n */\n private _createNoResultsRow() {\n const row = document.createElement('li');\n row.classList.add('autocomplete-no-results');\n row.setAttribute('role', 'none');\n row.setAttribute('aria-hidden', 'true');\n row.textContent = this.options.i18n.noResults;\n return row;\n }\n\n _setStatusLoading() {\n const statusElement = this._statusInfo;\n if (statusElement) statusElement.replaceChildren(Autocomplete._loadingIndicator());\n this._announce(this.options.i18n.loading);\n }\n\n private _announce(message: string) {\n if (!this._announcer) return;\n const text = this.el.matches(':focus') && this.el.value.length >= this.options.minLength ? message : '';\n if (this._announcer.textContent !== text) this._announcer.textContent = text;\n }\n\n /** Announces the entries a person can choose. Disabled ones are shown, not counted. */\n private _resultsMessage() {\n const count = this.menuItems.filter((entry) => entry.disabled !== true).length;\n return count ? this.options.i18n.results(count) : this.options.i18n.noResults;\n }\n\n _updateSelectedInfo() {\n const statusElement = this._statusInfo;\n if (statusElement) {\n if (this.options.isMultiSelect)\n statusElement.textContent = this.selectedValues.length.toString();\n else statusElement.replaceChildren();\n }\n }\n\n _refreshInputText() {\n if (this.selectedValues.length === 1) {\n const entry = this.selectedValues[0];\n this.el.value = entry.text || <string>entry.id; // Write Text to Input\n }\n }\n\n _triggerChanged() {\n // Counted before the native change, whose listeners may select again.\n const values = this.selectedValues;\n const selection = ++this._selection;\n this.el.dispatchEvent(new Event('change', { bubbles: true, cancelable: true, composed: true }));\n if (selection !== this._selection) return;\n this._notify('autocomplete', this.options.onAutocomplete, { args: [values], detail: { values }, current: () => selection === this._selection });\n }\n\n /**\n * Show autocomplete.\n */\n open = () => {\n const inputText = this.el.value.toLocaleLowerCase();\n this._resetAutocomplete();\n if (inputText.length >= this.options.minLength) {\n this._renderMenu();\n this._announce(this._resultsMessage());\n }\n // Open menu\n if (!this.menu.isOpen) {\n // Cancel first: two open() calls before the callback fires would leave\n // the earlier timer untracked, and destroy() can only cancel the one it\n // knows about.\n if (this._openTimer !== undefined) clearTimeout(this._openTimer);\n this._openTimer = setTimeout(() => {\n this._openTimer = undefined;\n this.menu.open();\n }, 0); // TODO: why?\n } else this.menu.recalculateDimensions(); // Recalculate menu when its already open\n };\n\n /**\n * Hide autocomplete.\n */\n close = () => {\n if (this._announcer) this._announcer.textContent = '';\n if (this._openTimer !== undefined) {\n clearTimeout(this._openTimer);\n this._openTimer = undefined;\n }\n this.isOpen = false;\n this.menu.close();\n };\n\n /**\n * Updates the visible or selectable items shown in the menu.\n * @param menuItems Items to be available.\n * @param selected Selected item ids\n * @param open Option to conditionally open menu\n */\n setMenuItems(menuItems: AutocompleteData[], selected: number[] | string[] = null, open: boolean = true) {\n if (this.el['Expressive_Autocomplete'] !== this) return;\n // Results that arrive after the user left the field update the list\n // without opening it under an input nobody is using.\n open &&= !this._left;\n this._noResults = menuItems.length === 0;\n this.menuItems = menuItems;\n if (selected) {\n this.selectedValues = this.menuItems.filter(\n (item) => !(selected.indexOf(<never>item.id) === -1)\n );\n }\n // open() clears and renders the list itself.\n if (this.options.isMultiSelect) {\n if (!open) this._renderMenu();\n } else {\n this._refreshInputText();\n }\n if (open) this.open();\n this._updateSelectedInfo();\n this._announce(open ? this._resultsMessage() : '');\n if (selected) this._triggerChanged();\n }\n\n private _toggleOption(entry: AutocompleteData) {\n const selected = !this.selectedValues.some((selectedEntry) => selectedEntry.id === entry.id);\n if (selected) this.selectedValues.push(entry);\n else this.selectedValues = this.selectedValues.filter((selectedEntry) => selectedEntry.id !== entry.id);\n // Update the row in place. Re-rendering the list dropped the active row,\n // and its reset of oldVal made the refocus below run a new search.\n const row = Array.from(this.container.querySelectorAll('li[data-id]')).find((li) => li.getAttribute('data-id') === String(entry.id));\n if (row) {\n row.setAttribute('aria-selected', String(selected));\n row.querySelector('input').checked = selected;\n }\n this.el.focus();\n }\n\n private _selectSingle(entry: AutocompleteData) {\n // A click focuses the row, and removing it would drop focus to <body>.\n // A selection made from code leaves focus where it is.\n const refocus = Utils.focusIsIn(this.container);\n // A search still waiting would run on the chosen label and reopen the list.\n this._cancelPendingSearch();\n this.selectedValues = [entry];\n this._refreshInputText();\n this._resetAutocomplete();\n this.close();\n if (refocus) {\n // The field already shows the choice, so returning to it is not a new search.\n this.oldVal = this.el.value.toLocaleLowerCase();\n this.el.focus();\n }\n }\n\n /** Commits a row chosen by Enter or a click. */\n private _choose(li: Element) {\n if (li.hasAttribute('data-create')) this._create(li.getAttribute('data-create'));\n else this.selectOption(li.getAttribute('data-id'));\n }\n\n private _create(text: string) {\n const refocus = Utils.focusIsIn(this.container);\n // A search still waiting would reopen the list on the same text.\n this._cancelPendingSearch();\n // The field keeps the text, so returning to it is not a new search.\n this.oldVal = this.el.value.toLocaleLowerCase();\n this.close();\n if (refocus) this.el.focus();\n this._notify('create', this.options.onCreate, { args: [text, this], detail: { text } });\n }\n\n /**\n * Select a specific autocomplete option via id-property.\n * @param id The id of a data-entry.\n */\n selectOption(id: number | string) {\n // A disabled entry is never found, so it is neither chosen nor removed.\n const entry = this.menuItems.find((item) => item.id == id && item.disabled !== true);\n if (!entry) return;\n if (this.options.isMultiSelect) this._toggleOption(entry);\n else this._selectSingle(entry);\n this._updateSelectedInfo();\n if (this.options.isMultiSelect) this._announce(this.options.i18n.selected(this.selectedValues.length));\n this._triggerChanged();\n }\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;AAqHA,IAAM,YAAiC;AAAA,EACrC,MAAM;AAAA,IACJ,SAAS;AAAA,IACT,WAAW;AAAA,IACX,SAAS,WAAS,GAAG,KAAK,IAAI,UAAU,IAAI,WAAW,SAAS;AAAA,IAChE,UAAU,WAAS,GAAG,KAAK,IAAI,UAAU,IAAI,SAAS,OAAO;AAAA,IAC7D,QAAQ,UAAQ,QAAQ,IAAI;AAAA,EAC9B;AAAA,EACA,MAAM,CAAC;AAAA;AAAA,EACP,gBAAgB;AAAA;AAAA,EAChB,aAAa;AAAA;AAAA,IAEX,WAAW;AAAA,IACX,cAAc;AAAA,IACd,cAAc;AAAA,EAChB;AAAA,EACA,WAAW;AAAA;AAAA,EACX,aAAa;AAAA,EACb,aAAa;AAAA,EACb,UAAU;AAAA,EACV,eAAe;AAAA,EACf,UAAU,CAAC,MAAc,iBAA+B;AACtD,UAAM,aAAa,KAAK,kBAAkB;AAC1C,iBAAa;AAAA,MACX,aAAa,QAAQ,KAAK;AAAA,QAAO,CAAC,WAChC,OAAO,GAAG,SAAS,EAAE,kBAAkB,EAAE,SAAS,UAAU,KACvD,OAAO,MAAM,kBAAkB,EAAE,SAAS,UAAU;AAAA,MAC3D;AAAA,IACF;AAAA,EACF;AAAA,EACA,eAAe;AAAA,EACf,iBAAiB;AAAA,EACjB,UAAU,CAAC;AACb;AAEO,IAAM,gBAAN,MAAM,sBAAqB,UAA+B;AAAA,EAuD/D,YAAY,IAAsB,SAAuC;AACvE,UAAM,IAAI,OAAO;AAhDnB;AAAA;AAAA;AAAA;AAAA,SAAQ,QAAQ;AAahB;AAAA,SAAQ,aAAa;AAIrB;AAAA,SAAQ,aAAa;AAuMrB,4BAAmB,MAAM;AACvB,UAAI,CAAC,KAAK,cAAc;AACtB,aAAK,QAAQ;AACb,aAAK,qBAAqB;AAC1B,aAAK,MAAM;AACX,aAAK,mBAAmB;AAAA,MAC1B;AAAA,IACF;AAEA,6BAAoB,MAAM;AACxB,oBAAa,WAAW;AAAA,IAC1B;AAEA,wBAAe,MAAM;AACnB,WAAK,QAAQ;AACb,WAAK,QAAQ;AACb,YAAM,cAAc,KAAK,GAAG,MAAM,kBAAkB;AAMpD,UAAI,KAAK,WAAW,aAAa;AAI/B,aAAK,6BAA6B;AAElC,aAAK,aAAa;AAClB,YAAI,KAAK,GAAG,QAAQ,gBAAgB,MAC9B,CAAC,KAAK,KAAK,UAAU,YAAY,SAAS,KAAK,QAAQ,WAAY,MAAK,KAAK;AAAA,MACrF;AACA,WAAK,sBAAsB,aAAa,IAAI;AAAA,IAC9C;AAEA,6BAAoB,MAAM;AACxB,WAAK,QAAQ;AACb,WAAK,QAAQ;AACb,YAAM,cAAc,KAAK,GAAG,MAAM,kBAAkB;AACpD,WAAK,sBAAsB,WAAW;AAAA,IACxC;AAEA,iCAAwB,CAAC,OAAe,UAAoB;AAE1D,YAAM,aAAa,CAAC,KAAK,QAAQ,iBAAiB,KAAK,eAAe,SAAS,KAC1E,KAAK,GAAG,WAAW,KAAK,eAAe,CAAC,EAAE,QAAQ,OAAO,KAAK,eAAe,CAAC,EAAE,EAAE;AACvF,UAAI,WAAY,MAAK,iBAAiB,CAAC;AAEvC,UAAI,KAAK,WAAW,OAAO;AACzB,aAAK,aAAa;AAClB,aAAK,kBAAkB;AACvB,aAAK,aAAa,KAAK;AAAA,MACzB;AACA,UAAI,WAAY,MAAK,gBAAgB;AACrC,WAAK,SAAS;AAAA,IAChB;AA2BA,+BAAsB,MAAM,oBAAoB,CAAC,MAAqB;AACpE,oBAAa,WAAW;AACxB,UAAI,EAAE,QAAQ,YAAY,EAAE,QAAQ,OAAO;AACzC,aAAK,SAAS,CAAC;AACf;AAAA,MACF;AAEA,YAAM,UAAU,KAAK,SAAS;AAC9B,YAAM,WAAW,QAAQ;AAEzB,UAAI,EAAE,QAAQ,WAAW,KAAK,eAAe,GAAG;AAC9C,cAAM,YAAY,QAAQ,KAAK,WAAW;AAC1C,YAAI,WAAW;AACb,eAAK,QAAQ,SAAS;AACtB,YAAE,eAAe;AAAA,QACnB;AACA;AAAA,MACF;AAEA,UAAI,EAAE,QAAQ,aAAa,EAAE,QAAQ,aAAa;AAChD,UAAE,eAAe;AAEjB,YAAI,CAAC,KAAK,KAAK,UAAU,KAAK,eAAe,QAAW;AACtD,eAAK,KAAK;AACV;AAAA,QACF;AACA,YAAI,EAAE,QAAQ,aAAa,KAAK,cAAc,EAAG,MAAK;AACtD,YAAI,EAAE,QAAQ,eAAe,KAAK,cAAc,WAAW;AACzD,eAAK;AACP,aAAK,WAAW,IAAI;AACpB,YAAI,KAAK,eAAe,GAAG;AACzB,eAAK,WAAW,QAAQ,KAAK,WAAW,CAAC;AAEzC,kBAAQ,KAAK,WAAW,EAAE,eAAe;AAAA,YACvC,UAAU;AAAA,YACV,OAAO;AAAA,YACP,QAAQ;AAAA,UACV,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF,CAAC;AAaD,6BAAoB,MAAM;AACxB,WAAK,KAAK;AAAA,IACZ;AAMA;AAAA;AAAA;AAAA;AAAA,uCAA8B,CAAC,MAAoB;AACjD,UAAI,CAAC,EAAE,UAAW;AAClB,UAAI,EAAE,gBAAgB,WAAW,EAAE,WAAW,EAAG;AACjD,WAAK,eAAe;AAAA,IACtB;AAEA,qCAA4B,MAAM;AAChC,WAAK,eAAe;AAAA,IACtB;AAKA;AAAA;AAAA;AAAA,gCAAuB,CAAC,MAAkB;AACxC,UAAI,EAAE,EAAE,kBAAkB,YAAY,CAAC,EAAE,OAAO,QAAQ,6EAA6E,EAAG;AACxI,QAAE,eAAe;AACjB,QAAE,gBAAgB;AAAA,IACpB;AAuRA;AAAA;AAAA;AAAA,gBAAO,MAAM;AACX,YAAM,YAAY,KAAK,GAAG,MAAM,kBAAkB;AAClD,WAAK,mBAAmB;AACxB,UAAI,UAAU,UAAU,KAAK,QAAQ,WAAW;AAC9C,aAAK,YAAY;AACjB,aAAK,UAAU,KAAK,gBAAgB,CAAC;AAAA,MACvC;AAEA,UAAI,CAAC,KAAK,KAAK,QAAQ;AAIrB,YAAI,KAAK,eAAe,OAAW,cAAa,KAAK,UAAU;AAC/D,aAAK,aAAa,WAAW,MAAM;AACjC,eAAK,aAAa;AAClB,eAAK,KAAK,KAAK;AAAA,QACjB,GAAG,CAAC;AAAA,MACN,MAAO,MAAK,KAAK,sBAAsB;AAAA,IACzC;AAKA;AAAA;AAAA;AAAA,iBAAQ,MAAM;AACZ,UAAI,KAAK,WAAY,MAAK,WAAW,cAAc;AACnD,UAAI,KAAK,eAAe,QAAW;AACjC,qBAAa,KAAK,UAAU;AAC5B,aAAK,aAAa;AAAA,MACpB;AACA,WAAK,SAAS;AACd,WAAK,KAAK,MAAM;AAAA,IAClB;AA5nBE,SAAK,SAAS;AACd,SAAK,QAAQ;AACb,SAAK,cAAc;AACnB,SAAK,SAAS;AACd,SAAK,iBAAiB,KAAK,QAAQ,SAAS,IAAI,CAAC,OAAO,KAAK,QAAQ,KAAK,KAAK,WAAS,MAAM,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC;AAClH,SAAK,YAAY,KAAK,QAAQ,QAAQ,CAAC;AACvC,SAAK,UAAU;AACf,SAAK,eAAe;AACpB,SAAK,WAAW;AAChB,SAAK,oBAAoB;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA/BQ,WAAW,MAA0B;AAC3C,SAAK,SAAS,UAAU,OAAO,QAAQ;AACvC,SAAK,UAAU;AACf,QAAI,MAAM;AACR,WAAK,UAAU,IAAI,QAAQ;AAC3B,WAAK,GAAG,aAAa,yBAAyB,KAAK,EAAE;AAAA,IACvD,OAAO;AACL,WAAK,GAAG,gBAAgB,uBAAuB;AAAA,IACjD;AAAA,EACF;AAAA,EAwBA,WAAW,WAAgC;AACzC,WAAO;AAAA,EACT;AAAA,EAaA,OAAe,oBAAiC;AAC9C,QAAI,CAAC,cAAa,kBAAkB;AAClC,YAAM,WAAW,SAAS,cAAc,UAAU;AAClD,eAAS,YAAY;AAAA;AAAA;AAAA;AAAA;AAKrB,oBAAa,mBAAmB,SAAS,QAAQ;AAAA,IACnD;AACA,WAAO,cAAa,iBAAiB,UAAU,IAAI;AAAA,EACrD;AAAA,EAEA,UAAU;AAIR,QAAI,KAAK,eAAe,QAAW;AACjC,mBAAa,KAAK,UAAU;AAC5B,WAAK,aAAa;AAAA,IACpB;AACA,SAAK,qBAAqB;AAC1B,SAAK,cAAc,MAAM;AACzB,SAAK,QAAQ,MAAM;AACnB,SAAK,KAAK,QAAQ;AAClB,SAAK,SAAS;AACd,SAAK,YAAY;AACjB,eAAW,QAAQ,CAAC,QAAQ,qBAAqB,iBAAiB,eAAe,iBAAiB,iBAAiB,uBAAuB,GAAG;AAC3I,WAAK,GAAG,gBAAgB,IAAI;AAAA,IAC9B;AACA,SAAK,YAAY,OAAO;AACxB,SAAK,WAAW,OAAO;AACvB,UAAM,QAAQ;AAAA,EAChB;AAAA,EAEA,sBAAsB;AACpB,UAAM,EAAE,OAAO,IAAI,KAAK;AACxB,SAAK,GAAG,iBAAiB,QAAQ,KAAK,kBAAkB,EAAE,OAAO,CAAC;AAClE,SAAK,GAAG,iBAAiB,SAAS,KAAK,cAAc,EAAE,OAAO,CAAC;AAC/D,SAAK,GAAG,iBAAiB,SAAS,KAAK,mBAAmB,EAAE,OAAO,CAAC;AACpE,SAAK,GAAG,iBAAiB,SAAS,KAAK,mBAAmB,EAAE,OAAO,CAAC;AACpE,SAAK,GAAG,iBAAiB,WAAW,KAAK,qBAAqB,EAAE,OAAO,CAAC;AACxE,SAAK,GAAG,iBAAiB,SAAS,KAAK,mBAAmB,EAAE,OAAO,CAAC;AAIpE,SAAK,UAAU,iBAAiB,eAAe,KAAK,6BAA6B,EAAE,OAAO,CAAC;AAC3F,SAAK,UAAU,iBAAiB,aAAa,KAAK,2BAA2B,EAAE,OAAO,CAAC;AACvF,SAAK,UAAU,iBAAiB,iBAAiB,KAAK,2BAA2B,EAAE,OAAO,CAAC;AAC3F,SAAK,UAAU,iBAAiB,aAAa,KAAK,sBAAsB,EAAE,SAAS,MAAM,OAAO,CAAC;AACjG,SAAK,UAAU,iBAAiB,SAAS,KAAK,sBAAsB,EAAE,SAAS,MAAM,OAAO,CAAC;AAAA,EAC/F;AAAA,EAEA,aAAa;AACX,SAAK,YAAY,SAAS,cAAc,MAAM;AAC9C,SAAK,UAAU,MAAM,YAAY,KAAK,QAAQ;AAC9C,SAAK,UAAU,KAAK,wBAAwB,MAAM,KAAK,CAAC;AACxD,SAAK,UAAU,UAAU,IAAI,sBAAsB;AACnD,SAAK,UAAU,eAAe;AAM9B,SAAK,UAAU,aAAa,QAAQ,SAAS;AAC7C,SAAK,GAAG,aAAa,QAAQ,UAAU;AACvC,SAAK,GAAG,aAAa,qBAAqB,MAAM;AAChD,SAAK,GAAG,aAAa,iBAAiB,KAAK,UAAU,EAAE;AACvD,SAAK,GAAG,aAAa,eAAe,KAAK,UAAU,EAAE;AAErD,SAAK,UAAU,QAAQ,CAAC,aAAa;AACnC,YAAM,cAAc,KAAK,gBAAgB,QAAQ;AACjD,WAAK,UAAU,OAAO,WAAW;AAAA,IACnC,CAAC;AAGD,SAAK,GAAG,cAAc,YAAY,KAAK,SAAS;AAGhD,UAAM,cAAc;AAAA,MAClB,GAAG,cAAa,SAAS;AAAA,MACzB,GAAG,KAAK,QAAQ;AAAA,IAClB;AACA,UAAM,kBAAkB,YAAY;AACpC,UAAM,mBAAmB,YAAY;AACrC,gBAAY,cAAc,CAAC,OAAO;AAChC,WAAK,SAAS;AACd,UAAI,OAAO,oBAAoB,WAAY,iBAAgB,KAAK,KAAK,MAAM,EAAE;AAAA,IAC/E;AACA,gBAAY,eAAe,CAAC,OAAO;AACjC,WAAK,SAAS;AACd,UAAI,OAAO,qBAAqB,WAAY,kBAAiB,KAAK,KAAK,MAAM,EAAE;AAAA,IACjF;AAKA,UAAM,kBAAkB,YAAY;AACpC,gBAAY,cAAc,CAAC,OAAO;AAChC,UAAI,CAAC,GAAI;AACT,WAAK,QAAQ,EAAE;AACf,UAAI,OAAO,oBAAoB,WAAY,iBAAgB,KAAK,KAAK,MAAM,EAAE;AAAA,IAC/E;AACA,SAAK,OAAO,KAAK,KAAK,KAAK,IAAI,WAAW;AAC1C,SAAK,GAAG,aAAa,iBAAiB,SAAS;AAI/C,UAAM,QAAQ,KAAK,GAAG,cAAc,cAAc,OAAO;AACzD,QAAI,MAAO,MAAK,GAAG,MAAM,KAAK;AAI9B,SAAK,GAAG,oBAAoB,SAAS,KAAK,KAAK,YAAY;AAC3D,SAAK,GAAG,oBAAoB,WAAW,KAAK,KAAK,qBAAqB;AACtE,QAAI,CAAC,KAAK,QAAQ,cAAe,MAAK,kBAAkB;AAExD,QAAI,KAAK,GAAG,MAAO,MAAK,aAAa,KAAK,GAAG,KAAK;AAElD,UAAM,MAAM,SAAS,cAAc,KAAK;AACxC,QAAI,UAAU,IAAI,aAAa;AAC/B,QAAI,aAAa,eAAe,MAAM;AACtC,QAAI,aAAa,SAAS,mCAAmC;AAC7D,SAAK,GAAG,cAAc,YAAY,GAAG;AACrC,SAAK,cAAc;AACnB,SAAK,aAAa,SAAS,cAAc,KAAK;AAC9C,SAAK,WAAW,UAAU,IAAI,qBAAqB;AACnD,SAAK,WAAW,aAAa,QAAQ,QAAQ;AAC7C,SAAK,WAAW,aAAa,aAAa,QAAQ;AAClD,SAAK,WAAW,aAAa,eAAe,MAAM;AAClD,SAAK,GAAG,cAAc,YAAY,KAAK,UAAU;AACjD,SAAK,oBAAoB;AAAA,EAC3B;AAAA,EAEA,cAAc;AACZ,SAAK,UAAU,eAAe;AAC9B,SAAK,UAAU,WAAW,YAAY,KAAK,SAAS;AAAA,EACtD;AAAA;AAAA,EA4DQ,aAAa,OAAiB;AACpC,SAAK,qBAAqB;AAC1B,UAAM,QAAQ,KAAK,QAAQ;AAC3B,QAAI,CAAC,SAAS,EAAE,QAAQ,KAAK,QAAQ,UAAW,QAAO,KAAK,QAAQ,KAAK,GAAG,KAAK;AAEjF,SAAK,cAAc,MAAM;AACzB,SAAK,eAAe,WAAW,MAAM;AACnC,WAAK,eAAe;AACpB,WAAK,QAAQ,KAAK,GAAG,KAAK;AAAA,IAC5B,GAAG,KAAK;AAAA,EACV;AAAA,EAEQ,uBAAuB;AAC7B,iBAAa,KAAK,YAAY;AAC9B,SAAK,eAAe;AAAA,EACtB;AAAA;AAAA,EAGQ,QAAQ,MAAc;AAC5B,SAAK,cAAc,MAAM;AACzB,SAAK,eAAe,IAAI,gBAAgB;AACxC,SAAK,QAAQ,SAAS,MAAM,MAAM,KAAK,aAAa,MAAM;AAAA,EAC5D;AAAA,EA4CQ,SAAS,GAAkB;AACjC,QAAI,EAAE,QAAQ,UAAU;AAGtB,UAAI,KAAK,KAAK,UAAU,KAAK,eAAe,OAAW,GAAE,eAAe;AACxE,WAAK,QAAQ;AAAA,IACf;AACA,SAAK,MAAM;AACX,SAAK,6BAA6B;AAAA,EACpC;AAAA;AAAA,EA8BQ,WAAW;AACjB,WAAO,KAAK,UAAU,iBAA8B,+CAA+C;AAAA,EACrG;AAAA,EAEA,+BAA+B;AAC7B,SAAK,cAAc;AACnB,SAAK,WAAW,IAAI;AAAA,EACtB;AAAA,EAEA,qBAAqB;AACnB,SAAK,UAAU,gBAAgB;AAC/B,SAAK,6BAA6B;AAClC,SAAK,SAAS;AACd,SAAK,eAAe;AAAA,EACtB;AAAA,EAEA,sBAAsB,OAAe,OAAe;AAClD,UAAM,QAAQ,MAAM,kBAAkB,EAAE,QAAQ,MAAM,kBAAkB,CAAC;AACzE,UAAM,MAAM,QAAQ,MAAM,SAAS;AAEnC,QAAI,SAAS,MAAM,OAAO,IAAI;AAC5B,aAAO,CAAC,OAAO,IAAI,EAAE;AAAA,IACvB;AACA,WAAO,CAAC,MAAM,MAAM,GAAG,KAAK,GAAG,MAAM,MAAM,OAAO,MAAM,CAAC,GAAG,MAAM,MAAM,MAAM,CAAC,CAAC;AAAA,EAClF;AAAA,EAEA,gBAAgB,OAAyB;AACvC,UAAM,OAAO,SAAS,cAAc,IAAI;AACxC,SAAK,KAAK,uBAAuB,MAAM,KAAK,CAAC;AAC7C,SAAK,aAAa,QAAQ,QAAQ;AAKlC,UAAM,aAAa,KAAK,eAAe,KAAK,CAAC,QAAQ,IAAI,OAAO,MAAM,EAAE;AACxE,SAAK,aAAa,iBAAiB,aAAa,SAAS,OAAO;AAChE,SAAK,aAAa,WAAmB,MAAM,EAAE;AAC7C,kBAAa,cAAc,MAAM,KAAK;AACtC,SAAK;AAAA,MACH;AAAA,MACA;AAAA,IACF;AACA,SAAK,WAAW;AAEhB,QAAI,KAAK,QAAQ,eAAe;AAC9B,YAAM,YAAY,SAAS,cAAc,KAAK;AAC9C,gBAAU,UAAU,IAAI,gBAAgB;AACxC,gBAAU,MAAM,YAAY;AAC5B,YAAM,WAAW,SAAS,cAAc,OAAO;AAC/C,eAAS,OAAO;AAChB,eAAS,WAAW;AACpB,eAAS,UAAU;AACnB,eAAS,WAAW,MAAM,aAAa;AACvC,YAAM,SAAS,SAAS,cAAc,MAAM;AAC5C,aAAO,MAAM,cAAc;AAC3B,gBAAU,OAAO,UAAU,MAAM;AACjC,WAAK,YAAY,SAAS;AAAA,IAC5B;AAEA,QAAI,MAAM,OAAO;AACf,YAAM,MAAM,SAAS,cAAc,KAAK;AACxC,UAAI,UAAU,IAAI,QAAQ;AAC1B,UAAI,MAAM,MAAM;AAChB,WAAK,YAAY,GAAG;AAAA,IACtB;AAEA,UAAM,MAAM,KAAK,aAAa,KAAK;AAEnC,UAAM,WAAW,SAAS,cAAc,KAAK;AAC7C,aAAS,UAAU,IAAI,WAAW;AAClC,aAAS,aAAa,SAAS,8BAA8B;AAC7D,SAAK,YAAY,QAAQ;AACzB,aAAS,YAAY,GAAG;AAExB,QACE,OAAO,MAAM,gBAAgB,YAC5B,OAAO,MAAM,gBAAgB,YAAY,CAAC,MAAM,MAAM,WAAW,GAClE;AACA,YAAM,cAAc,SAAS,cAAc,OAAO;AAClD,kBAAY;AAAA,QACV;AAAA,QACA;AAAA,MACF;AACA,kBAAY,YAAY,MAAM;AAC9B,eAAS,YAAY,WAAW;AAAA,IAClC;AAEA,UAAM,gBAAgB,MAAM;AAC1B,UAAI,KAAK,QAAQ,eAAe;AAC9B,YAAI,MAAM,MAAO,QAAO;AACxB,eAAO;AAAA,MACT;AACA,UAAI,MAAM,MAAO,QAAO;AACxB,aAAO;AAAA,IACT;AACA,SAAK,MAAM,sBAAsB,cAAc;AAC/C,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,OAAe,cAAc,MAAmB,OAAyB;AACvE,QAAI,MAAM,aAAa,KAAM,MAAK,aAAa,iBAAiB,MAAM;AAAA,EACxE;AAAA,EAEA,aAAa,OAAyB;AACpC,UAAM,YAAY,KAAK,GAAG,MAAM,kBAAkB;AAClD,UAAM,SAAS,MAAM,QAAQ,MAAM,IAAI,SAAS;AAChD,UAAM,MAAM,SAAS,cAAc,KAAK;AACxC,QAAI,aAAa,SAAS,kCAAkC;AAG5D,QAAI,KAAK,QAAQ,mBAAmB,MAAM,KAAM,MAAK,eAAe,KAAK,OAAO,SAAS;AAAA,QACpF,MAAK,eAAe,KAAK,KAAK,sBAAsB,WAAW,KAAK,CAAC;AAC1E,WAAO;AAAA,EACT;AAAA,EAEA,eAAe,KAAkB,OAAe,WAAmB;AAIjE,QAAI,YAAY;AAChB,UAAM,SAAS,SAAS,iBAAiB,KAAK,WAAW,SAAS;AAClE,aAAS,OAAO,OAAO,SAAS,GAAW,MAAM,OAAO,OAAO,SAAS,GAAW;AACjF,YAAM,CAAC,QAAQ,KAAK,IAAI,KAAK,sBAAsB,WAAW,KAAK,IAAI;AACvE,UAAI,CAAC,MAAO;AACZ,YAAM,UAAU,KAAK,UAAU,OAAO,MAAM;AAC5C,cAAQ,UAAU,MAAM,MAAM;AAC9B,YAAM,YAAY,SAAS,cAAc,MAAM;AAC/C,gBAAU,UAAU,IAAI,WAAW;AACnC,cAAQ,YAAY,SAAS;AAC7B,gBAAU,OAAO,OAAO;AACxB;AAAA,IACF;AAAA,EACF;AAAA,EAEA,eAAe,KAAkB,OAAiB;AAChD,QAAI,YAAY,SAAS,eAAe,MAAM,CAAC,CAAC,CAAC;AACjD,QAAI,MAAM,CAAC,GAAG;AACZ,YAAM,YAAY,SAAS,cAAc,MAAM;AAC/C,gBAAU,cAAc,MAAM,CAAC;AAC/B,gBAAU,UAAU,IAAI,WAAW;AACnC,UAAI,YAAY,SAAS;AACzB,UAAI,YAAY,SAAS,eAAe,MAAM,CAAC,CAAC,CAAC;AAAA,IACnD;AAAA,EACF;AAAA,EAEA,cAAc;AACZ,SAAK,mBAAmB;AACxB,QAAI,KAAK,WAAY,MAAK,UAAU,OAAO,KAAK,oBAAoB,CAAC;AAErE,QAAI,KAAK,UAAU,WAAW,GAAG;AAC/B,WAAK,YAAY,KAAK;AAAA,IACxB;AACA,UAAM,SAAS,oBAAI,IAAyB;AAC5C,SAAK,UAAU,QAAQ,CAAC,UAAU,KAAK,WAAW,MAAM,OAAO,MAAM,EAAE,OAAO,KAAK,gBAAgB,KAAK,CAAC,CAAC;AAC1G,UAAM,aAAa,KAAK,YAAY;AACpC,QAAI,WAAY,MAAK,UAAU,OAAO,KAAK,WAAW,UAAU,CAAC;AAAA,EACnE;AAAA;AAAA,EAGQ,WAAW,MAA0B,QAAkC;AAC7E,QAAI,CAAC,KAAM,QAAO,KAAK;AACvB,QAAI,CAAC,OAAO,IAAI,IAAI,EAAG,QAAO,IAAI,MAAM,KAAK,aAAa,IAAI,CAAC;AAC/D,WAAO,OAAO,IAAI,IAAI;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,aAAa,MAAc;AACjC,UAAM,UAAU,SAAS,cAAc,IAAI;AAC3C,YAAQ,KAAK,sBAAsB,MAAM,KAAK,CAAC;AAC/C,YAAQ,aAAa,QAAQ,cAAc;AAC3C,YAAQ,UAAU,IAAI,SAAS,0BAA0B;AACzD,YAAQ,cAAc;AACtB,UAAM,OAAO,SAAS,cAAc,IAAI;AACxC,SAAK,aAAa,QAAQ,OAAO;AACjC,SAAK,aAAa,mBAAmB,QAAQ,EAAE;AAC/C,SAAK,OAAO,OAAO;AACnB,UAAM,UAAU,SAAS,cAAc,IAAI;AAC3C,YAAQ,aAAa,QAAQ,MAAM;AACnC,YAAQ,OAAO,IAAI;AACnB,SAAK,UAAU,OAAO,OAAO;AAC7B,WAAO;AAAA,EACT;AAAA;AAAA,EAGQ,cAAc;AACpB,UAAM,OAAO,KAAK,GAAG,MAAM,KAAK;AAChC,QAAI,CAAC,KAAK,QAAQ,eAAe,KAAK,SAAS,KAAK,QAAQ,UAAW,QAAO;AAC9E,UAAM,QAAQ,KAAK,kBAAkB;AACrC,WAAO,KAAK,UAAU,KAAK,CAAC,WAAW,MAAM,QAAQ,OAAO,MAAM,EAAE,GAAG,kBAAkB,MAAM,KAAK,IAAI,KAAK;AAAA,EAC/G;AAAA;AAAA,EAGQ,WAAW,MAAc;AAC/B,UAAM,OAAO,SAAS,cAAc,IAAI;AACxC,SAAK,KAAK,uBAAuB,MAAM,KAAK,CAAC;AAC7C,SAAK,aAAa,QAAQ,QAAQ;AAClC,SAAK,aAAa,iBAAiB,OAAO;AAG1C,SAAK,aAAa,eAAe,IAAI;AACrC,SAAK,UAAU,IAAI,qBAAqB;AACxC,SAAK,aAAa,SAAS,uDAAuD;AAClF,SAAK,WAAW;AAChB,UAAM,QAAQ,SAAS,cAAc,KAAK;AAC1C,UAAM,UAAU,IAAI,WAAW;AAC/B,UAAM,aAAa,SAAS,8DAA8D;AAC1F,UAAM,cAAc,KAAK,QAAQ,KAAK,OAAO,IAAI;AACjD,SAAK,OAAO,KAAK;AACjB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,sBAAsB;AAC5B,UAAM,MAAM,SAAS,cAAc,IAAI;AACvC,QAAI,UAAU,IAAI,yBAAyB;AAC3C,QAAI,aAAa,QAAQ,MAAM;AAC/B,QAAI,aAAa,eAAe,MAAM;AACtC,QAAI,cAAc,KAAK,QAAQ,KAAK;AACpC,WAAO;AAAA,EACT;AAAA,EAEA,oBAAoB;AAClB,UAAM,gBAAgB,KAAK;AAC3B,QAAI,cAAe,eAAc,gBAAgB,cAAa,kBAAkB,CAAC;AACjF,SAAK,UAAU,KAAK,QAAQ,KAAK,OAAO;AAAA,EAC1C;AAAA,EAEQ,UAAU,SAAiB;AACjC,QAAI,CAAC,KAAK,WAAY;AACtB,UAAM,OAAO,KAAK,GAAG,QAAQ,QAAQ,KAAK,KAAK,GAAG,MAAM,UAAU,KAAK,QAAQ,YAAY,UAAU;AACrG,QAAI,KAAK,WAAW,gBAAgB,KAAM,MAAK,WAAW,cAAc;AAAA,EAC1E;AAAA;AAAA,EAGQ,kBAAkB;AACxB,UAAM,QAAQ,KAAK,UAAU,OAAO,CAAC,UAAU,MAAM,aAAa,IAAI,EAAE;AACxE,WAAO,QAAQ,KAAK,QAAQ,KAAK,QAAQ,KAAK,IAAI,KAAK,QAAQ,KAAK;AAAA,EACtE;AAAA,EAEA,sBAAsB;AACpB,UAAM,gBAAgB,KAAK;AAC3B,QAAI,eAAe;AACjB,UAAI,KAAK,QAAQ;AACf,sBAAc,cAAc,KAAK,eAAe,OAAO,SAAS;AAAA,UAC7D,eAAc,gBAAgB;AAAA,IACrC;AAAA,EACF;AAAA,EAEA,oBAAoB;AAClB,QAAI,KAAK,eAAe,WAAW,GAAG;AACpC,YAAM,QAAQ,KAAK,eAAe,CAAC;AACnC,WAAK,GAAG,QAAQ,MAAM,QAAgB,MAAM;AAAA,IAC9C;AAAA,EACF;AAAA,EAEA,kBAAkB;AAEhB,UAAM,SAAS,KAAK;AACpB,UAAM,YAAY,EAAE,KAAK;AACzB,SAAK,GAAG,cAAc,IAAI,MAAM,UAAU,EAAE,SAAS,MAAM,YAAY,MAAM,UAAU,KAAK,CAAC,CAAC;AAC9F,QAAI,cAAc,KAAK,WAAY;AACnC,SAAK,QAAQ,gBAAgB,KAAK,QAAQ,gBAAgB,EAAE,MAAM,CAAC,MAAM,GAAG,QAAQ,EAAE,OAAO,GAAG,SAAS,MAAM,cAAc,KAAK,WAAW,CAAC;AAAA,EAChJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA4CA,aAAa,WAA+B,WAAgC,MAAM,OAAgB,MAAM;AACtG,QAAI,KAAK,GAAG,yBAAyB,MAAM,KAAM;AAGjD,oBAAS,CAAC,KAAK;AACf,SAAK,aAAa,UAAU,WAAW;AACvC,SAAK,YAAY;AACjB,QAAI,UAAU;AACZ,WAAK,iBAAiB,KAAK,UAAU;AAAA,QACnC,CAAC,SAAS,EAAE,SAAS,QAAe,KAAK,EAAE,MAAM;AAAA,MACnD;AAAA,IACF;AAEA,QAAI,KAAK,QAAQ,eAAe;AAC9B,UAAI,CAAC,KAAM,MAAK,YAAY;AAAA,IAC9B,OAAO;AACL,WAAK,kBAAkB;AAAA,IACzB;AACA,QAAI,KAAM,MAAK,KAAK;AACpB,SAAK,oBAAoB;AACzB,SAAK,UAAU,OAAO,KAAK,gBAAgB,IAAI,EAAE;AACjD,QAAI,SAAU,MAAK,gBAAgB;AAAA,EACrC;AAAA,EAEQ,cAAc,OAAyB;AAC7C,UAAM,WAAW,CAAC,KAAK,eAAe,KAAK,CAAC,kBAAkB,cAAc,OAAO,MAAM,EAAE;AAC3F,QAAI,SAAU,MAAK,eAAe,KAAK,KAAK;AAAA,QACvC,MAAK,iBAAiB,KAAK,eAAe,OAAO,CAAC,kBAAkB,cAAc,OAAO,MAAM,EAAE;AAGtG,UAAM,MAAM,MAAM,KAAK,KAAK,UAAU,iBAAiB,aAAa,CAAC,EAAE,KAAK,CAAC,OAAO,GAAG,aAAa,SAAS,MAAM,OAAO,MAAM,EAAE,CAAC;AACnI,QAAI,KAAK;AACP,UAAI,aAAa,iBAAiB,OAAO,QAAQ,CAAC;AAClD,UAAI,cAAc,OAAO,EAAE,UAAU;AAAA,IACvC;AACA,SAAK,GAAG,MAAM;AAAA,EAChB;AAAA,EAEQ,cAAc,OAAyB;AAG7C,UAAM,UAAU,MAAM,UAAU,KAAK,SAAS;AAE9C,SAAK,qBAAqB;AAC1B,SAAK,iBAAiB,CAAC,KAAK;AAC5B,SAAK,kBAAkB;AACvB,SAAK,mBAAmB;AACxB,SAAK,MAAM;AACX,QAAI,SAAS;AAEX,WAAK,SAAS,KAAK,GAAG,MAAM,kBAAkB;AAC9C,WAAK,GAAG,MAAM;AAAA,IAChB;AAAA,EACF;AAAA;AAAA,EAGQ,QAAQ,IAAa;AAC3B,QAAI,GAAG,aAAa,aAAa,EAAG,MAAK,QAAQ,GAAG,aAAa,aAAa,CAAC;AAAA,QAC1E,MAAK,aAAa,GAAG,aAAa,SAAS,CAAC;AAAA,EACnD;AAAA,EAEQ,QAAQ,MAAc;AAC5B,UAAM,UAAU,MAAM,UAAU,KAAK,SAAS;AAE9C,SAAK,qBAAqB;AAE1B,SAAK,SAAS,KAAK,GAAG,MAAM,kBAAkB;AAC9C,SAAK,MAAM;AACX,QAAI,QAAS,MAAK,GAAG,MAAM;AAC3B,SAAK,QAAQ,UAAU,KAAK,QAAQ,UAAU,EAAE,MAAM,CAAC,MAAM,IAAI,GAAG,QAAQ,EAAE,KAAK,EAAE,CAAC;AAAA,EACxF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAa,IAAqB;AAEhC,UAAM,QAAQ,KAAK,UAAU,KAAK,CAAC,SAAS,KAAK,MAAM,MAAM,KAAK,aAAa,IAAI;AACnF,QAAI,CAAC,MAAO;AACZ,QAAI,KAAK,QAAQ,cAAe,MAAK,cAAc,KAAK;AAAA,QACnD,MAAK,cAAc,KAAK;AAC7B,SAAK,oBAAoB;AACzB,QAAI,KAAK,QAAQ,cAAe,MAAK,UAAU,KAAK,QAAQ,KAAK,SAAS,KAAK,eAAe,MAAM,CAAC;AACrG,SAAK,gBAAgB;AAAA,EACvB;AACF;AApxBa,cA0EJ,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA1EF,cAmFI,mBAAgC;AAnF1C,IAAM,eAAN;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import {
|
|
2
|
+
LineChart,
|
|
3
|
+
numberFormat
|
|
4
|
+
} from "./chunk-ZM3XBHWV.mjs";
|
|
5
|
+
|
|
6
|
+
// src/ts/components/treemapChart.ts
|
|
7
|
+
var COLORS = 6;
|
|
8
|
+
var NEXT = ["ArrowRight", "ArrowDown"];
|
|
9
|
+
var PREVIOUS = ["ArrowLeft", "ArrowUp"];
|
|
10
|
+
var sum = (areas) => areas.reduce((total, area) => total + area, 0);
|
|
11
|
+
var flip = ([x, y, width, height]) => [y, x, height, width];
|
|
12
|
+
function worst(areas, side) {
|
|
13
|
+
const [total, squared] = [sum(areas) ** 2, side ** 2];
|
|
14
|
+
return Math.max(...areas.map((area) => Math.max(squared * area / total, total / (squared * area))));
|
|
15
|
+
}
|
|
16
|
+
function strip(areas, free) {
|
|
17
|
+
if (free[2] < free[3]) {
|
|
18
|
+
const [boxes2, rest] = strip(areas, flip(free));
|
|
19
|
+
return [boxes2.map(flip), flip(rest)];
|
|
20
|
+
}
|
|
21
|
+
const [x, y, width, height] = free;
|
|
22
|
+
const across = sum(areas) / height;
|
|
23
|
+
let top = y;
|
|
24
|
+
const boxes = areas.map((area) => {
|
|
25
|
+
const box = [x, top, across, area / across];
|
|
26
|
+
top += area / across;
|
|
27
|
+
return box;
|
|
28
|
+
});
|
|
29
|
+
return [boxes, [x + across, y, width - across, height]];
|
|
30
|
+
}
|
|
31
|
+
function squarify(areas, free) {
|
|
32
|
+
const boxes = [];
|
|
33
|
+
let row = [];
|
|
34
|
+
for (const area of areas) {
|
|
35
|
+
const side = Math.min(free[2], free[3]);
|
|
36
|
+
if (row.length && worst([...row, area], side) > worst(row, side)) {
|
|
37
|
+
const [laid, rest] = strip(row, free);
|
|
38
|
+
boxes.push(...laid);
|
|
39
|
+
[free, row] = [rest, []];
|
|
40
|
+
}
|
|
41
|
+
row.push(area);
|
|
42
|
+
}
|
|
43
|
+
return [...boxes, ...strip(row, free)[0]];
|
|
44
|
+
}
|
|
45
|
+
var inside = ([x, y, width, height], at, down) => at >= x && at < x + width && down >= y && down < y + height;
|
|
46
|
+
var hang = (y, height) => y + height / 2 > 0.5 ? { top: "auto", bottom: `${(1 - y - height) * 100}%` } : { top: `${y * 100}%`, bottom: "auto" };
|
|
47
|
+
var TreemapChart = class extends LineChart {
|
|
48
|
+
get _type() {
|
|
49
|
+
return "treemap-chart";
|
|
50
|
+
}
|
|
51
|
+
/** Area carries the value, so there is no value axis. */
|
|
52
|
+
get _axis() {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
get _points() {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Highlights one row: outlines its rectangle and fills the tooltip, with
|
|
60
|
+
* the row's share. A row with no rectangle passes to the next one with
|
|
61
|
+
* one, as when focus asks for the first row. Pass -1 to hide them.
|
|
62
|
+
*/
|
|
63
|
+
show(index) {
|
|
64
|
+
const row = this._drawnFrom(index);
|
|
65
|
+
if (!this._tooltip || row === this.activeIndex) return;
|
|
66
|
+
this._boxes.forEach((box, i) => box?.classList.toggle("active", i === row));
|
|
67
|
+
super.show(row);
|
|
68
|
+
this._share(row);
|
|
69
|
+
}
|
|
70
|
+
/** The first row from `index` on with a rectangle, or -1. */
|
|
71
|
+
_drawnFrom(index) {
|
|
72
|
+
return index < 0 ? index : this._boxes.findIndex((box, i) => i >= index && box);
|
|
73
|
+
}
|
|
74
|
+
/** Adds the row's share of the whole to its cell in the tooltip, as the pie chart writes it. */
|
|
75
|
+
_share(row) {
|
|
76
|
+
if (row < 0) return;
|
|
77
|
+
const share = this._values[row] / sum(this._values);
|
|
78
|
+
const percent = numberFormat(this.el, { style: "percent", maximumFractionDigits: share < 0.1 ? 1 : 0 });
|
|
79
|
+
this._tooltip.querySelector("span:nth-of-type(2)").textContent += ` (${percent.format(share)})`;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Opens the tooltip from the middle of the row's rectangle toward the
|
|
83
|
+
* middle of the plot.
|
|
84
|
+
*/
|
|
85
|
+
_place(index) {
|
|
86
|
+
const [x, y, width, height] = this._places[index];
|
|
87
|
+
const middle = x + width / 2;
|
|
88
|
+
const left = this._reversed ? 1 - middle : middle;
|
|
89
|
+
Object.assign(this._tooltip.style, { left: `${left * 100}%`, ...hang(y, height) });
|
|
90
|
+
this._tooltip.classList.toggle("end", left > 0.5);
|
|
91
|
+
}
|
|
92
|
+
/** The row whose rectangle is under the pointer, or -1. */
|
|
93
|
+
_indexAt(e) {
|
|
94
|
+
const box = this._plot.getBoundingClientRect();
|
|
95
|
+
const across = (e.clientX - box.left) / box.width;
|
|
96
|
+
const [at, down] = [this._reversed ? 1 - across : across, (e.clientY - box.top) / box.height];
|
|
97
|
+
return this._places.findIndex((place) => place && inside(place, at, down));
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* The arrows step through the rows with a rectangle in table order, which
|
|
101
|
+
* runs in no one direction on screen, so they do not swap in a
|
|
102
|
+
* right-to-left page. Home and End go to the first and last of them.
|
|
103
|
+
*/
|
|
104
|
+
_keyTarget(key) {
|
|
105
|
+
const drawn = this._boxes.flatMap((box, i) => box ? [i] : []);
|
|
106
|
+
const [at, last] = [drawn.indexOf(this.activeIndex), drawn.length - 1];
|
|
107
|
+
const step = NEXT.includes(key) ? Math.min(at + 1, last) : PREVIOUS.includes(key) ? Math.max(at - 1, 0) : { Home: 0, End: last }[key];
|
|
108
|
+
return step === void 0 ? super._keyTarget(key) : drawn[step];
|
|
109
|
+
}
|
|
110
|
+
destroy() {
|
|
111
|
+
this._sizes?.disconnect();
|
|
112
|
+
super.destroy();
|
|
113
|
+
}
|
|
114
|
+
/** Neither row labels nor a legend: each rectangle carries its name. */
|
|
115
|
+
_guides() {
|
|
116
|
+
return [];
|
|
117
|
+
}
|
|
118
|
+
/** One rectangle per positive row, in table order, placed by _layout(). */
|
|
119
|
+
_draw() {
|
|
120
|
+
this._values = this.series[0].values.map((value) => Math.max(0, value ?? 0));
|
|
121
|
+
const container = document.createElement("div");
|
|
122
|
+
container.className = "treemap-chart-boxes";
|
|
123
|
+
container.setAttribute("aria-hidden", "true");
|
|
124
|
+
let drawn = 0;
|
|
125
|
+
this._boxes = this._values.map((value, i) => {
|
|
126
|
+
if (!value) return null;
|
|
127
|
+
const box = document.createElement("div");
|
|
128
|
+
box.className = "treemap-chart-box";
|
|
129
|
+
box.dataset.series = String(drawn++ % COLORS + 1);
|
|
130
|
+
const [name, text] = [document.createElement("span"), document.createElement("span")];
|
|
131
|
+
[name.textContent, text.textContent] = [this.labels[i], this.series[0].text[i]];
|
|
132
|
+
box.append(name, text);
|
|
133
|
+
container.append(box);
|
|
134
|
+
return box;
|
|
135
|
+
});
|
|
136
|
+
this.el.append(this._plot);
|
|
137
|
+
this._layout();
|
|
138
|
+
this._sizes?.disconnect();
|
|
139
|
+
this._sizes = new ResizeObserver(() => this._layout());
|
|
140
|
+
this._sizes.observe(this._plot);
|
|
141
|
+
return container;
|
|
142
|
+
}
|
|
143
|
+
/** Squarifies the positive rows, largest first, equal values in table order, and places their rectangles. */
|
|
144
|
+
_layout() {
|
|
145
|
+
const [width, height] = [this._plot.clientWidth || 1, this._plot.clientHeight || 1];
|
|
146
|
+
const rows = this._values.map((_, i) => i).filter((i) => this._values[i]).sort((a, b) => this._values[b] - this._values[a]);
|
|
147
|
+
const scale = width * height / sum(this._values);
|
|
148
|
+
const laid = squarify(rows.map((i) => this._values[i] * scale), [0, 0, width, height]);
|
|
149
|
+
this._places = [];
|
|
150
|
+
rows.forEach((row, k) => {
|
|
151
|
+
const [x, y, w, h] = laid[k];
|
|
152
|
+
const place = this._places[row] = [x / width, y / height, w / width, h / height];
|
|
153
|
+
Object.assign(this._boxes[row].style, {
|
|
154
|
+
insetInlineStart: `${place[0] * 100}%`,
|
|
155
|
+
top: `${place[1] * 100}%`,
|
|
156
|
+
width: `${place[2] * 100}%`,
|
|
157
|
+
height: `${place[3] * 100}%`
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
TreemapChart.key = "Expressive_TreemapChart";
|
|
163
|
+
|
|
164
|
+
export {
|
|
165
|
+
TreemapChart
|
|
166
|
+
};
|
|
167
|
+
//# sourceMappingURL=chunk-VH4BMAZS.mjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/ts/components/treemapChart.ts"],
|
|
4
|
+
"sourcesContent": ["import { LineChart, LineChartOptions, numberFormat } from './lineChart';\n\nexport type TreemapChartOptions = LineChartOptions;\n\n/** A rectangle: its inline start, top, width and height. */\ntype Box = [x: number, y: number, width: number, height: number];\n\n// ponytail: rows past six repeat the colors, so neighbours can match.\nconst COLORS = 6;\n/** The keys that move to the next row and to the one before, in any direction. */\nconst NEXT = ['ArrowRight', 'ArrowDown'];\nconst PREVIOUS = ['ArrowLeft', 'ArrowUp'];\n\nconst sum = (areas: number[]) => areas.reduce((total, area) => total + area, 0);\n\n/** The box with its axes swapped, so one strip routine lays out both ways. */\nconst flip = ([x, y, width, height]: Box): Box => [y, x, height, width];\n\n/** How far the least square of `areas` is from square, in a strip along a side `side` long. */\nfunction worst(areas: number[], side: number) {\n const [total, squared] = [sum(areas) ** 2, side ** 2];\n return Math.max(...areas.map((area) => Math.max((squared * area) / total, total / (squared * area))));\n}\n\n/**\n * Lays `areas` out as one strip down the inline start of `free`, or across\n * its top when it is taller than wide, in order, and returns their boxes and\n * the space left beside the strip.\n */\nfunction strip(areas: number[], free: Box): [Box[], Box] {\n if (free[2] < free[3]) {\n const [boxes, rest] = strip(areas, flip(free));\n return [boxes.map(flip), flip(rest)];\n }\n const [x, y, width, height] = free;\n const across = sum(areas) / height;\n let top = y;\n const boxes = areas.map((area): Box => {\n const box: Box = [x, top, across, area / across];\n top += area / across;\n return box;\n });\n return [boxes, [x + across, y, width - across, height]];\n}\n\n/**\n * The squarified treemap of Bruls, Huizing and van Wijk: `areas`, largest\n * first and adding up to the free box's area, each join the current strip\n * while that keeps its rectangles nearer square, and the strip is laid down\n * when it would not.\n */\nfunction squarify(areas: number[], free: Box): Box[] {\n const boxes: Box[] = [];\n let row: number[] = [];\n for (const area of areas) {\n const side = Math.min(free[2], free[3]);\n if (row.length && worst([...row, area], side) > worst(row, side)) {\n const [laid, rest] = strip(row, free);\n boxes.push(...laid);\n [free, row] = [rest, []];\n }\n row.push(area);\n }\n return [...boxes, ...strip(row, free)[0]];\n}\n\n/** Whether a point, as fractions of the plot, lies in a box. */\nconst inside = ([x, y, width, height]: Box, at: number, down: number) =>\n at >= x && at < x + width && down >= y && down < y + height;\n\n/**\n * The tooltip's top or bottom for a box: from its top in the plot's upper\n * half, and up from its bottom in the lower half, so it stays in the plot.\n */\nconst hang = (y: number, height: number) => (y + height / 2 > 0.5\n ? { top: 'auto', bottom: `${(1 - y - height) * 100}%` }\n : { top: `${y * 100}%`, bottom: 'auto' });\n\n/**\n * Treemap chart. It reads its <table> like LineChart, but draws each row of\n * the first value column as a rectangle whose area is its share of the\n * whole, filling the plot, the largest at the top inline-start corner. Rows\n * with no positive value draw nothing. Further columns show in the tooltip.\n *\n * Call `update()` after changing the table, or start it with `watch` or\n * `data-watch`.\n */\nexport class TreemapChart extends LineChart {\n // No initializers: LineChart's constructor draws before they would run.\n /** Each row's positive value, or 0 for a row with no rectangle. */\n private _values: number[];\n /** Each row's rectangle, or null. */\n private _boxes: (HTMLElement | null)[];\n /** Each drawn row's place as fractions of the plot. */\n private _places: Box[];\n /** Lays the rectangles out again when the plot changes shape. */\n private _sizes: ResizeObserver;\n\n protected get _type() {\n return 'treemap-chart';\n }\n\n /** Area carries the value, so there is no value axis. */\n protected get _axis() {\n return false;\n }\n\n protected get _points() {\n return false;\n }\n\n static key = 'Expressive_TreemapChart';\n\n /**\n * Highlights one row: outlines its rectangle and fills the tooltip, with\n * the row's share. A row with no rectangle passes to the next one with\n * one, as when focus asks for the first row. Pass -1 to hide them.\n */\n show(index: number) {\n const row = this._drawnFrom(index);\n if (!this._tooltip || row === this.activeIndex) return;\n this._boxes.forEach((box, i) => box?.classList.toggle('active', i === row));\n super.show(row);\n this._share(row);\n }\n\n /** The first row from `index` on with a rectangle, or -1. */\n private _drawnFrom(index: number) {\n return index < 0 ? index : this._boxes.findIndex((box, i) => i >= index && box);\n }\n\n /** Adds the row's share of the whole to its cell in the tooltip, as the pie chart writes it. */\n private _share(row: number) {\n if (row < 0) return;\n const share = this._values[row] / sum(this._values);\n // Whole percentages, with a tenth below 10% so a small part is not 0%.\n const percent = numberFormat(this.el, { style: 'percent', maximumFractionDigits: share < 0.1 ? 1 : 0 });\n this._tooltip.querySelector('span:nth-of-type(2)')!.textContent += ` (${percent.format(share)})`;\n }\n\n /**\n * Opens the tooltip from the middle of the row's rectangle toward the\n * middle of the plot.\n */\n protected _place(index: number) {\n const [x, y, width, height] = this._places[index];\n const middle = x + width / 2;\n const left = this._reversed ? 1 - middle : middle;\n Object.assign(this._tooltip.style, { left: `${left * 100}%`, ...hang(y, height) });\n this._tooltip.classList.toggle('end', left > 0.5);\n }\n\n /** The row whose rectangle is under the pointer, or -1. */\n protected _indexAt(e: PointerEvent) {\n const box = this._plot.getBoundingClientRect();\n const across = (e.clientX - box.left) / box.width;\n const [at, down] = [this._reversed ? 1 - across : across, (e.clientY - box.top) / box.height];\n return this._places.findIndex((place) => place && inside(place, at, down));\n }\n\n /**\n * The arrows step through the rows with a rectangle in table order, which\n * runs in no one direction on screen, so they do not swap in a\n * right-to-left page. Home and End go to the first and last of them.\n */\n protected _keyTarget(key: string): number | undefined {\n const drawn = this._boxes.flatMap((box, i) => (box ? [i] : []));\n const [at, last] = [drawn.indexOf(this.activeIndex), drawn.length - 1];\n const step = NEXT.includes(key) ? Math.min(at + 1, last)\n : PREVIOUS.includes(key) ? Math.max(at - 1, 0)\n : ({ Home: 0, End: last } as Record<string, number>)[key];\n return step === undefined ? super._keyTarget(key) : drawn[step];\n }\n\n destroy() {\n this._sizes?.disconnect();\n super.destroy();\n }\n\n /** Neither row labels nor a legend: each rectangle carries its name. */\n protected _guides(): Element[] {\n return [];\n }\n\n /** One rectangle per positive row, in table order, placed by _layout(). */\n protected _draw(): Element {\n this._values = this.series[0].values.map((value) => Math.max(0, value ?? 0));\n const container = document.createElement('div');\n container.className = 'treemap-chart-boxes';\n container.setAttribute('aria-hidden', 'true');\n let drawn = 0;\n this._boxes = this._values.map((value, i) => {\n if (!value) return null;\n const box = document.createElement('div');\n box.className = 'treemap-chart-box';\n box.dataset.series = String((drawn++ % COLORS) + 1);\n const [name, text] = [document.createElement('span'), document.createElement('span')];\n [name.textContent, text.textContent] = [this.labels[i], this.series[0].text[i]];\n box.append(name, text);\n container.append(box);\n return box;\n });\n // The squares depend on the plot's shape, so it goes in the page to be measured.\n this.el.append(this._plot);\n this._layout();\n this._sizes?.disconnect();\n this._sizes = new ResizeObserver(() => this._layout());\n this._sizes.observe(this._plot);\n return container;\n }\n\n /** Squarifies the positive rows, largest first, equal values in table order, and places their rectangles. */\n private _layout() {\n // A hidden plot has no size; lay it out as a square until it shows.\n const [width, height] = [this._plot.clientWidth || 1, this._plot.clientHeight || 1];\n const rows = this._values.map((_, i) => i).filter((i) => this._values[i]).sort((a, b) => this._values[b] - this._values[a]);\n const scale = (width * height) / sum(this._values);\n const laid = squarify(rows.map((i) => this._values[i] * scale), [0, 0, width, height]);\n this._places = [];\n rows.forEach((row, k) => {\n const [x, y, w, h] = laid[k];\n const place = (this._places[row] = [x / width, y / height, w / width, h / height]);\n Object.assign(this._boxes[row]!.style, {\n insetInlineStart: `${place[0] * 100}%`,\n top: `${place[1] * 100}%`,\n width: `${place[2] * 100}%`,\n height: `${place[3] * 100}%`\n });\n });\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["boxes"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Component
|
|
3
|
+
} from "./chunk-CMGXGYUC.mjs";
|
|
4
|
+
|
|
5
|
+
// src/ts/components/inputMask.ts
|
|
6
|
+
var _defaults = Object.freeze({});
|
|
7
|
+
var SLOTS = { "0": /[0-9]/, a: /\p{L}/u, "*": /[0-9\p{L}]/u };
|
|
8
|
+
var DELETES = { deleteContentBackward: -1, deleteContentForward: 1 };
|
|
9
|
+
var parse = (mask) => (mask.match(/\\[^]|[^]/gu) ?? []).map((part) => SLOTS[part] ? { accepts: SLOTS[part] } : { literal: part.slice(-1) });
|
|
10
|
+
function landing(tokens, t, ch) {
|
|
11
|
+
if (tokens[t]?.literal === ch) return t;
|
|
12
|
+
const slot = tokens.findIndex((token, i) => i >= t && "accepts" in token);
|
|
13
|
+
return slot < 0 ? tokens.length : slot;
|
|
14
|
+
}
|
|
15
|
+
function place(tokens, t, ch, chars) {
|
|
16
|
+
const at = landing(tokens, t, ch);
|
|
17
|
+
const token = tokens[at];
|
|
18
|
+
if (!token) return t;
|
|
19
|
+
if ("literal" in token) return at + 1;
|
|
20
|
+
if (!token.accepts.test(ch)) return t;
|
|
21
|
+
chars.push(ch);
|
|
22
|
+
return at + 1;
|
|
23
|
+
}
|
|
24
|
+
function read(tokens, value, caret) {
|
|
25
|
+
const chars = [];
|
|
26
|
+
let t = 0;
|
|
27
|
+
let at = 0;
|
|
28
|
+
let before = 0;
|
|
29
|
+
for (const typed of value) {
|
|
30
|
+
for (const ch of typed.normalize("NFKC")) t = place(tokens, t, ch, chars);
|
|
31
|
+
at += typed.length;
|
|
32
|
+
if (at <= caret) before = chars.length;
|
|
33
|
+
}
|
|
34
|
+
return { chars, before };
|
|
35
|
+
}
|
|
36
|
+
function write(tokens, chars) {
|
|
37
|
+
let text = "";
|
|
38
|
+
let pending = "";
|
|
39
|
+
const ends = [];
|
|
40
|
+
for (const token of tokens) {
|
|
41
|
+
if (ends.length === chars.length) break;
|
|
42
|
+
if ("literal" in token) pending += token.literal;
|
|
43
|
+
else {
|
|
44
|
+
text += pending + chars[ends.length];
|
|
45
|
+
pending = "";
|
|
46
|
+
ends.push(text.length);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return { text, ends };
|
|
50
|
+
}
|
|
51
|
+
var InputMask = class extends Component {
|
|
52
|
+
constructor(el, options) {
|
|
53
|
+
super(el, options);
|
|
54
|
+
this._onInput = (e) => {
|
|
55
|
+
if (!e.isComposing) this._format();
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Backspace after a literal, or Delete before one, would remove the
|
|
59
|
+
* literal, which the mask then writes back. It removes the slot character
|
|
60
|
+
* across the literal instead.
|
|
61
|
+
*/
|
|
62
|
+
this._onBeforeInput = (e) => {
|
|
63
|
+
const step = DELETES[e.inputType];
|
|
64
|
+
const index = step && this.el.selectionStart === this.el.selectionEnd ? this._acrossLiteral(step) : -1;
|
|
65
|
+
if (index < 0) return;
|
|
66
|
+
e.preventDefault();
|
|
67
|
+
this._remove(index, e.inputType);
|
|
68
|
+
};
|
|
69
|
+
this._onReset = (e) => {
|
|
70
|
+
if (e.target === this.el.form) setTimeout(this._afterReset);
|
|
71
|
+
};
|
|
72
|
+
this._afterReset = () => {
|
|
73
|
+
if (!this._events.signal.aborted) this._rewrite();
|
|
74
|
+
};
|
|
75
|
+
this._format = () => {
|
|
76
|
+
const caret = this._rewrite();
|
|
77
|
+
if (caret !== null && this.el.ownerDocument.activeElement === this.el) this.el.setSelectionRange(caret, caret);
|
|
78
|
+
};
|
|
79
|
+
this._tokens = parse(el.dataset.mask ?? "");
|
|
80
|
+
if (!this._tokens.some((token) => "accepts" in token)) return;
|
|
81
|
+
const signal = this._events.signal;
|
|
82
|
+
el.addEventListener("input", this._onInput, { capture: true, signal });
|
|
83
|
+
el.addEventListener("compositionend", this._format, { signal });
|
|
84
|
+
el.addEventListener("beforeinput", this._onBeforeInput, { signal });
|
|
85
|
+
el.ownerDocument.addEventListener("reset", this._onReset, { capture: true, signal });
|
|
86
|
+
this._rewrite();
|
|
87
|
+
}
|
|
88
|
+
static get defaults() {
|
|
89
|
+
return _defaults;
|
|
90
|
+
}
|
|
91
|
+
/** The index among the slot characters to delete when the character `step` from the caret is a literal, or -1. */
|
|
92
|
+
_acrossLiteral(step) {
|
|
93
|
+
const { selectionStart: caret, value } = this.el;
|
|
94
|
+
const here = read(this._tokens, value, caret);
|
|
95
|
+
const index = here.before + Math.min(step, 0);
|
|
96
|
+
return read(this._tokens, value, caret + step).before === here.before && index in here.chars ? index : -1;
|
|
97
|
+
}
|
|
98
|
+
/** Removes slot character `index`, puts the caret where it was, and reports the edit as typing would. */
|
|
99
|
+
_remove(index, inputType) {
|
|
100
|
+
const { chars } = read(this._tokens, this.el.value, 0);
|
|
101
|
+
chars.splice(index, 1);
|
|
102
|
+
const { text, ends } = write(this._tokens, chars);
|
|
103
|
+
this.el.value = text;
|
|
104
|
+
const caret = ends[index - 1] ?? 0;
|
|
105
|
+
this.el.setSelectionRange(caret, caret);
|
|
106
|
+
this.el.dispatchEvent(new InputEvent("input", { bubbles: true, composed: true, inputType }));
|
|
107
|
+
}
|
|
108
|
+
/** Rewrites the value to the mask. Returns where the caret goes, or null when the value already fit. */
|
|
109
|
+
_rewrite() {
|
|
110
|
+
const el = this.el;
|
|
111
|
+
const { chars, before } = read(this._tokens, el.value, el.selectionEnd ?? el.value.length);
|
|
112
|
+
const { text, ends } = write(this._tokens, chars);
|
|
113
|
+
if (text === el.value) return null;
|
|
114
|
+
el.value = text;
|
|
115
|
+
return ends[before - 1] ?? 0;
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
InputMask.key = "Expressive_InputMask";
|
|
119
|
+
|
|
120
|
+
export {
|
|
121
|
+
InputMask
|
|
122
|
+
};
|
|
123
|
+
//# sourceMappingURL=chunk-VJVQIXHC.mjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/ts/components/inputMask.ts"],
|
|
4
|
+
"sourcesContent": ["import { Component, BaseOptions } from '../core/component';\n\nconst _defaults = Object.freeze({});\n\n/** A mask position: a slot that takes the characters `accepts` matches, or a literal the mask writes itself. */\ntype Token = { accepts: RegExp } | { literal: string };\n\n/** What each slot character in a mask accepts. */\nconst SLOTS: Record<string, RegExp> = { '0': /[0-9]/, a: /\\p{L}/u, '*': /[0-9\\p{L}]/u };\n\n/** Which way a one-character delete from a collapsed caret goes. */\nconst DELETES: Record<string, number> = { deleteContentBackward: -1, deleteContentForward: 1 };\n\n/** Splits a mask into tokens. A backslash makes the character after it a literal. */\nconst parse = (mask: string): Token[] =>\n (mask.match(/\\\\[^]|[^]/gu) ?? []).map((part) => (SLOTS[part] ? { accepts: SLOTS[part] } : { literal: part.slice(-1) }));\n\n/**\n * The token `ch` lands on from token `t`: the literal at `t` when `ch` is that\n * literal, otherwise the next slot. Only the literal at `t` counts, so a\n * digit is not taken for a literal further on, such as the 1 in `+1 (000)`.\n */\nfunction landing(tokens: Token[], t: number, ch: string) {\n if ((tokens[t] as { literal?: string })?.literal === ch) return t;\n const slot = tokens.findIndex((token, i) => i >= t && 'accepts' in token);\n return slot < 0 ? tokens.length : slot;\n}\n\n/** Feeds `ch` to the mask at token `t`, keeping it in `chars` if a slot takes it. Returns the next token. */\nfunction place(tokens: Token[], t: number, ch: string, chars: string[]) {\n const at = landing(tokens, t, ch);\n const token = tokens[at];\n if (!token) return t;\n if ('literal' in token) return at + 1;\n if (!token.accepts.test(ch)) return t;\n chars.push(ch);\n return at + 1;\n}\n\n/**\n * The slot characters in `value`, in order, and how many of them come before\n * `caret`. Characters are normalized first, so full-width digits from an IME\n * fill digit slots. A character that neither fits a slot nor matches the next\n * literal is dropped, and so is any past the last slot.\n */\nfunction read(tokens: Token[], value: string, caret: number) {\n const chars: string[] = [];\n let t = 0;\n let at = 0;\n let before = 0;\n for (const typed of value) {\n for (const ch of typed.normalize('NFKC')) t = place(tokens, t, ch, chars);\n at += typed.length;\n if (at <= caret) before = chars.length;\n }\n return { chars, before };\n}\n\n/**\n * Writes `chars` into the mask's slots, with the literals that come before\n * each filled slot and none after the last. Returns the text and the index\n * just after each slot character.\n */\nfunction write(tokens: Token[], chars: string[]) {\n let text = '';\n let pending = '';\n const ends: number[] = [];\n for (const token of tokens) {\n if (ends.length === chars.length) break;\n if ('literal' in token) pending += token.literal;\n else {\n text += pending + chars[ends.length];\n pending = '';\n ends.push(text.length);\n }\n }\n return { text, ends };\n}\n\n/**\n * Input mask. Formats a text field's value to the pattern in its `data-mask`\n * attribute as people type, paste or compose: `0` takes a digit, `a` a\n * letter, `*` either, and every other character is a literal the mask writes\n * itself. The form submits the value as the field shows it.\n */\nexport class InputMask extends Component<BaseOptions> {\n declare el: HTMLInputElement;\n static key = 'Expressive_InputMask';\n private _tokens: Token[];\n\n constructor(el: HTMLInputElement, options: Partial<BaseOptions>) {\n super(el, options);\n this._tokens = parse(el.dataset.mask ?? '');\n // A mask with no slot would format every value to nothing, erasing a\n // saved value, so the component leaves such a field alone.\n if (!this._tokens.some((token) => 'accepts' in token)) return;\n const signal = this._events.signal;\n // Capture, which runs before the field's own bubble listeners, so the\n // page's input listeners read the formatted value.\n el.addEventListener('input', this._onInput, { capture: true, signal });\n // An IME writes as it composes; the mask waits until it is done. Engines\n // fire the last input before or after compositionend, and formatting\n // twice changes nothing.\n el.addEventListener('compositionend', this._format, { signal });\n el.addEventListener('beforeinput', this._onBeforeInput, { signal });\n // The form resets its fields after the reset event, so the mask formats\n // the restored value a task later.\n el.ownerDocument.addEventListener('reset', this._onReset, { capture: true, signal });\n this._rewrite();\n }\n\n static get defaults(): BaseOptions {\n return _defaults;\n }\n\n private _onInput = (e: InputEvent) => {\n if (!e.isComposing) this._format();\n };\n\n /**\n * Backspace after a literal, or Delete before one, would remove the\n * literal, which the mask then writes back. It removes the slot character\n * across the literal instead.\n */\n private _onBeforeInput = (e: InputEvent) => {\n const step = DELETES[e.inputType];\n const index = step && this.el.selectionStart === this.el.selectionEnd ? this._acrossLiteral(step) : -1;\n if (index < 0) return;\n e.preventDefault();\n this._remove(index, e.inputType);\n };\n\n /** The index among the slot characters to delete when the character `step` from the caret is a literal, or -1. */\n private _acrossLiteral(step: number) {\n const { selectionStart: caret, value } = this.el;\n const here = read(this._tokens, value, caret);\n const index = here.before + Math.min(step, 0);\n // Stepping over a literal passes no slot character.\n return read(this._tokens, value, caret + step).before === here.before && index in here.chars ? index : -1;\n }\n\n /** Removes slot character `index`, puts the caret where it was, and reports the edit as typing would. */\n private _remove(index: number, inputType: string) {\n const { chars } = read(this._tokens, this.el.value, 0);\n chars.splice(index, 1);\n const { text, ends } = write(this._tokens, chars);\n this.el.value = text;\n const caret = ends[index - 1] ?? 0;\n this.el.setSelectionRange(caret, caret);\n this.el.dispatchEvent(new InputEvent('input', { bubbles: true, composed: true, inputType }));\n }\n\n private _onReset = (e: Event) => {\n if (e.target === this.el.form) setTimeout(this._afterReset);\n };\n\n private _afterReset = () => {\n if (!this._events.signal.aborted) this._rewrite();\n };\n\n private _format = () => {\n const caret = this._rewrite();\n if (caret !== null && this.el.ownerDocument.activeElement === this.el) this.el.setSelectionRange(caret, caret);\n };\n\n /** Rewrites the value to the mask. Returns where the caret goes, or null when the value already fit. */\n private _rewrite() {\n const el = this.el;\n const { chars, before } = read(this._tokens, el.value, el.selectionEnd ?? el.value.length);\n const { text, ends } = write(this._tokens, chars);\n if (text === el.value) return null;\n el.value = text;\n return ends[before - 1] ?? 0;\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|