@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
|
@@ -44,11 +44,15 @@ import { useShift } from "../composables/useShift"
|
|
|
44
44
|
import { useLabels } from "../composables/useLpConfig"
|
|
45
45
|
import { mergeClass } from "../composables/useMergedClass"
|
|
46
46
|
import LpFieldNotice from "./LpFieldNotice.vue"
|
|
47
|
-
import
|
|
47
|
+
import FieldWrapper from "./FieldWrapper.vue"
|
|
48
|
+
import { BADGE_REMOVE } from "./badge"
|
|
49
|
+
import LpBadge from "./LpBadge.vue"
|
|
48
50
|
import LpIcon from "./LpIcon.vue"
|
|
49
|
-
import
|
|
51
|
+
import OptionContent from "./OptionContent.vue"
|
|
52
|
+
import { OPTION_ITEM, optionStagger, POPOVER_PANEL } from "./dropdown"
|
|
50
53
|
import type { LpOptionBase, OptionSelection } from "./options"
|
|
51
54
|
import { addTags, splitTags, type TagDuplicates, type TagRejection, type TagValidator } from "./tags"
|
|
55
|
+
import { useOutsideGuard, usePortalTarget } from "../composables/useView"
|
|
52
56
|
|
|
53
57
|
const props = withDefaults(
|
|
54
58
|
defineProps<{
|
|
@@ -327,6 +331,7 @@ function choose(opt: LpOptionBase<string>): void {
|
|
|
327
331
|
|
|
328
332
|
/** Clicks on the box itself are not "outside" the list: they are typing. */
|
|
329
333
|
function keepOpenInside(event: Event): void {
|
|
334
|
+
guardOutside(event)
|
|
330
335
|
const target = event.target
|
|
331
336
|
if (target instanceof Node && boxEl.value?.contains(target)) event.preventDefault()
|
|
332
337
|
}
|
|
@@ -413,19 +418,25 @@ function onModel(value: (string | Record<string, unknown>)[] | null): void {
|
|
|
413
418
|
}
|
|
414
419
|
|
|
415
420
|
defineExpose({ focus: () => inputEl.value?.focus(), add: (value: string) => add(value) })
|
|
421
|
+
|
|
422
|
+
// Overlays open in the window this component renders in (an LpFrame's, inside one).
|
|
423
|
+
const portalTo = usePortalTarget()
|
|
424
|
+
// What happens in another document (the page around a frame, or a frame in
|
|
425
|
+
// the page) is not "outside" for this layer.
|
|
426
|
+
const guardOutside = useOutsideGuard()
|
|
416
427
|
</script>
|
|
417
428
|
|
|
418
429
|
<template>
|
|
419
|
-
<
|
|
420
|
-
:
|
|
430
|
+
<FieldWrapper
|
|
431
|
+
:wrapped="hasField"
|
|
421
432
|
:ref="bindField"
|
|
422
|
-
:
|
|
423
|
-
:
|
|
424
|
-
:
|
|
425
|
-
:
|
|
426
|
-
:
|
|
427
|
-
:class="
|
|
428
|
-
:style="
|
|
433
|
+
:id="field.id"
|
|
434
|
+
:label="label"
|
|
435
|
+
:hint="hint"
|
|
436
|
+
:error="error"
|
|
437
|
+
:required="required"
|
|
438
|
+
:class="attrs.class"
|
|
439
|
+
:style="attrs.style"
|
|
429
440
|
>
|
|
430
441
|
<div class="relative">
|
|
431
442
|
<TagsInputRoot
|
|
@@ -458,29 +469,39 @@ defineExpose({ focus: () => inputEl.value?.focus(), add: (value: string) => add(
|
|
|
458
469
|
enter-active-class="animate-[chip-in_var(--duration-fast)_var(--ease-emphasized)] motion-reduce:animate-none"
|
|
459
470
|
leave-active-class="animate-[chip-out_var(--duration-fast)_ease] motion-reduce:animate-none"
|
|
460
471
|
>
|
|
472
|
+
<!-- The chip is the kit's removable badge; reka's item and delete
|
|
473
|
+
primitives ride on it (as-child, the #remove slot) because they
|
|
474
|
+
own the keyboard: arrows between tags, Backspace to remove. -->
|
|
461
475
|
<TagsInputItem
|
|
462
476
|
v-for="{ tag, key, shown } in keyed"
|
|
463
477
|
:key="key"
|
|
464
|
-
|
|
478
|
+
as-child
|
|
465
479
|
:value="tag"
|
|
466
|
-
class="inline-flex max-w-full items-center gap-1 rounded-pill bg-surface-raised py-0.5 pr-1 text-xs font-medium text-ink outline-none data-[state=active]:ring-2 data-[state=active]:ring-ring"
|
|
467
|
-
:class="shown?.image ? 'pl-0.5' : 'pl-2.5'"
|
|
468
480
|
>
|
|
469
|
-
<
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
</template>
|
|
475
|
-
<span v-else class="truncate">{{ tag }}</span>
|
|
476
|
-
</TagsInputItemText>
|
|
477
|
-
<TagsInputItemDelete
|
|
478
|
-
:aria-labelledby="undefined"
|
|
479
|
-
:aria-label="text.remove.replace('{tag}', shown?.label ?? tag)"
|
|
480
|
-
class="grid size-4 shrink-0 place-items-center rounded-pill text-muted transition-colors hover:bg-ink/10 hover:text-ink"
|
|
481
|
+
<LpBadge
|
|
482
|
+
removable
|
|
483
|
+
:data-tag-key="key"
|
|
484
|
+
class="max-w-full bg-surface-raised text-ink outline-none data-[state=active]:ring-2 data-[state=active]:ring-ring"
|
|
485
|
+
:class="shown?.image ? 'pl-0.5' : ''"
|
|
481
486
|
>
|
|
482
|
-
<
|
|
483
|
-
|
|
487
|
+
<img v-if="shown?.image" :src="shown.image" alt="" class="size-4 shrink-0 rounded-full object-cover" />
|
|
488
|
+
<TagsInputItemText class="flex min-w-0 items-baseline gap-1">
|
|
489
|
+
<template v-if="shown">
|
|
490
|
+
<span class="truncate">{{ shown.label }}</span>
|
|
491
|
+
<span v-if="shown.hint" class="truncate font-normal text-muted">{{ shown.hint }}</span>
|
|
492
|
+
</template>
|
|
493
|
+
<span v-else class="truncate">{{ tag }}</span>
|
|
494
|
+
</TagsInputItemText>
|
|
495
|
+
<template #remove>
|
|
496
|
+
<TagsInputItemDelete
|
|
497
|
+
:aria-labelledby="undefined"
|
|
498
|
+
:aria-label="text.remove.replace('{tag}', shown?.label ?? tag)"
|
|
499
|
+
:class="BADGE_REMOVE"
|
|
500
|
+
>
|
|
501
|
+
<LpIcon name="lucide:x" :size="12" />
|
|
502
|
+
</TagsInputItemDelete>
|
|
503
|
+
</template>
|
|
504
|
+
</LpBadge>
|
|
484
505
|
</TagsInputItem>
|
|
485
506
|
</TransitionGroup>
|
|
486
507
|
<TagsInputInput
|
|
@@ -505,7 +526,7 @@ defineExpose({ focus: () => inputEl.value?.focus(), add: (value: string) => add(
|
|
|
505
526
|
<LpFieldNotice v-if="standalone" :notice="notice" :id="noticeId" />
|
|
506
527
|
<PopoverRoot v-if="options" :open="listOpen" @update:open="(o) => !o && (dismissed = true)">
|
|
507
528
|
<PopoverAnchor v-if="boxEl" :reference="boxEl" class="hidden" />
|
|
508
|
-
<PopoverPortal>
|
|
529
|
+
<PopoverPortal :to="portalTo">
|
|
509
530
|
<PopoverContent
|
|
510
531
|
:id="listId"
|
|
511
532
|
role="listbox"
|
|
@@ -533,18 +554,13 @@ defineExpose({ focus: () => inputEl.value?.focus(), add: (value: string) => add(
|
|
|
533
554
|
:aria-disabled="opt.disabled || undefined"
|
|
534
555
|
:data-highlighted="i === activeIndex ? '' : undefined"
|
|
535
556
|
:data-disabled="opt.disabled ? '' : undefined"
|
|
536
|
-
:style="
|
|
557
|
+
:style="optionStagger(i)"
|
|
537
558
|
:class="[OPTION_ITEM, 'data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50']"
|
|
538
559
|
@pointerdown.prevent
|
|
539
560
|
@pointermove="activeIndex = i"
|
|
540
561
|
@click="!opt.disabled && choose(opt)"
|
|
541
562
|
>
|
|
542
|
-
<
|
|
543
|
-
<LpIcon v-else-if="opt.icon" :name="opt.icon" :size="16" class="shrink-0 text-muted" />
|
|
544
|
-
<span class="flex min-w-0 flex-col">
|
|
545
|
-
<span class="truncate">{{ opt.label ?? opt.value }}</span>
|
|
546
|
-
<span v-if="opt.description" class="truncate text-xs text-muted">{{ opt.description }}</span>
|
|
547
|
-
</span>
|
|
563
|
+
<OptionContent :option="opt" />
|
|
548
564
|
</div>
|
|
549
565
|
</template>
|
|
550
566
|
</PopoverContent>
|
|
@@ -552,5 +568,5 @@ defineExpose({ focus: () => inputEl.value?.focus(), add: (value: string) => add(
|
|
|
552
568
|
</PopoverRoot>
|
|
553
569
|
</div>
|
|
554
570
|
<span class="sr-only" aria-live="polite">{{ announcement }}</span>
|
|
555
|
-
</
|
|
571
|
+
</FieldWrapper>
|
|
556
572
|
</template>
|
|
@@ -0,0 +1,236 @@
|
|
|
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
|
+
* Text that arrives word by word (or letter by letter): each piece fades in,
|
|
9
|
+
* rises a few pixels and comes into focus, one after another.
|
|
10
|
+
*
|
|
11
|
+
* For a line that is the point of the screen: a hero heading, an empty state's
|
|
12
|
+
* message, a result that was just computed. On body copy it only slows reading
|
|
13
|
+
* down, so it is not a default for text in general.
|
|
14
|
+
*
|
|
15
|
+
* <LpTextReveal text="Your server is ready" as="h2" />
|
|
16
|
+
* <LpTextReveal :text="summary" by="letter" :stagger="15" />
|
|
17
|
+
*
|
|
18
|
+
* It plays the first time the text is on screen (useReveal), not at mount, so
|
|
19
|
+
* a heading below the fold is still arriving when it is scrolled to. `play`
|
|
20
|
+
* takes over when the moment is the app's to decide (a step becoming active),
|
|
21
|
+
* and a new `replayKey` plays it again.
|
|
22
|
+
*
|
|
23
|
+
* When `text` changes, the words that stay keep their place and do not replay:
|
|
24
|
+
* the words that are gone fade out, the new ones arrive in their spot. A status
|
|
25
|
+
* line going from "3 builds running" to "4 builds running" moves one word, not
|
|
26
|
+
* the whole sentence.
|
|
27
|
+
*
|
|
28
|
+
* Screen readers get the whole string once; the split pieces are hidden from
|
|
29
|
+
* them, so the sentence is not read as a list of separate words. The pieces
|
|
30
|
+
* are inline boxes separated by real spaces, so the text wraps like any other.
|
|
31
|
+
*/
|
|
32
|
+
import { computed, onBeforeUnmount, ref, watch } from "vue"
|
|
33
|
+
import { prefersReducedMotion } from "../composables/easing"
|
|
34
|
+
import { useMergedAttrs } from "../composables/useMergedClass"
|
|
35
|
+
import { useReveal } from "../composables/useReveal"
|
|
36
|
+
import { splitText, wordKeys, type TextPiece } from "./textSplit"
|
|
37
|
+
|
|
38
|
+
const props = withDefaults(
|
|
39
|
+
defineProps<{
|
|
40
|
+
/** The text. A change animates only the words that changed. */
|
|
41
|
+
text: string
|
|
42
|
+
/** The unit that animates. Letters suit a short heading; words read better on a sentence. */
|
|
43
|
+
by?: "word" | "letter"
|
|
44
|
+
/** Delay between pieces in ms. Defaults to 70 for words, 22 for letters. */
|
|
45
|
+
stagger?: number
|
|
46
|
+
/** Each piece's entrance in ms. */
|
|
47
|
+
duration?: number
|
|
48
|
+
/** How far a piece rises, in px. 0 for a pure fade. */
|
|
49
|
+
rise?: number
|
|
50
|
+
/** Start out of focus and sharpen. Off for long text on a slow machine, where a blur per piece costs frames. */
|
|
51
|
+
blur?: boolean
|
|
52
|
+
/**
|
|
53
|
+
* Hold the text hidden until true. Leave unset to play the first time the
|
|
54
|
+
* text is on screen.
|
|
55
|
+
*/
|
|
56
|
+
play?: boolean
|
|
57
|
+
/** Changing this plays the whole text again (the old one fades out first). */
|
|
58
|
+
replayKey?: unknown
|
|
59
|
+
/** Element to render: `h1`…`h6` or `p` for a heading or a paragraph. */
|
|
60
|
+
as?: string
|
|
61
|
+
}>(),
|
|
62
|
+
{ by: "word", duration: 560, rise: 8, blur: true, play: undefined, as: "span" },
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
const emit = defineEmits<{
|
|
66
|
+
/** The last piece has arrived. */
|
|
67
|
+
done: []
|
|
68
|
+
}>()
|
|
69
|
+
|
|
70
|
+
const { class: rootClass, attrs: rest } = useMergedAttrs(() => "lp-reveal")
|
|
71
|
+
|
|
72
|
+
const LEAVE_MS = 180
|
|
73
|
+
|
|
74
|
+
const { el, revealed } = useReveal({ immediate: () => props.play !== undefined })
|
|
75
|
+
const ready = computed(() => props.play ?? revealed.value)
|
|
76
|
+
|
|
77
|
+
const shown = ref(props.text)
|
|
78
|
+
const generation = ref(0)
|
|
79
|
+
const pieces = computed<TextPiece[]>(() =>
|
|
80
|
+
splitText(shown.value, props.by).map((p) => ({ ...p, key: `${generation.value}:${p.key}` })),
|
|
81
|
+
)
|
|
82
|
+
// The words that animate in on this pass; everything else stays as it is.
|
|
83
|
+
const fresh = ref<Set<string>>(wordKeys(pieces.value))
|
|
84
|
+
const leaving = ref<Set<string>>(new Set())
|
|
85
|
+
|
|
86
|
+
const stagger = computed(() => props.stagger ?? (props.by === "letter" ? 22 : 70))
|
|
87
|
+
|
|
88
|
+
// The position of each fresh part in the cascade. Counted over fresh parts only,
|
|
89
|
+
// so a single changed word in a long line starts at once instead of waiting for
|
|
90
|
+
// the words before it.
|
|
91
|
+
const order = computed(() => {
|
|
92
|
+
const map = new Map<string, number>()
|
|
93
|
+
let i = 0
|
|
94
|
+
for (const piece of pieces.value) {
|
|
95
|
+
if (piece.kind !== "word" || !fresh.value.has(piece.key)) continue
|
|
96
|
+
map.set(piece.key, i)
|
|
97
|
+
i += piece.parts.length
|
|
98
|
+
}
|
|
99
|
+
return { map, count: i }
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
let leaveTimer: ReturnType<typeof setTimeout> | undefined
|
|
103
|
+
let doneTimer: ReturnType<typeof setTimeout> | undefined
|
|
104
|
+
|
|
105
|
+
function scheduleDone() {
|
|
106
|
+
clearTimeout(doneTimer)
|
|
107
|
+
if (!ready.value) return
|
|
108
|
+
const count = order.value.count
|
|
109
|
+
const ms = prefersReducedMotion() || count === 0 ? 0 : props.duration + stagger.value * (count - 1)
|
|
110
|
+
doneTimer = setTimeout(() => emit("done"), ms)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function apply(text: string, bump: boolean) {
|
|
114
|
+
const before = wordKeys(pieces.value)
|
|
115
|
+
if (bump) generation.value++
|
|
116
|
+
shown.value = text
|
|
117
|
+
const after = wordKeys(pieces.value)
|
|
118
|
+
// Before the reveal everything is still to come; after it, only what is new.
|
|
119
|
+
fresh.value = ready.value ? new Set([...after].filter((k) => !before.has(k))) : after
|
|
120
|
+
leaving.value = new Set()
|
|
121
|
+
scheduleDone()
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function change(text: string, bump: boolean) {
|
|
125
|
+
clearTimeout(leaveTimer)
|
|
126
|
+
if (!ready.value || prefersReducedMotion()) return apply(text, bump)
|
|
127
|
+
const next = new Set(
|
|
128
|
+
splitText(text, props.by).map((p) => `${generation.value + (bump ? 1 : 0)}:${p.key}`),
|
|
129
|
+
)
|
|
130
|
+
const gone = [...wordKeys(pieces.value)].filter((k) => !next.has(k))
|
|
131
|
+
if (!gone.length) return apply(text, bump)
|
|
132
|
+
leaving.value = new Set(gone)
|
|
133
|
+
leaveTimer = setTimeout(() => apply(text, bump), LEAVE_MS)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
watch(() => props.text, (text) => change(text, false))
|
|
137
|
+
watch(() => props.replayKey, () => change(props.text, true))
|
|
138
|
+
watch(() => props.by, () => apply(props.text, true))
|
|
139
|
+
watch(ready, (now) => now && scheduleDone(), { immediate: true })
|
|
140
|
+
|
|
141
|
+
onBeforeUnmount(() => {
|
|
142
|
+
clearTimeout(leaveTimer)
|
|
143
|
+
clearTimeout(doneTimer)
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
const style = computed(() => ({
|
|
147
|
+
"--lp-reveal-duration": `${props.duration}ms`,
|
|
148
|
+
"--lp-reveal-stagger": `${stagger.value}ms`,
|
|
149
|
+
"--lp-reveal-rise": `${props.rise}px`,
|
|
150
|
+
"--lp-reveal-blur": props.blur ? "4px" : "0px",
|
|
151
|
+
"--lp-reveal-leave": `${LEAVE_MS}ms`,
|
|
152
|
+
}))
|
|
153
|
+
|
|
154
|
+
// A leaving word drops its entrance: an animation's fill outranks the fade-out
|
|
155
|
+
// declaration, and the word would stay fully visible until it is removed.
|
|
156
|
+
function partClass(key: string) {
|
|
157
|
+
if (leaving.value.has(key)) return "lp-reveal__part lp-reveal__part--out"
|
|
158
|
+
return ready.value && fresh.value.has(key) ? "lp-reveal__part lp-reveal__part--in" : "lp-reveal__part"
|
|
159
|
+
}
|
|
160
|
+
</script>
|
|
161
|
+
|
|
162
|
+
<template>
|
|
163
|
+
<component
|
|
164
|
+
:is="as"
|
|
165
|
+
ref="el"
|
|
166
|
+
:class="[rootClass, ready ? '' : 'lp-reveal--waiting']"
|
|
167
|
+
:style="style"
|
|
168
|
+
v-bind="rest"
|
|
169
|
+
>
|
|
170
|
+
<span class="sr-only">{{ text }}</span>
|
|
171
|
+
<span aria-hidden="true"
|
|
172
|
+
><template v-for="piece in pieces" :key="piece.key"
|
|
173
|
+
><template v-if="piece.kind === 'space'">{{ piece.text }}</template
|
|
174
|
+
><span
|
|
175
|
+
v-else-if="by === 'word'"
|
|
176
|
+
:class="partClass(piece.key)"
|
|
177
|
+
:style="{ '--lp-reveal-i': order.map.get(piece.key) ?? 0 }"
|
|
178
|
+
>{{ piece.text }}</span
|
|
179
|
+
><span
|
|
180
|
+
v-else
|
|
181
|
+
class="inline-block whitespace-nowrap"
|
|
182
|
+
:class="leaving.has(piece.key) ? 'lp-reveal__part--out' : ''"
|
|
183
|
+
><span
|
|
184
|
+
v-for="(letter, j) in piece.parts"
|
|
185
|
+
:key="j"
|
|
186
|
+
:class="leaving.has(piece.key) ? 'lp-reveal__part' : partClass(piece.key)"
|
|
187
|
+
:style="{ '--lp-reveal-i': (order.map.get(piece.key) ?? 0) + j }"
|
|
188
|
+
>{{ letter }}</span
|
|
189
|
+
></span
|
|
190
|
+
></template
|
|
191
|
+
></span
|
|
192
|
+
>
|
|
193
|
+
</component>
|
|
194
|
+
</template>
|
|
195
|
+
|
|
196
|
+
<style>
|
|
197
|
+
/* Unscoped and namespaced, like LpRollingText: the classes are toggled on
|
|
198
|
+
elements rendered inside a v-for of fragments. */
|
|
199
|
+
.lp-reveal__part {
|
|
200
|
+
display: inline-block;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
.lp-reveal--waiting .lp-reveal__part {
|
|
204
|
+
opacity: 0;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.lp-reveal__part--in {
|
|
208
|
+
animation: lp-reveal-in var(--lp-reveal-duration) var(--ease-emphasized) both;
|
|
209
|
+
animation-delay: calc(var(--lp-reveal-i, 0) * var(--lp-reveal-stagger));
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
.lp-reveal__part--out {
|
|
213
|
+
opacity: 0;
|
|
214
|
+
filter: blur(var(--lp-reveal-blur));
|
|
215
|
+
transition:
|
|
216
|
+
opacity var(--lp-reveal-leave) ease-in,
|
|
217
|
+
filter var(--lp-reveal-leave) ease-in;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
@keyframes lp-reveal-in {
|
|
221
|
+
from {
|
|
222
|
+
opacity: 0;
|
|
223
|
+
transform: translateY(var(--lp-reveal-rise));
|
|
224
|
+
filter: blur(var(--lp-reveal-blur));
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
@media (prefers-reduced-motion: reduce) {
|
|
229
|
+
.lp-reveal__part--in {
|
|
230
|
+
animation: none;
|
|
231
|
+
}
|
|
232
|
+
.lp-reveal__part--out {
|
|
233
|
+
transition: none;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
</style>
|
|
@@ -6,7 +6,7 @@ export default { inheritAttrs: false }
|
|
|
6
6
|
import { computed, useAttrs } from "vue"
|
|
7
7
|
import { useFieldControl } from "../composables/useField"
|
|
8
8
|
import { mergeClass } from "../composables/useMergedClass"
|
|
9
|
-
import
|
|
9
|
+
import FieldWrapper from "./FieldWrapper.vue"
|
|
10
10
|
|
|
11
11
|
const props = defineProps<{
|
|
12
12
|
modelValue?: string
|
|
@@ -56,15 +56,15 @@ const textareaClass = computed(() =>
|
|
|
56
56
|
</script>
|
|
57
57
|
|
|
58
58
|
<template>
|
|
59
|
-
<
|
|
60
|
-
:
|
|
61
|
-
:id="
|
|
62
|
-
:label="
|
|
63
|
-
:hint="
|
|
64
|
-
:error="
|
|
65
|
-
:required="
|
|
66
|
-
:class="
|
|
67
|
-
:style="
|
|
59
|
+
<FieldWrapper
|
|
60
|
+
:wrapped="hasField"
|
|
61
|
+
:id="field.id"
|
|
62
|
+
:label="label"
|
|
63
|
+
:hint="hint"
|
|
64
|
+
:error="error"
|
|
65
|
+
:required="required"
|
|
66
|
+
:class="attrs.class"
|
|
67
|
+
:style="attrs.style"
|
|
68
68
|
>
|
|
69
69
|
<textarea
|
|
70
70
|
v-bind="textareaAttrs"
|
|
@@ -80,5 +80,5 @@ const textareaClass = computed(() =>
|
|
|
80
80
|
:style="hasField ? undefined : (attrs.style as never)"
|
|
81
81
|
@input="$emit('update:modelValue', ($event.target as HTMLTextAreaElement).value)"
|
|
82
82
|
/>
|
|
83
|
-
</
|
|
83
|
+
</FieldWrapper>
|
|
84
84
|
</template>
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/*
|
|
3
|
+
* The theme, tuned in place: a base theme, any brand colour, corners, control
|
|
4
|
+
* size and motion speed, all applied live, and the result ready to take away
|
|
5
|
+
* as code, JSON or CSS. State lives in useThemeStudio (remembered, shared with
|
|
6
|
+
* an LpThemeSwitcher opened with `studio`), so the panel can sit in a popover,
|
|
7
|
+
* a settings page or a drawer.
|
|
8
|
+
*
|
|
9
|
+
* An app adds its own rows through `#start` and `#end` (LpThemeStudioSection
|
|
10
|
+
* gives them the panel's look) and drops built-in ones with `hide`.
|
|
11
|
+
*/
|
|
12
|
+
import { computed, ref } from "vue"
|
|
13
|
+
import { useLabels } from "../composables/useLpConfig"
|
|
14
|
+
import { STUDIO_BRANDS, STUDIO_SYSTEM, useThemeStudio, type StudioState, type ThemeStudio } from "../theme/studio"
|
|
15
|
+
import type { TokenSet } from "../theme/tokens"
|
|
16
|
+
import type { RevealOrigin } from "../theme/useTheme"
|
|
17
|
+
import LpButton from "./LpButton.vue"
|
|
18
|
+
import LpCodeBlock from "./LpCodeBlock.vue"
|
|
19
|
+
import LpColorPicker from "./LpColorPicker.vue"
|
|
20
|
+
import LpIcon from "./LpIcon.vue"
|
|
21
|
+
import LpSegmented from "./LpSegmented.vue"
|
|
22
|
+
import LpThemeStudioSection from "./LpThemeStudioSection.vue"
|
|
23
|
+
|
|
24
|
+
export type ThemeStudioPart = "themes" | "brand" | "corners" | "size" | "motion" | "export"
|
|
25
|
+
|
|
26
|
+
export interface ThemeStudioLabels extends Record<string, string> {
|
|
27
|
+
title: string
|
|
28
|
+
reset: string
|
|
29
|
+
themes: string
|
|
30
|
+
system: string
|
|
31
|
+
brand: string
|
|
32
|
+
anyBrand: string
|
|
33
|
+
corners: string
|
|
34
|
+
sharp: string
|
|
35
|
+
round: string
|
|
36
|
+
size: string
|
|
37
|
+
compact: string
|
|
38
|
+
comfortable: string
|
|
39
|
+
motion: string
|
|
40
|
+
fast: string
|
|
41
|
+
normal: string
|
|
42
|
+
slow: string
|
|
43
|
+
default: string
|
|
44
|
+
export: string
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const props = defineProps<{
|
|
48
|
+
/** A studio from useThemeStudio; by default the shared one for `storageKey`. */
|
|
49
|
+
studio?: ThemeStudio
|
|
50
|
+
/** Base themes, when the panel makes its own studio. */
|
|
51
|
+
themes?: TokenSet[]
|
|
52
|
+
storageKey?: string
|
|
53
|
+
/** Brand swatches offered beside the free colour picker. */
|
|
54
|
+
brands?: string[]
|
|
55
|
+
/** Built-in rows to leave out. */
|
|
56
|
+
hide?: ThemeStudioPart[]
|
|
57
|
+
labels?: Partial<ThemeStudioLabels>
|
|
58
|
+
}>()
|
|
59
|
+
|
|
60
|
+
const studio = props.studio ?? useThemeStudio({ themes: props.themes, storageKey: props.storageKey })
|
|
61
|
+
const { state, brand, changed, exported } = studio
|
|
62
|
+
// Assigned through the ref: a destructured binding assigned in the template
|
|
63
|
+
// would replace the local name, not write the studio's state.
|
|
64
|
+
const setBrand = (color: string) => (brand.value = color)
|
|
65
|
+
|
|
66
|
+
const text = useLabels<ThemeStudioLabels>(
|
|
67
|
+
"themeStudio",
|
|
68
|
+
{
|
|
69
|
+
title: "Theme",
|
|
70
|
+
reset: "Reset",
|
|
71
|
+
themes: "Theme",
|
|
72
|
+
system: "System",
|
|
73
|
+
brand: "Brand colour",
|
|
74
|
+
anyBrand: "Any brand colour",
|
|
75
|
+
corners: "Corners",
|
|
76
|
+
sharp: "Sharp",
|
|
77
|
+
round: "Round",
|
|
78
|
+
size: "Control size",
|
|
79
|
+
compact: "Compact",
|
|
80
|
+
comfortable: "Roomy",
|
|
81
|
+
motion: "Motion",
|
|
82
|
+
fast: "Fast",
|
|
83
|
+
normal: "Normal",
|
|
84
|
+
slow: "Slow",
|
|
85
|
+
default: "Default",
|
|
86
|
+
export: "Use this theme",
|
|
87
|
+
},
|
|
88
|
+
() => props.labels,
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
const shows = (part: ThemeStudioPart) => !props.hide?.includes(part)
|
|
92
|
+
const swatches = computed(() => props.brands ?? STUDIO_BRANDS)
|
|
93
|
+
const format = ref<"code" | "json" | "css">("code")
|
|
94
|
+
|
|
95
|
+
// A new base theme reveals from the swatch that picked it; Reset from itself.
|
|
96
|
+
function origin(event: Event): RevealOrigin | undefined {
|
|
97
|
+
const r = (event.currentTarget as Element | null)?.getBoundingClientRect()
|
|
98
|
+
return r ? { x: r.left + r.width / 2, y: r.top + r.height / 2 } : undefined
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const TILE =
|
|
102
|
+
"flex min-w-0 flex-col items-center gap-1 rounded-control p-1.5 text-[11px] text-muted transition-colors duration-(--duration-fast) hover:bg-surface-soft hover:text-ink"
|
|
103
|
+
const SWATCH = "relative size-8 overflow-hidden rounded-full ring-2 transition-[box-shadow] duration-(--duration-fast)"
|
|
104
|
+
|
|
105
|
+
const tuneTo = <K extends keyof Omit<StudioState, "theme">>(key: K) =>
|
|
106
|
+
(value: string) => studio.tune({ [key]: value } as Partial<StudioState>)
|
|
107
|
+
</script>
|
|
108
|
+
|
|
109
|
+
<template>
|
|
110
|
+
<div class="flex flex-col gap-4">
|
|
111
|
+
<div class="flex items-center justify-between">
|
|
112
|
+
<p class="text-sm font-semibold text-ink">{{ text.title }}</p>
|
|
113
|
+
<LpButton v-if="changed" variant="ghost" size="xs" @click="studio.reset(origin($event))">
|
|
114
|
+
<LpIcon name="lucide:rotate-ccw" :size="12" />{{ text.reset }}
|
|
115
|
+
</LpButton>
|
|
116
|
+
</div>
|
|
117
|
+
|
|
118
|
+
<slot name="start" :studio="studio" />
|
|
119
|
+
|
|
120
|
+
<LpThemeStudioSection v-if="shows('themes')" :label="text.themes">
|
|
121
|
+
<div class="grid grid-cols-4 gap-2">
|
|
122
|
+
<!-- Follows the OS between its pair: drawn as both halves. -->
|
|
123
|
+
<button
|
|
124
|
+
v-if="studio.system.value"
|
|
125
|
+
type="button"
|
|
126
|
+
:class="[TILE, state.theme === STUDIO_SYSTEM && 'bg-surface-soft text-ink']"
|
|
127
|
+
:aria-pressed="state.theme === STUDIO_SYSTEM"
|
|
128
|
+
@click="studio.pickTheme(STUDIO_SYSTEM, origin($event))"
|
|
129
|
+
>
|
|
130
|
+
<span
|
|
131
|
+
:class="[SWATCH, state.theme === STUDIO_SYSTEM ? 'ring-brand' : 'ring-line']"
|
|
132
|
+
:style="{ background: `linear-gradient(135deg, ${studio.system.value.light.colors.surface} 50%, ${studio.system.value.dark.colors.surface} 50%)` }"
|
|
133
|
+
/>
|
|
134
|
+
<span class="max-w-full truncate">{{ text.system }}</span>
|
|
135
|
+
</button>
|
|
136
|
+
<button
|
|
137
|
+
v-for="t in studio.themes.value"
|
|
138
|
+
:key="t.name"
|
|
139
|
+
type="button"
|
|
140
|
+
:class="[TILE, state.theme === t.name && 'bg-surface-soft text-ink']"
|
|
141
|
+
:aria-pressed="state.theme === t.name"
|
|
142
|
+
@click="studio.pickTheme(t.name, origin($event))"
|
|
143
|
+
>
|
|
144
|
+
<span :class="[SWATCH, state.theme === t.name ? 'ring-brand' : 'ring-line']" :style="{ background: t.colors.surface }">
|
|
145
|
+
<span class="absolute inset-x-0 bottom-0 h-1/2" :style="{ background: t.colors.brand }" />
|
|
146
|
+
</span>
|
|
147
|
+
<span class="max-w-full truncate">{{ t.name }}</span>
|
|
148
|
+
</button>
|
|
149
|
+
</div>
|
|
150
|
+
</LpThemeStudioSection>
|
|
151
|
+
|
|
152
|
+
<LpThemeStudioSection v-if="shows('brand')" :label="text.brand">
|
|
153
|
+
<div class="flex flex-wrap items-center gap-1.5">
|
|
154
|
+
<button
|
|
155
|
+
v-for="color in swatches"
|
|
156
|
+
:key="color"
|
|
157
|
+
type="button"
|
|
158
|
+
class="size-6 rounded-full ring-2 ring-offset-2 ring-offset-surface-raised transition-[box-shadow,scale] duration-(--duration-fast) hover:scale-110"
|
|
159
|
+
:class="brand === color ? 'ring-ink' : 'ring-transparent'"
|
|
160
|
+
:style="{ background: color }"
|
|
161
|
+
:aria-label="`${text.brand} ${color}`"
|
|
162
|
+
:aria-pressed="brand === color"
|
|
163
|
+
@click="setBrand(color)"
|
|
164
|
+
/>
|
|
165
|
+
<LpColorPicker :model-value="brand" size="sm" :aria-label="text.anyBrand" @update:model-value="setBrand" />
|
|
166
|
+
</div>
|
|
167
|
+
</LpThemeStudioSection>
|
|
168
|
+
|
|
169
|
+
<LpThemeStudioSection v-if="shows('corners')" :label="text.corners">
|
|
170
|
+
<LpSegmented
|
|
171
|
+
:model-value="state.corners"
|
|
172
|
+
size="sm"
|
|
173
|
+
:options="[{ value: 'sharp', label: text.sharp }, { value: 'default', label: text.default }, { value: 'round', label: text.round }]"
|
|
174
|
+
@update:model-value="tuneTo('corners')"
|
|
175
|
+
/>
|
|
176
|
+
</LpThemeStudioSection>
|
|
177
|
+
|
|
178
|
+
<LpThemeStudioSection v-if="shows('size')" :label="text.size">
|
|
179
|
+
<LpSegmented
|
|
180
|
+
:model-value="state.size"
|
|
181
|
+
size="sm"
|
|
182
|
+
:options="[{ value: 'compact', label: text.compact }, { value: 'default', label: text.default }, { value: 'comfortable', label: text.comfortable }]"
|
|
183
|
+
@update:model-value="tuneTo('size')"
|
|
184
|
+
/>
|
|
185
|
+
</LpThemeStudioSection>
|
|
186
|
+
|
|
187
|
+
<LpThemeStudioSection v-if="shows('motion')" :label="text.motion">
|
|
188
|
+
<LpSegmented
|
|
189
|
+
:model-value="state.motion"
|
|
190
|
+
size="sm"
|
|
191
|
+
:options="[{ value: 'fast', label: text.fast }, { value: 'normal', label: text.normal }, { value: 'slow', label: text.slow }]"
|
|
192
|
+
@update:model-value="tuneTo('motion')"
|
|
193
|
+
/>
|
|
194
|
+
</LpThemeStudioSection>
|
|
195
|
+
|
|
196
|
+
<slot name="end" :studio="studio" />
|
|
197
|
+
|
|
198
|
+
<div v-if="shows('export')" class="flex flex-col gap-2 border-t border-line pt-3">
|
|
199
|
+
<div class="flex items-center justify-between gap-2">
|
|
200
|
+
<span class="text-[11px] font-medium tracking-wide text-muted uppercase">{{ text.export }}</span>
|
|
201
|
+
<LpSegmented
|
|
202
|
+
v-model="format"
|
|
203
|
+
size="sm"
|
|
204
|
+
:options="[{ value: 'code', label: 'Code' }, { value: 'json', label: 'JSON' }, { value: 'css', label: 'CSS' }]"
|
|
205
|
+
/>
|
|
206
|
+
</div>
|
|
207
|
+
<LpCodeBlock
|
|
208
|
+
:model-value="exported[format]"
|
|
209
|
+
:lang="format === 'json' ? 'json' : format === 'css' ? 'plain' : 'ts'"
|
|
210
|
+
copyable
|
|
211
|
+
height="140px"
|
|
212
|
+
class="text-[11px]"
|
|
213
|
+
/>
|
|
214
|
+
</div>
|
|
215
|
+
</div>
|
|
216
|
+
</template>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/*
|
|
3
|
+
* One row of LpThemeStudio: a small caps label over its controls. The studio
|
|
4
|
+
* builds its own rows with it, and an app adding its own (a font, a density
|
|
5
|
+
* of its own, a layout switch) through the studio's slots uses it too, so the
|
|
6
|
+
* added row reads as part of the panel.
|
|
7
|
+
*/
|
|
8
|
+
defineProps<{ label: string }>()
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
<template>
|
|
12
|
+
<div class="flex flex-col gap-2">
|
|
13
|
+
<span class="text-[11px] font-medium tracking-wide text-muted uppercase">{{ label }}</span>
|
|
14
|
+
<slot />
|
|
15
|
+
</div>
|
|
16
|
+
</template>
|