@leavepulse/ui 0.77.2 → 0.78.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/README.md +68 -0
- package/dist/assets/{LpCommandPalette-DOIZHw-g.css → LpCommandPalette-DDJKICKh.css} +19 -19
- package/dist/assets/{LpDock-Cbh0wQUv.css → LpDock-Dw82tWVD.css} +3 -3
- package/dist/assets/{LpDropzone-B_qRq1-R.css → LpDropzone-DNbh_NFJ.css} +10 -10
- package/dist/assets/{LpImageEditor-XM5bAziW.css → LpImageEditor-Bgu20XLs.css} +6 -6
- package/dist/assets/{LpTable-Bv-EcQs7.css → LpTable-CCk0ZHo7.css} +19 -19
- package/dist/assets/LpTabs-Bh7a-Bdl.css +18 -0
- package/dist/chunks/AppShellContextNav-C6Ho2mof.js +49 -0
- package/dist/chunks/ChartRangeSelector-HO0sMMz6.js +129 -0
- package/dist/chunks/{ContextMenuItems-BXumicbh.js → ContextMenuItems-DmaKSJVv.js} +1 -1
- package/dist/chunks/{DropzoneLinkField-C-9BCGJn.js → DropzoneLinkField-DXIr0eFz.js} +2 -2
- package/dist/chunks/{FieldWrapper-CORPzo9s.js → FieldWrapper-DnuMTrqW.js} +1 -1
- package/dist/chunks/IconCloseButton-COZEsa9u.js +29 -0
- package/dist/chunks/{LayoutCanvas-CNOAUk7D.js → LayoutCanvas-CZKOltfA.js} +1 -1
- package/dist/chunks/{LayoutNode-DF5BMN0J.js → LayoutNode-D2f7v683.js} +45 -45
- package/dist/chunks/{LpActionBar-BP1ld7-S.js → LpActionBar-BGMk5KoG.js} +3 -3
- package/dist/chunks/{LpActivityLine-CJvzrNpj.js → LpActivityLine-Ea-t5Vza.js} +4 -2
- package/dist/chunks/{LpAddressInput-sYMvYzcY.js → LpAddressInput-ZqoZ-N2Y.js} +12 -11
- package/dist/chunks/{LpAlert-n5XPAZfv.js → LpAlert-CjvTZIKF.js} +3 -3
- package/dist/chunks/LpAppShell-BNAVTQsY.js +582 -0
- package/dist/chunks/{LpAutocomplete-DOu7FN5P.js → LpAutocomplete-DkY6CSyD.js} +26 -42
- package/dist/chunks/{LpAvatar-Cg6Az3wz.js → LpAvatar-cQVsNk6F.js} +2 -2
- package/dist/chunks/{LpBadge-wUYLN4U9.js → LpBadge-D5QQdDQ_.js} +2 -2
- package/dist/chunks/{LpBottomNav-CbNQQPuL.js → LpBottomNav-zxLGGbjm.js} +9 -2
- package/dist/chunks/{LpBreadcrumbs-DPdbth-c.js → LpBreadcrumbs-CIIBsygI.js} +4 -3
- package/dist/chunks/{LpButton-CFb44IjC.js → LpButton-DSHioIfD.js} +5 -4
- package/dist/chunks/{LpCalendar-CuoWks-0.js → LpCalendar-D4-LVjfF.js} +1 -1
- package/dist/chunks/{LpCard-r13WRqox.js → LpCard-BPtYXwnT.js} +1 -1
- package/dist/chunks/{LpCheckbox-Cs4SHaHX.js → LpCheckbox-D6RuDW4X.js} +38 -16
- package/dist/chunks/{LpCodeBlock-DRC8VbXW.js → LpCodeBlock-DuzmnIHl.js} +19 -41
- package/dist/chunks/{LpCodeDisplay-CE9TxCA4.js → LpCodeDisplay-CO8fngxa.js} +5 -5
- package/dist/chunks/{LpCollapse-CWS9M_lm.js → LpCollapse-DrAw5DBZ.js} +5 -4
- package/dist/chunks/{LpColorPicker-1y1QJHZR.js → LpColorPicker-BxAHEnR5.js} +11 -12
- package/dist/chunks/{LpCommandScope-CtUhJe8T.js → LpCommandScope-DRUvHiX7.js} +1 -1
- package/dist/chunks/{LpConfirmDialog-DlD45Bi_.js → LpConfirmDialog-6oCIJTDa.js} +3 -3
- package/dist/chunks/{LpConfirmHost-BIWjBLmI.js → LpConfirmHost-DgHvfT6s.js} +1 -1
- package/dist/chunks/{LpContextMenu-rx2tCjwk.js → LpContextMenu--eMGIql6.js} +13 -15
- package/dist/chunks/{LpContextSwitcher-Dwh6dyID.js → LpContextSwitcher-1C1tExdl.js} +2 -2
- package/dist/chunks/{LpCopyButton-xF7wFVoU.js → LpCopyButton-7EOSIuwa.js} +3 -3
- package/dist/chunks/{LpCountdown-DgeY3cLG.js → LpCountdown-DVl7vXI1.js} +4 -3
- package/dist/chunks/{LpDataList-Jxyl9H5w.js → LpDataList-DgBeM01y.js} +13 -4
- package/dist/chunks/{LpDatePicker-CA0QTfBC.js → LpDatePicker-DwSDY0mt.js} +12 -18
- package/dist/chunks/{LpDateRangePicker-u3J51xXk.js → LpDateRangePicker-CNQXdTVv.js} +10 -16
- package/dist/chunks/{LpDisclosure-Cpa7Hc5T.js → LpDisclosure-DG7JCo-d.js} +2 -2
- package/dist/chunks/{LpDrawer-CrG8t_KP.js → LpDrawer-Bt9UUqt_.js} +61 -61
- package/dist/chunks/{LpDropdownMenu-Dl7Z4ZhS.js → LpDropdownMenu-CLzxIOgM.js} +9 -17
- package/dist/chunks/{LpEditable-Cy6GLbFx.js → LpEditable-DVT0Rh8F.js} +9 -6
- package/dist/chunks/{LpEmptyState-EQHiRYhG.js → LpEmptyState-DurPF001.js} +1 -1
- package/dist/chunks/{LpFieldNotice-CzQ2_5rQ.js → LpFieldNotice-DJ10cYIo.js} +1 -1
- package/dist/chunks/LpFileTree-BSx1kBoV.js +735 -0
- package/dist/chunks/{LpFileTreeNode-cT6BIWvz.js → LpFileTreeNode-4dVmFHb3.js} +116 -34
- package/dist/chunks/{LpFormField-Ch69Jd-X.js → LpFormField-BKYn9dyP.js} +3 -3
- package/dist/chunks/{LpFrame-BVQCQLDI.js → LpFrame-Bv5Fphte.js} +25 -11
- package/dist/chunks/{LpHintExample-9Py0wc-L.js → LpHintExample-YzCXiSUp.js} +1 -1
- package/dist/chunks/{LpHintLayer-CgObdUsM.js → LpHintLayer-BeKRsRon.js} +2 -2
- package/dist/chunks/{LpHints-Bz-BlaSl.js → LpHints-qf3xYsza.js} +3 -3
- package/dist/chunks/{LpHoverCard-spGxyw7T.js → LpHoverCard-DanH3Nz1.js} +23 -5
- package/dist/chunks/{LpIcon--5WSb3jJ.js → LpIcon-C6JpQ5td.js} +6 -3
- package/dist/chunks/{LpIdenticon-BzdC_qz9.js → LpIdenticon-Dbbr4fvt.js} +2 -1
- package/dist/chunks/{LpInfraNode-46XOCkfq.js → LpInfraNode-BAU40Km2.js} +2 -2
- package/dist/chunks/{LpInput-Tw-yxT4I.js → LpInput-DL6HEJdi.js} +16 -28
- package/dist/chunks/LpInspector-CuoMAhiw.js +209 -0
- package/dist/chunks/{LpLightbox-B95yu22B.js → LpLightbox-xvpQ64MM.js} +57 -32
- package/dist/chunks/{LpLoader-DVwkOmt9.js → LpLoader-Bf1yZwaU.js} +1 -1
- package/dist/chunks/LpLogInspector-6cNnXqp4.js +119 -0
- package/dist/chunks/{LpLogViewer-ngqkns4m.js → LpLogViewer-Dvb1E9_G.js} +234 -53
- package/dist/chunks/{LpMapPicker-DRGgh89B.js → LpMapPicker-D5_YLLBC.js} +4 -3
- package/dist/chunks/{LpMasonry--k0571qG.js → LpMasonry-DPYekFxs.js} +8 -5
- package/dist/chunks/{LpMediaGallery-Bkram-MO.js → LpMediaGallery-Df-tiWeq.js} +3 -3
- package/dist/chunks/{LpModal-CoGhLTyH.js → LpModal-DrtQ_1A2.js} +11 -13
- package/dist/chunks/{LpModalNav-BGvs2y5Q.js → LpModalNav-DkmGCnZE.js} +11 -37
- package/dist/chunks/{LpNotificationBell-B0034Lk-.js → LpNotificationBell-D_wklO1m.js} +9 -9
- package/dist/chunks/{LpNumberField-e0IBkWU1.js → LpNumberField-CNHsmSDZ.js} +7 -16
- package/dist/chunks/{LpOtpInput-CeBPsM7D.js → LpOtpInput-BRpLBbOD.js} +2 -2
- package/dist/chunks/{LpPagination-BIIiYHXR.js → LpPagination-snQ020xQ.js} +6 -4
- package/dist/chunks/{LpPaletteTheme-DiLYKQiZ.js → LpPaletteTheme-dVtxHx-F.js} +4 -4
- package/dist/chunks/{LpPasswordInput-BkHKQDhM.js → LpPasswordInput-B-zD6tUS.js} +2 -2
- package/dist/chunks/{LpPhoneInput-CETEp5W7.js → LpPhoneInput-BSL7NX4z.js} +15 -26
- package/dist/chunks/{LpPie-DrZepi0p.js → LpPie-9t_guO49.js} +22 -21
- package/dist/chunks/{LpPipeline-B3aOVOkV.js → LpPipeline-rjXvEDRJ.js} +16 -7
- package/dist/chunks/{LpPopover-DmZ3wUtP.js → LpPopover-BQSuxtai.js} +10 -1
- package/dist/chunks/{LpProgress-Yr6ONG5t.js → LpProgress-D_MSjowb.js} +2 -1
- package/dist/chunks/{LpQuota-Dk2MyI2Z.js → LpQuota-CgWPgdVt.js} +1 -1
- package/dist/chunks/{LpRadioGroup-ggaPL92T.js → LpRadioGroup-BrazjLY_.js} +4 -4
- package/dist/chunks/{LpRangeCalendar-CYYUYqJ7.js → LpRangeCalendar-BrqlGZzE.js} +1 -1
- package/dist/chunks/{LpRangeSlider-CM-0ZITZ.js → LpRangeSlider-fz61tzc-.js} +5 -9
- package/dist/chunks/{LpRelativeTime-DwgCb5-8.js → LpRelativeTime-BovUk8MP.js} +1 -1
- package/dist/chunks/{LpRepeater-D7ZmnIYd.js → LpRepeater-BkJHSPI1.js} +3 -3
- package/dist/chunks/{LpRevealOnScroll-DcQjexLy.js → LpRevealOnScroll-CPwyiQAr.js} +1 -1
- package/dist/chunks/{LpScramble-Bn9OoOtC.js → LpScramble-DsE77iVp.js} +1 -1
- package/dist/chunks/{LpScrollArea-MyEnVB_5.js → LpScrollArea-ay4Xo_hg.js} +22 -10
- package/dist/chunks/{LpSecretField-BbmqM9ye.js → LpSecretField-DBvU6iAw.js} +10 -9
- package/dist/chunks/{LpSection-DFK_uoJE.js → LpSection-BfteipxU.js} +1 -1
- package/dist/chunks/{LpSegmented-CeACsMMA.js → LpSegmented-DbEJhbv-.js} +8 -10
- package/dist/chunks/{LpSelect-Cxq4yBGd.js → LpSelect-Y-iuSymW.js} +47 -30
- package/dist/chunks/{LpShaderBackdrop-Bote0iuy.js → LpShaderBackdrop-wQygYb5h.js} +13 -10
- package/dist/chunks/{LpShift-CCq7dofl.js → LpShift-DAgS_d2x.js} +18 -15
- package/dist/chunks/{LpSidebar-DzE1783C.js → LpSidebar-kSkpPh3-.js} +74 -87
- package/dist/chunks/{LpSidebarNav-DE3PhXVP.js → LpSidebarNav-C2mvqrY2.js} +8 -6
- package/dist/chunks/{LpSidebarRow-BRYhNDSo.js → LpSidebarRow-eRP4Q31q.js} +6 -5
- package/dist/chunks/{LpSlider-DxYoCJJO.js → LpSlider-A4ixovgS.js} +5 -9
- package/dist/chunks/{LpSpotlight-4F3NeUMY.js → LpSpotlight-DwxkhFgR.js} +2 -1
- package/dist/chunks/{LpStat-f2LfDCJ4.js → LpStat-pMNZgFcq.js} +2 -2
- package/dist/chunks/{LpStatus-DglxttQ7.js → LpStatus-DGJFwk5F.js} +2 -2
- package/dist/chunks/{LpStepMark-DpzKVyh8.js → LpStepMark-Dw2MRTrt.js} +2 -2
- package/dist/chunks/{LpStepper-DpsocBNJ.js → LpStepper-DNnh7lCu.js} +1 -1
- package/dist/chunks/{LpSwap-C96c0LWh.js → LpSwap-M7nFeW3C.js} +1 -1
- package/dist/chunks/{LpSwitch-BnXd1llc.js → LpSwitch-DnC2-0aV.js} +3 -3
- package/dist/chunks/{LpTabFace-DPCwKkH2.js → LpTabFace-DQoV8mQG.js} +2 -2
- package/dist/chunks/{LpTableFilter-CiVBpaq0.js → LpTableFilter-DgARTsA1.js} +4 -4
- package/dist/chunks/{LpTableOfContents-BN5zvpnx.js → LpTableOfContents-CKkWEK6R.js} +14 -9
- package/dist/chunks/{LpTagsInput-C-mDG648.js → LpTagsInput-Dt0mteSj.js} +19 -27
- package/dist/chunks/{LpTextarea-TE-yZv2U.js → LpTextarea-Co0b9PVx.js} +8 -16
- package/dist/chunks/LpThemeProvider-XK6ZeWAE.js +81 -0
- package/dist/chunks/{LpThemeStudio-BpORDvH6.js → LpThemeStudio-DzYfE-5k.js} +12 -195
- package/dist/chunks/{LpThemeSwitcher-BnEn_mvf.js → LpThemeSwitcher-CFLkdbBL.js} +8 -6
- package/dist/chunks/{LpTimeField-BawSVsmt.js → LpTimeField-DeOcKWJq.js} +6 -9
- package/dist/chunks/{LpToaster-IwTXjbbU.js → LpToaster-QFj0P-5m.js} +10 -8
- package/dist/chunks/{LpTooltip-BcBvIx4z.js → LpTooltip-BJf3lZMq.js} +51 -19
- package/dist/chunks/LpTopologyCanvas-BOHHHZ_6.js +673 -0
- package/dist/chunks/{LpTour-BZq-mUMv.js → LpTour-ClKYhx4h.js} +7 -5
- package/dist/chunks/{LpTruncate-CflAIwiJ.js → LpTruncate-C6u3gjc6.js} +6 -5
- package/dist/chunks/{LpTypewriter-BCL_a6wE.js → LpTypewriter-CZIzpdbe.js} +2 -1
- package/dist/chunks/{LpUptimeBar-DqNvvMBK.js → LpUptimeBar-BnYmR2rj.js} +3 -3
- package/dist/chunks/{LpVideoBackdrop-DS1wGv-X.js → LpVideoBackdrop-Ct4St4ZL.js} +10 -13
- package/dist/chunks/LpWindow-B8YSRVTH.js +297 -0
- package/dist/chunks/LpWorkspaceSwitcher-D0e9upAy.js +139 -0
- package/dist/chunks/{MenuTitle-BmCNNTKH.js → MenuTitle-Bh5dAdV1.js} +1 -1
- package/dist/chunks/{OptionContent-22UT8zLn.js → OptionContent-CGb8QlHA.js} +1 -1
- package/dist/chunks/{PickerField-Bfh8id3d.js → PickerField-BM1dyafh.js} +4 -4
- package/dist/chunks/{RevealToggle-BEit1n6Z.js → RevealToggle-CCPDE8Mv.js} +3 -3
- package/dist/chunks/SliderRail-DhPREa_R.js +18 -0
- package/dist/chunks/{TourCard-DNclH3u_.js → TourCard-DAzTYfav.js} +4 -4
- package/dist/chunks/{icons-DMITlfw5.js → icons-CYfcpSDS.js} +26 -10
- package/dist/component-names.d.ts +1 -1
- package/dist/components/AppShellContextNav.vue.d.ts +13 -0
- package/dist/components/AppShellContextNav.vue.js +4 -0
- package/dist/components/ChartRangeSelector.vue.d.ts +21 -0
- package/dist/components/ChartRangeSelector.vue.js +4 -0
- package/dist/components/ContextMenuItems.vue.js +1 -1
- package/dist/components/DropzoneLinkField.vue.d.ts +2 -2
- package/dist/components/DropzoneLinkField.vue.js +1 -1
- package/dist/components/FieldWrapper.vue.js +1 -1
- package/dist/components/IconCloseButton.vue.d.ts +7 -0
- package/dist/components/IconCloseButton.vue.js +4 -0
- package/dist/components/LayoutCanvas.vue.js +1 -1
- package/dist/components/LayoutNode.vue.js +1 -1
- package/dist/components/LpActionBar.vue.js +1 -1
- package/dist/components/LpActivityLine.vue.js +1 -1
- package/dist/components/LpAddressInput.vue.js +1 -1
- package/dist/components/LpAlert.vue.js +1 -1
- package/dist/components/LpAppShell.vue.d.ts +110 -2
- package/dist/components/LpAppShell.vue.js +1 -1
- package/dist/components/LpAutocomplete.vue.js +1 -1
- package/dist/components/LpAvatar.vue.js +1 -1
- package/dist/components/LpBadge.vue.js +1 -1
- package/dist/components/LpBottomNav.vue.d.ts +5 -0
- package/dist/components/LpBottomNav.vue.js +1 -1
- package/dist/components/LpBreadcrumbs.vue.js +1 -1
- package/dist/components/LpButton.vue.d.ts +14 -2
- package/dist/components/LpButton.vue.js +1 -1
- package/dist/components/LpCalendar.vue.js +1 -1
- package/dist/components/LpCard.vue.js +1 -1
- package/dist/components/LpChart.vue.d.ts +74 -2
- package/dist/components/LpChart.vue.js +326 -85
- package/dist/components/LpCheckbox.vue.d.ts +6 -2
- package/dist/components/LpCheckbox.vue.js +1 -1
- package/dist/components/LpCodeBlock.vue.js +1 -1
- package/dist/components/LpCodeDisplay.vue.js +1 -1
- package/dist/components/LpCollapse.vue.js +1 -1
- package/dist/components/LpColorPicker.vue.js +1 -1
- package/dist/components/LpCommandPalette.vue.d.ts +8 -0
- package/dist/components/LpCommandPalette.vue.js +107 -56
- package/dist/components/LpCommandScope.vue.js +1 -1
- package/dist/components/LpConfirmDialog.vue.js +1 -1
- package/dist/components/LpConfirmHost.vue.js +1 -1
- package/dist/components/LpContextMenu.vue.js +1 -1
- package/dist/components/LpContextSwitcher.vue.js +1 -1
- package/dist/components/LpCopyButton.vue.js +1 -1
- package/dist/components/LpCountdown.vue.js +1 -1
- package/dist/components/LpDataList.vue.d.ts +1 -1
- package/dist/components/LpDataList.vue.js +1 -1
- package/dist/components/LpDatePicker.vue.d.ts +3 -15
- package/dist/components/LpDatePicker.vue.js +1 -1
- package/dist/components/LpDateRangePicker.vue.d.ts +3 -13
- package/dist/components/LpDateRangePicker.vue.js +1 -1
- package/dist/components/LpDisclosure.vue.js +1 -1
- package/dist/components/LpDock.vue.js +21 -18
- package/dist/components/LpDrawer.vue.d.ts +1 -1
- package/dist/components/LpDrawer.vue.js +1 -1
- package/dist/components/LpDropdownMenu.vue.js +1 -1
- package/dist/components/LpDropzone.vue.js +14 -11
- package/dist/components/LpEditable.vue.js +1 -1
- package/dist/components/LpEmptyState.vue.js +1 -1
- package/dist/components/LpFieldNotice.vue.js +1 -1
- package/dist/components/LpFileTree.vue.d.ts +96 -6
- package/dist/components/LpFileTree.vue.js +1 -1
- package/dist/components/LpFileTreeNode.vue.d.ts +48 -0
- package/dist/components/LpFileTreeNode.vue.js +1 -1
- package/dist/components/LpFormField.vue.js +1 -1
- package/dist/components/LpFrame.vue.js +1 -1
- package/dist/components/LpGauge.vue.d.ts +1 -1
- package/dist/components/LpHintExample.vue.js +1 -1
- package/dist/components/LpHintLayer.vue.js +1 -1
- package/dist/components/LpHints.vue.js +1 -1
- package/dist/components/LpHoverCard.vue.js +1 -1
- package/dist/components/LpIcon.vue.d.ts +2 -0
- package/dist/components/LpIcon.vue.js +1 -1
- package/dist/components/LpIdenticon.vue.js +1 -1
- package/dist/components/LpImageEditor.vue.js +7 -6
- package/dist/components/LpInfraNode.vue.js +1 -1
- package/dist/components/LpInput.vue.d.ts +1 -1
- package/dist/components/LpInput.vue.js +1 -1
- package/dist/components/LpInspector.vue.d.ts +87 -0
- package/dist/components/LpInspector.vue.js +4 -0
- package/dist/components/LpLightbox.vue.d.ts +8 -0
- package/dist/components/LpLightbox.vue.js +1 -1
- package/dist/components/LpLoader.vue.d.ts +1 -1
- package/dist/components/LpLoader.vue.js +1 -1
- package/dist/components/LpLogInspector.vue.d.ts +18 -0
- package/dist/components/LpLogInspector.vue.js +4 -0
- package/dist/components/LpLogViewer.vue.d.ts +93 -0
- package/dist/components/LpLogViewer.vue.js +1 -1
- package/dist/components/LpMapPicker.vue.js +1 -1
- package/dist/components/LpMasonry.vue.js +1 -1
- package/dist/components/LpMediaGallery.vue.js +1 -1
- package/dist/components/LpModal.vue.d.ts +4 -2
- package/dist/components/LpModal.vue.js +1 -1
- package/dist/components/LpModalNav.vue.d.ts +5 -5
- package/dist/components/LpModalNav.vue.js +1 -1
- package/dist/components/LpNotificationBell.vue.d.ts +2 -2
- package/dist/components/LpNotificationBell.vue.js +1 -1
- package/dist/components/LpNumberField.vue.js +1 -1
- package/dist/components/LpOtpInput.vue.js +1 -1
- package/dist/components/LpPagination.vue.js +1 -1
- package/dist/components/LpPaletteFacts.vue.js +1 -1
- package/dist/components/LpPaletteHeader.vue.js +2 -2
- package/dist/components/LpPaletteTheme.vue.js +1 -1
- package/dist/components/LpPasswordInput.vue.js +1 -1
- package/dist/components/LpPhoneInput.vue.js +1 -1
- package/dist/components/LpPie.vue.d.ts +2 -2
- package/dist/components/LpPie.vue.js +1 -1
- package/dist/components/LpPipeline.vue.d.ts +4 -0
- package/dist/components/LpPipeline.vue.js +1 -1
- package/dist/components/LpPopover.vue.d.ts +7 -3
- package/dist/components/LpPopover.vue.js +1 -1
- package/dist/components/LpProgress.vue.d.ts +1 -1
- package/dist/components/LpProgress.vue.js +1 -1
- package/dist/components/LpQuota.vue.js +1 -1
- package/dist/components/LpRadioGroup.vue.js +1 -1
- package/dist/components/LpRangeCalendar.vue.js +1 -1
- package/dist/components/LpRangeSlider.vue.js +1 -1
- package/dist/components/LpRelativeTime.vue.js +1 -1
- package/dist/components/LpRepeater.vue.js +1 -1
- package/dist/components/LpRevealOnScroll.vue.js +1 -1
- package/dist/components/LpScramble.vue.js +1 -1
- package/dist/components/LpScrollArea.vue.js +1 -1
- package/dist/components/LpSecretField.vue.js +1 -1
- package/dist/components/LpSection.vue.js +1 -1
- package/dist/components/LpSegmented.vue.js +1 -1
- package/dist/components/LpSelect.vue.js +1 -1
- package/dist/components/LpShaderBackdrop.vue.js +1 -1
- package/dist/components/LpShift.vue.js +1 -1
- package/dist/components/LpShortcutsDialog.vue.js +1 -1
- package/dist/components/LpSidebar.vue.d.ts +1 -1
- package/dist/components/LpSidebar.vue.js +1 -1
- package/dist/components/LpSidebarNav.vue.js +1 -1
- package/dist/components/LpSidebarRow.vue.js +1 -1
- package/dist/components/LpSlider.vue.js +1 -1
- package/dist/components/LpSparkline.vue.d.ts +1 -1
- package/dist/components/LpSpotlight.vue.js +1 -1
- package/dist/components/LpStat.vue.js +1 -1
- package/dist/components/LpStatus.vue.js +1 -1
- package/dist/components/LpStepMark.vue.js +1 -1
- package/dist/components/LpStepper.vue.js +1 -1
- package/dist/components/LpSwap.vue.js +1 -1
- package/dist/components/LpSwitch.vue.js +1 -1
- package/dist/components/LpTabFace.vue.js +1 -1
- package/dist/components/LpTable.vue.d.ts +132 -0
- package/dist/components/LpTable.vue.js +547 -135
- package/dist/components/LpTableFilter.vue.js +1 -1
- package/dist/components/LpTableOfContents.vue.js +1 -1
- package/dist/components/LpTabs.vue.js +6 -5
- package/dist/components/LpTagsInput.vue.js +1 -1
- package/dist/components/LpTextarea.vue.js +1 -1
- package/dist/components/LpThemeProvider.vue.d.ts +2 -0
- package/dist/components/LpThemeProvider.vue.js +1 -1
- package/dist/components/LpThemeStudio.vue.js +1 -1
- package/dist/components/LpThemeSwitcher.vue.js +1 -1
- package/dist/components/LpTimeField.vue.js +1 -1
- package/dist/components/LpToaster.vue.js +1 -1
- package/dist/components/LpTooltip.vue.js +1 -1
- package/dist/components/LpTopologyCanvas.vue.d.ts +131 -5
- package/dist/components/LpTopologyCanvas.vue.js +1 -1
- package/dist/components/LpTour.vue.js +1 -1
- package/dist/components/LpTruncate.vue.js +1 -1
- package/dist/components/LpTypewriter.vue.js +1 -1
- package/dist/components/LpUptimeBar.vue.js +1 -1
- package/dist/components/LpVideoBackdrop.vue.js +1 -1
- package/dist/components/LpWindow.vue.d.ts +99 -0
- package/dist/components/LpWindow.vue.js +4 -0
- package/dist/components/LpWorkspaceSwitcher.vue.d.ts +18 -0
- package/dist/components/LpWorkspaceSwitcher.vue.js +4 -0
- package/dist/components/MenuTitle.vue.js +1 -1
- package/dist/components/OptionContent.vue.js +1 -1
- package/dist/components/PickerField.vue.d.ts +2 -2
- package/dist/components/PickerField.vue.js +1 -1
- package/dist/components/RevealToggle.vue.js +1 -1
- package/dist/components/SliderRail.vue.d.ts +3 -0
- package/dist/components/SliderRail.vue.js +4 -0
- package/dist/components/TourCard.vue.js +1 -1
- package/dist/components/address.js +2 -1
- package/dist/components/appShell.d.ts +36 -0
- package/dist/components/appShell.js +30 -0
- package/dist/components/calendar.d.ts +12 -3
- package/dist/components/calendar.js +2 -5
- package/dist/components/chart.d.ts +21 -0
- package/dist/components/chart.js +4 -3
- package/dist/components/chartWindow.d.ts +57 -0
- package/dist/components/chartWindow.js +136 -0
- package/dist/components/color.js +1 -1
- package/dist/components/commandPalette.d.ts +16 -2
- package/dist/components/commandPalette.js +39 -4
- package/dist/components/controlSize.d.ts +5 -0
- package/dist/components/controlSize.js +8 -0
- package/dist/components/dropdown.d.ts +5 -0
- package/dist/components/dropdown.js +2 -0
- package/dist/components/exportData.d.ts +6 -1
- package/dist/components/exportData.js +25 -18
- package/dist/components/fileTree.d.ts +67 -0
- package/dist/components/fileTree.js +141 -1
- package/dist/components/identicon.js +3 -2
- package/dist/components/logTools.d.ts +93 -0
- package/dist/components/logTools.js +210 -0
- package/dist/components/menuWhen.js +1 -1
- package/dist/components/meter.js +2 -1
- package/dist/components/pipeline.d.ts +2 -0
- package/dist/components/pipeline.js +5 -0
- package/dist/components/relativeTime.js +2 -1
- package/dist/components/reveal.js +2 -1
- package/dist/components/select.d.ts +5 -0
- package/dist/components/select.js +10 -0
- package/dist/components/sidebar.d.ts +1 -0
- package/dist/components/tableFeatures.d.ts +58 -0
- package/dist/components/tableFeatures.js +87 -0
- package/dist/components/topologyGraph.d.ts +164 -0
- package/dist/components/topologyGraph.js +416 -0
- package/dist/components/tour.js +5 -3
- package/dist/components/videoBackdrop.js +7 -6
- package/dist/composables/clamp.d.ts +2 -0
- package/dist/composables/clamp.js +4 -0
- package/dist/composables/devWarn.d.ts +3 -0
- package/dist/composables/devWarn.js +14 -0
- package/dist/composables/easing.d.ts +13 -4
- package/dist/composables/easing.js +16 -10
- package/dist/composables/overlayHistory.js +14 -1
- package/dist/composables/pointerDrag.d.ts +15 -0
- package/dist/composables/pointerDrag.js +40 -0
- package/dist/composables/propCheck.d.ts +10 -0
- package/dist/composables/propCheck.js +78 -0
- package/dist/composables/realm.d.ts +6 -0
- package/dist/composables/realm.js +23 -0
- package/dist/composables/scroll.js +4 -2
- package/dist/composables/scrollMemory.d.ts +12 -1
- package/dist/composables/scrollMemory.js +36 -12
- package/dist/composables/spatialNav.js +2 -1
- package/dist/composables/textEntry.d.ts +17 -0
- package/dist/composables/textEntry.js +19 -0
- package/dist/composables/useAsyncTask.d.ts +6 -0
- package/dist/composables/useChartSync.d.ts +5 -0
- package/dist/composables/useChartSync.js +33 -0
- package/dist/composables/useCloseGuard.d.ts +3 -1
- package/dist/composables/useCloseGuard.js +6 -3
- package/dist/composables/useCommands.d.ts +50 -0
- package/dist/composables/useCommands.js +66 -0
- package/dist/composables/useField.d.ts +37 -0
- package/dist/composables/useField.js +27 -2
- package/dist/composables/useFitScale.js +4 -1
- package/dist/composables/useFormDraft.d.ts +13 -2
- package/dist/composables/useFormDraft.js +17 -9
- package/dist/composables/useHintSystem.js +2 -2
- package/dist/composables/useHotkeys.js +11 -32
- package/dist/composables/useInView.js +2 -1
- package/dist/composables/useInputFilter.js +7 -5
- package/dist/composables/useInputMask.js +5 -3
- package/dist/composables/useLinkedView.d.ts +97 -0
- package/dist/composables/useLinkedView.js +139 -0
- package/dist/composables/useOptimisticToggle.d.ts +3 -1
- package/dist/composables/useOptimisticToggle.js +2 -1
- package/dist/composables/useOverlayHistory.d.ts +7 -0
- package/dist/composables/useOverlayHistory.js +16 -2
- package/dist/composables/usePaintSelect.js +18 -14
- package/dist/composables/usePaletteCommands.d.ts +7 -0
- package/dist/composables/usePaletteCommands.js +12 -1
- package/dist/composables/usePersisted.d.ts +10 -0
- package/dist/composables/usePersisted.js +1 -1
- package/dist/composables/usePillTransition.d.ts +2 -2
- package/dist/composables/usePillTransition.js +5 -5
- package/dist/composables/useResizeObserver.js +2 -1
- package/dist/composables/useReveal.js +2 -1
- package/dist/composables/useRovingFocus.d.ts +2 -2
- package/dist/composables/useRovingFocus.js +9 -11
- package/dist/composables/useScramble.js +7 -1
- package/dist/composables/useShift.js +8 -6
- package/dist/composables/useTilt.js +2 -1
- package/dist/composables/useTween.js +9 -5
- package/dist/composables/useView.d.ts +1 -0
- package/dist/composables/useView.js +14 -2
- package/dist/composables/useZoomPan.js +2 -4
- package/dist/composables/windowing.d.ts +40 -0
- package/dist/composables/windowing.js +118 -0
- package/dist/icons-all.js +1 -1
- package/dist/icons.d.ts +4 -0
- package/dist/index.d.ts +30 -5
- package/dist/index.js +310 -264
- package/dist/layout/tree.js +19 -15
- package/dist/layout/useLayout.d.ts +2 -0
- package/dist/layout/useLayout.js +5 -1
- package/dist/layout/useWorkspaces.d.ts +52 -0
- package/dist/layout/useWorkspaces.js +140 -0
- package/dist/{chunks/backdrop-Dkf2vM81.js → theme/backdrop.js} +5 -5
- package/dist/theme/config.js +25 -0
- package/dist/theme/define.js +61 -0
- package/dist/{chunks/palette-Co8tSASo.js → theme/palette.js} +2 -2
- package/dist/theme/presets.js +239 -0
- package/dist/theme/studio.js +134 -0
- package/dist/theme/tokens.js +63 -0
- package/dist/theme/useTheme.d.ts +3 -2
- package/dist/theme/useTheme.js +325 -0
- package/package.json +8 -1
- package/src/component-names.ts +5 -1
- package/src/components/AppShellContextNav.vue +44 -0
- package/src/components/ChartRangeSelector.vue +120 -0
- package/src/components/IconCloseButton.vue +21 -0
- package/src/components/LayoutCanvas.vue +3 -0
- package/src/components/LayoutNode.vue +37 -38
- package/src/components/LpActivityLine.vue +4 -2
- package/src/components/LpAddressInput.vue +3 -3
- package/src/components/LpAppShell.vue +362 -24
- package/src/components/LpAutocomplete.vue +18 -30
- package/src/components/LpBottomNav.vue +9 -1
- package/src/components/LpBreadcrumbs.vue +2 -1
- package/src/components/LpButton.vue +11 -4
- package/src/components/LpChart.vue +336 -37
- package/src/components/LpCheckbox.vue +43 -9
- package/src/components/LpCodeBlock.vue +17 -23
- package/src/components/LpCollapse.vue +5 -4
- package/src/components/LpColorPicker.vue +8 -9
- package/src/components/LpCommandPalette.vue +133 -50
- package/src/components/LpContextMenu.vue +15 -13
- package/src/components/LpCountdown.vue +2 -1
- package/src/components/LpDataList.vue +13 -1
- package/src/components/LpDatePicker.vue +5 -17
- package/src/components/LpDateRangePicker.vue +5 -16
- package/src/components/LpDock.vue +25 -16
- package/src/components/LpDrawer.vue +70 -61
- package/src/components/LpDropdownMenu.vue +6 -10
- package/src/components/LpDropzone.vue +12 -7
- package/src/components/LpEditable.vue +6 -2
- package/src/components/LpFileTree.vue +507 -66
- package/src/components/LpFileTreeNode.vue +106 -5
- package/src/components/LpFormField.vue +1 -1
- package/src/components/LpFrame.vue +33 -13
- package/src/components/LpHoverCard.vue +30 -5
- package/src/components/LpIcon.vue +6 -2
- package/src/components/LpIdenticon.vue +2 -1
- package/src/components/LpImageEditor.vue +5 -2
- package/src/components/LpInput.vue +15 -23
- package/src/components/LpInspector.vue +197 -0
- package/src/components/LpLightbox.vue +74 -29
- package/src/components/LpLogInspector.vue +85 -0
- package/src/components/LpLogViewer.vue +239 -29
- package/src/components/LpMapPicker.vue +2 -1
- package/src/components/LpMasonry.vue +8 -5
- package/src/components/LpModal.vue +12 -12
- package/src/components/LpModalNav.vue +2 -21
- package/src/components/LpNumberField.vue +6 -15
- package/src/components/LpOtpInput.vue +2 -2
- package/src/components/LpPagination.vue +5 -3
- package/src/components/LpPhoneInput.vue +8 -19
- package/src/components/LpPie.vue +25 -23
- package/src/components/LpPipeline.vue +14 -1
- package/src/components/LpPopover.vue +23 -2
- package/src/components/LpProgress.vue +2 -1
- package/src/components/LpRadioGroup.vue +2 -2
- package/src/components/LpRangeSlider.vue +5 -6
- package/src/components/LpRevealOnScroll.vue +1 -1
- package/src/components/LpScrollArea.vue +28 -11
- package/src/components/LpSecretField.vue +2 -1
- package/src/components/LpSegmented.vue +6 -8
- package/src/components/LpSelect.vue +54 -24
- package/src/components/LpShaderBackdrop.vue +12 -9
- package/src/components/LpShift.vue +18 -15
- package/src/components/LpSidebar.vue +77 -74
- package/src/components/LpSidebarNav.vue +3 -2
- package/src/components/LpSidebarRow.vue +2 -1
- package/src/components/LpSlider.vue +5 -6
- package/src/components/LpSpotlight.vue +2 -1
- package/src/components/LpSwitch.vue +5 -3
- package/src/components/LpTable.vue +609 -93
- package/src/components/LpTableFilter.vue +1 -1
- package/src/components/LpTableOfContents.vue +16 -9
- package/src/components/LpTabs.vue +2 -1
- package/src/components/LpTagsInput.vue +12 -19
- package/src/components/LpTextarea.vue +5 -11
- package/src/components/LpThemeProvider.vue +29 -13
- package/src/components/LpTimeField.vue +4 -7
- package/src/components/LpToaster.vue +7 -6
- package/src/components/LpTooltip.vue +62 -18
- package/src/components/LpTopologyCanvas.vue +567 -42
- package/src/components/LpTour.vue +7 -5
- package/src/components/LpTruncate.vue +4 -3
- package/src/components/LpTypewriter.vue +2 -1
- package/src/components/LpVideoBackdrop.vue +11 -13
- package/src/components/LpWindow.vue +373 -0
- package/src/components/LpWorkspaceSwitcher.vue +116 -0
- package/src/components/PickerField.vue +2 -2
- package/src/components/SliderRail.vue +10 -0
- package/src/components/address.ts +3 -1
- package/src/components/appShell.ts +74 -0
- package/src/components/calendar.ts +12 -5
- package/src/components/chart.ts +27 -3
- package/src/components/chartWindow.ts +198 -0
- package/src/components/color.ts +2 -1
- package/src/components/commandPalette.ts +66 -5
- package/src/components/controlSize.ts +6 -0
- package/src/components/dropdown.ts +3 -0
- package/src/components/exportData.ts +33 -18
- package/src/components/fileTree.ts +215 -0
- package/src/components/identicon.ts +4 -2
- package/src/components/logTools.ts +298 -0
- package/src/components/meter.ts +2 -1
- package/src/components/pipeline.ts +6 -0
- package/src/components/relativeTime.ts +2 -1
- package/src/components/reveal.ts +3 -1
- package/src/components/select.ts +14 -0
- package/src/components/sidebar.ts +1 -0
- package/src/components/tableFeatures.ts +149 -0
- package/src/components/topologyGraph.ts +655 -0
- package/src/components/tour.ts +5 -3
- package/src/components/videoBackdrop.ts +7 -6
- package/src/composables/clamp.ts +2 -0
- package/src/composables/devWarn.ts +19 -0
- package/src/composables/easing.ts +37 -12
- package/src/composables/overlayHistory.ts +24 -0
- package/src/composables/pointerDrag.ts +54 -0
- package/src/composables/propCheck.ts +90 -0
- package/src/composables/realm.ts +25 -0
- package/src/composables/scroll.ts +4 -2
- package/src/composables/scrollMemory.ts +56 -14
- package/src/composables/spatialNav.ts +2 -1
- package/src/composables/textEntry.ts +33 -0
- package/src/composables/useAsyncTask.ts +6 -0
- package/src/composables/useChartSync.ts +52 -0
- package/src/composables/useCloseGuard.ts +22 -10
- package/src/composables/useCommands.ts +123 -0
- package/src/composables/useField.ts +41 -2
- package/src/composables/useFitScale.ts +4 -1
- package/src/composables/useFormDraft.ts +38 -14
- package/src/composables/useHintSystem.ts +2 -2
- package/src/composables/useHotkeys.ts +19 -48
- package/src/composables/useInView.ts +2 -1
- package/src/composables/useInputFilter.ts +8 -5
- package/src/composables/useInputMask.ts +8 -3
- package/src/composables/useLinkedView.ts +222 -0
- package/src/composables/useOptimisticToggle.ts +7 -1
- package/src/composables/useOverlayHistory.ts +20 -0
- package/src/composables/usePaintSelect.ts +20 -14
- package/src/composables/usePaletteCommands.ts +13 -0
- package/src/composables/usePersisted.ts +10 -0
- package/src/composables/usePillTransition.ts +9 -6
- package/src/composables/useResizeObserver.ts +2 -1
- package/src/composables/useReveal.ts +2 -1
- package/src/composables/useRovingFocus.ts +11 -14
- package/src/composables/useScramble.ts +12 -1
- package/src/composables/useShift.ts +8 -6
- package/src/composables/useTilt.ts +2 -1
- package/src/composables/useTween.ts +10 -5
- package/src/composables/useView.ts +17 -3
- package/src/composables/useZoomPan.ts +2 -5
- package/src/composables/windowing.ts +190 -0
- package/src/icons.ts +27 -6
- package/src/index.ts +41 -4
- package/src/kit-icons.ts +1 -1
- package/src/layout/tree.ts +31 -16
- package/src/layout/useLayout.ts +6 -0
- package/src/layout/useWorkspaces.ts +234 -0
- package/src/nuxt.ts +9 -1
- package/src/runtime/propCheck.plugin.ts +10 -0
- package/src/theme/studio.ts +7 -5
- package/src/theme/useTheme.ts +89 -15
- package/src/tokens/tokens.css +8 -1
- package/dist/assets/LpTabs-CJ0rYQbx.css +0 -18
- package/dist/chunks/LpAppShell-Dgejipzz.js +0 -319
- package/dist/chunks/LpFileTree-CooHinsC.js +0 -425
- package/dist/chunks/LpThemeProvider-8MG6yqU9.js +0 -640
- package/dist/chunks/LpTopologyCanvas-B1gIbS0n.js +0 -298
|
@@ -16,10 +16,15 @@ export default { inheritAttrs: false }
|
|
|
16
16
|
* every series at that index at once, so comparing series is one hover, not one
|
|
17
17
|
* hover per line.
|
|
18
18
|
*/
|
|
19
|
+
import { clamp } from "../composables/clamp"
|
|
19
20
|
import { Motion } from "motion-v"
|
|
20
|
-
import { computed, ref, shallowRef, watch, onMounted } from "vue"
|
|
21
|
+
import { computed, nextTick, ref, shallowRef, useId, watch, onMounted } from "vue"
|
|
22
|
+
import { useChartSync } from "../composables/useChartSync"
|
|
21
23
|
import { useLabels } from "../composables/useLpConfig"
|
|
22
|
-
import { easeTravel
|
|
24
|
+
import { easeTravel } from "../composables/easing"
|
|
25
|
+
import { usePrefersReducedMotion } from "../composables/useReducedMotion"
|
|
26
|
+
import { startPointerDrag } from "../composables/pointerDrag"
|
|
27
|
+
import { nodeWindow } from "../composables/useView"
|
|
23
28
|
import { usePillTransition } from "../composables/usePillTransition"
|
|
24
29
|
import { useReveal } from "../composables/useReveal"
|
|
25
30
|
import { lerp, mixValues, resample, useTween } from "../composables/useTween"
|
|
@@ -44,10 +49,23 @@ import {
|
|
|
44
49
|
xLabelIndices,
|
|
45
50
|
yAt,
|
|
46
51
|
type Box,
|
|
52
|
+
type ChartAnnotation,
|
|
53
|
+
type ChartBand,
|
|
47
54
|
type ChartMarker,
|
|
48
55
|
type ChartSeries,
|
|
49
56
|
type ChartThreshold,
|
|
50
57
|
} from "./chart"
|
|
58
|
+
import ChartRangeSelector from "./ChartRangeSelector.vue"
|
|
59
|
+
import {
|
|
60
|
+
ZOOM_STEP,
|
|
61
|
+
chartView,
|
|
62
|
+
clampRange,
|
|
63
|
+
slotOf,
|
|
64
|
+
sourceOf,
|
|
65
|
+
zoomRange,
|
|
66
|
+
type ChartDownsample,
|
|
67
|
+
type ChartRange,
|
|
68
|
+
} from "./chartWindow"
|
|
51
69
|
import { PANEL_SURFACE } from "./dropdown"
|
|
52
70
|
import LegendSwatch from "./LegendSwatch.vue"
|
|
53
71
|
import LpContextMenu, { type ContextMenuItemDef } from "./LpContextMenu.vue"
|
|
@@ -72,6 +90,12 @@ export interface ChartText {
|
|
|
72
90
|
point: string
|
|
73
91
|
/** Header of the label column in a CSV export. */
|
|
74
92
|
xColumn: string
|
|
93
|
+
/** Name of the overview's left edge, for assistive tech. */
|
|
94
|
+
rangeStart: string
|
|
95
|
+
/** Name of the overview's right edge. */
|
|
96
|
+
rangeEnd: string
|
|
97
|
+
/** The button that shows the whole series again. */
|
|
98
|
+
resetZoom: string
|
|
75
99
|
}
|
|
76
100
|
|
|
77
101
|
export interface ChartExportOptions {
|
|
@@ -151,6 +175,36 @@ const props = withDefaults(
|
|
|
151
175
|
thresholds?: ChartThreshold[]
|
|
152
176
|
/** Vertical markers at x positions (deploys, incidents). */
|
|
153
177
|
markers?: ChartMarker[]
|
|
178
|
+
/** Stretches of the x axis, drawn under the data (maintenance, incidents). */
|
|
179
|
+
bands?: ChartBand[]
|
|
180
|
+
/** Notes pinned to single readings. */
|
|
181
|
+
annotations?: ChartAnnotation[]
|
|
182
|
+
/**
|
|
183
|
+
* The window of the data on show, by point index (`v-model:range`). Unset
|
|
184
|
+
* and null are the whole series. Exports and `dataTable` always hold all of it.
|
|
185
|
+
*/
|
|
186
|
+
range?: ChartRange | null
|
|
187
|
+
/** The overview under the plot, for moving and resizing the window. */
|
|
188
|
+
rangeSelector?: boolean
|
|
189
|
+
/**
|
|
190
|
+
* Zoom on the plot: drag across it, Ctrl+wheel or pinch, the + and - keys.
|
|
191
|
+
* Double click, 0 or the reset button show the whole series.
|
|
192
|
+
*/
|
|
193
|
+
zoomable?: boolean
|
|
194
|
+
/**
|
|
195
|
+
* Thin a series longer than the plot is wide, for line and area charts.
|
|
196
|
+
* `minmax` keeps each bucket's extremes, so a one-point spike survives;
|
|
197
|
+
* `lttb` keeps the shape of a smooth curve and can lose one. Off by default.
|
|
198
|
+
* Curves are drawn straight while thinned: `smooth` would overshoot.
|
|
199
|
+
*/
|
|
200
|
+
downsample?: ChartDownsample | false
|
|
201
|
+
/** Points to thin to. Defaults to one a pixel of the chart's width. */
|
|
202
|
+
maxPoints?: number
|
|
203
|
+
/**
|
|
204
|
+
* Charts of one group mark the same x label on hover. Matched by label, so
|
|
205
|
+
* they may hold different windows of the same timeline.
|
|
206
|
+
*/
|
|
207
|
+
syncGroup?: string
|
|
154
208
|
/** Accessible name for the plot. Defaults to a generated summary. */
|
|
155
209
|
ariaLabel?: string
|
|
156
210
|
/** Render the data as a visually hidden table for screen readers. */
|
|
@@ -178,6 +232,9 @@ const props = withDefaults(
|
|
|
178
232
|
animate: true,
|
|
179
233
|
thresholds: () => [],
|
|
180
234
|
markers: () => [],
|
|
235
|
+
bands: () => [],
|
|
236
|
+
annotations: () => [],
|
|
237
|
+
range: undefined,
|
|
181
238
|
dataTable: false,
|
|
182
239
|
sample: true,
|
|
183
240
|
},
|
|
@@ -185,7 +242,16 @@ const props = withDefaults(
|
|
|
185
242
|
|
|
186
243
|
const strings = useLabels<ChartText>(
|
|
187
244
|
"chart",
|
|
188
|
-
{
|
|
245
|
+
{
|
|
246
|
+
empty: "No data",
|
|
247
|
+
loading: "Loading",
|
|
248
|
+
rightAxis: "Measured on the right axis",
|
|
249
|
+
point: "Point",
|
|
250
|
+
xColumn: "Label",
|
|
251
|
+
rangeStart: "Start of the range",
|
|
252
|
+
rangeEnd: "End of the range",
|
|
253
|
+
resetZoom: "Show all",
|
|
254
|
+
},
|
|
189
255
|
() => props.text,
|
|
190
256
|
)
|
|
191
257
|
|
|
@@ -194,6 +260,8 @@ const emit = defineEmits<{
|
|
|
194
260
|
(e: "pointClick", payload: ChartPointEvent): void
|
|
195
261
|
/** Right-click on a point/bar, fired before `menuItems` is consulted. */
|
|
196
262
|
(e: "pointContextMenu", payload: ChartPointEvent): void
|
|
263
|
+
/** The window moved; null is the whole series. */
|
|
264
|
+
(e: "update:range", range: ChartRange | null): void
|
|
197
265
|
}>()
|
|
198
266
|
|
|
199
267
|
// ── size ───────────────────────────────────────
|
|
@@ -211,7 +279,7 @@ const width = ref(0)
|
|
|
211
279
|
*/
|
|
212
280
|
const { el: revealAnchor, revealed } = useReveal({ immediate: () => !props.animate })
|
|
213
281
|
// SMIL ignores the reduced-motion media query, so the wipe is skipped here.
|
|
214
|
-
const reduced =
|
|
282
|
+
const reduced = usePrefersReducedMotion()
|
|
215
283
|
const still = computed(() => !props.animate || reduced.value)
|
|
216
284
|
const drawing = computed(() => !still.value && revealed.value)
|
|
217
285
|
|
|
@@ -219,7 +287,6 @@ onMounted(() => {
|
|
|
219
287
|
// One element, two observers: hand the composable the same node rather than
|
|
220
288
|
// wrapping the chart in a spare div just to carry a second ref.
|
|
221
289
|
revealAnchor.value = root.value
|
|
222
|
-
reduced.value = prefersReducedMotion()
|
|
223
290
|
})
|
|
224
291
|
useResizeObserver(root, (entry, el) => (width.value = entry ? entry.contentRect.width : el.clientWidth), {
|
|
225
292
|
immediate: true,
|
|
@@ -233,7 +300,7 @@ const toggleSeries = (id: string) => {
|
|
|
233
300
|
if (next.has(id)) next.delete(id)
|
|
234
301
|
else next.add(id)
|
|
235
302
|
// Never hide the last visible series — an empty plot reads as broken.
|
|
236
|
-
if (
|
|
303
|
+
if (allSeries.value.some((s) => !next.has(s.id))) hidden.value = next
|
|
237
304
|
}
|
|
238
305
|
|
|
239
306
|
const SAMPLE_POINTS = 12
|
|
@@ -251,24 +318,78 @@ const source = computed<ChartSeries[]>(() => {
|
|
|
251
318
|
})
|
|
252
319
|
|
|
253
320
|
// Identity is position plus name, so two series sharing a name stay separate.
|
|
254
|
-
const
|
|
321
|
+
const fullSeries = computed(() =>
|
|
255
322
|
normalise(source.value).map((s, i) => ({ ...s, id: `${i}:${s.name}` })),
|
|
256
323
|
)
|
|
324
|
+
const fullCount = computed(() => pointCount(fullSeries.value))
|
|
325
|
+
const fullLabels = computed(() => resolveLabels(source.value, props.labels, fullCount.value))
|
|
326
|
+
|
|
327
|
+
/*
|
|
328
|
+
* The window and the thinning sit between the data and everything drawn. Past
|
|
329
|
+
* this point a mark's index is a slot of `view`; `sourceOf` and `slotOf` cross
|
|
330
|
+
* back to the data. Slots follow the chart's own width and not the plot's: the
|
|
331
|
+
* plot's gutters come from the scale, which comes from these very values.
|
|
332
|
+
*/
|
|
333
|
+
const ownRange = shallowRef<ChartRange | null>(null)
|
|
334
|
+
const range = computed(() => clampRange(props.range === undefined ? ownRange.value : props.range, fullCount.value))
|
|
335
|
+
|
|
336
|
+
const view = computed(() =>
|
|
337
|
+
chartView(
|
|
338
|
+
fullSeries.value.map((s) => s.values),
|
|
339
|
+
fullCount.value,
|
|
340
|
+
range.value,
|
|
341
|
+
props.type === "bar" ? false : props.downsample,
|
|
342
|
+
props.maxPoints ?? Math.floor(width.value),
|
|
343
|
+
),
|
|
344
|
+
)
|
|
345
|
+
const narrowed = computed(() => range.value !== null || view.value.indices !== null)
|
|
346
|
+
|
|
347
|
+
/* What the chart works from: the same objects as the data when nothing narrows it. */
|
|
348
|
+
const allSeries = computed(() =>
|
|
349
|
+
narrowed.value ? fullSeries.value.map((s, i) => ({ ...s, values: view.value.values[i] })) : fullSeries.value,
|
|
350
|
+
)
|
|
351
|
+
|
|
352
|
+
function setRange(next: ChartRange | null) {
|
|
353
|
+
ownRange.value = next
|
|
354
|
+
emit("update:range", next)
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/*
|
|
358
|
+
* A zoom follows the hand, so it lands at once: easing would slide the curve
|
|
359
|
+
* under the pointer. The flag only has to cover the watchers of this flush.
|
|
360
|
+
*/
|
|
361
|
+
let rangeMoving = false
|
|
362
|
+
watch(
|
|
363
|
+
() => `${range.value?.start}:${range.value?.end}`,
|
|
364
|
+
() => {
|
|
365
|
+
rangeMoving = true
|
|
366
|
+
void nextTick(() => (rangeMoving = false))
|
|
367
|
+
},
|
|
368
|
+
{ flush: "sync" },
|
|
369
|
+
)
|
|
257
370
|
const visible = computed(() => allSeries.value.filter((s) => !hidden.value.has(s.id)))
|
|
258
371
|
|
|
259
372
|
// A series asked to start hidden is hidden once, when it first appears: the
|
|
260
373
|
// legend owns it from then on, and a data refresh must not switch it back off.
|
|
374
|
+
// That state lives as long as the series does: one that goes away takes it
|
|
375
|
+
// along, so a new series in its place starts from its own `hidden`. An empty
|
|
376
|
+
// list is data still on its way, not every series removed.
|
|
261
377
|
const seeded = new Set<string>()
|
|
262
378
|
watch(
|
|
263
379
|
() => props.series.map((s, i) => [`${i}:${s.name}`, !!s.hidden] as const),
|
|
264
380
|
(entries) => {
|
|
265
|
-
|
|
381
|
+
if (!entries.length) return
|
|
382
|
+
const ids = new Set<string>(entries.map(([id]) => id))
|
|
383
|
+
for (const id of seeded) if (!ids.has(id)) seeded.delete(id)
|
|
384
|
+
const kept = [...hidden.value].filter((id) => ids.has(id))
|
|
385
|
+
const next = new Set(kept)
|
|
266
386
|
for (const [id, off] of entries) {
|
|
267
387
|
if (seeded.has(id)) continue
|
|
268
388
|
seeded.add(id)
|
|
269
|
-
if (off)
|
|
389
|
+
if (off) next.add(id)
|
|
270
390
|
}
|
|
271
|
-
|
|
391
|
+
const allowed = next.size < entries.length ? next : new Set(kept)
|
|
392
|
+
if (allowed.size !== hidden.value.size || [...allowed].some((id) => !hidden.value.has(id))) hidden.value = allowed
|
|
272
393
|
},
|
|
273
394
|
{ immediate: true },
|
|
274
395
|
)
|
|
@@ -302,7 +423,7 @@ const SETTLE_MS = 260
|
|
|
302
423
|
const settle = {
|
|
303
424
|
duration: SETTLE_MS,
|
|
304
425
|
ease: easeTravel,
|
|
305
|
-
enabled: () => props.animate,
|
|
426
|
+
enabled: () => props.animate && !rangeMoving,
|
|
306
427
|
}
|
|
307
428
|
|
|
308
429
|
/*
|
|
@@ -386,7 +507,7 @@ const drawnSeries = useTween(() => targetDrawn.value, mixDrawn, {
|
|
|
386
507
|
* itself in on its own entrance — a morph from readings nobody saw would
|
|
387
508
|
* only muddy it.
|
|
388
509
|
*/
|
|
389
|
-
enabled: () => props.animate && revealed.value && !!svgEl.value,
|
|
510
|
+
enabled: () => props.animate && !rangeMoving && revealed.value && !!svgEl.value,
|
|
390
511
|
})
|
|
391
512
|
|
|
392
513
|
/** The drawn copy of each current series, by id, for marks built from `visible`. */
|
|
@@ -397,11 +518,16 @@ const drawnById = computed(() => {
|
|
|
397
518
|
})
|
|
398
519
|
|
|
399
520
|
const count = computed(() => pointCount(allSeries.value))
|
|
400
|
-
const labels = computed(() =>
|
|
521
|
+
const labels = computed(() =>
|
|
522
|
+
narrowed.value
|
|
523
|
+
? Array.from({ length: count.value }, (_, slot) => fullLabels.value[sourceOf(view.value, slot)] ?? "")
|
|
524
|
+
: fullLabels.value,
|
|
525
|
+
)
|
|
401
526
|
const banded = computed(() => props.type === "bar")
|
|
402
527
|
|
|
528
|
+
// The whole data, not the window: a gap zoomed into is a gap, not an empty chart.
|
|
403
529
|
const hasData = computed(() =>
|
|
404
|
-
|
|
530
|
+
fullSeries.value.some((s) => s.values.some((v) => v != null)),
|
|
405
531
|
)
|
|
406
532
|
|
|
407
533
|
/* Data to interact with: present, and not about to be replaced by the load in
|
|
@@ -692,7 +818,7 @@ const xLabels = computed(() =>
|
|
|
692
818
|
// ── marks ──────────────────────────────────────
|
|
693
819
|
const baseY = computed(() =>
|
|
694
820
|
yAt(
|
|
695
|
-
|
|
821
|
+
clamp(0, scale.value.min, scale.value.max),
|
|
696
822
|
scale.value.min,
|
|
697
823
|
scale.value.max,
|
|
698
824
|
box.value,
|
|
@@ -707,19 +833,21 @@ const baseY = computed(() =>
|
|
|
707
833
|
* it falls out of the plot while the remaining series keep their place, which is
|
|
708
834
|
* what "stop showing this one" should look like.
|
|
709
835
|
*/
|
|
836
|
+
const curve = computed(() => (view.value.indices ? 0 : props.smooth))
|
|
837
|
+
|
|
710
838
|
const lines = computed(() =>
|
|
711
839
|
drawnSeries.value.map((s) => {
|
|
712
840
|
const g = geoOf(s)
|
|
713
841
|
// A series leaving the data collapses exactly as one being hidden does.
|
|
714
842
|
const p = presenceOf(s.id) * s.enter
|
|
715
843
|
// Values pulled toward the axis floor, so the curve flattens into it.
|
|
716
|
-
const base =
|
|
844
|
+
const base = clamp(0, g.min, g.max)
|
|
717
845
|
const values = p === 1 ? s.values : s.values.map((v) => (v == null ? null : base + (v - base) * p))
|
|
718
846
|
return {
|
|
719
847
|
...s,
|
|
720
848
|
values,
|
|
721
|
-
d: linePath(values, g,
|
|
722
|
-
fill: props.type === "area" ? areaPath(values, g,
|
|
849
|
+
d: linePath(values, g, curve.value),
|
|
850
|
+
fill: props.type === "area" ? areaPath(values, g, curve.value) : "",
|
|
723
851
|
/* A dashed series is a reference level (a budget, a target), not a
|
|
724
852
|
measurement — dotting it implies readings that aren't there. */
|
|
725
853
|
points: props.showPoints && !s.dashed,
|
|
@@ -782,7 +910,7 @@ const bars = computed(() => {
|
|
|
782
910
|
} else {
|
|
783
911
|
const sc = scaleOf(s)
|
|
784
912
|
const top = yAt(v, sc.min, sc.max, box.value)
|
|
785
|
-
const base = yAt(
|
|
913
|
+
const base = yAt(clamp(0, sc.min, sc.max), sc.min, sc.max, box.value)
|
|
786
914
|
y = Math.min(top, base)
|
|
787
915
|
h = Math.abs(top - base)
|
|
788
916
|
}
|
|
@@ -837,6 +965,42 @@ const bars = computed(() => {
|
|
|
837
965
|
const active = ref(-1)
|
|
838
966
|
const pointer = ref({ x: 0, y: 0 })
|
|
839
967
|
|
|
968
|
+
/* The hover of another chart in the group, as a slot of this one. */
|
|
969
|
+
const { peerLabel, publish } = useChartSync(() => props.syncGroup)
|
|
970
|
+
const labelIndex = computed(() => (props.syncGroup ? new Map(fullLabels.value.map((label, i) => [label, i])) : null))
|
|
971
|
+
const peerSlot = computed(() => {
|
|
972
|
+
const source = peerLabel.value == null ? undefined : labelIndex.value?.get(peerLabel.value)
|
|
973
|
+
return source === undefined ? -1 : slotOf(view.value, source)
|
|
974
|
+
})
|
|
975
|
+
const crosshair = computed(() => (active.value >= 0 ? active.value : peerSlot.value))
|
|
976
|
+
watch(active, (slot) => publish(slot >= 0 ? (labels.value[slot] ?? null) : null))
|
|
977
|
+
|
|
978
|
+
/* Past this many px a press on the plot is a selection, not a click. */
|
|
979
|
+
const SELECT_SLOP = 4
|
|
980
|
+
let swallowClick = false
|
|
981
|
+
const selection = ref<{ from: number; to: number } | null>(null)
|
|
982
|
+
|
|
983
|
+
const onPointerDown = (e: PointerEvent) => {
|
|
984
|
+
if (!props.zoomable || e.button !== 0) return
|
|
985
|
+
const el = e.currentTarget as SVGElement
|
|
986
|
+
const offset = (ev: PointerEvent) => ev.clientX - el.getBoundingClientRect().left
|
|
987
|
+
const pressedAt = offset(e)
|
|
988
|
+
startPointerDrag(e, {
|
|
989
|
+
move(ev) {
|
|
990
|
+
const x = offset(ev)
|
|
991
|
+
if (Math.abs(x - pressedAt) > SELECT_SLOP) selection.value = { from: pressedAt, to: x }
|
|
992
|
+
},
|
|
993
|
+
end(completed) {
|
|
994
|
+
const picked = selection.value
|
|
995
|
+
selection.value = null
|
|
996
|
+
if (!completed || !picked) return
|
|
997
|
+
swallowClick = true
|
|
998
|
+
const ends = [picked.from, picked.to].map((x) => sourceOf(view.value, nearestIndex(x, geo.value)))
|
|
999
|
+
setRange(clampRange({ start: ends[0], end: ends[1] }, fullCount.value))
|
|
1000
|
+
},
|
|
1001
|
+
})
|
|
1002
|
+
}
|
|
1003
|
+
|
|
840
1004
|
const onMove = (e: PointerEvent) => {
|
|
841
1005
|
keyboard.value = false
|
|
842
1006
|
const el = e.currentTarget as SVGElement
|
|
@@ -846,12 +1010,36 @@ const onMove = (e: PointerEvent) => {
|
|
|
846
1010
|
active.value = nearestIndex(x, geo.value)
|
|
847
1011
|
}
|
|
848
1012
|
|
|
1013
|
+
const selectionBox = computed(() => {
|
|
1014
|
+
if (!selection.value) return null
|
|
1015
|
+
const right = box.value.width - box.value.right
|
|
1016
|
+
const [from, to] = [selection.value.from, selection.value.to].map((x) => clamp(x, box.value.left, right))
|
|
1017
|
+
return { x: Math.min(from, to), width: Math.abs(to - from) }
|
|
1018
|
+
})
|
|
1019
|
+
|
|
1020
|
+
function zoomBy(factor: number, anchor: number) {
|
|
1021
|
+
setRange(zoomRange(range.value, fullCount.value, anchor, factor))
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
/* Plain wheel stays the page's: a chart in a dashboard must not trap scrolling. */
|
|
1025
|
+
const onWheel = (e: WheelEvent) => {
|
|
1026
|
+
if (!props.zoomable || !e.ctrlKey || !ready.value) return
|
|
1027
|
+
e.preventDefault()
|
|
1028
|
+
const rect = (e.currentTarget as SVGElement).getBoundingClientRect()
|
|
1029
|
+
const plot = plotWidth(box.value) || 1
|
|
1030
|
+
zoomBy(e.deltaY < 0 ? ZOOM_STEP : 1 / ZOOM_STEP, (e.clientX - rect.left - box.value.left) / plot)
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
const resetZoom = () => {
|
|
1034
|
+
if (range.value) setRange(null)
|
|
1035
|
+
}
|
|
1036
|
+
|
|
849
1037
|
const onLeave = () => {
|
|
850
1038
|
active.value = -1
|
|
851
1039
|
}
|
|
852
1040
|
|
|
853
1041
|
const pointEvent = (originalEvent: MouseEvent): ChartPointEvent => ({
|
|
854
|
-
index: active.value,
|
|
1042
|
+
index: sourceOf(view.value, active.value),
|
|
855
1043
|
label: labels.value[active.value] ?? "",
|
|
856
1044
|
values: allSeries.value.map((s) => s.values[active.value] ?? null),
|
|
857
1045
|
originalEvent,
|
|
@@ -860,6 +1048,10 @@ const pointEvent = (originalEvent: MouseEvent): ChartPointEvent => ({
|
|
|
860
1048
|
/* A tap fires pointerleave before click, which has already cleared the hover,
|
|
861
1049
|
so the index comes from the click itself. */
|
|
862
1050
|
const onClick = (e: MouseEvent) => {
|
|
1051
|
+
if (swallowClick) {
|
|
1052
|
+
swallowClick = false
|
|
1053
|
+
return
|
|
1054
|
+
}
|
|
863
1055
|
const rect = (e.currentTarget as SVGElement).getBoundingClientRect()
|
|
864
1056
|
active.value = nearestIndex(e.clientX - rect.left, geo.value)
|
|
865
1057
|
if (active.value < 0) return
|
|
@@ -891,19 +1083,19 @@ const onContextMenu = (e: MouseEvent) => {
|
|
|
891
1083
|
}
|
|
892
1084
|
|
|
893
1085
|
const activeX = computed(() =>
|
|
894
|
-
|
|
1086
|
+
crosshair.value < 0 ? 0 : xAt(crosshair.value, count.value, box.value, banded.value),
|
|
895
1087
|
)
|
|
896
1088
|
|
|
897
1089
|
/** Dots on the crosshair — one per visible series that has a value here. */
|
|
898
1090
|
const activePoints = computed(() => {
|
|
899
|
-
if (
|
|
1091
|
+
if (crosshair.value < 0) return []
|
|
900
1092
|
return visible.value
|
|
901
|
-
.map((s) => ({ s, v: s.values[
|
|
1093
|
+
.map((s) => ({ s, v: s.values[crosshair.value] }))
|
|
902
1094
|
.filter((r): r is { s: (typeof visible.value)[number]; v: number } => r.v != null)
|
|
903
1095
|
.map(({ s, v }) => {
|
|
904
1096
|
const sc = scaleOf(s)
|
|
905
1097
|
// The dot rides the curve as drawn; the figure is the reading itself.
|
|
906
|
-
const at = drawnById.value.get(s.id)?.values[
|
|
1098
|
+
const at = drawnById.value.get(s.id)?.values[crosshair.value] ?? v
|
|
907
1099
|
return {
|
|
908
1100
|
color: s.color,
|
|
909
1101
|
id: s.id,
|
|
@@ -971,7 +1163,7 @@ watch(
|
|
|
971
1163
|
},
|
|
972
1164
|
)
|
|
973
1165
|
|
|
974
|
-
const clipId = `lp-chart-${
|
|
1166
|
+
const clipId = `lp-chart-${useId()}`
|
|
975
1167
|
|
|
976
1168
|
/*
|
|
977
1169
|
* The gradient id for a series, with the series NAME reduced to id-safe
|
|
@@ -1015,7 +1207,7 @@ const thresholdMarks = computed(() =>
|
|
|
1015
1207
|
|
|
1016
1208
|
const markerMarks = computed(() =>
|
|
1017
1209
|
props.markers.flatMap((m, i) => {
|
|
1018
|
-
const index = markerIndex(m.at,
|
|
1210
|
+
const index = slotOf(view.value, markerIndex(m.at, fullLabels.value, fullCount.value))
|
|
1019
1211
|
if (index < 0 || width.value <= 0) return []
|
|
1020
1212
|
return [
|
|
1021
1213
|
{
|
|
@@ -1028,6 +1220,47 @@ const markerMarks = computed(() =>
|
|
|
1028
1220
|
}),
|
|
1029
1221
|
)
|
|
1030
1222
|
|
|
1223
|
+
/* A source point's x, held to the plot when the window has left it behind. */
|
|
1224
|
+
const xOfSource = (source: number): number => {
|
|
1225
|
+
if (source < view.value.start) return box.value.left
|
|
1226
|
+
if (source > view.value.end) return box.value.width - box.value.right
|
|
1227
|
+
return xAt(slotOf(view.value, source), count.value, box.value, banded.value)
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1230
|
+
const bandMarks = computed(() =>
|
|
1231
|
+
props.bands.flatMap((b, i) => {
|
|
1232
|
+
const ends = [markerIndex(b.from, fullLabels.value, fullCount.value), markerIndex(b.to, fullLabels.value, fullCount.value)]
|
|
1233
|
+
if (ends.some((end) => end < 0) || width.value <= 0) return []
|
|
1234
|
+
const from = Math.min(...ends)
|
|
1235
|
+
const to = Math.max(...ends)
|
|
1236
|
+
if (to < view.value.start || from > view.value.end) return []
|
|
1237
|
+
const x = xOfSource(from)
|
|
1238
|
+
return [{ key: i, x, width: xOfSource(to) - x, label: b.label, color: b.color ?? "var(--color-line-strong)" }]
|
|
1239
|
+
}),
|
|
1240
|
+
)
|
|
1241
|
+
|
|
1242
|
+
const annotationMarks = computed(() =>
|
|
1243
|
+
props.annotations.flatMap((a, i) => {
|
|
1244
|
+
const source = markerIndex(a.at, fullLabels.value, fullCount.value)
|
|
1245
|
+
const slot = slotOf(view.value, source)
|
|
1246
|
+
const lead = fullSeries.value.find((s) => !hidden.value.has(s.id) && s.values[source] != null)
|
|
1247
|
+
const value = a.value ?? lead?.values[source]
|
|
1248
|
+
if (slot < 0 || value == null || width.value <= 0) return []
|
|
1249
|
+
const sc = (a.value == null ? lead?.axis : a.axis) === "right" && rightScale.value ? rightScale.value : scale.value
|
|
1250
|
+
const x = xAt(slot, count.value, box.value, banded.value)
|
|
1251
|
+
return [
|
|
1252
|
+
{
|
|
1253
|
+
key: i,
|
|
1254
|
+
x,
|
|
1255
|
+
y: yAt(value, sc.min, sc.max, box.value),
|
|
1256
|
+
label: a.label,
|
|
1257
|
+
color: a.color ?? "var(--color-ink)",
|
|
1258
|
+
anchor: x > box.value.width - CARD_W ? ("end" as const) : ("start" as const),
|
|
1259
|
+
},
|
|
1260
|
+
]
|
|
1261
|
+
}),
|
|
1262
|
+
)
|
|
1263
|
+
|
|
1031
1264
|
// ── keyboard & assistive text ──────────────────
|
|
1032
1265
|
const summary = computed(
|
|
1033
1266
|
() => props.ariaLabel ?? chartSummary(visible.value, labels.value, fmtSeries, props.title),
|
|
@@ -1058,11 +1291,23 @@ const onKeydown = (e: KeyboardEvent) => {
|
|
|
1058
1291
|
case " ":
|
|
1059
1292
|
if (active.value < 0) return
|
|
1060
1293
|
e.preventDefault()
|
|
1061
|
-
emit("pointClick", pointEvent(new MouseEvent("click")))
|
|
1294
|
+
emit("pointClick", pointEvent(new (nodeWindow(e.target as Node).MouseEvent)("click")))
|
|
1062
1295
|
return
|
|
1063
1296
|
case "Escape":
|
|
1064
1297
|
active.value = -1
|
|
1065
1298
|
return
|
|
1299
|
+
case "+":
|
|
1300
|
+
case "=":
|
|
1301
|
+
case "-":
|
|
1302
|
+
if (!props.zoomable) return
|
|
1303
|
+
e.preventDefault()
|
|
1304
|
+
zoomBy(e.key === "-" ? 1 / ZOOM_STEP : ZOOM_STEP, active.value < 0 ? 0.5 : active.value / last)
|
|
1305
|
+
return
|
|
1306
|
+
case "0":
|
|
1307
|
+
if (!props.zoomable) return
|
|
1308
|
+
e.preventDefault()
|
|
1309
|
+
resetZoom()
|
|
1310
|
+
return
|
|
1066
1311
|
default:
|
|
1067
1312
|
return
|
|
1068
1313
|
}
|
|
@@ -1095,13 +1340,13 @@ const readout = computed(() =>
|
|
|
1095
1340
|
const svgEl = ref<SVGSVGElement | null>(null)
|
|
1096
1341
|
|
|
1097
1342
|
function exportCsv(options: ChartExportOptions & CsvOptions = {}): string {
|
|
1098
|
-
const rows =
|
|
1343
|
+
const rows = fullLabels.value.map((label, i) => ({ label, i }))
|
|
1099
1344
|
const csv = toCsv(rows, [
|
|
1100
1345
|
{ key: "label", label: strings.value.xColumn },
|
|
1101
|
-
...
|
|
1346
|
+
...fullSeries.value.map((s) => ({ key: s.id, label: s.name, value: (r: { i: number }) => s.values[r.i] })),
|
|
1102
1347
|
], options)
|
|
1103
1348
|
if (options.download !== false) {
|
|
1104
|
-
downloadFile(`${fileStem(options.filename ?? props.title, "chart")}.csv`, csv, "text/csv;charset=utf-8")
|
|
1349
|
+
downloadFile(`${fileStem(options.filename ?? props.title, "chart")}.csv`, csv, "text/csv;charset=utf-8", svgEl.value?.ownerDocument)
|
|
1105
1350
|
}
|
|
1106
1351
|
return csv
|
|
1107
1352
|
}
|
|
@@ -1114,8 +1359,8 @@ function exportCsv(options: ChartExportOptions & CsvOptions = {}): string {
|
|
|
1114
1359
|
*/
|
|
1115
1360
|
async function exportPng(options: ChartExportOptions & { scale?: number; background?: string } = {}): Promise<Blob | null> {
|
|
1116
1361
|
const svg = svgEl.value
|
|
1117
|
-
if (!svg
|
|
1118
|
-
const style = getComputedStyle(root.value ?? svg)
|
|
1362
|
+
if (!svg) return null
|
|
1363
|
+
const style = nodeWindow(svg).getComputedStyle(root.value ?? svg)
|
|
1119
1364
|
const font = style.fontFamily
|
|
1120
1365
|
const ink = style.getPropertyValue("--color-ink").trim() || style.color
|
|
1121
1366
|
const muted = style.getPropertyValue("--color-muted-strong").trim() || style.color
|
|
@@ -1151,7 +1396,7 @@ async function exportPng(options: ChartExportOptions & { scale?: number; backgro
|
|
|
1151
1396
|
return y ? y + 8 : 0
|
|
1152
1397
|
},
|
|
1153
1398
|
})
|
|
1154
|
-
if (options.download !== false) downloadFile(`${fileStem(options.filename ?? props.title, "chart")}.png`, blob)
|
|
1399
|
+
if (options.download !== false) downloadFile(`${fileStem(options.filename ?? props.title, "chart")}.png`, blob, undefined, svgEl.value?.ownerDocument)
|
|
1155
1400
|
return blob
|
|
1156
1401
|
}
|
|
1157
1402
|
|
|
@@ -1295,9 +1540,12 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(
|
|
|
1295
1540
|
:height="height"
|
|
1296
1541
|
class="block overflow-visible touch-none select-none"
|
|
1297
1542
|
aria-hidden="true"
|
|
1543
|
+
@pointerdown="onPointerDown"
|
|
1298
1544
|
@pointermove="onMove"
|
|
1299
1545
|
@pointerleave="onLeave"
|
|
1300
1546
|
@click="onClick"
|
|
1547
|
+
@dblclick="zoomable && resetZoom()"
|
|
1548
|
+
@wheel="onWheel"
|
|
1301
1549
|
@contextmenu="onContextMenu"
|
|
1302
1550
|
>
|
|
1303
1551
|
<defs>
|
|
@@ -1399,6 +1647,12 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(
|
|
|
1399
1647
|
opacity="0.5"
|
|
1400
1648
|
/>
|
|
1401
1649
|
|
|
1650
|
+
<!-- stretches of the x axis sit under the data -->
|
|
1651
|
+
<g v-for="b in bandMarks" :key="`x-band-${b.key}`">
|
|
1652
|
+
<rect :x="b.x" :y="box.top" :width="b.width" :height="plotHeight(box)" :fill="b.color" opacity="0.1" />
|
|
1653
|
+
<text v-if="b.label" :x="b.x + 4" :y="box.top + 9" class="text-[10px]" :fill="b.color">{{ b.label }}</text>
|
|
1654
|
+
</g>
|
|
1655
|
+
|
|
1402
1656
|
<!-- threshold bands sit under the data -->
|
|
1403
1657
|
<rect
|
|
1404
1658
|
v-for="t in thresholdMarks.filter((m) => m.height > 0)"
|
|
@@ -1496,8 +1750,32 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(
|
|
|
1496
1750
|
</text>
|
|
1497
1751
|
</g>
|
|
1498
1752
|
|
|
1753
|
+
<g v-for="a in annotationMarks" :key="`a-${a.key}`">
|
|
1754
|
+
<circle :cx="a.x" :cy="a.y" r="3.5" :fill="a.color" stroke="var(--color-surface)" stroke-width="1.5" />
|
|
1755
|
+
<text
|
|
1756
|
+
:x="a.anchor === 'end' ? a.x - 6 : a.x + 6"
|
|
1757
|
+
:y="a.y - 6"
|
|
1758
|
+
:text-anchor="a.anchor"
|
|
1759
|
+
class="text-[10px]"
|
|
1760
|
+
:fill="a.color"
|
|
1761
|
+
>
|
|
1762
|
+
{{ a.label }}
|
|
1763
|
+
</text>
|
|
1764
|
+
</g>
|
|
1765
|
+
|
|
1766
|
+
<rect
|
|
1767
|
+
v-if="selectionBox"
|
|
1768
|
+
data-lp-chart-selection
|
|
1769
|
+
:x="selectionBox.x"
|
|
1770
|
+
:y="box.top"
|
|
1771
|
+
:width="selectionBox.width"
|
|
1772
|
+
:height="plotHeight(box)"
|
|
1773
|
+
fill="var(--color-brand)"
|
|
1774
|
+
opacity="0.15"
|
|
1775
|
+
/>
|
|
1776
|
+
|
|
1499
1777
|
<!-- crosshair -->
|
|
1500
|
-
<g v-if="
|
|
1778
|
+
<g v-if="crosshair >= 0 && type !== 'bar'">
|
|
1501
1779
|
<line
|
|
1502
1780
|
:x1="activeX"
|
|
1503
1781
|
:x2="activeX"
|
|
@@ -1572,23 +1850,44 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(
|
|
|
1572
1850
|
</LpShift>
|
|
1573
1851
|
</Motion>
|
|
1574
1852
|
|
|
1853
|
+
<button
|
|
1854
|
+
v-if="zoomable && range && ready"
|
|
1855
|
+
type="button"
|
|
1856
|
+
class="absolute right-1 top-1 rounded-inner bg-surface-raised px-2 py-0.5 text-[11px] text-muted-strong outline-none hover:text-ink focus-visible:ring-2 focus-visible:ring-ring"
|
|
1857
|
+
@click="resetZoom"
|
|
1858
|
+
>
|
|
1859
|
+
{{ strings.resetZoom }}
|
|
1860
|
+
</button>
|
|
1861
|
+
|
|
1575
1862
|
<span class="sr-only" aria-live="polite">{{ readout }}</span>
|
|
1576
1863
|
</div>
|
|
1577
1864
|
</LpContextMenu>
|
|
1578
1865
|
|
|
1866
|
+
<ChartRangeSelector
|
|
1867
|
+
v-if="rangeSelector && ready && width > 0"
|
|
1868
|
+
:values="(fullSeries.find((s) => s.values.some((v) => v != null))?.values ?? [])"
|
|
1869
|
+
:count="fullCount"
|
|
1870
|
+
:range="range"
|
|
1871
|
+
:width="width"
|
|
1872
|
+
:labels="fullLabels"
|
|
1873
|
+
:start-label="strings.rangeStart"
|
|
1874
|
+
:end-label="strings.rangeEnd"
|
|
1875
|
+
@change="setRange"
|
|
1876
|
+
/>
|
|
1877
|
+
|
|
1579
1878
|
<div v-if="dataTable && ready" class="sr-only">
|
|
1580
1879
|
<table>
|
|
1581
1880
|
<caption v-if="title">{{ title }}</caption>
|
|
1582
1881
|
<thead>
|
|
1583
1882
|
<tr>
|
|
1584
1883
|
<th scope="col"></th>
|
|
1585
|
-
<th v-for="s in
|
|
1884
|
+
<th v-for="s in fullSeries" :key="s.id" scope="col">{{ s.name }}</th>
|
|
1586
1885
|
</tr>
|
|
1587
1886
|
</thead>
|
|
1588
1887
|
<tbody>
|
|
1589
|
-
<tr v-for="(label, i) in
|
|
1888
|
+
<tr v-for="(label, i) in fullLabels" :key="i">
|
|
1590
1889
|
<th scope="row">{{ label }}</th>
|
|
1591
|
-
<td v-for="s in
|
|
1890
|
+
<td v-for="s in fullSeries" :key="s.id">
|
|
1592
1891
|
{{ s.values[i] == null ? "—" : fmtSeries(s, s.values[i] as number) }}
|
|
1593
1892
|
</td>
|
|
1594
1893
|
</tr>
|