@leavepulse/ui 0.69.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.js +107 -138
- 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/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 +143 -154
- 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 +9 -32
- 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/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
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { useReducedMotion } from "motion-v"
|
|
2
1
|
import { computed, type ComputedRef } from "vue"
|
|
2
|
+
import { usePrefersReducedMotion } from "./useReducedMotion"
|
|
3
3
|
|
|
4
4
|
/*
|
|
5
5
|
* Shared motion-v transition for an element that FLIES to a new position rather
|
|
@@ -8,27 +8,32 @@ import { computed, type ComputedRef } from "vue"
|
|
|
8
8
|
* tooltip trailing the cursor. One spring per feel keeps them consistent, and
|
|
9
9
|
* every preset collapses to an instant move when the OS prefers reduced motion.
|
|
10
10
|
*
|
|
11
|
-
*
|
|
11
|
+
* Three feels, because the jobs want different things:
|
|
12
12
|
*
|
|
13
|
-
* "pill"
|
|
14
|
-
*
|
|
15
|
-
* "float"
|
|
16
|
-
*
|
|
17
|
-
*
|
|
13
|
+
* "pill" — snappy. The move is a direct answer to a click, so it should read
|
|
14
|
+
* as already-arrived: high stiffness, almost no visible travel.
|
|
15
|
+
* "float" — trailing. The element chases a continuously moving pointer, so it
|
|
16
|
+
* wants perceptible lag and a soft landing; a pill-stiff spring
|
|
17
|
+
* tracks the cursor so exactly that it reads as jitter, not motion.
|
|
18
|
+
* "layout" — a box resizing or a block moving to a new place (motion-v
|
|
19
|
+
* `layout`): LpTabs' panel height, a block dropped in LayoutCanvas.
|
|
20
|
+
* As quick as the pill, a touch more damped and lighter, so a
|
|
21
|
+
* large box lands without a wobble at its edge.
|
|
18
22
|
*/
|
|
19
23
|
export type PillTransition =
|
|
20
24
|
| { duration: number }
|
|
21
|
-
| { type: "spring"; stiffness: number; damping: number }
|
|
25
|
+
| { type: "spring"; stiffness: number; damping: number; mass?: number }
|
|
22
26
|
|
|
23
|
-
export type PillFeel = "pill" | "float"
|
|
27
|
+
export type PillFeel = "pill" | "float" | "layout"
|
|
24
28
|
|
|
25
|
-
const SPRING: Record<PillFeel, { type: "spring"; stiffness: number; damping: number }> = {
|
|
29
|
+
const SPRING: Record<PillFeel, { type: "spring"; stiffness: number; damping: number; mass?: number }> = {
|
|
26
30
|
pill: { type: "spring", stiffness: 520, damping: 40 },
|
|
27
31
|
float: { type: "spring", stiffness: 210, damping: 26 },
|
|
32
|
+
layout: { type: "spring", stiffness: 520, damping: 42, mass: 0.9 },
|
|
28
33
|
}
|
|
29
34
|
|
|
30
35
|
export function usePillTransition(feel: PillFeel = "pill"): ComputedRef<PillTransition> {
|
|
31
|
-
const reduceMotion =
|
|
36
|
+
const reduceMotion = usePrefersReducedMotion()
|
|
32
37
|
return computed<PillTransition>(() =>
|
|
33
38
|
reduceMotion.value ? { duration: 0 } : SPRING[feel],
|
|
34
39
|
)
|
|
@@ -51,7 +56,10 @@ export function usePillTransition(feel: PillFeel = "pill"): ComputedRef<PillTran
|
|
|
51
56
|
* matched by feel and kept beside their motion-v counterparts so that a change
|
|
52
57
|
* to one is an obvious prompt to check the other.
|
|
53
58
|
*/
|
|
54
|
-
|
|
59
|
+
/** The feels a pointer follower uses; "layout" is a motion-v layout move only. */
|
|
60
|
+
export type StepFeel = Exclude<PillFeel, "layout">
|
|
61
|
+
|
|
62
|
+
const STEP_SPRING: Record<StepFeel, { stiffness: number; damping: number }> = {
|
|
55
63
|
// Critically damped: reaches the target quickly, never past it.
|
|
56
64
|
pill: { stiffness: 420, damping: 41 },
|
|
57
65
|
float: { stiffness: 260, damping: 32 },
|
|
@@ -67,7 +75,7 @@ export interface SpringState {
|
|
|
67
75
|
export function springStep(
|
|
68
76
|
state: SpringState,
|
|
69
77
|
target: number,
|
|
70
|
-
feel:
|
|
78
|
+
feel: StepFeel = "float",
|
|
71
79
|
/** Frame time in seconds; clamped so a backgrounded tab can't explode it. */
|
|
72
80
|
dt = 1 / 60,
|
|
73
81
|
): SpringState {
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { onScopeDispose, toValue, type MaybeRefOrGetter } from "vue"
|
|
2
|
+
import { prefersReducedMotion } from "./easing"
|
|
3
|
+
|
|
4
|
+
/*
|
|
5
|
+
* The scaffolding of a decoration that follows the pointer (LpMagnetic's
|
|
6
|
+
* pull, the spotlight glow, LpTilt's lean): take the latest pointer position,
|
|
7
|
+
* and paint from it once per animation frame.
|
|
8
|
+
*
|
|
9
|
+
* pointermove fires faster than frames, and a re-render per event for a
|
|
10
|
+
* decoration is the kind of cost the launcher on WebKitGTK actually feels. So
|
|
11
|
+
* nothing here is reactive: `move` records the position and asks for a frame,
|
|
12
|
+
* `paint` runs in that frame with the latest one, and writes straight to the
|
|
13
|
+
* element (a style property, a custom property). The three effects had this
|
|
14
|
+
* written out each, with the same filters in slightly different orders.
|
|
15
|
+
*
|
|
16
|
+
* Who listens is the caller's: the spotlight listens on its own element, the
|
|
17
|
+
* magnet on its window (its field reaches past its edges), the tilt through
|
|
18
|
+
* handlers its consumer binds. They all feed `move`.
|
|
19
|
+
*
|
|
20
|
+
* Touch and pen are ignored unless `anyPointer`: there is no hover to follow,
|
|
21
|
+
* and an effect that jumps to wherever a finger landed reads as a pressed
|
|
22
|
+
* state that is not one. Reduced motion and `disabled` drop moves entirely.
|
|
23
|
+
*/
|
|
24
|
+
export interface PointerFrameOptions {
|
|
25
|
+
/** Paint with the latest pointer position, in client coordinates. */
|
|
26
|
+
paint: (x: number, y: number) => void
|
|
27
|
+
/** Drop moves while true; the caller decides what "off" looks like. */
|
|
28
|
+
disabled?: MaybeRefOrGetter<boolean | undefined>
|
|
29
|
+
/** Follow touch and pen too, not only a mouse. */
|
|
30
|
+
anyPointer?: boolean
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface PointerFrame {
|
|
34
|
+
/** Feed a pointer event. False when it was dropped (touch, reduced motion, disabled). */
|
|
35
|
+
move: (event: PointerEvent) => boolean
|
|
36
|
+
/** Paint at a given position on the next frame, as if the pointer were there (a pointer that left the window). */
|
|
37
|
+
moveTo: (x: number, y: number) => void
|
|
38
|
+
/** Drop a frame that has been asked for but not painted yet. */
|
|
39
|
+
cancel: () => void
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function usePointerFrame(options: PointerFrameOptions): PointerFrame {
|
|
43
|
+
let frame = 0
|
|
44
|
+
let lastX = 0
|
|
45
|
+
let lastY = 0
|
|
46
|
+
|
|
47
|
+
const run = () => {
|
|
48
|
+
frame = 0
|
|
49
|
+
options.paint(lastX, lastY)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const moveTo = (x: number, y: number) => {
|
|
53
|
+
lastX = x
|
|
54
|
+
lastY = y
|
|
55
|
+
if (!frame) frame = requestAnimationFrame(run)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const move = (event: PointerEvent): boolean => {
|
|
59
|
+
if (!options.anyPointer && event.pointerType !== "mouse") return false
|
|
60
|
+
if (toValue(options.disabled) || prefersReducedMotion()) return false
|
|
61
|
+
moveTo(event.clientX, event.clientY)
|
|
62
|
+
return true
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const cancel = () => {
|
|
66
|
+
if (frame) cancelAnimationFrame(frame)
|
|
67
|
+
frame = 0
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
onScopeDispose(cancel)
|
|
71
|
+
return { move, moveTo, cancel }
|
|
72
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Ref } from "vue"
|
|
2
|
+
import { useMediaQuery } from "./useMediaQuery"
|
|
3
|
+
|
|
4
|
+
/*
|
|
5
|
+
* `prefersReducedMotion()` as a ref, for a component that has to RE-RENDER
|
|
6
|
+
* when the setting changes mid-session (a spring that becomes an instant move,
|
|
7
|
+
* a tilt that goes flat), not just read it when an animation starts.
|
|
8
|
+
*
|
|
9
|
+
* The kit had two sources for this question: the plain function in easing.ts
|
|
10
|
+
* and motion-v's `useReducedMotion`, picked per file. Both read the same media
|
|
11
|
+
* query, so this is the one reactive answer and the function stays the one
|
|
12
|
+
* point-in-time answer. motion-v's hook adds nothing the kit needs: motion-v
|
|
13
|
+
* does not consult it for its own layout animations (every caller had to turn
|
|
14
|
+
* a spring into `{ duration: 0 }` itself), and it reads the page's window, where
|
|
15
|
+
* this asks the window the component renders in (an LpFrame's, say).
|
|
16
|
+
*
|
|
17
|
+
* False until mounted, like every media query here, so a server render and the
|
|
18
|
+
* hydrating client agree; nothing animates before mount anyway.
|
|
19
|
+
*/
|
|
20
|
+
export function usePrefersReducedMotion(): Ref<boolean> {
|
|
21
|
+
return useMediaQuery("(prefers-reduced-motion: reduce)")
|
|
22
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { computed, toRaw } from "vue"
|
|
2
|
+
|
|
3
|
+
export type RepeaterItemKey<T> = keyof T | ((item: T) => string | number)
|
|
4
|
+
|
|
5
|
+
/** Keys live beside the model: unsaved rows need identity without adding fields to a DTO. */
|
|
6
|
+
export function useRepeater<T extends object>(options: {
|
|
7
|
+
value: () => T[]
|
|
8
|
+
set: (items: T[]) => void
|
|
9
|
+
createItem: () => T
|
|
10
|
+
itemKey: () => RepeaterItemKey<T> | undefined
|
|
11
|
+
disabled: () => boolean
|
|
12
|
+
}) {
|
|
13
|
+
const keys = new WeakMap<object, string>()
|
|
14
|
+
let sequence = 0
|
|
15
|
+
|
|
16
|
+
function keyFor(item: T): string {
|
|
17
|
+
const key = options.itemKey()
|
|
18
|
+
const explicit = typeof key === "function" ? key(item) : key === undefined ? undefined : item[key]
|
|
19
|
+
if (explicit !== undefined && explicit !== null) return `item:${typeof explicit}:${String(explicit)}`
|
|
20
|
+
const raw = toRaw(item)
|
|
21
|
+
if (!keys.has(raw)) keys.set(raw, `local:${sequence++}`)
|
|
22
|
+
return keys.get(raw)!
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const rows = computed(() => options.value().map((item) => ({ item, key: keyFor(item) })))
|
|
26
|
+
|
|
27
|
+
function add() {
|
|
28
|
+
if (!options.disabled()) options.set([...options.value(), options.createItem()])
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function remove(index: number) {
|
|
32
|
+
if (options.disabled() || index < 0 || index >= options.value().length) return
|
|
33
|
+
options.set(options.value().filter((_, i) => i !== index))
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function update(index: number, item: T) {
|
|
37
|
+
const previous = options.value()[index]
|
|
38
|
+
if (options.disabled() || previous === undefined) return
|
|
39
|
+
keys.set(toRaw(item), keyFor(previous))
|
|
40
|
+
options.set(options.value().map((value, i) => i === index ? item : value))
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return { rows, add, remove, update }
|
|
44
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { onScopeDispose, toValue, watch, type MaybeRefOrGetter } from "vue"
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
* "Tell me when this element changes size", for as long as the component lives.
|
|
5
|
+
*
|
|
6
|
+
* A dozen components wrote the same scaffolding around a ResizeObserver: a
|
|
7
|
+
* variable for it, a guard for engines without one (old WebKitGTK, tests),
|
|
8
|
+
* disconnect-and-reobserve when the element ref changes, disconnect on unmount.
|
|
9
|
+
* Each copy got one of those slightly different, and a missing guard is a crash
|
|
10
|
+
* rather than a style difference. This is that scaffolding once.
|
|
11
|
+
*
|
|
12
|
+
* `target` is a ref or a getter, so the observed element can be a template ref,
|
|
13
|
+
* a component's exposed element or something found from one (the scroll
|
|
14
|
+
* viewport around a table); a new element is observed in place of the old one
|
|
15
|
+
* and `null` stops observing. `immediate` also calls back right when an element
|
|
16
|
+
* is attached, without an entry, for components that must measure before the
|
|
17
|
+
* first paint: the observer's own first report arrives a frame later.
|
|
18
|
+
*/
|
|
19
|
+
export interface UseResizeObserverOptions extends ResizeObserverOptions {
|
|
20
|
+
/** Call back once as soon as an element is attached (with no entry), not only on the first report. */
|
|
21
|
+
immediate?: boolean
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function useResizeObserver(
|
|
25
|
+
target: MaybeRefOrGetter<Element | null | undefined>,
|
|
26
|
+
callback: (entry: ResizeObserverEntry | undefined, el: Element) => void,
|
|
27
|
+
options: UseResizeObserverOptions = {},
|
|
28
|
+
): { stop: () => void } {
|
|
29
|
+
const { immediate = false, ...observe } = options
|
|
30
|
+
let observer: ResizeObserver | undefined
|
|
31
|
+
|
|
32
|
+
const disconnect = () => {
|
|
33
|
+
observer?.disconnect()
|
|
34
|
+
observer = undefined
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const stopWatch = watch(
|
|
38
|
+
() => toValue(target),
|
|
39
|
+
(el) => {
|
|
40
|
+
disconnect()
|
|
41
|
+
if (!el) return
|
|
42
|
+
if (immediate) callback(undefined, el)
|
|
43
|
+
if (typeof ResizeObserver === "undefined") return
|
|
44
|
+
observer = new ResizeObserver((entries) => {
|
|
45
|
+
const entry = entries[entries.length - 1]
|
|
46
|
+
if (entry) callback(entry, el)
|
|
47
|
+
})
|
|
48
|
+
observer.observe(el, observe)
|
|
49
|
+
},
|
|
50
|
+
{ immediate: true, flush: "post" },
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
const stop = () => {
|
|
54
|
+
stopWatch()
|
|
55
|
+
disconnect()
|
|
56
|
+
}
|
|
57
|
+
onScopeDispose(stop)
|
|
58
|
+
return { stop }
|
|
59
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { computed, ref, toValue, watch, type MaybeRefOrGetter, type Ref } from "vue"
|
|
2
|
+
import { easeOut } from "./easing"
|
|
3
|
+
import { useReveal } from "./useReveal"
|
|
4
|
+
import { lerp, useTween } from "./useTween"
|
|
5
|
+
|
|
6
|
+
/*
|
|
7
|
+
* A number that waits to be seen before it moves to its value.
|
|
8
|
+
*
|
|
9
|
+
* A meter that fills (LpProgress, LpGauge, LpQuota) or a figure that counts up
|
|
10
|
+
* (LpNumberFlow) is showing a quantity being measured, and that only works if
|
|
11
|
+
* the reader sees the sweep. So the number is held at its starting point until
|
|
12
|
+
* the element is revealed (useReveal), then let go to the real value; every
|
|
13
|
+
* change after that goes straight through. Each of those components used to
|
|
14
|
+
* carry this hold-and-release by hand, and they disagreed in the corners: what
|
|
15
|
+
* a value change before the reveal does, and what the server renders.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
export interface UseRevealedValueOptions {
|
|
19
|
+
/** Where the number starts while held: 0 for a bar, the floor for a gauge. */
|
|
20
|
+
from?: MaybeRefOrGetter<number>
|
|
21
|
+
/** False shows the value at once, with nothing held. */
|
|
22
|
+
animateOnMount?: MaybeRefOrGetter<boolean>
|
|
23
|
+
/**
|
|
24
|
+
* Also tween `shown` toward the target over this many ms (eased out), for a
|
|
25
|
+
* component that draws from one interpolated number. Omitted, `shown` is the
|
|
26
|
+
* target itself, for a component that animates in CSS or through LpNumberFlow.
|
|
27
|
+
*/
|
|
28
|
+
duration?: MaybeRefOrGetter<number>
|
|
29
|
+
/**
|
|
30
|
+
* Whether a change that arrives before the reveal waits too (default) or
|
|
31
|
+
* goes through at once. A meter waits, so its first sweep is still seen;
|
|
32
|
+
* LpNumberFlow lets it through, because a figure that changes while the user
|
|
33
|
+
* is on the page is news whether or not it is in view.
|
|
34
|
+
*/
|
|
35
|
+
holdChanges?: boolean
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface UseRevealedValue {
|
|
39
|
+
/** Attach to the element whose appearance releases the value. */
|
|
40
|
+
el: Ref<Element | null>
|
|
41
|
+
/** False until that element has been seen. */
|
|
42
|
+
revealed: Ref<boolean>
|
|
43
|
+
/** The value released so far: `from` while held, then the source. */
|
|
44
|
+
target: Readonly<Ref<number>>
|
|
45
|
+
/** What to draw: `target`, tweened when a `duration` is given. */
|
|
46
|
+
shown: Readonly<Ref<number>>
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function useRevealedValue(
|
|
50
|
+
value: () => number,
|
|
51
|
+
options: UseRevealedValueOptions = {},
|
|
52
|
+
): UseRevealedValue {
|
|
53
|
+
const animate = () => toValue(options.animateOnMount) ?? true
|
|
54
|
+
const { el, revealed } = useReveal({ immediate: () => !animate() })
|
|
55
|
+
|
|
56
|
+
/*
|
|
57
|
+
* The server has no viewport, so useReveal reports it revealed; releasing
|
|
58
|
+
* there would render the final value and the client, which starts held,
|
|
59
|
+
* would hydrate a different one. The server renders the starting point and
|
|
60
|
+
* the client releases it once the element is seen.
|
|
61
|
+
*/
|
|
62
|
+
const canRelease = () => !animate() || typeof window !== "undefined"
|
|
63
|
+
|
|
64
|
+
const target = ref(animate() ? (toValue(options.from) ?? 0) : value())
|
|
65
|
+
|
|
66
|
+
watch(
|
|
67
|
+
revealed,
|
|
68
|
+
(seen) => {
|
|
69
|
+
if (seen && canRelease()) target.value = value()
|
|
70
|
+
},
|
|
71
|
+
{ immediate: true },
|
|
72
|
+
)
|
|
73
|
+
watch(value, (v) => {
|
|
74
|
+
if (revealed.value || options.holdChanges === false) target.value = v
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
const duration = options.duration
|
|
78
|
+
const shown =
|
|
79
|
+
duration === undefined
|
|
80
|
+
? computed(() => target.value)
|
|
81
|
+
: useTween(() => target.value, lerp, { duration: () => toValue(duration), ease: easeOut })
|
|
82
|
+
|
|
83
|
+
return { el, revealed, target, shown }
|
|
84
|
+
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { computed, onScopeDispose, shallowRef, toValue, watch, type ComputedRef, type MaybeRefOrGetter, type ShallowRef } from "vue"
|
|
2
|
+
import {
|
|
3
|
+
planScramble,
|
|
4
|
+
scrambleFrame,
|
|
5
|
+
settledCells,
|
|
6
|
+
SCRAMBLE_GLYPHS,
|
|
7
|
+
type Random,
|
|
8
|
+
type ScrambleCell,
|
|
9
|
+
type ScrambleFrameCell,
|
|
10
|
+
} from "../components/scramble"
|
|
11
|
+
import { prefersReducedMotion } from "./easing"
|
|
12
|
+
|
|
13
|
+
/*
|
|
14
|
+
* A value that "decrypts" into place: each position churns through random
|
|
15
|
+
* glyphs and settles on its character.
|
|
16
|
+
*
|
|
17
|
+
* For values that are revealed rather than read: an API key shown after a
|
|
18
|
+
* click, a hash arriving from a job, a code a user is about to copy. The churn
|
|
19
|
+
* says "this was just produced" in a way a plain swap does not.
|
|
20
|
+
*
|
|
21
|
+
* The composable owns the clock; the frames themselves come from the pure
|
|
22
|
+
* functions in components/scramble.ts. It hands back CELLS rather than only a
|
|
23
|
+
* string, because a component that wants the width to hold still needs to know
|
|
24
|
+
* which character each position will end as (LpScramble sizes each cell by it).
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
export interface UseScrambleOptions {
|
|
28
|
+
/** Travel time in ms. */
|
|
29
|
+
duration?: MaybeRefOrGetter<number | undefined>
|
|
30
|
+
/** See ScrambleOptions.order. */
|
|
31
|
+
order?: MaybeRefOrGetter<"sequential" | "together" | undefined>
|
|
32
|
+
/** Glyph pool. */
|
|
33
|
+
glyphs?: MaybeRefOrGetter<string | undefined>
|
|
34
|
+
/** Characters that never churn. Whitespace by default. */
|
|
35
|
+
keep?: (char: string) => boolean
|
|
36
|
+
/**
|
|
37
|
+
* How often a churning position draws a new glyph, in ms. Every frame is too
|
|
38
|
+
* fast to read as anything but noise; ~50 ms looks like a display cycling.
|
|
39
|
+
*/
|
|
40
|
+
tick?: number
|
|
41
|
+
/** Scramble when the source changes. Off: a change lands at once and only `play()` scrambles. */
|
|
42
|
+
onChange?: MaybeRefOrGetter<boolean | undefined>
|
|
43
|
+
/**
|
|
44
|
+
* What shows before the first `play()`: the value (`settled`) or a static
|
|
45
|
+
* mask of glyphs (`masked`), for a value that should decrypt on first sight
|
|
46
|
+
* rather than flash its plain text first.
|
|
47
|
+
*/
|
|
48
|
+
start?: "settled" | "masked"
|
|
49
|
+
/** Inject for reproducible frames (tests, screenshots). */
|
|
50
|
+
random?: Random
|
|
51
|
+
/** Called when a run lands. */
|
|
52
|
+
onDone?: () => void
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface UseScramble {
|
|
56
|
+
/** The positions as they are drawn now. */
|
|
57
|
+
cells: Readonly<ShallowRef<ScrambleFrameCell[]>>
|
|
58
|
+
/** The same as one string. */
|
|
59
|
+
text: ComputedRef<string>
|
|
60
|
+
/** A run is in progress. */
|
|
61
|
+
running: Readonly<ShallowRef<boolean>>
|
|
62
|
+
/** Scramble from what is shown now into the source value (into itself when unchanged). */
|
|
63
|
+
play: () => void
|
|
64
|
+
/** Land at once on the source value. */
|
|
65
|
+
settle: () => void
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function useScramble(source: MaybeRefOrGetter<string>, options: UseScrambleOptions = {}): UseScramble {
|
|
69
|
+
const random = options.random ?? Math.random
|
|
70
|
+
const tick = options.tick ?? 50
|
|
71
|
+
const glyphs = () => toValue(options.glyphs) || SCRAMBLE_GLYPHS
|
|
72
|
+
|
|
73
|
+
const initial = toValue(source)
|
|
74
|
+
const cells = shallowRef<ScrambleFrameCell[]>(
|
|
75
|
+
options.start === "masked"
|
|
76
|
+
? scrambleFrame(planScramble(initial, initial, { duration: 1, keep: options.keep }, random), 0, random, glyphs())
|
|
77
|
+
: settledCells(initial),
|
|
78
|
+
)
|
|
79
|
+
const running = shallowRef(false)
|
|
80
|
+
const text = computed(() => cells.value.map((cell) => cell.char).join(""))
|
|
81
|
+
|
|
82
|
+
let frame = 0
|
|
83
|
+
let plan: ScrambleCell[] = []
|
|
84
|
+
let started = 0
|
|
85
|
+
let lastRoll = 0
|
|
86
|
+
|
|
87
|
+
const stopFrame = () => {
|
|
88
|
+
if (frame && typeof cancelAnimationFrame !== "undefined") cancelAnimationFrame(frame)
|
|
89
|
+
frame = 0
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function settle() {
|
|
93
|
+
stopFrame()
|
|
94
|
+
cells.value = settledCells(toValue(source))
|
|
95
|
+
if (running.value) {
|
|
96
|
+
running.value = false
|
|
97
|
+
options.onDone?.()
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function step(now: number) {
|
|
102
|
+
const elapsed = now - started
|
|
103
|
+
const duration = Math.max(1, toValue(options.duration) ?? 900)
|
|
104
|
+
if (elapsed >= duration) return settle()
|
|
105
|
+
if (now - lastRoll >= tick) {
|
|
106
|
+
lastRoll = now
|
|
107
|
+
cells.value = scrambleFrame(plan, elapsed, random, glyphs())
|
|
108
|
+
} else {
|
|
109
|
+
// Between re-rolls only the positions that just landed change, so the
|
|
110
|
+
// settle front moves smoothly while the churn keeps its own rate.
|
|
111
|
+
const shown = cells.value
|
|
112
|
+
let changed = false
|
|
113
|
+
const next = shown.map((cell, i) => {
|
|
114
|
+
const p = plan[i]
|
|
115
|
+
if (!cell.settled && p && (p.fixed || elapsed >= p.settleAt)) {
|
|
116
|
+
changed = true
|
|
117
|
+
return { char: p.final, sizer: p.final, settled: true }
|
|
118
|
+
}
|
|
119
|
+
return cell
|
|
120
|
+
})
|
|
121
|
+
if (changed) cells.value = next
|
|
122
|
+
}
|
|
123
|
+
frame = requestAnimationFrame(step)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function play() {
|
|
127
|
+
const to = toValue(source)
|
|
128
|
+
const duration = toValue(options.duration) ?? 900
|
|
129
|
+
if (prefersReducedMotion() || duration <= 0 || typeof requestAnimationFrame === "undefined") return settle()
|
|
130
|
+
stopFrame()
|
|
131
|
+
// From what is DRAWN: a change that lands mid-run carries on from the
|
|
132
|
+
// positions as they are, instead of snapping back to the old value first.
|
|
133
|
+
const from = cells.value.map((cell) => cell.sizer).join("")
|
|
134
|
+
plan = planScramble(from, to, { duration, order: toValue(options.order), keep: options.keep }, random)
|
|
135
|
+
started = performance.now()
|
|
136
|
+
lastRoll = -Infinity
|
|
137
|
+
running.value = true
|
|
138
|
+
frame = requestAnimationFrame(step)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
watch(
|
|
142
|
+
() => toValue(source),
|
|
143
|
+
() => {
|
|
144
|
+
if (toValue(options.onChange) === false) settle()
|
|
145
|
+
else play()
|
|
146
|
+
},
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
onScopeDispose(stopFrame)
|
|
150
|
+
|
|
151
|
+
return { cells, text, running, play, settle }
|
|
152
|
+
}
|
|
@@ -180,22 +180,16 @@ export function useShift(
|
|
|
180
180
|
const fromWidth = lastWidth
|
|
181
181
|
const tops = readScroll()
|
|
182
182
|
|
|
183
|
-
// Measured
|
|
184
|
-
//
|
|
185
|
-
//
|
|
186
|
-
//
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
if (wantsWidth()) {
|
|
192
|
-
node.style.width = ""
|
|
193
|
-
node.style.maxWidth = "none"
|
|
194
|
-
}
|
|
183
|
+
// Measured where the box will settle: free of the pinned size, but with
|
|
184
|
+
// its `max-*` in place. The target used to be read with the cap lifted
|
|
185
|
+
// while the settled size was read with it, so a box whose content is
|
|
186
|
+
// wider than its cap never matched its own target: every render started
|
|
187
|
+
// another tween and it never came to rest (a breadcrumb trail too wide for
|
|
188
|
+
// its bar re-animated some sixty times a second).
|
|
189
|
+
if (wantsHeight()) node.style.height = ""
|
|
190
|
+
if (wantsWidth()) node.style.width = ""
|
|
195
191
|
const toHeight = wantsHeight() ? node.offsetHeight : 0
|
|
196
192
|
const toWidth = wantsWidth() ? node.offsetWidth : 0
|
|
197
|
-
if (wantsHeight()) node.style.maxHeight = ""
|
|
198
|
-
if (wantsWidth()) node.style.maxWidth = ""
|
|
199
193
|
restoreScroll(tops)
|
|
200
194
|
lastHeight = toHeight
|
|
201
195
|
lastWidth = toWidth
|
|
@@ -239,8 +233,8 @@ export function useShift(
|
|
|
239
233
|
// clearing it let the box spread to the window's edges.
|
|
240
234
|
if (wantsHeight()) node.style.height = ""
|
|
241
235
|
if (wantsWidth()) node.style.width = ""
|
|
242
|
-
// Re-read rather than trusting the target:
|
|
243
|
-
//
|
|
236
|
+
// Re-read rather than trusting the target: the layout around may have
|
|
237
|
+
// moved meanwhile, and the next tween has to start from where it sits.
|
|
244
238
|
lastHeight = node.offsetHeight
|
|
245
239
|
lastWidth = node.offsetWidth
|
|
246
240
|
}, wait)
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { onBeforeUnmount, ref, toValue, watch, type MaybeRefOrGetter, type Ref } from "vue"
|
|
2
|
+
import { usePointerFrame } from "./usePointerFrame"
|
|
3
|
+
|
|
4
|
+
/*
|
|
5
|
+
* Drives the `.lp-spotlight` glow (tokens/effects.css): writes the pointer
|
|
6
|
+
* position into custom properties on the element and marks it while the
|
|
7
|
+
* pointer is inside.
|
|
8
|
+
*
|
|
9
|
+
* Writes go straight to the element's style, not through a reactive binding,
|
|
10
|
+
* one per animation frame with the latest position (usePointerFrame, shared
|
|
11
|
+
* with LpMagnetic and useTilt). Touch and pen are ignored: a glow that jumps
|
|
12
|
+
* to wherever a finger landed reads as a pressed state that is not one.
|
|
13
|
+
* Reduced motion turns it off rather than freezing it.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
export interface UseSpotlightOptions {
|
|
17
|
+
/** Switch the effect off without unbinding — the listeners stay, nothing is drawn. */
|
|
18
|
+
disabled?: MaybeRefOrGetter<boolean | undefined>
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface UseSpotlight {
|
|
22
|
+
/** Attach to the element carrying `.lp-spotlight`. */
|
|
23
|
+
el: Ref<HTMLElement | null>
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Pointer position relative to a rect, in px, as the CSS custom properties want it. */
|
|
27
|
+
export function spotlightPoint(rect: { left: number; top: number }, clientX: number, clientY: number) {
|
|
28
|
+
return { x: `${Math.round(clientX - rect.left)}px`, y: `${Math.round(clientY - rect.top)}px` }
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function useSpotlight(options: UseSpotlightOptions = {}): UseSpotlight {
|
|
32
|
+
const el = ref<HTMLElement | null>(null)
|
|
33
|
+
|
|
34
|
+
const pointer = usePointerFrame({
|
|
35
|
+
disabled: options.disabled,
|
|
36
|
+
paint: (clientX, clientY) => {
|
|
37
|
+
const node = el.value
|
|
38
|
+
if (!node) return
|
|
39
|
+
const { x, y } = spotlightPoint(node.getBoundingClientRect(), clientX, clientY)
|
|
40
|
+
node.style.setProperty("--lp-spot-x", x)
|
|
41
|
+
node.style.setProperty("--lp-spot-y", y)
|
|
42
|
+
},
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
function onMove(event: PointerEvent) {
|
|
46
|
+
if (pointer.move(event)) el.value?.setAttribute("data-lp-spot", "")
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function onLeave() {
|
|
50
|
+
el.value?.removeAttribute("data-lp-spot")
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function detach(node: HTMLElement) {
|
|
54
|
+
node.removeEventListener("pointermove", onMove)
|
|
55
|
+
node.removeEventListener("pointerleave", onLeave)
|
|
56
|
+
node.removeAttribute("data-lp-spot")
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
watch(
|
|
60
|
+
el,
|
|
61
|
+
(node, previous) => {
|
|
62
|
+
if (previous) detach(previous)
|
|
63
|
+
if (!node) return
|
|
64
|
+
node.addEventListener("pointermove", onMove, { passive: true })
|
|
65
|
+
node.addEventListener("pointerleave", onLeave, { passive: true })
|
|
66
|
+
},
|
|
67
|
+
{ flush: "post" },
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
watch(
|
|
71
|
+
() => toValue(options.disabled),
|
|
72
|
+
(disabled) => {
|
|
73
|
+
if (disabled) onLeave()
|
|
74
|
+
},
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
onBeforeUnmount(() => {
|
|
78
|
+
if (el.value) detach(el.value)
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
return { el }
|
|
82
|
+
}
|