@leavepulse/ui 0.70.0 → 0.71.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 +103 -0
- package/dist/assets/{LpCommandPalette-u-zOxKWa.css → LpCommandPalette-DgPZX0us.css} +24 -17
- package/dist/assets/{LpPaletteFacts-B9FdVmIO.css → LpPaletteFacts-CVNh5ICn.css} +16 -16
- package/dist/assets/{LpPaletteStats-ClE-37MK.css → LpPaletteStats-ZiZmR6vz.css} +5 -5
- package/dist/assets/LpRepeater-C1Cw27hj.css +21 -0
- package/dist/assets/{LpRollingText-BGnE6q9j.css → LpRollingText-dyOXedGO.css} +7 -0
- package/dist/assets/{LpTable-DHxEQ_-3.css → LpTable-DHvorDiU.css} +19 -19
- package/dist/assets/LpTabs-CO3EcsNV.css +18 -0
- package/dist/chunks/{ContextMenuItems-B5uE8Znw.js → ContextMenuItems-eS7qx9gD.js} +11 -5
- package/dist/chunks/{DropzoneLinkField-Bw8Flkhk.js → DropzoneLinkField-DkFhdfEJ.js} +2 -2
- package/dist/chunks/{FieldWrapper-BiennROB.js → FieldWrapper-YzbvvC3M.js} +1 -1
- package/dist/chunks/{LayoutCanvas-BsJIzhdd.js → LayoutCanvas-Ba4A9QC5.js} +1 -1
- package/dist/chunks/{LayoutNode-DJVhkSGk.js → LayoutNode-CTTTLMDM.js} +1 -1
- package/dist/chunks/{LpActionBar-CzOFar5t.js → LpActionBar-B7anGlkI.js} +2 -2
- package/dist/chunks/{LpAddressInput-CNnLTDZg.js → LpAddressInput-CD0bzrt-.js} +7 -7
- package/dist/chunks/{LpAlert-C5igj802.js → LpAlert-BHi7ARqu.js} +1 -1
- package/dist/chunks/{LpAppShell-CEUAB8kK.js → LpAppShell-1RmBp6xQ.js} +3 -3
- package/dist/chunks/{LpAutocomplete-D92niDHE.js → LpAutocomplete-DDqe2M5g.js} +5 -2
- package/dist/chunks/{LpAvatar-CLPl-qOF.js → LpAvatar-DqfKCIdr.js} +1 -1
- package/dist/chunks/{LpBadge-HOEPBYmi.js → LpBadge-C8fKEmTF.js} +2 -2
- package/dist/chunks/{LpBreadcrumbs-DYoPc3P4.js → LpBreadcrumbs-DhcoStFa.js} +2 -2
- package/dist/chunks/{LpButton-CVxBfGjd.js → LpButton-BQDAFXBd.js} +3 -0
- package/dist/chunks/{LpCalendar-pVL91-Pl.js → LpCalendar-NmrA47J9.js} +1 -1
- package/dist/chunks/{LpCheckbox-DHc2bHDe.js → LpCheckbox-BoOuLnGB.js} +5 -2
- package/dist/chunks/{LpCodeBlock-BGsQhxw8.js → LpCodeBlock-Czu-fq1M.js} +2 -2
- package/dist/chunks/{LpCodeDisplay-CIKKT2iW.js → LpCodeDisplay-BK2FHbtM.js} +6 -6
- package/dist/chunks/{LpColorPicker-DFugXNUi.js → LpColorPicker-Ee1DZiRd.js} +3 -3
- package/dist/chunks/LpCommandScope-ubtWDMa0.js +53 -0
- package/dist/chunks/{LpConfirmDialog-CfGCux8m.js → LpConfirmDialog-i15pulMT.js} +3 -3
- package/dist/chunks/{LpConfirmHost-exB7JmcO.js → LpConfirmHost-D0oGavtd.js} +1 -1
- package/dist/chunks/{LpContextMenu-COwOwRgI.js → LpContextMenu-DXpFJjlO.js} +17 -6
- package/dist/chunks/{LpCopyButton-DzHjnFs0.js → LpCopyButton-Dmq7DmFw.js} +3 -3
- package/dist/chunks/{LpCountdown-Dtq1ihlJ.js → LpCountdown-DTdMF8DL.js} +2 -2
- package/dist/chunks/{LpDataList-B-5nHfNw.js → LpDataList-CFPtSsBB.js} +7 -6
- package/dist/chunks/{LpDatePicker-BUe1VUC0.js → LpDatePicker-cC9K-Pk8.js} +7 -6
- package/dist/chunks/{LpDateRangePicker-C_k65vGR.js → LpDateRangePicker-BVQKPbvo.js} +5 -4
- package/dist/chunks/{LpDisclosure-DOarzlAG.js → LpDisclosure-hRnX3FWL.js} +4 -1
- package/dist/chunks/{LpDrawer-DGNKRsGq.js → LpDrawer-u4rxnuR-.js} +1 -1
- package/dist/chunks/{LpDropdownMenu-CRgrhdAH.js → LpDropdownMenu-BgZ0Z_Im.js} +17 -4
- package/dist/chunks/{LpEditable-DTqLt2lT.js → LpEditable-CjxuOVh_.js} +7 -5
- package/dist/chunks/{LpEmptyState-KTKipws2.js → LpEmptyState-CKFTtQgJ.js} +1 -1
- package/dist/chunks/{LpFieldNotice-CurbNuXI.js → LpFieldNotice-CPI8EwtU.js} +1 -1
- package/dist/chunks/{LpFileTree-DMISXVHC.js → LpFileTree-BH0gNlSJ.js} +2 -2
- package/dist/chunks/{LpFileTreeNode-CPXB_Yy3.js → LpFileTreeNode-gPVB1oXM.js} +4 -4
- package/dist/chunks/{LpFormField-BWwgm1E4.js → LpFormField-gRASfyj2.js} +4 -1
- package/dist/chunks/{LpGauge-Bk8TwJj0.js → LpGauge-BdjPGnqw.js} +2 -2
- package/dist/chunks/{LpHintLayer-p4hqzdyA.js → LpHintLayer-C2asBIfs.js} +2 -2
- package/dist/chunks/{LpHints-CCrhRfy9.js → LpHints-CNZQ76JV.js} +3 -3
- package/dist/chunks/{LpIcon-HJP5xMz4.js → LpIcon-DkP-9mzK.js} +1 -1
- package/dist/chunks/{LpInfraNode-CUC3t4na.js → LpInfraNode-yTh4-5qa.js} +2 -2
- package/dist/chunks/{LpInput-CDuwODJG.js → LpInput-2H-5ILOB.js} +5 -2
- package/dist/chunks/{LpLightbox-XJ0LpTcZ.js → LpLightbox-lAt5uIfx.js} +2 -2
- package/dist/chunks/{LpLogViewer-elZHbj85.js → LpLogViewer-x78YfhJf.js} +5 -5
- package/dist/chunks/{LpMapPicker-BtIl7NOM.js → LpMapPicker-Dp5RSCi9.js} +1 -1
- package/dist/chunks/{LpMediaGallery-D5swlmZ_.js → LpMediaGallery-D92oJfY_.js} +3 -3
- package/dist/chunks/{LpModal-eBMt2Fqn.js → LpModal-CpH0bNo7.js} +1 -1
- package/dist/chunks/{LpModalNav-D4Z0wVHR.js → LpModalNav-BH4ANQGJ.js} +4 -4
- package/dist/chunks/{LpNotificationBell-DPZmP5dM.js → LpNotificationBell-BdUQqZhs.js} +8 -8
- package/dist/chunks/{LpNumberField-B9k-h2HE.js → LpNumberField-DZY3Z670.js} +4 -1
- package/dist/chunks/{LpNumberFlow-Cfyh033Q.js → LpNumberFlow-5khYxsfX.js} +6 -3
- package/dist/chunks/{LpPagination-VNCX6pFC.js → LpPagination-DbeACavM.js} +1 -1
- package/dist/chunks/LpPaletteTheme-CqWNRwHE.js +104 -0
- package/dist/chunks/{LpPasswordInput-DTV18FIh.js → LpPasswordInput-BzAZsf5V.js} +14 -8
- package/dist/chunks/{LpPhoneInput-C60tx1tC.js → LpPhoneInput-BMpd-0QR.js} +2 -2
- package/dist/chunks/{LpPie-CFuV7pZv.js → LpPie-DdFSTbGE.js} +5 -5
- package/dist/chunks/{LpPipeline-D81yh_NX.js → LpPipeline-zjEM1Lwc.js} +4 -4
- package/dist/chunks/{LpPopover-BEIcqb9p.js → LpPopover-DmZ3wUtP.js} +6 -5
- package/dist/chunks/{LpProgress-CE-m5OpD.js → LpProgress-BX33EKkN.js} +1 -1
- package/dist/chunks/{LpQuota-2Sw_gqcJ.js → LpQuota-DqNv1yjs.js} +3 -3
- package/dist/chunks/{LpRadioGroup-CGBr5nIp.js → LpRadioGroup-CsXeV9Ct.js} +4 -1
- package/dist/chunks/{LpRangeCalendar-c5qj7YcC.js → LpRangeCalendar-l-0nSFmY.js} +1 -1
- package/dist/chunks/{LpRangeSlider-Dv6lNvHY.js → LpRangeSlider-CM-0ZITZ.js} +3 -0
- package/dist/chunks/{LpRelativeTime-CKzVqAo9.js → LpRelativeTime-UM8EkfrN.js} +2 -2
- package/dist/chunks/LpRepeater-OvzByE5L.js +180 -0
- package/dist/chunks/{LpRollingText-DB7upf-5.js → LpRollingText-DiL717LK.js} +4 -3
- package/dist/chunks/{LpSecretField-DMfdJ1cQ.js → LpSecretField-DwQiPOko.js} +27 -16
- package/dist/chunks/{LpSection-BW4xJ-Li.js → LpSection-DcQsieHG.js} +1 -1
- package/dist/chunks/{LpSegmented-BO99Sr4m.js → LpSegmented-D2VST0o3.js} +4 -1
- package/dist/chunks/{LpSelect-B4f_yRi5.js → LpSelect-DYX2-u5A.js} +43 -18
- package/dist/chunks/{LpSidebar-D-M0Y_7U.js → LpSidebar-D44peKq2.js} +3 -3
- package/dist/chunks/{LpSidebarNav-DF-TYxOV.js → LpSidebarNav--VwkXO_a.js} +3 -3
- package/dist/chunks/{LpSlider-DuoRpOrH.js → LpSlider-DxYoCJJO.js} +3 -0
- package/dist/chunks/{LpStat-B2ix1Q7t.js → LpStat-DIsQfbeD.js} +3 -3
- package/dist/chunks/{LpStatus-C7kx5PKE.js → LpStatus-BQU1TUsv.js} +2 -2
- package/dist/chunks/{LpStepMark-DK-5BKAt.js → LpStepMark-CXa7DJy_.js} +2 -2
- package/dist/chunks/{LpStepper-DRFfdJaq.js → LpStepper-C9RM_yTG.js} +1 -1
- package/dist/chunks/{LpSwitch-DrzKrZZV.js → LpSwitch-bGZxUDSx.js} +3 -0
- package/dist/chunks/{LpTableFilter-DyvHGbOk.js → LpTableFilter-CTZMqFDU.js} +2 -2
- package/dist/chunks/{LpTableOfContents-rYvo8z5T.js → LpTableOfContents-CraicEs4.js} +2 -2
- package/dist/chunks/{LpTagsInput-DgpBFRV2.js → LpTagsInput-DrjmrOge.js} +8 -5
- package/dist/chunks/{LpTextarea-DiWjeVoJ.js → LpTextarea-BbYqmG1S.js} +4 -1
- package/dist/chunks/{LpThemeStudio-DguwHdGt.js → LpThemeStudio-B2nPaG-h.js} +18 -14
- package/dist/chunks/{LpThemeSwitcher-D5uz0MhK.js → LpThemeSwitcher-C0A5sg_E.js} +6 -4
- package/dist/chunks/{LpTimeField-BFQVf_PW.js → LpTimeField-DQ8WvPr2.js} +4 -1
- package/dist/chunks/{LpToaster-Wv9ksj4q.js → LpToaster-BTTl_wuy.js} +2 -2
- package/dist/chunks/{LpTooltip-Cz8SQwRt.js → LpTooltip-BcBvIx4z.js} +23 -5
- package/dist/chunks/{LpTopologyCanvas-ZhKthfgz.js → LpTopologyCanvas-B0wEvAoq.js} +1 -1
- package/dist/chunks/{LpTour-NfRJNEIP.js → LpTour-BgCfNlaW.js} +1 -1
- package/dist/chunks/{LpTruncate-D_5Pfv5B.js → LpTruncate-TcqfkyJM.js} +2 -2
- package/dist/chunks/{LpUptimeBar-DWegV2p6.js → LpUptimeBar-DRadGq4Y.js} +136 -47
- package/dist/chunks/{MenuTitle-BjQZX8tQ.js → MenuTitle-Dab3EGOp.js} +1 -1
- package/dist/chunks/{OptionContent-CmYUUeWj.js → OptionContent-DPzNsybd.js} +1 -1
- package/dist/chunks/PalettePreviewBoundary-B0Hhu3Yw.js +20 -0
- package/dist/chunks/{PickerField-CHRS1h7K.js → PickerField-DwLw7j0L.js} +26 -17
- package/dist/chunks/{RevealToggle-C-KzaQGJ.js → RevealToggle-BVFM_FAU.js} +3 -3
- package/dist/chunks/{TourCard-BXuVHsfn.js → TourCard--2IfgnUU.js} +3 -3
- package/dist/chunks/icons-CLu1iR1j.js +43 -0
- package/dist/chunks/palette-BiY7yQZL.js +29 -0
- package/dist/component-names.d.ts +1 -1
- package/dist/components/ContextMenuItems.vue.js +1 -1
- package/dist/components/DropzoneLinkField.vue.js +1 -1
- package/dist/components/FieldWrapper.vue.js +1 -1
- package/dist/components/LayoutCanvas.vue.js +1 -1
- package/dist/components/LayoutNode.vue.js +1 -1
- package/dist/components/LpActionBar.vue.js +1 -1
- package/dist/components/LpAddressInput.vue.d.ts +1 -1
- package/dist/components/LpAddressInput.vue.js +1 -1
- package/dist/components/LpAlert.vue.d.ts +3 -3
- package/dist/components/LpAlert.vue.js +1 -1
- package/dist/components/LpAppShell.vue.js +1 -1
- package/dist/components/LpAutocomplete.vue.d.ts +7 -1
- package/dist/components/LpAutocomplete.vue.js +1 -1
- package/dist/components/LpAvatar.vue.js +1 -1
- package/dist/components/LpBadge.vue.d.ts +2 -2
- package/dist/components/LpBadge.vue.js +1 -1
- package/dist/components/LpBreadcrumbs.vue.js +1 -1
- package/dist/components/LpButton.vue.d.ts +4 -0
- package/dist/components/LpButton.vue.js +1 -1
- package/dist/components/LpCalendar.vue.js +1 -1
- package/dist/components/LpChart.vue.js +27 -25
- package/dist/components/LpCheckbox.vue.d.ts +8 -1
- package/dist/components/LpCheckbox.vue.js +1 -1
- package/dist/components/LpCodeBlock.vue.js +1 -1
- package/dist/components/LpCodeDisplay.vue.js +1 -1
- package/dist/components/LpColorPicker.vue.d.ts +2 -2
- package/dist/components/LpColorPicker.vue.js +1 -1
- package/dist/components/LpCommandPalette.vue.d.ts +43 -7
- package/dist/components/LpCommandPalette.vue.js +451 -126
- package/dist/components/LpCommandScope.vue.d.ts +28 -0
- package/dist/components/LpCommandScope.vue.js +4 -0
- package/dist/components/LpConfirmDialog.vue.js +1 -1
- package/dist/components/LpConfirmHost.vue.js +1 -1
- package/dist/components/LpContextMenu.vue.d.ts +5 -1
- package/dist/components/LpContextMenu.vue.js +1 -1
- package/dist/components/LpCopyButton.vue.d.ts +1 -1
- package/dist/components/LpCopyButton.vue.js +1 -1
- package/dist/components/LpCountdown.vue.js +1 -1
- package/dist/components/LpDataList.vue.js +1 -1
- package/dist/components/LpDatePicker.vue.d.ts +2 -0
- package/dist/components/LpDatePicker.vue.js +1 -1
- package/dist/components/LpDateRangePicker.vue.d.ts +2 -0
- package/dist/components/LpDateRangePicker.vue.js +1 -1
- package/dist/components/LpDisclosure.vue.d.ts +4 -0
- package/dist/components/LpDisclosure.vue.js +1 -1
- package/dist/components/LpDock.vue.js +2 -2
- package/dist/components/LpDrawer.vue.js +1 -1
- package/dist/components/LpDropdownMenu.vue.d.ts +5 -1
- package/dist/components/LpDropdownMenu.vue.js +1 -1
- package/dist/components/LpDropzone.vue.js +2 -2
- package/dist/components/LpEditable.vue.js +1 -1
- package/dist/components/LpEmptyState.vue.js +1 -1
- package/dist/components/LpFieldNotice.vue.js +1 -1
- package/dist/components/LpFileTree.vue.d.ts +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/LpGauge.vue.js +1 -1
- package/dist/components/LpHintLayer.vue.js +1 -1
- package/dist/components/LpHints.vue.js +1 -1
- package/dist/components/LpIcon.vue.js +1 -1
- package/dist/components/LpImageEditor.vue.js +3 -2
- package/dist/components/LpInfraNode.vue.js +1 -1
- package/dist/components/LpInput.vue.d.ts +6 -0
- package/dist/components/LpInput.vue.js +1 -1
- package/dist/components/LpLightbox.vue.js +1 -1
- package/dist/components/LpLoader.vue.d.ts +1 -1
- package/dist/components/LpLogViewer.vue.js +1 -1
- package/dist/components/LpMapPicker.vue.js +1 -1
- package/dist/components/LpMediaGallery.vue.d.ts +2 -2
- 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.js +1 -1
- package/dist/components/LpNumberField.vue.d.ts +6 -0
- package/dist/components/LpNumberField.vue.js +1 -1
- package/dist/components/LpNumberFlow.vue.js +1 -1
- package/dist/components/LpPagination.vue.js +1 -1
- package/dist/components/LpPaletteFacts.vue.d.ts +1 -0
- package/dist/components/LpPaletteFacts.vue.js +40 -26
- package/dist/components/LpPaletteHeader.vue.js +2 -2
- package/dist/components/LpPaletteStats.vue.d.ts +1 -0
- package/dist/components/LpPaletteStats.vue.js +45 -21
- package/dist/components/LpPaletteTheme.vue.d.ts +7 -0
- package/dist/components/LpPaletteTheme.vue.js +4 -0
- package/dist/components/LpPasswordInput.vue.d.ts +7 -1
- package/dist/components/LpPasswordInput.vue.js +1 -1
- package/dist/components/LpPhoneInput.vue.js +1 -1
- package/dist/components/LpPie.vue.js +1 -1
- package/dist/components/LpPipeline.vue.js +1 -1
- package/dist/components/LpPopover.vue.js +1 -1
- package/dist/components/LpProgress.vue.d.ts +1 -1
- package/dist/components/LpProgress.vue.js +1 -1
- package/dist/components/LpQuota.vue.js +1 -1
- package/dist/components/LpRadioGroup.vue.d.ts +6 -1
- package/dist/components/LpRadioGroup.vue.js +1 -1
- package/dist/components/LpRangeCalendar.vue.js +1 -1
- package/dist/components/LpRangeSlider.vue.d.ts +6 -0
- package/dist/components/LpRangeSlider.vue.js +1 -1
- package/dist/components/LpRelativeTime.vue.js +1 -1
- package/dist/components/LpRepeater.vue.js +1 -1
- package/dist/components/LpRollingText.vue.d.ts +2 -0
- package/dist/components/LpRollingText.vue.js +1 -1
- package/dist/components/LpSecretField.vue.js +1 -1
- package/dist/components/LpSection.vue.js +1 -1
- package/dist/components/LpSegmented.vue.d.ts +6 -0
- package/dist/components/LpSegmented.vue.js +1 -1
- package/dist/components/LpSelect.vue.d.ts +3 -0
- package/dist/components/LpSelect.vue.js +1 -1
- package/dist/components/LpShinyText.vue.d.ts +1 -1
- 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.d.ts +6 -0
- package/dist/components/LpSlider.vue.js +1 -1
- package/dist/components/LpStat.vue.js +1 -1
- package/dist/components/LpStatus.vue.js +1 -1
- package/dist/components/LpStepMark.vue.js +1 -1
- package/dist/components/LpStepper.vue.js +1 -1
- package/dist/components/LpSwitch.vue.d.ts +6 -0
- package/dist/components/LpSwitch.vue.js +1 -1
- package/dist/components/LpTable.vue.d.ts +6 -0
- package/dist/components/LpTable.vue.js +74 -35
- package/dist/components/LpTableFilter.vue.js +1 -1
- package/dist/components/LpTableOfContents.vue.js +1 -1
- package/dist/components/LpTabs.vue.d.ts +1 -1
- package/dist/components/LpTabs.vue.js +15 -6
- package/dist/components/LpTagsInput.vue.d.ts +6 -0
- package/dist/components/LpTagsInput.vue.js +1 -1
- package/dist/components/LpTextarea.vue.d.ts +8 -1
- package/dist/components/LpTextarea.vue.js +1 -1
- package/dist/components/LpThemeStudio.vue.js +1 -1
- package/dist/components/LpThemeSwitcher.vue.js +1 -1
- package/dist/components/LpTimeField.vue.d.ts +6 -0
- package/dist/components/LpTimeField.vue.js +1 -1
- package/dist/components/LpToaster.vue.js +1 -1
- package/dist/components/LpTooltip.vue.js +1 -1
- package/dist/components/LpTopologyCanvas.vue.js +1 -1
- package/dist/components/LpTour.vue.js +1 -1
- package/dist/components/LpTruncate.vue.js +1 -1
- package/dist/components/LpUptimeBar.vue.d.ts +18 -9
- package/dist/components/LpUptimeBar.vue.js +1 -1
- package/dist/components/MenuTitle.vue.js +1 -1
- package/dist/components/OptionContent.vue.js +1 -1
- package/dist/components/PalettePreviewBoundary.vue.d.ts +13 -0
- package/dist/components/PalettePreviewBoundary.vue.js +4 -0
- package/dist/components/PickerField.vue.d.ts +5 -3
- package/dist/components/PickerField.vue.js +1 -1
- package/dist/components/RevealToggle.vue.js +1 -1
- package/dist/components/TourCard.vue.js +1 -1
- package/dist/components/commandPalette.d.ts +33 -0
- package/dist/components/commandPalette.js +21 -1
- package/dist/components/commandSearch.d.ts +5 -0
- package/dist/components/commandSearch.js +22 -2
- package/dist/components/format.d.ts +7 -0
- package/dist/components/format.js +4 -0
- package/dist/components/menuWhen.js +1 -1
- package/dist/components/uptimeBar.d.ts +45 -0
- package/dist/components/uptimeBar.js +51 -0
- package/dist/composables/scroll.d.ts +5 -0
- package/dist/composables/scroll.js +7 -0
- package/dist/composables/useField.d.ts +9 -0
- package/dist/composables/useField.js +24 -1
- package/dist/composables/useForm.js +13 -4
- package/dist/composables/usePaletteCommands.d.ts +61 -0
- package/dist/composables/usePaletteCommands.js +220 -0
- package/dist/composables/useReveal.js +21 -0
- package/dist/composables/useView.js +9 -2
- package/dist/icons-all.js +1 -1
- package/dist/index.d.ts +14 -1
- package/dist/index.js +103 -87
- package/dist/theme/palette.d.ts +9 -0
- package/dist/theme/studio.d.ts +12 -1
- package/package.json +4 -1
- package/src/component-names.ts +2 -0
- package/src/components/ContextMenuItems.vue +5 -2
- package/src/components/LpAutocomplete.vue +6 -1
- package/src/components/LpButton.vue +5 -1
- package/src/components/LpChart.vue +19 -17
- package/src/components/LpCheckbox.vue +7 -2
- package/src/components/LpCommandPalette.vue +263 -29
- package/src/components/LpCommandScope.vue +35 -0
- package/src/components/LpContextMenu.vue +17 -5
- package/src/components/LpDataList.vue +2 -2
- package/src/components/LpDatePicker.vue +2 -0
- package/src/components/LpDateRangePicker.vue +2 -0
- package/src/components/LpDisclosure.vue +5 -1
- package/src/components/LpDropdownMenu.vue +14 -3
- package/src/components/LpEditable.vue +3 -1
- package/src/components/LpFormField.vue +3 -0
- package/src/components/LpInput.vue +6 -1
- package/src/components/LpNumberField.vue +6 -1
- package/src/components/LpNumberFlow.vue +12 -2
- package/src/components/LpPaletteFacts.vue +11 -6
- package/src/components/LpPaletteStats.vue +12 -5
- package/src/components/LpPaletteTheme.vue +48 -0
- package/src/components/LpPasswordInput.vue +13 -5
- package/src/components/LpPopover.vue +4 -0
- package/src/components/LpRadioGroup.vue +4 -1
- package/src/components/LpRangeSlider.vue +6 -1
- package/src/components/LpRepeater.vue +64 -13
- package/src/components/LpRollingText.vue +12 -1
- package/src/components/LpSecretField.vue +18 -8
- package/src/components/LpSegmented.vue +6 -1
- package/src/components/LpSelect.vue +44 -10
- package/src/components/LpSlider.vue +6 -1
- package/src/components/LpSwitch.vue +6 -1
- package/src/components/LpTable.vue +35 -2
- package/src/components/LpTableOfContents.vue +2 -4
- package/src/components/LpTabs.vue +7 -0
- package/src/components/LpTagsInput.vue +6 -1
- package/src/components/LpTextarea.vue +7 -2
- package/src/components/LpThemeStudio.vue +7 -5
- package/src/components/LpThemeSwitcher.vue +3 -0
- package/src/components/LpTimeField.vue +6 -1
- package/src/components/LpTooltip.vue +23 -1
- package/src/components/LpUptimeBar.vue +69 -41
- package/src/components/PalettePreviewBoundary.vue +5 -0
- package/src/components/PickerField.vue +5 -4
- package/src/components/commandPalette.ts +22 -1
- package/src/components/commandSearch.ts +23 -1
- package/src/components/format.ts +10 -0
- package/src/components/uptimeBar.ts +98 -0
- package/src/composables/scroll.ts +11 -0
- package/src/composables/useField.ts +33 -1
- package/src/composables/useForm.ts +14 -5
- package/src/composables/usePaletteCommands.ts +220 -0
- package/src/composables/useReveal.ts +29 -0
- package/src/composables/useView.ts +8 -1
- package/src/index.ts +18 -1
- package/src/kit-icons.ts +1 -1
- package/src/theme/palette.ts +26 -0
- package/src/theme/studio.ts +15 -8
- package/dist/assets/LpTabs-BJ-nrJuI.css +0 -18
- package/dist/chunks/LpRepeater-D0VjmD6y.js +0 -140
- package/dist/chunks/icons-4IywzkHk.js +0 -43
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { useId } from "vue"
|
|
3
|
+
import { menuPaletteCommands } from "./commandPalette"
|
|
4
|
+
import { usePaletteCommands, usePaletteScope, type PaletteControlOptions } from "../composables/usePaletteCommands"
|
|
2
5
|
/*
|
|
3
6
|
* Right-click context menu (reka ContextMenu). Same items as LpDropdownMenu,
|
|
4
7
|
* drawn by the same renderer: nested submenus (`children`), tick-box items and
|
|
@@ -14,7 +17,7 @@ import { HINT_SIGNALS, noteContextTarget } from "../composables/useHintSystem"
|
|
|
14
17
|
import ContextMenuItems from "./ContextMenuItems.vue"
|
|
15
18
|
import MenuTitle from "./MenuTitle.vue"
|
|
16
19
|
import { POPOVER_PANEL } from "./dropdown"
|
|
17
|
-
import { useOutsideGuard, usePortalTarget } from "../composables/useView"
|
|
20
|
+
import { useOutsideGuard, usePortalTarget, useView, viewDocument } from "../composables/useView"
|
|
18
21
|
|
|
19
22
|
export interface ContextMenuItemDef {
|
|
20
23
|
label: string
|
|
@@ -39,7 +42,8 @@ export interface ContextMenuItemDef {
|
|
|
39
42
|
checked?: boolean
|
|
40
43
|
}
|
|
41
44
|
|
|
42
|
-
const props = defineProps<{
|
|
45
|
+
const props = withDefaults(defineProps<{
|
|
46
|
+
palette?: PaletteControlOptions
|
|
43
47
|
items: ContextMenuItemDef[]
|
|
44
48
|
/**
|
|
45
49
|
* Keep the reka menu mounted even while `items` is momentarily empty. Use when
|
|
@@ -64,7 +68,7 @@ const props = defineProps<{
|
|
|
64
68
|
* menus that only hold generic items (a whole table without row actions).
|
|
65
69
|
*/
|
|
66
70
|
noHint?: boolean
|
|
67
|
-
}>()
|
|
71
|
+
}>(), { palette: undefined })
|
|
68
72
|
|
|
69
73
|
// With no items the trigger is disabled, so the element keeps the browser's
|
|
70
74
|
// native context menu. Lets callers wrap unconditionally and pass [] to opt out
|
|
@@ -81,12 +85,13 @@ const PANEL = `${POPOVER_PANEL} z-(--z-popover) min-w-48 p-1 outline-none`
|
|
|
81
85
|
// selection if the menu action left the text as it was.
|
|
82
86
|
type TextField = HTMLInputElement | HTMLTextAreaElement
|
|
83
87
|
const SELECTABLE = new Set(["text", "search", "url", "tel", "password"])
|
|
88
|
+
const view = useView()
|
|
84
89
|
let field: { el: TextField; value: string; start: number; end: number } | null = null
|
|
85
90
|
|
|
86
91
|
function rememberField() {
|
|
87
|
-
const el =
|
|
92
|
+
const el = viewDocument(view.value).activeElement
|
|
88
93
|
const text =
|
|
89
|
-
el
|
|
94
|
+
el?.tagName === "TEXTAREA" || (el?.tagName === "INPUT" && SELECTABLE.has((el as HTMLInputElement).type))
|
|
90
95
|
field = text
|
|
91
96
|
? { el: el as TextField, value: (el as TextField).value, start: (el as TextField).selectionStart ?? 0, end: (el as TextField).selectionEnd ?? 0 }
|
|
92
97
|
: null
|
|
@@ -145,6 +150,13 @@ const portalTo = usePortalTarget()
|
|
|
145
150
|
// What happens in another document (the page around a frame, or a frame in
|
|
146
151
|
// the page) is not "outside" for this layer.
|
|
147
152
|
const guardOutside = useOutsideGuard()
|
|
153
|
+
|
|
154
|
+
const paletteScope = usePaletteScope()
|
|
155
|
+
const paletteId = useId()
|
|
156
|
+
usePaletteCommands(() => props.palette === false || !props.title || !props.items.length ? [] : [{
|
|
157
|
+
id: `${paletteScope?.id}/${props.palette?.id ?? paletteId}`, label: props.palette?.label ?? props.title,
|
|
158
|
+
children: menuPaletteCommands(props.items, `${paletteScope?.id}/${props.palette?.id ?? paletteId}`),
|
|
159
|
+
}], { automatic: true })
|
|
148
160
|
</script>
|
|
149
161
|
|
|
150
162
|
<template>
|
|
@@ -128,7 +128,7 @@ const pad = computed(() => (props.size === "sm" ? "py-1.5 text-xs" : "py-2.5 tex
|
|
|
128
128
|
</LpTooltip>
|
|
129
129
|
</dt>
|
|
130
130
|
<dd class="flex min-w-0 items-center gap-1.5 text-ink" :class="item.mono ? 'font-mono' : ''">
|
|
131
|
-
<span class="min-w-0
|
|
131
|
+
<span class="min-w-0 flex-1 [overflow-wrap:anywhere]">
|
|
132
132
|
<slot
|
|
133
133
|
v-if="slots[`value-${keyOf(item)}`] || slots.value"
|
|
134
134
|
:name="slots[`value-${keyOf(item)}`] ? `value-${keyOf(item)}` : 'value'"
|
|
@@ -136,7 +136,7 @@ const pad = computed(() => (props.size === "sm" ? "py-1.5 text-xs" : "py-2.5 tex
|
|
|
136
136
|
:value="item.value"
|
|
137
137
|
/>
|
|
138
138
|
<span v-else-if="isEmpty(item.value)" class="text-muted">{{ text.empty }}</span>
|
|
139
|
-
<LpRollingText v-else-if="rolls(item.value)" :value="item.value!" align="start" />
|
|
139
|
+
<LpRollingText v-else-if="rolls(item.value)" :value="item.value!" align="start" wrap />
|
|
140
140
|
<template v-else>{{ item.value }}</template>
|
|
141
141
|
</span>
|
|
142
142
|
<!-- Quiet until the row is hovered or focused; always there on touch,
|
|
@@ -87,6 +87,7 @@ const props = withDefaults(
|
|
|
87
87
|
|
|
88
88
|
const emit = defineEmits<{
|
|
89
89
|
(e: "update:modelValue", value: string | undefined): void
|
|
90
|
+
(e: "blur", event: FocusEvent): void
|
|
90
91
|
}>()
|
|
91
92
|
|
|
92
93
|
const open = ref(false)
|
|
@@ -197,6 +198,7 @@ const presetOptions = computed(() => presetList.value.map((preset) => ({
|
|
|
197
198
|
:presets="presetOptions"
|
|
198
199
|
presets-class="sm:w-36"
|
|
199
200
|
@clear="clear"
|
|
201
|
+
@blur="emit('blur', $event)"
|
|
200
202
|
>
|
|
201
203
|
<div class="flex flex-col">
|
|
202
204
|
<LpCalendar
|
|
@@ -69,6 +69,7 @@ const props = withDefaults(
|
|
|
69
69
|
|
|
70
70
|
const emit = defineEmits<{
|
|
71
71
|
(e: "update:modelValue", value: DateRange | undefined): void
|
|
72
|
+
(e: "blur", event: FocusEvent): void
|
|
72
73
|
}>()
|
|
73
74
|
|
|
74
75
|
const text = useLabels<DateRangePickerLabels>(
|
|
@@ -157,6 +158,7 @@ const presetOptions = computed(() => presetList.value.map((preset) => ({
|
|
|
157
158
|
:presets="presetOptions"
|
|
158
159
|
presets-class="sm:w-40"
|
|
159
160
|
@clear="emit('update:modelValue', undefined)"
|
|
161
|
+
@blur="emit('blur', $event)"
|
|
160
162
|
>
|
|
161
163
|
<LpRangeCalendar
|
|
162
164
|
:model-value="value"
|
|
@@ -6,6 +6,7 @@ export default { inheritAttrs: false }
|
|
|
6
6
|
</script>
|
|
7
7
|
|
|
8
8
|
<script setup lang="ts">
|
|
9
|
+
import { usePaletteAction, type PaletteControlOptions } from "../composables/usePaletteCommands"
|
|
9
10
|
/*
|
|
10
11
|
* Collapsible "show more" section built on reka Collapsible. The trigger is a
|
|
11
12
|
* full-width row with a chevron that rotates open; the body folds open and shut
|
|
@@ -31,6 +32,7 @@ import { useMergedAttrs } from "../composables/useMergedClass"
|
|
|
31
32
|
|
|
32
33
|
const props = withDefaults(
|
|
33
34
|
defineProps<{
|
|
35
|
+
palette?: PaletteControlOptions
|
|
34
36
|
/** Controlled open state. Omit to let the component own it (with `defaultOpen`). */
|
|
35
37
|
open?: boolean
|
|
36
38
|
defaultOpen?: boolean
|
|
@@ -45,7 +47,7 @@ const props = withDefaults(
|
|
|
45
47
|
*/
|
|
46
48
|
scrollIntoView?: boolean
|
|
47
49
|
}>(),
|
|
48
|
-
{ defaultOpen: false, scrollIntoView: false },
|
|
50
|
+
{ palette: undefined, defaultOpen: false, scrollIntoView: false },
|
|
49
51
|
)
|
|
50
52
|
|
|
51
53
|
const emit = defineEmits<{ (e: "update:open", value: boolean): void }>()
|
|
@@ -113,6 +115,8 @@ function onToggle(value: boolean) {
|
|
|
113
115
|
const { class: rootClass, attrs: rest } = useMergedAttrs(
|
|
114
116
|
"shrink-0 overflow-hidden rounded-control border border-line bg-surface-soft",
|
|
115
117
|
)
|
|
118
|
+
|
|
119
|
+
usePaletteAction({ label: () => props.label, element: () => (root.value?.$el as HTMLElement | undefined)?.querySelector<HTMLElement>("button"), disabled: () => false })
|
|
116
120
|
</script>
|
|
117
121
|
|
|
118
122
|
<template>
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { useId } from "vue"
|
|
3
|
+
import { menuPaletteCommands } from "./commandPalette"
|
|
4
|
+
import { usePaletteCommands, usePaletteScope, type PaletteControlOptions } from "../composables/usePaletteCommands"
|
|
2
5
|
/*
|
|
3
6
|
* A menu opened from a button (usually a row's "…"). Its items are the same
|
|
4
7
|
* shape as LpContextMenu's and are drawn by the same renderer, so one array
|
|
@@ -17,7 +20,8 @@ import { useOutsideGuard, usePortalTarget } from "../composables/useView"
|
|
|
17
20
|
/** A dropdown item: the context-menu item shape, kept under its old name. */
|
|
18
21
|
export type MenuItem = ContextMenuItemDef
|
|
19
22
|
|
|
20
|
-
const props = defineProps<{
|
|
23
|
+
const props = withDefaults(defineProps<{
|
|
24
|
+
palette?: PaletteControlOptions
|
|
21
25
|
items: MenuItem[]
|
|
22
26
|
/** A heading naming what the menu acts on; see LpContextMenu's `title`. */
|
|
23
27
|
title?: string
|
|
@@ -29,7 +33,7 @@ const props = defineProps<{
|
|
|
29
33
|
* menu). Opening it then counts toward the hint system's right-click tip.
|
|
30
34
|
*/
|
|
31
35
|
rightClickToo?: boolean
|
|
32
|
-
}>()
|
|
36
|
+
}>(), { palette: undefined })
|
|
33
37
|
|
|
34
38
|
const PANEL = `${POPOVER_PANEL} z-(--z-popover) min-w-44 p-1 outline-none`
|
|
35
39
|
|
|
@@ -42,10 +46,17 @@ const portalTo = usePortalTarget()
|
|
|
42
46
|
// What happens in another document (the page around a frame, or a frame in
|
|
43
47
|
// the page) is not "outside" for this layer.
|
|
44
48
|
const guardOutside = useOutsideGuard()
|
|
49
|
+
|
|
50
|
+
const paletteScope = usePaletteScope()
|
|
51
|
+
const paletteId = useId()
|
|
52
|
+
usePaletteCommands(() => props.palette === false || !props.title || !props.items.length ? [] : [{
|
|
53
|
+
id: `${paletteScope?.id}/${props.palette?.id ?? paletteId}`, label: props.palette?.label ?? props.title,
|
|
54
|
+
children: menuPaletteCommands(props.items, `${paletteScope?.id}/${props.palette?.id ?? paletteId}`),
|
|
55
|
+
}], { automatic: true })
|
|
45
56
|
</script>
|
|
46
57
|
|
|
47
58
|
<template>
|
|
48
|
-
<DropdownMenuRoot @update:open="opened">
|
|
59
|
+
<DropdownMenuRoot :modal="false" @update:open="opened">
|
|
49
60
|
<DropdownMenuTrigger as-child>
|
|
50
61
|
<slot name="trigger" />
|
|
51
62
|
</DropdownMenuTrigger>
|
|
@@ -129,7 +129,7 @@ function cancel() {
|
|
|
129
129
|
|
|
130
130
|
let committing = false
|
|
131
131
|
async function commit(refocus: boolean) {
|
|
132
|
-
if (!editing.value || committing) return
|
|
132
|
+
if (!editing.value || committing || !interactive.value) return
|
|
133
133
|
const value = props.trim ? draft.value.trim() : draft.value
|
|
134
134
|
if (value === props.modelValue) {
|
|
135
135
|
notice.clear()
|
|
@@ -273,6 +273,8 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(() => "relative inline-
|
|
|
273
273
|
:aria-invalid="(notice.tone.value === 'danger' && !!notice.message.value) || undefined"
|
|
274
274
|
:placeholder="placeholder"
|
|
275
275
|
:maxlength="maxlength"
|
|
276
|
+
:disabled="disabled"
|
|
277
|
+
:readonly="readonly"
|
|
276
278
|
:rows="multiline ? 1 : undefined"
|
|
277
279
|
class="col-start-1 row-start-1 w-full min-w-0 resize-none overflow-hidden bg-transparent text-ink outline-none placeholder:text-muted"
|
|
278
280
|
:class="PAD[size]"
|
|
@@ -49,6 +49,9 @@ const noticeId = computed(() => `${id.value}-notice`)
|
|
|
49
49
|
provideField(
|
|
50
50
|
computed(() => ({
|
|
51
51
|
id: id.value,
|
|
52
|
+
label: props.label,
|
|
53
|
+
hint: props.hint,
|
|
54
|
+
error: props.error,
|
|
52
55
|
labelId: props.label ? `${id.value}-label` : undefined,
|
|
53
56
|
describedBy:
|
|
54
57
|
[hasMessage.value ? messageId.value : "", notice.message.value ? noticeId.value : ""]
|
|
@@ -3,6 +3,7 @@ export default { inheritAttrs: false }
|
|
|
3
3
|
</script>
|
|
4
4
|
|
|
5
5
|
<script setup lang="ts">
|
|
6
|
+
import { usePaletteControl, type PaletteControlOptions } from "../composables/usePaletteCommands"
|
|
6
7
|
import { tv, type VariantProps } from "tailwind-variants"
|
|
7
8
|
import { computed, ref, useAttrs, useSlots } from "vue"
|
|
8
9
|
import { useFieldControl } from "../composables/useField"
|
|
@@ -46,6 +47,8 @@ type InputVariants = VariantProps<typeof shell>
|
|
|
46
47
|
|
|
47
48
|
const props = withDefaults(
|
|
48
49
|
defineProps<{
|
|
50
|
+
/** Contextual palette metadata; false excludes this control. */
|
|
51
|
+
palette?: PaletteControlOptions
|
|
49
52
|
modelValue?: string
|
|
50
53
|
size?: InputVariants["size"]
|
|
51
54
|
invalid?: boolean
|
|
@@ -87,7 +90,7 @@ const props = withDefaults(
|
|
|
87
90
|
/** Extra or replacement mask tokens, one-character RegExps by key. */
|
|
88
91
|
maskTokens?: MaskTokens
|
|
89
92
|
}>(),
|
|
90
|
-
{ type: "text", size: "md" },
|
|
93
|
+
{ palette: undefined, type: "text", size: "md" },
|
|
91
94
|
)
|
|
92
95
|
|
|
93
96
|
const emit = defineEmits<{
|
|
@@ -174,6 +177,8 @@ defineExpose({
|
|
|
174
177
|
select: () => inputEl.value?.select(),
|
|
175
178
|
input: inputEl,
|
|
176
179
|
})
|
|
180
|
+
|
|
181
|
+
usePaletteControl({ label: () => props.label, disabled: () => field.value.disabled, invalid: () => field.value.invalid, available: () => !['password', 'hidden'].includes(props.type), editorProps: () => ({ label: undefined, hint: undefined, error: undefined }) })
|
|
177
182
|
</script>
|
|
178
183
|
|
|
179
184
|
<template>
|
|
@@ -6,6 +6,7 @@ export default { inheritAttrs: false }
|
|
|
6
6
|
</script>
|
|
7
7
|
|
|
8
8
|
<script setup lang="ts">
|
|
9
|
+
import { usePaletteControl, type PaletteControlOptions } from "../composables/usePaletteCommands"
|
|
9
10
|
// Numeric input with stepper buttons (reka NumberField). Themed via tokens.
|
|
10
11
|
import {
|
|
11
12
|
NumberFieldDecrement,
|
|
@@ -25,6 +26,8 @@ export interface NumberFieldLabels extends Record<string, string> {
|
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
const props = withDefaults(defineProps<{
|
|
29
|
+
/** Contextual palette metadata; false excludes this control. */
|
|
30
|
+
palette?: PaletteControlOptions
|
|
28
31
|
// null = empty field (reka's native state); consumers that need a number
|
|
29
32
|
// should default it themselves, the field doesn't invent a value.
|
|
30
33
|
modelValue?: number | null
|
|
@@ -67,7 +70,7 @@ const props = withDefaults(defineProps<{
|
|
|
67
70
|
/** Control height, matching LpInput. */
|
|
68
71
|
size?: "sm" | "md" | "lg"
|
|
69
72
|
labels?: Partial<NumberFieldLabels>
|
|
70
|
-
}>(), { size: "md", stepSnapping: true, steppers: true, focusOnChange: true })
|
|
73
|
+
}>(), { palette: undefined, size: "md", stepSnapping: true, steppers: true, focusOnChange: true })
|
|
71
74
|
|
|
72
75
|
// The value is committed when the field loses focus or Enter is pressed, and on
|
|
73
76
|
// every step, not on each keystroke: "1." or "-" is not a number yet, and a
|
|
@@ -131,6 +134,8 @@ const rootClass = useMergedClass(() =>
|
|
|
131
134
|
: "border-line focus-within:border-brand focus-within:ring-ring",
|
|
132
135
|
].join(" "),
|
|
133
136
|
)
|
|
137
|
+
|
|
138
|
+
usePaletteControl({ disabled: () => field.value.disabled, invalid: () => field.value.invalid })
|
|
134
139
|
</script>
|
|
135
140
|
|
|
136
141
|
<template>
|
|
@@ -28,6 +28,8 @@
|
|
|
28
28
|
*/
|
|
29
29
|
import { computed, onBeforeUnmount, ref, watch } from "vue"
|
|
30
30
|
import { easeOut, prefersReducedMotion } from "../composables/easing"
|
|
31
|
+
import { useLocale } from "../composables/useLocale"
|
|
32
|
+
import { decimalMark } from "./format"
|
|
31
33
|
import { useRevealedValue } from "../composables/useRevealedValue"
|
|
32
34
|
import { compactNumber } from "./format"
|
|
33
35
|
|
|
@@ -222,6 +224,14 @@ const { el: revealAnchor, target } = useRevealedValue(() => props.value, {
|
|
|
222
224
|
watch(target, travel)
|
|
223
225
|
onBeforeUnmount(stop)
|
|
224
226
|
|
|
227
|
+
/*
|
|
228
|
+
* The app's locale (reka's ConfigProvider) when the counter has none of its
|
|
229
|
+
* own, the same rule the dates follow: a Russian app read "4,594" otherwise.
|
|
230
|
+
*/
|
|
231
|
+
const locale = useLocale(() => props.locale)
|
|
232
|
+
// Only the grouped form is written in the locale; the others always use ".".
|
|
233
|
+
const fractionMark = computed(() => (props.grouped && !props.format && !props.compact ? decimalMark(locale.value) : "."))
|
|
234
|
+
|
|
225
235
|
const formatted = computed(() => formatAt(round(displayed.value), !settled.value))
|
|
226
236
|
|
|
227
237
|
// Rounded first by the caller: every branch should render the shape the
|
|
@@ -246,7 +256,7 @@ function formatAt(v: number, padded: boolean): string {
|
|
|
246
256
|
}
|
|
247
257
|
const pad = padded ? Math.max(1, padTo.value) : 1
|
|
248
258
|
if (props.grouped)
|
|
249
|
-
return v.toLocaleString(
|
|
259
|
+
return v.toLocaleString(locale.value, {
|
|
250
260
|
minimumFractionDigits: props.decimals,
|
|
251
261
|
maximumFractionDigits: props.decimals,
|
|
252
262
|
minimumIntegerDigits: pad,
|
|
@@ -294,7 +304,7 @@ interface Cell {
|
|
|
294
304
|
*/
|
|
295
305
|
const cells = computed<Cell[]>(() => {
|
|
296
306
|
const chars = [...formatted.value]
|
|
297
|
-
const dot = chars.indexOf(
|
|
307
|
+
const dot = chars.indexOf(fractionMark.value)
|
|
298
308
|
const intEnd = dot === -1 ? chars.length : dot
|
|
299
309
|
|
|
300
310
|
const isDigit = (c: string) => {
|
|
@@ -20,11 +20,14 @@
|
|
|
20
20
|
import HighlightText from "./HighlightText.vue"
|
|
21
21
|
import LpIcon from "./LpIcon.vue"
|
|
22
22
|
import LpRollingText from "./LpRollingText.vue"
|
|
23
|
+
import LpSkeleton from "./LpSkeleton.vue"
|
|
23
24
|
import type { PaletteFact } from "./commandPalette"
|
|
25
|
+
import { computed } from "vue"
|
|
24
26
|
|
|
25
|
-
withDefaults(
|
|
27
|
+
const props = withDefaults(
|
|
26
28
|
defineProps<{
|
|
27
29
|
items: PaletteFact[]
|
|
30
|
+
loading?: boolean
|
|
28
31
|
/** Small heading over the list. */
|
|
29
32
|
title?: string
|
|
30
33
|
/** Plain rows instead of soft tiles, for a list read as text. */
|
|
@@ -32,6 +35,7 @@ withDefaults(
|
|
|
32
35
|
}>(),
|
|
33
36
|
{ plain: false },
|
|
34
37
|
)
|
|
38
|
+
const shown = computed(() => props.loading && !props.items.length ? Array.from({ length: 3 }, () => ({ label: "", value: "—" } as PaletteFact)) : props.items)
|
|
35
39
|
|
|
36
40
|
defineSlots<{
|
|
37
41
|
value?: (props: { item: PaletteFact; index: number }) => unknown
|
|
@@ -39,11 +43,11 @@ defineSlots<{
|
|
|
39
43
|
</script>
|
|
40
44
|
|
|
41
45
|
<template>
|
|
42
|
-
<section class="lp-palette-facts" :class="{ 'lp-palette-facts--plain': plain }">
|
|
46
|
+
<section class="lp-palette-facts" :aria-busy="loading || undefined" :class="{ 'lp-palette-facts--plain': plain }">
|
|
43
47
|
<p v-if="title" class="lp-palette-facts__title">{{ title }}</p>
|
|
44
48
|
<ul class="lp-palette-facts__list">
|
|
45
49
|
<li
|
|
46
|
-
v-for="(item, index) in
|
|
50
|
+
v-for="(item, index) in shown"
|
|
47
51
|
:key="index"
|
|
48
52
|
class="lp-palette-facts__row"
|
|
49
53
|
:class="{ 'is-current': item.current }"
|
|
@@ -52,15 +56,16 @@ defineSlots<{
|
|
|
52
56
|
<span v-if="item.color" class="lp-palette-facts__dot" :style="{ background: item.color }" />
|
|
53
57
|
<LpIcon v-else-if="item.icon" :name="item.icon" :size="15" class="lp-palette-facts__icon" />
|
|
54
58
|
<span class="lp-palette-facts__label">
|
|
55
|
-
<span class="lp-palette-facts__name"><HighlightText :text="item.label" /></span>
|
|
59
|
+
<span class="lp-palette-facts__name"><LpSkeleton v-if="loading && !item.label" class="h-3 w-24" /><HighlightText v-else :text="item.label" /></span>
|
|
56
60
|
<span v-if="item.hint?.length" class="lp-palette-facts__hint"><HighlightText :text="item.hint" /></span>
|
|
57
61
|
</span>
|
|
58
62
|
<span
|
|
59
|
-
v-if="item.value !== undefined && item.value !== '' || $slots.value"
|
|
63
|
+
v-if="loading || item.value !== undefined && item.value !== '' || $slots.value"
|
|
60
64
|
class="lp-palette-facts__value"
|
|
61
65
|
:class="{ 'lp-palette-facts__value--mono': item.mono }"
|
|
62
66
|
>
|
|
63
|
-
<
|
|
67
|
+
<LpSkeleton v-if="loading" class="h-3 w-16 max-w-full" />
|
|
68
|
+
<slot v-else name="value" :item="item" :index="index">
|
|
64
69
|
<LpRollingText v-if="item.value !== undefined" :value="item.value" align="end" />
|
|
65
70
|
</slot>
|
|
66
71
|
</span>
|
|
@@ -13,23 +13,29 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import LpNumberFlow from "./LpNumberFlow.vue"
|
|
15
15
|
import LpRollingText from "./LpRollingText.vue"
|
|
16
|
+
import LpSkeleton from "./LpSkeleton.vue"
|
|
16
17
|
import type { PaletteStat } from "./commandPalette"
|
|
18
|
+
import { computed } from "vue"
|
|
17
19
|
|
|
18
|
-
withDefaults(
|
|
20
|
+
const props = withDefaults(
|
|
19
21
|
defineProps<{
|
|
20
22
|
items: PaletteStat[]
|
|
23
|
+
loading?: boolean
|
|
21
24
|
/** Tiles per row. */
|
|
22
25
|
columns?: 2 | 3 | 4
|
|
23
26
|
}>(),
|
|
24
27
|
{ columns: 2 },
|
|
25
28
|
)
|
|
29
|
+
const shown = computed(() => props.loading && !props.items.length ? Array.from({ length: props.columns }, () => ({ label: "", value: "—" } as PaletteStat)) : props.items)
|
|
26
30
|
</script>
|
|
27
31
|
|
|
28
32
|
<template>
|
|
29
|
-
<dl class="lp-palette-stats" :style="{ gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))` }">
|
|
30
|
-
<div v-for="(item, index) in
|
|
31
|
-
<dt>{{ item.label }}</dt>
|
|
32
|
-
<dd>
|
|
33
|
+
<dl class="lp-palette-stats" :aria-busy="loading || undefined" :style="{ gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))` }">
|
|
34
|
+
<div v-for="(item, index) in shown" :key="`${item.label}-${index}`" class="lp-palette-stats__tile">
|
|
35
|
+
<dt><LpSkeleton v-if="loading && !item.label" class="my-1 h-2 w-20" /><template v-else>{{ item.label }}</template></dt>
|
|
36
|
+
<dd class="relative">
|
|
37
|
+
<LpSkeleton v-if="loading" class="absolute top-1/2 h-[1em] w-16 max-w-full -translate-y-1/2" />
|
|
38
|
+
<span :class="loading && 'invisible'" :aria-hidden="loading || undefined">
|
|
33
39
|
<LpNumberFlow
|
|
34
40
|
v-if="typeof item.value === 'number'"
|
|
35
41
|
:value="item.value"
|
|
@@ -40,6 +46,7 @@ withDefaults(
|
|
|
40
46
|
grouped
|
|
41
47
|
/>
|
|
42
48
|
<LpRollingText v-else :value="item.value" align="start" />
|
|
49
|
+
</span>
|
|
43
50
|
</dd>
|
|
44
51
|
</div>
|
|
45
52
|
</dl>
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed, ref } from "vue"
|
|
3
|
+
import type { StudioState, PreviewableThemeStudio } from "../theme/studio"
|
|
4
|
+
import { useLabels } from "../composables/useLpConfig"
|
|
5
|
+
import { suppressPaletteDiscovery } from "../composables/usePaletteCommands"
|
|
6
|
+
import LpThemeStudio from "./LpThemeStudio.vue"
|
|
7
|
+
import LpThemeProvider from "./LpThemeProvider.vue"
|
|
8
|
+
import LpButton from "./LpButton.vue"
|
|
9
|
+
import LpInput from "./LpInput.vue"
|
|
10
|
+
|
|
11
|
+
const props = defineProps<{ studio: PreviewableThemeStudio }>()
|
|
12
|
+
suppressPaletteDiscovery()
|
|
13
|
+
const text = useLabels("paletteTheme", { title: "Theme", apply: "Apply theme", revert: "Revert draft", sample: "Preview", action: "Continue", placeholder: "A field in this theme" })
|
|
14
|
+
const snapshot = ref({ ...props.studio.state.value })
|
|
15
|
+
const state = ref<StudioState>({ ...snapshot.value })
|
|
16
|
+
const preview = computed(() => props.studio.preview(state.value))
|
|
17
|
+
const changed = computed(() => JSON.stringify(state.value) !== JSON.stringify(snapshot.value))
|
|
18
|
+
const draft: PreviewableThemeStudio = {
|
|
19
|
+
state, themes: props.studio.themes, system: props.studio.system,
|
|
20
|
+
theme: computed(() => preview.value.theme), exported: computed(() => preview.value.exported), changed,
|
|
21
|
+
brand: computed({ get: () => preview.value.theme.colors.brand, set: brand => { state.value = { ...state.value, brand } } }),
|
|
22
|
+
pickTheme: theme => { state.value = { ...state.value, theme } },
|
|
23
|
+
tune: patch => { state.value = { ...state.value, ...patch } },
|
|
24
|
+
reset: () => { state.value = { ...snapshot.value } },
|
|
25
|
+
preview: props.studio.preview,
|
|
26
|
+
}
|
|
27
|
+
function apply() {
|
|
28
|
+
const { theme, ...tuning } = state.value
|
|
29
|
+
props.studio.pickTheme(theme)
|
|
30
|
+
props.studio.tune(tuning)
|
|
31
|
+
snapshot.value = { ...state.value }
|
|
32
|
+
}
|
|
33
|
+
</script>
|
|
34
|
+
|
|
35
|
+
<template>
|
|
36
|
+
<div class="flex min-w-0 flex-col gap-4">
|
|
37
|
+
<div class="sticky top-0 z-10 flex gap-2 border-b border-line bg-surface-overlay pb-3">
|
|
38
|
+
<LpButton :disabled="!changed" @click="apply">{{ text.apply }}</LpButton>
|
|
39
|
+
<LpButton variant="ghost" :disabled="!changed" @click="draft.reset()">{{ text.revert }}</LpButton>
|
|
40
|
+
</div>
|
|
41
|
+
<LpThemeProvider :theme="preview.theme" class="flex flex-col gap-3 rounded-card border border-line p-4">
|
|
42
|
+
<span class="text-sm font-semibold">{{ text.sample }}</span>
|
|
43
|
+
<LpInput :placeholder="text.placeholder" readonly :tabindex="-1" />
|
|
44
|
+
<LpButton :tabindex="-1">{{ text.action }}</LpButton>
|
|
45
|
+
</LpThemeProvider>
|
|
46
|
+
<LpThemeStudio :studio="draft" :labels="{ reset: text.revert }" />
|
|
47
|
+
</div>
|
|
48
|
+
</template>
|
|
@@ -8,20 +8,24 @@ export interface PasswordInputLabels extends Record<string, string> {
|
|
|
8
8
|
</script>
|
|
9
9
|
|
|
10
10
|
<script setup lang="ts">
|
|
11
|
+
import { suppressPaletteDiscovery } from "../composables/usePaletteCommands"
|
|
11
12
|
// Password field = LpInput + a show/hide toggle in its trailing slot.
|
|
12
13
|
// No duplicated field styling — the shell lives in LpInput.
|
|
13
14
|
// LpSecretField's input form is this same field: it drives `visible` (to hide
|
|
14
15
|
// again on a timer) and puts its copy button in `actions`.
|
|
15
16
|
import { ref } from "vue"
|
|
17
|
+
import { useFieldControl } from "../composables/useField"
|
|
16
18
|
import { useLabels } from "../composables/useLpConfig"
|
|
17
19
|
import LpInput from "./LpInput.vue"
|
|
18
20
|
import RevealToggle from "./RevealToggle.vue"
|
|
19
21
|
|
|
20
|
-
const props = defineProps<{
|
|
22
|
+
const props = withDefaults(defineProps<{
|
|
21
23
|
modelValue?: string
|
|
22
24
|
placeholder?: string
|
|
23
25
|
invalid?: boolean
|
|
24
26
|
disabled?: boolean
|
|
27
|
+
/** Offer the show/hide button. When false, the field stays masked. */
|
|
28
|
+
revealable?: boolean
|
|
25
29
|
// Field wrapping mirrors LpInput: passing any of these wraps the control in
|
|
26
30
|
// LpFormField, so a password field labels itself like every other field.
|
|
27
31
|
label?: string
|
|
@@ -31,10 +35,11 @@ const props = defineProps<{
|
|
|
31
35
|
/** Control height, as on LpInput. */
|
|
32
36
|
size?: "sm" | "md" | "lg"
|
|
33
37
|
labels?: Partial<PasswordInputLabels>
|
|
34
|
-
}>()
|
|
38
|
+
}>(), { revealable: true })
|
|
35
39
|
defineEmits<{ (e: "update:modelValue", value: string): void }>()
|
|
36
40
|
/** Whether the text shows; bind it to reveal or hide from outside. */
|
|
37
41
|
const visible = defineModel<boolean>("visible", { default: false })
|
|
42
|
+
const field = useFieldControl(() => ({ wrapped: false, disabled: props.disabled }))
|
|
38
43
|
|
|
39
44
|
const text = useLabels<PasswordInputLabels>(
|
|
40
45
|
"passwordInput",
|
|
@@ -47,6 +52,8 @@ defineExpose({
|
|
|
47
52
|
blur: () => inner.value?.blur(),
|
|
48
53
|
select: () => inner.value?.select(),
|
|
49
54
|
})
|
|
55
|
+
|
|
56
|
+
suppressPaletteDiscovery()
|
|
50
57
|
</script>
|
|
51
58
|
|
|
52
59
|
<template>
|
|
@@ -54,10 +61,10 @@ defineExpose({
|
|
|
54
61
|
ref="inner"
|
|
55
62
|
v-bind="$attrs"
|
|
56
63
|
:model-value="modelValue"
|
|
57
|
-
:type="visible ? 'text' : 'password'"
|
|
64
|
+
:type="revealable && visible ? 'text' : 'password'"
|
|
58
65
|
:placeholder="placeholder"
|
|
59
66
|
:invalid="invalid"
|
|
60
|
-
:disabled="disabled"
|
|
67
|
+
:disabled="field.disabled"
|
|
61
68
|
:label="label"
|
|
62
69
|
:hint="hint"
|
|
63
70
|
:error="error"
|
|
@@ -71,11 +78,12 @@ defineExpose({
|
|
|
71
78
|
<!-- Sized to the icon with a hair of padding, as the field's other
|
|
72
79
|
trailing controls are, rather than to a full square button. -->
|
|
73
80
|
<RevealToggle
|
|
81
|
+
v-if="revealable"
|
|
74
82
|
v-model="visible"
|
|
75
83
|
:icon-size="size === 'sm' ? 14 : 16"
|
|
76
84
|
:show-label="text.show"
|
|
77
85
|
:hide-label="text.hide"
|
|
78
|
-
:disabled="disabled"
|
|
86
|
+
:disabled="field.disabled"
|
|
79
87
|
class="size-auto rounded-inner p-1 hover:bg-transparent"
|
|
80
88
|
/>
|
|
81
89
|
</template>
|
|
@@ -10,6 +10,9 @@ import { mergeClass } from "../composables/useMergedClass"
|
|
|
10
10
|
import { POPOVER_PANEL } from "./dropdown"
|
|
11
11
|
import { useOutsideGuard, usePortalTarget } from "../composables/useView"
|
|
12
12
|
|
|
13
|
+
// The trigger owns its attributes through the slot; fallthrough tags the panel.
|
|
14
|
+
defineOptions({ inheritAttrs: false })
|
|
15
|
+
|
|
13
16
|
const props = withDefaults(
|
|
14
17
|
defineProps<{
|
|
15
18
|
side?: "top" | "right" | "bottom" | "left"
|
|
@@ -47,6 +50,7 @@ const guardOutside = useOutsideGuard()
|
|
|
47
50
|
</PopoverTrigger>
|
|
48
51
|
<PopoverPortal :to="portalTo">
|
|
49
52
|
<PopoverContent
|
|
53
|
+
v-bind="$attrs"
|
|
50
54
|
@interact-outside="guardOutside"
|
|
51
55
|
@escape-key-down="guardOutside"
|
|
52
56
|
:collision-padding="8"
|
|
@@ -6,6 +6,7 @@ export default { inheritAttrs: false }
|
|
|
6
6
|
</script>
|
|
7
7
|
|
|
8
8
|
<script setup lang="ts">
|
|
9
|
+
import { usePaletteControl, type PaletteControlOptions } from "../composables/usePaletteCommands"
|
|
9
10
|
import { RadioGroupIndicator, RadioGroupItem, RadioGroupRoot } from "reka-ui"
|
|
10
11
|
import { useId } from "vue"
|
|
11
12
|
import { useFieldControl } from "../composables/useField"
|
|
@@ -21,7 +22,7 @@ export interface RadioOption extends LpOptionBase<string> {
|
|
|
21
22
|
// a disabled option stays visible but cannot be picked. For anything richer
|
|
22
23
|
// (badges, custom layout) pass <LpRadio> children in the default slot instead —
|
|
23
24
|
// they share the same RadioGroupRoot, so selection still flows through v-model.
|
|
24
|
-
const props = defineProps<{ modelValue?: string; options?: RadioOption[]; disabled?: boolean }>()
|
|
25
|
+
const props = withDefaults(defineProps<{ palette?: PaletteControlOptions; modelValue?: string; options?: RadioOption[]; disabled?: boolean }>(), { palette: undefined })
|
|
25
26
|
defineEmits<{ (e: "update:modelValue", value: string): void }>()
|
|
26
27
|
|
|
27
28
|
const field = useFieldControl(() => ({ wrapped: false, disabled: props.disabled }))
|
|
@@ -31,6 +32,8 @@ const uid = useId()
|
|
|
31
32
|
const { class: rootClass, attrs: rest } = useMergedAttrs(
|
|
32
33
|
"flex flex-col gap-2",
|
|
33
34
|
)
|
|
35
|
+
|
|
36
|
+
usePaletteControl({ disabled: () => field.value.disabled })
|
|
34
37
|
</script>
|
|
35
38
|
|
|
36
39
|
<template>
|
|
@@ -6,6 +6,7 @@ export default { inheritAttrs: false }
|
|
|
6
6
|
</script>
|
|
7
7
|
|
|
8
8
|
<script setup lang="ts">
|
|
9
|
+
import { usePaletteControl, type PaletteControlOptions } from "../composables/usePaletteCommands"
|
|
9
10
|
/*
|
|
10
11
|
* Two thumbs on one track: a range rather than a value. A price "from – to",
|
|
11
12
|
* a stretch of a clip to loop, a span of years. The model is `[low, high]`;
|
|
@@ -20,6 +21,8 @@ import { SLIDER_GLIDE, useSliderDrag } from "./slider"
|
|
|
20
21
|
|
|
21
22
|
const props = withDefaults(
|
|
22
23
|
defineProps<{
|
|
24
|
+
/** Contextual palette metadata; false excludes this control. */
|
|
25
|
+
palette?: PaletteControlOptions
|
|
23
26
|
modelValue?: [number, number]
|
|
24
27
|
min?: number
|
|
25
28
|
max?: number
|
|
@@ -32,7 +35,7 @@ const props = withDefaults(
|
|
|
32
35
|
/** Label over each thumb while it is in use: `(value) => "1:05"`. */
|
|
33
36
|
format?: (value: number) => string
|
|
34
37
|
}>(),
|
|
35
|
-
{ modelValue: () => [0, 100], min: 0, max: 100, step: 1, minGap: 0 },
|
|
38
|
+
{ palette: undefined, modelValue: () => [0, 100], min: 0, max: 100, step: 1, minGap: 0 },
|
|
36
39
|
)
|
|
37
40
|
|
|
38
41
|
const emit = defineEmits<{
|
|
@@ -65,6 +68,8 @@ const thumbClass =
|
|
|
65
68
|
"group/thumb relative block size-4 rounded-pill border-2 border-brand bg-surface shadow outline-none transition-transform duration-[var(--duration-fast)] ease-[var(--ease-emphasized)] hover:scale-110 active:scale-95 focus-visible:ring-2 focus-visible:ring-ring motion-reduce:hover:scale-100 motion-reduce:active:scale-100"
|
|
66
69
|
const labelClass =
|
|
67
70
|
"pointer-events-none absolute bottom-full left-1/2 mb-1.5 -translate-x-1/2 translate-y-0.5 rounded-control bg-surface-raised px-1.5 py-0.5 text-[11px] whitespace-nowrap text-ink tabular-nums opacity-0 shadow-sm transition-[opacity,translate] duration-[var(--duration-fast)] ease-[var(--ease-emphasized)] group-hover/thumb:translate-y-0 group-hover/thumb:opacity-100 group-focus-visible/thumb:translate-y-0 group-focus-visible/thumb:opacity-100 group-active/thumb:translate-y-0 group-active/thumb:opacity-100 motion-reduce:transition-none"
|
|
71
|
+
|
|
72
|
+
usePaletteControl({ disabled: () => field.value.disabled })
|
|
68
73
|
</script>
|
|
69
74
|
|
|
70
75
|
<template>
|