@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
|
@@ -4,8 +4,10 @@ import { useFieldControl } from "../composables/useField"
|
|
|
4
4
|
import { useLabels } from "../composables/useLpConfig"
|
|
5
5
|
import { useMergedAttrs } from "../composables/useMergedClass"
|
|
6
6
|
import { useRepeater, type RepeaterItemKey } from "../composables/useRepeater"
|
|
7
|
+
import { usePrefersReducedMotion } from "../composables/useReducedMotion"
|
|
7
8
|
import LpButton from "./LpButton.vue"
|
|
8
9
|
import LpIcon from "./LpIcon.vue"
|
|
10
|
+
import LpShift from "./LpShift.vue"
|
|
9
11
|
|
|
10
12
|
defineOptions({ inheritAttrs: false })
|
|
11
13
|
const props = defineProps<{
|
|
@@ -33,11 +35,31 @@ const list = useRepeater({
|
|
|
33
35
|
disabled: () => field.value.disabled,
|
|
34
36
|
})
|
|
35
37
|
const { rows } = list
|
|
36
|
-
const
|
|
38
|
+
const rowsHost = ref<HTMLElement | null>(null)
|
|
39
|
+
const reducedMotion = usePrefersReducedMotion()
|
|
37
40
|
const addButton = ref<InstanceType<typeof LpButton> | null>(null)
|
|
38
41
|
const focusable = 'input:not([type="hidden"]):not([disabled]), textarea:not([disabled]), select:not([disabled]), button:not([disabled]), [tabindex="0"], [contenteditable="true"]'
|
|
39
42
|
function focusRow(index: number) {
|
|
40
|
-
|
|
43
|
+
rowAt(index)?.querySelector<HTMLElement>(focusable)?.focus({ preventScroll: true })
|
|
44
|
+
}
|
|
45
|
+
function rowAt(index: number): HTMLElement | undefined {
|
|
46
|
+
return Array.from(rowsHost.value?.children ?? []).filter((node): node is HTMLElement =>
|
|
47
|
+
node.hasAttribute("data-lp-repeater-row") && !node.hasAttribute("inert"),
|
|
48
|
+
)[index]
|
|
49
|
+
}
|
|
50
|
+
function beforeLeave(el: Element) {
|
|
51
|
+
const row = el as HTMLElement
|
|
52
|
+
row.style.width = `${row.offsetWidth}px`
|
|
53
|
+
row.style.top = `${row.offsetTop}px`
|
|
54
|
+
row.setAttribute("inert", "")
|
|
55
|
+
row.setAttribute("aria-hidden", "true")
|
|
56
|
+
}
|
|
57
|
+
function beforeEnter(el: Element) {
|
|
58
|
+
const row = el as HTMLElement
|
|
59
|
+
row.removeAttribute("inert")
|
|
60
|
+
row.removeAttribute("aria-hidden")
|
|
61
|
+
row.style.removeProperty("top")
|
|
62
|
+
row.style.removeProperty("width")
|
|
41
63
|
}
|
|
42
64
|
async function add() {
|
|
43
65
|
if (field.value.disabled) return
|
|
@@ -47,34 +69,63 @@ async function add() {
|
|
|
47
69
|
}
|
|
48
70
|
async function remove(index: number) {
|
|
49
71
|
if (field.value.disabled) return
|
|
50
|
-
const row =
|
|
72
|
+
const row = rowAt(index)
|
|
51
73
|
const restore = row?.contains(row.ownerDocument.activeElement)
|
|
52
74
|
list.remove(index)
|
|
53
75
|
if (!restore) return
|
|
54
76
|
await nextTick()
|
|
55
77
|
if (model.value.length) focusRow(Math.min(index, model.value.length - 1))
|
|
56
|
-
else (addButton.value?.$el as HTMLElement | undefined)?.focus()
|
|
78
|
+
else (addButton.value?.$el as HTMLElement | undefined)?.focus({ preventScroll: true })
|
|
57
79
|
}
|
|
58
80
|
defineExpose({ add, remove, update: list.update })
|
|
59
81
|
const { class: rootClass, attrs: rest } = useMergedAttrs("flex min-w-0 flex-col gap-2")
|
|
60
82
|
</script>
|
|
61
83
|
|
|
62
84
|
<template>
|
|
63
|
-
<div
|
|
85
|
+
<div v-bind="rest" :class="rootClass">
|
|
64
86
|
<div class="flex items-center justify-between gap-2">
|
|
65
87
|
<span v-if="label" class="text-sm font-medium text-ink">{{ label }}</span>
|
|
66
88
|
<LpButton ref="addButton" size="xs" variant="ghost" :disabled="field.disabled" @click="add">
|
|
67
89
|
<LpIcon name="lucide:plus" :size="14" />{{ text.add }}
|
|
68
90
|
</LpButton>
|
|
69
91
|
</div>
|
|
70
|
-
<
|
|
71
|
-
<div class="min-w-0 flex-
|
|
72
|
-
<
|
|
92
|
+
<LpShift axis="height">
|
|
93
|
+
<div ref="rowsHost" class="relative flex min-w-0 flex-col gap-2">
|
|
94
|
+
<TransitionGroup name="lp-repeater" :css="!reducedMotion" @before-enter="beforeEnter" @before-leave="beforeLeave">
|
|
95
|
+
<div v-for="({ item, key }, index) in rows" :key="key" data-lp-repeater-row class="flex min-w-0 items-start gap-2">
|
|
96
|
+
<div class="min-w-0 flex-1">
|
|
97
|
+
<slot :item="item" :index="index" :disabled="field.disabled" :update="(next: T) => list.update(index, next)" :remove="() => remove(index)" />
|
|
98
|
+
</div>
|
|
99
|
+
<LpButton variant="ghost" size="sm" square :disabled="field.disabled" :aria-label="text.remove.replace('{index}', String(index + 1))" @click="remove(index)">
|
|
100
|
+
<LpIcon name="lucide:x" :size="14" />
|
|
101
|
+
</LpButton>
|
|
102
|
+
</div>
|
|
103
|
+
<div v-if="!rows.length" key="empty" class="text-xs text-muted"><slot name="empty">{{ text.empty }}</slot></div>
|
|
104
|
+
</TransitionGroup>
|
|
73
105
|
</div>
|
|
74
|
-
|
|
75
|
-
<LpIcon name="lucide:x" :size="14" />
|
|
76
|
-
</LpButton>
|
|
77
|
-
</div>
|
|
78
|
-
<div v-if="!rows.length" class="text-xs text-muted"><slot name="empty">{{ text.empty }}</slot></div>
|
|
106
|
+
</LpShift>
|
|
79
107
|
</div>
|
|
80
108
|
</template>
|
|
109
|
+
|
|
110
|
+
<style>
|
|
111
|
+
.lp-repeater-move,
|
|
112
|
+
.lp-repeater-enter-active,
|
|
113
|
+
.lp-repeater-leave-active {
|
|
114
|
+
transition: transform var(--duration-fast) var(--ease-emphasized), opacity var(--duration-fast) var(--ease-emphasized);
|
|
115
|
+
}
|
|
116
|
+
.lp-repeater-leave-active {
|
|
117
|
+
position: absolute;
|
|
118
|
+
}
|
|
119
|
+
.lp-repeater-enter-from,
|
|
120
|
+
.lp-repeater-leave-to {
|
|
121
|
+
opacity: 0;
|
|
122
|
+
transform: translateY(-0.5rem);
|
|
123
|
+
}
|
|
124
|
+
@media (prefers-reduced-motion: reduce) {
|
|
125
|
+
.lp-repeater-move,
|
|
126
|
+
.lp-repeater-enter-active,
|
|
127
|
+
.lp-repeater-leave-active {
|
|
128
|
+
transition: none;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
</style>
|
|
@@ -35,6 +35,8 @@ const props = withDefaults(
|
|
|
35
35
|
* width — a value that grows shouldn't shove its neighbours.
|
|
36
36
|
*/
|
|
37
37
|
align?: "start" | "center" | "end"
|
|
38
|
+
/** Wrap to the available width instead of keeping a single line. */
|
|
39
|
+
wrap?: boolean
|
|
38
40
|
}>(),
|
|
39
41
|
{ mode: "slide", direction: "up", duration: 320, align: "center" },
|
|
40
42
|
)
|
|
@@ -63,7 +65,7 @@ const style = computed(() => ({
|
|
|
63
65
|
<template>
|
|
64
66
|
<span
|
|
65
67
|
class="lp-roll relative inline-flex overflow-hidden align-bottom"
|
|
66
|
-
:class="justify"
|
|
68
|
+
:class="[justify, wrap && 'lp-roll--wrap']"
|
|
67
69
|
:style="style"
|
|
68
70
|
>
|
|
69
71
|
<Transition :name="name">
|
|
@@ -93,6 +95,15 @@ const style = computed(() => ({
|
|
|
93
95
|
backface-visibility: hidden;
|
|
94
96
|
}
|
|
95
97
|
|
|
98
|
+
.lp-roll--wrap {
|
|
99
|
+
max-width: 100%;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.lp-roll--wrap .lp-roll__item {
|
|
103
|
+
white-space: normal;
|
|
104
|
+
overflow-wrap: anywhere;
|
|
105
|
+
}
|
|
106
|
+
|
|
96
107
|
/* The outgoing copy leaves the flow so the incoming one keeps the baseline. */
|
|
97
108
|
.lp-roll-up-leave-active,
|
|
98
109
|
.lp-roll-down-leave-active,
|
|
@@ -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.
|
|
@@ -37,6 +38,7 @@ import { computed, onBeforeUnmount, onMounted, ref, useId, watch } from "vue"
|
|
|
37
38
|
import { prefersReducedMotion } from "../composables/easing"
|
|
38
39
|
import { useScramble } from "../composables/useScramble"
|
|
39
40
|
import { useLabels } from "../composables/useLpConfig"
|
|
41
|
+
import { useFieldControl } from "../composables/useField"
|
|
40
42
|
import { mergeClass } from "../composables/useMergedClass"
|
|
41
43
|
import FieldWrapper from "./FieldWrapper.vue"
|
|
42
44
|
import LpButton from "./LpButton.vue"
|
|
@@ -91,7 +93,11 @@ const emit = defineEmits<{
|
|
|
91
93
|
}>()
|
|
92
94
|
|
|
93
95
|
/** Shown or hidden; bind it to drive the reveal from outside. */
|
|
94
|
-
const
|
|
96
|
+
const revealedModel = defineModel<boolean>("revealed", { default: false })
|
|
97
|
+
const revealed = computed({
|
|
98
|
+
get: () => props.revealable && revealedModel.value,
|
|
99
|
+
set: (value: boolean) => { revealedModel.value = value },
|
|
100
|
+
})
|
|
95
101
|
|
|
96
102
|
const text = useLabels<SecretFieldLabels>(
|
|
97
103
|
"secretField",
|
|
@@ -107,6 +113,7 @@ const text = useLabels<SecretFieldLabels>(
|
|
|
107
113
|
)
|
|
108
114
|
|
|
109
115
|
const secret = computed(() => (props.input ? props.modelValue : props.value) ?? "")
|
|
116
|
+
const control = useFieldControl(() => ({ wrapped: false, disabled: props.disabled }))
|
|
110
117
|
|
|
111
118
|
// Revealing decrypts the value into place, and a new value (a regenerated key)
|
|
112
119
|
// decrypts over the old one: the change is seen happening, not just swapped.
|
|
@@ -167,11 +174,13 @@ const shell = computed(() =>
|
|
|
167
174
|
mergeClass(
|
|
168
175
|
"relative flex w-full items-center gap-1 overflow-hidden rounded-control border bg-surface-soft text-ink transition-colors duration-(--duration-fast)",
|
|
169
176
|
props.error ? "border-danger" : "border-line",
|
|
170
|
-
|
|
177
|
+
control.value.disabled ? "opacity-55" : "",
|
|
171
178
|
props.wrap ? "py-1.5" : "",
|
|
172
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],
|
|
173
180
|
),
|
|
174
181
|
)
|
|
182
|
+
|
|
183
|
+
suppressPaletteDiscovery()
|
|
175
184
|
</script>
|
|
176
185
|
|
|
177
186
|
<template>
|
|
@@ -184,7 +193,8 @@ const shell = computed(() =>
|
|
|
184
193
|
class="[&_input]:font-mono"
|
|
185
194
|
:model-value="modelValue"
|
|
186
195
|
:placeholder="placeholder"
|
|
187
|
-
:disabled="disabled"
|
|
196
|
+
:disabled="control.disabled"
|
|
197
|
+
:revealable="revealable"
|
|
188
198
|
:label="label"
|
|
189
199
|
:hint="hint"
|
|
190
200
|
:error="error"
|
|
@@ -199,7 +209,7 @@ const shell = computed(() =>
|
|
|
199
209
|
:value="secret"
|
|
200
210
|
size="xs"
|
|
201
211
|
class="size-7"
|
|
202
|
-
:disabled="disabled"
|
|
212
|
+
:disabled="control.disabled"
|
|
203
213
|
@copied="(t: string) => emit('copied', t)"
|
|
204
214
|
/>
|
|
205
215
|
<slot name="actions" />
|
|
@@ -212,7 +222,7 @@ const shell = computed(() =>
|
|
|
212
222
|
:aria-label="text.regenerate"
|
|
213
223
|
:title="text.regenerate"
|
|
214
224
|
:action="regenerate"
|
|
215
|
-
:disabled="disabled"
|
|
225
|
+
:disabled="control.disabled"
|
|
216
226
|
>
|
|
217
227
|
<LpIcon name="lucide:refresh-cw" :size="iconSize" />
|
|
218
228
|
</LpButton>
|
|
@@ -264,7 +274,7 @@ const shell = computed(() =>
|
|
|
264
274
|
:icon-size="iconSize"
|
|
265
275
|
:show-label="text.show"
|
|
266
276
|
:hide-label="text.hide"
|
|
267
|
-
:disabled="disabled"
|
|
277
|
+
:disabled="control.disabled"
|
|
268
278
|
:controls="id"
|
|
269
279
|
class="size-7"
|
|
270
280
|
/>
|
|
@@ -273,7 +283,7 @@ const shell = computed(() =>
|
|
|
273
283
|
:value="secret"
|
|
274
284
|
:size="copySize"
|
|
275
285
|
class="size-7 text-muted hover:text-ink"
|
|
276
|
-
:disabled="disabled"
|
|
286
|
+
:disabled="control.disabled"
|
|
277
287
|
@copied="(t: string) => emit('copied', t)"
|
|
278
288
|
/>
|
|
279
289
|
<slot name="actions" />
|
|
@@ -284,7 +294,7 @@ const shell = computed(() =>
|
|
|
284
294
|
square
|
|
285
295
|
class="size-7 text-muted hover:text-ink"
|
|
286
296
|
:action="regenerate"
|
|
287
|
-
:disabled="disabled"
|
|
297
|
+
:disabled="control.disabled"
|
|
288
298
|
>
|
|
289
299
|
<LpIcon name="lucide:refresh-cw" :size="iconSize" />
|
|
290
300
|
</LpButton>
|
|
@@ -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.
|
|
@@ -36,7 +37,7 @@ import {
|
|
|
36
37
|
ComboboxViewport,
|
|
37
38
|
} from "reka-ui"
|
|
38
39
|
import { computed, nextTick, reactive, ref, useAttrs, useId, watch } from "vue"
|
|
39
|
-
import { useFieldControl } from "../composables/useField"
|
|
40
|
+
import { useFieldBlur, useFieldControl } from "../composables/useField"
|
|
40
41
|
import { useLabels } from "../composables/useLpConfig"
|
|
41
42
|
import { useMergedAttrs } from "../composables/useMergedClass"
|
|
42
43
|
import { OPTION_ITEM, optionStagger, POPOVER_PANEL } from "./dropdown"
|
|
@@ -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,16 +176,42 @@ 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
|
-
const
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
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 })
|
|
186
215
|
}
|
|
187
216
|
|
|
188
217
|
/*
|
|
@@ -373,6 +402,8 @@ const portalTo = usePortalTarget()
|
|
|
373
402
|
// What happens in another document (the page around a frame, or a frame in
|
|
374
403
|
// the page) is not "outside" for this layer.
|
|
375
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 }) })
|
|
376
407
|
</script>
|
|
377
408
|
|
|
378
409
|
<template>
|
|
@@ -396,7 +427,7 @@ const guardOutside = useOutsideGuard()
|
|
|
396
427
|
@update:open="onOpenChange"
|
|
397
428
|
>
|
|
398
429
|
<ComboboxAnchor
|
|
399
|
-
:data-lp-
|
|
430
|
+
:data-lp-field-part="partId"
|
|
400
431
|
@focusout="onFocusOut"
|
|
401
432
|
:class="[
|
|
402
433
|
anchorHeight,
|
|
@@ -413,7 +444,10 @@ const guardOutside = useOutsideGuard()
|
|
|
413
444
|
being cut short. -->
|
|
414
445
|
<span :id="valueId" hidden>{{ valueText }}</span>
|
|
415
446
|
<ComboboxTrigger
|
|
447
|
+
ref="triggerRef"
|
|
416
448
|
:id="field.id"
|
|
449
|
+
:tabindex="field.disabled ? -1 : 0"
|
|
450
|
+
@keydown="openFromKeyboard"
|
|
417
451
|
v-bind="triggerName"
|
|
418
452
|
:aria-invalid="field.invalid || undefined"
|
|
419
453
|
:aria-describedby="field.describedBy"
|
|
@@ -528,8 +562,8 @@ const guardOutside = useOutsideGuard()
|
|
|
528
562
|
|
|
529
563
|
<ComboboxPortal :to="portalTo">
|
|
530
564
|
<ComboboxContent
|
|
531
|
-
:data-lp-
|
|
532
|
-
@focusout="
|
|
565
|
+
:data-lp-field-part="partId"
|
|
566
|
+
@focusout="onListFocusOut"
|
|
533
567
|
@interact-outside="guardOutside"
|
|
534
568
|
@escape-key-down="guardOutside"
|
|
535
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>
|
|
@@ -5,7 +5,10 @@ export default { inheritAttrs: false }
|
|
|
5
5
|
</script>
|
|
6
6
|
|
|
7
7
|
<script setup lang="ts" generic="T extends Record<string, unknown>">
|
|
8
|
-
import { computed, nextTick, onBeforeUnmount, onMounted, ref, shallowRef, useAttrs, watch } from "vue"
|
|
8
|
+
import { computed, h, nextTick, onBeforeUnmount, onMounted, ref, shallowRef, useAttrs, useId, watch } from "vue"
|
|
9
|
+
import { suppressPaletteDiscovery, usePaletteCommands, usePaletteScope } from "../composables/usePaletteCommands"
|
|
10
|
+
import { menuPaletteCommands } from "./commandPalette"
|
|
11
|
+
import LpDataList from "./LpDataList.vue"
|
|
9
12
|
import LpCheckbox from "./LpCheckbox.vue"
|
|
10
13
|
import LpContextMenu, { type ContextMenuItemDef } from "./LpContextMenu.vue"
|
|
11
14
|
import LpEmptyState from "./LpEmptyState.vue"
|
|
@@ -157,6 +160,8 @@ type RowKey = string | number
|
|
|
157
160
|
|
|
158
161
|
const props = withDefaults(
|
|
159
162
|
defineProps<{
|
|
163
|
+
/** Publish loaded rows and existing row actions to the enclosing command scope. */
|
|
164
|
+
palette?: false | { id?: string; label?: string; labelKey?: keyof T }
|
|
160
165
|
columns: TableColumn<T>[]
|
|
161
166
|
/** The rows, for a table that holds its data. Ignored when `load` is set. */
|
|
162
167
|
rows?: T[]
|
|
@@ -245,7 +250,7 @@ const props = withDefaults(
|
|
|
245
250
|
*/
|
|
246
251
|
allMatching?: boolean
|
|
247
252
|
}>(),
|
|
248
|
-
{
|
|
253
|
+
{ palette: undefined,
|
|
249
254
|
rows: () => [],
|
|
250
255
|
pageSize: 25,
|
|
251
256
|
skeletonRows: 5,
|
|
@@ -1075,6 +1080,34 @@ onBeforeUnmount(() => {
|
|
|
1075
1080
|
const barInsetTop = computed(() =>
|
|
1076
1081
|
props.stickyHeader && headHeight.value ? `${headHeight.value}px` : undefined,
|
|
1077
1082
|
)
|
|
1083
|
+
|
|
1084
|
+
const paletteScope = usePaletteScope()
|
|
1085
|
+
const paletteId = useId()
|
|
1086
|
+
suppressPaletteDiscovery()
|
|
1087
|
+
usePaletteCommands(() => {
|
|
1088
|
+
if (props.palette === false) return []
|
|
1089
|
+
const name = props.palette?.label ?? attrs["aria-label"] as string | undefined
|
|
1090
|
+
if (!name) return []
|
|
1091
|
+
const id = `${paletteScope?.id}/${props.palette?.id ?? paletteId}`
|
|
1092
|
+
return [{
|
|
1093
|
+
id, label: name, icon: "lucide:table", children: [
|
|
1094
|
+
...menuPaletteCommands(tableMenu(), `${id}/table`),
|
|
1095
|
+
...displayRows.value.map((row, index) => {
|
|
1096
|
+
const menu = resolveRowMenu(props.rowMenu?.(row))
|
|
1097
|
+
const rowId = `${id}/row/${keyFor(row, index)}`
|
|
1098
|
+
const labelKey = props.palette && props.palette.labelKey || props.columns[0]?.key
|
|
1099
|
+
return {
|
|
1100
|
+
id: rowId, label: menu.title ?? String(labelKey ? row[labelKey] ?? keyFor(row, index) : keyFor(row, index)),
|
|
1101
|
+
description: menu.subtitle, icon: menu.icon ?? "lucide:rows-3", image: menu.image,
|
|
1102
|
+
onSelect: () => emit("rowClick", row), actions: menuPaletteCommands(menu.items, rowId),
|
|
1103
|
+
previewComponent: { setup: () => () => h(LpDataList, { items: props.columns.map(column => ({
|
|
1104
|
+
label: column.label, value: typeof row[column.key] === "object" ? null : String(row[column.key] ?? ""),
|
|
1105
|
+
})) }) },
|
|
1106
|
+
}
|
|
1107
|
+
}),
|
|
1108
|
+
],
|
|
1109
|
+
}]
|
|
1110
|
+
}, { automatic: true })
|
|
1078
1111
|
</script>
|
|
1079
1112
|
|
|
1080
1113
|
<template>
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
import { Motion } from "motion-v"
|
|
13
13
|
import { computed, onBeforeUnmount, onMounted, ref, useId, watch } from "vue"
|
|
14
14
|
import { useLabels } from "../composables/useLpConfig"
|
|
15
|
-
import { scrollParent } from "../composables/scroll"
|
|
15
|
+
import { atScrollEnd, scrollParent } from "../composables/scroll"
|
|
16
16
|
import { usePillTransition } from "../composables/usePillTransition"
|
|
17
17
|
|
|
18
18
|
export interface TocLink {
|
|
@@ -112,9 +112,7 @@ function setup() {
|
|
|
112
112
|
const line = Math.max(props.offset, view / 4)
|
|
113
113
|
for (const el of headings) if (el.getBoundingClientRect().top - top <= line + 1) current = el.id
|
|
114
114
|
const scrolled = scroller ? scroller.scrollTop : window.scrollY
|
|
115
|
-
const end =
|
|
116
|
-
? scroller.scrollTop + scroller.clientHeight >= scroller.scrollHeight - 2
|
|
117
|
-
: window.scrollY + window.innerHeight >= document.documentElement.scrollHeight - 2
|
|
115
|
+
const end = atScrollEnd(headings[0])
|
|
118
116
|
if (scrolled > 0 && end) current = headings[headings.length - 1]!.id
|
|
119
117
|
activeId.value = current
|
|
120
118
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { usePaletteCommands, usePaletteScope } from "../composables/usePaletteCommands"
|
|
2
3
|
import { Motion } from "motion-v"
|
|
3
4
|
import { TabsContent, TabsList, TabsRoot, TabsTrigger } from "reka-ui"
|
|
4
5
|
import { computed, nextTick, ref, useId, watch } from "vue"
|
|
@@ -152,6 +153,12 @@ function releaseFocusAfterPointer(event: PointerEvent) {
|
|
|
152
153
|
const target = event.currentTarget
|
|
153
154
|
if (target instanceof HTMLElement) target.blur()
|
|
154
155
|
}
|
|
156
|
+
|
|
157
|
+
const paletteScope = usePaletteScope()
|
|
158
|
+
usePaletteCommands(() => props.items.map(item => ({
|
|
159
|
+
id: `${paletteScope?.id}/tabs/${pillId}/${item.value}`, label: props.label ? `${props.label}: ${item.label}` : item.label,
|
|
160
|
+
icon: item.icon, disabled: item.disabled, onSelect: () => select(item.value),
|
|
161
|
+
})), { automatic: true })
|
|
155
162
|
</script>
|
|
156
163
|
|
|
157
164
|
<template>
|
|
@@ -13,6 +13,7 @@ export type TagsInputLabels = {
|
|
|
13
13
|
</script>
|
|
14
14
|
|
|
15
15
|
<script setup lang="ts">
|
|
16
|
+
import { usePaletteControl, type PaletteControlOptions } from "../composables/usePaletteCommands"
|
|
16
17
|
/*
|
|
17
18
|
* Free-form list of short values: emails, labels, hostnames. Typing a
|
|
18
19
|
* delimiter or Enter turns the text into a tag, a paste is split into many,
|
|
@@ -56,6 +57,8 @@ import { useOutsideGuard, usePortalTarget } from "../composables/useView"
|
|
|
56
57
|
|
|
57
58
|
const props = withDefaults(
|
|
58
59
|
defineProps<{
|
|
60
|
+
/** Contextual palette metadata; false excludes this control. */
|
|
61
|
+
palette?: PaletteControlOptions
|
|
59
62
|
modelValue?: string[]
|
|
60
63
|
placeholder?: string
|
|
61
64
|
/** Characters (or a RegExp) that end a tag while typing and split a paste. */
|
|
@@ -99,7 +102,7 @@ const props = withDefaults(
|
|
|
99
102
|
/** Box height and text size, as LpInput. */
|
|
100
103
|
size?: "sm" | "md" | "lg"
|
|
101
104
|
}>(),
|
|
102
|
-
{
|
|
105
|
+
{ palette: undefined,
|
|
103
106
|
modelValue: () => [],
|
|
104
107
|
delimiter: () => [",", "\n", "\t"],
|
|
105
108
|
duplicates: "reject",
|
|
@@ -424,6 +427,8 @@ const portalTo = usePortalTarget()
|
|
|
424
427
|
// What happens in another document (the page around a frame, or a frame in
|
|
425
428
|
// the page) is not "outside" for this layer.
|
|
426
429
|
const guardOutside = useOutsideGuard()
|
|
430
|
+
|
|
431
|
+
usePaletteControl({ label: () => props.label, disabled: () => field.value.disabled, invalid: () => field.value.invalid, editorProps: () => ({ label: undefined, hint: undefined, error: undefined }) })
|
|
427
432
|
</script>
|
|
428
433
|
|
|
429
434
|
<template>
|
|
@@ -3,12 +3,15 @@ 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 { computed, useAttrs } from "vue"
|
|
7
8
|
import { useFieldControl } from "../composables/useField"
|
|
8
9
|
import { mergeClass } from "../composables/useMergedClass"
|
|
9
10
|
import FieldWrapper from "./FieldWrapper.vue"
|
|
10
11
|
|
|
11
|
-
const props = defineProps<{
|
|
12
|
+
const props = withDefaults(defineProps<{
|
|
13
|
+
/** Contextual palette metadata; false excludes this control. */
|
|
14
|
+
palette?: PaletteControlOptions
|
|
12
15
|
modelValue?: string
|
|
13
16
|
placeholder?: string
|
|
14
17
|
rows?: number
|
|
@@ -22,7 +25,7 @@ const props = defineProps<{
|
|
|
22
25
|
* the <textarea> for native validation.
|
|
23
26
|
*/
|
|
24
27
|
required?: boolean
|
|
25
|
-
}>()
|
|
28
|
+
}>(), { palette: undefined })
|
|
26
29
|
|
|
27
30
|
defineEmits<{ (e: "update:modelValue", value: string): void }>()
|
|
28
31
|
|
|
@@ -53,6 +56,8 @@ const textareaClass = computed(() =>
|
|
|
53
56
|
hasField.value ? "" : (attrs.class as string),
|
|
54
57
|
),
|
|
55
58
|
)
|
|
59
|
+
|
|
60
|
+
usePaletteControl({ label: () => props.label, disabled: () => field.value.disabled, invalid: () => field.value.invalid, editorProps: () => ({ label: undefined, hint: undefined, error: undefined }) })
|
|
56
61
|
</script>
|
|
57
62
|
|
|
58
63
|
<template>
|