@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,139 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
// The root class is merged with the consumer's (useMergedAttrs).
|
|
3
|
+
export default { inheritAttrs: false }
|
|
4
|
+
</script>
|
|
5
|
+
|
|
6
|
+
<script setup lang="ts">
|
|
7
|
+
/*
|
|
8
|
+
* Accent text with light moving through it.
|
|
9
|
+
*
|
|
10
|
+
* Two looks, for two jobs:
|
|
11
|
+
*
|
|
12
|
+
* "shine" — the text keeps its tone and a soft band sweeps across it now
|
|
13
|
+
* and then. Draws the eye to one word without changing what it says: a
|
|
14
|
+
* "New" next to a menu item, the plan name on an upgrade card, a status
|
|
15
|
+
* that is still working ("Deploying…").
|
|
16
|
+
* "gradient" — the text is painted with the theme's brand, accent and action
|
|
17
|
+
* colours drifting across it. A display headline, a logo word.
|
|
18
|
+
*
|
|
19
|
+
* <LpShinyText>Pro</LpShinyText>
|
|
20
|
+
* <LpShinyText variant="gradient" as="h1" class="text-4xl font-bold">Leave Pulse</LpShinyText>
|
|
21
|
+
*
|
|
22
|
+
* Pure CSS: the text is clipped to an animated background. The sheen moves
|
|
23
|
+
* toward the theme's ink, not toward white, so it lightens the text on a dark
|
|
24
|
+
* theme and darkens it on a light one and the word never washes out into the
|
|
25
|
+
* page. The loop pauses while the text is off screen or the tab is hidden;
|
|
26
|
+
* under reduced motion it stands still (the gradient stays, the sheen goes).
|
|
27
|
+
*/
|
|
28
|
+
import { computed } from "vue"
|
|
29
|
+
import { useInView } from "../composables/useInView"
|
|
30
|
+
import { useMergedAttrs } from "../composables/useMergedClass"
|
|
31
|
+
import { toneLook, type ToneName } from "./tone"
|
|
32
|
+
|
|
33
|
+
const props = withDefaults(
|
|
34
|
+
defineProps<{
|
|
35
|
+
/** `shine` sweeps a band over toned text; `gradient` paints it with drifting theme colours. */
|
|
36
|
+
variant?: "shine" | "gradient"
|
|
37
|
+
/** Base colour for `shine`. `ink` sweeps the brand colour over plain text. */
|
|
38
|
+
tone?: ToneName | "ink"
|
|
39
|
+
/** Seconds per sweep. Slower reads as ambient; under ~1.5 s it starts to nag. */
|
|
40
|
+
speed?: number
|
|
41
|
+
/** Stop the motion (keeps the look). For a word that should only shine while something is happening. */
|
|
42
|
+
paused?: boolean
|
|
43
|
+
/** Element to render. */
|
|
44
|
+
as?: string
|
|
45
|
+
}>(),
|
|
46
|
+
{ variant: "shine", tone: "brand", speed: 3, paused: false, as: "span" },
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
const { el, inView } = useInView()
|
|
50
|
+
const { class: rootClass, attrs: rest } = useMergedAttrs(() => `lp-shiny lp-shiny--${props.variant}`)
|
|
51
|
+
|
|
52
|
+
const style = computed(() => {
|
|
53
|
+
const base = props.tone === "ink" ? "var(--color-ink)" : toneLook(props.tone).color
|
|
54
|
+
return {
|
|
55
|
+
"--lp-shiny-base": base,
|
|
56
|
+
// Toward ink, so the band is the contrast direction in either theme; plain
|
|
57
|
+
// ink text gets a brand band instead, since ink toward ink is no band.
|
|
58
|
+
"--lp-shiny-sheen":
|
|
59
|
+
props.tone === "ink" ? "var(--color-brand)" : `color-mix(in oklab, ${base}, var(--color-ink) 65%)`,
|
|
60
|
+
"--lp-shiny-speed": `${Math.max(0.3, props.speed)}s`,
|
|
61
|
+
animationPlayState: props.paused || !inView.value ? "paused" : "running",
|
|
62
|
+
}
|
|
63
|
+
})
|
|
64
|
+
</script>
|
|
65
|
+
|
|
66
|
+
<template>
|
|
67
|
+
<component :is="as" ref="el" :class="rootClass" :style="style" v-bind="rest">
|
|
68
|
+
<slot />
|
|
69
|
+
</component>
|
|
70
|
+
</template>
|
|
71
|
+
|
|
72
|
+
<style>
|
|
73
|
+
.lp-shiny {
|
|
74
|
+
color: var(--lp-shiny-base);
|
|
75
|
+
background-repeat: repeat-x;
|
|
76
|
+
-webkit-background-clip: text;
|
|
77
|
+
background-clip: text;
|
|
78
|
+
-webkit-text-fill-color: transparent;
|
|
79
|
+
/* Descenders and italics poke out of the content box; the clip follows the
|
|
80
|
+
background box, so give it room instead of cutting a tail off. */
|
|
81
|
+
padding-block: 0.08em;
|
|
82
|
+
animation: lp-shiny-move var(--lp-shiny-speed) linear infinite;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.lp-shiny--shine {
|
|
86
|
+
/* The band is a third of a 300% wide image; the image moves by its own
|
|
87
|
+
width, so the band crosses the text and then rests off to the side for
|
|
88
|
+
a while, which is what makes it an occasional glint and not a strobe. */
|
|
89
|
+
background-image: linear-gradient(
|
|
90
|
+
105deg,
|
|
91
|
+
var(--lp-shiny-base) 0%,
|
|
92
|
+
var(--lp-shiny-base) 40%,
|
|
93
|
+
var(--lp-shiny-sheen) 50%,
|
|
94
|
+
var(--lp-shiny-base) 60%,
|
|
95
|
+
var(--lp-shiny-base) 100%
|
|
96
|
+
);
|
|
97
|
+
background-size: 300% 100%;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.lp-shiny--gradient {
|
|
101
|
+
/* First and last stops match, so the repeat has no seam as it drifts. */
|
|
102
|
+
background-image: linear-gradient(
|
|
103
|
+
90deg,
|
|
104
|
+
var(--color-brand),
|
|
105
|
+
var(--color-accent),
|
|
106
|
+
var(--color-action),
|
|
107
|
+
var(--color-brand)
|
|
108
|
+
);
|
|
109
|
+
background-size: 200% 100%;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
@keyframes lp-shiny-move {
|
|
113
|
+
from {
|
|
114
|
+
background-position: 100% 0;
|
|
115
|
+
}
|
|
116
|
+
to {
|
|
117
|
+
background-position: -200% 0;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.lp-shiny--gradient {
|
|
122
|
+
animation-name: lp-shiny-drift;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
@keyframes lp-shiny-drift {
|
|
126
|
+
from {
|
|
127
|
+
background-position: 0% 0;
|
|
128
|
+
}
|
|
129
|
+
to {
|
|
130
|
+
background-position: -200% 0;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
@media (prefers-reduced-motion: reduce) {
|
|
135
|
+
.lp-shiny {
|
|
136
|
+
animation: none;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
</style>
|
|
@@ -320,6 +320,7 @@ defineOptions({ inheritAttrs: false })
|
|
|
320
320
|
v-model="query"
|
|
321
321
|
size="sm"
|
|
322
322
|
icon="lucide:search"
|
|
323
|
+
clearable
|
|
323
324
|
class="mb-2 shrink-0"
|
|
324
325
|
:placeholder="placeholder"
|
|
325
326
|
:aria-label="placeholder"
|
|
@@ -380,6 +381,7 @@ defineOptions({ inheritAttrs: false })
|
|
|
380
381
|
v-model="query"
|
|
381
382
|
size="sm"
|
|
382
383
|
icon="lucide:search"
|
|
384
|
+
clearable
|
|
383
385
|
class="mb-2 shrink-0"
|
|
384
386
|
:placeholder="placeholder"
|
|
385
387
|
:aria-label="placeholder"
|
|
@@ -11,6 +11,7 @@ export default { inheritAttrs: false }
|
|
|
11
11
|
import { SliderRange, SliderRoot, SliderThumb, SliderTrack } from "reka-ui"
|
|
12
12
|
import { useFieldControl } from "../composables/useField"
|
|
13
13
|
import { useMergedAttrs } from "../composables/useMergedClass"
|
|
14
|
+
import { SLIDER_GLIDE, useSliderDrag } from "./slider"
|
|
14
15
|
|
|
15
16
|
const props = withDefaults(
|
|
16
17
|
defineProps<{
|
|
@@ -43,8 +44,9 @@ const field = useFieldControl(() => ({ wrapped: false, disabled: props.disabled
|
|
|
43
44
|
|
|
44
45
|
// A slider is full-width by default; putting one in a toolbar means constraining it, and a fixed h-5 has to yield to a denser row.
|
|
45
46
|
const { class: rootClass, attrs: rest } = useMergedAttrs(
|
|
46
|
-
|
|
47
|
+
`relative flex h-5 w-full touch-none select-none items-center data-[disabled]:opacity-55 ${SLIDER_GLIDE}`,
|
|
47
48
|
)
|
|
49
|
+
const { dragging, onPointerDown } = useSliderDrag()
|
|
48
50
|
</script>
|
|
49
51
|
|
|
50
52
|
<template>
|
|
@@ -56,6 +58,8 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(
|
|
|
56
58
|
:disabled="field.disabled"
|
|
57
59
|
:class="rootClass"
|
|
58
60
|
v-bind="rest"
|
|
61
|
+
:data-dragging="dragging || undefined"
|
|
62
|
+
@pointerdown="onPointerDown"
|
|
59
63
|
@update:model-value="onUpdate"
|
|
60
64
|
@value-commit="onCommit"
|
|
61
65
|
>
|
|
@@ -19,8 +19,10 @@ import LpSkeleton from "./LpSkeleton.vue"
|
|
|
19
19
|
import { sampleValues } from "./chartSkeleton"
|
|
20
20
|
import { useSample } from "../composables/useSample"
|
|
21
21
|
import { useReveal } from "../composables/useReveal"
|
|
22
|
+
import { mixValues, useTween } from "../composables/useTween"
|
|
22
23
|
import { useLabels } from "../composables/useLpConfig"
|
|
23
24
|
import { areaPath, extent, linePath, normalise, type Box } from "./chart"
|
|
25
|
+
import { toneLook, type ToneName } from "./tone"
|
|
24
26
|
|
|
25
27
|
const props = withDefaults(
|
|
26
28
|
defineProps<{
|
|
@@ -32,7 +34,7 @@ const props = withDefaults(
|
|
|
32
34
|
/** Any CSS colour. Defaults to the brand token. */
|
|
33
35
|
color?: string
|
|
34
36
|
/** Named theme tones, for callers that don't want to spell a var(). */
|
|
35
|
-
tone?:
|
|
37
|
+
tone?: ToneName
|
|
36
38
|
/** Fill under the line. */
|
|
37
39
|
area?: boolean
|
|
38
40
|
/** Curve tension, as in LpChart. 0 draws a polyline. */
|
|
@@ -77,15 +79,23 @@ const props = withDefaults(
|
|
|
77
79
|
{ width: 84, height: 24, tone: "brand", smooth: 0.9, animate: true, duration: 900, sample: true },
|
|
78
80
|
)
|
|
79
81
|
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
82
|
+
const stroke = computed(() => props.color ?? toneLook(props.tone).color)
|
|
83
|
+
|
|
84
|
+
/*
|
|
85
|
+
* The sweep is held until the svg is actually on screen. Forty of these sit in
|
|
86
|
+
* a list, most of them below the fold; started on mount they would all have
|
|
87
|
+
* finished before the rows carrying them were ever scrolled to.
|
|
88
|
+
*/
|
|
89
|
+
const { el, revealed } = useReveal({ immediate: () => !props.animate })
|
|
87
90
|
|
|
88
|
-
|
|
91
|
+
// The stub holds the place when there is nothing to draw, so the sample can
|
|
92
|
+
// still find the hint it sits in.
|
|
93
|
+
const stub = ref<Element | null>(null)
|
|
94
|
+
const sampling = useSample(
|
|
95
|
+
computed(() => el.value ?? stub.value),
|
|
96
|
+
() => !props.loading && !props.data.some((v) => v != null),
|
|
97
|
+
() => props.sample,
|
|
98
|
+
)
|
|
89
99
|
|
|
90
100
|
const data = computed(() => (sampling.value ? sampleValues(props.data.length || 12) : props.data))
|
|
91
101
|
|
|
@@ -116,32 +126,56 @@ const bounds = computed(() => {
|
|
|
116
126
|
return { min: props.min ?? auto.min, max: props.max ?? auto.max }
|
|
117
127
|
})
|
|
118
128
|
|
|
129
|
+
/*
|
|
130
|
+
* What is DRAWN: each reading as its height in the box, 0 at the bottom and 1
|
|
131
|
+
* at the top, travelling from the last line to the new one.
|
|
132
|
+
*
|
|
133
|
+
* Heights, not raw values, because the range moves with the data. New values
|
|
134
|
+
* on the old range overshoot the box and old values on the new range redraw the
|
|
135
|
+
* line at another height, and tweening values and range side by side has a
|
|
136
|
+
* blind spot of its own: when the new range collapses (a flat series), values
|
|
137
|
+
* and range shrink in proportion, the line holds its old shape the whole way
|
|
138
|
+
* and then drops on the last frame. Heights are already on the range, so a
|
|
139
|
+
* frame partway is a line partway, whatever happened to the scale.
|
|
140
|
+
*/
|
|
141
|
+
const heights = computed(() => {
|
|
142
|
+
const { min, max } = bounds.value
|
|
143
|
+
const span = max - min || 1
|
|
144
|
+
return series.value[0].values.map((v) => (v == null ? null : (v - min) / span))
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
const shown = useTween(() => heights.value, mixValues, {
|
|
148
|
+
/*
|
|
149
|
+
* Only a line already on screen morphs. Before it is revealed the draw-on
|
|
150
|
+
* is still to come, and while the loading band or the stub stands in (`el`
|
|
151
|
+
* unset) the line will mount fresh and draw itself in — a morph from
|
|
152
|
+
* readings nobody saw would only blur that entrance.
|
|
153
|
+
*/
|
|
154
|
+
enabled: () => props.animate && revealed.value && !!el.value,
|
|
155
|
+
})
|
|
156
|
+
|
|
119
157
|
const geo = computed(() => ({
|
|
120
|
-
min:
|
|
121
|
-
max:
|
|
158
|
+
min: 0,
|
|
159
|
+
max: 1,
|
|
122
160
|
box: box.value,
|
|
123
|
-
count:
|
|
161
|
+
count: shown.value.length,
|
|
124
162
|
banded: false,
|
|
125
163
|
}))
|
|
126
164
|
|
|
127
|
-
const d = computed(() => linePath(
|
|
128
|
-
const fill = computed(() =>
|
|
129
|
-
props.area ? areaPath(series.value[0].values, geo.value, props.smooth) : "",
|
|
130
|
-
)
|
|
165
|
+
const d = computed(() => linePath(shown.value, geo.value, props.smooth))
|
|
166
|
+
const fill = computed(() => (props.area ? areaPath(shown.value, geo.value, props.smooth) : ""))
|
|
131
167
|
|
|
132
168
|
/** Last point that actually has a value — the dot goes there, not on a gap. */
|
|
133
169
|
const lastPoint = computed(() => {
|
|
134
|
-
const values =
|
|
170
|
+
const values = shown.value
|
|
135
171
|
for (let i = values.length - 1; i >= 0; i--) {
|
|
136
172
|
const v = values[i]
|
|
137
173
|
if (v == null) continue
|
|
138
|
-
const span = bounds.value.max - bounds.value.min || 1
|
|
139
174
|
const w = props.width - PAD * 2
|
|
140
175
|
const h = props.height - PAD * 2
|
|
141
176
|
return {
|
|
142
|
-
x:
|
|
143
|
-
y: PAD + h -
|
|
144
|
-
v,
|
|
177
|
+
x: values.length <= 1 ? PAD + w / 2 : PAD + (w / (values.length - 1)) * i,
|
|
178
|
+
y: PAD + h - v * h,
|
|
145
179
|
}
|
|
146
180
|
}
|
|
147
181
|
return null
|
|
@@ -186,22 +220,6 @@ const pathLength = computed(() => {
|
|
|
186
220
|
return Math.ceil(segment * n + 4)
|
|
187
221
|
})
|
|
188
222
|
|
|
189
|
-
/*
|
|
190
|
-
* The sweep is held until the svg is actually on screen. Forty of these sit in
|
|
191
|
-
* a list, most of them below the fold; started on mount they would all have
|
|
192
|
-
* finished before the rows carrying them were ever scrolled to.
|
|
193
|
-
*/
|
|
194
|
-
const { el, revealed } = useReveal({ immediate: () => !props.animate })
|
|
195
|
-
|
|
196
|
-
// The stub holds the place when there is nothing to draw, so the sample can
|
|
197
|
-
// still find the hint it sits in.
|
|
198
|
-
const stub = ref<Element | null>(null)
|
|
199
|
-
const sampling = useSample(
|
|
200
|
-
computed(() => el.value ?? stub.value),
|
|
201
|
-
() => !props.loading && !props.data.some((v) => v != null),
|
|
202
|
-
() => props.sample,
|
|
203
|
-
)
|
|
204
|
-
|
|
205
223
|
const revealStyle = computed(() =>
|
|
206
224
|
props.animate
|
|
207
225
|
? {
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
export default { inheritAttrs: false }
|
|
3
|
+
</script>
|
|
4
|
+
|
|
5
|
+
<script setup lang="ts">
|
|
6
|
+
/*
|
|
7
|
+
* LpSpotlight — a soft glow that follows the pointer inside whatever it wraps.
|
|
8
|
+
*
|
|
9
|
+
* <LpSpotlight class="rounded-card"><MyTile /></LpSpotlight>
|
|
10
|
+
*
|
|
11
|
+
* For a grid of tiles the eye should scan with the mouse: the lit one is the
|
|
12
|
+
* one about to be clicked, without a hover border shouting it. LpCard has the
|
|
13
|
+
* same effect as its `spotlight` prop; reach for this wrapper around anything
|
|
14
|
+
* that is not a card. Mouse only; reduced motion draws nothing. The glow is
|
|
15
|
+
* painted by `.lp-spotlight` in tokens/effects.css.
|
|
16
|
+
*/
|
|
17
|
+
import { computed } from "vue"
|
|
18
|
+
import { useMergedAttrs } from "../composables/useMergedClass"
|
|
19
|
+
import { useSpotlight } from "../composables/useSpotlight"
|
|
20
|
+
|
|
21
|
+
const props = withDefaults(
|
|
22
|
+
defineProps<{
|
|
23
|
+
/** Any CSS colour. Defaults to the brand colour, so it follows the theme. */
|
|
24
|
+
color?: string
|
|
25
|
+
/** Diameter of the lit circle, in px. Larger reads as ambient, smaller as a torch. */
|
|
26
|
+
size?: number
|
|
27
|
+
/** How much of the colour mixes in, 0–100. Keep it low on text-heavy surfaces. */
|
|
28
|
+
strength?: number
|
|
29
|
+
/** Keep the wrapper but draw nothing — for a tile that is disabled or busy. */
|
|
30
|
+
disabled?: boolean
|
|
31
|
+
/** Element to render as. */
|
|
32
|
+
as?: string
|
|
33
|
+
}>(),
|
|
34
|
+
{ size: 280, strength: 18, disabled: false, as: "div" },
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
const { el } = useSpotlight({ disabled: () => props.disabled })
|
|
38
|
+
const { class: classes, attrs: rest } = useMergedAttrs(() => "lp-spotlight rounded-card")
|
|
39
|
+
|
|
40
|
+
const style = computed(() => ({
|
|
41
|
+
"--lp-spot-size": `${props.size}px`,
|
|
42
|
+
"--lp-spot-strength": `${Math.min(100, Math.max(0, props.strength))}%`,
|
|
43
|
+
...(props.color ? { "--lp-spot-color": props.color } : {}),
|
|
44
|
+
}))
|
|
45
|
+
</script>
|
|
46
|
+
|
|
47
|
+
<template>
|
|
48
|
+
<component :is="as" ref="el" :class="classes" :style="style" v-bind="rest">
|
|
49
|
+
<slot />
|
|
50
|
+
</component>
|
|
51
|
+
</template>
|
|
@@ -12,7 +12,9 @@ import { computed } from "vue"
|
|
|
12
12
|
import LpIcon from "./LpIcon.vue"
|
|
13
13
|
import LpNumberFlow from "./LpNumberFlow.vue"
|
|
14
14
|
import LpSkeleton from "./LpSkeleton.vue"
|
|
15
|
+
import LpStatus from "./LpStatus.vue"
|
|
15
16
|
import { useMergedAttrs } from "../composables/useMergedClass"
|
|
17
|
+
import { TONES } from "./tone"
|
|
16
18
|
|
|
17
19
|
const props = withDefaults(
|
|
18
20
|
defineProps<{
|
|
@@ -77,7 +79,7 @@ const trendIcon = computed(() =>
|
|
|
77
79
|
const trendColor = computed(() => {
|
|
78
80
|
if (dir.value === "flat") return "text-muted"
|
|
79
81
|
const good = props.invertTrend ? dir.value === "down" : dir.value === "up"
|
|
80
|
-
return good ?
|
|
82
|
+
return good ? TONES.success.text : TONES.danger.text
|
|
81
83
|
})
|
|
82
84
|
|
|
83
85
|
// Numeric delta gets an explicit sign; string deltas are shown as given.
|
|
@@ -128,7 +130,9 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(
|
|
|
128
130
|
:class="rootClass"
|
|
129
131
|
v-bind="rest">
|
|
130
132
|
<div class="flex items-center gap-2">
|
|
131
|
-
|
|
133
|
+
<!-- The kit's own "online" light, so a live tile reads (and is spoken)
|
|
134
|
+
the same as a live server row elsewhere on the page. -->
|
|
135
|
+
<LpStatus v-if="online" state="online" size="sm" hide-label />
|
|
132
136
|
<LpIcon v-if="icon" :name="icon" :size="14" class="text-muted" />
|
|
133
137
|
<span class="text-[11px] font-semibold uppercase tracking-[0.08em] text-muted">
|
|
134
138
|
<Transition v-bind="FADE">
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
// The consumer's `class` is merged into the root's own rather than appended to
|
|
3
|
+
// it, so opt out of the automatic pass-through that would add it unmerged.
|
|
4
|
+
export default { inheritAttrs: false }
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<script setup lang="ts">
|
|
8
|
+
/*
|
|
9
|
+
* What state something is in, as a light and a word: a server online, a bot
|
|
10
|
+
* starting, a region degraded.
|
|
11
|
+
*
|
|
12
|
+
* Not LpBadge with a dot. A badge is a label whose text is the point and whose
|
|
13
|
+
* dot is decoration; here the STATE is the point and the caller passes a state,
|
|
14
|
+
* not a colour and a word. The light, the word, the pulse and the spoken text
|
|
15
|
+
* all follow from it, so every status in an app looks and sounds the same, and
|
|
16
|
+
* a change of state (starting → online) reads as one thing changing: the light
|
|
17
|
+
* crossfades, the word rolls, the pulse starts or stops.
|
|
18
|
+
*/
|
|
19
|
+
import { computed } from "vue"
|
|
20
|
+
import { useLabels } from "../composables/useLpConfig"
|
|
21
|
+
import { useMergedAttrs } from "../composables/useMergedClass"
|
|
22
|
+
import LpBadge from "./LpBadge.vue"
|
|
23
|
+
import LpRollingText from "./LpRollingText.vue"
|
|
24
|
+
import LpShift from "./LpShift.vue"
|
|
25
|
+
import { TONE_COLOR, type MeterTone } from "./meter"
|
|
26
|
+
import { STATUS_LABELS, STATUS_LOOK, type StatusKind } from "./status"
|
|
27
|
+
|
|
28
|
+
const props = withDefaults(
|
|
29
|
+
defineProps<{
|
|
30
|
+
state: StatusKind
|
|
31
|
+
/** The word shown, when the state's own name is not the right one ("Ready", "In a match"). */
|
|
32
|
+
label?: string
|
|
33
|
+
/** Overrides the state's tone, for an app whose "offline" is an alarm rather than a rest state. */
|
|
34
|
+
tone?: MeterTone
|
|
35
|
+
/** Overrides whether the light pulses. */
|
|
36
|
+
pulse?: boolean
|
|
37
|
+
/**
|
|
38
|
+
* `inline` (default) is a light and a word in running text or a table cell;
|
|
39
|
+
* `pill` puts them on a chip, which is LpBadge's own: the chip is the
|
|
40
|
+
* badge, the state (light, word, pulse, tone) is what this adds to it.
|
|
41
|
+
*/
|
|
42
|
+
variant?: "inline" | "pill"
|
|
43
|
+
size?: "sm" | "md"
|
|
44
|
+
/**
|
|
45
|
+
* Light only. The word is still there for screen readers and as a native
|
|
46
|
+
* hint on hover, so a dense list can drop it visually without going silent.
|
|
47
|
+
*/
|
|
48
|
+
hideLabel?: boolean
|
|
49
|
+
/**
|
|
50
|
+
* Speak changes as they happen (`role="status"`). Off by default: a table
|
|
51
|
+
* of twenty servers announcing each flip would drown everything else.
|
|
52
|
+
* Turn it on for the one status the user is waiting on.
|
|
53
|
+
*/
|
|
54
|
+
announce?: boolean
|
|
55
|
+
labels?: Partial<Record<StatusKind, string>>
|
|
56
|
+
}>(),
|
|
57
|
+
{ variant: "inline", size: "md", hideLabel: false, announce: false, pulse: undefined },
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
const names = useLabels<Record<StatusKind, string>>("status", STATUS_LABELS, () => props.labels)
|
|
61
|
+
|
|
62
|
+
const look = computed(() => STATUS_LOOK[props.state] ?? STATUS_LOOK.unknown)
|
|
63
|
+
const tone = computed(() => props.tone ?? look.value.tone)
|
|
64
|
+
const pulsing = computed(() => props.pulse ?? look.value.pulse)
|
|
65
|
+
const word = computed(() => props.label ?? names.value[props.state] ?? props.state)
|
|
66
|
+
|
|
67
|
+
const { class: rootClass, attrs: rest } = useMergedAttrs(() =>
|
|
68
|
+
props.variant === "pill"
|
|
69
|
+
? ""
|
|
70
|
+
: [
|
|
71
|
+
"inline-flex shrink-0 items-center align-middle font-medium leading-[1.2] whitespace-nowrap text-muted-strong",
|
|
72
|
+
props.size === "sm" ? "gap-1.5 text-[11px]" : "gap-2 text-xs",
|
|
73
|
+
].join(" "),
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
const dotSize = computed(() => (props.size === "sm" ? "size-1.5" : "size-2"))
|
|
78
|
+
</script>
|
|
79
|
+
|
|
80
|
+
<template>
|
|
81
|
+
<component
|
|
82
|
+
:is="variant === 'pill' ? LpBadge : 'span'"
|
|
83
|
+
:role="announce ? 'status' : undefined"
|
|
84
|
+
:title="hideLabel ? word : undefined"
|
|
85
|
+
:class="rootClass"
|
|
86
|
+
v-bind="variant === 'pill' ? { ...rest, tone, size } : rest"
|
|
87
|
+
>
|
|
88
|
+
<span class="relative inline-flex shrink-0" :class="dotSize" aria-hidden="true">
|
|
89
|
+
<!-- The halo is the same colour as the light and scales out from it, so
|
|
90
|
+
it stays in step with a tone change instead of lagging a beat. -->
|
|
91
|
+
<span
|
|
92
|
+
class="lp-status-halo absolute inset-0 rounded-full transition-[background-color,opacity] duration-(--duration-medium)"
|
|
93
|
+
:class="pulsing ? 'lp-status-halo--on' : 'opacity-0'"
|
|
94
|
+
:style="{ backgroundColor: TONE_COLOR[tone] }"
|
|
95
|
+
/>
|
|
96
|
+
<span
|
|
97
|
+
class="relative inline-flex size-full rounded-full transition-[background-color] duration-(--duration-medium) ease-(--ease-emphasized) motion-reduce:transition-none"
|
|
98
|
+
:style="{ backgroundColor: TONE_COLOR[tone] }"
|
|
99
|
+
/>
|
|
100
|
+
</span>
|
|
101
|
+
<span v-if="hideLabel" class="sr-only">{{ word }}</span>
|
|
102
|
+
<LpRollingText v-else-if="variant === 'pill'" :value="word" align="start" />
|
|
103
|
+
<LpShift v-else axis="width">
|
|
104
|
+
<LpRollingText :value="word" align="start" />
|
|
105
|
+
</LpShift>
|
|
106
|
+
</component>
|
|
107
|
+
</template>
|
|
108
|
+
|
|
109
|
+
<style>
|
|
110
|
+
/*
|
|
111
|
+
* Unscoped and namespaced, like LpSkeleton's pulse. The keyframe is the kit's
|
|
112
|
+
* halo (tokens.css): one animation name keeps every live light on a page
|
|
113
|
+
* breathing in phase, because CSS animations are timed against the document
|
|
114
|
+
* rather than against when each one mounted. A column of servers pulsing out
|
|
115
|
+
* of step reads as flicker. A small light swells to 2.6x, the halo's default.
|
|
116
|
+
*/
|
|
117
|
+
.lp-status-halo--on {
|
|
118
|
+
animation: lp-halo 2s cubic-bezier(0, 0, 0.2, 1) infinite;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
@media (prefers-reduced-motion: reduce) {
|
|
122
|
+
.lp-status-halo--on {
|
|
123
|
+
animation: none;
|
|
124
|
+
opacity: 0;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
</style>
|
|
@@ -0,0 +1,138 @@
|
|
|
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 state of one job as a round glyph: hollow while it waits, spinning while
|
|
11
|
+
* it runs, a tick, a cross, a dash for skipped, a slash for cancelled.
|
|
12
|
+
*
|
|
13
|
+
* LpPipeline draws its steps with it, and it stands alone wherever a single
|
|
14
|
+
* job's state sits next to its name: a row in a deploys table, a check in a
|
|
15
|
+
* list, a toast about a build. A change of status is a change the viewer is
|
|
16
|
+
* waiting for, so it shows as one: the colours ease, the glyph flips to the
|
|
17
|
+
* new one (LpRollingText), and a running mark breathes a halo so it reads as
|
|
18
|
+
* live even while the spinner is small.
|
|
19
|
+
*
|
|
20
|
+
* Decorative by default (the text next to it says the state); pass `label`
|
|
21
|
+
* when the mark is all there is.
|
|
22
|
+
*
|
|
23
|
+
* `variant="step"` is the same mark as a wizard draws it (LpStepper): the
|
|
24
|
+
* step you are on is a brand ring with its number (`status="current"`), a
|
|
25
|
+
* finished one is filled with the brand colour rather than the "passed"
|
|
26
|
+
* green, and the ones ahead are a quiet ring with no fill of their own.
|
|
27
|
+
*/
|
|
28
|
+
import { computed } from "vue"
|
|
29
|
+
import { useMergedAttrs } from "../composables/useMergedClass"
|
|
30
|
+
import LpIcon from "./LpIcon.vue"
|
|
31
|
+
import LpLoader from "./LpLoader.vue"
|
|
32
|
+
import LpRollingText from "./LpRollingText.vue"
|
|
33
|
+
import type { StepStatus } from "./pipeline"
|
|
34
|
+
import { TONES } from "./tone"
|
|
35
|
+
|
|
36
|
+
/** A job's state, plus `current`: the step a person is on in a flow they drive. */
|
|
37
|
+
export type StepMarkStatus = StepStatus | "current"
|
|
38
|
+
|
|
39
|
+
const props = withDefaults(
|
|
40
|
+
defineProps<{
|
|
41
|
+
status: StepMarkStatus
|
|
42
|
+
/** `status` (default) colours a job's outcome; `step` is a wizard's step (see above). */
|
|
43
|
+
variant?: "status" | "step"
|
|
44
|
+
size?: "sm" | "md" | "lg"
|
|
45
|
+
/** Shown inside a pending mark: the step's number in a numbered flow. */
|
|
46
|
+
number?: number | string
|
|
47
|
+
/** Shown inside a pending mark instead of the number. */
|
|
48
|
+
icon?: string
|
|
49
|
+
/** Accessible name; without it the mark is hidden from assistive tech. */
|
|
50
|
+
label?: string
|
|
51
|
+
}>(),
|
|
52
|
+
{ variant: "status", size: "md" },
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
const BOX = { sm: "size-4 text-[9px]", md: "size-6 text-[11px]", lg: "size-8 text-xs" }
|
|
56
|
+
const GLYPH = { sm: 10, md: 14, lg: 18 }
|
|
57
|
+
|
|
58
|
+
// Outcomes in the kit's tones (tone.ts): a ring for what is under way, a solid
|
|
59
|
+
// disc for what is decided. The quiet states are greys, not tones.
|
|
60
|
+
const TONE: Record<StepMarkStatus, string> = {
|
|
61
|
+
pending: "border-line-strong bg-surface text-muted",
|
|
62
|
+
current: `bg-surface ${TONES.brand.border} ${TONES.brand.text}`,
|
|
63
|
+
running: `${TONES.brand.border} ${TONES.brand.chip}`,
|
|
64
|
+
success: `border-transparent text-ink-inverse ${TONES.success.bg}`,
|
|
65
|
+
failed: `border-transparent text-ink-inverse ${TONES.danger.bg}`,
|
|
66
|
+
skipped: "border-dashed border-line-strong bg-surface text-muted",
|
|
67
|
+
cancelled: "border-line-strong bg-surface-soft text-muted-strong",
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// A wizard's step sits on whatever surface the form has, so only its ring and number are its own.
|
|
71
|
+
const STEP_TONE: Partial<Record<StepMarkStatus, string>> = {
|
|
72
|
+
pending: "border-line text-muted",
|
|
73
|
+
current: `${TONES.brand.border} ${TONES.brand.text}`,
|
|
74
|
+
success: `border-transparent text-ink-inverse ${TONES.brand.bg}`,
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const ICON: Partial<Record<StepMarkStatus, string>> = {
|
|
78
|
+
success: "lucide:check",
|
|
79
|
+
failed: "lucide:x",
|
|
80
|
+
skipped: "lucide:minus",
|
|
81
|
+
cancelled: "lucide:slash",
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/*
|
|
85
|
+
* What the glyph shows, as one value the roll keys on: a status change flips
|
|
86
|
+
* it, a pending step's number changing (a reordered flow) flips it too.
|
|
87
|
+
*/
|
|
88
|
+
const glyph = computed(() => {
|
|
89
|
+
// Pending and current show the same thing, so arriving at a step keeps its number in place.
|
|
90
|
+
if (props.status !== "pending" && props.status !== "current") return props.status
|
|
91
|
+
if (props.icon) return "icon"
|
|
92
|
+
return props.number !== undefined ? `n:${props.number}` : "pending"
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
const { class: rootClass, attrs: rest } = useMergedAttrs(() =>
|
|
96
|
+
`relative inline-flex shrink-0 items-center justify-center rounded-pill border font-semibold tabular-nums transition-[color,background-color,border-color] duration-(--duration-medium) ease-(--ease-emphasized) motion-reduce:transition-none ${BOX[props.size]} ${(props.variant === "step" && STEP_TONE[props.status]) || TONE[props.status]}`,
|
|
97
|
+
)
|
|
98
|
+
</script>
|
|
99
|
+
|
|
100
|
+
<template>
|
|
101
|
+
<span
|
|
102
|
+
:class="rootClass"
|
|
103
|
+
:role="label ? 'img' : undefined"
|
|
104
|
+
:aria-label="label || undefined"
|
|
105
|
+
:aria-hidden="label ? undefined : 'true'"
|
|
106
|
+
:data-status="status"
|
|
107
|
+
v-bind="rest"
|
|
108
|
+
>
|
|
109
|
+
<span v-if="status === 'running'" class="lp-step-halo pointer-events-none absolute -inset-px rounded-pill border border-brand" />
|
|
110
|
+
<LpRollingText mode="flip" :duration="260" :value="glyph">
|
|
111
|
+
<template #default="{ value }">
|
|
112
|
+
<LpLoader
|
|
113
|
+
v-if="value === 'running'"
|
|
114
|
+
:delay="0"
|
|
115
|
+
:min-visible="0"
|
|
116
|
+
size="inline"
|
|
117
|
+
:class="size === 'sm' ? 'text-[10px]' : size === 'md' ? 'text-sm' : 'text-lg'"
|
|
118
|
+
/>
|
|
119
|
+
<LpIcon v-else-if="ICON[value as StepMarkStatus]" :name="ICON[value as StepMarkStatus]!" :size="GLYPH[size]" />
|
|
120
|
+
<LpIcon v-else-if="value === 'icon' && icon" :name="icon" :size="variant === 'step' ? GLYPH[size] : GLYPH[size] - 2" />
|
|
121
|
+
<template v-else-if="String(value).startsWith('n:')">{{ number }}</template>
|
|
122
|
+
<!-- An empty slot would fall back to printing the raw key. -->
|
|
123
|
+
<span v-else class="block size-0" />
|
|
124
|
+
</template>
|
|
125
|
+
</LpRollingText>
|
|
126
|
+
</span>
|
|
127
|
+
</template>
|
|
128
|
+
|
|
129
|
+
<style>
|
|
130
|
+
/* The kit's halo (tokens.css), swelling less: this ring already starts at the mark's own size. */
|
|
131
|
+
.lp-step-halo {
|
|
132
|
+
--halo-scale: 1.6;
|
|
133
|
+
animation: lp-halo 1.6s var(--ease-emphasized, ease-out) infinite;
|
|
134
|
+
}
|
|
135
|
+
@media (prefers-reduced-motion: reduce) {
|
|
136
|
+
.lp-step-halo { animation: none; opacity: 0; }
|
|
137
|
+
}
|
|
138
|
+
</style>
|