@leavepulse/ui 0.70.1 → 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 +91 -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/{LpTable-DHxEQ_-3.css → LpTable-DHvorDiU.css} +19 -19
- package/dist/assets/LpTabs-CO3EcsNV.css +18 -0
- package/dist/chunks/{ContextMenuItems-6kxEivBI.js → ContextMenuItems-eS7qx9gD.js} +1 -1
- 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-Chv_Xf8q.js → LpAddressInput-CD0bzrt-.js} +7 -7
- package/dist/chunks/{LpAlert-C5igj802.js → LpAlert-BHi7ARqu.js} +1 -1
- package/dist/chunks/{LpAppShell-BiWByLmt.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-BBq1Er9T.js → LpBadge-C8fKEmTF.js} +1 -1
- package/dist/chunks/{LpBreadcrumbs-JKEi_yFF.js → LpBreadcrumbs-DhcoStFa.js} +1 -1
- 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-CbJMs-IK.js → LpCodeDisplay-BK2FHbtM.js} +5 -5
- package/dist/chunks/{LpColorPicker-B7HSIFmn.js → LpColorPicker-Ee1DZiRd.js} +2 -2
- 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-Cj96ENDC.js → LpContextMenu-DXpFJjlO.js} +13 -3
- package/dist/chunks/{LpCopyButton-DzHjnFs0.js → LpCopyButton-Dmq7DmFw.js} +3 -3
- package/dist/chunks/{LpCountdown-BQnmB4gq.js → LpCountdown-DTdMF8DL.js} +1 -1
- package/dist/chunks/{LpDataList-CHNYQw7h.js → LpDataList-CFPtSsBB.js} +3 -3
- package/dist/chunks/{LpDatePicker-ac1_6o5P.js → LpDatePicker-cC9K-Pk8.js} +4 -4
- package/dist/chunks/{LpDateRangePicker-B15gYrZJ.js → LpDateRangePicker-BVQKPbvo.js} +2 -2
- 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-R4aYVtVV.js → LpDropdownMenu-BgZ0Z_Im.js} +13 -3
- package/dist/chunks/{LpEditable-Ws3DNQHn.js → LpEditable-CjxuOVh_.js} +2 -2
- 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-DDNg34tJ.js → LpFileTree-BH0gNlSJ.js} +2 -2
- package/dist/chunks/{LpFileTreeNode-DmPuYNZ_.js → LpFileTreeNode-gPVB1oXM.js} +4 -4
- package/dist/chunks/{LpFormField-BWwgm1E4.js → LpFormField-gRASfyj2.js} +4 -1
- package/dist/chunks/{LpGauge-C14Z9503.js → LpGauge-BdjPGnqw.js} +1 -1
- package/dist/chunks/{LpHintLayer-HvwUA5Ec.js → LpHintLayer-C2asBIfs.js} +2 -2
- package/dist/chunks/{LpHints-DxbPKOzQ.js → LpHints-CNZQ76JV.js} +3 -3
- package/dist/chunks/{LpIcon-HJP5xMz4.js → LpIcon-DkP-9mzK.js} +1 -1
- package/dist/chunks/{LpInfraNode-D64hywJI.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-DKK4ySZl.js → LpLogViewer-x78YfhJf.js} +5 -5
- package/dist/chunks/{LpMapPicker-BtIl7NOM.js → LpMapPicker-Dp5RSCi9.js} +1 -1
- package/dist/chunks/{LpMediaGallery-rmI1DjKN.js → LpMediaGallery-D92oJfY_.js} +3 -3
- package/dist/chunks/{LpModal-eBMt2Fqn.js → LpModal-CpH0bNo7.js} +1 -1
- package/dist/chunks/{LpModalNav-DiyFCHiZ.js → LpModalNav-BH4ANQGJ.js} +4 -4
- package/dist/chunks/{LpNotificationBell-D-WhE5m2.js → LpNotificationBell-BdUQqZhs.js} +6 -6
- 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-GL2KOFK8.js → LpPasswordInput-BzAZsf5V.js} +4 -2
- package/dist/chunks/{LpPhoneInput-C60tx1tC.js → LpPhoneInput-BMpd-0QR.js} +2 -2
- package/dist/chunks/{LpPie-BgXZ3xmm.js → LpPie-DdFSTbGE.js} +4 -4
- package/dist/chunks/{LpPipeline-B31h41Mu.js → LpPipeline-zjEM1Lwc.js} +3 -3
- package/dist/chunks/{LpProgress-CE-m5OpD.js → LpProgress-BX33EKkN.js} +1 -1
- package/dist/chunks/{LpQuota-DaL8TgNe.js → LpQuota-DqNv1yjs.js} +2 -2
- 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-yin9uQP7.js → LpRelativeTime-UM8EkfrN.js} +1 -1
- package/dist/chunks/{LpRepeater-D0S7jjwr.js → LpRepeater-OvzByE5L.js} +2 -2
- package/dist/chunks/{LpSecretField-CfWyHv9m.js → LpSecretField-DwQiPOko.js} +9 -7
- 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-C_8cJtj6.js → LpSelect-DYX2-u5A.js} +36 -6
- package/dist/chunks/{LpSidebar-CZRXtvem.js → LpSidebar-D44peKq2.js} +3 -3
- package/dist/chunks/{LpSidebarNav-DBg1U1oW.js → LpSidebarNav--VwkXO_a.js} +3 -3
- package/dist/chunks/{LpSlider-DuoRpOrH.js → LpSlider-DxYoCJJO.js} +3 -0
- package/dist/chunks/{LpStat-DFKlPJgy.js → LpStat-DIsQfbeD.js} +3 -3
- package/dist/chunks/{LpStatus-BsGLrpor.js → LpStatus-BQU1TUsv.js} +1 -1
- package/dist/chunks/{LpStepMark-TrzOioa9.js → LpStepMark-CXa7DJy_.js} +1 -1
- package/dist/chunks/{LpStepper-BbnS5jUr.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-DZg80W-B.js → LpTagsInput-DrjmrOge.js} +8 -5
- package/dist/chunks/{LpTextarea-DiWjeVoJ.js → LpTextarea-BbYqmG1S.js} +4 -1
- package/dist/chunks/{LpThemeStudio-DxVZMtzN.js → LpThemeStudio-B2nPaG-h.js} +18 -14
- package/dist/chunks/{LpThemeSwitcher-CadVBTBn.js → LpThemeSwitcher-C0A5sg_E.js} +5 -3
- 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-C17A1XCb.js → LpTopologyCanvas-B0wEvAoq.js} +1 -1
- package/dist/chunks/{LpTour-CY2bFXge.js → LpTour-BgCfNlaW.js} +1 -1
- package/dist/chunks/{LpTruncate-D_5Pfv5B.js → LpTruncate-TcqfkyJM.js} +2 -2
- package/dist/chunks/{LpUptimeBar-Tew1Ykx4.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-DoHv0WMH.js → PickerField-DwLw7j0L.js} +1 -1
- package/dist/chunks/{RevealToggle-C-KzaQGJ.js → RevealToggle-BVFM_FAU.js} +3 -3
- package/dist/chunks/{TourCard-BJ8i7dk0.js → TourCard--2IfgnUU.js} +2 -2
- 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 +2 -2
- 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.js +1 -1
- 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.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/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/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 +14 -5
- 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.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 +4 -0
- package/dist/composables/useField.js +3 -0
- 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 +5 -1
- package/dist/icons-all.js +1 -1
- package/dist/index.d.ts +14 -1
- package/dist/index.js +101 -85
- package/dist/theme/palette.d.ts +9 -0
- package/dist/theme/studio.d.ts +12 -1
- package/package.json +1 -1
- package/src/component-names.ts +2 -0
- package/src/components/LpAutocomplete.vue +6 -1
- package/src/components/LpButton.vue +5 -1
- 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 +13 -2
- package/src/components/LpDisclosure.vue +5 -1
- package/src/components/LpDropdownMenu.vue +13 -2
- 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 +3 -0
- package/src/components/LpRadioGroup.vue +4 -1
- package/src/components/LpRangeSlider.vue +6 -1
- package/src/components/LpSecretField.vue +3 -0
- package/src/components/LpSegmented.vue +6 -1
- package/src/components/LpSelect.vue +41 -2
- 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/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 +7 -0
- package/src/composables/usePaletteCommands.ts +220 -0
- package/src/composables/useReveal.ts +29 -0
- package/src/composables/useView.ts +5 -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/icons-4IywzkHk.js +0 -43
|
@@ -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,6 +46,13 @@ 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>
|
|
@@ -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,6 +8,7 @@ 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
|
|
@@ -51,6 +52,8 @@ defineExpose({
|
|
|
51
52
|
blur: () => inner.value?.blur(),
|
|
52
53
|
select: () => inner.value?.select(),
|
|
53
54
|
})
|
|
55
|
+
|
|
56
|
+
suppressPaletteDiscovery()
|
|
54
57
|
</script>
|
|
55
58
|
|
|
56
59
|
<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
|
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>
|
|
@@ -12,6 +12,7 @@ export interface SecretFieldLabels extends Record<string, string> {
|
|
|
12
12
|
</script>
|
|
13
13
|
|
|
14
14
|
<script setup lang="ts">
|
|
15
|
+
import { suppressPaletteDiscovery } from "../composables/usePaletteCommands"
|
|
15
16
|
/*
|
|
16
17
|
* A value someone must be able to read and copy but should not have on screen
|
|
17
18
|
* by default: an API key, a bot token, a webhook secret, a recovery code.
|
|
@@ -178,6 +179,8 @@ const shell = computed(() =>
|
|
|
178
179
|
{ sm: "min-h-(--size-control-sm) pl-2.5 pr-1 text-xs", md: "min-h-(--size-control-md) pl-3 pr-1.5 text-sm", lg: "min-h-(--size-control-lg) pl-3.5 pr-1.5 text-sm" }[props.size],
|
|
179
180
|
),
|
|
180
181
|
)
|
|
182
|
+
|
|
183
|
+
suppressPaletteDiscovery()
|
|
181
184
|
</script>
|
|
182
185
|
|
|
183
186
|
<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
|
* Segmented control — a compact bar of mutually-exclusive options with a sliding
|
|
11
12
|
* pill marking the selection (iOS-style). Built on reka ToggleGroup for the
|
|
@@ -36,6 +37,8 @@ export interface SegmentedOption extends LpOptionBase<string> {
|
|
|
36
37
|
|
|
37
38
|
const props = withDefaults(
|
|
38
39
|
defineProps<{
|
|
40
|
+
/** Contextual palette metadata; false excludes this control. */
|
|
41
|
+
palette?: PaletteControlOptions
|
|
39
42
|
modelValue?: string
|
|
40
43
|
options: SegmentedOption[]
|
|
41
44
|
size?: "sm" | "md" | "lg"
|
|
@@ -49,7 +52,7 @@ const props = withDefaults(
|
|
|
49
52
|
*/
|
|
50
53
|
hoverFollow?: boolean
|
|
51
54
|
}>(),
|
|
52
|
-
{ size: "md", block: false, hoverFollow: true },
|
|
55
|
+
{ palette: undefined, size: "md", block: false, hoverFollow: true },
|
|
53
56
|
)
|
|
54
57
|
|
|
55
58
|
const emit = defineEmits<{
|
|
@@ -106,6 +109,8 @@ function releaseFocusAfterPointer(event: PointerEvent) {
|
|
|
106
109
|
const target = event.currentTarget
|
|
107
110
|
if (target instanceof HTMLElement) target.blur()
|
|
108
111
|
}
|
|
112
|
+
|
|
113
|
+
usePaletteControl({ disabled: () => field.value.disabled })
|
|
109
114
|
</script>
|
|
110
115
|
|
|
111
116
|
<template>
|
|
@@ -16,6 +16,7 @@ export type SelectLabels = {
|
|
|
16
16
|
</script>
|
|
17
17
|
|
|
18
18
|
<script setup lang="ts" generic="V extends SelectValue = string">
|
|
19
|
+
import { usePaletteControl, type PaletteControlOptions } from "../composables/usePaletteCommands"
|
|
19
20
|
/*
|
|
20
21
|
* One select to rule them all — built on reka-ui Combobox.
|
|
21
22
|
* `searchable` opts into the filter input; without it, it's a plain select.
|
|
@@ -61,6 +62,8 @@ type Model = V | V[] | undefined
|
|
|
61
62
|
|
|
62
63
|
const props = withDefaults(
|
|
63
64
|
defineProps<{
|
|
65
|
+
/** Contextual palette metadata; false excludes this control. */
|
|
66
|
+
palette?: PaletteControlOptions
|
|
64
67
|
modelValue?: Model
|
|
65
68
|
options: SelectOption<V>[]
|
|
66
69
|
placeholder?: string
|
|
@@ -90,7 +93,7 @@ const props = withDefaults(
|
|
|
90
93
|
selected?: SelectSelection | (SelectSelection | null | undefined)[] | null
|
|
91
94
|
labels?: Partial<SelectLabels>
|
|
92
95
|
}>(),
|
|
93
|
-
{
|
|
96
|
+
{ palette: undefined,
|
|
94
97
|
searchable: false,
|
|
95
98
|
multiple: false,
|
|
96
99
|
clearable: false,
|
|
@@ -173,12 +176,43 @@ function onOpenChange(open: boolean) {
|
|
|
173
176
|
isOpen.value = open
|
|
174
177
|
query.value = ""
|
|
175
178
|
}
|
|
179
|
+
async function openFromKeyboard(event: KeyboardEvent) {
|
|
180
|
+
if (field.value.disabled || isOpen.value || !["ArrowDown", "ArrowUp"].includes(event.key)) return
|
|
181
|
+
event.preventDefault()
|
|
182
|
+
event.stopPropagation()
|
|
183
|
+
const trigger = event.currentTarget as HTMLElement
|
|
184
|
+
trigger.click()
|
|
185
|
+
await nextTick()
|
|
186
|
+
const panel = trigger.ownerDocument.getElementById(trigger.getAttribute("aria-controls") ?? "")
|
|
187
|
+
const search = panel?.querySelector<HTMLInputElement>('input:not([disabled])')
|
|
188
|
+
const items = panel?.querySelectorAll<HTMLElement>('[role="option"]:not([data-disabled])')
|
|
189
|
+
const selected = panel?.querySelector<HTMLElement>('[role="option"][aria-selected="true"]:not([data-disabled])')
|
|
190
|
+
const target = search ?? selected ?? (event.key === "ArrowUp" ? items?.[items.length - 1] : items?.[0])
|
|
191
|
+
target?.focus()
|
|
192
|
+
}
|
|
176
193
|
|
|
177
194
|
// Leaving the field, not moving between its parts: the trigger and the list
|
|
178
195
|
// are marked with one id, because the list is portalled away from the trigger
|
|
179
196
|
// and a check on the trigger alone either missed the search box or took a
|
|
180
197
|
// step into it for leaving.
|
|
181
198
|
const { partId, onFocusOut } = useFieldBlur((event) => emit("blur", event))
|
|
199
|
+
const triggerRef = ref<{ $el: HTMLElement } | null>(null)
|
|
200
|
+
|
|
201
|
+
/*
|
|
202
|
+
* A pick closes the list while the chosen option still holds focus, then the
|
|
203
|
+
* option is removed and focus falls to the body: the field looked left, and
|
|
204
|
+
* the next arrow key went to the page (inside the palette's editor it went
|
|
205
|
+
* nowhere). Focus dropped by a closed list goes back to the trigger instead,
|
|
206
|
+
* and that is not leaving the field, so no blur is reported for it.
|
|
207
|
+
*/
|
|
208
|
+
function onListFocusOut(event: FocusEvent) {
|
|
209
|
+
const trigger = triggerRef.value?.$el
|
|
210
|
+
if (isOpen.value || event.relatedTarget || !trigger?.isConnected) {
|
|
211
|
+
onFocusOut(event)
|
|
212
|
+
return
|
|
213
|
+
}
|
|
214
|
+
trigger.focus({ preventScroll: true })
|
|
215
|
+
}
|
|
182
216
|
|
|
183
217
|
/*
|
|
184
218
|
* The trigger's name. reka hard-codes aria-label="Show popup" on it, which hid
|
|
@@ -368,6 +402,8 @@ const portalTo = usePortalTarget()
|
|
|
368
402
|
// What happens in another document (the page around a frame, or a frame in
|
|
369
403
|
// the page) is not "outside" for this layer.
|
|
370
404
|
const guardOutside = useOutsideGuard()
|
|
405
|
+
|
|
406
|
+
usePaletteControl({ disabled: () => field.value.disabled, invalid: () => field.value.invalid, editorProps: () => ({ selected: props.multiple ? modelList.value.map((value, index) => shown(value, index)) : current.value }) })
|
|
371
407
|
</script>
|
|
372
408
|
|
|
373
409
|
<template>
|
|
@@ -408,7 +444,10 @@ const guardOutside = useOutsideGuard()
|
|
|
408
444
|
being cut short. -->
|
|
409
445
|
<span :id="valueId" hidden>{{ valueText }}</span>
|
|
410
446
|
<ComboboxTrigger
|
|
447
|
+
ref="triggerRef"
|
|
411
448
|
:id="field.id"
|
|
449
|
+
:tabindex="field.disabled ? -1 : 0"
|
|
450
|
+
@keydown="openFromKeyboard"
|
|
412
451
|
v-bind="triggerName"
|
|
413
452
|
:aria-invalid="field.invalid || undefined"
|
|
414
453
|
:aria-describedby="field.describedBy"
|
|
@@ -524,7 +563,7 @@ const guardOutside = useOutsideGuard()
|
|
|
524
563
|
<ComboboxPortal :to="portalTo">
|
|
525
564
|
<ComboboxContent
|
|
526
565
|
:data-lp-field-part="partId"
|
|
527
|
-
@focusout="
|
|
566
|
+
@focusout="onListFocusOut"
|
|
528
567
|
@interact-outside="guardOutside"
|
|
529
568
|
@escape-key-down="guardOutside"
|
|
530
569
|
position="popper"
|
|
@@ -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
|
// Single-value slider (reka Slider). reka models value as an array; we expose
|
|
10
11
|
// a plain number for the common single-thumb case. Themed via tokens.
|
|
11
12
|
import { SliderRange, SliderRoot, SliderThumb, SliderTrack } from "reka-ui"
|
|
@@ -15,6 +16,8 @@ import { SLIDER_GLIDE, useSliderDrag } from "./slider"
|
|
|
15
16
|
|
|
16
17
|
const props = withDefaults(
|
|
17
18
|
defineProps<{
|
|
19
|
+
/** Contextual palette metadata; false excludes this control. */
|
|
20
|
+
palette?: PaletteControlOptions
|
|
18
21
|
modelValue?: number
|
|
19
22
|
min?: number
|
|
20
23
|
max?: number
|
|
@@ -23,7 +26,7 @@ const props = withDefaults(
|
|
|
23
26
|
/** Accessible name for the thumb when there's no visible label. */
|
|
24
27
|
ariaLabel?: string
|
|
25
28
|
}>(),
|
|
26
|
-
{ modelValue: 0, min: 0, max: 100, step: 1 },
|
|
29
|
+
{ palette: undefined, modelValue: 0, min: 0, max: 100, step: 1 },
|
|
27
30
|
)
|
|
28
31
|
|
|
29
32
|
const emit = defineEmits<{
|
|
@@ -47,6 +50,8 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(
|
|
|
47
50
|
`relative flex h-5 w-full touch-none select-none items-center data-[disabled]:opacity-55 ${SLIDER_GLIDE}`,
|
|
48
51
|
)
|
|
49
52
|
const { dragging, onPointerDown } = useSliderDrag()
|
|
53
|
+
|
|
54
|
+
usePaletteControl({ disabled: () => field.value.disabled })
|
|
50
55
|
</script>
|
|
51
56
|
|
|
52
57
|
<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
|
import { computed, useId, useSlots } from "vue"
|
|
10
11
|
import { SwitchRoot, SwitchThumb } from "reka-ui"
|
|
11
12
|
import { useFieldControl } from "../composables/useField"
|
|
@@ -15,6 +16,8 @@ import { useMergedAttrs } from "../composables/useMergedClass"
|
|
|
15
16
|
|
|
16
17
|
const props = withDefaults(
|
|
17
18
|
defineProps<{
|
|
19
|
+
/** Contextual palette metadata; false excludes this control. */
|
|
20
|
+
palette?: PaletteControlOptions
|
|
18
21
|
modelValue?: boolean
|
|
19
22
|
disabled?: boolean
|
|
20
23
|
label?: string
|
|
@@ -34,7 +37,7 @@ const props = withDefaults(
|
|
|
34
37
|
*/
|
|
35
38
|
action?: (value: boolean) => unknown
|
|
36
39
|
}>(),
|
|
37
|
-
{ labelPosition: "end" },
|
|
40
|
+
{ palette: undefined, labelPosition: "end" },
|
|
38
41
|
)
|
|
39
42
|
const emit = defineEmits<{
|
|
40
43
|
(e: "update:modelValue", value: boolean): void
|
|
@@ -79,6 +82,8 @@ const describedBy = computed(
|
|
|
79
82
|
function onUpdate(value: boolean) {
|
|
80
83
|
void set(value)
|
|
81
84
|
}
|
|
85
|
+
|
|
86
|
+
usePaletteControl({ label: () => props.label, disabled: () => field.value.disabled || pending.value, editorProps: () => ({ action: undefined, 'onUpdate:modelValue': onUpdate }) })
|
|
82
87
|
</script>
|
|
83
88
|
|
|
84
89
|
<template>
|