@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
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import IconCloseButton from "./IconCloseButton.vue"
|
|
3
|
+
import { clamp } from "../composables/clamp"
|
|
4
|
+
import type { DataListItem } from "./LpDataList.vue"
|
|
5
|
+
|
|
6
|
+
export interface InspectorSection {
|
|
7
|
+
/** Stable identity, and the name of its slot: `#section-<key>`. */
|
|
8
|
+
key: string
|
|
9
|
+
title?: string
|
|
10
|
+
/** Facts about the subject. Replaced by the section's slot, which is where editing fields go. */
|
|
11
|
+
items?: DataListItem[]
|
|
12
|
+
/** Folds under its title. Sections without a title cannot fold. */
|
|
13
|
+
collapsible?: boolean
|
|
14
|
+
/** Starts folded, when `collapsible`. */
|
|
15
|
+
collapsed?: boolean
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export default { inheritAttrs: false }
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<script setup lang="ts" generic="T">
|
|
22
|
+
/*
|
|
23
|
+
* The panel beside a table, graph or canvas that shows the selected thing and
|
|
24
|
+
* lets it be edited: one place and one shape for "what is this, and change it".
|
|
25
|
+
*
|
|
26
|
+
* <LpInspector :subject="server" :title="server?.name" :sections="[
|
|
27
|
+
* { key: 'facts', title: 'Overview', items: facts },
|
|
28
|
+
* { key: 'edit', title: 'Settings' },
|
|
29
|
+
* ]" v-model:open="inspecting" resizable persist="servers">
|
|
30
|
+
* <template #section-edit="{ subject }"><LpInput v-model="subject.name" label="Name" /></template>
|
|
31
|
+
* </LpInspector>
|
|
32
|
+
*
|
|
33
|
+
* It sits in the layout, beside what it inspects, so selecting another row
|
|
34
|
+
* while it is open just works: nothing is covered and no focus is taken. On a
|
|
35
|
+
* phone, where there is no beside, put it in an LpDrawer with `closable` off.
|
|
36
|
+
*
|
|
37
|
+
* With nothing selected it stays and says so (`#empty`), so the page around it
|
|
38
|
+
* does not jump at every change of selection.
|
|
39
|
+
*/
|
|
40
|
+
import { computed, onBeforeUnmount, useSlots, watch } from "vue"
|
|
41
|
+
import { startPointerDrag } from "../composables/pointerDrag"
|
|
42
|
+
import { useCloseGuard, type CloseGuard } from "../composables/useCloseGuard"
|
|
43
|
+
import { useLabels } from "../composables/useLpConfig"
|
|
44
|
+
import { useMergedAttrs } from "../composables/useMergedClass"
|
|
45
|
+
import { usePersisted } from "../composables/usePersisted"
|
|
46
|
+
import { CLOSE_ICON } from "./dropdown"
|
|
47
|
+
import LpDataList from "./LpDataList.vue"
|
|
48
|
+
import LpDisclosure from "./LpDisclosure.vue"
|
|
49
|
+
import LpIcon from "./LpIcon.vue"
|
|
50
|
+
import LpScrollArea from "./LpScrollArea.vue"
|
|
51
|
+
|
|
52
|
+
const KEY_STEP = 16
|
|
53
|
+
|
|
54
|
+
const props = withDefaults(
|
|
55
|
+
defineProps<{
|
|
56
|
+
/** The thing inspected, handed to the slots. Empty state when nothing else is given either. */
|
|
57
|
+
subject?: T | null
|
|
58
|
+
title?: string
|
|
59
|
+
subtitle?: string
|
|
60
|
+
sections?: InspectorSection[]
|
|
61
|
+
/** Which side of the content it sits on: the resize grip goes on the other. */
|
|
62
|
+
side?: "left" | "right"
|
|
63
|
+
/** Default width in px. */
|
|
64
|
+
width?: number
|
|
65
|
+
/** Drag the inner edge to resize, or use arrow keys on it. */
|
|
66
|
+
resizable?: boolean
|
|
67
|
+
minWidth?: number
|
|
68
|
+
maxWidth?: number
|
|
69
|
+
/** Remember the dragged width under this key, across visits. */
|
|
70
|
+
persist?: string
|
|
71
|
+
closable?: boolean
|
|
72
|
+
/** Unsaved edits: `true` asks before closing, a function asks the app. */
|
|
73
|
+
guard?: CloseGuard
|
|
74
|
+
labels?: Partial<{ close: string; empty: string; resize: string; region: string }>
|
|
75
|
+
}>(),
|
|
76
|
+
{ side: "right", width: 320, minWidth: 240, maxWidth: 640, closable: true, subject: undefined },
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
const open = defineModel<boolean>("open", { default: true })
|
|
80
|
+
const slots = useSlots()
|
|
81
|
+
const text = useLabels(
|
|
82
|
+
"inspector",
|
|
83
|
+
{ close: "Close", empty: "Nothing selected", resize: "Resize panel", region: "Details" },
|
|
84
|
+
() => props.labels,
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
const saved = usePersisted<number | null>(() => props.resizable && props.persist && `lp-inspector:${props.persist}`, null, {
|
|
88
|
+
validate: (value): value is number | null => value === null || (typeof value === "number" && value > 0),
|
|
89
|
+
})
|
|
90
|
+
// Applied within today's limits; the saved width outlives a change to them.
|
|
91
|
+
const shownWidth = computed(() => clamp(saved.value ?? props.width, props.minWidth, props.maxWidth))
|
|
92
|
+
|
|
93
|
+
const isEmpty = computed(() => props.subject == null && !props.sections?.length && !slots.default)
|
|
94
|
+
|
|
95
|
+
const { allowClose } = useCloseGuard(() => props.guard, () => open.value)
|
|
96
|
+
async function close() {
|
|
97
|
+
if (await allowClose()) open.value = false
|
|
98
|
+
}
|
|
99
|
+
defineExpose({ close })
|
|
100
|
+
|
|
101
|
+
const { class: rootClass, attrs: rest } = useMergedAttrs(() =>
|
|
102
|
+
[
|
|
103
|
+
"relative flex h-full min-h-0 shrink-0 flex-col bg-surface border-line",
|
|
104
|
+
props.side === "right" ? "border-l" : "border-r",
|
|
105
|
+
].join(" "),
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
let stopDrag: (() => void) | null = null
|
|
109
|
+
|
|
110
|
+
function startResize(event: PointerEvent) {
|
|
111
|
+
if (event.button !== 0) return
|
|
112
|
+
const start = shownWidth.value
|
|
113
|
+
const startX = event.clientX
|
|
114
|
+
const sign = props.side === "right" ? -1 : 1
|
|
115
|
+
stopDrag = startPointerDrag(event, {
|
|
116
|
+
move: (ev) => {
|
|
117
|
+
saved.value = clamp(start + (ev.clientX - startX) * sign, props.minWidth, props.maxWidth)
|
|
118
|
+
},
|
|
119
|
+
end: () => (stopDrag = null),
|
|
120
|
+
})
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function onGripKeydown(event: KeyboardEvent) {
|
|
124
|
+
const step = event.key === "ArrowLeft" ? -KEY_STEP : event.key === "ArrowRight" ? KEY_STEP : 0
|
|
125
|
+
if (!step) return
|
|
126
|
+
event.preventDefault()
|
|
127
|
+
const sign = props.side === "right" ? -1 : 1
|
|
128
|
+
saved.value = clamp(shownWidth.value + step * sign, props.minWidth, props.maxWidth)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
watch(open, (isOpen) => {
|
|
132
|
+
if (!isOpen) stopDrag?.()
|
|
133
|
+
})
|
|
134
|
+
onBeforeUnmount(() => stopDrag?.())
|
|
135
|
+
</script>
|
|
136
|
+
|
|
137
|
+
<template>
|
|
138
|
+
<aside
|
|
139
|
+
v-if="open"
|
|
140
|
+
v-bind="rest"
|
|
141
|
+
:class="rootClass"
|
|
142
|
+
:style="{ width: `${shownWidth}px` }"
|
|
143
|
+
:aria-label="title ?? text.region"
|
|
144
|
+
>
|
|
145
|
+
<div
|
|
146
|
+
v-if="resizable"
|
|
147
|
+
role="separator"
|
|
148
|
+
tabindex="0"
|
|
149
|
+
aria-orientation="vertical"
|
|
150
|
+
:aria-label="text.resize"
|
|
151
|
+
:aria-valuenow="shownWidth"
|
|
152
|
+
:aria-valuemin="minWidth"
|
|
153
|
+
:aria-valuemax="maxWidth"
|
|
154
|
+
class="group/resize absolute inset-y-0 z-10 w-1.5 cursor-ew-resize touch-none outline-none"
|
|
155
|
+
:class="side === 'right' ? '-left-px' : '-right-px'"
|
|
156
|
+
@pointerdown="startResize"
|
|
157
|
+
@keydown="onGripKeydown"
|
|
158
|
+
>
|
|
159
|
+
<span class="absolute inset-y-0 left-0 w-px transition-colors group-hover/resize:bg-brand group-focus-visible/resize:bg-brand" />
|
|
160
|
+
</div>
|
|
161
|
+
|
|
162
|
+
<header v-if="title || subtitle || $slots.title || closable" class="flex shrink-0 items-start gap-2 px-4 pb-3 pt-4">
|
|
163
|
+
<div class="min-w-0 flex-1">
|
|
164
|
+
<h2 class="truncate text-sm font-semibold text-ink"><slot name="title">{{ title }}</slot></h2>
|
|
165
|
+
<p v-if="subtitle" class="truncate text-xs text-muted">{{ subtitle }}</p>
|
|
166
|
+
</div>
|
|
167
|
+
<slot name="actions" />
|
|
168
|
+
<IconCloseButton v-if="closable" :label="text.close" @click="close" />
|
|
169
|
+
</header>
|
|
170
|
+
|
|
171
|
+
<LpScrollArea class="min-h-0 flex-1" content-class="flex flex-col gap-4 px-4 pb-4">
|
|
172
|
+
<slot v-if="isEmpty" name="empty">
|
|
173
|
+
<p class="py-8 text-center text-sm text-muted">{{ text.empty }}</p>
|
|
174
|
+
</slot>
|
|
175
|
+
<template v-else>
|
|
176
|
+
<template v-for="section in sections" :key="section.key">
|
|
177
|
+
<LpDisclosure v-if="section.collapsible && section.title" :label="section.title" :default-open="!section.collapsed">
|
|
178
|
+
<slot :name="`section-${section.key}`" :subject="subject" :section="section">
|
|
179
|
+
<LpDataList :items="section.items ?? []" size="sm" />
|
|
180
|
+
</slot>
|
|
181
|
+
</LpDisclosure>
|
|
182
|
+
<section v-else class="flex flex-col gap-2">
|
|
183
|
+
<h3 v-if="section.title" class="text-xs font-semibold text-muted">{{ section.title }}</h3>
|
|
184
|
+
<slot :name="`section-${section.key}`" :subject="subject" :section="section">
|
|
185
|
+
<LpDataList :items="section.items ?? []" size="sm" />
|
|
186
|
+
</slot>
|
|
187
|
+
</section>
|
|
188
|
+
</template>
|
|
189
|
+
<slot :subject="subject" />
|
|
190
|
+
</template>
|
|
191
|
+
</LpScrollArea>
|
|
192
|
+
|
|
193
|
+
<footer v-if="$slots.footer" class="flex shrink-0 justify-end gap-2 px-4 pb-4 pt-3">
|
|
194
|
+
<slot name="footer" :subject="subject" :close="close" />
|
|
195
|
+
</footer>
|
|
196
|
+
</aside>
|
|
197
|
+
</template>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { useModelOverlayHistory, type OverlayHistoryMode } from "../composables/useOverlayHistory"
|
|
2
3
|
/*
|
|
3
4
|
* Full-screen image viewer — the Discord-style lightbox: click a thumbnail, the
|
|
4
5
|
* image fills the screen, arrows step through the set, the wheel zooms toward
|
|
@@ -13,6 +14,7 @@
|
|
|
13
14
|
* Controlled via v-model:open and v-model:index, so the caller owns which image
|
|
14
15
|
* is showing and can drive it from a grid, a route or a keyboard shortcut.
|
|
15
16
|
*/
|
|
17
|
+
import { clamp } from "../composables/clamp"
|
|
16
18
|
import {
|
|
17
19
|
DialogContent,
|
|
18
20
|
DialogDescription,
|
|
@@ -24,12 +26,14 @@ import {
|
|
|
24
26
|
import { computed, nextTick, onBeforeUnmount, ref, watch } from "vue"
|
|
25
27
|
import { useLabels } from "../composables/useLpConfig"
|
|
26
28
|
import { useZoomPan } from "../composables/useZoomPan"
|
|
29
|
+
import { clickLink } from "./exportData"
|
|
27
30
|
import { fileNameOf, type LightboxItem } from "./lightbox"
|
|
28
31
|
import LpCopyButton from "./LpCopyButton.vue"
|
|
29
32
|
import LpIcon from "./LpIcon.vue"
|
|
30
33
|
import LpLoader from "./LpLoader.vue"
|
|
31
34
|
import { useModalLayer } from "./modalDepth"
|
|
32
|
-
import {
|
|
35
|
+
import { inTextField } from "../composables/textEntry"
|
|
36
|
+
import { nodeWindow, useOutsideGuard, usePortalTarget, useView, viewDocument } from "../composables/useView"
|
|
33
37
|
|
|
34
38
|
export type LightboxLabels = {
|
|
35
39
|
viewer: string
|
|
@@ -50,6 +54,12 @@ export type LightboxLabels = {
|
|
|
50
54
|
|
|
51
55
|
const props = withDefaults(
|
|
52
56
|
defineProps<{
|
|
57
|
+
/**
|
|
58
|
+
* Browser Back closes it, and opening it adds a history entry. Unset
|
|
59
|
+
* follows `provideOverlayHistory` (off without one); `"reopen"` also opens
|
|
60
|
+
* it again on Forward; `false` keeps it out of history.
|
|
61
|
+
*/
|
|
62
|
+
history?: OverlayHistoryMode
|
|
53
63
|
open?: boolean
|
|
54
64
|
/** Images to page through. */
|
|
55
65
|
items: LightboxItem[]
|
|
@@ -70,6 +80,7 @@ const props = withDefaults(
|
|
|
70
80
|
labels?: Partial<LightboxLabels>
|
|
71
81
|
}>(),
|
|
72
82
|
{
|
|
83
|
+
history: undefined,
|
|
73
84
|
open: false,
|
|
74
85
|
index: 0,
|
|
75
86
|
rotatable: true,
|
|
@@ -90,6 +101,13 @@ const emit = defineEmits<{
|
|
|
90
101
|
(e: "copy", item: LightboxItem, ok: boolean): void
|
|
91
102
|
}>()
|
|
92
103
|
|
|
104
|
+
useModelOverlayHistory({
|
|
105
|
+
mode: () => props.history,
|
|
106
|
+
open: () => !!props.open,
|
|
107
|
+
setOpen: (open) => emit("update:open", open),
|
|
108
|
+
allowClose: async () => true,
|
|
109
|
+
})
|
|
110
|
+
|
|
93
111
|
const text = useLabels<LightboxLabels>(
|
|
94
112
|
"lightbox",
|
|
95
113
|
{
|
|
@@ -137,7 +155,7 @@ const isPanning = computed(() => zoom.panning.value)
|
|
|
137
155
|
// moves it locally and reports the move.
|
|
138
156
|
const shown = ref(props.index)
|
|
139
157
|
watch(() => props.index, (i) => (shown.value = i))
|
|
140
|
-
const current = computed(() =>
|
|
158
|
+
const current = computed(() => clamp(shown.value, 0, Math.max(props.items.length - 1, 0)))
|
|
141
159
|
const item = computed<LightboxItem | undefined>(() => props.items[current.value])
|
|
142
160
|
const total = computed(() => props.items.length)
|
|
143
161
|
const showStrip = computed(() => props.filmstrip ?? total.value > 1)
|
|
@@ -146,6 +164,7 @@ const rotation = ref(0)
|
|
|
146
164
|
const loading = ref(false)
|
|
147
165
|
const failed = ref(false)
|
|
148
166
|
const viewport = ref<HTMLElement | null>(null)
|
|
167
|
+
const stageImage = ref<HTMLImageElement | null>(null)
|
|
149
168
|
const stripEl = ref<HTMLElement | null>(null)
|
|
150
169
|
|
|
151
170
|
watch(viewport, (el) => zoom.setViewport(el))
|
|
@@ -158,7 +177,7 @@ function go(next: number) {
|
|
|
158
177
|
if (!total.value) return
|
|
159
178
|
const wrapped = props.loop
|
|
160
179
|
? (next + total.value) % total.value
|
|
161
|
-
:
|
|
180
|
+
: clamp(next, 0, total.value - 1)
|
|
162
181
|
if (wrapped === current.value) return
|
|
163
182
|
// Compare against the raw target, not the wrapped one: stepping past the last
|
|
164
183
|
// image is still "forward" even though the index jumps back to 0.
|
|
@@ -225,7 +244,7 @@ function onStageWheel(e: WheelEvent) {
|
|
|
225
244
|
// Reset the view whenever the image changes — carrying a 4x zoom onto the next
|
|
226
245
|
// picture means landing on a random crop of it.
|
|
227
246
|
watch(
|
|
228
|
-
() => [current.value, props.open] as const,
|
|
247
|
+
() => [current.value, props.open, item.value?.src] as const,
|
|
229
248
|
() => {
|
|
230
249
|
zoom.reset()
|
|
231
250
|
rotation.value = 0
|
|
@@ -235,6 +254,16 @@ watch(
|
|
|
235
254
|
},
|
|
236
255
|
)
|
|
237
256
|
|
|
257
|
+
/*
|
|
258
|
+
* An image paged past stays in flight after it leaves the DOM and still reports
|
|
259
|
+
* here: only the one on stage may settle the spinner or the failed state.
|
|
260
|
+
*/
|
|
261
|
+
function imageSettled(event: Event, ok: boolean) {
|
|
262
|
+
if (event.currentTarget !== stageImage.value) return
|
|
263
|
+
loading.value = false
|
|
264
|
+
if (!ok) failed.value = true
|
|
265
|
+
}
|
|
266
|
+
|
|
238
267
|
function scrollThumbIntoView() {
|
|
239
268
|
const el = stripEl.value?.querySelector<HTMLElement>(`[data-index="${current.value}"]`)
|
|
240
269
|
el?.scrollIntoView({ behavior: "smooth", block: "nearest", inline: "center" })
|
|
@@ -261,7 +290,13 @@ watch(
|
|
|
261
290
|
},
|
|
262
291
|
)
|
|
263
292
|
|
|
293
|
+
/* Controls in the `actions` slot keep their own keys: a caret, a typed "r". */
|
|
294
|
+
const OWNS_KEYS =
|
|
295
|
+
"input, textarea, select, [contenteditable]:not([contenteditable='false']), [role='textbox'], [role='searchbox'], [role='combobox']"
|
|
296
|
+
|
|
264
297
|
function onKeydown(e: KeyboardEvent) {
|
|
298
|
+
if (e.defaultPrevented || e.ctrlKey || e.metaKey || e.altKey) return
|
|
299
|
+
if (inTextField(e.target, OWNS_KEYS)) return
|
|
265
300
|
switch (e.key) {
|
|
266
301
|
case "ArrowRight":
|
|
267
302
|
e.preventDefault()
|
|
@@ -338,27 +373,27 @@ function onViewportClick(e: MouseEvent) {
|
|
|
338
373
|
close()
|
|
339
374
|
}
|
|
340
375
|
|
|
376
|
+
/*
|
|
377
|
+
* The window the viewer opened in. Inside an LpFrame its location is
|
|
378
|
+
* about:blank, which resolves nothing, so a relative source is read against the
|
|
379
|
+
* document's base URL rather than the location.
|
|
380
|
+
*/
|
|
381
|
+
const view = useView()
|
|
382
|
+
const viewerDocument = () => viewDocument(view.value)
|
|
383
|
+
const viewerWindow = () => nodeWindow(viewerDocument())
|
|
384
|
+
const resolved = (src: string) => new URL(src, viewerDocument().baseURI)
|
|
385
|
+
|
|
341
386
|
function sameOrigin(src: string): boolean {
|
|
342
387
|
try {
|
|
343
|
-
const url =
|
|
344
|
-
return url.protocol === "blob:" || url.protocol === "data:" || url.origin ===
|
|
388
|
+
const url = resolved(src)
|
|
389
|
+
return url.protocol === "blob:" || url.protocol === "data:" || url.origin === new URL(viewerDocument().baseURI).origin
|
|
345
390
|
} catch {
|
|
346
391
|
return false
|
|
347
392
|
}
|
|
348
393
|
}
|
|
349
394
|
|
|
350
395
|
function save(href: string, name: string, newTab = false) {
|
|
351
|
-
|
|
352
|
-
a.href = href
|
|
353
|
-
if (newTab) {
|
|
354
|
-
a.target = "_blank"
|
|
355
|
-
a.rel = "noopener"
|
|
356
|
-
} else {
|
|
357
|
-
a.download = name
|
|
358
|
-
}
|
|
359
|
-
document.body.appendChild(a)
|
|
360
|
-
a.click()
|
|
361
|
-
a.remove()
|
|
396
|
+
clickLink(viewerDocument(), newTab ? { href, target: "_blank", rel: "noopener" } : { href, download: name })
|
|
362
397
|
}
|
|
363
398
|
|
|
364
399
|
/*
|
|
@@ -373,11 +408,12 @@ async function download() {
|
|
|
373
408
|
const name = fileNameOf(target)
|
|
374
409
|
if (sameOrigin(target.src)) return save(target.src, name)
|
|
375
410
|
try {
|
|
376
|
-
const
|
|
411
|
+
const win = viewerWindow()
|
|
412
|
+
const response = await win.fetch(resolved(target.src).href, { mode: "cors" })
|
|
377
413
|
if (!response.ok) throw new Error(String(response.status))
|
|
378
|
-
const url = URL.createObjectURL(await response.blob())
|
|
414
|
+
const url = win.URL.createObjectURL(await response.blob())
|
|
379
415
|
save(url, name)
|
|
380
|
-
|
|
416
|
+
win.setTimeout(() => win.URL.revokeObjectURL(url), 0)
|
|
381
417
|
} catch {
|
|
382
418
|
save(target.src, name, true)
|
|
383
419
|
}
|
|
@@ -392,20 +428,28 @@ let copyTarget: LightboxItem | undefined
|
|
|
392
428
|
async function imageToCopy(): Promise<Blob> {
|
|
393
429
|
const target = (copyTarget = item.value)
|
|
394
430
|
if (!target) throw new Error("No image")
|
|
395
|
-
const
|
|
431
|
+
const win = viewerWindow()
|
|
432
|
+
const response = await win.fetch(resolved(target.src).href)
|
|
396
433
|
const blob = await response.blob()
|
|
397
434
|
// Clipboard only takes PNG; re-encode anything else through a canvas.
|
|
398
|
-
return blob.type === "image/png" ? blob : reencodeToPng(await createImageBitmap(blob))
|
|
435
|
+
return blob.type === "image/png" ? blob : reencodeToPng(await win.createImageBitmap(blob))
|
|
399
436
|
}
|
|
400
437
|
function copyDone(ok: boolean) {
|
|
401
|
-
|
|
438
|
+
const target = copyTarget
|
|
439
|
+
copyTarget = undefined
|
|
440
|
+
if (target) emit("copy", target, ok)
|
|
402
441
|
}
|
|
403
442
|
|
|
404
443
|
async function reencodeToPng(bitmap: ImageBitmap): Promise<Blob> {
|
|
405
|
-
const canvas =
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
444
|
+
const canvas = viewerDocument().createElement("canvas")
|
|
445
|
+
try {
|
|
446
|
+
canvas.width = bitmap.width
|
|
447
|
+
canvas.height = bitmap.height
|
|
448
|
+
canvas.getContext("2d")?.drawImage(bitmap, 0, 0)
|
|
449
|
+
} finally {
|
|
450
|
+
// Decoded pixels live outside the JS heap; a large image should not wait for GC.
|
|
451
|
+
bitmap.close()
|
|
452
|
+
}
|
|
409
453
|
return new Promise((resolve, reject) =>
|
|
410
454
|
canvas.toBlob((b) => (b ? resolve(b) : reject(new Error("encode failed"))), "image/png"),
|
|
411
455
|
)
|
|
@@ -570,14 +614,15 @@ const guardOutside = useOutsideGuard()
|
|
|
570
614
|
<img
|
|
571
615
|
v-else-if="item"
|
|
572
616
|
:key="`${current}:${item.src}`"
|
|
617
|
+
ref="stageImage"
|
|
573
618
|
data-lightbox-image
|
|
574
619
|
:src="item.src"
|
|
575
620
|
:alt="item.title ?? ''"
|
|
576
621
|
class="max-h-full max-w-full select-none object-contain transition-transform duration-[var(--duration-medium)] ease-[var(--ease-emphasized)] animate-[lightbox-frame-in_var(--duration-medium)_var(--ease-emphasized)] motion-reduce:animate-none motion-reduce:transition-none"
|
|
577
622
|
:style="imageStyle"
|
|
578
623
|
draggable="false"
|
|
579
|
-
@load="
|
|
580
|
-
@error="(
|
|
624
|
+
@load="imageSettled($event, true)"
|
|
625
|
+
@error="imageSettled($event, false)"
|
|
581
626
|
/>
|
|
582
627
|
|
|
583
628
|
<!-- Mounted throughout and driven by `active`, so a cached image that
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/*
|
|
3
|
+
* One log entry read closely: a structured payload as a tree, a stack trace with
|
|
4
|
+
* its frames set apart from the error above them. LpLogViewer shows it under
|
|
5
|
+
* the stream for the selected line (`inspector`); on its own it takes the
|
|
6
|
+
* message, or `value` for a payload the app already has parsed.
|
|
7
|
+
*/
|
|
8
|
+
import { computed, ref, watch } from "vue"
|
|
9
|
+
import LpIcon from "./LpIcon.vue"
|
|
10
|
+
import LpInput from "./LpInput.vue"
|
|
11
|
+
import { useLabels } from "../composables/useLpConfig"
|
|
12
|
+
import { jsonRows, stackLines, structuredPayload } from "./logTools"
|
|
13
|
+
|
|
14
|
+
export interface LogInspectorLabels {
|
|
15
|
+
[key: string]: string
|
|
16
|
+
title: string
|
|
17
|
+
filterFields: string
|
|
18
|
+
noFields: string
|
|
19
|
+
expand: string
|
|
20
|
+
collapse: string
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const props = defineProps<{
|
|
24
|
+
/** The entry's text. Its JSON, if it holds any, becomes the tree. */
|
|
25
|
+
message?: string
|
|
26
|
+
/** A parsed payload, instead of reading one from `message`. */
|
|
27
|
+
value?: object
|
|
28
|
+
labels?: Partial<LogInspectorLabels>
|
|
29
|
+
}>()
|
|
30
|
+
|
|
31
|
+
const text = useLabels<LogInspectorLabels>(
|
|
32
|
+
"logInspector",
|
|
33
|
+
{ title: "Log entry", filterFields: "Filter fields", noFields: "No fields match", expand: "Expand {field}", collapse: "Collapse {field}" },
|
|
34
|
+
() => props.labels,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
const filter = ref("")
|
|
38
|
+
const collapsed = ref(new Set<string>())
|
|
39
|
+
const payload = computed(() => props.value ?? (props.message ? structuredPayload(props.message) : null))
|
|
40
|
+
const rows = computed(() => (payload.value ? jsonRows(payload.value, collapsed.value, filter.value) : []))
|
|
41
|
+
const stack = computed(() => (props.message ? stackLines(props.message) : null))
|
|
42
|
+
|
|
43
|
+
// Another entry is another document: what was folded here means nothing there.
|
|
44
|
+
watch(payload, () => {
|
|
45
|
+
collapsed.value = new Set()
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
function toggle(path: string) {
|
|
49
|
+
const next = new Set(collapsed.value)
|
|
50
|
+
if (!next.delete(path)) next.add(path)
|
|
51
|
+
collapsed.value = next
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const VALUE_TONE = { string: "text-success", number: "text-accent", boolean: "text-brand", null: "text-muted", object: "text-muted", array: "text-muted" }
|
|
55
|
+
/* Each level of the tree steps in by this much, in rem. */
|
|
56
|
+
const INDENT_REM = 1
|
|
57
|
+
</script>
|
|
58
|
+
|
|
59
|
+
<template>
|
|
60
|
+
<section :aria-label="text.title" class="font-mono text-xs leading-5">
|
|
61
|
+
<template v-if="payload">
|
|
62
|
+
<LpInput v-model="filter" type="search" size="sm" icon="lucide:filter" clearable class="mb-2 font-sans" :aria-label="text.filterFields" :placeholder="text.filterFields" />
|
|
63
|
+
<p v-if="!rows.length" class="py-1 font-sans text-muted">{{ text.noFields }}</p>
|
|
64
|
+
<ul v-else class="min-w-0">
|
|
65
|
+
<li v-for="row in rows" :key="row.path" class="flex items-start gap-1" :style="{ paddingLeft: `${row.depth * INDENT_REM}rem` }">
|
|
66
|
+
<button
|
|
67
|
+
v-if="row.expandable"
|
|
68
|
+
type="button"
|
|
69
|
+
class="mt-0.5 shrink-0 rounded-xs text-muted outline-none hover:text-ink focus-visible:ring-2 focus-visible:ring-ring"
|
|
70
|
+
:aria-expanded="!collapsed.has(row.path)"
|
|
71
|
+
:aria-label="(collapsed.has(row.path) ? text.expand : text.collapse).replace('{field}', row.label)"
|
|
72
|
+
@click="toggle(row.path)"
|
|
73
|
+
>
|
|
74
|
+
<LpIcon :name="collapsed.has(row.path) ? 'lucide:chevron-right' : 'lucide:chevron-down'" :size="12" />
|
|
75
|
+
</button>
|
|
76
|
+
<span v-else class="w-3 shrink-0" aria-hidden="true" />
|
|
77
|
+
<span class="shrink-0 text-muted-strong">{{ row.label }}:</span>
|
|
78
|
+
<span class="min-w-0 whitespace-pre-wrap break-words" :class="VALUE_TONE[row.kind]">{{ row.value }}</span>
|
|
79
|
+
</li>
|
|
80
|
+
</ul>
|
|
81
|
+
</template>
|
|
82
|
+
<pre v-else-if="stack" class="overflow-x-auto"><template v-for="(line, i) in stack" :key="i"><span :class="line.frame ? 'text-muted' : 'text-ink'">{{ line.text }}</span>{{ "\n" }}</template></pre>
|
|
83
|
+
<p v-else class="whitespace-pre-wrap break-words text-ink">{{ message }}</p>
|
|
84
|
+
</section>
|
|
85
|
+
</template>
|