@expressivecss/expressive 0.15.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1807 -1
- package/README.md +9 -8
- package/dist/css/expressive.css +19176 -11958
- 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-26VUH75M.mjs +102 -0
- package/dist/js/chunks/chunk-26VUH75M.mjs.map +7 -0
- package/dist/js/chunks/chunk-2LFCOGC3.mjs +233 -0
- package/dist/js/chunks/chunk-2LFCOGC3.mjs.map +7 -0
- package/dist/js/chunks/{chunk-DXGRXYYL.mjs → chunk-36GELQGX.mjs} +29 -46
- package/dist/js/chunks/chunk-36GELQGX.mjs.map +7 -0
- package/dist/js/chunks/{chunk-74MXKKLN.mjs → chunk-3FKWIRHW.mjs} +15 -29
- package/dist/js/chunks/chunk-3FKWIRHW.mjs.map +7 -0
- package/dist/js/chunks/chunk-3KF65KGL.mjs +209 -0
- package/dist/js/chunks/chunk-3KF65KGL.mjs.map +7 -0
- package/dist/js/chunks/{chunk-KVJAVDBC.mjs → chunk-3KLZRQZI.mjs} +88 -116
- package/dist/js/chunks/chunk-3KLZRQZI.mjs.map +7 -0
- package/dist/js/chunks/{chunk-CK2XCICY.mjs → chunk-3XORNED5.mjs} +3 -11
- package/dist/js/chunks/chunk-3XORNED5.mjs.map +7 -0
- package/dist/js/chunks/chunk-4WBGAQN3.mjs +113 -0
- package/dist/js/chunks/chunk-4WBGAQN3.mjs.map +7 -0
- package/dist/js/chunks/{chunk-FM5CZOUB.mjs → chunk-5F4URJHL.mjs} +19 -30
- package/dist/js/chunks/chunk-5F4URJHL.mjs.map +7 -0
- package/dist/js/chunks/chunk-67UNY7RH.mjs +299 -0
- package/dist/js/chunks/chunk-67UNY7RH.mjs.map +7 -0
- package/dist/js/chunks/chunk-7CXNATJS.mjs +97 -0
- package/dist/js/chunks/chunk-7CXNATJS.mjs.map +7 -0
- package/dist/js/chunks/{chunk-UETTGDLI.mjs → chunk-7X44MKEQ.mjs} +43 -48
- package/dist/js/chunks/chunk-7X44MKEQ.mjs.map +7 -0
- package/dist/js/chunks/chunk-7ZAMOMGY.mjs +440 -0
- package/dist/js/chunks/chunk-7ZAMOMGY.mjs.map +7 -0
- package/dist/js/chunks/chunk-AEG6LOAJ.mjs +54 -0
- package/dist/js/chunks/chunk-AEG6LOAJ.mjs.map +7 -0
- package/dist/js/chunks/chunk-AQNFCJJ5.mjs +135 -0
- package/dist/js/chunks/chunk-AQNFCJJ5.mjs.map +7 -0
- package/dist/js/chunks/chunk-B55LWKBM.mjs +75 -0
- package/dist/js/chunks/chunk-B55LWKBM.mjs.map +7 -0
- package/dist/js/chunks/chunk-BB5VXYXT.mjs +28 -0
- package/dist/js/chunks/chunk-BB5VXYXT.mjs.map +7 -0
- package/dist/js/chunks/chunk-BDATLH3H.mjs +108 -0
- package/dist/js/chunks/chunk-BDATLH3H.mjs.map +7 -0
- package/dist/js/chunks/chunk-CWMQOT4O.mjs +232 -0
- package/dist/js/chunks/chunk-CWMQOT4O.mjs.map +7 -0
- package/dist/js/chunks/chunk-CY2CTOVM.mjs +81 -0
- package/dist/js/chunks/chunk-CY2CTOVM.mjs.map +7 -0
- package/dist/js/chunks/{chunk-NUHMOAOY.mjs → chunk-DWA5UYLJ.mjs} +363 -218
- package/dist/js/chunks/chunk-DWA5UYLJ.mjs.map +7 -0
- package/dist/js/chunks/chunk-EB2V4OKL.mjs +79 -0
- package/dist/js/chunks/chunk-EB2V4OKL.mjs.map +7 -0
- package/dist/js/chunks/chunk-EWO662ZC.mjs +188 -0
- package/dist/js/chunks/chunk-EWO662ZC.mjs.map +7 -0
- package/dist/js/chunks/{chunk-ZX6M7SWO.mjs → chunk-F7LAKFMX.mjs} +320 -141
- package/dist/js/chunks/chunk-F7LAKFMX.mjs.map +7 -0
- package/dist/js/chunks/{chunk-L27Q6ZMI.mjs → chunk-FNIIH2LU.mjs} +20 -33
- package/dist/js/chunks/chunk-FNIIH2LU.mjs.map +7 -0
- package/dist/js/chunks/chunk-GE3YMFS6.mjs +15 -0
- package/dist/js/chunks/chunk-GE3YMFS6.mjs.map +7 -0
- package/dist/js/chunks/chunk-GFWYMWYN.mjs +125 -0
- package/dist/js/chunks/chunk-GFWYMWYN.mjs.map +7 -0
- package/dist/js/chunks/chunk-GNRSYMVH.mjs +1 -0
- package/dist/js/chunks/chunk-H5ISU45X.mjs +87 -0
- package/dist/js/chunks/chunk-H5ISU45X.mjs.map +7 -0
- package/dist/js/chunks/{chunk-GJL6GCIU.mjs → chunk-H6YIKFAQ.mjs} +311 -186
- package/dist/js/chunks/chunk-H6YIKFAQ.mjs.map +7 -0
- package/dist/js/chunks/{chunk-BGZLF6JZ.mjs → chunk-HEH7E3KO.mjs} +155 -35
- package/dist/js/chunks/chunk-HEH7E3KO.mjs.map +7 -0
- package/dist/js/chunks/chunk-HQRLBTNM.mjs +152 -0
- package/dist/js/chunks/chunk-HQRLBTNM.mjs.map +7 -0
- package/dist/js/chunks/chunk-I2F7MLUU.mjs +137 -0
- package/dist/js/chunks/chunk-I2F7MLUU.mjs.map +7 -0
- package/dist/js/chunks/chunk-IQOTGGHX.mjs +797 -0
- package/dist/js/chunks/chunk-IQOTGGHX.mjs.map +7 -0
- package/dist/js/chunks/chunk-JH3YWKA6.mjs +225 -0
- package/dist/js/chunks/chunk-JH3YWKA6.mjs.map +7 -0
- package/dist/js/chunks/chunk-JOLJAYIJ.mjs +7 -0
- package/dist/js/chunks/chunk-JOLJAYIJ.mjs.map +7 -0
- package/dist/js/chunks/{chunk-VGNYF6FB.mjs → chunk-KOTGMCMI.mjs} +116 -24
- package/dist/js/chunks/chunk-KOTGMCMI.mjs.map +7 -0
- package/dist/js/chunks/{chunk-LQWUDNHZ.mjs → chunk-LC4O5LFS.mjs} +21 -45
- package/dist/js/chunks/chunk-LC4O5LFS.mjs.map +7 -0
- package/dist/js/chunks/chunk-LEF33SCP.mjs +127 -0
- package/dist/js/chunks/chunk-LEF33SCP.mjs.map +7 -0
- package/dist/js/chunks/{chunk-PDG64UHF.mjs → chunk-LFORZRPH.mjs} +21 -23
- package/dist/js/chunks/chunk-LFORZRPH.mjs.map +7 -0
- package/dist/js/chunks/chunk-LWLNV5EC.mjs +451 -0
- package/dist/js/chunks/chunk-LWLNV5EC.mjs.map +7 -0
- package/dist/js/chunks/chunk-LXRHUQAX.mjs +491 -0
- package/dist/js/chunks/chunk-LXRHUQAX.mjs.map +7 -0
- package/dist/js/chunks/{chunk-SFI2U4YW.mjs → chunk-MA2SZZFB.mjs} +82 -111
- package/dist/js/chunks/chunk-MA2SZZFB.mjs.map +7 -0
- package/dist/js/chunks/chunk-MDBZAMIV.mjs +121 -0
- package/dist/js/chunks/chunk-MDBZAMIV.mjs.map +7 -0
- package/dist/js/chunks/chunk-NODZ5VAD.mjs +75 -0
- package/dist/js/chunks/chunk-NODZ5VAD.mjs.map +7 -0
- package/dist/js/chunks/chunk-O2WJB6TH.mjs +365 -0
- package/dist/js/chunks/chunk-O2WJB6TH.mjs.map +7 -0
- package/dist/js/chunks/chunk-PCABY5BN.mjs +35 -0
- package/dist/js/chunks/chunk-PCABY5BN.mjs.map +7 -0
- package/dist/js/chunks/chunk-PWKYVMND.mjs +120 -0
- package/dist/js/chunks/chunk-PWKYVMND.mjs.map +7 -0
- package/dist/js/chunks/{chunk-SMY7GJSS.mjs → chunk-QHZZT7YO.mjs} +66 -38
- package/dist/js/chunks/chunk-QHZZT7YO.mjs.map +7 -0
- package/dist/js/chunks/chunk-QND56EW2.mjs +439 -0
- package/dist/js/chunks/chunk-QND56EW2.mjs.map +7 -0
- package/dist/js/chunks/chunk-QNODAANY.mjs +376 -0
- package/dist/js/chunks/chunk-QNODAANY.mjs.map +7 -0
- package/dist/js/chunks/{chunk-KHXZ2A4K.mjs → chunk-QRO5FV3I.mjs} +156 -73
- package/dist/js/chunks/chunk-QRO5FV3I.mjs.map +7 -0
- package/dist/js/chunks/chunk-R7A7JRC5.mjs +440 -0
- package/dist/js/chunks/chunk-R7A7JRC5.mjs.map +7 -0
- package/dist/js/chunks/chunk-RKG2CBFE.mjs +74 -0
- package/dist/js/chunks/chunk-RKG2CBFE.mjs.map +7 -0
- package/dist/js/chunks/{chunk-XAEAEHIX.mjs → chunk-RSNS5OYS.mjs} +38 -25
- package/dist/js/chunks/chunk-RSNS5OYS.mjs.map +7 -0
- package/dist/js/chunks/{chunk-X4ISMKE2.mjs → chunk-RUDYMEJ3.mjs} +7 -6
- package/dist/js/chunks/chunk-RUDYMEJ3.mjs.map +7 -0
- package/dist/js/chunks/chunk-STJR62SU.mjs +161 -0
- package/dist/js/chunks/chunk-STJR62SU.mjs.map +7 -0
- package/dist/js/chunks/chunk-SUSD4UTN.mjs +220 -0
- package/dist/js/chunks/chunk-SUSD4UTN.mjs.map +7 -0
- package/dist/js/chunks/{chunk-5CEAOLUA.mjs → chunk-SYBOA5HC.mjs} +26 -48
- package/dist/js/chunks/chunk-SYBOA5HC.mjs.map +7 -0
- package/dist/js/chunks/chunk-T4MOBP3J.mjs +108 -0
- package/dist/js/chunks/chunk-T4MOBP3J.mjs.map +7 -0
- package/dist/js/chunks/chunk-TM7HPGTV.mjs +342 -0
- package/dist/js/chunks/chunk-TM7HPGTV.mjs.map +7 -0
- package/dist/js/chunks/{chunk-C6CHEWYP.mjs → chunk-TMQDZSDC.mjs} +71 -35
- package/dist/js/chunks/chunk-TMQDZSDC.mjs.map +7 -0
- package/dist/js/chunks/chunk-TVSX5YA2.mjs +48 -0
- package/dist/js/chunks/chunk-TVSX5YA2.mjs.map +7 -0
- package/dist/js/chunks/chunk-UHO5CV6K.mjs +80 -0
- package/dist/js/chunks/chunk-UHO5CV6K.mjs.map +7 -0
- package/dist/js/chunks/chunk-UKCNELUN.mjs +223 -0
- package/dist/js/chunks/chunk-UKCNELUN.mjs.map +7 -0
- package/dist/js/chunks/chunk-UKQK5GWR.mjs +167 -0
- package/dist/js/chunks/chunk-UKQK5GWR.mjs.map +7 -0
- package/dist/js/chunks/{chunk-TSZYSW7F.mjs → chunk-UTSLYQ65.mjs} +21 -48
- package/dist/js/chunks/chunk-UTSLYQ65.mjs.map +7 -0
- package/dist/js/chunks/chunk-VS5OJBOD.mjs +108 -0
- package/dist/js/chunks/chunk-VS5OJBOD.mjs.map +7 -0
- package/dist/js/chunks/chunk-VZMROW5A.mjs +759 -0
- package/dist/js/chunks/chunk-VZMROW5A.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-XB6Y7P5W.mjs +69 -0
- package/dist/js/chunks/chunk-XB6Y7P5W.mjs.map +7 -0
- package/dist/js/chunks/chunk-XDAMOMVD.mjs +226 -0
- package/dist/js/chunks/chunk-XDAMOMVD.mjs.map +7 -0
- package/dist/js/chunks/{chunk-WDK4T63U.mjs → chunk-XJPMW5SP.mjs} +247 -172
- package/dist/js/chunks/chunk-XJPMW5SP.mjs.map +7 -0
- package/dist/js/chunks/{chunk-KUFHW3DS.mjs → chunk-YKANQILZ.mjs} +16 -21
- package/dist/js/chunks/chunk-YKANQILZ.mjs.map +7 -0
- package/dist/js/chunks/chunk-YLZOJLDI.mjs +175 -0
- package/dist/js/chunks/chunk-YLZOJLDI.mjs.map +7 -0
- package/dist/js/chunks/chunk-ZK7YY322.mjs +514 -0
- package/dist/js/chunks/chunk-ZK7YY322.mjs.map +7 -0
- package/dist/js/expressive.cjs +10266 -3628
- package/dist/js/expressive.cjs.map +4 -4
- package/dist/js/expressive.js +10266 -3628
- 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 +181 -69
- 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 +8 -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 +5 -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 +7 -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 +12 -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 -65
- 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 +41 -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 +60 -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 +5 -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 +14 -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 +6 -3
- package/dist/js/internal/core/formControl.mjs +12 -0
- package/dist/js/internal/core/formControl.mjs.map +7 -0
- package/dist/js/internal/core/imageURL.mjs +7 -0
- package/dist/js/internal/core/imageURL.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 +21 -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 +172 -69
- package/dist/types/behaviors/bottomSheets.d.ts +23 -5
- package/dist/types/behaviors/copy.d.ts +18 -0
- package/dist/types/behaviors/dataTables.d.ts +125 -0
- package/dist/types/behaviors/dialogs.d.ts +27 -1
- package/dist/types/behaviors/forms.d.ts +70 -4
- package/dist/types/behaviors/imageCompare.d.ts +13 -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 +53 -0
- package/dist/types/components/appBar.d.ts +5 -6
- package/dist/types/components/autocomplete.d.ts +105 -20
- 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 +16 -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 +80 -19
- package/dist/types/components/colorPicker.d.ts +56 -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 +60 -0
- package/dist/types/components/datepicker.d.ts +107 -56
- package/dist/types/components/expandingCard.d.ts +4 -6
- package/dist/types/components/funnelChart.d.ts +35 -0
- package/dist/types/components/heatmapChart.d.ts +42 -8
- package/dist/types/components/hoverCard.d.ts +59 -0
- package/dist/types/components/index.d.ts +16 -1
- package/dist/types/components/inputMask.d.ts +28 -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 +212 -12
- package/dist/types/components/loadingOverlay.d.ts +42 -0
- package/dist/types/components/mapView.d.ts +138 -27
- package/dist/types/components/menu.d.ts +74 -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 +22 -5
- package/dist/types/components/pieChart.d.ts +33 -9
- 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 +45 -22
- 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 +44 -33
- package/dist/types/components/showMore.d.ts +53 -0
- package/dist/types/components/slider.d.ts +2 -15
- package/dist/types/components/snackbar.d.ts +68 -1
- package/dist/types/components/swipeActions.d.ts +81 -0
- package/dist/types/components/tabs.d.ts +92 -30
- package/dist/types/components/timepicker.d.ts +128 -27
- package/dist/types/components/tooltip.d.ts +57 -21
- 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 +49 -25
- package/dist/types/core/formControl.d.ts +21 -0
- package/dist/types/core/imageURL.d.ts +2 -0
- package/dist/types/core/spring.d.ts +20 -0
- package/dist/types/core/utils.d.ts +123 -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 +39 -0
- package/package.json +17 -13
- 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 +864 -78
- package/src/sass/abstracts/_spring.scss +63 -0
- package/src/sass/abstracts/_variables.scss +64 -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 +10 -19
- package/src/sass/components/_alert.scss +102 -0
- package/src/sass/components/_aura.scss +9 -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 +31 -90
- package/src/sass/components/_bottom-sheet.scss +51 -16
- package/src/sass/components/_breadcrumb.scss +8 -7
- package/src/sass/components/_button-groups.scss +30 -63
- package/src/sass/components/_buttons.scss +137 -94
- package/src/sass/components/_calendar.scss +244 -0
- package/src/sass/components/_cards.scss +36 -44
- package/src/sass/components/_carousel.scss +37 -113
- package/src/sass/components/_cascader.scss +131 -0
- package/src/sass/components/_chips.scss +36 -46
- package/src/sass/components/_column-chart.scss +15 -26
- package/src/sass/components/_command-palette.scss +4 -7
- package/src/sass/components/_confetti.scss +1 -4
- package/src/sass/components/_countdown.scss +1 -1
- package/src/sass/components/_data-table.scss +172 -25
- package/src/sass/components/_datepicker.scss +54 -40
- package/src/sass/components/_description-list.scss +85 -0
- package/src/sass/components/_dialog.scss +48 -55
- 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 +21 -14
- package/src/sass/components/_fab-menu.scss +43 -39
- package/src/sass/components/_funnel-chart.scss +63 -0
- package/src/sass/components/_heatmap-chart.scss +114 -29
- package/src/sass/components/_icon-buttons.scss +8 -11
- 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 +9 -63
- 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 +37 -11
- package/src/sass/components/_marquee.scss +4 -3
- package/src/sass/components/_mega-menu.scss +128 -0
- package/src/sass/components/_menu.scss +146 -127
- package/src/sass/components/_menubar.scss +47 -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 +27 -35
- package/src/sass/components/_modal-display.scss +21 -0
- package/src/sass/components/_navbar.scss +45 -36
- package/src/sass/components/_navigation-bar.scss +12 -77
- package/src/sass/components/_navigation-rail.scss +161 -92
- package/src/sass/components/_org-chart.scss +192 -0
- package/src/sass/components/_page-footer.scss +2 -4
- package/src/sass/components/_pagination.scss +9 -27
- package/src/sass/components/_panes.scss +35 -42
- package/src/sass/components/_particles.scss +1 -4
- package/src/sass/components/_pie-chart.scss +86 -68
- package/src/sass/components/_popover.scss +18 -5
- package/src/sass/components/_progress.scss +183 -44
- 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 +40 -42
- package/src/sass/components/_radial-chart.scss +108 -46
- package/src/sass/components/_rich-text-editor.scss +2 -2
- package/src/sass/components/_sankey-chart.scss +91 -0
- package/src/sass/components/_scatter-chart.scss +144 -0
- package/src/sass/components/_scrim.scss +0 -2
- package/src/sass/components/_scrollspy.scss +0 -2
- package/src/sass/components/_search.scss +27 -26
- package/src/sass/components/_show-more.scss +8 -0
- package/src/sass/components/_side-sheet.scss +32 -51
- package/src/sass/components/_skeleton.scss +26 -19
- package/src/sass/components/_snackbar.scss +25 -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/_table_of_contents.scss +1 -3
- package/src/sass/components/_tabs.scss +49 -46
- package/src/sass/components/_timeline.scss +12 -12
- package/src/sass/components/_timepicker.scss +111 -79
- package/src/sass/components/_toolbar.scss +36 -47
- package/src/sass/components/_tooltip.scss +25 -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 +7 -32
- package/src/sass/components/_treemap-chart.scss +98 -0
- package/src/sass/components/forms/_checkboxes.scss +107 -44
- 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 +16 -13
- package/src/sass/components/forms/_fieldset.scss +4 -7
- package/src/sass/components/forms/_file-input.scss +12 -8
- package/src/sass/components/forms/_index.scss +3 -1
- package/src/sass/components/forms/_input-fields.scss +271 -90
- package/src/sass/components/forms/_radio-buttons.scss +34 -117
- package/src/sass/components/forms/_rating.scss +2 -32
- package/src/sass/components/forms/_select.scss +198 -20
- package/src/sass/components/forms/_slider.scss +92 -98
- package/src/sass/components/forms/_switches.scss +62 -180
- 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 +184 -27
- 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 +46 -77
- 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 +0 -90
- 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/timepicker.ts"],
|
|
4
|
+
"sourcesContent": ["import { Utils, controllerFor, pickerFooter, svgNode } from '../core/utils';\nimport { Component, BaseOptions, I18nOptions } from '../core/component';\nimport { DisplayPlugin, createDisplayPlugin, hideModal } from '../plugins/modalDisplayPlugin';\n\nexport type Views = 'hours' | 'minutes';\n\n/** The clock's fields, in the order they appear. */\nconst UNITS = ['hours', 'minutes', 'seconds'] as const;\ntype Unit = (typeof UNITS)[number];\n\n/** How far each key moves a field, wrapping round. */\nconst STEPS: Record<string, number> = { ArrowUp: 1, ArrowDown: -1, PageUp: 5, PageDown: -5 };\n/** Whether a key steps a field. Alt, Ctrl and Meta stay the browser's. */\nconst isStepKey = (e: KeyboardEvent) => e.key in STEPS && Utils.plainKey(e);\n\n/** A 12-hour time's hour of the day, 0 to 23. */\nconst dayHour = (hours: number, pm: boolean) => (hours % 12) + (pm ? 12 : 0);\n\n/** Each field's length in seconds and how many values it has. */\nconst SPANS: Record<Unit, [number, number]> = { hours: [3600, 24], minutes: [60, 60], seconds: [1, 60] };\n\n/**\n * The hour at a position on the 24-hour dial, 0 to 12 from the top: the\n * inner ring holds 1 to 12, the outer 13 to 23 and 00.\n */\nconst ringHour = (position: number, inner: boolean) => {\n const hour = (position % 12) + (inner ? 0 : 12);\n return hour % 12 ? hour : 12 - hour;\n};\n\n/** The last second of the day. */\nconst DAY_END = 24 * 3600 - 1;\n\n/** A clock number as two digits. */\nconst pad2 = (n: number) => String(n).padStart(2, '0');\n\n/**\n * The hour on the 24-hour clock, minute and second of a written time such as\n * '14:30', '02:30:45 PM' or 'now'. A missing part reads as 0.\n */\nfunction readTime(text: string, fromNow: number): [number, number, number] {\n const upper = text.trim().toUpperCase();\n if (upper.split(':')[0] === 'NOW') {\n const now = new Date(+new Date() + fromNow);\n return [now.getHours(), now.getMinutes(), now.getSeconds()];\n }\n const period = /AM|PM/.exec(upper)?.[0];\n const parts = upper.replace(/AM|PM/, '').split(':');\n const [hours, minutes, seconds] = [0, 1, 2].map((i) => +parts[i] || 0);\n // A written AM or PM fixes the hour on either clock: \"03:30 PM\" is 15:30\n // on a 24-hour clock too.\n return [period ? dayHour(hours, period === 'PM') : hours, minutes, seconds];\n}\n\n/** Seconds since midnight for an hour, minute and second. */\nconst daySeconds = ([hours, minutes, seconds]: number[]) => hours * 3600 + minutes * 60 + seconds;\n\n/**\n * With a `lang` on or around the input, whether that language tells the\n * time on a 12-hour clock.\n */\nfunction localeClock(el: Element): Partial<TimepickerOptions> {\n const locale = Utils.locale(el);\n if (!locale) return {};\n const cycle = new Intl.DateTimeFormat(locale, { hour: 'numeric' }).resolvedOptions().hourCycle;\n return { twelveHour: cycle === 'h11' || cycle === 'h12' };\n}\n\nexport interface TimepickerOptions extends BaseOptions {\n /**\n * Dial radius.\n * @default 135\n */\n dialRadius: number;\n /**\n * Outer radius.\n * @default 105\n */\n outerRadius: number;\n /**\n * Inner radius.\n * @default 70\n */\n innerRadius: number;\n /**\n * Tick radius.\n * @default 20\n */\n tickRadius: number;\n /**\n * Duration of the transition from/to the hours/minutes view.\n * @default 350\n */\n duration: number;\n /**\n * Specify a DOM element OR selector for a DOM element to render\n * the time picker in, by default it will be placed before the input.\n * @default null\n */\n container: HTMLElement | string | null;\n /**\n * Show the clear button in the Timepicker.\n * @default false\n */\n showClearBtn: boolean;\n /**\n * Autosubmit timepicker selection to input field\n * @default true\n */\n autoSubmit: boolean;\n /**\n * Default time to set on the timepicker 'now' or '13:14'.\n * @default 'now';\n */\n defaultTime: string;\n /**\n * Millisecond offset from the defaultTime.\n * @default 0\n */\n fromNow: number;\n /**\n * Internationalization options.\n */\n i18n: Partial<I18nOptions & { hours: string; minutes: string; seconds: string }>;\n /**\n * Use 12 hour AM/PM clock instead of 24 hour clock.\n * @default true, or the clock the input's `lang` uses\n */\n twelveHour: boolean;\n /**\n * Add a seconds field after the minutes, and write `HH:MM:SS`. The dial\n * still sets hours and minutes only.\n * @default false\n */\n showSeconds: boolean;\n /**\n * The earliest time a person can choose, as 24-hour `'HH:MM'` or\n * `'HH:MM:SS'`. Without `showSeconds` it rounds up to a whole minute.\n * @default null\n */\n minTime: string | null;\n /**\n * The latest time a person can choose, as 24-hour `'HH:MM'` or\n * `'HH:MM:SS'`. Without `showSeconds` it rounds down to a whole minute.\n * @default null\n */\n maxTime: string | null;\n /**\n * Vibrate device when dragging clock hand.\n * @default true\n */\n vibrate: boolean;\n /**\n * Callback function when a time is selected.\n * @default null\n */\n onSelect: (hour: number, minute: number) => void;\n /**\n * Callback function for interaction with input field.\n * @default null\n */\n onInputInteraction: (() => void) | null;\n /**\n * Callback function for done.\n * @default null\n */\n onDone: (() => void) | null;\n /**\n * Callback function for cancel.\n * @default null\n */\n onCancel: (() => void) | null;\n /**\n * Display plugin: 'docked' for a popover under the input, or 'modal' for a\n * dialog with Cancel and Ok. A modal picker writes the input only on Ok,\n * so it clears `autoSubmit`.\n */\n displayPlugin: string;\n /**\n * Configurable display plugin options\n */\n displayPluginOptions: object;\n}\n\nconst _defaults: TimepickerOptions = {\n dialRadius: 135,\n outerRadius: 105,\n innerRadius: 70,\n tickRadius: 20,\n duration: 350,\n container: null,\n defaultTime: 'now', // default time, 'now' or '13:14' e.g.\n fromNow: 0, // Millisecond offset from the defaultTime\n showClearBtn: false,\n autoSubmit: true,\n // internationalization\n i18n: {\n cancel: 'Cancel',\n clear: 'Clear',\n done: 'Ok',\n hours: 'Hours',\n minutes: 'Minutes',\n seconds: 'Seconds'\n },\n twelveHour: true, // change to 12 hour AM/PM clock from 24 hour\n showSeconds: false,\n minTime: null,\n maxTime: null,\n vibrate: true, // vibrate the device when dragging clock hand\n // Callbacks\n onSelect: null,\n onInputInteraction: null,\n onDone: null,\n onCancel: null,\n displayPlugin: null,\n displayPluginOptions: null,\n};\n\nexport class Timepicker extends Component<TimepickerOptions> {\n declare el: HTMLInputElement;\n id: string;\n containerEl: HTMLElement;\n plate: HTMLElement;\n digitalClock: HTMLElement;\n inputHours: HTMLInputElement;\n inputMinutes: HTMLInputElement;\n /** The seconds field, or null without `showSeconds`. */\n inputSeconds: HTMLInputElement | null;\n x0: number;\n y0: number;\n moved: boolean;\n /** Which pointer is dragging the clock hand; a second finger is ignored. */\n private _dragPointerId: number | null = null;\n /** Removes the document listeners of the drag in progress. */\n private _drag: AbortController | null = null;\n dx: number;\n dy: number;\n /**\n * Current view on the timepicker.\n * @default 'hours'\n */\n currentView: Views;\n hand: SVGElement;\n minutesView: HTMLElement;\n hours: number;\n minutes: number;\n seconds: number;\n /** The selected time as the clock shows it. On a 12-hour clock `amOrPm` says which half of the day. */\n time: string;\n /**\n * If the time is AM or PM on twelve-hour clock.\n * @default 'PM'\n */\n amOrPm: 'AM' | 'PM';\n static _template: string;\n /** Whether this device exposes the Vibration API at all. */\n canVibrate: boolean;\n _canvas: HTMLElement;\n hoursView: HTMLElement;\n spanAmPm: HTMLSpanElement;\n footer: HTMLElement;\n private _amBtn: HTMLButtonElement;\n private _pmBtn: HTMLButtonElement;\n bg: Element;\n g: Element;\n toggleViewTimer: ReturnType<typeof setTimeout>;\n vibrateTimer: ReturnType<typeof setTimeout>;\n private _autoSubmitTimer: ReturnType<typeof setTimeout>;\n /** Clear was pressed in a picker that writes on Ok. */\n private _clearPending = false;\n private _clockResetTimer: ReturnType<typeof setTimeout>;\n private displayPlugin: DisplayPlugin;\n /** Whether the dial (ticks + SVG + AM/PM buttons) has been built yet. */\n private _clockBuilt = false;\n /** Whether the pointer last pointed at a value outside the range. */\n private _handRefused = false;\n /** The first and last allowed second of the day. */\n private _limits: [number, number] = [0, DAY_END];\n\n constructor(el: HTMLInputElement, options: Partial<TimepickerOptions>) {\n super(el, { ...localeClock(el), ...options });\n // A modal clock writes on Ok, so it has the buttons.\n this.options.autoSubmit &&= this.options.displayPlugin !== 'modal';\n this.id = Utils.guid();\n this._readLimits();\n this._insertHTMLIntoDOM();\n this._setupVariables();\n this._setupEventHandlers();\n // The dial is ~40 elements (12 or 24 hour ticks, 12 minute ticks, the SVG\n // hand and the AM/PM buttons) and is built by _ensureClockBuilt() rather\n // than here - see _pickerSetup for when that first happens.\n this._pickerSetup();\n\n this.displayPlugin = createDisplayPlugin(this.options.displayPlugin, this.el, this.containerEl, this.options.displayPluginOptions, this.cancel);\n }\n\n static get defaults(): TimepickerOptions {\n return _defaults;\n }\n\n static key = 'Expressive_Timepicker';\n\n destroy() {\n clearTimeout(this._autoSubmitTimer);\n clearTimeout(this.toggleViewTimer);\n clearTimeout(this.vibrateTimer);\n this._cancelClockReset();\n // Drag handlers live on the document while the clock hand is held; if the\n // component is destroyed mid-drag they would otherwise outlive it.\n this._drag?.abort();\n this.displayPlugin?.destroy();\n this.containerEl.remove();\n super.destroy();\n }\n\n _setupEventHandlers() {\n const { signal } = this._events;\n this.el.addEventListener('click', this._handleInputClick, { signal });\n this.el.addEventListener('keydown', this._handleInputKeydown, { signal });\n this.plate.addEventListener('pointerdown', this._handleClockClickStart);\n this.digitalClock.addEventListener('input', this._inputFromTextField, { signal });\n this.digitalClock.addEventListener('keydown', this._handleDigitalKeydown, { signal });\n this.containerEl.addEventListener('pointerdown', this._keepTime, { capture: true, signal });\n this.containerEl.addEventListener('keydown', this._keepTime, { capture: true, signal });\n this.inputHours.addEventListener('focus', () => this.showView('hours'));\n this.inputHours.addEventListener('focusout', () => this.formatHours());\n this.inputMinutes.addEventListener('focus', () => this.showView('minutes'));\n this.inputMinutes.addEventListener('focusout', () => this.formatMinutes());\n this.inputSeconds?.addEventListener('focusout', () => this.formatSeconds());\n }\n\n _handleInputClick = () => {\n this._updateTimeFromInput();\n // Before focus(): focusing inputHours fires the handler that calls\n // showView, and an already-focused input fires nothing at all.\n this._ensureClockBuilt();\n if (this.displayPlugin) this.displayPlugin.show();\n this.inputHours.focus();\n if (typeof this.options.onInputInteraction === 'function') this.options.onInputInteraction.call(this);\n };\n\n _handleInputKeydown = Utils.ignoringComposition((e: KeyboardEvent) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n this._handleInputClick();\n }\n });\n\n _handleClockClickStart = (e: PointerEvent) => {\n if (!e.isPrimary) return;\n if (e.pointerType === 'mouse' && e.button !== 0) return;\n e.preventDefault();\n this._ensureClockBuilt();\n const clockPlateBR = this.plate.getBoundingClientRect();\n const offset = { x: clockPlateBR.left, y: clockPlateBR.top };\n\n this.x0 = offset.x + this.options.dialRadius;\n this.y0 = offset.y + this.options.dialRadius;\n this.moved = false;\n this._dragPointerId = e.pointerId;\n this.dx = e.clientX - this.x0;\n this.dy = e.clientY - this.y0;\n\n // Set clock hands\n this.setHand(this.dx, this.dy, false);\n // The hand follows the pointer anywhere on the page while it is held.\n // `pointercancel` ends the drag the same way `pointerup` does: without it\n // these document listeners outlived a cancelled touch, because the\n // `touchend` pair this replaced had no `touchcancel` companion.\n this._drag?.abort();\n this._drag = controllerFor(this.el);\n const { signal } = this._drag;\n document.addEventListener('pointermove', this._handleDocumentClickMove, { signal });\n document.addEventListener('pointerup', this._handleDocumentClickEnd, { signal });\n document.addEventListener('pointercancel', this._handleDocumentClickCancel, { signal });\n };\n\n _handleDocumentClickMove = (e: PointerEvent) => {\n if (e.pointerId !== this._dragPointerId) return;\n e.preventDefault();\n const x = e.clientX - this.x0;\n const y = e.clientY - this.y0;\n this.moved = true;\n this.setHand(x, y, false);\n };\n\n _handleDocumentClickEnd = (e: PointerEvent) => {\n if (e.pointerId !== this._dragPointerId) return;\n this._dragPointerId = null;\n e.preventDefault();\n this._drag.abort();\n const x = e.clientX - this.x0;\n const y = e.clientY - this.y0;\n if (this.moved && x === this.dx && y === this.dy) {\n this.setHand(x, y);\n }\n // A release on a disabled tick is no choice at all.\n if (!this._handRefused) this._chooseHand();\n };\n\n /** Take the value under the hand: move on to the minutes, or submit. */\n private _chooseHand() {\n if (this.currentView === 'hours') {\n this.inputMinutes.focus();\n this.showView('minutes', this.options.duration / 2);\n } else {\n clearTimeout(this._autoSubmitTimer);\n this._autoSubmitTimer = setTimeout(() => {\n this._autoSubmitTimer = null;\n if (this.options.autoSubmit) this.done();\n }, this.options.duration / 2);\n }\n\n const { hours, minutes } = this;\n this._notify('select', this.options.onSelect, { args: [hours, minutes], detail: { hours, minutes }, current: () => this.hours === hours && this.minutes === minutes });\n }\n\n /**\n * A cancelled pointer is not a completed selection. The browser or the OS\n * took the gesture over, so this only lets go of the drag - it must not run\n * the pointer-up path, which advances hours to minutes, fires `onSelect`,\n * and under `autoSubmit` closes the picker on a time the user never chose.\n */\n _handleDocumentClickCancel = (e: PointerEvent) => {\n if (e.pointerId !== this._dragPointerId) return;\n this._dragPointerId = null;\n this.moved = false;\n this._drag.abort();\n };\n\n /**\n * Read `minTime` and `maxTime` as seconds of the day. Without a seconds\n * field the picker writes whole minutes, so the bounds round inward to a\n * whole minute: `maxTime` takes in every second of its minute, and the\n * hidden seconds never clamp.\n */\n private _readLimits() {\n const { minTime, maxTime, showSeconds, fromNow } = this.options;\n const read = (time: string | null, fallback: number) => (time ? daySeconds(readTime(time, fromNow)) : fallback);\n let [min, max] = [read(minTime, 0), read(maxTime, DAY_END)];\n if (!showSeconds) [min, max] = [Math.ceil(min / 60) * 60, Math.floor(max / 60) * 60 + 59];\n if (min > max) return console.warn('Timepicker ignored minTime and maxTime: minTime is after maxTime.', this.el);\n this._limits = [min, max];\n }\n\n _insertHTMLIntoDOM() {\n const template = document.createElement('template');\n template.innerHTML = Timepicker._template.trim();\n\n this.containerEl = <HTMLElement>template.content.firstChild;\n this.containerEl.id = 'container-' + this.id;\n\n // Append popover to input by default\n const optEl = this.options.container;\n const containerEl = typeof optEl === 'string' ? Utils.querySelector(this.el, optEl) : optEl;\n\n if (containerEl) {\n containerEl.append(this.containerEl);\n } else {\n this.el.parentElement.appendChild(this.containerEl);\n }\n }\n\n _setupVariables() {\n this.currentView = 'hours';\n // `navigator.webkitVibrate` never shipped in any browser - the probe it\n // came from was folklore. A plain feature check is the whole of it.\n this.canVibrate = typeof navigator.vibrate === 'function';\n this._canvas = this.containerEl.querySelector('.timepicker-canvas');\n this.plate = this.containerEl.querySelector('.timepicker-plate');\n this.digitalClock = this.containerEl.querySelector('.timepicker-display-column');\n this.hoursView = this.containerEl.querySelector('.timepicker-hours');\n this.minutesView = this.containerEl.querySelector('.timepicker-minutes');\n this.inputHours = this.containerEl.querySelector('.timepicker-input-hours');\n this.inputMinutes = this.containerEl.querySelector('.timepicker-input-minutes');\n this.inputSeconds = this.containerEl.querySelector('.timepicker-input-seconds');\n if (!this.options.showSeconds) this._removeSecondsField();\n // The fields are spin buttons: the arrows step them, and the hour and\n // minute fields move the hand.\n for (const unit of this._units()) {\n const [min, max] = this._bounds(unit);\n const attributes = { role: 'spinbutton', 'aria-valuemin': min, 'aria-valuemax': max, 'aria-label': this.options.i18n[unit] };\n Object.entries(attributes).forEach(([name, value]) => this._input(unit).setAttribute(name, String(value)));\n }\n this.spanAmPm = this.containerEl.querySelector('.timepicker-span-am-pm');\n this.footer = this.containerEl.querySelector('.timepicker-footer');\n this.amOrPm = 'PM';\n }\n\n private _removeSecondsField() {\n this.containerEl.querySelectorAll('.timepicker-seconds-divider, .timepicker-input-seconds-wrapper').forEach((el) => el.remove());\n this.inputSeconds = null;\n }\n\n private _input(unit: Unit): HTMLInputElement | null {\n return { hours: this.inputHours, minutes: this.inputMinutes, seconds: this.inputSeconds }[unit];\n }\n\n /** The units that have a field. */\n private _units(): Unit[] {\n return UNITS.filter((unit) => this._input(unit));\n }\n\n /** Which unit's field `target` is, if any. */\n private _unitOf(target: EventTarget): Unit | undefined {\n return this._units().find((unit) => this._input(unit) === target);\n }\n\n _pickerSetup() {\n pickerFooter(this.footer, this.options, 'timepicker-clear', this.clear, this.confirm, this.cancel);\n\n this._updateTimeFromInput();\n\n // With a docked display the container is `visibility: hidden` until\n // show(), so the dial can wait for the first interaction. Without one it\n // is on screen from the moment it is inserted and has to be ready now.\n if (!this.options.displayPlugin) this.showView('hours');\n }\n\n /**\n * Build the dial, once. Cheap to call repeatedly - every entry point that\n * touches the clock calls it first, so the picker cannot be interacted with\n * before it exists.\n */\n private _ensureClockBuilt() {\n if (this._clockBuilt) return;\n this._clockBuilt = true;\n this._clockSetup();\n // Applies the AM/PM state _updateTimeFromInput worked out before the\n // buttons existed.\n this._updateAmPmView();\n this._updateRanges();\n }\n\n _clockSetup() {\n if (this.options.twelveHour) {\n // AM Button\n this._amBtn = document.createElement('button');\n this._amBtn.type = 'button';\n this._amBtn.classList.add('am-btn');\n this._amBtn.innerText = 'AM';\n this._amBtn.addEventListener('click', this._handleAmPmClick);\n this.spanAmPm.appendChild(this._amBtn);\n // PM Button\n this._pmBtn = document.createElement('button');\n this._pmBtn.type = 'button';\n this._pmBtn.classList.add('pm-btn');\n this._pmBtn.innerText = 'PM';\n this._pmBtn.addEventListener('click', this._handleAmPmClick);\n this.spanAmPm.appendChild(this._pmBtn);\n }\n this._buildHoursView();\n this._buildMinutesView();\n this._buildSVGClock();\n }\n\n _buildSVGClock() {\n // Draw clock hands and others\n const dialRadius = this.options.dialRadius;\n const tickRadius = this.options.tickRadius;\n const diameter = dialRadius * 2;\n // The ticks, hand and pointer math all centre on dialRadius, so the\n // painted face has to be the same size or the hand sits off centre.\n this.plate.style.width = this.plate.style.height = diameter + 'px';\n const svg = svgNode('svg', { class: 'timepicker-svg', width: String(diameter), height: String(diameter) });\n const g = svgNode('g', { transform: `translate(${dialRadius},${dialRadius})` });\n const bearing = svgNode('circle', { class: 'timepicker-canvas-bearing', cx: '0', cy: '0', r: '4' });\n const hand = svgNode('line', { x1: '0', y1: '0' });\n const bg = svgNode('circle', { class: 'timepicker-canvas-bg', r: String(tickRadius) });\n g.appendChild(hand);\n g.appendChild(bg);\n g.appendChild(bearing);\n svg.appendChild(g);\n this._canvas.appendChild(svg);\n this.hand = hand;\n this.bg = bg;\n this.g = g;\n }\n\n _buildHoursView() {\n // Hours view\n if (this.options.twelveHour) {\n for (let i = 1; i < 13; i += 1) {\n const radian = (i / 6) * Math.PI;\n const radius = this.options.outerRadius;\n this._buildHoursTick(i, radian, radius);\n }\n } else {\n for (let i = 0; i < 24; i += 1) {\n const radian = (i / 6) * Math.PI;\n const inner = i > 0 && i < 13;\n const radius = inner ? this.options.innerRadius : this.options.outerRadius;\n this._buildHoursTick(i, radian, radius);\n }\n }\n }\n\n _buildHoursTick(i: number, radian: number, radius: number) {\n this._placeTick(this.hoursView, radian, radius, i === 0 ? '00' : i.toString());\n }\n\n _buildMinutesView() {\n for (let i = 0; i < 60; i += 5) {\n const radian = (i / 30) * Math.PI;\n this._placeTick(this.minutesView, radian, this.options.outerRadius, pad2(i));\n }\n }\n\n private _placeTick(view: HTMLElement, radian: number, radius: number, text: string) {\n const tick = document.createElement('div');\n tick.classList.add('timepicker-tick');\n tick.style.left =\n this.options.dialRadius + Math.sin(radian) * radius - this.options.tickRadius + 'px';\n tick.style.top =\n this.options.dialRadius - Math.cos(radian) * radius - this.options.tickRadius + 'px';\n tick.textContent = text;\n view.appendChild(tick);\n }\n\n _handleAmPmClick = (e: MouseEvent) => {\n this._handleAmPmInteraction(<HTMLElement>e.target);\n };\n\n _handleAmPmInteraction = (e: HTMLElement) => {\n this.amOrPm = e.classList.contains('am-btn') ? 'AM' : 'PM';\n this._updateAmPmView();\n this._afterChange();\n this.resetClock(null);\n }\n\n _updateAmPmView() {\n // _updateTimeFromInput settles amOrPm before the dial is built; the\n // buttons pick the state up in _ensureClockBuilt.\n if (!this._amBtn || !this._pmBtn) return;\n this._amBtn.setAttribute('aria-pressed', String(this.amOrPm === 'AM'));\n this._pmBtn.setAttribute('aria-pressed', String(this.amOrPm === 'PM'));\n this._amBtn.classList.toggle('outlined', this.amOrPm !== 'AM');\n this._pmBtn.classList.toggle('outlined', this.amOrPm !== 'PM');\n if (this.options.twelveHour) {\n if (this.amOrPm === 'PM') {\n this._amBtn.classList.remove('filled');\n this._pmBtn.classList.add('filled');\n } else if (this.amOrPm === 'AM') {\n this._amBtn.classList.add('filled');\n this._pmBtn.classList.remove('filled');\n }\n }\n }\n\n _updateTimeFromInput() {\n this._clearPending = false;\n this._cancelClockReset();\n const [hours, minutes, seconds] = readTime(`${this.el.value || this.options.defaultTime || ''}`, this.options.fromNow);\n [this.minutes, this.seconds] = [minutes, seconds];\n this._setHours24(hours);\n this._clamp();\n this._writeFields();\n this._updateAmPmView();\n this._updateRanges();\n }\n\n /** Show the time in every field but `except`, which the person is typing in. */\n private _writeFields(except?: HTMLInputElement) {\n this._units().forEach((unit) => {\n if (this._input(unit) !== except) this._input(unit).value = pad2(this[unit]);\n });\n }\n\n /** After a change to the time: keep it in range and update what depends on it. */\n private _afterChange(except?: HTMLInputElement) {\n if (this._clamp()) this._writeFields(except);\n this._updateRanges();\n }\n\n /**\n * Give each field the allowed range of values, and disable a period with\n * no allowed time.\n */\n private _updateRanges() {\n for (const unit of this._units()) {\n const [min, max] = this._range(unit);\n this._input(unit).setAttribute('aria-valuemin', String(min));\n this._input(unit).setAttribute('aria-valuemax', String(max));\n }\n const [first, last] = this._dayRange('hours');\n if (this._amBtn) [this._amBtn.disabled, this._pmBtn.disabled] = [first > 11, last < 12];\n this._disableTicks(this.hoursView, 'hours');\n this._disableTicks(this.minutesView, 'minutes');\n }\n\n /** Mark the ticks of a dial view that are outside the range. */\n private _disableTicks(view: HTMLElement, unit: Unit) {\n view.querySelectorAll('.timepicker-tick').forEach((tick) => {\n tick.classList.toggle('is-disabled', !this._allows(unit, Number(tick.textContent)));\n });\n }\n\n /** The hour on the 24-hour clock, setting AM or PM on a 12-hour one. */\n private _setHours24(hour: number): void {\n if (!this.options.twelveHour) return void (this.hours = hour);\n this.amOrPm = hour >= 12 ? 'PM' : 'AM';\n this.hours = hour % 12 || 12;\n this._updateAmPmView();\n }\n\n /** The time as seconds of the day. */\n private _time() {\n return daySeconds([this._dayValue('hours', this.hours), this.minutes, this.seconds]);\n }\n\n /** Move the time to the nearest allowed time, and say whether it moved. */\n private _clamp() {\n const time = this._time();\n const clamped = Math.min(Math.max(time, this._limits[0]), this._limits[1]);\n if (clamped === time) return false;\n this._setHours24(Math.floor(clamped / 3600));\n [this.minutes, this.seconds] = [Math.floor(clamped / 60) % 60, clamped % 60];\n return true;\n }\n\n /**\n * Show hours or minutes view on timepicker.\n * @param view The name of the view you want to switch to, 'hours' or 'minutes'.\n * @param delay\n */\n showView = (view: Views, delay: number = null) => {\n this._ensureClockBuilt();\n const isHours = view === 'hours',\n nextView = isHours ? this.hoursView : this.minutesView,\n hideView = isHours ? this.minutesView : this.hoursView;\n this.currentView = view;\n\n // Transition view\n hideView.classList.add('timepicker-dial-out');\n\n nextView.style.visibility = 'visible';\n nextView.classList.remove('timepicker-dial-out');\n\n // Reset clock hand\n this.resetClock(delay);\n // After transitions ended\n clearTimeout(this.toggleViewTimer);\n this.toggleViewTimer = setTimeout(() => {\n hideView.style.visibility = 'hidden';\n }, this.options.duration);\n };\n\n private _cancelClockReset() {\n clearTimeout(this._clockResetTimer);\n this._clockResetTimer = null;\n this._canvas?.classList.remove('timepicker-canvas-out');\n }\n\n resetClock(delay: number | null): void {\n this._cancelClockReset();\n const view = this.currentView,\n value = this[view],\n isHours = view === 'hours',\n unit = Math.PI / (isHours ? 6 : 30),\n radian = value * unit,\n radius =\n isHours && value > 0 && value < 13 ? this.options.innerRadius : this.options.outerRadius,\n x = Math.sin(radian) * radius,\n y = -Math.cos(radian) * radius;\n\n if (delay) {\n this._canvas?.classList.add('timepicker-canvas-out');\n this._clockResetTimer = setTimeout(() => {\n this.setHand(x, y);\n }, delay);\n } else {\n this.setHand(x, y);\n }\n }\n\n /**\n * Enter in the hour or minute field commits the typed time. The dial ticks\n * are pointer targets only, and under `autoSubmit` there is no Ok button,\n * so without this a keyboard user could type a time but never set it.\n * Cancelling also keeps Enter from submitting a surrounding form. The\n * listener's column holds only the fields; AM/PM is a separate column.\n */\n _handleDigitalKeydown = Utils.ignoringComposition((event: KeyboardEvent) => {\n if (isStepKey(event)) return this._step(event);\n if (event.key !== 'Enter') return;\n event.preventDefault();\n // Normalize first, as leaving the field would: an emptied field takes its\n // default, and the committed time has to be the one the fields then show.\n this._formatFields();\n if (this.options.autoSubmit) this.done();\n else this.confirm();\n });\n\n /** The lowest and highest value a field can show. */\n private _bounds(unit: Unit): [number, number] {\n if (unit !== 'hours') return [0, 59];\n return this.options.twelveHour ? [1, 12] : [0, 23];\n }\n\n /** The lowest and highest allowed value of a field, given the others. */\n private _range(unit: Unit): [number, number] {\n const [min, max] = this._bounds(unit);\n const allowed = Array.from({ length: max - min + 1 }, (_, i) => min + i).filter((value) => this._allows(unit, value));\n return allowed.length ? [Math.min(...allowed), Math.max(...allowed)] : [min, max];\n }\n\n /**\n * The first and last allowed value of a field, given the fields before it,\n * with hours on the 24-hour clock. An hour is allowed when any second of\n * it is, and so is a minute.\n */\n private _dayRange(unit: Unit): number[] {\n const [size, count] = SPANS[unit];\n const start = this._time() - (this._time() % (size * count));\n return this._limits.map((limit) => Math.min(Math.max(Math.floor((limit - start) / size), 0), count - 1));\n }\n\n /** A field's value with hours on the 24-hour clock. */\n private _dayValue(unit: Unit, value: number) {\n return unit === 'hours' && this.options.twelveHour ? dayHour(value, this.amOrPm === 'PM') : value;\n }\n\n /** Whether a field can take `value` within the range. */\n private _allows(unit: Unit, value: number) {\n const [first, last] = this._dayRange(unit);\n const day = this._dayValue(unit, value);\n return Math.min(Math.max(day, first), last) === day;\n }\n\n /** The whole number typed in a field, or NaN when the field can't take it. */\n private _fieldValue(unit: Unit, text: string) {\n const value = Number(text.trim() || NaN);\n return this._takes(unit, value) ? value : NaN;\n }\n\n /** Whether a field can show `value` and the range allows it. */\n private _takes(unit: Unit, value: number) {\n const [min, max] = this._bounds(unit);\n return Number.isInteger(value) && Math.min(Math.max(value, min), max) === value && this._allows(unit, value);\n }\n\n /** Point the hand at an hour or minute. Seconds have no dial view. */\n private _moveHand(unit: Unit, value: number) {\n if (unit === 'seconds') return;\n this._cancelClockReset();\n this.drawClockFromTimeInput(value, unit === 'hours');\n }\n\n /**\n * Up and Down step a field by one, Page Up and Page Down by five, round\n * the dial: past 59 minutes comes 00. The hand follows hours and minutes.\n * Hours step round the day, so in 12-hour time passing 12 switches AM and\n * PM. Minutes and seconds wrap without carrying. With `minTime` or\n * `maxTime`, a field that is not wholly allowed stops at its last allowed\n * value instead of wrapping.\n */\n private _step(event: KeyboardEvent) {\n const input = event.target as HTMLInputElement;\n const unit = this._unitOf(input);\n if (!unit) return;\n event.preventDefault();\n const value = this._stepValue(unit, STEPS[event.key]);\n if (unit === 'hours') this._setHours24(value);\n else this[unit] = value;\n this._afterChange();\n input.value = pad2(this[unit]);\n this._moveHand(unit, this[unit]);\n }\n\n /** A field's value `step` on, with hours on the 24-hour clock. */\n private _stepValue(unit: Unit, step: number) {\n const [first, last] = this._dayRange(unit);\n const count = SPANS[unit][1];\n const next = this._dayValue(unit, this[unit]) + step;\n return first === 0 && last === count - 1 ? (next + count) % count : Math.min(Math.max(next, first), last);\n }\n\n _inputFromTextField = (event: Event) => {\n const input = event.target as HTMLInputElement;\n const unit = this._unitOf(input);\n if (!unit) return;\n // Any edit to an hour or minute cancels an older delayed hand move.\n if (unit !== 'seconds') this._cancelClockReset();\n const value = this._fieldValue(unit, input.value);\n if (Number.isNaN(value)) return;\n this[unit] = value;\n this._afterChange(input);\n this._moveHand(unit, value);\n };\n\n drawClockFromTimeInput(value: number, isHours: boolean): void {\n const unit = Math.PI / (isHours ? 6 : 30);\n const radian = value * unit;\n let radius;\n if (this.options.twelveHour) {\n radius = this.options.outerRadius;\n } else {\n radius =\n isHours && value > 0 && value < 13 ? this.options.innerRadius : this.options.outerRadius;\n }\n this.setClockAttributes(radian, radius);\n }\n\n setHand(x: number, y: number, roundBy5: boolean = false): void {\n this._cancelClockReset();\n const isHours = this.currentView === 'hours',\n unit = Math.PI / (isHours || roundBy5 ? 6 : 30),\n z = Math.sqrt(x * x + y * y),\n inner = isHours && z < (this.options.outerRadius + this.options.innerRadius) / 2;\n const radius = inner && !this.options.twelveHour ? this.options.innerRadius : this.options.outerRadius;\n let radian = Math.atan2(x, -y);\n\n // Radian should in range [0, 2PI]\n if (radian < 0) {\n radian = Math.PI * 2 + radian;\n }\n\n // Get the round value\n const position = Math.round(radian / unit);\n\n // Get the round radian\n radian = position * unit;\n\n const value = isHours ? this._hourAt(position, inner) : ((roundBy5 ? position * 5 : position) % 60);\n // The hand stays on the last allowed value.\n this._handRefused = !this._allows(this.currentView, value);\n if (this._handRefused) return;\n\n // Once hours or minutes changed, vibrate the device. The timer keeps it\n // from vibrating too frequently.\n if (this[this.currentView] !== value && this.canVibrate && this.options.vibrate && !this.vibrateTimer) {\n navigator.vibrate(10);\n this.vibrateTimer = setTimeout(() => {\n this.vibrateTimer = null;\n }, 100);\n }\n\n this[this.currentView] = value;\n (isHours ? this.inputHours : this.inputMinutes).value = pad2(value);\n\n // Set clock hand and others' position\n this.setClockAttributes(radian, radius);\n this._afterChange();\n }\n\n /** The hour at a dial position, 0 to 12 from the top. */\n private _hourAt(position: number, inner: boolean) {\n return this.options.twelveHour ? position % 12 || 12 : ringHour(position, inner);\n }\n\n setClockAttributes(radian: number, radius: number) {\n // Nothing to point at until the SVG exists.\n if (!this.hand || !this.bg) return;\n const cx1 = Math.sin(radian) * (radius - this.options.tickRadius),\n cy1 = -Math.cos(radian) * (radius - this.options.tickRadius),\n cx2 = Math.sin(radian) * radius,\n cy2 = -Math.cos(radian) * radius;\n this.hand.setAttribute('x2', cx1.toString());\n this.hand.setAttribute('y2', cy1.toString());\n this.bg.setAttribute('cx', cx2.toString());\n this.bg.setAttribute('cy', cy2.toString());\n }\n\n formatHours() {\n if (this.inputHours.value === '') this.setHoursDefault();\n this.inputHours.value = pad2(this.hours);\n }\n\n // An emptied field takes the current time, which can be outside minTime\n // and maxTime, so it goes through _afterChange like any other change.\n formatMinutes() {\n if (this.inputMinutes.value === '') {\n this.minutes = new Date().getMinutes();\n this._afterChange();\n }\n this.inputMinutes.value = pad2(this.minutes);\n }\n\n formatSeconds() {\n if (this.inputSeconds.value === '') {\n this.seconds = new Date().getSeconds();\n this._afterChange();\n }\n this.inputSeconds.value = pad2(this.seconds);\n }\n\n /** Normalize every field, as leaving it would. */\n private _formatFields() {\n this.formatHours();\n this.formatMinutes();\n if (this.inputSeconds) this.formatSeconds();\n }\n\n setHoursDefault() {\n // _setHours24 also sets AM or PM, which the old 12-hour path left as it was.\n this._setHours24(new Date().getHours());\n this._afterChange();\n this.inputHours.value = this.hours.toString();\n }\n\n done = (clearValue: boolean | null = null): void => {\n // Set input value\n const last = this.el.value;\n let value = clearValue ? '' : this._clockTime(this.hours);\n this.time = value;\n if (!clearValue) value = this._inputValue(value);\n this.el.value = value;\n // Trigger change event\n if (value !== last) {\n this.el.dispatchEvent(\n new Event('change', { bubbles: true, cancelable: true, composed: true })\n );\n }\n };\n\n /** `HH:MM` for the given hour, or `HH:MM:SS` with a seconds field. */\n private _clockTime(hours: number) {\n const parts = this.inputSeconds ? [hours, this.minutes, this.seconds] : [hours, this.minutes];\n return parts.map(pad2).join(':');\n }\n\n // A time input accepts only 24-hour HH:mm or HH:mm:ss and empties itself\n // on anything else, so it never gets the AM/PM a text input shows.\n private _inputValue(time: string) {\n if (this.el.type === 'time') return this._clockTime(this._dayValue('hours', this.hours));\n return this.options.twelveHour ? `${time} ${this.amOrPm}` : time;\n }\n\n confirm = () => {\n this.done(this._clearPending);\n this._clearPending = false;\n hideModal(this.displayPlugin);\n this._notify('confirm', this.options.onDone, { args: [] });\n }\n\n cancel = () => {\n // Cancel keeps the previously submitted value in the input.\n this._clearPending = false;\n hideModal(this.displayPlugin);\n this._notify('cancel', this.options.onCancel, { args: [] });\n }\n\n /**\n * Empties the input. A picker with Ok and Cancel, which a modal always is,\n * empties its fields and waits for Ok, so Cancel keeps the value: it used to\n * write the empty value at once.\n */\n clear = () => {\n if (this.options.autoSubmit) return this.done(true);\n this._clearPending = true;\n this._units().forEach((unit) => (this._input(unit).value = ''));\n };\n\n /** Choosing a time after Clear, anywhere but the footer, keeps a time after all. */\n private _keepTime = (e: Event) => {\n if (!this._clearPending || this.footer.contains(e.target as Node)) return;\n this._clearPending = false;\n // A key goes into the field it was pressed in, so that field stays empty.\n this._writeFields(e.type === 'keydown' ? (e.target as HTMLInputElement) : undefined);\n };\n\n static {\n Timepicker._template = `<div class=\"timepicker-container\">\n <div class=\"timepicker-digital-display\">\n <div class=\"timepicker-text-container\">\n <div class=\"timepicker-display-column timepicker-display-digital-clock\">\n <div class=\"timepicker-input-hours-wrapper\">\n <input type=\"text\" maxlength=\"2\" class=\"timepicker-input-hours\" />\n </div>\n <div class=\"timepicker-input-divider-wrapper\">\n <span class=\"timepicker-input-divider\">:</span>\n </div>\n <div class=\"timepicker-input-minutes-wrapper\">\n <input type=\"text\" maxlength=\"2\" class=\"timepicker-input-minutes\" />\n </div>\n <div class=\"timepicker-input-divider-wrapper timepicker-seconds-divider\">\n <span class=\"timepicker-input-divider\">:</span>\n </div>\n <div class=\"timepicker-input-seconds-wrapper\">\n <input type=\"text\" maxlength=\"2\" class=\"timepicker-input-seconds\" />\n </div>\n </div>\n <div class=\"timepicker-display-column timepicker-display-am-pm\">\n <div class=\"timepicker-span-am-pm\"></div>\n </div>\n </div>\n </div>\n <div class=\"timepicker-analog-display\">\n <div class=\"timepicker-plate\">\n <div class=\"timepicker-canvas\"></div>\n <div class=\"timepicker-dial timepicker-hours\"></div>\n <div class=\"timepicker-dial timepicker-minutes timepicker-dial-out\"></div>\n </div>\n <div class=\"timepicker-footer\"></div>\n </div>\n </div>`;\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// src/ts/core/spring.ts
|
|
2
|
+
var FPS = 60;
|
|
3
|
+
var REST = 0.5;
|
|
4
|
+
var LONGEST = 5;
|
|
5
|
+
function displacement(x0, v0, { damping, stiffness }, t) {
|
|
6
|
+
const w = Math.sqrt(stiffness);
|
|
7
|
+
if (damping >= 1) return Math.exp(-w * t) * (x0 + (v0 + w * x0) * t);
|
|
8
|
+
const wd = w * Math.sqrt(1 - damping * damping);
|
|
9
|
+
return Math.exp(-damping * w * t) * (x0 * Math.cos(wd * t) + (v0 + damping * w * x0) / wd * Math.sin(wd * t));
|
|
10
|
+
}
|
|
11
|
+
function springPath(from, to, velocity, spring) {
|
|
12
|
+
const path = [from];
|
|
13
|
+
const [x0, v0] = [from - to, velocity * 1e3];
|
|
14
|
+
for (let frame = 1; frame < LONGEST * FPS; frame++) {
|
|
15
|
+
const x = displacement(x0, v0, spring, frame / FPS);
|
|
16
|
+
path.push(to + x);
|
|
17
|
+
if (Math.abs(x) < REST && Math.abs(to + x - path[frame - 1]) < REST) break;
|
|
18
|
+
}
|
|
19
|
+
path.push(to);
|
|
20
|
+
return path;
|
|
21
|
+
}
|
|
22
|
+
function springToken(el, name) {
|
|
23
|
+
const style = getComputedStyle(el);
|
|
24
|
+
const read = (part) => parseFloat(style.getPropertyValue(`--md-sys-motion-spring-${name}-${part}`));
|
|
25
|
+
const [damping, stiffness] = [read("damping"), read("stiffness")];
|
|
26
|
+
return damping > 0 && stiffness > 0 ? { damping, stiffness } : null;
|
|
27
|
+
}
|
|
28
|
+
function animatePath(el, property, path, write) {
|
|
29
|
+
const frames = path.map((value) => ({ [property]: write(value) }));
|
|
30
|
+
return el.animate(frames, { duration: (path.length - 1) * 1e3 / FPS, easing: "linear" });
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export {
|
|
34
|
+
springPath,
|
|
35
|
+
springToken,
|
|
36
|
+
animatePath
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=chunk-W6FAL3TI.mjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/ts/core/spring.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Springs solved at run time. The CSS springs are sampled at build time\n * into linear() easings that always start from rest, so motion that is\n * interrupted restarts. A spring solved here starts from where something\n * is, at the speed it has, as M3's springs do: mass 1, a damping ratio and\n * a stiffness.\n */\nexport interface Spring {\n damping: number;\n stiffness: number;\n}\n\n/** Frames per second the path is sampled at. */\nconst FPS = 60;\n/** Settled once within this distance of the target and moving less than this a frame. */\nconst REST = 0.5;\n/** No spring runs longer than this, in seconds. */\nconst LONGEST = 5;\n\n/**\n * How far from the target a spring is at `t` seconds, released `x0` away\n * at speed `v0`: underdamped springs oscillate as they decay, and M3's\n * critically damped ones do not.\n */\nfunction displacement(x0: number, v0: number, { damping, stiffness }: Spring, t: number) {\n const w = Math.sqrt(stiffness);\n if (damping >= 1) return Math.exp(-w * t) * (x0 + (v0 + w * x0) * t);\n const wd = w * Math.sqrt(1 - damping * damping);\n return Math.exp(-damping * w * t) * (x0 * Math.cos(wd * t) + ((v0 + damping * w * x0) / wd) * Math.sin(wd * t));\n}\n\n/**\n * The spring's path from `from` to `to`, released at `velocity` in units\n * per millisecond, as one value a frame until it settles on `to`.\n */\nexport function springPath(from: number, to: number, velocity: number, spring: Spring): number[] {\n const path = [from];\n const [x0, v0] = [from - to, velocity * 1000];\n for (let frame = 1; frame < LONGEST * FPS; frame++) {\n const x = displacement(x0, v0, spring, frame / FPS);\n path.push(to + x);\n if (Math.abs(x) < REST && Math.abs(to + x - path[frame - 1]) < REST) break;\n }\n path.push(to);\n return path;\n}\n\n/** The spring a CSS token names, from its -damping and -stiffness tokens, or null without them. */\nexport function springToken(el: Element, name: string): Spring | null {\n const style = getComputedStyle(el);\n const read = (part: string) => parseFloat(style.getPropertyValue(`--md-sys-motion-spring-${name}-${part}`));\n const [damping, stiffness] = [read('damping'), read('stiffness')];\n return damping > 0 && stiffness > 0 ? { damping, stiffness } : null;\n}\n\n/** Plays a path on one property, `write` turning each value into CSS. */\nexport function animatePath(el: Element, property: string, path: number[], write: (value: number) => string): Animation {\n const frames = path.map((value) => ({ [property]: write(value) }));\n return el.animate(frames, { duration: ((path.length - 1) * 1000) / FPS, easing: 'linear' });\n}\n"],
|
|
5
|
+
"mappings": ";AAaA,IAAM,MAAM;AAEZ,IAAM,OAAO;AAEb,IAAM,UAAU;AAOhB,SAAS,aAAa,IAAY,IAAY,EAAE,SAAS,UAAU,GAAW,GAAW;AACvF,QAAM,IAAI,KAAK,KAAK,SAAS;AAC7B,MAAI,WAAW,EAAG,QAAO,KAAK,IAAI,CAAC,IAAI,CAAC,KAAK,MAAM,KAAK,IAAI,MAAM;AAClE,QAAM,KAAK,IAAI,KAAK,KAAK,IAAI,UAAU,OAAO;AAC9C,SAAO,KAAK,IAAI,CAAC,UAAU,IAAI,CAAC,KAAK,KAAK,KAAK,IAAI,KAAK,CAAC,KAAM,KAAK,UAAU,IAAI,MAAM,KAAM,KAAK,IAAI,KAAK,CAAC;AAC/G;AAMO,SAAS,WAAW,MAAc,IAAY,UAAkB,QAA0B;AAC/F,QAAM,OAAO,CAAC,IAAI;AAClB,QAAM,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,IAAI,WAAW,GAAI;AAC5C,WAAS,QAAQ,GAAG,QAAQ,UAAU,KAAK,SAAS;AAClD,UAAM,IAAI,aAAa,IAAI,IAAI,QAAQ,QAAQ,GAAG;AAClD,SAAK,KAAK,KAAK,CAAC;AAChB,QAAI,KAAK,IAAI,CAAC,IAAI,QAAQ,KAAK,IAAI,KAAK,IAAI,KAAK,QAAQ,CAAC,CAAC,IAAI,KAAM;AAAA,EACvE;AACA,OAAK,KAAK,EAAE;AACZ,SAAO;AACT;AAGO,SAAS,YAAY,IAAa,MAA6B;AACpE,QAAM,QAAQ,iBAAiB,EAAE;AACjC,QAAM,OAAO,CAAC,SAAiB,WAAW,MAAM,iBAAiB,0BAA0B,IAAI,IAAI,IAAI,EAAE,CAAC;AAC1G,QAAM,CAAC,SAAS,SAAS,IAAI,CAAC,KAAK,SAAS,GAAG,KAAK,WAAW,CAAC;AAChE,SAAO,UAAU,KAAK,YAAY,IAAI,EAAE,SAAS,UAAU,IAAI;AACjE;AAGO,SAAS,YAAY,IAAa,UAAkB,MAAgB,OAA6C;AACtH,QAAM,SAAS,KAAK,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,GAAG,MAAM,KAAK,EAAE,EAAE;AACjE,SAAO,GAAG,QAAQ,QAAQ,EAAE,WAAY,KAAK,SAAS,KAAK,MAAQ,KAAK,QAAQ,SAAS,CAAC;AAC5F;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ColumnChart
|
|
3
|
+
} from "./chunk-26VUH75M.mjs";
|
|
4
|
+
import {
|
|
5
|
+
hasClass,
|
|
6
|
+
niceStep,
|
|
7
|
+
steps
|
|
8
|
+
} from "./chunk-IQOTGGHX.mjs";
|
|
9
|
+
|
|
10
|
+
// src/ts/components/mixedChart.ts
|
|
11
|
+
function fitSteps(min, max, parts) {
|
|
12
|
+
let step = niceStep(max - min, parts);
|
|
13
|
+
while (Math.floor(min / step) * step + parts * step < max) step = niceStep(step * parts * 1.001, parts);
|
|
14
|
+
return [Math.floor(min / step) * step, step];
|
|
15
|
+
}
|
|
16
|
+
var MixedChart = class extends ColumnChart {
|
|
17
|
+
get _type() {
|
|
18
|
+
return "mixed-chart";
|
|
19
|
+
}
|
|
20
|
+
get _points() {
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* With .stacked, the columns on each scale stack on the ones before them;
|
|
25
|
+
* the lines and areas keep their own values.
|
|
26
|
+
*/
|
|
27
|
+
_stack(series) {
|
|
28
|
+
const columns = series.filter((each) => hasClass(each, "column"));
|
|
29
|
+
super._stack(columns.filter((each) => !hasClass(each, "end")));
|
|
30
|
+
super._stack(columns.filter((each) => hasClass(each, "end")));
|
|
31
|
+
}
|
|
32
|
+
/** The start scale, then the end scale; each includes zero if it has columns. */
|
|
33
|
+
_scale(series, min, max) {
|
|
34
|
+
const end = series.filter((each) => hasClass(each, "end"));
|
|
35
|
+
const start = series.filter((each) => !end.includes(each));
|
|
36
|
+
const columns = (list) => list.some((each) => hasClass(each, "column"));
|
|
37
|
+
const endRange = [this._number("endMin"), this._number("endMax")];
|
|
38
|
+
const y = super._scale(start, min, max, columns(start));
|
|
39
|
+
super._scale(end, ...endRange, columns(end));
|
|
40
|
+
if ([min, max, ...endRange].every((value) => value === null)) this._align(start, end);
|
|
41
|
+
return y;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* With .axis, widens the end scale to as many round steps as the start
|
|
45
|
+
* scale has, so its labels fall on the start scale's grid lines.
|
|
46
|
+
*/
|
|
47
|
+
_align(start, end) {
|
|
48
|
+
const parts = start.length ? start[0].scale.ticks.length - 1 : 0;
|
|
49
|
+
if (parts < 1 || !end.length) return;
|
|
50
|
+
const [low, step] = fitSteps(end[0].scale.min, end[0].scale.max, parts);
|
|
51
|
+
const high = low + parts * step;
|
|
52
|
+
this._apply(end, { min: low, max: high, ticks: steps(low, high, step) });
|
|
53
|
+
}
|
|
54
|
+
/** Columns behind, then the lines and areas over them. */
|
|
55
|
+
_draw() {
|
|
56
|
+
const marks = document.createElement("div");
|
|
57
|
+
marks.className = "mixed-chart-marks";
|
|
58
|
+
const columns = super._draw(this.series.filter((series) => hasClass(series, "column")));
|
|
59
|
+
columns.className = "mixed-chart-columns";
|
|
60
|
+
marks.append(columns, this._drawLines(this.series.filter((series) => !hasClass(series, "column"))));
|
|
61
|
+
return marks;
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
MixedChart.key = "Expressive_MixedChart";
|
|
65
|
+
|
|
66
|
+
export {
|
|
67
|
+
MixedChart
|
|
68
|
+
};
|
|
69
|
+
//# sourceMappingURL=chunk-XB6Y7P5W.mjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/ts/components/mixedChart.ts"],
|
|
4
|
+
"sourcesContent": ["import { ColumnChart } from './columnChart';\nimport { LineChartOptions, Series, hasClass as has, niceStep, steps } from './lineChart';\n\nexport type MixedChartOptions = LineChartOptions;\n\n/** The low end and round step that cover min to max in exactly `parts` steps. */\nfunction fitSteps(min: number, max: number, parts: number): [low: number, step: number] {\n let step = niceStep(max - min, parts);\n // A floored start can leave the top short; the next round step covers it.\n while (Math.floor(min / step) * step + parts * step < max) step = niceStep(step * parts * 1.001, parts);\n return [Math.floor(min / step) * step, step];\n}\n\n/**\n * Mixed chart. It reads its <table> like LineChart, and draws each series\n * by its header cell's class: `column` as columns from zero, `area` as a\n * line with a fill under it, and anything else as a line. Series with\n * `end` are drawn against a second scale, set by `data-end-min` and\n * `data-end-max`, so values of different sizes or units share the plot.\n * With `stacked` the columns stack; `points` and `straight` apply to the\n * lines as in LineChart.\n *\n * Call `update()` after changing the table, or start it with `watch` or\n * `data-watch`.\n */\nexport class MixedChart extends ColumnChart {\n protected get _type() {\n return 'mixed-chart';\n }\n\n protected get _points() {\n return true;\n }\n\n static key = 'Expressive_MixedChart';\n\n /**\n * With .stacked, the columns on each scale stack on the ones before them;\n * the lines and areas keep their own values.\n */\n protected _stack(series: Series[]) {\n const columns = series.filter((each) => has(each, 'column'));\n super._stack(columns.filter((each) => !has(each, 'end')));\n super._stack(columns.filter((each) => has(each, 'end')));\n }\n\n /** The start scale, then the end scale; each includes zero if it has columns. */\n protected _scale(series: Series[], min: number | null, max: number | null) {\n const end = series.filter((each) => has(each, 'end'));\n const start = series.filter((each) => !end.includes(each));\n const columns = (list: Series[]) => list.some((each) => has(each, 'column'));\n const endRange = [this._number('endMin'), this._number('endMax')] as const;\n const y = super._scale(start, min, max, columns(start));\n super._scale(end, ...endRange, columns(end));\n // Only scales the chart chose itself can stretch to line up.\n if ([min, max, ...endRange].every((value) => value === null)) this._align(start, end);\n return y;\n }\n\n /**\n * With .axis, widens the end scale to as many round steps as the start\n * scale has, so its labels fall on the start scale's grid lines.\n */\n private _align(start: Series[], end: Series[]) {\n const parts = start.length ? start[0].scale.ticks.length - 1 : 0;\n if (parts < 1 || !end.length) return;\n const [low, step] = fitSteps(end[0].scale.min, end[0].scale.max, parts);\n const high = low + parts * step;\n this._apply(end, { min: low, max: high, ticks: steps(low, high, step) });\n }\n\n /** Columns behind, then the lines and areas over them. */\n protected _draw(): Element {\n const marks = document.createElement('div');\n marks.className = 'mixed-chart-marks';\n const columns = super._draw(this.series.filter((series) => has(series, 'column')));\n columns.className = 'mixed-chart-columns';\n marks.append(columns, this._drawLines(this.series.filter((series) => !has(series, 'column'))));\n return marks;\n }\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;AAMA,SAAS,SAAS,KAAa,KAAa,OAA4C;AACtF,MAAI,OAAO,SAAS,MAAM,KAAK,KAAK;AAEpC,SAAO,KAAK,MAAM,MAAM,IAAI,IAAI,OAAO,QAAQ,OAAO,IAAK,QAAO,SAAS,OAAO,QAAQ,OAAO,KAAK;AACtG,SAAO,CAAC,KAAK,MAAM,MAAM,IAAI,IAAI,MAAM,IAAI;AAC7C;AAcO,IAAM,aAAN,cAAyB,YAAY;AAAA,EAC1C,IAAc,QAAQ;AACpB,WAAO;AAAA,EACT;AAAA,EAEA,IAAc,UAAU;AACtB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAQU,OAAO,QAAkB;AACjC,UAAM,UAAU,OAAO,OAAO,CAAC,SAAS,SAAI,MAAM,QAAQ,CAAC;AAC3D,UAAM,OAAO,QAAQ,OAAO,CAAC,SAAS,CAAC,SAAI,MAAM,KAAK,CAAC,CAAC;AACxD,UAAM,OAAO,QAAQ,OAAO,CAAC,SAAS,SAAI,MAAM,KAAK,CAAC,CAAC;AAAA,EACzD;AAAA;AAAA,EAGU,OAAO,QAAkB,KAAoB,KAAoB;AACzE,UAAM,MAAM,OAAO,OAAO,CAAC,SAAS,SAAI,MAAM,KAAK,CAAC;AACpD,UAAM,QAAQ,OAAO,OAAO,CAAC,SAAS,CAAC,IAAI,SAAS,IAAI,CAAC;AACzD,UAAM,UAAU,CAAC,SAAmB,KAAK,KAAK,CAAC,SAAS,SAAI,MAAM,QAAQ,CAAC;AAC3E,UAAM,WAAW,CAAC,KAAK,QAAQ,QAAQ,GAAG,KAAK,QAAQ,QAAQ,CAAC;AAChE,UAAM,IAAI,MAAM,OAAO,OAAO,KAAK,KAAK,QAAQ,KAAK,CAAC;AACtD,UAAM,OAAO,KAAK,GAAG,UAAU,QAAQ,GAAG,CAAC;AAE3C,QAAI,CAAC,KAAK,KAAK,GAAG,QAAQ,EAAE,MAAM,CAAC,UAAU,UAAU,IAAI,EAAG,MAAK,OAAO,OAAO,GAAG;AACpF,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,OAAO,OAAiB,KAAe;AAC7C,UAAM,QAAQ,MAAM,SAAS,MAAM,CAAC,EAAE,MAAM,MAAM,SAAS,IAAI;AAC/D,QAAI,QAAQ,KAAK,CAAC,IAAI,OAAQ;AAC9B,UAAM,CAAC,KAAK,IAAI,IAAI,SAAS,IAAI,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC,EAAE,MAAM,KAAK,KAAK;AACtE,UAAM,OAAO,MAAM,QAAQ;AAC3B,SAAK,OAAO,KAAK,EAAE,KAAK,KAAK,KAAK,MAAM,OAAO,MAAM,KAAK,MAAM,IAAI,EAAE,CAAC;AAAA,EACzE;AAAA;AAAA,EAGU,QAAiB;AACzB,UAAM,QAAQ,SAAS,cAAc,KAAK;AAC1C,UAAM,YAAY;AAClB,UAAM,UAAU,MAAM,MAAM,KAAK,OAAO,OAAO,CAAC,WAAW,SAAI,QAAQ,QAAQ,CAAC,CAAC;AACjF,YAAQ,YAAY;AACpB,UAAM,OAAO,SAAS,KAAK,WAAW,KAAK,OAAO,OAAO,CAAC,WAAW,CAAC,SAAI,QAAQ,QAAQ,CAAC,CAAC,CAAC;AAC7F,WAAO;AAAA,EACT;AACF;AAvDa,WASJ,MAAM;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import {
|
|
2
|
+
LineChart,
|
|
3
|
+
ROW_COLORS,
|
|
4
|
+
cellValue,
|
|
5
|
+
linearKey,
|
|
6
|
+
morph,
|
|
7
|
+
pace,
|
|
8
|
+
seriesColor,
|
|
9
|
+
textSpan
|
|
10
|
+
} from "./chunk-IQOTGGHX.mjs";
|
|
11
|
+
import {
|
|
12
|
+
svgNode
|
|
13
|
+
} from "./chunk-67UNY7RH.mjs";
|
|
14
|
+
|
|
15
|
+
// src/ts/components/sankeyChart.ts
|
|
16
|
+
var NODE_WIDTH = 2;
|
|
17
|
+
var NODE_GAP = 4;
|
|
18
|
+
var text = (row, column) => row.cells[column]?.textContent.trim() ?? "";
|
|
19
|
+
var sum = (flows) => flows.reduce((total, flow) => total + flow.value, 0);
|
|
20
|
+
function flowOf(row, index) {
|
|
21
|
+
const [source, target, value] = [text(row, 0), text(row, 1), Number(cellValue(row.cells[2]))];
|
|
22
|
+
return source && target && value > 0 ? { row: index, source, target, value } : null;
|
|
23
|
+
}
|
|
24
|
+
function reaches(flows, from, to, seen = /* @__PURE__ */ new Set()) {
|
|
25
|
+
if (from === to) return true;
|
|
26
|
+
seen.add(from);
|
|
27
|
+
return flows.some((flow) => flow.source === from && !seen.has(flow.target) && reaches(flows, flow.target, to, seen));
|
|
28
|
+
}
|
|
29
|
+
function flowsOf(rows) {
|
|
30
|
+
const flows = [];
|
|
31
|
+
rows.forEach((row, index) => {
|
|
32
|
+
const flow = flowOf(row, index);
|
|
33
|
+
if (flow && !reaches(flows, flow.target, flow.source)) flows.push(flow);
|
|
34
|
+
});
|
|
35
|
+
return flows;
|
|
36
|
+
}
|
|
37
|
+
function columnOf(name, flows, columns) {
|
|
38
|
+
if (!columns.has(name)) {
|
|
39
|
+
const sources = flows.filter((flow) => flow.target === name).map((flow) => columnOf(flow.source, flows, columns) + 1);
|
|
40
|
+
columns.set(name, Math.max(0, ...sources));
|
|
41
|
+
}
|
|
42
|
+
return columns.get(name);
|
|
43
|
+
}
|
|
44
|
+
function nodesOf(flows) {
|
|
45
|
+
const columns = /* @__PURE__ */ new Map();
|
|
46
|
+
return [...new Set(flows.flatMap((flow) => [flow.source, flow.target]))].map((name, i) => ({
|
|
47
|
+
name,
|
|
48
|
+
color: seriesColor(i, ROW_COLORS),
|
|
49
|
+
column: columnOf(name, flows, columns),
|
|
50
|
+
size: Math.max(sum(flows.filter((flow) => flow.target === name)), sum(flows.filter((flow) => flow.source === name))),
|
|
51
|
+
x: 0,
|
|
52
|
+
top: 0,
|
|
53
|
+
height: 0
|
|
54
|
+
}));
|
|
55
|
+
}
|
|
56
|
+
function place(nodes) {
|
|
57
|
+
const count = Math.max(...nodes.map((node) => node.column)) + 1;
|
|
58
|
+
const columns = Array.from({ length: count }, (_, c) => nodes.filter((node) => node.column === c));
|
|
59
|
+
const gap = Math.min(NODE_GAP, 50 / Math.max(...columns.map((column) => column.length)));
|
|
60
|
+
const room = (column) => 100 - (column.length - 1) * gap;
|
|
61
|
+
const total = (column) => column.reduce((height, node) => height + node.size, 0);
|
|
62
|
+
const scale = Math.min(...columns.map((column) => room(column) / total(column)));
|
|
63
|
+
columns.forEach((column, c) => {
|
|
64
|
+
let top = (room(column) - total(column) * scale) / 2;
|
|
65
|
+
for (const node of column) {
|
|
66
|
+
Object.assign(node, { x: c / (count - 1) * (100 - NODE_WIDTH), top, height: node.size * scale });
|
|
67
|
+
top += node.height + gap;
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
return scale;
|
|
71
|
+
}
|
|
72
|
+
function linksOf(flows, nodes, scale) {
|
|
73
|
+
const byName = new Map(nodes.map((node) => [node.name, node]));
|
|
74
|
+
const [out, into] = [/* @__PURE__ */ new Map(), /* @__PURE__ */ new Map()];
|
|
75
|
+
const next = (used, node, size) => {
|
|
76
|
+
const top = node.top + (used.get(node) ?? 0);
|
|
77
|
+
used.set(node, top - node.top + size);
|
|
78
|
+
return top;
|
|
79
|
+
};
|
|
80
|
+
return flows.map((flow) => {
|
|
81
|
+
const [source, target, size] = [byName.get(flow.source), byName.get(flow.target), flow.value * scale];
|
|
82
|
+
return { flow, source, target, from: next(out, source, size), to: next(into, target, size), size };
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
var SankeyChart = class extends LineChart {
|
|
86
|
+
get _type() {
|
|
87
|
+
return "sankey-chart";
|
|
88
|
+
}
|
|
89
|
+
/** The value column is the one series; the target column is read on its own. */
|
|
90
|
+
get _seriesFrom() {
|
|
91
|
+
return 2;
|
|
92
|
+
}
|
|
93
|
+
get _seriesTo() {
|
|
94
|
+
return 3;
|
|
95
|
+
}
|
|
96
|
+
/** The links carry the values, so there is no value axis. */
|
|
97
|
+
get _axis() {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
/** The links the keys and pointer reach. */
|
|
101
|
+
get _count() {
|
|
102
|
+
return this._links?.length ?? 0;
|
|
103
|
+
}
|
|
104
|
+
/** Highlights one link, numbered in table order among those drawn. Pass -1 to hide the tooltip. */
|
|
105
|
+
show(index) {
|
|
106
|
+
if (!this._tooltip || index === this.activeIndex) return;
|
|
107
|
+
this._paths[this.activeIndex]?.classList.remove("active");
|
|
108
|
+
this._paths[index]?.classList.add("active");
|
|
109
|
+
this.activeIndex = index;
|
|
110
|
+
const link = this._links[index];
|
|
111
|
+
this._tooltip.hidden = !link;
|
|
112
|
+
if (link) this._fill(link);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Fills the tooltip beside the link's middle: its source and target under
|
|
116
|
+
* their column headers, with their nodes' colors, and the value cell's
|
|
117
|
+
* text, as the author wrote them. Past the middle it opens back over the plot.
|
|
118
|
+
*/
|
|
119
|
+
_fill({ flow, source, target, from, to, size }) {
|
|
120
|
+
const x = this._across((source.x + NODE_WIDTH + target.x) / 2);
|
|
121
|
+
Object.assign(this._tooltip.style, { left: `${x}%`, top: `${(from + to + size) / 2}%` });
|
|
122
|
+
this._tooltip.classList.toggle("end", x > 50);
|
|
123
|
+
const header = this._header.map((cell) => cell.textContent.trim());
|
|
124
|
+
const [sourceName, targetName, value] = [textSpan(header[0]), textSpan(header[1]), textSpan(header[2])];
|
|
125
|
+
sourceName.dataset.series = source.color;
|
|
126
|
+
targetName.dataset.series = target.color;
|
|
127
|
+
value.className = "value";
|
|
128
|
+
this._tooltip.replaceChildren(sourceName, textSpan(source.name), targetName, textSpan(target.name), value, textSpan(text(this._rows[flow.row], 2)));
|
|
129
|
+
}
|
|
130
|
+
/** The link under the pointer, or -1 off every link. By position, since a touch keeps its first target as it drags. */
|
|
131
|
+
_indexAt(e) {
|
|
132
|
+
const hits = this.el.getRootNode().elementsFromPoint(e.clientX, e.clientY);
|
|
133
|
+
const link = hits.find((hit) => this._paths.includes(hit));
|
|
134
|
+
return this._paths.indexOf(link);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Steps through the links in table order. The arrows keep their meaning
|
|
138
|
+
* in a right-to-left chart, since table order is no direction on screen.
|
|
139
|
+
*/
|
|
140
|
+
_keyTarget(key) {
|
|
141
|
+
return linearKey(key, this.activeIndex, this._links.length - 1);
|
|
142
|
+
}
|
|
143
|
+
/** Reads the flows and lays out their nodes and links. Without a link to draw, the chart draws nothing. */
|
|
144
|
+
_read() {
|
|
145
|
+
super._read();
|
|
146
|
+
const flows = flowsOf(this._rows);
|
|
147
|
+
if (!flows.length) {
|
|
148
|
+
[this.series, this._nodes, this._links] = [[], [], []];
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
this._nodes = nodesOf(flows);
|
|
152
|
+
this._links = linksOf(flows, this._nodes, place(this._nodes));
|
|
153
|
+
}
|
|
154
|
+
/** An x position in hundredths of the plot, mirrored in a right-to-left chart. */
|
|
155
|
+
_across(x) {
|
|
156
|
+
return this._reversed ? 100 - x : x;
|
|
157
|
+
}
|
|
158
|
+
/** A node as path data: a rectangle. */
|
|
159
|
+
_nodePath({ x, top, height }) {
|
|
160
|
+
const [start, end] = [this._across(x), this._across(x + NODE_WIDTH)];
|
|
161
|
+
return `M${start},${top}H${end}V${top + height}H${start}Z`;
|
|
162
|
+
}
|
|
163
|
+
/** A link as path data: two curves from the source's edge to the target's, closed between them. */
|
|
164
|
+
_linkPath({ source, target, from, to, size }) {
|
|
165
|
+
const [x0, x1] = [source.x + NODE_WIDTH, target.x];
|
|
166
|
+
const [start, middle, end] = [this._across(x0), this._across((x0 + x1) / 2), this._across(x1)];
|
|
167
|
+
return `M${start},${from}C${middle},${from} ${middle},${to} ${end},${to}V${to + size}C${middle},${to + size} ${middle},${from + size} ${start},${from + size}Z`;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* The links, then the nodes over their ends. Neither has a stroke, so the
|
|
171
|
+
* stretched SVG keeps their sizes. After update(), each shape still in the
|
|
172
|
+
* table moves from where it was: a link found by its source and target
|
|
173
|
+
* names, a node by its name.
|
|
174
|
+
*/
|
|
175
|
+
_draw() {
|
|
176
|
+
const svg = svgNode("svg", {
|
|
177
|
+
viewBox: "0 0 100 100",
|
|
178
|
+
preserveAspectRatio: "none",
|
|
179
|
+
"aria-hidden": "true",
|
|
180
|
+
focusable: "false"
|
|
181
|
+
});
|
|
182
|
+
const [was, timing] = [this._shapes ?? /* @__PURE__ */ new Map(), this._before.length ? pace(this.el) : null];
|
|
183
|
+
this._shapes = /* @__PURE__ */ new Map();
|
|
184
|
+
const shape = (className, key, color, d) => {
|
|
185
|
+
const path = svgNode("path", { class: className, "data-series": color, d });
|
|
186
|
+
if (timing && was.has(key)) morph(path, was.get(key), timing);
|
|
187
|
+
this._shapes.set(key, d);
|
|
188
|
+
return path;
|
|
189
|
+
};
|
|
190
|
+
this._paths = this._links.map((link) => shape("sankey-chart-link", JSON.stringify([link.source.name, link.target.name]), link.source.color, this._linkPath(link)));
|
|
191
|
+
const nodes = this._nodes.map((node) => shape("sankey-chart-node", JSON.stringify(node.name), node.color, this._nodePath(node)));
|
|
192
|
+
svg.append(...this._paths, ...nodes);
|
|
193
|
+
return svg;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* The node names, over the drawing, each level with its node and toward
|
|
197
|
+
* the plot's middle: after the node, or before it in the last column.
|
|
198
|
+
* They are placed from the inline start, so they need no mirroring.
|
|
199
|
+
*/
|
|
200
|
+
_axes() {
|
|
201
|
+
const names = document.createElement("div");
|
|
202
|
+
names.className = "sankey-chart-names";
|
|
203
|
+
names.setAttribute("aria-hidden", "true");
|
|
204
|
+
const last = Math.max(...this._nodes.map((node) => node.column));
|
|
205
|
+
names.append(...this._nodes.map((node) => this._name(node, node.column === last)));
|
|
206
|
+
return [names];
|
|
207
|
+
}
|
|
208
|
+
_name({ name, x, top, height }, last) {
|
|
209
|
+
const span = document.createElement("span");
|
|
210
|
+
span.className = last ? "sankey-chart-name end" : "sankey-chart-name";
|
|
211
|
+
span.textContent = name;
|
|
212
|
+
span.style.setProperty("--sankey-chart-x", `${last ? x : x + NODE_WIDTH}%`);
|
|
213
|
+
span.style.setProperty("--sankey-chart-y", `${top + height / 2}%`);
|
|
214
|
+
return span;
|
|
215
|
+
}
|
|
216
|
+
/** No row labels or legend: the nodes carry the names. */
|
|
217
|
+
_guides() {
|
|
218
|
+
return [];
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
SankeyChart.key = "Expressive_SankeyChart";
|
|
222
|
+
|
|
223
|
+
export {
|
|
224
|
+
SankeyChart
|
|
225
|
+
};
|
|
226
|
+
//# sourceMappingURL=chunk-XDAMOMVD.mjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/ts/components/sankeyChart.ts"],
|
|
4
|
+
"sourcesContent": ["import { svgNode } from '../core/utils';\nimport { LineChart, LineChartOptions, ROW_COLORS, cellValue, linearKey, morph, pace, seriesColor, textSpan as span } from './lineChart';\n\nexport type SankeyChartOptions = LineChartOptions;\n\n// ponytail: fixed shares of the plot; tokens if authors ask to tune them.\n/** A node's width, in hundredths of the plot's width. */\nconst NODE_WIDTH = 2;\n/** The gap between nodes in a column, in hundredths of the plot's height. */\nconst NODE_GAP = 4;\n// ponytail: nodes past six repeat the colors, as pie chart rows do.\n\n/** A row that draws a link: its index, its source and target names, and its value. */\ninterface Flow {\n row: number;\n source: string;\n target: string;\n value: number;\n}\n\n/** A node: its name, color, column and size in value units, and where it sits, in hundredths of the plot. */\ninterface Node {\n name: string;\n color: string;\n column: number;\n size: number;\n x: number;\n top: number;\n height: number;\n}\n\n/** A drawn link: its flow, its ends' nodes, its top at each end and its thickness, in hundredths of the plot. */\ninterface Link {\n flow: Flow;\n source: Node;\n target: Node;\n from: number;\n to: number;\n size: number;\n}\n\n/** A cell's trimmed text, or '' without the cell. */\nconst text = (row: HTMLTableRowElement, column: number) => row.cells[column]?.textContent.trim() ?? '';\n\nconst sum = (flows: Flow[]) => flows.reduce((total, flow) => total + flow.value, 0);\n\n/** A row's flow, or null for a row without both names or a positive value. */\nfunction flowOf(row: HTMLTableRowElement, index: number): Flow | null {\n // A gap's null becomes 0, which draws nothing.\n const [source, target, value] = [text(row, 0), text(row, 1), Number(cellValue(row.cells[2]))];\n return source && target && value > 0 ? { row: index, source, target, value } : null;\n}\n\n/** Whether `from` reaches `to` along the flows, so a flow from `to` to `from` would close a cycle. */\nfunction reaches(flows: Flow[], from: string, to: string, seen = new Set<string>()): boolean {\n if (from === to) return true;\n seen.add(from);\n return flows.some((flow) => flow.source === from && !seen.has(flow.target) && reaches(flows, flow.target, to, seen));\n}\n\n/** The rows' flows in table order, leaving out rows without one and any that would close a cycle. */\nfunction flowsOf(rows: HTMLTableRowElement[]) {\n const flows: Flow[] = [];\n rows.forEach((row, index) => {\n const flow = flowOf(row, index);\n if (flow && !reaches(flows, flow.target, flow.source)) flows.push(flow);\n });\n return flows;\n}\n\n/** A node's column: 0 without incoming flows, otherwise one past the furthest of its sources. */\nfunction columnOf(name: string, flows: Flow[], columns: Map<string, number>): number {\n if (!columns.has(name)) {\n const sources = flows.filter((flow) => flow.target === name).map((flow) => columnOf(flow.source, flows, columns) + 1);\n columns.set(name, Math.max(0, ...sources));\n }\n return columns.get(name)!;\n}\n\n/**\n * The nodes in the order their names first appear, each sized by the larger\n * of its in and out totals, and colored in that order.\n */\nfunction nodesOf(flows: Flow[]): Node[] {\n const columns = new Map<string, number>();\n return [...new Set(flows.flatMap((flow) => [flow.source, flow.target]))].map((name, i) => ({\n name,\n color: seriesColor(i, ROW_COLORS),\n column: columnOf(name, flows, columns),\n size: Math.max(sum(flows.filter((flow) => flow.target === name)), sum(flows.filter((flow) => flow.source === name))),\n x: 0,\n top: 0,\n height: 0\n }));\n}\n\n/** Sets each node's place: columns spread across the plot, each centred down it, on one scale. */\nfunction place(nodes: Node[]) {\n const count = Math.max(...nodes.map((node) => node.column)) + 1;\n const columns = Array.from({ length: count }, (_, c) => nodes.filter((node) => node.column === c));\n // Gaps take at most half the height, however many nodes a column has.\n const gap = Math.min(NODE_GAP, 50 / Math.max(...columns.map((column) => column.length)));\n const room = (column: Node[]) => 100 - (column.length - 1) * gap;\n const total = (column: Node[]) => column.reduce((height, node) => height + node.size, 0);\n // The tallest column, nodes and gaps, fills the plot.\n const scale = Math.min(...columns.map((column) => room(column) / total(column)));\n columns.forEach((column, c) => {\n let top = (room(column) - total(column) * scale) / 2;\n for (const node of column) {\n Object.assign(node, { x: (c / (count - 1)) * (100 - NODE_WIDTH), top, height: node.size * scale });\n top += node.height + gap;\n }\n });\n return scale;\n}\n\n/** Each flow's link, stacked in table order down its source's outgoing edge and its target's incoming one. */\nfunction linksOf(flows: Flow[], nodes: Node[], scale: number): Link[] {\n const byName = new Map(nodes.map((node) => [node.name, node]));\n const [out, into] = [new Map<Node, number>(), new Map<Node, number>()];\n const next = (used: Map<Node, number>, node: Node, size: number) => {\n const top = node.top + (used.get(node) ?? 0);\n used.set(node, top - node.top + size);\n return top;\n };\n return flows.map((flow) => {\n const [source, target, size] = [byName.get(flow.source)!, byName.get(flow.target)!, flow.value * scale];\n return { flow, source, target, from: next(out, source, size), to: next(into, target, size), size };\n });\n}\n\n/**\n * Sankey chart. Each row of its <table> is a flow: the first cell names the\n * source node, the second the target node, and the third holds the value.\n * Nodes stand in columns, a node with no incoming flow in the first and any\n * other one column past the furthest of its sources, and stack in the order\n * their names first appear. Each link is as thick as its value, and each\n * node as tall as the larger of its in and out totals, on one scale. A row\n * without both names or a positive value, or whose link would close a\n * cycle, draws nothing.\n *\n * Call `update()` after changing the table, or start it with `watch` or\n * `data-watch`.\n */\nexport class SankeyChart extends LineChart {\n // No initializers: LineChart's constructor draws before they would run.\n private _nodes: Node[];\n /** The drawn links, in table order. */\n private _links: Link[];\n /** The links' paths, in the same order. */\n private _paths: SVGPathElement[];\n /** Each drawn shape's path data, by its link's source and target names or its node's name, which update() moves from. */\n private _shapes: Map<string, string>;\n\n protected get _type() {\n return 'sankey-chart';\n }\n\n /** The value column is the one series; the target column is read on its own. */\n protected get _seriesFrom() {\n return 2;\n }\n\n protected get _seriesTo() {\n return 3;\n }\n\n /** The links carry the values, so there is no value axis. */\n protected get _axis() {\n return false;\n }\n\n static key = 'Expressive_SankeyChart';\n\n /** The links the keys and pointer reach. */\n protected get _count() {\n return this._links?.length ?? 0;\n }\n\n /** Highlights one link, numbered in table order among those drawn. Pass -1 to hide the tooltip. */\n show(index: number) {\n if (!this._tooltip || index === this.activeIndex) return;\n this._paths[this.activeIndex]?.classList.remove('active');\n this._paths[index]?.classList.add('active');\n this.activeIndex = index;\n const link = this._links[index];\n this._tooltip.hidden = !link;\n if (link) this._fill(link);\n }\n\n /**\n * Fills the tooltip beside the link's middle: its source and target under\n * their column headers, with their nodes' colors, and the value cell's\n * text, as the author wrote them. Past the middle it opens back over the plot.\n */\n private _fill({ flow, source, target, from, to, size }: Link) {\n const x = this._across((source.x + NODE_WIDTH + target.x) / 2);\n Object.assign(this._tooltip.style, { left: `${x}%`, top: `${(from + to + size) / 2}%` });\n this._tooltip.classList.toggle('end', x > 50);\n const header = this._header.map((cell) => cell.textContent.trim());\n const [sourceName, targetName, value] = [span(header[0]), span(header[1]), span(header[2])];\n sourceName.dataset.series = source.color;\n targetName.dataset.series = target.color;\n value.className = 'value';\n this._tooltip.replaceChildren(sourceName, span(source.name), targetName, span(target.name), value, span(text(this._rows[flow.row], 2)));\n }\n\n /** The link under the pointer, or -1 off every link. By position, since a touch keeps its first target as it drags. */\n protected _indexAt(e: PointerEvent) {\n const hits = (this.el.getRootNode() as Document | ShadowRoot).elementsFromPoint(e.clientX, e.clientY);\n const link = hits.find((hit) => this._paths.includes(hit as SVGPathElement));\n return this._paths.indexOf(link as SVGPathElement);\n }\n\n /**\n * Steps through the links in table order. The arrows keep their meaning\n * in a right-to-left chart, since table order is no direction on screen.\n */\n protected _keyTarget(key: string): number | undefined {\n return linearKey(key, this.activeIndex, this._links.length - 1);\n }\n\n /** Reads the flows and lays out their nodes and links. Without a link to draw, the chart draws nothing. */\n protected _read() {\n super._read();\n const flows = flowsOf(this._rows);\n if (!flows.length) {\n [this.series, this._nodes, this._links] = [[], [], []];\n return;\n }\n this._nodes = nodesOf(flows);\n this._links = linksOf(flows, this._nodes, place(this._nodes));\n }\n\n /** An x position in hundredths of the plot, mirrored in a right-to-left chart. */\n private _across(x: number) {\n return this._reversed ? 100 - x : x;\n }\n\n /** A node as path data: a rectangle. */\n private _nodePath({ x, top, height }: Node) {\n const [start, end] = [this._across(x), this._across(x + NODE_WIDTH)];\n return `M${start},${top}H${end}V${top + height}H${start}Z`;\n }\n\n /** A link as path data: two curves from the source's edge to the target's, closed between them. */\n private _linkPath({ source, target, from, to, size }: Link) {\n const [x0, x1] = [source.x + NODE_WIDTH, target.x];\n const [start, middle, end] = [this._across(x0), this._across((x0 + x1) / 2), this._across(x1)];\n return `M${start},${from}C${middle},${from} ${middle},${to} ${end},${to}`\n + `V${to + size}C${middle},${to + size} ${middle},${from + size} ${start},${from + size}Z`;\n }\n\n /**\n * The links, then the nodes over their ends. Neither has a stroke, so the\n * stretched SVG keeps their sizes. After update(), each shape still in the\n * table moves from where it was: a link found by its source and target\n * names, a node by its name.\n */\n protected _draw(): Element {\n const svg = svgNode('svg', {\n viewBox: '0 0 100 100',\n preserveAspectRatio: 'none',\n 'aria-hidden': 'true',\n focusable: 'false'\n });\n const [was, timing] = [this._shapes ?? new Map<string, string>(), this._before.length ? pace(this.el) : null];\n this._shapes = new Map();\n const shape = (className: string, key: string, color: string, d: string) => {\n const path = svgNode('path', { class: className, 'data-series': color, d }) as SVGPathElement;\n if (timing && was.has(key)) morph(path, was.get(key)!, timing);\n this._shapes.set(key, d);\n return path;\n };\n this._paths = this._links.map((link) =>\n shape('sankey-chart-link', JSON.stringify([link.source.name, link.target.name]), link.source.color, this._linkPath(link)));\n const nodes = this._nodes.map((node) => shape('sankey-chart-node', JSON.stringify(node.name), node.color, this._nodePath(node)));\n svg.append(...this._paths, ...nodes);\n return svg;\n }\n\n /**\n * The node names, over the drawing, each level with its node and toward\n * the plot's middle: after the node, or before it in the last column.\n * They are placed from the inline start, so they need no mirroring.\n */\n protected _axes(): Element[] {\n const names = document.createElement('div');\n names.className = 'sankey-chart-names';\n names.setAttribute('aria-hidden', 'true');\n const last = Math.max(...this._nodes.map((node) => node.column));\n names.append(...this._nodes.map((node) => this._name(node, node.column === last)));\n return [names];\n }\n\n private _name({ name, x, top, height }: Node, last: boolean) {\n const span = document.createElement('span');\n span.className = last ? 'sankey-chart-name end' : 'sankey-chart-name';\n span.textContent = name;\n span.style.setProperty('--sankey-chart-x', `${last ? x : x + NODE_WIDTH}%`);\n span.style.setProperty('--sankey-chart-y', `${top + height / 2}%`);\n return span;\n }\n\n /** No row labels or legend: the nodes carry the names. */\n protected _guides(): Element[] {\n return [];\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|