@leavepulse/ui 0.68.0 → 0.70.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 +37 -0
- package/dist/assets/LoaderMark-DxBV2iDJ.css +43 -0
- package/dist/assets/LpActivityLine-B3EwNQEB.css +33 -0
- package/dist/assets/{LpCommandPalette-DxyjhYn_.css → LpCommandPalette-u-zOxKWa.css} +21 -31
- package/dist/assets/LpDock-Cbh0wQUv.css +17 -0
- package/dist/assets/{LpDropzone-Qb8k7cg4.css → LpDropzone-Bb1vBTeU.css} +12 -17
- package/dist/assets/{LpImageEditor-CElPDzpF.css → LpImageEditor-XM5bAziW.css} +6 -6
- package/dist/assets/LpLogViewer-BDNW6P52.css +38 -0
- package/dist/assets/{LpPalettePreview-CJmAKgYW.css → LpPalettePreview-B9VKDrvA.css} +2 -7
- package/dist/assets/LpShinyText-D69cBYDR.css +61 -0
- package/dist/assets/LpStatus-430OGTZY.css +17 -0
- package/dist/assets/LpStepMark-Drvx33Vg.css +10 -0
- package/dist/assets/{LpTable-BPERfJIk.css → LpTable-DHxEQ_-3.css} +19 -19
- package/dist/assets/LpTabs-BJ-nrJuI.css +18 -0
- package/dist/assets/LpTextReveal-DjI1MsDS.css +35 -0
- package/dist/assets/LpTypewriter-CXAm9Nca.css +27 -0
- package/dist/chunks/AttentionDot-DCBf4aWg.js +25 -0
- package/dist/chunks/{ContextMenuItems-B7XFHksm.js → ContextMenuItems-B5uE8Znw.js} +1 -1
- package/dist/chunks/{DropzoneLinkField-CjkrpDqO.js → DropzoneLinkField-Bw8Flkhk.js} +2 -2
- package/dist/chunks/FieldWrapper-BiennROB.js +43 -0
- package/dist/chunks/{LayoutCanvas-DF9CovaK.js → LayoutCanvas-BsJIzhdd.js} +1 -1
- package/dist/chunks/{LayoutNode-D9bIFzk0.js → LayoutNode-DJVhkSGk.js} +6 -8
- package/dist/chunks/LegendSwatch-BhRjrtzv.js +18 -0
- package/dist/chunks/LoaderMark-C1dubiKn.js +85 -0
- package/dist/chunks/{LpActionBar-MPKMu3pz.js → LpActionBar-CzOFar5t.js} +14 -20
- package/dist/chunks/LpActivityLine-CJvzrNpj.js +95 -0
- package/dist/chunks/{LpAddressInput-DG0BTqdH.js → LpAddressInput-CNnLTDZg.js} +7 -7
- package/dist/chunks/LpAlert-C5igj802.js +119 -0
- package/dist/chunks/{LpAppShell-DPh1756q.js → LpAppShell-CEUAB8kK.js} +15 -16
- package/dist/chunks/{LpAutocomplete-Dgn6hw3p.js → LpAutocomplete-D92niDHE.js} +15 -32
- package/dist/chunks/{LpAvatar-Bs0Fb1lC.js → LpAvatar-CLPl-qOF.js} +18 -6
- package/dist/chunks/LpBadge-HOEPBYmi.js +126 -0
- package/dist/chunks/LpBreadcrumbs-DYoPc3P4.js +144 -0
- package/dist/chunks/{LpButton-DNR-YAq5.js → LpButton-CVxBfGjd.js} +12 -4
- package/dist/chunks/{LpCalendar-BLya39Fh.js → LpCalendar-pVL91-Pl.js} +1 -1
- package/dist/chunks/{LpCard-Bf71NXZq.js → LpCard-CqKLnEhl.js} +18 -8
- package/dist/chunks/{LpCheckbox-Da5oZPHo.js → LpCheckbox-DHc2bHDe.js} +9 -6
- package/dist/chunks/{LpCodeBlock-lLbmslfs.js → LpCodeBlock-BGsQhxw8.js} +24 -32
- package/dist/chunks/LpCodeDisplay-CIKKT2iW.js +189 -0
- package/dist/chunks/LpCollapse-CWS9M_lm.js +115 -0
- package/dist/chunks/{LpColorPicker-DtEfBAcK.js → LpColorPicker-DFugXNUi.js} +10 -5
- package/dist/chunks/{LpConfirmDialog-D7s4jakB.js → LpConfirmDialog-CfGCux8m.js} +3 -3
- package/dist/chunks/{LpConfirmHost-DrYI5y1K.js → LpConfirmHost-exB7JmcO.js} +1 -1
- package/dist/chunks/{LpContextMenu-CRnjoqSt.js → LpContextMenu-COwOwRgI.js} +13 -5
- package/dist/chunks/LpCopyButton-DzHjnFs0.js +133 -0
- package/dist/chunks/LpCountdown-Dtq1ihlJ.js +231 -0
- package/dist/chunks/LpDataList-B-5nHfNw.js +120 -0
- package/dist/chunks/LpDatePicker-BUe1VUC0.js +168 -0
- package/dist/chunks/LpDateRangePicker-C_k65vGR.js +126 -0
- package/dist/chunks/{LpDisclosure-6AplYBub.js → LpDisclosure-DOarzlAG.js} +22 -11
- package/dist/chunks/{LpDrawer-Q4SOxM4s.js → LpDrawer-DGNKRsGq.js} +9 -4
- package/dist/chunks/{LpDropdownMenu-DWTt0ooM.js → LpDropdownMenu-CRgrhdAH.js} +10 -5
- package/dist/chunks/LpEditable-DTqLt2lT.js +236 -0
- package/dist/chunks/{LpEmptyState-om1UnFjV.js → LpEmptyState-KTKipws2.js} +1 -1
- package/dist/chunks/{LpFieldNotice-CHuDeLjc.js → LpFieldNotice-CurbNuXI.js} +1 -1
- package/dist/chunks/{LpFileTree-CW24YsVX.js → LpFileTree-DMISXVHC.js} +5 -3
- package/dist/chunks/{LpFileTreeNode-BXhTHaKW.js → LpFileTreeNode-CPXB_Yy3.js} +42 -55
- package/dist/chunks/{LpFormField-DPb47HEm.js → LpFormField-BWwgm1E4.js} +23 -9
- package/dist/chunks/LpFrame-BVQCQLDI.js +155 -0
- package/dist/chunks/LpGauge-Bk8TwJj0.js +204 -0
- package/dist/chunks/LpGlowBorder-B8V-QzIl.js +40 -0
- package/dist/chunks/{LpHintExample-C1eKYdeL.js → LpHintExample-9Py0wc-L.js} +11 -34
- package/dist/chunks/{LpHintLayer-7UOdWQG3.js → LpHintLayer-p4hqzdyA.js} +27 -14
- package/dist/chunks/{LpHints-BUtBp9-w.js → LpHints-CCrhRfy9.js} +3 -3
- package/dist/chunks/LpHoverCard-spGxyw7T.js +130 -0
- package/dist/chunks/{LpIcon-6tSrZ3Zy.js → LpIcon-HJP5xMz4.js} +1 -1
- package/dist/chunks/LpIdenticon-BzdC_qz9.js +63 -0
- package/dist/chunks/{LpInfraNode-Ds_8SZgN.js → LpInfraNode-CUC3t4na.js} +39 -25
- package/dist/chunks/{LpInput-CUyr6PIE.js → LpInput-CDuwODJG.js} +44 -18
- package/dist/chunks/{LpLightbox-B9J8rzsj.js → LpLightbox-XJ0LpTcZ.js} +69 -69
- package/dist/chunks/LpLoader-DjJEX8hL.js +92 -0
- package/dist/chunks/{LpLogViewer-4QFc-sVN.js → LpLogViewer-elZHbj85.js} +225 -129
- package/dist/chunks/LpMagnetic-CtXKLa2Y.js +62 -0
- package/dist/chunks/{LpMapPicker-BTbkFeSG.js → LpMapPicker-BtIl7NOM.js} +34 -31
- package/dist/chunks/LpMasonry--k0571qG.js +185 -0
- package/dist/chunks/{LpMediaGallery-CuPcscx3.js → LpMediaGallery-D5swlmZ_.js} +3 -3
- package/dist/chunks/{LpModal-hk1noDcr.js → LpModal-eBMt2Fqn.js} +8 -3
- package/dist/chunks/{LpModalNav-DQd2keZm.js → LpModalNav-D4Z0wVHR.js} +4 -4
- package/dist/chunks/{LpNotificationBell-X84PJIxD.js → LpNotificationBell-DPZmP5dM.js} +32 -48
- package/dist/chunks/LpNumberField-B9k-h2HE.js +140 -0
- package/dist/chunks/{LpNumberFlow-z4WPZcZu.js → LpNumberFlow-Cfyh033Q.js} +8 -28
- package/dist/chunks/{LpOtpInput-PbeNJ5In.js → LpOtpInput-CeBPsM7D.js} +2 -1
- package/dist/chunks/{LpPagination-Bx-VG4Ag.js → LpPagination-VNCX6pFC.js} +37 -6
- package/dist/chunks/{LpPalettePreview-CFav_7co.js → LpPalettePreview-BNB8T_MY.js} +1 -1
- package/dist/chunks/{LpPasswordInput-CbnXitAS.js → LpPasswordInput-DTV18FIh.js} +20 -20
- package/dist/chunks/{LpPhoneInput-DP69HONS.js → LpPhoneInput-C60tx1tC.js} +12 -7
- package/dist/chunks/{LpPie-yLF9-aDR.js → LpPie-CFuV7pZv.js} +158 -47
- package/dist/chunks/LpPipeline-D81yh_NX.js +329 -0
- package/dist/chunks/{LpPopover-DVnkHaOu.js → LpPopover-BEIcqb9p.js} +8 -3
- package/dist/chunks/{LpProgress-CA86wxXu.js → LpProgress-CE-m5OpD.js} +23 -63
- package/dist/chunks/LpQuota-2Sw_gqcJ.js +162 -0
- package/dist/chunks/{LpRadioGroup-8S5hf8lE.js → LpRadioGroup-CGBr5nIp.js} +1 -1
- package/dist/chunks/{LpRangeCalendar-ByQi-WUz.js → LpRangeCalendar-c5qj7YcC.js} +1 -1
- package/dist/chunks/{LpRangeSlider-C1yF9-nP.js → LpRangeSlider-Dv6lNvHY.js} +6 -2
- package/dist/chunks/LpRelativeTime-CKzVqAo9.js +73 -0
- package/dist/chunks/LpRepeater-D0VjmD6y.js +140 -0
- package/dist/chunks/LpRevealOnScroll-DcQjexLy.js +76 -0
- package/dist/chunks/LpScramble-TDO5Kdou.js +85 -0
- package/dist/chunks/LpSecretField-DMfdJ1cQ.js +307 -0
- package/dist/chunks/{LpSection-BmRXe6ZP.js → LpSection-BW4xJ-Li.js} +1 -1
- package/dist/chunks/{LpSegmented-CW3bFHM4.js → LpSegmented-BO99Sr4m.js} +11 -14
- package/dist/chunks/{LpSelect-BCyDYoih.js → LpSelect-B4f_yRi5.js} +93 -108
- package/dist/chunks/LpShaderBackdrop-Bote0iuy.js +332 -0
- package/dist/chunks/LpShinyText-DX2ajtWq.js +48 -0
- package/dist/chunks/{LpSidebar-DfIiS-lB.js → LpSidebar-D-M0Y_7U.js} +5 -3
- package/dist/chunks/{LpSidebarNav-C5FDNI0t.js → LpSidebarNav-DF-TYxOV.js} +3 -3
- package/dist/chunks/{LpSlider-Cuzmrd7p.js → LpSlider-DuoRpOrH.js} +6 -2
- package/dist/chunks/{LpSparkline-DXT4KrSi.js → LpSparkline-CExIRDb3.js} +32 -27
- package/dist/chunks/LpSpotlight-4F3NeUMY.js +41 -0
- package/dist/chunks/{LpStat-iBMF5QNk.js → LpStat-B2ix1Q7t.js} +38 -35
- package/dist/chunks/LpStatus-C7kx5PKE.js +86 -0
- package/dist/chunks/LpStepMark-DK-5BKAt.js +101 -0
- package/dist/chunks/LpStepper-DRFfdJaq.js +76 -0
- package/dist/chunks/{LpSwap-D82jiecV.js → LpSwap-DzE6M3Mg.js} +1 -1
- package/dist/chunks/LpSwitch-DrzKrZZV.js +112 -0
- package/dist/chunks/{LpTableFilter-CuIbgdW0.js → LpTableFilter-DyvHGbOk.js} +3 -2
- package/dist/chunks/{LpTableOfContents-C_4VBktT.js → LpTableOfContents-rYvo8z5T.js} +34 -21
- package/dist/chunks/{LpTagsInput-DiXrpYeE.js → LpTagsInput-DgpBFRV2.js} +68 -71
- package/dist/chunks/LpTextReveal-CtAnOUkp.js +140 -0
- package/dist/chunks/{LpTextarea-xoQd5Lnp.js → LpTextarea-DiWjeVoJ.js} +12 -11
- package/dist/chunks/{LpThemeProvider-CQ2jC9TA.js → LpThemeProvider-DcbfOxsU.js} +1 -1
- package/dist/chunks/LpThemeStudio-DguwHdGt.js +416 -0
- package/dist/chunks/LpThemeStudioSection-BwhqYDLf.js +20 -0
- package/dist/chunks/LpThemeSwitcher-D5uz0MhK.js +278 -0
- package/dist/chunks/{LpTimeField-MFgAsNc5.js → LpTimeField-BFQVf_PW.js} +13 -5
- package/dist/chunks/{LpToaster-C4zE9zB7.js → LpToaster-Wv9ksj4q.js} +49 -82
- package/dist/chunks/{LpTooltip-suFCM34F.js → LpTooltip-Cz8SQwRt.js} +8 -3
- package/dist/chunks/{LpTopologyCanvas-6ozNrQKh.js → LpTopologyCanvas-ZhKthfgz.js} +1 -1
- package/dist/chunks/{LpTour-BUp3Jt2e.js → LpTour-NfRJNEIP.js} +24 -18
- package/dist/chunks/LpTruncate-D_5Pfv5B.js +112 -0
- package/dist/chunks/LpTypewriter-BCL_a6wE.js +159 -0
- package/dist/chunks/{LpUptimeBar-B6kHw4Cj.js → LpUptimeBar-DWegV2p6.js} +9 -8
- package/dist/chunks/{LpVideoBackdrop-qWRYBOTQ.js → LpVideoBackdrop-DS1wGv-X.js} +7 -8
- package/dist/chunks/{MenuTitle-obgek0B7.js → MenuTitle-BjQZX8tQ.js} +1 -1
- package/dist/chunks/OptionContent-CmYUUeWj.js +40 -0
- package/dist/chunks/PickerField-CHRS1h7K.js +116 -0
- package/dist/chunks/RevealToggle-C-KzaQGJ.js +65 -0
- package/dist/chunks/StepConnector-37OgEOXA.js +41 -0
- package/dist/chunks/TourCard-BXuVHsfn.js +123 -0
- package/dist/chunks/backdrop-Dkf2vM81.js +59 -0
- package/dist/chunks/{icons-DVhZ_plB.js → icons-4IywzkHk.js} +1 -1
- package/dist/chunks/{useTheme-2qHG8NEU.js → useTheme-BOV_-AiY.js} +9 -65
- package/dist/component-names.d.ts +1 -1
- package/dist/components/AttentionDot.vue.d.ts +9 -0
- package/dist/components/AttentionDot.vue.js +4 -0
- package/dist/components/ContextMenuItems.vue.js +1 -1
- package/dist/components/DropzoneLinkField.vue.js +1 -1
- package/dist/components/FieldWrapper.vue.d.ts +25 -0
- package/dist/components/FieldWrapper.vue.js +4 -0
- package/dist/components/LayoutCanvas.vue.js +1 -1
- package/dist/components/LayoutNode.vue.d.ts +4 -4
- package/dist/components/LayoutNode.vue.js +1 -1
- package/dist/components/LegendSwatch.vue.d.ts +6 -0
- package/dist/components/LegendSwatch.vue.js +4 -0
- package/dist/components/LoaderMark.vue.d.ts +12 -0
- package/dist/components/LoaderMark.vue.js +4 -0
- package/dist/components/LpActionBar.vue.js +1 -1
- package/dist/components/LpActivityLine.vue.d.ts +58 -0
- package/dist/components/LpActivityLine.vue.js +4 -0
- package/dist/components/LpAddressInput.vue.js +1 -1
- package/dist/components/LpAlert.vue.d.ts +2 -2
- package/dist/components/LpAlert.vue.js +1 -1
- package/dist/components/LpAppShell.vue.d.ts +8 -7
- package/dist/components/LpAppShell.vue.js +1 -1
- package/dist/components/LpAutocomplete.vue.js +1 -1
- package/dist/components/LpAvatar.vue.d.ts +16 -0
- package/dist/components/LpAvatar.vue.js +1 -1
- package/dist/components/LpBadge.vue.d.ts +19 -5
- package/dist/components/LpBadge.vue.js +1 -1
- package/dist/components/LpBreadcrumbs.vue.js +1 -1
- package/dist/components/LpButton.vue.d.ts +2 -2
- package/dist/components/LpButton.vue.js +1 -1
- package/dist/components/LpCalendar.vue.js +1 -1
- package/dist/components/LpCard.vue.d.ts +24 -0
- package/dist/components/LpCard.vue.js +1 -1
- package/dist/components/LpChart.vue.d.ts +10 -0
- package/dist/components/LpChart.vue.js +122 -142
- package/dist/components/LpCheckbox.vue.d.ts +2 -2
- package/dist/components/LpCheckbox.vue.js +1 -1
- package/dist/components/LpCodeBlock.vue.js +1 -1
- package/dist/components/LpCodeDisplay.vue.d.ts +89 -0
- package/dist/components/LpCodeDisplay.vue.js +4 -0
- package/dist/components/LpCollapse.vue.d.ts +58 -0
- package/dist/components/LpCollapse.vue.js +4 -0
- package/dist/components/LpColorPicker.vue.d.ts +2 -2
- package/dist/components/LpColorPicker.vue.js +1 -1
- package/dist/components/LpCommandPalette.vue.js +34 -23
- 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/LpCopyButton.vue.d.ts +82 -0
- package/dist/components/LpCopyButton.vue.js +4 -0
- package/dist/components/LpCountdown.vue.d.ts +100 -0
- package/dist/components/LpCountdown.vue.js +4 -0
- package/dist/components/LpDataList.vue.d.ts +66 -0
- package/dist/components/LpDataList.vue.js +4 -0
- package/dist/components/LpDatePicker.vue.d.ts +1 -1
- package/dist/components/LpDatePicker.vue.js +1 -1
- package/dist/components/LpDateRangePicker.vue.d.ts +1 -1
- package/dist/components/LpDateRangePicker.vue.js +1 -1
- package/dist/components/LpDisclosure.vue.js +1 -1
- package/dist/components/LpDock.vue.d.ts +74 -0
- package/dist/components/LpDock.vue.js +204 -0
- package/dist/components/LpDrawer.vue.js +1 -1
- package/dist/components/LpDropdownMenu.vue.js +1 -1
- package/dist/components/LpDropzone.vue.d.ts +8 -1
- package/dist/components/LpDropzone.vue.js +36 -15
- package/dist/components/LpEditable.vue.d.ts +85 -0
- package/dist/components/LpEditable.vue.js +4 -0
- package/dist/components/LpEmptyState.vue.js +1 -1
- package/dist/components/LpFieldNotice.vue.js +1 -1
- package/dist/components/LpFileTree.vue.js +1 -1
- package/dist/components/LpFileTreeNode.vue.js +1 -1
- package/dist/components/LpFormField.vue.js +1 -1
- package/dist/components/LpFrame.vue.d.ts +22 -0
- package/dist/components/LpFrame.vue.js +4 -0
- package/dist/components/LpGauge.vue.d.ts +116 -0
- package/dist/components/LpGauge.vue.js +4 -0
- package/dist/components/LpGlowBorder.vue.d.ts +47 -0
- package/dist/components/LpGlowBorder.vue.js +4 -0
- package/dist/components/LpHintExample.vue.d.ts +2 -2
- 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.d.ts +60 -0
- package/dist/components/LpHoverCard.vue.js +4 -0
- package/dist/components/LpIcon.vue.js +1 -1
- package/dist/components/LpIdenticon.vue.d.ts +37 -0
- package/dist/components/LpIdenticon.vue.js +4 -0
- package/dist/components/LpImageEditor.vue.js +13 -19
- package/dist/components/LpInfraNode.vue.js +1 -1
- package/dist/components/LpInput.vue.d.ts +10 -0
- package/dist/components/LpInput.vue.js +1 -1
- package/dist/components/LpLightbox.vue.js +1 -1
- package/dist/components/LpLoader.vue.d.ts +106 -0
- package/dist/components/LpLoader.vue.js +4 -0
- package/dist/components/LpLogViewer.vue.js +1 -1
- package/dist/components/LpMagnetic.vue.d.ts +28 -0
- package/dist/components/LpMagnetic.vue.js +4 -0
- package/dist/components/LpMapPicker.vue.js +1 -1
- package/dist/components/LpMasonry.vue.d.ts +42 -0
- package/dist/components/LpMasonry.vue.js +4 -0
- package/dist/components/LpMediaGallery.vue.js +1 -1
- package/dist/components/LpModal.vue.js +1 -1
- package/dist/components/LpModalNav.vue.js +1 -1
- package/dist/components/LpNotificationBell.vue.d.ts +15 -6
- package/dist/components/LpNotificationBell.vue.js +1 -1
- package/dist/components/LpNumberField.vue.d.ts +57 -0
- package/dist/components/LpNumberField.vue.js +1 -1
- package/dist/components/LpNumberFlow.vue.js +1 -1
- package/dist/components/LpOtpInput.vue.d.ts +12 -4
- 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/LpPalettePreview.vue.js +1 -1
- package/dist/components/LpPaletteStats.vue.js +1 -1
- package/dist/components/LpPasswordInput.vue.d.ts +12 -1
- package/dist/components/LpPasswordInput.vue.js +1 -1
- package/dist/components/LpPhoneInput.vue.js +1 -1
- package/dist/components/LpPie.vue.d.ts +3 -1
- package/dist/components/LpPie.vue.js +1 -1
- package/dist/components/LpPipeline.vue.d.ts +91 -0
- package/dist/components/LpPipeline.vue.js +4 -0
- package/dist/components/LpPopover.vue.d.ts +2 -2
- package/dist/components/LpPopover.vue.js +1 -1
- package/dist/components/LpProgress.vue.d.ts +11 -4
- package/dist/components/LpProgress.vue.js +1 -1
- package/dist/components/LpQuota.vue.d.ts +68 -0
- package/dist/components/LpQuota.vue.js +4 -0
- 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.d.ts +41 -0
- package/dist/components/LpRelativeTime.vue.js +4 -0
- package/dist/components/LpRepeater.vue.d.ts +48 -0
- package/dist/components/LpRepeater.vue.js +4 -0
- package/dist/components/LpRevealOnScroll.vue.d.ts +67 -0
- package/dist/components/LpRevealOnScroll.vue.js +4 -0
- package/dist/components/LpRollingText.vue.d.ts +1 -1
- package/dist/components/LpScramble.vue.d.ts +55 -0
- package/dist/components/LpScramble.vue.js +4 -0
- package/dist/components/LpScrollArea.vue.d.ts +1 -1
- package/dist/components/LpSecretField.vue.d.ts +108 -0
- package/dist/components/LpSecretField.vue.js +4 -0
- package/dist/components/LpSection.vue.js +1 -1
- package/dist/components/LpSegmented.vue.js +1 -1
- package/dist/components/LpSelect.vue.d.ts +2 -0
- package/dist/components/LpSelect.vue.js +1 -1
- package/dist/components/LpShaderBackdrop.vue.d.ts +39 -0
- package/dist/components/LpShaderBackdrop.vue.js +4 -0
- package/dist/components/LpShinyText.vue.d.ts +39 -0
- package/dist/components/LpShinyText.vue.js +4 -0
- package/dist/components/LpShortcutsDialog.vue.js +1 -1
- package/dist/components/LpSidebar.vue.js +1 -1
- package/dist/components/LpSidebarNav.vue.js +1 -1
- package/dist/components/LpSlider.vue.js +1 -1
- package/dist/components/LpSparkline.vue.d.ts +4 -3
- package/dist/components/LpSparkline.vue.js +1 -1
- package/dist/components/LpSpotlight.vue.d.ts +37 -0
- package/dist/components/LpSpotlight.vue.js +4 -0
- package/dist/components/LpStat.vue.js +1 -1
- package/dist/components/LpStatus.vue.d.ts +65 -0
- package/dist/components/LpStatus.vue.js +4 -0
- package/dist/components/LpStepMark.vue.d.ts +31 -0
- package/dist/components/LpStepMark.vue.js +4 -0
- package/dist/components/LpStepper.vue.js +1 -1
- package/dist/components/LpSwap.vue.js +1 -1
- package/dist/components/LpSwitch.vue.d.ts +2 -2
- package/dist/components/LpSwitch.vue.js +1 -1
- package/dist/components/LpTable.vue.js +104 -120
- package/dist/components/LpTableFilter.vue.js +1 -1
- package/dist/components/LpTableOfContents.vue.d.ts +6 -1
- package/dist/components/LpTableOfContents.vue.js +1 -1
- package/dist/components/LpTabs.vue.d.ts +5 -5
- package/dist/components/LpTabs.vue.js +25 -33
- package/dist/components/LpTagsInput.vue.js +1 -1
- package/dist/components/LpTextReveal.vue.d.ts +58 -0
- package/dist/components/LpTextReveal.vue.js +4 -0
- package/dist/components/LpTextarea.vue.js +1 -1
- package/dist/components/LpThemeProvider.vue.js +1 -1
- package/dist/components/LpThemeStudio.vue.d.ts +54 -0
- package/dist/components/LpThemeStudio.vue.js +4 -0
- package/dist/components/LpThemeStudioSection.vue.d.ts +16 -0
- package/dist/components/LpThemeStudioSection.vue.js +4 -0
- package/dist/components/LpThemeSwitcher.vue.d.ts +32 -1
- package/dist/components/LpThemeSwitcher.vue.js +1 -1
- package/dist/components/LpTimeField.vue.d.ts +2 -0
- package/dist/components/LpTimeField.vue.js +1 -1
- package/dist/components/LpToaster.vue.js +1 -1
- package/dist/components/LpTooltip.vue.d.ts +2 -2
- package/dist/components/LpTooltip.vue.js +1 -1
- package/dist/components/LpTopologyCanvas.vue.js +1 -1
- package/dist/components/LpTour.vue.js +1 -1
- package/dist/components/LpTruncate.vue.d.ts +34 -0
- package/dist/components/LpTruncate.vue.js +4 -0
- package/dist/components/LpTypewriter.vue.d.ts +61 -0
- package/dist/components/LpTypewriter.vue.js +4 -0
- package/dist/components/LpUptimeBar.vue.js +1 -1
- package/dist/components/LpVideoBackdrop.vue.js +1 -1
- package/dist/components/MenuTitle.vue.js +1 -1
- package/dist/components/OptionContent.vue.d.ts +7 -0
- package/dist/components/OptionContent.vue.js +4 -0
- package/dist/components/PickerField.vue.d.ts +43 -0
- package/dist/components/PickerField.vue.js +4 -0
- package/dist/components/RevealToggle.vue.d.ts +21 -0
- package/dist/components/RevealToggle.vue.js +4 -0
- package/dist/components/StepConnector.vue.d.ts +19 -0
- package/dist/components/StepConnector.vue.js +4 -0
- package/dist/components/TourCard.vue.js +1 -1
- package/dist/components/badge.d.ts +1 -0
- package/dist/components/badge.js +4 -0
- package/dist/components/chart.d.ts +5 -1
- package/dist/components/chart.js +2 -21
- package/dist/components/dateRange.d.ts +11 -0
- package/dist/components/dateRange.js +12 -0
- package/dist/components/dock.d.ts +19 -0
- package/dist/components/dock.js +16 -0
- package/dist/components/dropdown.d.ts +10 -1
- package/dist/components/dropdown.js +7 -2
- package/dist/components/fieldText.d.ts +38 -0
- package/dist/components/fieldText.js +53 -0
- package/dist/components/fileTree.d.ts +7 -3
- package/dist/components/fileTree.js +12 -18
- package/dist/components/format.d.ts +41 -0
- package/dist/components/format.js +67 -0
- package/dist/components/identicon.d.ts +38 -0
- package/dist/components/identicon.js +85 -0
- package/dist/components/masonry.d.ts +32 -0
- package/dist/components/masonry.js +40 -0
- package/dist/components/menuWhen.js +1 -1
- package/dist/components/meter.d.ts +64 -0
- package/dist/components/meter.js +53 -0
- package/dist/components/otp.d.ts +1 -1
- package/dist/components/otp.js +7 -2
- package/dist/components/pipeline.d.ts +55 -0
- package/dist/components/pipeline.js +51 -0
- package/dist/components/quota.d.ts +57 -0
- package/dist/components/quota.js +40 -0
- package/dist/components/relativeTime.d.ts +24 -0
- package/dist/components/relativeTime.js +56 -0
- package/dist/components/reveal.d.ts +18 -0
- package/dist/components/reveal.js +32 -0
- package/dist/components/scramble.d.ts +68 -0
- package/dist/components/scramble.js +58 -0
- package/dist/components/shaderBackdrop.d.ts +20 -0
- package/dist/components/shaderBackdrop.js +156 -0
- package/dist/components/slider.d.ts +5 -0
- package/dist/components/slider.js +24 -0
- package/dist/components/slotText.d.ts +2 -0
- package/dist/components/slotText.js +9 -0
- package/dist/components/status.d.ts +14 -0
- package/dist/components/status.js +22 -0
- package/dist/components/tableFacets.d.ts +8 -0
- package/dist/components/tableFacets.js +19 -0
- package/dist/components/textSplit.d.ts +17 -0
- package/dist/components/textSplit.js +24 -0
- package/dist/components/timeSpan.d.ts +78 -0
- package/dist/components/timeSpan.js +85 -0
- package/dist/components/tone.d.ts +43 -0
- package/dist/components/tone.js +82 -0
- package/dist/components/tour.js +3 -2
- package/dist/components/typewriter.d.ts +36 -0
- package/dist/components/typewriter.js +53 -0
- package/dist/components/videoBackdrop.js +5 -6
- package/dist/composables/easing.d.ts +22 -1
- package/dist/composables/easing.js +42 -1
- package/dist/composables/pseudoLocale.d.ts +15 -0
- package/dist/composables/pseudoLocale.js +96 -0
- package/dist/composables/scroll.js +5 -3
- package/dist/composables/useClipboard.d.ts +4 -1
- package/dist/composables/useClipboard.js +12 -2
- package/dist/composables/useField.d.ts +8 -0
- package/dist/composables/useField.js +5 -0
- package/dist/composables/useForm.js +19 -5
- package/dist/composables/useHintSystem.d.ts +4 -0
- package/dist/composables/useHintSystem.js +33 -1
- package/dist/composables/useHints.js +9 -3
- package/dist/composables/useInView.d.ts +11 -0
- package/dist/composables/useInView.js +39 -0
- package/dist/composables/useLoadingGate.d.ts +8 -0
- package/dist/composables/useLoadingGate.js +38 -0
- package/dist/composables/useLpConfig.d.ts +10 -0
- package/dist/composables/useLpConfig.js +11 -1
- package/dist/composables/useMediaQuery.js +3 -1
- package/dist/composables/useNow.d.ts +16 -0
- package/dist/composables/useNow.js +39 -0
- package/dist/composables/usePersisted.js +14 -7
- package/dist/composables/usePillTransition.d.ts +5 -2
- package/dist/composables/usePillTransition.js +4 -3
- package/dist/composables/usePointerFrame.d.ts +18 -0
- package/dist/composables/usePointerFrame.js +31 -0
- package/dist/composables/useReducedMotion.d.ts +2 -0
- package/dist/composables/useReducedMotion.js +7 -0
- package/dist/composables/useRepeater.d.ts +17 -0
- package/dist/composables/useRepeater.js +31 -0
- package/dist/composables/useResizeObserver.d.ts +8 -0
- package/dist/composables/useResizeObserver.js +33 -0
- package/dist/composables/useRevealedValue.d.ts +31 -0
- package/dist/composables/useRevealedValue.js +26 -0
- package/dist/composables/useScramble.d.ts +42 -0
- package/dist/composables/useScramble.js +76 -0
- package/dist/composables/useShift.js +2 -10
- package/dist/composables/useSpotlight.d.ts +18 -0
- package/dist/composables/useSpotlight.js +53 -0
- package/dist/composables/useTilt.js +26 -18
- package/dist/composables/useTween.d.ts +43 -0
- package/dist/composables/useTween.js +69 -0
- package/dist/composables/useView.d.ts +18 -0
- package/dist/composables/useView.js +61 -0
- package/dist/icons-all.js +1 -1
- package/dist/index.d.ts +98 -1
- package/dist/index.js +262 -104
- package/dist/theme/define.d.ts +12 -0
- package/dist/theme/studio.d.ts +90 -0
- package/package.json +5 -2
- package/src/component-names.ts +33 -0
- package/src/components/AttentionDot.vue +27 -0
- package/src/components/FieldWrapper.vue +38 -0
- package/src/components/LayoutNode.vue +5 -9
- package/src/components/LegendSwatch.vue +15 -0
- package/src/components/LoaderMark.vue +90 -0
- package/src/components/LpActionBar.vue +12 -20
- package/src/components/LpActivityLine.vue +186 -0
- package/src/components/LpAlert.vue +54 -24
- package/src/components/LpAppShell.vue +7 -11
- package/src/components/LpAutocomplete.vue +16 -14
- package/src/components/LpAvatar.vue +17 -2
- package/src/components/LpBadge.vue +77 -13
- package/src/components/LpBreadcrumbs.vue +101 -35
- package/src/components/LpButton.vue +15 -3
- package/src/components/LpCard.vue +30 -7
- package/src/components/LpChart.vue +152 -156
- package/src/components/LpCheckbox.vue +10 -4
- package/src/components/LpCodeBlock.vue +11 -19
- package/src/components/LpCodeDisplay.vue +228 -0
- package/src/components/LpCollapse.vue +162 -0
- package/src/components/LpColorPicker.vue +10 -1
- package/src/components/LpCommandPalette.vue +38 -24
- package/src/components/LpContextMenu.vue +10 -1
- package/src/components/LpCopyButton.vue +185 -0
- package/src/components/LpCountdown.vue +308 -0
- package/src/components/LpDataList.vue +154 -0
- package/src/components/LpDatePicker.vue +53 -104
- package/src/components/LpDateRangePicker.vue +49 -95
- package/src/components/LpDisclosure.vue +58 -36
- package/src/components/LpDock.vue +274 -0
- package/src/components/LpDrawer.vue +10 -1
- package/src/components/LpDropdownMenu.vue +10 -1
- package/src/components/LpDropzone.vue +34 -13
- package/src/components/LpEditable.vue +293 -0
- package/src/components/LpFileTree.vue +5 -1
- package/src/components/LpFileTreeNode.vue +25 -50
- package/src/components/LpFormField.vue +22 -3
- package/src/components/LpFrame.vue +200 -0
- package/src/components/LpGauge.vue +287 -0
- package/src/components/LpGlowBorder.vue +60 -0
- package/src/components/LpHintExample.vue +14 -38
- package/src/components/LpHintLayer.vue +13 -3
- package/src/components/LpHoverCard.vue +175 -0
- package/src/components/LpIdenticon.vue +69 -0
- package/src/components/LpImageEditor.vue +15 -18
- package/src/components/LpInfraNode.vue +27 -16
- package/src/components/LpInput.vue +30 -16
- package/src/components/LpLightbox.vue +44 -23
- package/src/components/LpLoader.vue +145 -0
- package/src/components/LpLogViewer.vue +311 -82
- package/src/components/LpMagnetic.vue +97 -0
- package/src/components/LpMapPicker.vue +26 -28
- package/src/components/LpMasonry.vue +247 -0
- package/src/components/LpModal.vue +10 -1
- package/src/components/LpNotificationBell.vue +33 -49
- package/src/components/LpNumberField.vue +79 -14
- package/src/components/LpNumberFlow.vue +10 -35
- package/src/components/LpOtpInput.vue +7 -2
- package/src/components/LpPagination.vue +38 -4
- package/src/components/LpPalettePreview.vue +2 -7
- package/src/components/LpPasswordInput.vue +16 -14
- package/src/components/LpPhoneInput.vue +12 -3
- package/src/components/LpPie.vue +197 -36
- package/src/components/LpPipeline.vue +366 -0
- package/src/components/LpPopover.vue +10 -1
- package/src/components/LpProgress.vue +22 -84
- package/src/components/LpQuota.vue +197 -0
- package/src/components/LpRangeSlider.vue +5 -1
- package/src/components/LpRelativeTime.vue +90 -0
- package/src/components/LpRepeater.vue +80 -0
- package/src/components/LpRevealOnScroll.vue +125 -0
- package/src/components/LpScramble.vue +107 -0
- package/src/components/LpSecretField.vue +313 -0
- package/src/components/LpSegmented.vue +3 -10
- package/src/components/LpSelect.vue +78 -64
- package/src/components/LpShaderBackdrop.vue +434 -0
- package/src/components/LpShinyText.vue +139 -0
- package/src/components/LpSidebar.vue +2 -0
- package/src/components/LpSlider.vue +5 -1
- package/src/components/LpSparkline.vue +55 -37
- package/src/components/LpSpotlight.vue +51 -0
- package/src/components/LpStat.vue +6 -2
- package/src/components/LpStatus.vue +127 -0
- package/src/components/LpStepMark.vue +138 -0
- package/src/components/LpStepper.vue +37 -43
- package/src/components/LpSwap.vue +2 -2
- package/src/components/LpSwitch.vue +15 -22
- package/src/components/LpTable.vue +47 -63
- package/src/components/LpTableFilter.vue +1 -0
- package/src/components/LpTableOfContents.vue +53 -29
- package/src/components/LpTabs.vue +10 -21
- package/src/components/LpTagsInput.vue +53 -37
- package/src/components/LpTextReveal.vue +236 -0
- package/src/components/LpTextarea.vue +11 -11
- package/src/components/LpThemeStudio.vue +216 -0
- package/src/components/LpThemeStudioSection.vue +16 -0
- package/src/components/LpThemeSwitcher.vue +156 -47
- package/src/components/LpTimeField.vue +9 -1
- package/src/components/LpToaster.vue +63 -83
- package/src/components/LpTooltip.vue +10 -1
- package/src/components/LpTour.vue +24 -13
- package/src/components/LpTruncate.vue +135 -0
- package/src/components/LpTypewriter.vue +236 -0
- package/src/components/LpUptimeBar.vue +6 -5
- package/src/components/LpVideoBackdrop.vue +15 -13
- package/src/components/OptionContent.vue +17 -0
- package/src/components/PickerField.vue +58 -0
- package/src/components/RevealToggle.vue +51 -0
- package/src/components/StepConnector.vue +54 -0
- package/src/components/TourCard.vue +29 -16
- package/src/components/badge.ts +8 -0
- package/src/components/chart.ts +8 -23
- package/src/components/dateRange.ts +25 -0
- package/src/components/dock.ts +31 -0
- package/src/components/dropdown.ts +15 -3
- package/src/components/fieldText.ts +95 -0
- package/src/components/fileTree.ts +19 -21
- package/src/components/format.ts +136 -0
- package/src/components/identicon.ts +160 -0
- package/src/components/masonry.ts +73 -0
- package/src/components/meter.ts +122 -0
- package/src/components/otp.ts +14 -3
- package/src/components/pipeline.ts +101 -0
- package/src/components/quota.ts +111 -0
- package/src/components/relativeTime.ts +118 -0
- package/src/components/reveal.ts +56 -0
- package/src/components/scramble.ts +138 -0
- package/src/components/shaderBackdrop.ts +208 -0
- package/src/components/slider.ts +30 -0
- package/src/components/slotText.ts +13 -0
- package/src/components/status.ts +46 -0
- package/src/components/tableFacets.ts +25 -0
- package/src/components/textSplit.ts +55 -0
- package/src/components/timeSpan.ts +183 -0
- package/src/components/tone.ts +144 -0
- package/src/components/tour.ts +3 -2
- package/src/components/typewriter.ts +104 -0
- package/src/components/videoBackdrop.ts +7 -6
- package/src/composables/easing.ts +66 -1
- package/src/composables/pseudoLocale.ts +105 -0
- package/src/composables/scroll.ts +6 -3
- package/src/composables/useClipboard.ts +25 -3
- package/src/composables/useField.ts +12 -0
- package/src/composables/useForm.ts +27 -6
- package/src/composables/useHintSystem.ts +40 -0
- package/src/composables/useHints.ts +14 -3
- package/src/composables/useInView.ts +61 -0
- package/src/composables/useLoadingGate.ts +63 -0
- package/src/composables/useLpConfig.ts +20 -1
- package/src/composables/useMediaQuery.ts +6 -2
- package/src/composables/useNow.ts +84 -0
- package/src/composables/usePersisted.ts +19 -8
- package/src/composables/usePillTransition.ts +21 -13
- package/src/composables/usePointerFrame.ts +72 -0
- package/src/composables/useReducedMotion.ts +22 -0
- package/src/composables/useRepeater.ts +44 -0
- package/src/composables/useResizeObserver.ts +59 -0
- package/src/composables/useRevealedValue.ts +84 -0
- package/src/composables/useScramble.ts +152 -0
- package/src/composables/useShift.ts +10 -16
- package/src/composables/useSpotlight.ts +82 -0
- package/src/composables/useTilt.ts +40 -23
- package/src/composables/useTween.ts +149 -0
- package/src/composables/useView.ts +93 -0
- package/src/index.css +1 -0
- package/src/index.ts +143 -1
- package/src/kit-icons.ts +1 -1
- package/src/theme/define.ts +65 -0
- package/src/theme/studio.ts +202 -0
- package/src/tokens/effects.css +151 -0
- package/src/tokens/tokens.css +131 -39
- package/src/tokens/utilities.css +81 -0
- package/dist/assets/LpTabs-Bk7v4bZz.css +0 -18
- package/dist/chunks/LpAlert-BdvxvcWE.js +0 -85
- package/dist/chunks/LpBadge-Fe0D1bYx.js +0 -62
- package/dist/chunks/LpBreadcrumbs-rzOKkLiI.js +0 -98
- package/dist/chunks/LpDatePicker-BMfM454Y.js +0 -243
- package/dist/chunks/LpDateRangePicker-CNb9X3eL.js +0 -195
- package/dist/chunks/LpNumberField-DO1ufKvE.js +0 -107
- package/dist/chunks/LpStepper-C2slwObu.js +0 -90
- package/dist/chunks/LpSwitch-CZy9_IoA.js +0 -132
- package/dist/chunks/LpThemeSwitcher-CDoziW0z.js +0 -166
- package/dist/chunks/TourCard-BKI7X9-r.js +0 -105
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
// The consumer's `class` is merged into the root's own (below) rather than
|
|
3
|
+
// appended to it, so opt out of the automatic pass-through that would add it
|
|
4
|
+
// a second time, unmerged.
|
|
5
|
+
export default { inheritAttrs: false }
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<script setup lang="ts">
|
|
9
|
+
/*
|
|
10
|
+
* The kit's loading indicator: a spinner, three dots or an indeterminate bar.
|
|
11
|
+
*
|
|
12
|
+
* Every component that waits used to draw its own (a lucide loader-circle
|
|
13
|
+
* with `animate-spin`, toned by hand), so each one blinked on fast loads in
|
|
14
|
+
* its own way and none told a screen reader anything. This one owns the three
|
|
15
|
+
* things they all needed and none had:
|
|
16
|
+
*
|
|
17
|
+
* - timing: `delay` before it appears, so a load that finishes quickly shows
|
|
18
|
+
* nothing at all, and `minVisible` once it has, so it never flashes
|
|
19
|
+
* (see useLoadingGate);
|
|
20
|
+
* - a status: role="status" with a polite label, so "loading" is announced
|
|
21
|
+
* rather than only drawn;
|
|
22
|
+
* - reduced motion: a spinner that simply stops reads as a frozen page, so
|
|
23
|
+
* under reduced motion every variant breathes (a slow fade) instead of
|
|
24
|
+
* moving — a change of state the eye can still see, without travel.
|
|
25
|
+
*
|
|
26
|
+
* <LpLoader /> inline spinner
|
|
27
|
+
* <LpLoader variant="dots" label="Connecting" />
|
|
28
|
+
* <LpLoader :active="loading"><Results /></LpLoader> placeholder → content
|
|
29
|
+
*
|
|
30
|
+
* Determinate progress (a known fraction) is LpProgress; this is for waits
|
|
31
|
+
* whose length is unknown.
|
|
32
|
+
*/
|
|
33
|
+
import { computed, useSlots } from "vue"
|
|
34
|
+
import { useLabels } from "../composables/useLpConfig"
|
|
35
|
+
import { useLoadingGate } from "../composables/useLoadingGate"
|
|
36
|
+
import { useMergedAttrs } from "../composables/useMergedClass"
|
|
37
|
+
import LoaderMark from "./LoaderMark.vue"
|
|
38
|
+
import LpSwap from "./LpSwap.vue"
|
|
39
|
+
import { toneLook, type ToneName } from "./tone"
|
|
40
|
+
|
|
41
|
+
export type LoaderVariant = "spinner" | "dots" | "bar"
|
|
42
|
+
export type LoaderSize = "inline" | "sm" | "md" | "lg"
|
|
43
|
+
/** `current` inherits the text colour around it; the rest are the kit's tones (tone.ts). */
|
|
44
|
+
export type LoaderTone = "current" | ToneName
|
|
45
|
+
export type LoaderLabels = { loading: string }
|
|
46
|
+
|
|
47
|
+
const props = withDefaults(
|
|
48
|
+
defineProps<{
|
|
49
|
+
/**
|
|
50
|
+
* `spinner` for a spot (a button, a row, a field); `dots` for something
|
|
51
|
+
* conversational (typing, connecting); `bar` for a region across its width
|
|
52
|
+
* (the top of a card or a page).
|
|
53
|
+
*/
|
|
54
|
+
variant?: LoaderVariant
|
|
55
|
+
/**
|
|
56
|
+
* `inline` sizes the mark from the font (a 1em spinner), so it fits a
|
|
57
|
+
* button or a line of text at whatever size that text is.
|
|
58
|
+
*/
|
|
59
|
+
size?: LoaderSize
|
|
60
|
+
/**
|
|
61
|
+
* `current` takes the surrounding text colour, which is what a loader
|
|
62
|
+
* inside a button or a coloured badge wants; the others pin a kit tone.
|
|
63
|
+
*/
|
|
64
|
+
tone?: LoaderTone
|
|
65
|
+
/**
|
|
66
|
+
* Whether work is under way. Off, the loader is not shown (or, with a
|
|
67
|
+
* default slot, the content is). Leave it on and mount the loader with
|
|
68
|
+
* `v-if` when it has nothing to swap with.
|
|
69
|
+
*/
|
|
70
|
+
active?: boolean
|
|
71
|
+
/**
|
|
72
|
+
* Ms of loading before anything appears. Most requests finish inside 150
|
|
73
|
+
* ms; a spinner for those is a blink, not information. 0 shows at once —
|
|
74
|
+
* the right call where the trigger already acknowledged the click (a
|
|
75
|
+
* button that faded its label).
|
|
76
|
+
*/
|
|
77
|
+
delay?: number
|
|
78
|
+
/** Ms the loader stays once shown, so a load ending just after it appeared does not blink it away. */
|
|
79
|
+
minVisible?: number
|
|
80
|
+
/**
|
|
81
|
+
* Visible text beside the indicator. Without it the indicator is still
|
|
82
|
+
* announced, with the `loading` label, to screen readers only.
|
|
83
|
+
*/
|
|
84
|
+
label?: string
|
|
85
|
+
/** Spinner only: draw the faint full circle the arc runs along. */
|
|
86
|
+
track?: boolean
|
|
87
|
+
labels?: Partial<LoaderLabels>
|
|
88
|
+
}>(),
|
|
89
|
+
{
|
|
90
|
+
variant: "spinner",
|
|
91
|
+
size: "md",
|
|
92
|
+
tone: "current",
|
|
93
|
+
active: true,
|
|
94
|
+
delay: 150,
|
|
95
|
+
minVisible: 400,
|
|
96
|
+
track: false,
|
|
97
|
+
},
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
const text = useLabels<LoaderLabels>("loader", { loading: "Loading…" }, () => props.labels)
|
|
101
|
+
const shown = useLoadingGate(() => props.active, {
|
|
102
|
+
delay: () => props.delay,
|
|
103
|
+
minVisible: () => props.minVisible,
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
const slots = useSlots()
|
|
107
|
+
const wraps = computed(() => !!slots.default)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
/*
|
|
111
|
+
* The consumer's class lands on the indicator's own box (the status element),
|
|
112
|
+
* so `class="w-40"` narrows a bar and `class="text-lg"` scales an `inline`
|
|
113
|
+
* loader, rather than styling a wrapper around them.
|
|
114
|
+
*/
|
|
115
|
+
const { class: rootClass, attrs: rest } = useMergedAttrs(() => {
|
|
116
|
+
const tone = props.tone === "current" ? "" : toneLook(props.tone).text
|
|
117
|
+
if (props.variant === "bar") {
|
|
118
|
+
return `flex w-full min-w-12 flex-col gap-1.5 ${tone}`
|
|
119
|
+
}
|
|
120
|
+
return `inline-flex items-center gap-2 align-middle ${tone}`
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
const spoken = computed(() => props.label || text.value.loading)
|
|
124
|
+
</script>
|
|
125
|
+
|
|
126
|
+
<template>
|
|
127
|
+
<div v-if="wraps" :aria-busy="shown ? 'true' : undefined">
|
|
128
|
+
<LpSwap :swap-key="shown ? 'loading' : 'content'">
|
|
129
|
+
<div v-if="shown" class="flex justify-center py-8">
|
|
130
|
+
<LoaderMark :class="rootClass" v-bind="rest" :variant="variant" :size="size" :track="track" :label="label" :spoken="spoken" />
|
|
131
|
+
</div>
|
|
132
|
+
<slot v-else />
|
|
133
|
+
</LpSwap>
|
|
134
|
+
</div>
|
|
135
|
+
|
|
136
|
+
<Transition
|
|
137
|
+
v-else
|
|
138
|
+
enter-active-class="transition-opacity duration-(--duration-fast) ease-(--ease-emphasized) motion-reduce:transition-none"
|
|
139
|
+
enter-from-class="opacity-0"
|
|
140
|
+
leave-active-class="transition-opacity duration-(--duration-fast) ease-out motion-reduce:transition-none"
|
|
141
|
+
leave-to-class="opacity-0"
|
|
142
|
+
>
|
|
143
|
+
<LoaderMark v-if="shown" :class="rootClass" v-bind="rest" :variant="variant" :size="size" :track="track" :label="label" :spoken="spoken" />
|
|
144
|
+
</Transition>
|
|
145
|
+
</template>
|
|
@@ -25,16 +25,21 @@ import {
|
|
|
25
25
|
watch,
|
|
26
26
|
} from "vue"
|
|
27
27
|
import { usePersisted } from "../composables/usePersisted"
|
|
28
|
-
import { prefersReducedMotion } from "../composables/easing"
|
|
28
|
+
import { durationToken, prefersReducedMotion, tokenEase } from "../composables/easing"
|
|
29
29
|
import { useClipboard } from "../composables/useClipboard"
|
|
30
30
|
import { useHotkeys } from "../composables/useHotkeys"
|
|
31
|
+
import LpBadge from "./LpBadge.vue"
|
|
31
32
|
import LpContextMenu, { type ContextMenuItemDef } from "./LpContextMenu.vue"
|
|
32
33
|
import LpEmptyState from "./LpEmptyState.vue"
|
|
33
34
|
import LpIcon from "./LpIcon.vue"
|
|
35
|
+
import LpLoader from "./LpLoader.vue"
|
|
36
|
+
import LpInput from "./LpInput.vue"
|
|
34
37
|
import LpScrollArea from "./LpScrollArea.vue"
|
|
35
38
|
import { useMergedAttrs } from "../composables/useMergedClass"
|
|
36
39
|
import { useLabels } from "../composables/useLpConfig"
|
|
40
|
+
import { useResizeObserver } from "../composables/useResizeObserver"
|
|
37
41
|
import { countLevels, matchPositions, ringWindow, stepMatch } from "./logSearch"
|
|
42
|
+
import { TONES, toneLook, type ToneName } from "./tone"
|
|
38
43
|
|
|
39
44
|
export interface LogViewerLabels {
|
|
40
45
|
[key: string]: string
|
|
@@ -225,16 +230,21 @@ const text = useLabels<LogViewerLabels>(
|
|
|
225
230
|
// red (fatal gets a filled chip to stand apart from plain error).
|
|
226
231
|
// `sel` tints ::selection in the row's semantic colour (info→brand, warn→accent,
|
|
227
232
|
// error/fatal→danger) via Tailwind's `selection:` variant — the highlight then
|
|
228
|
-
// matches the level instead of the browser default.
|
|
229
|
-
//
|
|
233
|
+
// matches the level instead of the browser default. The toned levels read the
|
|
234
|
+
// kit's tones (tone.ts, where the classes are spelled out whole for Tailwind's
|
|
235
|
+
// scan); trace and debug are quieter than any tone, two steps of grey.
|
|
236
|
+
const toned = (tone: ToneName) => {
|
|
237
|
+
const look = toneLook(tone)
|
|
238
|
+
return { rail: look.bg, text: "text-ink", chip: look.text, sel: look.selection }
|
|
239
|
+
}
|
|
230
240
|
const levelMeta: Record<LogLevel, { rail: string; text: string; chip: string; sel: string }> = {
|
|
231
|
-
trace: { rail: "bg-line-strong", text: "text-muted", chip: "text-muted", sel:
|
|
241
|
+
trace: { rail: "bg-line-strong", text: "text-muted", chip: "text-muted", sel: TONES.neutral.selection },
|
|
232
242
|
debug: { rail: "bg-line-strong", text: "text-muted-strong", chip: "text-muted-strong", sel: "selection:bg-muted-strong/40" },
|
|
233
|
-
info:
|
|
234
|
-
success:
|
|
235
|
-
warn:
|
|
236
|
-
error:
|
|
237
|
-
fatal: {
|
|
243
|
+
info: toned("info"),
|
|
244
|
+
success: toned("success"),
|
|
245
|
+
warn: toned("warning"),
|
|
246
|
+
error: toned("error"),
|
|
247
|
+
fatal: { ...toned("error"), chip: `rounded-xs px-1 text-ink-inverse ${TONES.danger.bg}` },
|
|
238
248
|
}
|
|
239
249
|
|
|
240
250
|
function metaFor(level?: LogLevel) {
|
|
@@ -511,7 +521,7 @@ function revealMatch(position: number | undefined) {
|
|
|
511
521
|
el.querySelector<HTMLElement>(`[data-log-row="${n}"]`)?.scrollIntoView({ block: "center", behavior })
|
|
512
522
|
}
|
|
513
523
|
|
|
514
|
-
const searchEl = ref<
|
|
524
|
+
const searchEl = ref<InstanceType<typeof LpInput> | null>(null)
|
|
515
525
|
|
|
516
526
|
function onSearchKeydown(event: KeyboardEvent) {
|
|
517
527
|
if (event.isComposing) return
|
|
@@ -727,7 +737,12 @@ let topArmed = true
|
|
|
727
737
|
|
|
728
738
|
function onScroll(e: Event) {
|
|
729
739
|
const el = e.target as HTMLElement
|
|
730
|
-
|
|
740
|
+
// The glide's own writes are not the user leaving the tail: a burst taller
|
|
741
|
+
// than NEAR would read as "scrolled up" on its first frame and unpin it.
|
|
742
|
+
// Anything the user does to scroll cancels the glide before this runs. Nor
|
|
743
|
+
// may a scroll event the glide queued before an upward wheel re-pin the
|
|
744
|
+
// tail the wheel just left (see `leaveTail`).
|
|
745
|
+
if (!glide && performance.now() - leftAt > LEAVE_GRACE_MS) pinned.value = atBottom(el)
|
|
731
746
|
// Feed the virtual window. Reading clientHeight here keeps it in sync with
|
|
732
747
|
// runtime resizes (drawer drag, window resize) without a ResizeObserver.
|
|
733
748
|
scrollTop.value = el.scrollTop
|
|
@@ -743,38 +758,171 @@ function onScroll(e: Event) {
|
|
|
743
758
|
}
|
|
744
759
|
}
|
|
745
760
|
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
761
|
+
/*
|
|
762
|
+
* Keep the line being read where it is when the lines change under it.
|
|
763
|
+
*
|
|
764
|
+
* Anchored on a row, not on the total height. Measuring how much scrollHeight
|
|
765
|
+
* grew and adding all of it to scrollTop is right for older lines prepended
|
|
766
|
+
* above, but a line appended BELOW grows it just the same, so every pushed
|
|
767
|
+
* line dragged a reader who had scrolled up one row further down. The absolute
|
|
768
|
+
* write also cancelled the browser's own animated wheel scroll, so with a busy
|
|
769
|
+
* stream a wheel turn up never got anywhere.
|
|
770
|
+
*
|
|
771
|
+
* The first row in view is remembered with its offset; afterwards scrollTop
|
|
772
|
+
* moves by however far that row was displaced, and is not written at all when
|
|
773
|
+
* it stayed put. Rows above that leave (a capped stream) are covered the same
|
|
774
|
+
* way.
|
|
775
|
+
*/
|
|
776
|
+
let anchorRow: HTMLElement | null = null
|
|
777
|
+
let anchorOffset = 0
|
|
778
|
+
|
|
779
|
+
function firstRowInView(el: HTMLElement): HTMLElement | null {
|
|
780
|
+
const top = el.getBoundingClientRect().top
|
|
781
|
+
for (const row of el.querySelectorAll<HTMLElement>("[data-log-row]")) {
|
|
782
|
+
if (row.getBoundingClientRect().bottom > top) return row
|
|
783
|
+
}
|
|
784
|
+
return null
|
|
785
|
+
}
|
|
786
|
+
|
|
751
787
|
function captureScrollAnchor() {
|
|
752
788
|
const el = viewport()
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
prevScrollTop = el.scrollTop
|
|
789
|
+
anchorRow = el ? firstRowInView(el) : null
|
|
790
|
+
if (el && anchorRow) anchorOffset = anchorRow.getBoundingClientRect().top - el.getBoundingClientRect().top
|
|
756
791
|
}
|
|
792
|
+
|
|
757
793
|
function restoreScrollAnchor() {
|
|
758
794
|
const el = viewport()
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
if (
|
|
795
|
+
const row = anchorRow
|
|
796
|
+
anchorRow = null
|
|
797
|
+
if (!el || !row?.isConnected) return
|
|
798
|
+
const drift = row.getBoundingClientRect().top - el.getBoundingClientRect().top - anchorOffset
|
|
799
|
+
if (Math.abs(drift) >= 1) el.scrollTop += drift
|
|
762
800
|
}
|
|
763
801
|
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
802
|
+
/*
|
|
803
|
+
* Follow the tail by easing scrollTop toward the bottom over a frame loop.
|
|
804
|
+
*
|
|
805
|
+
* The browser's own smooth scroll covered one 20px row in three frames, so a
|
|
806
|
+
* pushed line still read as a jolt; it also cannot be retargeted, and a line
|
|
807
|
+
* arriving mid-scroll restarted it from wherever it stood. Here the target is
|
|
808
|
+
* re-read every frame, so lines landing during the glide (or rows collapsing
|
|
809
|
+
* above it) only move where it ends, and a fresh change restarts the easing
|
|
810
|
+
* from the position actually on screen.
|
|
811
|
+
*
|
|
812
|
+
* A jump of more than a viewport starts one viewport short of the end: easing
|
|
813
|
+
* across a whole burst is a smear of text nobody can follow, and snapping
|
|
814
|
+
* there outright was the jolt this replaces.
|
|
815
|
+
*/
|
|
816
|
+
let glide = 0
|
|
817
|
+
|
|
818
|
+
function stopGlide() {
|
|
819
|
+
if (glide) cancelAnimationFrame(glide)
|
|
820
|
+
glide = 0
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
/*
|
|
824
|
+
* Where "the bottom" is: the newest row that is staying, not the end of the
|
|
825
|
+
* scroll height. Rows still collapsing out under it (a window that slid back,
|
|
826
|
+
* a filter that dropped the tail) briefly make the list overflow, and gliding
|
|
827
|
+
* down into them scrolled a list that fits by a few pixels and back again as
|
|
828
|
+
* they closed.
|
|
829
|
+
*/
|
|
830
|
+
function tailEnd(el: HTMLElement): number {
|
|
831
|
+
const max = el.scrollHeight - el.clientHeight
|
|
832
|
+
const list = el.querySelector("[data-log-row]")?.parentElement
|
|
833
|
+
let row = list?.lastElementChild ?? null
|
|
834
|
+
const below = row ? max + el.clientHeight - contentBottom(el, row) : 0
|
|
835
|
+
while (row && (!row.hasAttribute("data-log-row") || row.classList.contains("lp-log-row-leave-active"))) {
|
|
836
|
+
row = row.previousElementSibling
|
|
837
|
+
}
|
|
838
|
+
if (!row) return max
|
|
839
|
+
return Math.max(0, Math.min(max, contentBottom(el, row) + below - el.clientHeight))
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
function contentBottom(el: HTMLElement, row: Element): number {
|
|
843
|
+
return row.getBoundingClientRect().bottom - el.getBoundingClientRect().top + el.scrollTop
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
function rideToBottom() {
|
|
768
847
|
const el = viewport()
|
|
769
848
|
if (!el) return
|
|
770
|
-
|
|
771
|
-
const
|
|
772
|
-
|
|
849
|
+
stopGlide()
|
|
850
|
+
const end = () => tailEnd(el)
|
|
851
|
+
if (prefersReducedMotion()) {
|
|
852
|
+
el.scrollTop = end()
|
|
853
|
+
return
|
|
854
|
+
}
|
|
855
|
+
const from = Math.max(el.scrollTop, end() - el.clientHeight)
|
|
856
|
+
if (Math.abs(end() - from) < 1) return
|
|
857
|
+
el.scrollTop = from
|
|
858
|
+
const ms = durationToken("duration-medium")
|
|
859
|
+
const ease = tokenEase("ease-emphasized")
|
|
860
|
+
const started = performance.now()
|
|
861
|
+
const step = (now: number) => {
|
|
862
|
+
const t = Math.min(1, Math.max(0, (now - started) / ms))
|
|
863
|
+
el.scrollTop = from + (end() - from) * ease(t)
|
|
864
|
+
glide = t < 1 ? requestAnimationFrame(step) : 0
|
|
865
|
+
}
|
|
866
|
+
glide = requestAnimationFrame(step)
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
/*
|
|
870
|
+
* The user reaching for the stream ends the glide at once, and an upward
|
|
871
|
+
* gesture leaves the tail there and then rather than when its scroll lands.
|
|
872
|
+
*
|
|
873
|
+
* Waiting for the scroll event was not enough: a wheel turn is itself animated
|
|
874
|
+
* by the browser, the next pushed line arrived before it had moved past NEAR,
|
|
875
|
+
* the tail still counted as pinned, and the glide's first write cancelled the
|
|
876
|
+
* wheel's own animation. With lines every ~100ms the stream simply refused to
|
|
877
|
+
* be scrolled up. A pointer or finger held on the stream (dragging the
|
|
878
|
+
* scrollbar, selecting text) holds the tail for the same reason.
|
|
879
|
+
*/
|
|
880
|
+
let holding = false
|
|
881
|
+
// Long enough for a scroll event already queued by the glide to arrive.
|
|
882
|
+
const LEAVE_GRACE_MS = 250
|
|
883
|
+
let leftAt = -Infinity
|
|
884
|
+
|
|
885
|
+
function leaveTail() {
|
|
886
|
+
stopGlide()
|
|
887
|
+
leftAt = performance.now()
|
|
888
|
+
const el = viewport()
|
|
889
|
+
if (el && el.scrollTop > 0) pinned.value = false
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
function onWheel(event: WheelEvent) {
|
|
893
|
+
if (event.deltaY < 0) leaveTail()
|
|
894
|
+
else stopGlide()
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
const UPWARD_KEYS = new Set(["ArrowUp", "PageUp", "Home"])
|
|
898
|
+
|
|
899
|
+
function onKeydown(event: KeyboardEvent) {
|
|
900
|
+
const field = event.target instanceof HTMLElement && event.target.closest("input, textarea, [contenteditable]")
|
|
901
|
+
if (!field && UPWARD_KEYS.has(event.key)) leaveTail()
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
function release() {
|
|
905
|
+
holding = false
|
|
906
|
+
window.removeEventListener("pointerup", release)
|
|
907
|
+
window.removeEventListener("pointercancel", release)
|
|
908
|
+
window.removeEventListener("touchend", release)
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
function hold(event: Event) {
|
|
912
|
+
// The scroll area's root, so its scrollbar (a sibling of the viewport)
|
|
913
|
+
// counts, and the toolbar and jump pill above it do not.
|
|
914
|
+
const area = viewport()?.parentElement
|
|
915
|
+
if (!area || !(event.target instanceof Node) || !area.contains(event.target)) return
|
|
916
|
+
stopGlide()
|
|
917
|
+
holding = true
|
|
918
|
+
window.addEventListener("pointerup", release)
|
|
919
|
+
window.addEventListener("pointercancel", release)
|
|
920
|
+
window.addEventListener("touchend", release)
|
|
773
921
|
}
|
|
774
922
|
|
|
775
923
|
function scrollToBottom() {
|
|
776
924
|
current.value = -1
|
|
777
|
-
rideToBottom(
|
|
925
|
+
rideToBottom()
|
|
778
926
|
pinned.value = true
|
|
779
927
|
}
|
|
780
928
|
|
|
@@ -802,8 +950,8 @@ watch(
|
|
|
802
950
|
linesSignal,
|
|
803
951
|
async () => {
|
|
804
952
|
await nextTick()
|
|
805
|
-
if (props.tail && pinned.value && current.value < 0) {
|
|
806
|
-
|
|
953
|
+
if (props.tail && pinned.value && !holding && current.value < 0) {
|
|
954
|
+
rideToBottom()
|
|
807
955
|
} else {
|
|
808
956
|
restoreScrollAnchor()
|
|
809
957
|
}
|
|
@@ -818,39 +966,77 @@ const showJump = computed(() => props.tail && !pinned.value && props.lines.lengt
|
|
|
818
966
|
// collapsed to a single row, so there was nothing to scroll, and `onScroll` —
|
|
819
967
|
// the only other place that refreshed the height — could never fire to correct
|
|
820
968
|
// it. The list looked stuck and wouldn't scroll at all.
|
|
821
|
-
let viewportResize: ResizeObserver | null = null
|
|
822
|
-
|
|
823
969
|
function measureViewport() {
|
|
824
970
|
const el = viewport()
|
|
825
971
|
if (el) viewportHeight.value = el.clientHeight
|
|
826
972
|
}
|
|
973
|
+
useResizeObserver(viewport, measureViewport)
|
|
827
974
|
|
|
828
975
|
onMounted(() => {
|
|
829
976
|
measureViewport()
|
|
830
977
|
const el = viewport()
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
}
|
|
978
|
+
// A tailing viewer opens on its newest lines. Opening at the top left the
|
|
979
|
+
// first pushed line to haul the whole history past in one go.
|
|
980
|
+
if (el && props.tail) el.scrollTop = el.scrollHeight
|
|
835
981
|
})
|
|
836
982
|
|
|
837
983
|
onBeforeUnmount(() => {
|
|
838
|
-
|
|
839
|
-
|
|
984
|
+
stopGlide()
|
|
985
|
+
release()
|
|
840
986
|
})
|
|
841
987
|
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
988
|
+
/*
|
|
989
|
+
* Enter / leave / move for the full-render TransitionGroup, bound via v-bind so
|
|
990
|
+
* the same list element can fall back to a plain <ol> when virtualised (a
|
|
991
|
+
* component :is can't carry TransitionGroup-only props inertly otherwise).
|
|
992
|
+
*
|
|
993
|
+
* Named classes from the <style> block rather than Tailwind utilities: every
|
|
994
|
+
* row carries `transition-colors` for its hover tint, and a utility that sets
|
|
995
|
+
* `transition` for the enter, leave or move lands in the same layer with the
|
|
996
|
+
* same specificity, so whichever Tailwind happened to emit last won. It was
|
|
997
|
+
* `transition-colors`: no row ever animated, a pushed line popped in and a
|
|
998
|
+
* dropped one took its height with it in a single frame.
|
|
999
|
+
*
|
|
1000
|
+
* A leaving row collapses from its own measured height. A fixed cap (it was
|
|
1001
|
+
* `max-h-8`) snapped a wrapped, three-line row down to the cap first.
|
|
1002
|
+
*/
|
|
845
1003
|
const transitionProps = {
|
|
846
1004
|
tag: "ol",
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
"
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
1005
|
+
name: "lp-log-row",
|
|
1006
|
+
onBeforeLeave: (el: Element) => {
|
|
1007
|
+
const row = el as HTMLElement
|
|
1008
|
+
row.style.setProperty("--lp-log-row-h", `${row.offsetHeight}px`)
|
|
1009
|
+
},
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
/*
|
|
1013
|
+
* Rows that just arrived while virtualised. The TransitionGroup is off there
|
|
1014
|
+
* (FLIP over thousands of rows is the cost virtualising avoids), but a pushed
|
|
1015
|
+
* line still should not pop in. Only the lines appended by the latest change
|
|
1016
|
+
* are marked, found by where the previous last line sits in the new array, so
|
|
1017
|
+
* a row scrolled into view later, or a whole replaced buffer, never plays it.
|
|
1018
|
+
* A burst taller than the viewport is not worth animating line by line.
|
|
1019
|
+
*/
|
|
1020
|
+
const FRESH_CAP = 40
|
|
1021
|
+
const freshLines = shallowRef<WeakSet<LogLine>>(new WeakSet())
|
|
1022
|
+
let lastSeen: LogLine | undefined
|
|
1023
|
+
watch(
|
|
1024
|
+
linesSignal,
|
|
1025
|
+
() => {
|
|
1026
|
+
const lines = props.lines
|
|
1027
|
+
const fresh = new WeakSet<LogLine>()
|
|
1028
|
+
const at = lastSeen ? lines.lastIndexOf(lastSeen) : -1
|
|
1029
|
+
if (at >= 0 && lines.length - 1 - at <= FRESH_CAP) {
|
|
1030
|
+
for (let i = at + 1; i < lines.length; i++) fresh.add(lines[i])
|
|
1031
|
+
}
|
|
1032
|
+
lastSeen = lines[lines.length - 1]
|
|
1033
|
+
freshLines.value = fresh
|
|
1034
|
+
},
|
|
1035
|
+
{ immediate: true },
|
|
1036
|
+
)
|
|
1037
|
+
function isFresh(n: number): boolean {
|
|
1038
|
+
const line = sourceLines.value[n]
|
|
1039
|
+
return virtualise.value && !!line && freshLines.value.has(line)
|
|
854
1040
|
}
|
|
855
1041
|
|
|
856
1042
|
// The viewer draws its own card frame and hides its overflow; a consumer
|
|
@@ -872,6 +1058,10 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(() =>
|
|
|
872
1058
|
v-bind="rest"
|
|
873
1059
|
@pointerenter="hovered = true"
|
|
874
1060
|
@pointerleave="hovered = false"
|
|
1061
|
+
@wheel.passive="onWheel"
|
|
1062
|
+
@touchstart.passive="hold"
|
|
1063
|
+
@pointerdown="hold"
|
|
1064
|
+
@keydown="onKeydown"
|
|
875
1065
|
>
|
|
876
1066
|
<!-- Says which state it is in, because a stream that has simply gone quiet
|
|
877
1067
|
looks exactly like a frozen one. -->
|
|
@@ -893,32 +1083,24 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(() =>
|
|
|
893
1083
|
v-if="toolbar"
|
|
894
1084
|
class="flex flex-wrap items-center gap-2 border-b border-line px-2 py-1.5 font-sans"
|
|
895
1085
|
>
|
|
896
|
-
<
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
aria-live="polite"
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
type="button"
|
|
915
|
-
class="rounded-xs p-0.5 text-muted outline-none hover:text-ink focus-visible:ring-2 focus-visible:ring-ring"
|
|
916
|
-
:aria-label="text.clearSearch"
|
|
917
|
-
@click="query = ''; searchEl?.focus()"
|
|
918
|
-
>
|
|
919
|
-
<LpIcon name="lucide:x" :size="12" />
|
|
920
|
-
</button>
|
|
921
|
-
</div>
|
|
1086
|
+
<LpInput
|
|
1087
|
+
ref="searchEl"
|
|
1088
|
+
v-model="query"
|
|
1089
|
+
type="search"
|
|
1090
|
+
size="sm"
|
|
1091
|
+
icon="lucide:search"
|
|
1092
|
+
clearable
|
|
1093
|
+
class="min-w-48 flex-1"
|
|
1094
|
+
:aria-label="text.search"
|
|
1095
|
+
:placeholder="text.search"
|
|
1096
|
+
:labels="{ clear: text.clearSearch }"
|
|
1097
|
+
@keydown="onSearchKeydown"
|
|
1098
|
+
>
|
|
1099
|
+
<template #trailing>
|
|
1100
|
+
<span v-if="term" class="shrink-0 text-[11px] tabular-nums text-muted" aria-live="polite">{{ matchLabel }}</span>
|
|
1101
|
+
</template>
|
|
1102
|
+
</LpInput>
|
|
1103
|
+
|
|
922
1104
|
<div class="flex items-center">
|
|
923
1105
|
<button
|
|
924
1106
|
type="button"
|
|
@@ -988,8 +1170,10 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(() =>
|
|
|
988
1170
|
v-if="loadingOlder"
|
|
989
1171
|
class="flex items-center justify-center gap-2 py-2 text-muted"
|
|
990
1172
|
>
|
|
991
|
-
|
|
992
|
-
|
|
1173
|
+
<!-- The loader speaks the row's words; the visible caption is hidden
|
|
1174
|
+
from screen readers so they are not read twice. -->
|
|
1175
|
+
<LpLoader size="inline" :delay="0" :labels="{ loading: text.loadingOlder }" class="text-[14px]" />
|
|
1176
|
+
<span class="text-[11px]" aria-hidden="true">{{ text.loadingOlder }}</span>
|
|
993
1177
|
</div>
|
|
994
1178
|
|
|
995
1179
|
<!-- ONE context menu wraps the whole list (not each row): @contextmenu
|
|
@@ -1026,7 +1210,7 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(() =>
|
|
|
1026
1210
|
:key="lineKey(n)"
|
|
1027
1211
|
:data-log-row="n"
|
|
1028
1212
|
class="group relative flex items-start gap-0 px-0 leading-5 transition-colors hover:bg-surface-soft/60"
|
|
1029
|
-
:class="[metaFor(line.level).sel, n === currentRow ? 'bg-accent/15' : '']"
|
|
1213
|
+
:class="[metaFor(line.level).sel, n === currentRow ? 'bg-accent/15' : '', isFresh(n) ? 'lp-log-row-fresh' : '']"
|
|
1030
1214
|
:aria-current="n === currentRow ? 'true' : undefined"
|
|
1031
1215
|
>
|
|
1032
1216
|
<!-- level rail -->
|
|
@@ -1091,12 +1275,13 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(() =>
|
|
|
1091
1275
|
enter-active-class="transition duration-[var(--duration-medium)] ease-[var(--ease-emphasized)]"
|
|
1092
1276
|
enter-from-class="scale-50 opacity-0"
|
|
1093
1277
|
>
|
|
1094
|
-
<
|
|
1278
|
+
<LpBadge
|
|
1095
1279
|
v-if="count > 1"
|
|
1096
1280
|
:key="count"
|
|
1097
|
-
|
|
1281
|
+
size="sm"
|
|
1282
|
+
class="ml-2 select-none tabular-nums"
|
|
1098
1283
|
:title="text.identical.replace('{n}', String(count))"
|
|
1099
|
-
>×{{ count }}</
|
|
1284
|
+
>×{{ count }}</LpBadge>
|
|
1100
1285
|
</Transition>
|
|
1101
1286
|
</span>
|
|
1102
1287
|
</li>
|
|
@@ -1137,3 +1322,47 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(() =>
|
|
|
1137
1322
|
</Transition>
|
|
1138
1323
|
</div>
|
|
1139
1324
|
</template>
|
|
1325
|
+
|
|
1326
|
+
<style>
|
|
1327
|
+
/*
|
|
1328
|
+
* Unscoped and namespaced, like LpRollingText: Vue applies these to the row
|
|
1329
|
+
* while it leaves, and an unlayered rule is also what lets them outrank the
|
|
1330
|
+
* row's own `transition-colors` utility (see `transitionProps`).
|
|
1331
|
+
*/
|
|
1332
|
+
/* Rises into place from just below, the direction a tail grows in (the kit's rise-in). */
|
|
1333
|
+
.lp-log-row-enter-active,
|
|
1334
|
+
.lp-log-row-fresh {
|
|
1335
|
+
--rise: 6px;
|
|
1336
|
+
animation: rise-in var(--duration-medium) var(--ease-emphasized);
|
|
1337
|
+
}
|
|
1338
|
+
|
|
1339
|
+
.lp-log-row-leave-active {
|
|
1340
|
+
overflow: hidden;
|
|
1341
|
+
animation: lp-log-row-out var(--duration-medium) var(--ease-emphasized) forwards;
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
.lp-log-row-move {
|
|
1345
|
+
transition: transform var(--duration-medium) var(--ease-emphasized);
|
|
1346
|
+
}
|
|
1347
|
+
|
|
1348
|
+
@keyframes lp-log-row-out {
|
|
1349
|
+
from {
|
|
1350
|
+
height: var(--lp-log-row-h, 1.25rem);
|
|
1351
|
+
}
|
|
1352
|
+
to {
|
|
1353
|
+
height: 0;
|
|
1354
|
+
opacity: 0;
|
|
1355
|
+
}
|
|
1356
|
+
}
|
|
1357
|
+
|
|
1358
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1359
|
+
.lp-log-row-enter-active,
|
|
1360
|
+
.lp-log-row-fresh,
|
|
1361
|
+
.lp-log-row-leave-active {
|
|
1362
|
+
animation: none;
|
|
1363
|
+
}
|
|
1364
|
+
.lp-log-row-move {
|
|
1365
|
+
transition: none;
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
</style>
|