@leavepulse/ui 0.43.4 → 0.45.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 +121 -7
- package/dist/assets/{LpCommandPalette-B-0Est4Z.css → LpCommandPalette-nGNnzXqQ.css} +21 -21
- package/dist/assets/{LpDropzone-BBoWvi-J.css → LpDropzone-i4BdMi1H.css} +12 -12
- package/dist/assets/{LpImageEditor-Ct7Y3aNu.css → LpImageEditor-CbMA82g8.css} +6 -6
- package/dist/assets/{LpRollingText-CR1mb0Vt.css → LpRollingText-BGnE6q9j.css} +3 -0
- package/dist/assets/{LpShortcutsDialog-C6YoQ8_M.css → LpShortcutsDialog-CqYX3yy6.css} +28 -7
- package/dist/assets/{LpSkeleton-D7xU8IPV.css → LpSkeleton-H3Z5dEIk.css} +4 -1
- package/dist/assets/{LpTable-BgPLJOXa.css → LpTable-CPwWxTJS.css} +49 -9
- package/dist/chunks/ContextMenuItems-BtKU7074.js +124 -0
- package/dist/chunks/{LayoutCanvas-Dd20boUG.js → LayoutCanvas-BkaGXTjx.js} +26 -9
- package/dist/chunks/{LayoutNode-DGpZA9LX.js → LayoutNode-B3_9E1Xa.js} +28 -12
- package/dist/chunks/{LpActionBar-BlvtGB2P.js → LpActionBar-CnfFVIwC.js} +26 -12
- package/dist/chunks/{LpAddressInput-B-Zvxsn7.js → LpAddressInput-BwX8uo4_.js} +54 -49
- package/dist/chunks/{LpAlert-BAYHDSS1.js → LpAlert-B6ilrM7T.js} +16 -9
- package/dist/chunks/{LpAppShell-BGQVIY-3.js → LpAppShell-C53_RaGF.js} +53 -26
- package/dist/chunks/{LpAutocomplete-DExlIZe_.js → LpAutocomplete-C8IgSMsi.js} +52 -24
- package/dist/chunks/{LpAvatar-B3-xAOH3.js → LpAvatar-C1XStdOo.js} +19 -10
- package/dist/chunks/LpBreadcrumbs-CQJd73Gm.js +95 -0
- package/dist/chunks/{LpButton-5VXXCjwF.js → LpButton-CKSwC6Mu.js} +45 -15
- package/dist/chunks/{LpCalendar-B7Ko5RdR.js → LpCalendar-DrA2McTU.js} +1 -1
- package/dist/chunks/{LpCard-BhI1N_vL.js → LpCard-C2IvucmX.js} +1 -1
- package/dist/chunks/{LpCheckbox-CVccKYaH.js → LpCheckbox-Bkj13CbW.js} +8 -4
- package/dist/chunks/{LpCodeBlock-Bo0B4TFR.js → LpCodeBlock-ca7ANFyW.js} +49 -17
- package/dist/chunks/{LpColorPicker-BlXea7LM.js → LpColorPicker-zz4VGkG4.js} +75 -26
- package/dist/chunks/{LpConfirmDialog-Q-bxff8z.js → LpConfirmDialog-DCw5jR1t.js} +59 -17
- package/dist/chunks/LpConfirmHost-CbywMpMP.js +49 -0
- package/dist/chunks/LpContextMenu-BqkAYa9X.js +69 -0
- package/dist/chunks/LpDatePicker-DuusgT69.js +195 -0
- package/dist/chunks/LpDateRangePicker-DHeuznfC.js +208 -0
- package/dist/chunks/{LpDisclosure-ChQYmjlR.js → LpDisclosure-Cc23-JOT.js} +1 -1
- package/dist/chunks/{LpDrawer-BZ6k3hvo.js → LpDrawer-Dt4aB4Fr.js} +65 -28
- package/dist/chunks/{LpDropdownMenu-DJpoqRCb.js → LpDropdownMenu-DdJGQzPn.js} +2 -1
- package/dist/chunks/{LpEmptyState-Dsdqz1Wj.js → LpEmptyState-BJbZXC8D.js} +1 -1
- package/dist/chunks/LpFieldNotice-wtieLUTj.js +64 -0
- package/dist/chunks/{LpFileTree-_5vFBgaK.js → LpFileTree-CNurOvkV.js} +25 -10
- package/dist/chunks/{LpFileTreeNode-BdcIYKIE.js → LpFileTreeNode-D_qRRdsH.js} +3 -3
- package/dist/chunks/LpFormField-CtVYj6tO.js +101 -0
- package/dist/chunks/{LpIcon-CCnX5_2j.js → LpIcon-DYtaid0K.js} +20 -6
- package/dist/chunks/{LpInput-9EXWUM9B.js → LpInput-D-YGQbEv.js} +58 -20
- package/dist/chunks/{LpLightbox-2sYVMY-S.js → LpLightbox-DSDahF23.js} +148 -61
- package/dist/chunks/{LpLink-DCND-zyu.js → LpLink-Krkjhe_y.js} +15 -6
- package/dist/chunks/{LpLogViewer-CaRy5MeS.js → LpLogViewer-KypbgOyo.js} +300 -72
- package/dist/chunks/{LpMapPicker-ul4oYno6.js → LpMapPicker-Cc84LaM3.js} +39 -14
- package/dist/chunks/{LpMediaGallery-FF-NquIo.js → LpMediaGallery-YKr-cQPN.js} +7 -4
- package/dist/chunks/{LpModal-Bt0pQCI_.js → LpModal-DMMDQHAu.js} +52 -29
- package/dist/chunks/{LpModalNav-YaifHrXC.js → LpModalNav-BVPDyIup.js} +10 -7
- package/dist/chunks/{LpNotificationBell-DyGGsMAM.js → LpNotificationBell-CCwyJP5C.js} +79 -33
- package/dist/chunks/{LpNumberField-CWuX08iX.js → LpNumberField-B77O-z28.js} +21 -8
- package/dist/chunks/{LpNumberFlow-amWYaeuA.js → LpNumberFlow-z4WPZcZu.js} +22 -12
- package/dist/chunks/{LpOtpInput-y2v-pmiN.js → LpOtpInput-CziPF3Oq.js} +37 -8
- package/dist/chunks/{LpPagination-5FxjmmB5.js → LpPagination-BcDlo3r_.js} +31 -20
- package/dist/chunks/{LpPasswordInput--sjYCkLS.js → LpPasswordInput-eKzQhbQP.js} +11 -8
- package/dist/chunks/LpPhoneInput-BCbrrhgE.js +336 -0
- package/dist/chunks/{LpPie-D6OnzwlJ.js → LpPie-BEJ2SfI6.js} +84 -28
- package/dist/chunks/{LpPopover-8268UmlC.js → LpPopover-DCKeqiVn.js} +5 -2
- package/dist/chunks/{LpProgress-Btq5W4Ut.js → LpProgress-CBU1iI69.js} +5 -4
- package/dist/chunks/{LpRadioGroup-xPIuVDO_.js → LpRadioGroup-DmEW0l78.js} +9 -2
- package/dist/chunks/LpRangeCalendar-DZuaRV0W.js +331 -0
- package/dist/chunks/{LpRollingText-CM5gkSeF.js → LpRollingText-DB7upf-5.js} +1 -1
- package/dist/chunks/{LpScrollArea-D8xyKXcF.js → LpScrollArea-Bry1fdOM.js} +14 -2
- package/dist/chunks/{LpSection-aM6J_u51.js → LpSection-tKEH0jYf.js} +1 -1
- package/dist/chunks/{LpSegmented-fV0Sk92p.js → LpSegmented-C09EEam2.js} +8 -4
- package/dist/chunks/{LpSelect-ANIVtrpM.js → LpSelect-DNIL6MB9.js} +50 -31
- package/dist/chunks/{LpSidebar-ClBUwoEz.js → LpSidebar-CQNB0-yU.js} +30 -22
- package/dist/chunks/{LpSidebarNav-llOcs_Fn.js → LpSidebarNav-kx-LdqNU.js} +16 -11
- package/dist/chunks/{LpSkeleton-CTI-vBgW.js → LpSkeleton-BB6XIV-w.js} +1 -1
- package/dist/chunks/{LpSlider-BwNIBkAK.js → LpSlider-Cuzmrd7p.js} +7 -2
- package/dist/chunks/{LpSparkline-C6xQ2dwv.js → LpSparkline-CB80N8SJ.js} +11 -4
- package/dist/chunks/{LpStat-CQaW8R--.js → LpStat-B-7udBRP.js} +2 -2
- package/dist/chunks/{LpStepper-Bk-XaQYU.js → LpStepper-C7XiVKZj.js} +34 -19
- package/dist/chunks/{LpSwitch-Blizvqyt.js → LpSwitch-OrcOJX9m.js} +41 -27
- package/dist/chunks/LpTableFilter-BV8PpLM9.js +158 -0
- package/dist/chunks/{LpTableOfContents-CjvxPMpU.js → LpTableOfContents-BUcAfGPQ.js} +36 -41
- package/dist/chunks/{LpTabs-Cefe_lys.js → LpTabs-29iW1XOx.js} +20 -6
- package/dist/chunks/LpTagsInput-D1SuqbhB.js +300 -0
- package/dist/chunks/LpTextarea-uuScWo6-.js +77 -0
- package/dist/chunks/LpThemeProvider-Be4r2TQX.js +35 -0
- package/dist/chunks/LpThemeSwitcher-B4aVPbNC.js +166 -0
- package/dist/chunks/{LpTilt-DuyKbpkA.js → LpTilt-B7KHX1zH.js} +2 -2
- package/dist/chunks/{LpTimeField-K6nAGboX.js → LpTimeField-Cqe7fXnh.js} +14 -8
- package/dist/chunks/{LpToaster-gDB1EaU3.js → LpToaster-DpJvoCOh.js} +94 -31
- package/dist/chunks/{LpTooltip-hCLPAqMG.js → LpTooltip-CXVKcOXT.js} +14 -6
- package/dist/chunks/LpTooltipProvider-CftjV7Xc.js +25 -0
- package/dist/chunks/{LpTopologyCanvas-Cm1L39uL.js → LpTopologyCanvas-6ozNrQKh.js} +8 -2
- package/dist/chunks/{LpUptimeBar-DvAMno0S.js → LpUptimeBar-ugcv25xj.js} +44 -15
- package/dist/chunks/icons-CkA0njzm.js +43 -0
- package/dist/chunks/{LpThemeSwitcher-Cue-myST.js → useTheme-DJm1JSsY.js} +215 -260
- package/dist/component-names.d.ts +1 -1
- package/dist/components/ContextMenuItems.vue.d.ts +8 -0
- package/dist/components/ContextMenuItems.vue.js +4 -0
- package/dist/components/LayoutCanvas.vue.js +1 -1
- package/dist/components/LayoutNode.vue.d.ts +4 -0
- package/dist/components/LayoutNode.vue.js +1 -1
- package/dist/components/LpActionBar.vue.d.ts +3 -0
- 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 +9 -0
- package/dist/components/LpAlert.vue.js +1 -1
- package/dist/components/LpAppShell.vue.d.ts +10 -0
- package/dist/components/LpAppShell.vue.js +1 -1
- package/dist/components/LpAutocomplete.vue.d.ts +31 -6
- package/dist/components/LpAutocomplete.vue.js +1 -1
- package/dist/components/LpAvatar.vue.d.ts +3 -3
- package/dist/components/LpAvatar.vue.js +1 -1
- package/dist/components/LpBadge.vue.d.ts +2 -2
- package/dist/components/LpBreadcrumbs.vue.d.ts +13 -9
- package/dist/components/LpBreadcrumbs.vue.js +1 -1
- package/dist/components/LpButton.vue.d.ts +35 -98
- package/dist/components/LpButton.vue.js +1 -1
- package/dist/components/LpCalendar.vue.js +1 -1
- package/dist/components/LpCard.vue.js +1 -1
- package/dist/components/LpChart.vue.d.ts +47 -3
- package/dist/components/LpChart.vue.js +377 -97
- package/dist/components/LpCheckbox.vue.js +1 -1
- package/dist/components/LpCodeBlock.vue.d.ts +2 -0
- package/dist/components/LpCodeBlock.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 +14 -3
- package/dist/components/LpCommandPalette.vue.js +142 -77
- package/dist/components/LpConfirmDialog.vue.d.ts +15 -3
- package/dist/components/LpConfirmDialog.vue.js +1 -1
- package/dist/components/LpConfirmHost.vue.d.ts +9 -0
- package/dist/components/LpConfirmHost.vue.js +4 -0
- package/dist/components/LpContextMenu.vue.d.ts +3 -5
- package/dist/components/LpContextMenu.vue.js +1 -1
- package/dist/components/LpDatePicker.vue.d.ts +24 -6
- package/dist/components/LpDatePicker.vue.js +1 -1
- package/dist/components/LpDateRangePicker.vue.d.ts +60 -0
- package/dist/components/LpDateRangePicker.vue.js +4 -0
- package/dist/components/LpDisclosure.vue.js +1 -1
- package/dist/components/LpDrawer.vue.d.ts +10 -0
- package/dist/components/LpDrawer.vue.js +1 -1
- package/dist/components/LpDropdownMenu.vue.js +1 -1
- package/dist/components/LpDropzone.vue.js +23 -7
- package/dist/components/LpEmptyState.vue.js +1 -1
- package/dist/components/LpFieldNotice.vue.d.ts +8 -0
- package/dist/components/LpFieldNotice.vue.js +4 -0
- package/dist/components/LpFileTree.vue.d.ts +11 -2
- package/dist/components/LpFileTree.vue.js +1 -1
- package/dist/components/LpFileTreeNode.vue.js +1 -1
- package/dist/components/LpFormField.vue.d.ts +13 -1
- package/dist/components/LpFormField.vue.js +1 -1
- package/dist/components/LpIcon.vue.d.ts +0 -1
- package/dist/components/LpIcon.vue.js +1 -1
- package/dist/components/LpImageEditor.vue.js +93 -58
- package/dist/components/LpInput.vue.d.ts +22 -3
- package/dist/components/LpInput.vue.js +1 -1
- package/dist/components/LpLightbox.vue.d.ts +17 -0
- package/dist/components/LpLightbox.vue.js +1 -1
- package/dist/components/LpLink.vue.d.ts +11 -11
- package/dist/components/LpLink.vue.js +1 -1
- package/dist/components/LpLogViewer.vue.d.ts +72 -3
- package/dist/components/LpLogViewer.vue.js +1 -1
- package/dist/components/LpMapPicker.vue.d.ts +4 -4
- package/dist/components/LpMapPicker.vue.js +1 -1
- package/dist/components/LpMediaGallery.vue.js +1 -1
- package/dist/components/LpModal.vue.d.ts +16 -6
- package/dist/components/LpModal.vue.js +1 -1
- package/dist/components/LpModalNav.vue.d.ts +0 -1
- package/dist/components/LpModalNav.vue.js +1 -1
- package/dist/components/LpNotificationBell.vue.d.ts +11 -2
- package/dist/components/LpNotificationBell.vue.js +1 -1
- package/dist/components/LpNumberField.vue.d.ts +2 -0
- package/dist/components/LpNumberField.vue.js +1 -1
- package/dist/components/LpNumberFlow.vue.js +1 -1
- package/dist/components/LpOtpInput.vue.js +1 -1
- package/dist/components/LpPagination.vue.d.ts +2 -0
- package/dist/components/LpPagination.vue.js +1 -1
- package/dist/components/LpPasswordInput.vue.js +1 -1
- package/dist/components/LpPhoneInput.vue.d.ts +13 -0
- package/dist/components/LpPhoneInput.vue.js +1 -1
- package/dist/components/LpPie.vue.d.ts +21 -2
- package/dist/components/LpPie.vue.js +1 -1
- package/dist/components/LpPopover.vue.d.ts +2 -0
- 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/LpRadioGroup.vue.js +1 -1
- package/dist/components/LpRangeCalendar.vue.d.ts +51 -0
- package/dist/components/LpRangeCalendar.vue.js +4 -0
- package/dist/components/LpRollingText.vue.d.ts +1 -1
- package/dist/components/LpRollingText.vue.js +1 -1
- package/dist/components/LpScrollArea.vue.d.ts +2 -2
- package/dist/components/LpScrollArea.vue.js +1 -1
- package/dist/components/LpSection.vue.d.ts +1 -1
- package/dist/components/LpSection.vue.js +1 -1
- package/dist/components/LpSegmented.vue.d.ts +5 -0
- package/dist/components/LpSegmented.vue.js +1 -1
- package/dist/components/LpSelect.vue.d.ts +1 -0
- package/dist/components/LpSelect.vue.js +1 -1
- package/dist/components/LpShortcutsDialog.vue.d.ts +7 -1
- package/dist/components/LpShortcutsDialog.vue.js +60 -15
- package/dist/components/LpSidebar.vue.d.ts +6 -2
- package/dist/components/LpSidebar.vue.js +1 -1
- package/dist/components/LpSidebarNav.vue.js +1 -1
- package/dist/components/LpSkeleton.vue.js +1 -1
- package/dist/components/LpSlider.vue.js +1 -1
- package/dist/components/LpSparkline.vue.d.ts +1 -0
- package/dist/components/LpSparkline.vue.js +1 -1
- package/dist/components/LpStat.vue.js +1 -1
- package/dist/components/LpStepper.vue.js +1 -1
- package/dist/components/LpSwitch.vue.js +1 -1
- package/dist/components/LpTable.vue.d.ts +107 -3
- package/dist/components/LpTable.vue.js +540 -128
- package/dist/components/LpTableFilter.vue.d.ts +31 -0
- package/dist/components/LpTableFilter.vue.js +4 -0
- package/dist/components/LpTableOfContents.vue.d.ts +4 -2
- package/dist/components/LpTableOfContents.vue.js +1 -1
- package/dist/components/LpTabs.vue.d.ts +2 -0
- package/dist/components/LpTabs.vue.js +1 -1
- package/dist/components/LpTagsInput.vue.d.ts +77 -0
- package/dist/components/LpTagsInput.vue.js +4 -0
- package/dist/components/LpTextarea.vue.d.ts +19 -6
- package/dist/components/LpTextarea.vue.js +1 -1
- package/dist/components/LpThemeProvider.vue.d.ts +22 -0
- package/dist/components/LpThemeProvider.vue.js +4 -0
- package/dist/components/LpThemeSwitcher.vue.d.ts +15 -2
- package/dist/components/LpThemeSwitcher.vue.js +1 -1
- package/dist/components/LpTilt.vue.js +1 -1
- package/dist/components/LpTimeField.vue.js +1 -1
- package/dist/components/LpToaster.vue.d.ts +6 -1
- package/dist/components/LpToaster.vue.js +1 -1
- package/dist/components/LpTooltip.vue.d.ts +1 -2
- package/dist/components/LpTooltip.vue.js +1 -1
- package/dist/components/LpTooltipProvider.vue.d.ts +22 -0
- package/dist/components/LpTooltipProvider.vue.js +4 -0
- package/dist/components/LpTopologyCanvas.vue.js +1 -1
- package/dist/components/LpUptimeBar.vue.d.ts +4 -0
- package/dist/components/LpUptimeBar.vue.js +1 -1
- package/dist/components/chart.d.ts +32 -1
- package/dist/components/chart.js +42 -6
- package/dist/components/codeHighlight.d.ts +6 -0
- package/dist/components/codeHighlight.js +92 -20
- package/dist/components/color.d.ts +1 -1
- package/dist/components/color.js +20 -9
- package/dist/components/commandSearch.js +3 -0
- package/dist/components/confirm.d.ts +25 -0
- package/dist/components/confirm.js +26 -0
- package/dist/components/countries.d.ts +6 -0
- package/dist/components/countries.js +7 -0
- package/dist/components/dateRange.d.ts +43 -0
- package/dist/components/dateRange.js +76 -0
- package/dist/components/exportData.d.ts +58 -0
- package/dist/components/exportData.js +165 -0
- package/dist/components/fileTree.js +16 -7
- package/dist/components/imageCrop.d.ts +42 -0
- package/dist/components/imageCrop.js +47 -0
- package/dist/components/link.d.ts +12 -0
- package/dist/components/link.js +19 -0
- package/dist/components/logSearch.d.ts +18 -0
- package/dist/components/logSearch.js +36 -0
- package/dist/components/modalDepth.d.ts +18 -2
- package/dist/components/modalDepth.js +17 -5
- package/dist/components/otp.d.ts +5 -0
- package/dist/components/otp.js +10 -0
- package/dist/components/phone.d.ts +41 -0
- package/dist/components/phone.js +80 -0
- package/dist/components/sidebar.d.ts +7 -1
- package/dist/components/tableFilter.d.ts +36 -0
- package/dist/components/tableFilter.js +84 -0
- package/dist/components/tableSort.d.ts +8 -0
- package/dist/components/tableSort.js +31 -0
- package/dist/components/tags.d.ts +20 -0
- package/dist/components/tags.js +37 -0
- package/dist/composables/useField.d.ts +38 -0
- package/dist/composables/useField.js +45 -0
- package/dist/composables/useFieldNotice.d.ts +17 -0
- package/dist/composables/useFieldNotice.js +28 -0
- package/dist/composables/useForm.d.ts +53 -0
- package/dist/composables/useForm.js +207 -0
- package/dist/composables/useFormDraft.d.ts +10 -3
- package/dist/composables/useFormDraft.js +9 -14
- package/dist/composables/useHotkeys.d.ts +81 -5
- package/dist/composables/useHotkeys.js +223 -25
- package/dist/composables/useInputFilter.d.ts +17 -0
- package/dist/composables/useInputFilter.js +47 -10
- package/dist/composables/useInputMask.d.ts +59 -0
- package/dist/composables/useInputMask.js +170 -0
- package/dist/composables/useLpConfig.d.ts +24 -0
- package/dist/composables/useLpConfig.js +44 -0
- package/dist/composables/usePaintSelect.d.ts +22 -0
- package/dist/composables/usePaintSelect.js +169 -0
- package/dist/composables/useRovingFocus.js +7 -0
- package/dist/composables/useShift.js +7 -2
- package/dist/composables/useTilt.d.ts +2 -2
- package/dist/composables/useTilt.js +5 -6
- package/dist/composables/useToast.d.ts +20 -0
- package/dist/composables/useToast.js +28 -4
- package/dist/composables/useZoomPan.d.ts +3 -3
- package/dist/composables/useZoomPan.js +4 -4
- package/dist/icons-all.d.ts +1 -0
- package/dist/icons-all.js +3 -0
- package/dist/icons.d.ts +14 -1
- package/dist/index.d.ts +60 -4
- package/dist/index.js +245 -141
- package/dist/kit-icons.d.ts +2 -0
- package/dist/layout/tree.d.ts +2 -0
- package/dist/layout/tree.js +16 -1
- package/dist/layout/useLayout.d.ts +15 -0
- package/dist/layout/useLayout.js +41 -14
- package/dist/theme/backdrop.d.ts +12 -0
- package/dist/theme/presets.d.ts +0 -2
- package/dist/theme/useTheme.d.ts +32 -9
- package/package.json +18 -8
- package/src/component-names.ts +9 -7
- package/src/components/ContextMenuItems.vue +88 -0
- package/src/components/LayoutCanvas.vue +26 -6
- package/src/components/LayoutNode.vue +30 -4
- package/src/components/LpActionBar.vue +31 -8
- package/src/components/LpAddressInput.vue +57 -41
- package/src/components/LpAlert.vue +16 -3
- package/src/components/LpAppShell.vue +45 -12
- package/src/components/LpAutocomplete.vue +47 -10
- package/src/components/LpAvatar.vue +20 -6
- package/src/components/LpBreadcrumbs.vue +65 -41
- package/src/components/LpButton.vue +60 -14
- package/src/components/LpChart.vue +351 -28
- package/src/components/LpCheckbox.vue +7 -3
- package/src/components/LpCodeBlock.vue +50 -14
- package/src/components/LpColorPicker.vue +73 -10
- package/src/components/LpCommandPalette.vue +115 -20
- package/src/components/LpConfirmDialog.vue +68 -17
- package/src/components/LpConfirmHost.vue +59 -0
- package/src/components/LpContextMenu.vue +15 -116
- package/src/components/LpDatePicker.vue +104 -68
- package/src/components/LpDateRangePicker.vue +224 -0
- package/src/components/LpDrawer.vue +56 -19
- package/src/components/LpDropdownMenu.vue +1 -0
- package/src/components/LpDropzone.vue +21 -4
- package/src/components/LpFieldNotice.vue +65 -0
- package/src/components/LpFileTree.vue +33 -7
- package/src/components/LpFormField.vue +59 -7
- package/src/components/LpIcon.vue +22 -4
- package/src/components/LpImageEditor.vue +96 -57
- package/src/components/LpInput.vue +62 -11
- package/src/components/LpLightbox.vue +140 -29
- package/src/components/LpLink.vue +24 -13
- package/src/components/LpLogViewer.vue +311 -39
- package/src/components/LpMapPicker.vue +36 -13
- package/src/components/LpMediaGallery.vue +8 -2
- package/src/components/LpModal.vue +54 -28
- package/src/components/LpModalNav.vue +5 -2
- package/src/components/LpNotificationBell.vue +77 -23
- package/src/components/LpNumberField.vue +21 -6
- package/src/components/LpNumberFlow.vue +26 -10
- package/src/components/LpOtpInput.vue +43 -8
- package/src/components/LpPagination.vue +23 -7
- package/src/components/LpPasswordInput.vue +4 -1
- package/src/components/LpPhoneInput.vue +224 -39
- package/src/components/LpPie.vue +102 -20
- package/src/components/LpPopover.vue +4 -0
- package/src/components/LpProgress.vue +5 -3
- package/src/components/LpRadioGroup.vue +9 -2
- package/src/components/LpRangeCalendar.vue +365 -0
- package/src/components/LpRollingText.vue +3 -0
- package/src/components/LpScrollArea.vue +22 -2
- package/src/components/LpSegmented.vue +12 -2
- package/src/components/LpSelect.vue +0 -0
- package/src/components/LpShortcutsDialog.vue +83 -9
- package/src/components/LpSidebar.vue +14 -9
- package/src/components/LpSidebarNav.vue +17 -5
- package/src/components/LpSkeleton.vue +4 -1
- package/src/components/LpSlider.vue +7 -1
- package/src/components/LpSparkline.vue +11 -3
- package/src/components/LpStepper.vue +23 -10
- package/src/components/LpSwitch.vue +31 -8
- package/src/components/LpTable.vue +668 -90
- package/src/components/LpTableFilter.vue +175 -0
- package/src/components/LpTableOfContents.vue +50 -32
- package/src/components/LpTabs.vue +23 -6
- package/src/components/LpTagsInput.vue +364 -0
- package/src/components/LpTextarea.vue +44 -6
- package/src/components/LpThemeProvider.vue +41 -0
- package/src/components/LpThemeSwitcher.vue +76 -33
- package/src/components/LpTilt.vue +2 -2
- package/src/components/LpTimeField.vue +14 -3
- package/src/components/LpToaster.vue +115 -27
- package/src/components/LpTooltip.vue +29 -5
- package/src/components/LpTooltipProvider.vue +24 -0
- package/src/components/LpTopologyCanvas.vue +19 -2
- package/src/components/LpUptimeBar.vue +46 -8
- package/src/components/chart.ts +82 -8
- package/src/components/codeHighlight.ts +111 -15
- package/src/components/color.ts +30 -9
- package/src/components/commandSearch.ts +6 -0
- package/src/components/confirm.ts +58 -0
- package/src/components/countries.ts +12 -0
- package/src/components/dateRange.ts +134 -0
- package/src/components/exportData.ts +228 -0
- package/src/components/fileTree.ts +19 -7
- package/src/components/imageCrop.ts +107 -0
- package/src/components/link.ts +34 -0
- package/src/components/logSearch.ts +46 -0
- package/src/components/modalDepth.ts +48 -6
- package/src/components/otp.ts +16 -0
- package/src/components/phone.ts +140 -0
- package/src/components/sidebar.ts +7 -1
- package/src/components/tableFilter.ts +122 -0
- package/src/components/tableSort.ts +37 -0
- package/src/components/tags.ts +62 -0
- package/src/composables/useField.ts +83 -0
- package/src/composables/useFieldNotice.ts +59 -0
- package/src/composables/useForm.ts +314 -0
- package/src/composables/useFormDraft.ts +25 -20
- package/src/composables/useHotkeys.ts +355 -28
- package/src/composables/useInputFilter.ts +77 -14
- package/src/composables/useInputMask.ts +254 -0
- package/src/composables/useLpConfig.ts +87 -0
- package/src/composables/usePaintSelect.ts +243 -0
- package/src/composables/useRovingFocus.ts +11 -0
- package/src/composables/useShift.ts +13 -2
- package/src/composables/useTilt.ts +5 -6
- package/src/composables/useToast.ts +56 -4
- package/src/composables/useZoomPan.ts +6 -6
- package/src/iconSubset.d.mts +10 -0
- package/src/iconSubset.mjs +51 -0
- package/src/icons-all.ts +10 -0
- package/src/icons.ts +59 -8
- package/src/index.ts +73 -4
- package/src/kit-icons.ts +5 -0
- package/src/layout/tree.ts +30 -0
- package/src/layout/useLayout.ts +68 -18
- package/src/nuxt.ts +87 -17
- package/src/runtime/config.plugin.ts +14 -0
- package/src/runtime/theme.plugin.ts +43 -23
- package/src/theme/backdrop.ts +69 -0
- package/src/theme/presets.ts +6 -64
- package/src/theme/useTheme.ts +206 -100
- package/src/tokens/tokens.css +46 -0
- package/dist/chunks/LpBreadcrumbs-p4jHe_V-.js +0 -62
- package/dist/chunks/LpContextMenu-CwW1QXe_.js +0 -217
- package/dist/chunks/LpDatePicker-CwOToxGq.js +0 -164
- package/dist/chunks/LpFormField-CazBc2-a.js +0 -62
- package/dist/chunks/LpPhoneInput-BDSKVl_z.js +0 -209
- package/dist/chunks/LpTextarea-t7F6gv8E.js +0 -47
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
// Confirmation dialog built on LpModal. Resolves an action via confirm/cancel.
|
|
3
|
-
import { computed } from "vue"
|
|
3
|
+
import { computed, nextTick, ref, watch } from "vue"
|
|
4
|
+
import { useLabels } from "../composables/useLpConfig"
|
|
4
5
|
import LpButton from "./LpButton.vue"
|
|
5
6
|
import LpIcon from "./LpIcon.vue"
|
|
6
7
|
import LpModal from "./LpModal.vue"
|
|
7
8
|
|
|
9
|
+
export type ConfirmLabels = {
|
|
10
|
+
confirm: string
|
|
11
|
+
cancel: string
|
|
12
|
+
loading: string
|
|
13
|
+
failed: string
|
|
14
|
+
}
|
|
15
|
+
|
|
8
16
|
const props = withDefaults(
|
|
9
17
|
defineProps<{
|
|
10
18
|
open?: boolean
|
|
@@ -33,13 +41,22 @@ const props = withDefaults(
|
|
|
33
41
|
* The confirm action is in flight: the button disables and swaps to
|
|
34
42
|
* `loadingLabel`, and confirming no longer closes the dialog — the owner
|
|
35
43
|
* closes it once the work settles, so a failure can stay on screen.
|
|
44
|
+
* Setting it from the `confirm` handler is enough; the dialog waits a tick
|
|
45
|
+
* for it before deciding to close.
|
|
36
46
|
*/
|
|
37
47
|
loading?: boolean
|
|
38
48
|
loadingLabel?: string
|
|
49
|
+
/**
|
|
50
|
+
* The work behind the confirm button. When given, the dialog runs it,
|
|
51
|
+
* shows the loading state itself, closes once it resolves and stays open
|
|
52
|
+
* with the error's message when it rejects.
|
|
53
|
+
*/
|
|
54
|
+
action?: () => unknown
|
|
39
55
|
/** Frosted glass panel, passed to LpModal. Follows `provideGlass` when unset. */
|
|
40
56
|
glass?: boolean
|
|
57
|
+
labels?: Partial<ConfirmLabels>
|
|
41
58
|
}>(),
|
|
42
|
-
{
|
|
59
|
+
{ glass: undefined },
|
|
43
60
|
)
|
|
44
61
|
|
|
45
62
|
const emit = defineEmits<{
|
|
@@ -48,29 +65,61 @@ const emit = defineEmits<{
|
|
|
48
65
|
(e: "cancel"): void
|
|
49
66
|
}>()
|
|
50
67
|
|
|
68
|
+
const text = useLabels<ConfirmLabels>(
|
|
69
|
+
"confirm",
|
|
70
|
+
{ confirm: "Confirm", cancel: "Cancel", loading: "Working…", failed: "Something went wrong." },
|
|
71
|
+
() => props.labels,
|
|
72
|
+
)
|
|
73
|
+
|
|
51
74
|
/*
|
|
52
75
|
* Only a destructive prompt is marked by default. A routine confirmation
|
|
53
76
|
* ("Save these changes?") with a warning badge cries wolf, and the badge stops
|
|
54
77
|
* meaning anything on the dialog where it matters.
|
|
55
|
-
*
|
|
56
|
-
* "Not given" cannot be tested with `undefined` here. A prop whose type union
|
|
57
|
-
* includes Boolean is boolean-cast by Vue, so an absent `icon` arrives as
|
|
58
|
-
* `false` — the same value the caller passes to suppress the marker — and the
|
|
59
|
-
* default silently never applied. A string is an override, and everything else
|
|
60
|
-
* (absent, or an explicit false) falls through to the danger default.
|
|
61
78
|
*/
|
|
62
79
|
const marker = computed<string>(() => {
|
|
63
80
|
if (props.icon !== undefined) return props.icon
|
|
64
81
|
return props.danger ? "lucide:triangle-alert" : ""
|
|
65
82
|
})
|
|
66
83
|
|
|
67
|
-
|
|
84
|
+
const running = ref(false)
|
|
85
|
+
const error = ref("")
|
|
86
|
+
const busy = computed(() => props.loading || running.value)
|
|
87
|
+
|
|
88
|
+
watch(
|
|
89
|
+
() => props.open,
|
|
90
|
+
(open) => {
|
|
91
|
+
if (open) error.value = ""
|
|
92
|
+
},
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
async function confirm() {
|
|
96
|
+
if (busy.value) return
|
|
97
|
+
error.value = ""
|
|
68
98
|
emit("confirm")
|
|
69
|
-
|
|
70
|
-
|
|
99
|
+
if (props.action) {
|
|
100
|
+
running.value = true
|
|
101
|
+
try {
|
|
102
|
+
await props.action()
|
|
103
|
+
} catch (e) {
|
|
104
|
+
error.value = e instanceof Error && e.message ? e.message : text.value.failed
|
|
105
|
+
return
|
|
106
|
+
} finally {
|
|
107
|
+
running.value = false
|
|
108
|
+
}
|
|
109
|
+
emit("update:open", false)
|
|
110
|
+
return
|
|
111
|
+
}
|
|
112
|
+
// A handler that sets `loading` does so through the parent, whose new props
|
|
113
|
+
// reach this component only on the next render.
|
|
114
|
+
await nextTick()
|
|
71
115
|
if (!props.loading) emit("update:open", false)
|
|
72
116
|
}
|
|
73
|
-
|
|
117
|
+
|
|
118
|
+
// Every way out that is not the confirm button counts as a cancel: Escape, the
|
|
119
|
+
// scrim, the close button. None of them may close it while work is in flight.
|
|
120
|
+
function dismiss(open: boolean) {
|
|
121
|
+
if (open) return emit("update:open", true)
|
|
122
|
+
if (busy.value) return
|
|
74
123
|
emit("cancel")
|
|
75
124
|
emit("update:open", false)
|
|
76
125
|
}
|
|
@@ -82,7 +131,8 @@ function cancel() {
|
|
|
82
131
|
:open="open"
|
|
83
132
|
:title="title"
|
|
84
133
|
:description="description"
|
|
85
|
-
|
|
134
|
+
role="alertdialog"
|
|
135
|
+
@update:open="dismiss"
|
|
86
136
|
>
|
|
87
137
|
<template v-if="marker" #title>
|
|
88
138
|
<span class="inline-flex items-center gap-2.5">
|
|
@@ -100,16 +150,17 @@ function cancel() {
|
|
|
100
150
|
</span>
|
|
101
151
|
</template>
|
|
102
152
|
<slot />
|
|
153
|
+
<p v-if="error" role="alert" class="mt-3 text-sm text-danger">{{ error }}</p>
|
|
103
154
|
<template #footer>
|
|
104
|
-
<LpButton variant="ghost" :disabled="
|
|
105
|
-
{{ cancelLabel }}
|
|
155
|
+
<LpButton variant="ghost" :disabled="busy" @click="dismiss(false)">
|
|
156
|
+
{{ cancelLabel ?? text.cancel }}
|
|
106
157
|
</LpButton>
|
|
107
158
|
<LpButton
|
|
108
159
|
:variant="danger ? 'danger' : 'solid'"
|
|
109
|
-
:disabled="
|
|
160
|
+
:disabled="busy"
|
|
110
161
|
@click="confirm"
|
|
111
162
|
>
|
|
112
|
-
{{
|
|
163
|
+
{{ busy ? (loadingLabel ?? text.loading) : (confirmLabel ?? text.confirm) }}
|
|
113
164
|
</LpButton>
|
|
114
165
|
</template>
|
|
115
166
|
</LpModal>
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/*
|
|
3
|
+
* Renders the requests made through `confirm()` / `useConfirm()`. Mount one
|
|
4
|
+
* near the app root, next to LpToaster.
|
|
5
|
+
*/
|
|
6
|
+
import { computed, ref, watch } from "vue"
|
|
7
|
+
import { confirmQueue, settleConfirm } from "./confirm"
|
|
8
|
+
import LpConfirmDialog from "./LpConfirmDialog.vue"
|
|
9
|
+
|
|
10
|
+
withDefaults(
|
|
11
|
+
defineProps<{
|
|
12
|
+
/** Frosted glass panel. Follows `provideGlass` when unset. */
|
|
13
|
+
glass?: boolean
|
|
14
|
+
}>(),
|
|
15
|
+
{ glass: undefined },
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
const current = computed(() => confirmQueue[0])
|
|
19
|
+
const open = ref(false)
|
|
20
|
+
let confirmed = false
|
|
21
|
+
const answer = (value: boolean) => (confirmed = value)
|
|
22
|
+
|
|
23
|
+
watch(
|
|
24
|
+
() => current.value?.id,
|
|
25
|
+
(id) => {
|
|
26
|
+
confirmed = false
|
|
27
|
+
open.value = id !== undefined
|
|
28
|
+
},
|
|
29
|
+
{ immediate: true },
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
// The dialog closes itself after a successful action, or straight away for a
|
|
33
|
+
// plain confirmation; a failed action keeps it open and never gets here.
|
|
34
|
+
function onOpen(value: boolean) {
|
|
35
|
+
open.value = value
|
|
36
|
+
const request = current.value
|
|
37
|
+
if (!value && request) settleConfirm(request.id, confirmed)
|
|
38
|
+
}
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
<template>
|
|
42
|
+
<LpConfirmDialog
|
|
43
|
+
v-if="current"
|
|
44
|
+
:key="current.id"
|
|
45
|
+
:open="open"
|
|
46
|
+
:glass="glass"
|
|
47
|
+
:title="current.title"
|
|
48
|
+
:description="current.description"
|
|
49
|
+
:danger="current.danger"
|
|
50
|
+
:icon="current.icon"
|
|
51
|
+
:confirm-label="current.confirmLabel"
|
|
52
|
+
:cancel-label="current.cancelLabel"
|
|
53
|
+
:loading-label="current.loadingLabel"
|
|
54
|
+
:action="current.action"
|
|
55
|
+
@confirm="answer(true)"
|
|
56
|
+
@cancel="answer(false)"
|
|
57
|
+
@update:open="onOpen"
|
|
58
|
+
/>
|
|
59
|
+
</template>
|
|
@@ -6,20 +6,10 @@
|
|
|
6
6
|
* long-press on touch) opens the menu at the pointer. Shares the floating-panel
|
|
7
7
|
* surface + option-row look with the rest of the kit via dropdown.ts.
|
|
8
8
|
*/
|
|
9
|
-
import {
|
|
10
|
-
ContextMenuContent,
|
|
11
|
-
ContextMenuItem,
|
|
12
|
-
ContextMenuPortal,
|
|
13
|
-
ContextMenuRoot,
|
|
14
|
-
ContextMenuSeparator,
|
|
15
|
-
ContextMenuSub,
|
|
16
|
-
ContextMenuSubContent,
|
|
17
|
-
ContextMenuSubTrigger,
|
|
18
|
-
ContextMenuTrigger,
|
|
19
|
-
} from "reka-ui"
|
|
9
|
+
import { ContextMenuContent, ContextMenuPortal, ContextMenuRoot, ContextMenuTrigger } from "reka-ui"
|
|
20
10
|
import { computed } from "vue"
|
|
11
|
+
import ContextMenuItems from "./ContextMenuItems.vue"
|
|
21
12
|
import { POPOVER_PANEL } from "./dropdown"
|
|
22
|
-
import LpIcon from "./LpIcon.vue"
|
|
23
13
|
|
|
24
14
|
export interface ContextMenuItemDef {
|
|
25
15
|
label: string
|
|
@@ -30,7 +20,7 @@ export interface ContextMenuItemDef {
|
|
|
30
20
|
disabled?: boolean
|
|
31
21
|
separatorBefore?: boolean
|
|
32
22
|
onSelect?: () => void
|
|
33
|
-
/** Nested submenu. When present, onSelect is ignored. */
|
|
23
|
+
/** Nested submenu, to any depth. When present, onSelect is ignored. */
|
|
34
24
|
children?: ContextMenuItemDef[]
|
|
35
25
|
/**
|
|
36
26
|
* Renders as a tick-box rather than a plain item, and the menu stays open on
|
|
@@ -52,17 +42,13 @@ const props = defineProps<{
|
|
|
52
42
|
always?: boolean
|
|
53
43
|
}>()
|
|
54
44
|
|
|
55
|
-
// With no items
|
|
56
|
-
//
|
|
57
|
-
//
|
|
58
|
-
//
|
|
45
|
+
// With no items the trigger is disabled, so the element keeps the browser's
|
|
46
|
+
// native context menu. Lets callers wrap unconditionally and pass [] to opt out
|
|
47
|
+
// per element. `always` overrides this so a late-populated menu is ready on the
|
|
48
|
+
// very first click.
|
|
59
49
|
const enabled = computed(() => props.always || props.items.length > 0)
|
|
60
50
|
|
|
61
51
|
const PANEL = `${POPOVER_PANEL} z-(--z-popover) min-w-48 p-1 outline-none`
|
|
62
|
-
const ITEM =
|
|
63
|
-
"group/item flex cursor-pointer select-none items-center gap-2 rounded-md px-2.5 py-1.5 text-sm outline-none transition-[background-color,color] duration-[var(--duration-fast)] data-[disabled]:pointer-events-none data-[disabled]:opacity-45 data-[highlighted]:bg-brand-soft"
|
|
64
|
-
const ICON =
|
|
65
|
-
"transition-transform duration-[var(--duration-fast)] ease-[var(--ease-emphasized)] group-data-[highlighted]/item:translate-x-0.5"
|
|
66
52
|
|
|
67
53
|
// A menu opened over a text field takes focus, and on close reka hands it to the
|
|
68
54
|
// trigger, so the caret and the selection the user right-clicked are gone — the
|
|
@@ -92,104 +78,17 @@ function returnFocus(event: Event) {
|
|
|
92
78
|
</script>
|
|
93
79
|
|
|
94
80
|
<template>
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
81
|
+
<!-- One tree whether or not there are items: swapping between a bare slot and
|
|
82
|
+
the reka trigger remounted the wrapped content whenever items arrived
|
|
83
|
+
late, losing its state and focus. A disabled trigger leaves the browser's
|
|
84
|
+
own menu in place. -->
|
|
85
|
+
<ContextMenuRoot>
|
|
86
|
+
<ContextMenuTrigger as-child :disabled="!enabled" @contextmenu.capture="rememberField">
|
|
99
87
|
<slot />
|
|
100
88
|
</ContextMenuTrigger>
|
|
101
89
|
<ContextMenuPortal v-if="items.length">
|
|
102
|
-
<ContextMenuContent :class="PANEL" @close-auto-focus="returnFocus">
|
|
103
|
-
<
|
|
104
|
-
<ContextMenuSeparator v-if="item.separatorBefore" class="my-1 h-px bg-line" />
|
|
105
|
-
|
|
106
|
-
<!-- Submenu branch -->
|
|
107
|
-
<ContextMenuSub v-if="item.children?.length">
|
|
108
|
-
<ContextMenuSubTrigger
|
|
109
|
-
:class="[ITEM, 'justify-between text-ink data-[highlighted]:text-brand data-[state=open]:bg-brand-soft data-[state=open]:text-brand']"
|
|
110
|
-
>
|
|
111
|
-
<span class="flex items-center gap-2">
|
|
112
|
-
<LpIcon v-if="item.icon" :name="item.icon" :size="15" :class="ICON" />
|
|
113
|
-
{{ item.label }}
|
|
114
|
-
</span>
|
|
115
|
-
<LpIcon name="lucide:chevron-right" :size="14" class="text-muted" />
|
|
116
|
-
</ContextMenuSubTrigger>
|
|
117
|
-
<ContextMenuPortal>
|
|
118
|
-
<ContextMenuSubContent :class="PANEL" :side-offset="2" :align-offset="-4">
|
|
119
|
-
<template v-for="(sub, j) in item.children" :key="j">
|
|
120
|
-
<ContextMenuSeparator v-if="sub.separatorBefore" class="my-1 h-px bg-line" />
|
|
121
|
-
<!-- The tick-box case, as in the top-level menu: this is
|
|
122
|
-
where most of them live, since a submenu is what a list
|
|
123
|
-
of choices opens into. -->
|
|
124
|
-
<ContextMenuItem
|
|
125
|
-
v-if="sub.checked !== undefined"
|
|
126
|
-
:class="[ITEM, 'justify-between text-ink data-[highlighted]:text-brand']"
|
|
127
|
-
:disabled="sub.disabled"
|
|
128
|
-
@select.prevent="sub.onSelect?.()"
|
|
129
|
-
>
|
|
130
|
-
<span class="flex items-center gap-2">
|
|
131
|
-
<LpIcon
|
|
132
|
-
:name="sub.checked ? 'lucide:check' : 'lucide:minus'"
|
|
133
|
-
:size="15"
|
|
134
|
-
:class="[ICON, sub.checked ? '' : 'opacity-25']"
|
|
135
|
-
/>
|
|
136
|
-
{{ sub.label }}
|
|
137
|
-
</span>
|
|
138
|
-
<kbd v-if="sub.shortcut" class="text-xs text-muted">{{ sub.shortcut }}</kbd>
|
|
139
|
-
</ContextMenuItem>
|
|
140
|
-
|
|
141
|
-
<ContextMenuItem
|
|
142
|
-
v-else
|
|
143
|
-
:class="[ITEM, 'justify-between', sub.danger ? 'text-danger data-[highlighted]:bg-danger-soft data-[highlighted]:text-danger' : 'text-ink data-[highlighted]:text-brand']"
|
|
144
|
-
:disabled="sub.disabled"
|
|
145
|
-
@select="sub.onSelect?.()"
|
|
146
|
-
>
|
|
147
|
-
<span class="flex items-center gap-2">
|
|
148
|
-
<LpIcon v-if="sub.icon" :name="sub.icon" :size="15" :class="ICON" />
|
|
149
|
-
{{ sub.label }}
|
|
150
|
-
</span>
|
|
151
|
-
<kbd v-if="sub.shortcut" class="text-xs text-muted">{{ sub.shortcut }}</kbd>
|
|
152
|
-
</ContextMenuItem>
|
|
153
|
-
</template>
|
|
154
|
-
</ContextMenuSubContent>
|
|
155
|
-
</ContextMenuPortal>
|
|
156
|
-
</ContextMenuSub>
|
|
157
|
-
|
|
158
|
-
<!-- Tick-box item. `@select.prevent` keeps the menu open: these come
|
|
159
|
-
in lists where several are set in one visit, and closing after
|
|
160
|
-
each tick would mean reopening for the next. The tick occupies a
|
|
161
|
-
fixed slot so unticked rows stay aligned with ticked ones. -->
|
|
162
|
-
<ContextMenuItem
|
|
163
|
-
v-else-if="item.checked !== undefined"
|
|
164
|
-
:class="[ITEM, 'justify-between text-ink data-[highlighted]:text-brand']"
|
|
165
|
-
:disabled="item.disabled"
|
|
166
|
-
@select.prevent="item.onSelect?.()"
|
|
167
|
-
>
|
|
168
|
-
<span class="flex items-center gap-2">
|
|
169
|
-
<LpIcon
|
|
170
|
-
:name="item.checked ? 'lucide:check' : 'lucide:minus'"
|
|
171
|
-
:size="15"
|
|
172
|
-
:class="[ICON, item.checked ? '' : 'opacity-25']"
|
|
173
|
-
/>
|
|
174
|
-
{{ item.label }}
|
|
175
|
-
</span>
|
|
176
|
-
<kbd v-if="item.shortcut" class="text-xs text-muted">{{ item.shortcut }}</kbd>
|
|
177
|
-
</ContextMenuItem>
|
|
178
|
-
|
|
179
|
-
<!-- Leaf item -->
|
|
180
|
-
<ContextMenuItem
|
|
181
|
-
v-else
|
|
182
|
-
:class="[ITEM, 'justify-between', item.danger ? 'text-danger data-[highlighted]:bg-danger-soft data-[highlighted]:text-danger' : 'text-ink data-[highlighted]:text-brand']"
|
|
183
|
-
:disabled="item.disabled"
|
|
184
|
-
@select="item.onSelect?.()"
|
|
185
|
-
>
|
|
186
|
-
<span class="flex items-center gap-2">
|
|
187
|
-
<LpIcon v-if="item.icon" :name="item.icon" :size="15" :class="ICON" />
|
|
188
|
-
{{ item.label }}
|
|
189
|
-
</span>
|
|
190
|
-
<kbd v-if="item.shortcut" class="text-xs text-muted">{{ item.shortcut }}</kbd>
|
|
191
|
-
</ContextMenuItem>
|
|
192
|
-
</template>
|
|
90
|
+
<ContextMenuContent :collision-padding="8" :class="PANEL" @close-auto-focus="returnFocus">
|
|
91
|
+
<ContextMenuItems :items="items" :panel="PANEL" />
|
|
193
92
|
</ContextMenuContent>
|
|
194
93
|
</ContextMenuPortal>
|
|
195
94
|
</ContextMenuRoot>
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
export default { inheritAttrs: false }
|
|
3
|
+
</script>
|
|
4
|
+
|
|
1
5
|
<script setup lang="ts">
|
|
2
6
|
/*
|
|
3
7
|
* Date field + calendar popover. The model is an ISO date string ("YYYY-MM-DD",
|
|
@@ -14,10 +18,14 @@
|
|
|
14
18
|
* the common case.
|
|
15
19
|
*/
|
|
16
20
|
import { PopoverContent, PopoverPortal, PopoverRoot, PopoverTrigger } from "reka-ui"
|
|
17
|
-
import { computed, ref } from "vue"
|
|
21
|
+
import { computed, ref, useAttrs } from "vue"
|
|
22
|
+
import { useFieldControl } from "../composables/useField"
|
|
23
|
+
import { useLabels } from "../composables/useLpConfig"
|
|
24
|
+
import { mergeClass } from "../composables/useMergedClass"
|
|
18
25
|
import { POPOVER_PANEL } from "./dropdown"
|
|
19
26
|
import LpCalendar from "./LpCalendar.vue"
|
|
20
27
|
import LpIcon from "./LpIcon.vue"
|
|
28
|
+
import LpRollingText from "./LpRollingText.vue"
|
|
21
29
|
import LpTimeField from "./LpTimeField.vue"
|
|
22
30
|
|
|
23
31
|
const props = withDefaults(
|
|
@@ -80,7 +88,11 @@ const shellSize = {
|
|
|
80
88
|
lg: "h-(--size-control-lg) text-sm",
|
|
81
89
|
}
|
|
82
90
|
|
|
83
|
-
function onPick(
|
|
91
|
+
function onPick(picked: string | undefined) {
|
|
92
|
+
// Clicking the selected day again is the calendar's "deselect". Here it is
|
|
93
|
+
// someone confirming the date they already have, so it keeps the value and
|
|
94
|
+
// closes like any other pick; clearing has its own button.
|
|
95
|
+
const v = picked ?? (day.value || undefined)
|
|
84
96
|
if (!props.time) {
|
|
85
97
|
emit("update:modelValue", v)
|
|
86
98
|
open.value = false
|
|
@@ -101,75 +113,99 @@ function onTime(at: string) {
|
|
|
101
113
|
function clear() {
|
|
102
114
|
emit("update:modelValue", undefined)
|
|
103
115
|
}
|
|
116
|
+
|
|
117
|
+
const attrs = useAttrs()
|
|
118
|
+
const field = useFieldControl(() => ({
|
|
119
|
+
wrapped: false,
|
|
120
|
+
id: typeof attrs.id === "string" ? attrs.id : undefined,
|
|
121
|
+
invalid: props.invalid,
|
|
122
|
+
disabled: props.disabled,
|
|
123
|
+
}))
|
|
124
|
+
const labels = useLabels("datePicker", { clear: "Clear" })
|
|
125
|
+
const showClear = computed(() => props.clearable && !!props.modelValue && !field.value.disabled)
|
|
104
126
|
</script>
|
|
105
127
|
|
|
106
128
|
<template>
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
129
|
+
<!-- The clear control sits beside the trigger, not inside it: a button
|
|
130
|
+
nested in a button is invalid, and the nested one was unreachable by
|
|
131
|
+
keyboard. -->
|
|
132
|
+
<div :class="mergeClass('relative w-full', attrs.class as string)" :style="attrs.style as never">
|
|
133
|
+
<PopoverRoot v-model:open="open">
|
|
134
|
+
<PopoverTrigger as-child>
|
|
135
|
+
<button
|
|
136
|
+
v-bind="{ ...attrs, class: undefined, style: undefined }"
|
|
137
|
+
:id="field.id"
|
|
138
|
+
type="button"
|
|
139
|
+
:disabled="field.disabled"
|
|
140
|
+
:aria-invalid="field.invalid || undefined"
|
|
141
|
+
:aria-describedby="field.describedBy"
|
|
142
|
+
class="group flex w-full items-center gap-2 rounded-control border bg-surface-soft px-3 text-left text-ink outline-none transition-colors duration-[var(--duration-fast)] focus-visible:ring-2 focus-visible:ring-ring data-[state=open]:border-brand disabled:cursor-not-allowed disabled:opacity-55"
|
|
143
|
+
:class="[
|
|
144
|
+
shellSize[size],
|
|
145
|
+
field.invalid ? 'border-danger focus-visible:ring-danger-soft' : 'border-line focus-visible:border-brand',
|
|
146
|
+
]"
|
|
147
|
+
>
|
|
148
|
+
<LpIcon name="lucide:calendar" :size="16" class="shrink-0 text-muted" />
|
|
149
|
+
<LpRollingText
|
|
150
|
+
:value="display || placeholder || ''"
|
|
151
|
+
align="start"
|
|
152
|
+
class="min-w-0 flex-1"
|
|
153
|
+
:class="display ? '' : 'text-muted'"
|
|
154
|
+
/>
|
|
155
|
+
<span v-if="showClear" class="w-[15px] shrink-0" aria-hidden="true" />
|
|
156
|
+
<LpIcon
|
|
157
|
+
name="lucide:chevron-down"
|
|
158
|
+
:size="15"
|
|
159
|
+
class="shrink-0 text-muted transition-transform duration-[var(--duration-fast)] ease-[var(--ease-emphasized)] group-data-[state=open]:rotate-180"
|
|
160
|
+
/>
|
|
161
|
+
</button>
|
|
162
|
+
</PopoverTrigger>
|
|
163
|
+
<PopoverPortal>
|
|
164
|
+
<PopoverContent
|
|
165
|
+
:collision-padding="8"
|
|
166
|
+
:side-offset="6"
|
|
167
|
+
align="start"
|
|
168
|
+
:class="[POPOVER_PANEL, 'z-(--z-popover) rounded-card p-0 outline-none']"
|
|
130
169
|
>
|
|
131
|
-
<
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
</button>
|
|
139
|
-
</PopoverTrigger>
|
|
140
|
-
<PopoverPortal>
|
|
141
|
-
<PopoverContent
|
|
142
|
-
:side-offset="6"
|
|
143
|
-
align="start"
|
|
144
|
-
:class="[POPOVER_PANEL, 'z-(--z-popover) rounded-card p-0 outline-none']"
|
|
145
|
-
>
|
|
146
|
-
<LpCalendar
|
|
147
|
-
:model-value="day"
|
|
148
|
-
:min="min"
|
|
149
|
-
:max="max"
|
|
150
|
-
:is-disabled="isDisabled"
|
|
151
|
-
class="border-0 bg-transparent"
|
|
152
|
-
@update:model-value="onPick"
|
|
153
|
-
/>
|
|
154
|
-
<div v-if="time" class="flex items-center gap-2 border-t border-line px-3 py-2">
|
|
155
|
-
<LpIcon name="lucide:clock" :size="15" class="shrink-0 text-muted" />
|
|
156
|
-
<LpTimeField
|
|
157
|
-
:model-value="minute || undefined"
|
|
158
|
-
:disabled="!day"
|
|
159
|
-
:icon="false"
|
|
160
|
-
size="sm"
|
|
161
|
-
class="flex-1"
|
|
162
|
-
@update:model-value="(at) => onTime(at || '')"
|
|
170
|
+
<LpCalendar
|
|
171
|
+
:model-value="day"
|
|
172
|
+
:min="min"
|
|
173
|
+
:max="max"
|
|
174
|
+
:is-disabled="isDisabled"
|
|
175
|
+
class="border-0 bg-transparent"
|
|
176
|
+
@update:model-value="onPick"
|
|
163
177
|
/>
|
|
164
|
-
<
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
178
|
+
<div v-if="time" class="flex items-center gap-2 border-t border-line px-3 py-2">
|
|
179
|
+
<LpIcon name="lucide:clock" :size="15" class="shrink-0 text-muted" />
|
|
180
|
+
<LpTimeField
|
|
181
|
+
:model-value="minute || undefined"
|
|
182
|
+
:disabled="!day"
|
|
183
|
+
:icon="false"
|
|
184
|
+
size="sm"
|
|
185
|
+
class="flex-1"
|
|
186
|
+
@update:model-value="(at) => onTime(at || '')"
|
|
187
|
+
/>
|
|
188
|
+
<button
|
|
189
|
+
type="button"
|
|
190
|
+
class="shrink-0 rounded-control px-2 py-1 text-xs text-muted transition-colors hover:text-ink"
|
|
191
|
+
@click="open = false"
|
|
192
|
+
>
|
|
193
|
+
{{ doneLabel }}
|
|
194
|
+
</button>
|
|
195
|
+
</div>
|
|
196
|
+
</PopoverContent>
|
|
197
|
+
</PopoverPortal>
|
|
198
|
+
</PopoverRoot>
|
|
199
|
+
<!-- Positioned over the spacer the trigger leaves for it, just before the
|
|
200
|
+
chevron (gap-2 + 15px chevron + px-3 from the right edge). -->
|
|
201
|
+
<button
|
|
202
|
+
v-if="showClear"
|
|
203
|
+
type="button"
|
|
204
|
+
:aria-label="labels.clear"
|
|
205
|
+
class="absolute top-1/2 right-[calc(0.75rem+15px+0.5rem)] flex -translate-y-1/2 items-center rounded-sm text-muted outline-none transition-colors hover:text-ink focus-visible:ring-2 focus-visible:ring-ring"
|
|
206
|
+
@click="clear"
|
|
207
|
+
>
|
|
208
|
+
<LpIcon name="lucide:x" :size="15" />
|
|
209
|
+
</button>
|
|
210
|
+
</div>
|
|
175
211
|
</template>
|