@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
|
@@ -14,6 +14,7 @@ export default { inheritAttrs: false }
|
|
|
14
14
|
* viewport element and re-emits the native scroll event — exactly what tailing
|
|
15
15
|
* needs.
|
|
16
16
|
*/
|
|
17
|
+
import { clamp } from "../composables/clamp"
|
|
17
18
|
import {
|
|
18
19
|
computed,
|
|
19
20
|
nextTick,
|
|
@@ -38,7 +39,27 @@ import LpScrollArea from "./LpScrollArea.vue"
|
|
|
38
39
|
import { useMergedAttrs } from "../composables/useMergedClass"
|
|
39
40
|
import { useLabels } from "../composables/useLpConfig"
|
|
40
41
|
import { useResizeObserver } from "../composables/useResizeObserver"
|
|
42
|
+
import { inTextField } from "../composables/textEntry"
|
|
43
|
+
import { isElement, nodeWindow } from "../composables/useView"
|
|
41
44
|
import { countLevels, matchPositions, ringWindow, stepMatch } from "./logSearch"
|
|
45
|
+
import { downloadFile } from "./exportData"
|
|
46
|
+
import LpLogInspector from "./LpLogInspector.vue"
|
|
47
|
+
import {
|
|
48
|
+
compilePattern,
|
|
49
|
+
exportLines,
|
|
50
|
+
findIds,
|
|
51
|
+
groupRepeats,
|
|
52
|
+
inTimeRange,
|
|
53
|
+
messageParts,
|
|
54
|
+
nearestByTime,
|
|
55
|
+
patternPositions,
|
|
56
|
+
rowSpan,
|
|
57
|
+
termRanges,
|
|
58
|
+
type LogExportFormat,
|
|
59
|
+
type LogId,
|
|
60
|
+
type LogTimeRange,
|
|
61
|
+
type MessagePart,
|
|
62
|
+
} from "./logTools"
|
|
42
63
|
import { TONES, toneLook, type ToneName } from "./tone"
|
|
43
64
|
|
|
44
65
|
export interface LogViewerLabels {
|
|
@@ -66,6 +87,13 @@ export interface LogViewerLabels {
|
|
|
66
87
|
matchCount: string
|
|
67
88
|
noMatches: string
|
|
68
89
|
levels: string
|
|
90
|
+
/** Toggle for reading the search as a regular expression. */
|
|
91
|
+
regex: string
|
|
92
|
+
invalidPattern: string
|
|
93
|
+
sources: string
|
|
94
|
+
groupRepeats: string
|
|
95
|
+
download: string
|
|
96
|
+
copySelection: string
|
|
69
97
|
}
|
|
70
98
|
|
|
71
99
|
export type LogLevel = "trace" | "debug" | "info" | "warn" | "error" | "fatal" | "success"
|
|
@@ -157,6 +185,29 @@ const props = withDefaults(
|
|
|
157
185
|
* not pick them again every time.
|
|
158
186
|
*/
|
|
159
187
|
persist?: string
|
|
188
|
+
/**
|
|
189
|
+
* Adds to the toolbar what reading a busy stream calls for: a regular
|
|
190
|
+
* expression toggle, source chips, folding repeats, and copy and download
|
|
191
|
+
* of the selection. Each is also its own model or prop.
|
|
192
|
+
*/
|
|
193
|
+
tools?: boolean
|
|
194
|
+
/** Only lines inside this span (inclusive). A line with no readable time stays. */
|
|
195
|
+
timeRange?: LogTimeRange
|
|
196
|
+
/**
|
|
197
|
+
* Fold every repeat of a message into its first line with a count, wherever
|
|
198
|
+
* they sit: numbers, ids and hashes are blanked first, so "job 41 failed"
|
|
199
|
+
* and "job 42 failed" count as one. Stronger than `compact`, which keeps
|
|
200
|
+
* chronology by folding runs of the same text only.
|
|
201
|
+
*/
|
|
202
|
+
group?: boolean
|
|
203
|
+
/** Make trace, request, span and correlation ids in a message clickable (`id-click`). */
|
|
204
|
+
linkIds?: boolean
|
|
205
|
+
/** Click selects a line, Shift+click a range (`v-model:selection`, `select`). */
|
|
206
|
+
selectable?: boolean
|
|
207
|
+
/** Show the selected line in an LpLogInspector under the stream. Needs `selectable`. */
|
|
208
|
+
inspector?: boolean
|
|
209
|
+
/** File name for a download, without its extension. */
|
|
210
|
+
fileName?: string
|
|
160
211
|
labels?: Partial<LogViewerLabels>
|
|
161
212
|
}>(),
|
|
162
213
|
{
|
|
@@ -180,12 +231,25 @@ const emit = defineEmits<{
|
|
|
180
231
|
* fires once. The viewer keeps the scroll anchored when the page prepends.
|
|
181
232
|
*/
|
|
182
233
|
(e: "reach-top"): void
|
|
234
|
+
/** A line was selected: the link to whatever else on the page follows it. */
|
|
235
|
+
(e: "select", payload: { line: LogLine; index: number }): void
|
|
236
|
+
/** A correlation id was clicked (`linkIds`). */
|
|
237
|
+
(e: "id-click", payload: { kind: LogId["kind"]; value: string; line: LogLine }): void
|
|
183
238
|
}>()
|
|
184
239
|
|
|
185
240
|
/** The toolbar's search term. Without the toolbar, `highlight` is the term. */
|
|
186
241
|
const query = defineModel<string>("search", { default: "" })
|
|
187
242
|
/** Levels to show. Empty shows every level. */
|
|
188
243
|
const levels = defineModel<LogLevel[]>("levels", { default: () => [] })
|
|
244
|
+
/** Read the search as a regular expression. */
|
|
245
|
+
const regex = defineModel<boolean>("regex", { default: false })
|
|
246
|
+
/** Sources to show. Empty shows every source. */
|
|
247
|
+
const sources = defineModel<string[]>("sources", { default: () => [] })
|
|
248
|
+
/** The selected span as original line numbers, first to last. */
|
|
249
|
+
const selection = defineModel<[number, number] | null>("selection", { default: null })
|
|
250
|
+
/** Fold repeats; the prop sets it, the toolbar's toggle flips it. */
|
|
251
|
+
const grouped = ref(!!props.group)
|
|
252
|
+
watch(() => props.group, (on) => (grouped.value = !!on))
|
|
189
253
|
const storedLevels = usePersisted<string[] | null>(
|
|
190
254
|
() => props.persist && `lp-log-viewer:${props.persist}:levels`,
|
|
191
255
|
null,
|
|
@@ -221,6 +285,12 @@ const text = useLabels<LogViewerLabels>(
|
|
|
221
285
|
matchCount: "{current} / {total}",
|
|
222
286
|
noMatches: "No matches",
|
|
223
287
|
levels: "Levels",
|
|
288
|
+
regex: "Regular expression",
|
|
289
|
+
invalidPattern: "Invalid pattern",
|
|
290
|
+
sources: "Sources",
|
|
291
|
+
groupRepeats: "Group repeats",
|
|
292
|
+
download: "Download",
|
|
293
|
+
copySelection: "Copy selection",
|
|
224
294
|
},
|
|
225
295
|
() => props.labels,
|
|
226
296
|
)
|
|
@@ -354,12 +424,9 @@ function freeze(): boolean {
|
|
|
354
424
|
// page and swallowing it would break them all.
|
|
355
425
|
if (!hovered.value && !focusWithin()) return false
|
|
356
426
|
if (frozen.value) return true
|
|
357
|
-
//
|
|
358
|
-
//
|
|
359
|
-
|
|
360
|
-
// A capped stream is usually one array pushed into in place, which a
|
|
361
|
-
// reference would not hold still; its window is small enough to copy.
|
|
362
|
-
frozenLines.value = props.maxLines ? props.lines.slice(-props.maxLines) : props.lines
|
|
427
|
+
// Copied, whatever the cap: a stream pushed into in place would move under a
|
|
428
|
+
// reference. This runs once per hold, not per keypress or per line.
|
|
429
|
+
frozenLines.value = props.maxLines ? props.lines.slice(-props.maxLines) : props.lines.slice()
|
|
363
430
|
frozen.value = true
|
|
364
431
|
return true
|
|
365
432
|
}
|
|
@@ -382,7 +449,7 @@ const hovered = ref(false)
|
|
|
382
449
|
|
|
383
450
|
function focusWithin() {
|
|
384
451
|
const el = root.value
|
|
385
|
-
return !!el && el.contains(
|
|
452
|
+
return !!el && el.contains(el.ownerDocument.activeElement)
|
|
386
453
|
}
|
|
387
454
|
|
|
388
455
|
// `when` rather than a bare decline: several viewers on one page all bind these
|
|
@@ -401,13 +468,21 @@ function onKeyup(event: KeyboardEvent) {
|
|
|
401
468
|
if (event.key === "Control" || event.key === "Meta") thaw()
|
|
402
469
|
}
|
|
403
470
|
|
|
471
|
+
// Inside an LpFrame the keyup lands in whichever window holds the focus: the
|
|
472
|
+
// frame's, or the page's, which is where a hold over the frame can start.
|
|
473
|
+
let keyWindows: Window[] = []
|
|
404
474
|
onMounted(() => {
|
|
405
|
-
window.
|
|
406
|
-
|
|
475
|
+
keyWindows = [...new Set<Window>([window, root.value ? nodeWindow(root.value) : window])]
|
|
476
|
+
for (const win of keyWindows) {
|
|
477
|
+
win.addEventListener("keyup", onKeyup as EventListener)
|
|
478
|
+
win.addEventListener("blur", thaw)
|
|
479
|
+
}
|
|
407
480
|
})
|
|
408
481
|
onBeforeUnmount(() => {
|
|
409
|
-
|
|
410
|
-
|
|
482
|
+
for (const win of keyWindows) {
|
|
483
|
+
win.removeEventListener("keyup", onKeyup as EventListener)
|
|
484
|
+
win.removeEventListener("blur", thaw)
|
|
485
|
+
}
|
|
411
486
|
})
|
|
412
487
|
|
|
413
488
|
const parsedLines = computed<LogLine[]>(() =>
|
|
@@ -418,13 +493,28 @@ const parsedLines = computed<LogLine[]>(() =>
|
|
|
418
493
|
// truthful when filtering, plus a `count` for compact mode (1 unless folded).
|
|
419
494
|
// With filterMatches + a search term, keep only lines whose message contains it
|
|
420
495
|
// (case-insensitive); otherwise pass everything.
|
|
496
|
+
const compiled = computed(() => (regex.value && term.value ? compilePattern(term.value) : null))
|
|
497
|
+
const pattern = computed(() => compiled.value?.pattern ?? null)
|
|
498
|
+
const patternFailed = computed(() => !!compiled.value?.error)
|
|
499
|
+
|
|
421
500
|
const visibleLines = computed<{ line: LogLine; n: number; count: number }[]>(() => {
|
|
422
501
|
const needle = props.filterMatches ? term.value.toLowerCase() : ""
|
|
502
|
+
const wantedSources = sources.value.length ? new Set(sources.value) : null
|
|
503
|
+
const inRegex = regex.value && !!needle
|
|
423
504
|
const shown = levels.value.length ? new Set<LogLevel>(levels.value) : null
|
|
424
505
|
const filtered = parsedLines.value
|
|
425
506
|
.map((line, n) => ({ line, n }))
|
|
426
507
|
.filter(({ line }) => !shown || shown.has(line.level ?? "info"))
|
|
427
|
-
.filter(({ line }) => !
|
|
508
|
+
.filter(({ line }) => !wantedSources || (line.source !== undefined && wantedSources.has(line.source)))
|
|
509
|
+
.filter(({ line }) => inTimeRange(line.time, props.timeRange))
|
|
510
|
+
.filter(({ line }) => inRegex || !needle || matchPositions([line], needle).length > 0)
|
|
511
|
+
|
|
512
|
+
if (inRegex) {
|
|
513
|
+
const found = pattern.value ? patternPositions(filtered.map((row) => row.line), pattern.value) : []
|
|
514
|
+
const kept = found.map((i) => filtered[i])
|
|
515
|
+
return grouped.value ? groupRepeats(kept) : kept.map((row) => ({ ...row, count: 1 }))
|
|
516
|
+
}
|
|
517
|
+
if (grouped.value) return groupRepeats(filtered)
|
|
428
518
|
|
|
429
519
|
if (!props.compact) return filtered.map((row) => ({ ...row, count: 1 }))
|
|
430
520
|
|
|
@@ -470,6 +560,13 @@ function lineKey(n: number): number {
|
|
|
470
560
|
const LEVEL_ORDER: LogLevel[] = ["trace", "debug", "info", "success", "warn", "error", "fatal"]
|
|
471
561
|
const levelCounts = computed(() => countLevels<LogLevel>(parsedLines.value, "info"))
|
|
472
562
|
const presentLevels = computed(() => LEVEL_ORDER.filter((l) => levelCounts.value.has(l)))
|
|
563
|
+
const presentSources = computed(() => [...new Set(parsedLines.value.flatMap((l) => (l.source ? [l.source] : [])))].sort())
|
|
564
|
+
|
|
565
|
+
function toggleSource(source: string) {
|
|
566
|
+
sources.value = sources.value.includes(source)
|
|
567
|
+
? sources.value.filter((s) => s !== source)
|
|
568
|
+
: [...sources.value, source]
|
|
569
|
+
}
|
|
473
570
|
|
|
474
571
|
function toggleLevel(level: LogLevel) {
|
|
475
572
|
levels.value = levels.value.includes(level)
|
|
@@ -477,7 +574,11 @@ function toggleLevel(level: LogLevel) {
|
|
|
477
574
|
: [...levels.value, level]
|
|
478
575
|
}
|
|
479
576
|
|
|
480
|
-
const matches = computed(() =>
|
|
577
|
+
const matches = computed(() => {
|
|
578
|
+
const rows = visibleLines.value.map((r) => r.line)
|
|
579
|
+
if (!regex.value) return matchPositions(rows, term.value)
|
|
580
|
+
return pattern.value ? patternPositions(rows, pattern.value) : []
|
|
581
|
+
})
|
|
481
582
|
const current = ref(-1)
|
|
482
583
|
const currentRow = computed(() => {
|
|
483
584
|
const pos = matches.value[current.value]
|
|
@@ -492,6 +593,7 @@ watch(matches, (list) => {
|
|
|
492
593
|
|
|
493
594
|
const matchLabel = computed(() => {
|
|
494
595
|
if (!term.value) return ""
|
|
596
|
+
if (patternFailed.value) return text.value.invalidPattern
|
|
495
597
|
const total = matches.value.length
|
|
496
598
|
if (!total) return text.value.noMatches
|
|
497
599
|
return text.value.matchCount
|
|
@@ -542,10 +644,62 @@ useHotkeys(() => [
|
|
|
542
644
|
{ key: "f3", shift: true, allowInInput: true, when: searching, handler: () => step(-1) },
|
|
543
645
|
])
|
|
544
646
|
|
|
647
|
+
// ── selection, export, jump ─────────────────────────────────────────
|
|
648
|
+
let selectAnchor: number | null = null
|
|
649
|
+
|
|
650
|
+
function onRowClick(event: MouseEvent) {
|
|
651
|
+
if (!props.selectable || !isElement(event.target)) return
|
|
652
|
+
// The end of a drag across text is the user copying it, not choosing a line.
|
|
653
|
+
if (nodeWindow(event.target).getSelection()?.isCollapsed === false) return
|
|
654
|
+
if (event.target.closest("button")) return
|
|
655
|
+
const el = event.target.closest<HTMLElement>("[data-log-row]")
|
|
656
|
+
const n = el ? Number(el.dataset.logRow) : Number.NaN
|
|
657
|
+
const line = parsedLines.value[n]
|
|
658
|
+
if (!line) return
|
|
659
|
+
const range = event.shiftKey && selectAnchor !== null
|
|
660
|
+
if (!range) selectAnchor = n
|
|
661
|
+
selection.value = range ? rowSpan(selectAnchor as number, n) : [n, n]
|
|
662
|
+
emit("select", { line, index: n })
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
const isSelected = (n: number) => !!selection.value && n >= selection.value[0] && n <= selection.value[1]
|
|
666
|
+
const selectedLine = computed(() => (selection.value ? parsedLines.value[selection.value[0]] : undefined))
|
|
667
|
+
|
|
668
|
+
// What a selection covers, or everything shown when nothing is selected. Hidden
|
|
669
|
+
// lines inside the span stay out: what is exported is what was on screen.
|
|
670
|
+
function chosenLines(): LogLine[] {
|
|
671
|
+
const span = selection.value
|
|
672
|
+
const rows = visibleLines.value.filter((row) => !span || (row.n >= span[0] && row.n <= span[1]))
|
|
673
|
+
return rows.map((row) => row.line)
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
function copySelection() {
|
|
677
|
+
return copy(exportLines(chosenLines(), "text", lineText))
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
function downloadSelection(format: LogExportFormat = "text") {
|
|
681
|
+
const extension = format === "ndjson" ? "ndjson" : "log"
|
|
682
|
+
downloadFile(`${props.fileName ?? "logs"}.${extension}`, exportLines(chosenLines(), format, lineText), undefined, root.value?.ownerDocument)
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
/** Scrolls to the line closest to `time` and selects it. False when no line has a readable time. */
|
|
686
|
+
function jumpToTime(time: number | string): boolean {
|
|
687
|
+
const position = nearestByTime(visibleLines.value.map((row) => row.line), time)
|
|
688
|
+
if (position < 0) return false
|
|
689
|
+
const { n } = visibleLines.value[position]
|
|
690
|
+
selection.value = [n, n]
|
|
691
|
+
pinned.value = false
|
|
692
|
+
nextTick(() => revealMatch(position))
|
|
693
|
+
return true
|
|
694
|
+
}
|
|
695
|
+
|
|
545
696
|
defineExpose({
|
|
546
697
|
next: () => step(1),
|
|
547
698
|
previous: () => step(-1),
|
|
548
699
|
focusSearch: () => searchEl.value?.focus(),
|
|
700
|
+
jumpToTime,
|
|
701
|
+
copySelection,
|
|
702
|
+
downloadSelection,
|
|
549
703
|
})
|
|
550
704
|
|
|
551
705
|
// True when filtering has emptied an otherwise non-empty stream.
|
|
@@ -642,11 +796,12 @@ function menuFor(line: LogLine, index: number): ContextMenuItemDef[] {
|
|
|
642
796
|
|
|
643
797
|
// Split a message around the (case-insensitive) highlight term so we can wrap
|
|
644
798
|
// matches in <mark> without v-html. Empty/absent term → single plain part.
|
|
645
|
-
|
|
646
|
-
text: string
|
|
647
|
-
hit: boolean
|
|
648
|
-
}
|
|
799
|
+
type Part = MessagePart
|
|
649
800
|
function splitHighlight(message: string): Part[] {
|
|
801
|
+
if (props.linkIds || regex.value) {
|
|
802
|
+
const hits = regex.value ? (pattern.value?.ranges(message) ?? []) : termRanges(message, term.value)
|
|
803
|
+
return messageParts(message, hits, props.linkIds ? findIds(message) : [])
|
|
804
|
+
}
|
|
650
805
|
if (!term.value) return [{ text: message, hit: false }]
|
|
651
806
|
const parts: Part[] = []
|
|
652
807
|
const lower = message.toLowerCase()
|
|
@@ -859,7 +1014,7 @@ function rideToBottom() {
|
|
|
859
1014
|
const ease = tokenEase("ease-emphasized")
|
|
860
1015
|
const started = performance.now()
|
|
861
1016
|
const step = (now: number) => {
|
|
862
|
-
const t =
|
|
1017
|
+
const t = clamp((now - started) / ms, 0, 1)
|
|
863
1018
|
el.scrollTop = from + (end() - from) * ease(t)
|
|
864
1019
|
glide = t < 1 ? requestAnimationFrame(step) : 0
|
|
865
1020
|
}
|
|
@@ -897,27 +1052,31 @@ function onWheel(event: WheelEvent) {
|
|
|
897
1052
|
const UPWARD_KEYS = new Set(["ArrowUp", "PageUp", "Home"])
|
|
898
1053
|
|
|
899
1054
|
function onKeydown(event: KeyboardEvent) {
|
|
900
|
-
|
|
901
|
-
if (!field && UPWARD_KEYS.has(event.key)) leaveTail()
|
|
1055
|
+
if (!inTextField(event.target) && UPWARD_KEYS.has(event.key)) leaveTail()
|
|
902
1056
|
}
|
|
903
1057
|
|
|
1058
|
+
let holdWindow: Window | null = null
|
|
1059
|
+
|
|
904
1060
|
function release() {
|
|
905
1061
|
holding = false
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
1062
|
+
holdWindow?.removeEventListener("pointerup", release)
|
|
1063
|
+
holdWindow?.removeEventListener("pointercancel", release)
|
|
1064
|
+
holdWindow?.removeEventListener("touchend", release)
|
|
1065
|
+
holdWindow = null
|
|
909
1066
|
}
|
|
910
1067
|
|
|
911
1068
|
function hold(event: Event) {
|
|
912
1069
|
// The scroll area's root, so its scrollbar (a sibling of the viewport)
|
|
913
1070
|
// counts, and the toolbar and jump pill above it do not.
|
|
914
1071
|
const area = viewport()?.parentElement
|
|
915
|
-
if (!area || !(event.target
|
|
1072
|
+
if (!area || !isElement(event.target) || !area.contains(event.target)) return
|
|
916
1073
|
stopGlide()
|
|
1074
|
+
release()
|
|
917
1075
|
holding = true
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
1076
|
+
holdWindow = nodeWindow(area)
|
|
1077
|
+
holdWindow.addEventListener("pointerup", release)
|
|
1078
|
+
holdWindow.addEventListener("pointercancel", release)
|
|
1079
|
+
holdWindow.addEventListener("touchend", release)
|
|
921
1080
|
}
|
|
922
1081
|
|
|
923
1082
|
function scrollToBottom() {
|
|
@@ -1141,6 +1300,43 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(() =>
|
|
|
1141
1300
|
<span class="font-normal tabular-nums text-muted">{{ levelCounts.get(level) }}</span>
|
|
1142
1301
|
</button>
|
|
1143
1302
|
</div>
|
|
1303
|
+
<template v-if="tools">
|
|
1304
|
+
<button
|
|
1305
|
+
type="button"
|
|
1306
|
+
class="rounded-xs px-1.5 py-0.5 font-mono text-[11px] outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
1307
|
+
:class="regex ? 'bg-surface-soft text-ink' : 'text-muted hover:text-ink'"
|
|
1308
|
+
:aria-label="text.regex"
|
|
1309
|
+
:aria-pressed="regex"
|
|
1310
|
+
@click="regex = !regex"
|
|
1311
|
+
>.*</button>
|
|
1312
|
+
<button
|
|
1313
|
+
type="button"
|
|
1314
|
+
class="rounded-xs p-1 outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
1315
|
+
:class="grouped ? 'bg-surface-soft text-ink' : 'text-muted hover:text-ink'"
|
|
1316
|
+
:aria-label="text.groupRepeats"
|
|
1317
|
+
:aria-pressed="grouped"
|
|
1318
|
+
@click="grouped = !grouped"
|
|
1319
|
+
>
|
|
1320
|
+
<LpIcon name="lucide:layers" :size="14" />
|
|
1321
|
+
</button>
|
|
1322
|
+
<button type="button" class="rounded-xs p-1 text-muted outline-none hover:text-ink focus-visible:ring-2 focus-visible:ring-ring" :aria-label="text.copySelection" @click="copySelection">
|
|
1323
|
+
<LpIcon name="lucide:copy" :size="14" />
|
|
1324
|
+
</button>
|
|
1325
|
+
<button type="button" class="rounded-xs p-1 text-muted outline-none hover:text-ink focus-visible:ring-2 focus-visible:ring-ring" :aria-label="text.download" @click="downloadSelection()">
|
|
1326
|
+
<LpIcon name="lucide:download" :size="14" />
|
|
1327
|
+
</button>
|
|
1328
|
+
<div v-if="presentSources.length > 1" role="group" :aria-label="text.sources" class="flex flex-wrap items-center gap-1">
|
|
1329
|
+
<button
|
|
1330
|
+
v-for="source in presentSources"
|
|
1331
|
+
:key="source"
|
|
1332
|
+
type="button"
|
|
1333
|
+
class="rounded-pill border px-2 py-0.5 text-[10px] outline-none transition-colors focus-visible:ring-2 focus-visible:ring-ring"
|
|
1334
|
+
:class="sources.includes(source) ? 'border-line-strong bg-surface-soft text-ink' : 'border-line text-muted hover:text-ink'"
|
|
1335
|
+
:aria-pressed="sources.includes(source)"
|
|
1336
|
+
@click="toggleSource(source)"
|
|
1337
|
+
>{{ source }}</button>
|
|
1338
|
+
</div>
|
|
1339
|
+
</template>
|
|
1144
1340
|
</div>
|
|
1145
1341
|
|
|
1146
1342
|
<!-- `instant`: this viewer decides for itself when a jump animates (see
|
|
@@ -1196,6 +1392,7 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(() =>
|
|
|
1196
1392
|
:is="virtualise ? 'ol' : TransitionGroup"
|
|
1197
1393
|
v-bind="virtualise ? {} : transitionProps"
|
|
1198
1394
|
class="py-1"
|
|
1395
|
+
@click="onRowClick"
|
|
1199
1396
|
@contextmenu="onRowContext"
|
|
1200
1397
|
@pointerdown="onRowPointerDown"
|
|
1201
1398
|
>
|
|
@@ -1210,8 +1407,9 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(() =>
|
|
|
1210
1407
|
:key="lineKey(n)"
|
|
1211
1408
|
:data-log-row="n"
|
|
1212
1409
|
class="group relative flex items-start gap-0 px-0 leading-5 transition-colors hover:bg-surface-soft/60"
|
|
1213
|
-
:class="[metaFor(line.level).sel, n === currentRow ? 'bg-accent/15' : '', isFresh(n) ? 'lp-log-row-fresh' : '']"
|
|
1410
|
+
:class="[metaFor(line.level).sel, n === currentRow ? 'bg-accent/15' : '', isFresh(n) ? 'lp-log-row-fresh' : '', isSelected(n) ? 'bg-brand/15' : '']"
|
|
1214
1411
|
:aria-current="n === currentRow ? 'true' : undefined"
|
|
1412
|
+
:data-selected="isSelected(n) ? '' : undefined"
|
|
1215
1413
|
>
|
|
1216
1414
|
<!-- level rail -->
|
|
1217
1415
|
<!-- Level rail: absolutely positioned so it spans the FULL row height
|
|
@@ -1262,8 +1460,14 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(() =>
|
|
|
1262
1460
|
v-for="(part, p) in splitHighlight(virtualise ? line.message.replace(/\r?\n/g, ' ↵ ') : line.message)"
|
|
1263
1461
|
:key="p"
|
|
1264
1462
|
>
|
|
1463
|
+
<button
|
|
1464
|
+
v-if="part.id"
|
|
1465
|
+
type="button"
|
|
1466
|
+
class="rounded-xs text-brand underline outline-none hover:text-ink focus-visible:ring-2 focus-visible:ring-ring"
|
|
1467
|
+
@click="emit('id-click', { kind: part.id.kind, value: part.id.value, line })"
|
|
1468
|
+
>{{ part.text }}</button>
|
|
1265
1469
|
<mark
|
|
1266
|
-
v-if="part.hit"
|
|
1470
|
+
v-else-if="part.hit"
|
|
1267
1471
|
class="rounded-xs bg-accent/30 text-ink"
|
|
1268
1472
|
>{{ part.text }}</mark>
|
|
1269
1473
|
<template v-else>{{ part.text }}</template>
|
|
@@ -1296,6 +1500,12 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(() =>
|
|
|
1296
1500
|
</template>
|
|
1297
1501
|
</LpScrollArea>
|
|
1298
1502
|
|
|
1503
|
+
<LpLogInspector
|
|
1504
|
+
v-if="inspector && selectedLine"
|
|
1505
|
+
:message="selectedLine.message"
|
|
1506
|
+
class="max-h-64 overflow-auto border-t border-line p-3"
|
|
1507
|
+
/>
|
|
1508
|
+
|
|
1299
1509
|
<!-- jump-to-latest: shown only when tailing and scrolled away. The
|
|
1300
1510
|
Transition rides an outer wrapper so its transform/opacity don't fight
|
|
1301
1511
|
the button's own -translate-x-1/2 centring and hover colour transition. -->
|
|
@@ -20,6 +20,7 @@ export default { inheritAttrs: false }
|
|
|
20
20
|
* layer first and swaps the tile pyramid only once the animation lands, which
|
|
21
21
|
* is how the zoom reads as continuous instead of as a hard cut between levels.
|
|
22
22
|
*/
|
|
23
|
+
import { clamp } from "../composables/clamp"
|
|
23
24
|
import { computed, onBeforeUnmount, ref, watch } from "vue"
|
|
24
25
|
import { prefersReducedMotion } from "../composables/easing"
|
|
25
26
|
import { type LatLon, OSM_TILES, type TileSource, project, tileUrl, unproject } from "./address"
|
|
@@ -107,7 +108,7 @@ let zoomTimer: ReturnType<typeof setTimeout> | undefined
|
|
|
107
108
|
let pruneTimer: ReturnType<typeof setTimeout> | undefined
|
|
108
109
|
|
|
109
110
|
function clampZoom(value: number) {
|
|
110
|
-
return Math.round(
|
|
111
|
+
return Math.round(clamp(value, minZoom.value, maxZoom.value))
|
|
111
112
|
}
|
|
112
113
|
|
|
113
114
|
/** World-pixel coordinate of the viewport's top-left corner, at `level`. */
|
|
@@ -26,6 +26,7 @@ export default { inheritAttrs: false }
|
|
|
26
26
|
* DOM order is the items' order, which is also the reading order for
|
|
27
27
|
* keyboard and screen readers.
|
|
28
28
|
*/
|
|
29
|
+
import { isHTMLElement, nodeWindow } from "../composables/useView"
|
|
29
30
|
import { computed, onBeforeUnmount, onMounted, reactive, ref, watch } from "vue"
|
|
30
31
|
import { easingToken, prefersReducedMotion } from "../composables/easing"
|
|
31
32
|
import { useMergedAttrs } from "../composables/useMergedClass"
|
|
@@ -91,7 +92,7 @@ function heightOf(entry: ResizeObserverEntry): number {
|
|
|
91
92
|
|
|
92
93
|
function setItem(key: string | number, el: unknown) {
|
|
93
94
|
const previous = elements.get(key)
|
|
94
|
-
if (el
|
|
95
|
+
if (isHTMLElement(el)) {
|
|
95
96
|
if (previous === el) return
|
|
96
97
|
if (previous) observer?.unobserve(previous)
|
|
97
98
|
elements.set(key, el)
|
|
@@ -108,11 +109,12 @@ function setItem(key: string | number, el: unknown) {
|
|
|
108
109
|
}
|
|
109
110
|
|
|
110
111
|
onMounted(() => {
|
|
111
|
-
|
|
112
|
+
const Observer = root.value ? nodeWindow(root.value).ResizeObserver : undefined
|
|
113
|
+
if (!Observer) {
|
|
112
114
|
width.value = root.value?.clientWidth ?? 0
|
|
113
115
|
return
|
|
114
116
|
}
|
|
115
|
-
observer = new
|
|
117
|
+
observer = new Observer((entries) => {
|
|
116
118
|
for (const entry of entries) {
|
|
117
119
|
if (entry.target === root.value) {
|
|
118
120
|
width.value = entry.contentRect.width
|
|
@@ -195,8 +197,9 @@ const hidden = computed(() => !ready.value || !revealed.value)
|
|
|
195
197
|
watch(
|
|
196
198
|
() => ready.value && revealed.value,
|
|
197
199
|
(go) => {
|
|
198
|
-
|
|
199
|
-
|
|
200
|
+
const box = root.value
|
|
201
|
+
if (!go || !box || !props.entrance || prefersReducedMotion(nodeWindow(box))) return
|
|
202
|
+
const easing = easingToken("ease-emphasized", undefined, box)
|
|
200
203
|
// Stagger by the order items are placed in, which reads top to bottom.
|
|
201
204
|
keys.value.forEach((key, index) => {
|
|
202
205
|
const el = elements.get(key)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { isElement } from "../composables/realm"
|
|
2
3
|
import {
|
|
3
4
|
DialogClose,
|
|
4
5
|
DialogContent,
|
|
@@ -11,7 +12,7 @@ import {
|
|
|
11
12
|
import { computed, onBeforeUnmount, ref, useSlots, watch } from "vue"
|
|
12
13
|
import { useCloseGuard, type CloseGuard } from "../composables/useCloseGuard"
|
|
13
14
|
import { useGlass } from "../composables/useGlass"
|
|
14
|
-
import {
|
|
15
|
+
import { useModelOverlayHistory, type OverlayHistoryMode } from "../composables/useOverlayHistory"
|
|
15
16
|
import { useLabels } from "../composables/useLpConfig"
|
|
16
17
|
import { useShift } from "../composables/useShift"
|
|
17
18
|
import { useModalLayer } from "./modalDepth"
|
|
@@ -65,7 +66,9 @@ const props = withDefaults(
|
|
|
65
66
|
* happens if the DOM order is left to decide.
|
|
66
67
|
*
|
|
67
68
|
* `"none"` leaves reka's own behaviour alone; pass a CSS selector to name
|
|
68
|
-
* the element yourself.
|
|
69
|
+
* the element yourself. A custom control the list cannot recognise (a
|
|
70
|
+
* canvas editor, a composite widget) marks its entry point with
|
|
71
|
+
* `data-lp-autofocus` and a tabindex.
|
|
69
72
|
*/
|
|
70
73
|
autoFocus?: "auto" | "none" | string
|
|
71
74
|
/**
|
|
@@ -129,16 +132,11 @@ function close() {
|
|
|
129
132
|
void onOpenChange(false)
|
|
130
133
|
}
|
|
131
134
|
|
|
132
|
-
|
|
135
|
+
useModelOverlayHistory({
|
|
133
136
|
mode: () => props.history,
|
|
134
137
|
open: () => !!props.open,
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
emit("update:open", false)
|
|
138
|
-
return true
|
|
139
|
-
},
|
|
140
|
-
reopen: () => emit("update:open", true),
|
|
141
|
-
navigated: () => emit("update:open", false),
|
|
138
|
+
setOpen: (open) => emit("update:open", open),
|
|
139
|
+
allowClose,
|
|
142
140
|
})
|
|
143
141
|
defineExpose({ close })
|
|
144
142
|
|
|
@@ -161,7 +159,7 @@ const onInteractOutside = (event: Event) => {
|
|
|
161
159
|
guardOutside(event)
|
|
162
160
|
if (!props.dismissible) return event.preventDefault()
|
|
163
161
|
const target = event.target
|
|
164
|
-
if (target
|
|
162
|
+
if (isElement(target) && target.closest("[data-lp-modal-aside]")) {
|
|
165
163
|
event.preventDefault()
|
|
166
164
|
}
|
|
167
165
|
}
|
|
@@ -233,6 +231,8 @@ const AUTO_FOCUS_ORDER = [
|
|
|
233
231
|
"input:not([type=hidden]):not([disabled]):not([readonly]):not([tabindex='-1'])",
|
|
234
232
|
"textarea:not([disabled]):not([readonly])",
|
|
235
233
|
"select:not([disabled])",
|
|
234
|
+
"[contenteditable]:not([contenteditable='false'])",
|
|
235
|
+
"[role='textbox']",
|
|
236
236
|
"[data-lp-autofocus]",
|
|
237
237
|
"button:not([disabled]):not([data-lp-dialog-close])",
|
|
238
238
|
"[href]",
|
|
@@ -273,7 +273,7 @@ function onOpenAutoFocus(event: Event) {
|
|
|
273
273
|
target.focus()
|
|
274
274
|
// Only once focus really landed: a prevented auto-focus that failed would
|
|
275
275
|
// leave the keyboard on the page behind the dialog.
|
|
276
|
-
if (
|
|
276
|
+
if (target.ownerDocument.activeElement !== target) continue
|
|
277
277
|
event.preventDefault()
|
|
278
278
|
// `focus-visible` is the browser's own heuristic and cannot be forced, so
|
|
279
279
|
// the ring is driven off an attribute the kit owns. Skipped for a control
|
|
@@ -138,6 +138,7 @@ const railPanel = computed(() => [
|
|
|
138
138
|
"rounded-card border border-line p-2 shadow-panel",
|
|
139
139
|
frosted.value ? "lp-glass-overlay" : "bg-surface-raised",
|
|
140
140
|
])
|
|
141
|
+
const railSlot = computed(() => (props.navSide === "end" ? "asideEnd" : "aside"))
|
|
141
142
|
</script>
|
|
142
143
|
|
|
143
144
|
<template>
|
|
@@ -154,27 +155,7 @@ const railPanel = computed(() => [
|
|
|
154
155
|
<!-- The gap sits on a wrapper rather than on LpSidebar itself: LpSidebar
|
|
155
156
|
splits its `class` between its root and the inner `nav`, so a margin
|
|
156
157
|
given to it lands on both. -->
|
|
157
|
-
<template v-if="hasNav
|
|
158
|
-
<div :class="railClass">
|
|
159
|
-
<LpSidebar
|
|
160
|
-
v-model="active"
|
|
161
|
-
v-model:open="navOpen"
|
|
162
|
-
variant="panel"
|
|
163
|
-
:items="items"
|
|
164
|
-
:sections="sections"
|
|
165
|
-
:width="navWidth"
|
|
166
|
-
:searchable="searchable"
|
|
167
|
-
:search-placeholder="searchPlaceholder"
|
|
168
|
-
:loading="loading"
|
|
169
|
-
responsive
|
|
170
|
-
:mobile-breakpoint="mobileBreakpoint"
|
|
171
|
-
:style="railStyle"
|
|
172
|
-
:class="railPanel"
|
|
173
|
-
/>
|
|
174
|
-
</div>
|
|
175
|
-
</template>
|
|
176
|
-
|
|
177
|
-
<template v-if="hasNav && navSide === 'end'" #asideEnd>
|
|
158
|
+
<template v-if="hasNav" #[railSlot]>
|
|
178
159
|
<div :class="railClass">
|
|
179
160
|
<LpSidebar
|
|
180
161
|
v-model="active"
|
|
@@ -6,6 +6,7 @@ export default { inheritAttrs: false }
|
|
|
6
6
|
</script>
|
|
7
7
|
|
|
8
8
|
<script setup lang="ts">
|
|
9
|
+
import { CONTROL_SIZE } from "./controlSize"
|
|
9
10
|
import { usePaletteControl, type PaletteControlOptions } from "../composables/usePaletteCommands"
|
|
10
11
|
// Numeric input with stepper buttons (reka NumberField). Themed via tokens.
|
|
11
12
|
import {
|
|
@@ -14,9 +15,9 @@ import {
|
|
|
14
15
|
NumberFieldInput,
|
|
15
16
|
NumberFieldRoot,
|
|
16
17
|
} from "reka-ui"
|
|
17
|
-
import { computed,
|
|
18
|
+
import { computed, useId } from "vue"
|
|
18
19
|
import LpIcon from "./LpIcon.vue"
|
|
19
|
-
import { focusLeft,
|
|
20
|
+
import { focusLeft, useAttrsField, mergeDescribedBy } from "../composables/useField"
|
|
20
21
|
import { useLabels } from "../composables/useLpConfig"
|
|
21
22
|
import { useMergedClass } from "../composables/useMergedClass"
|
|
22
23
|
|
|
@@ -93,21 +94,11 @@ const text = useLabels<NumberFieldLabels>(
|
|
|
93
94
|
() => props.labels,
|
|
94
95
|
)
|
|
95
96
|
|
|
96
|
-
const SIZE =
|
|
97
|
-
sm: "h-(--size-control-sm) text-xs",
|
|
98
|
-
md: "h-(--size-control-md) text-sm",
|
|
99
|
-
lg: "h-(--size-control-lg) text-sm",
|
|
100
|
-
}
|
|
97
|
+
const SIZE = CONTROL_SIZE
|
|
101
98
|
|
|
102
|
-
const attrs =
|
|
103
|
-
const field = useFieldControl(() => ({
|
|
104
|
-
wrapped: false,
|
|
105
|
-
id: typeof attrs.id === "string" ? attrs.id : undefined,
|
|
106
|
-
invalid: props.invalid,
|
|
107
|
-
disabled: props.disabled,
|
|
108
|
-
}))
|
|
99
|
+
const { attrs, field } = useAttrsField(() => ({ invalid: props.invalid, disabled: props.disabled }))
|
|
109
100
|
const describedBy = computed(
|
|
110
|
-
() => [field.value.describedBy, props.unit ? unitId : undefined
|
|
101
|
+
() => mergeDescribedBy(attrs["aria-describedby"], field.value.describedBy, props.unit ? unitId : undefined),
|
|
111
102
|
)
|
|
112
103
|
|
|
113
104
|
// The frame takes the consumer's class and style, and `name` goes to reka's
|