@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
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
* the static <nav> it always has — existing call sites are unaffected.
|
|
15
15
|
*/
|
|
16
16
|
import { computed, ref, useId } from "vue"
|
|
17
|
+
import { useLabels } from "../composables/useLpConfig"
|
|
17
18
|
import LpDrawer from "./LpDrawer.vue"
|
|
18
19
|
import LpInput from "./LpInput.vue"
|
|
19
20
|
import LpSidebarNav from "./LpSidebarNav.vue"
|
|
@@ -45,8 +46,10 @@ const props = withDefaults(
|
|
|
45
46
|
* query is active — a hidden match is the same as no match.
|
|
46
47
|
*/
|
|
47
48
|
searchable?: boolean
|
|
48
|
-
/** Placeholder for that field. */
|
|
49
|
+
/** Placeholder for that field (defaults to the `search` label). */
|
|
49
50
|
searchPlaceholder?: string
|
|
51
|
+
/** Text overrides: `nav` names the landmark, `search` the filter field. */
|
|
52
|
+
labels?: Partial<{ nav: string; search: string }>
|
|
50
53
|
/** The query, when the app wants to own it (v-model:search). */
|
|
51
54
|
search?: string
|
|
52
55
|
/** Show a skeleton placeholder instead of the items. */
|
|
@@ -113,7 +116,6 @@ const props = withDefaults(
|
|
|
113
116
|
autoCollapseAfter?: number
|
|
114
117
|
}>(),
|
|
115
118
|
{
|
|
116
|
-
searchPlaceholder: "Search",
|
|
117
119
|
skeletonRows: 6,
|
|
118
120
|
skeletonHeader: true,
|
|
119
121
|
responsive: false,
|
|
@@ -132,6 +134,9 @@ const emit = defineEmits<{
|
|
|
132
134
|
(e: "update:search", value: string): void
|
|
133
135
|
}>()
|
|
134
136
|
|
|
137
|
+
const text = useLabels("sidebar", { nav: "Sidebar", search: "Search" }, () => props.labels)
|
|
138
|
+
const placeholder = computed(() => props.searchPlaceholder ?? text.value.search)
|
|
139
|
+
|
|
135
140
|
// Normalise both inputs to a single section list.
|
|
136
141
|
const allGroups = computed<SidebarSection[]>(() =>
|
|
137
142
|
props.sections ?? (props.items ? [{ items: props.items }] : []),
|
|
@@ -271,7 +276,7 @@ defineOptions({ inheritAttrs: false })
|
|
|
271
276
|
class="h-full flex-col gap-1 p-3"
|
|
272
277
|
:class="[railClass, chromeClass, width ? '' : 'w-60']"
|
|
273
278
|
:style="width ? { width } : undefined"
|
|
274
|
-
aria-label="
|
|
279
|
+
:aria-label="text.nav"
|
|
275
280
|
v-bind="$attrs"
|
|
276
281
|
>
|
|
277
282
|
<!-- Rail: edge-to-edge (negative margins cancel the p-3) and h-16 to match
|
|
@@ -298,8 +303,8 @@ defineOptions({ inheritAttrs: false })
|
|
|
298
303
|
size="sm"
|
|
299
304
|
icon="lucide:search"
|
|
300
305
|
class="mb-2 shrink-0"
|
|
301
|
-
:placeholder="
|
|
302
|
-
:aria-label="
|
|
306
|
+
:placeholder="placeholder"
|
|
307
|
+
:aria-label="placeholder"
|
|
303
308
|
/>
|
|
304
309
|
<LpSidebarNav
|
|
305
310
|
:groups="groups"
|
|
@@ -339,7 +344,7 @@ defineOptions({ inheritAttrs: false })
|
|
|
339
344
|
:edge-breakpoint="mobileBreakpoint"
|
|
340
345
|
@update:open="(v) => emit('update:open', v)"
|
|
341
346
|
>
|
|
342
|
-
<
|
|
347
|
+
<nav class="flex h-full flex-col gap-1" :aria-label="text.nav">
|
|
343
348
|
<div
|
|
344
349
|
v-if="$slots.header"
|
|
345
350
|
class="shrink-0"
|
|
@@ -357,8 +362,8 @@ defineOptions({ inheritAttrs: false })
|
|
|
357
362
|
size="sm"
|
|
358
363
|
icon="lucide:search"
|
|
359
364
|
class="mb-2 shrink-0"
|
|
360
|
-
:placeholder="
|
|
361
|
-
:aria-label="
|
|
365
|
+
:placeholder="placeholder"
|
|
366
|
+
:aria-label="placeholder"
|
|
362
367
|
/>
|
|
363
368
|
<LpSidebarNav
|
|
364
369
|
:groups="groups"
|
|
@@ -383,6 +388,6 @@ defineOptions({ inheritAttrs: false })
|
|
|
383
388
|
<div v-if="$slots.footer" class="mt-2 shrink-0 border-t border-line pt-3">
|
|
384
389
|
<slot name="footer" />
|
|
385
390
|
</div>
|
|
386
|
-
</
|
|
391
|
+
</nav>
|
|
387
392
|
</LpDrawer>
|
|
388
393
|
</template>
|
|
@@ -21,6 +21,8 @@ import LpContextMenu from "./LpContextMenu.vue"
|
|
|
21
21
|
import LpIcon from "./LpIcon.vue"
|
|
22
22
|
import LpScrollArea from "./LpScrollArea.vue"
|
|
23
23
|
import type { SidebarItem, SidebarSection } from "./sidebar"
|
|
24
|
+
import { resolveLink, type ResolvedLink } from "./link"
|
|
25
|
+
import { useLinkComponent } from "../composables/useLpConfig"
|
|
24
26
|
import { useMergedAttrs } from "../composables/useMergedClass"
|
|
25
27
|
|
|
26
28
|
const props = withDefaults(
|
|
@@ -75,6 +77,18 @@ function isOpen(section: SidebarSection): boolean {
|
|
|
75
77
|
|
|
76
78
|
const pillTransition = usePillTransition()
|
|
77
79
|
|
|
80
|
+
const linkComponent = useLinkComponent()
|
|
81
|
+
|
|
82
|
+
/*
|
|
83
|
+
* A disabled item is always a disabled button: an anchor cannot be disabled,
|
|
84
|
+
* and the old enabled-button fallback for a disabled link stayed focusable.
|
|
85
|
+
*/
|
|
86
|
+
function rowOf(item: SidebarItem): ResolvedLink {
|
|
87
|
+
const link = item.disabled ? null : resolveLink(linkComponent.value, { to: item.to, href: item.href })
|
|
88
|
+
if (link) return link
|
|
89
|
+
return { is: "button", props: { type: "button", disabled: item.disabled || undefined } }
|
|
90
|
+
}
|
|
91
|
+
|
|
78
92
|
// The nav fills the remaining height with a fixed gap between groups; a short sidebar needs both under the consumer's control.
|
|
79
93
|
const { class: rootClass, attrs: rest } = useMergedAttrs(
|
|
80
94
|
"flex min-h-0 flex-1 flex-col gap-4",
|
|
@@ -118,7 +132,7 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(
|
|
|
118
132
|
because a thing that reacts to a click must look like one. -->
|
|
119
133
|
<CollapsibleTrigger
|
|
120
134
|
v-if="section.title && section.collapsible"
|
|
121
|
-
class="group/section mt-2 flex cursor-pointer items-center gap-2 rounded-control px-2 py-1 text-[11px] font-semibold uppercase tracking-[0.08em] text-muted outline-none transition-colors duration-[var(--duration-fast)] hover:bg-
|
|
135
|
+
class="group/section mt-2 flex cursor-pointer items-center gap-2 rounded-control px-2 py-1 text-[11px] font-semibold uppercase tracking-[0.08em] text-muted outline-none transition-colors duration-[var(--duration-fast)] hover:bg-ink/[0.04] hover:text-ink focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring"
|
|
122
136
|
>
|
|
123
137
|
<LpIcon
|
|
124
138
|
v-if="section.icon"
|
|
@@ -165,10 +179,8 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(
|
|
|
165
179
|
:items="item.menu ?? []"
|
|
166
180
|
>
|
|
167
181
|
<component
|
|
168
|
-
:is="item.
|
|
169
|
-
|
|
170
|
-
:type="item.href ? undefined : 'button'"
|
|
171
|
-
:disabled="item.href ? undefined : item.disabled"
|
|
182
|
+
:is="rowOf(item).is"
|
|
183
|
+
v-bind="rowOf(item).props"
|
|
172
184
|
:aria-current="itemActive(item) ? 'page' : undefined"
|
|
173
185
|
:aria-disabled="item.disabled || undefined"
|
|
174
186
|
class="group/item relative flex items-center gap-3 rounded-control px-3 py-2 text-sm font-medium outline-none transition-colors duration-[var(--duration-fast)] focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring"
|
|
@@ -88,7 +88,10 @@ const isBlock = computed(() => !slots.default)
|
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
@media (prefers-reduced-motion: reduce) {
|
|
91
|
-
|
|
91
|
+
/* Repeats the descendant form: it outranks a bare class, and grouped items
|
|
92
|
+
kept pulsing under reduced motion. */
|
|
93
|
+
.lp-skeleton-item,
|
|
94
|
+
.lp-skeleton .lp-skeleton-item {
|
|
92
95
|
animation: none;
|
|
93
96
|
opacity: 0.75;
|
|
94
97
|
}
|
|
@@ -9,6 +9,7 @@ export default { inheritAttrs: false }
|
|
|
9
9
|
// Single-value slider (reka Slider). reka models value as an array; we expose
|
|
10
10
|
// a plain number for the common single-thumb case. Themed via tokens.
|
|
11
11
|
import { SliderRange, SliderRoot, SliderThumb, SliderTrack } from "reka-ui"
|
|
12
|
+
import { useFieldControl } from "../composables/useField"
|
|
12
13
|
import { useMergedAttrs } from "../composables/useMergedClass"
|
|
13
14
|
|
|
14
15
|
const props = withDefaults(
|
|
@@ -38,6 +39,8 @@ function onCommit(v: number[] | undefined) {
|
|
|
38
39
|
if (v && v.length) emit("change", v[0])
|
|
39
40
|
}
|
|
40
41
|
|
|
42
|
+
const field = useFieldControl(() => ({ wrapped: false, disabled: props.disabled }))
|
|
43
|
+
|
|
41
44
|
// A slider is full-width by default; putting one in a toolbar means constraining it, and a fixed h-5 has to yield to a denser row.
|
|
42
45
|
const { class: rootClass, attrs: rest } = useMergedAttrs(
|
|
43
46
|
"relative flex h-5 w-full touch-none select-none items-center data-[disabled]:opacity-55",
|
|
@@ -50,7 +53,7 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(
|
|
|
50
53
|
:min="min"
|
|
51
54
|
:max="max"
|
|
52
55
|
:step="step"
|
|
53
|
-
:disabled="disabled"
|
|
56
|
+
:disabled="field.disabled"
|
|
54
57
|
:class="rootClass"
|
|
55
58
|
v-bind="rest"
|
|
56
59
|
@update:model-value="onUpdate"
|
|
@@ -60,7 +63,10 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(
|
|
|
60
63
|
<SliderRange class="absolute h-full rounded-pill bg-brand" />
|
|
61
64
|
</SliderTrack>
|
|
62
65
|
<SliderThumb
|
|
66
|
+
:id="field.id"
|
|
63
67
|
:aria-label="ariaLabel"
|
|
68
|
+
:aria-labelledby="ariaLabel ? undefined : field.labelId"
|
|
69
|
+
:aria-describedby="field.describedBy"
|
|
64
70
|
class="block size-4 rounded-pill border-2 border-brand bg-surface shadow outline-none transition-transform duration-[var(--duration-fast)] ease-[var(--ease-emphasized)] hover:scale-110 active:scale-95 focus-visible:ring-2 focus-visible:ring-ring motion-reduce:hover:scale-100 motion-reduce:active:scale-100"
|
|
65
71
|
/>
|
|
66
72
|
</SliderRoot>
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
*/
|
|
17
17
|
import { computed } from "vue"
|
|
18
18
|
import { useReveal } from "../composables/useReveal"
|
|
19
|
+
import { useLabels } from "../composables/useLpConfig"
|
|
19
20
|
import { areaPath, extent, linePath, normalise, type Box } from "./chart"
|
|
20
21
|
|
|
21
22
|
const props = withDefaults(
|
|
@@ -56,6 +57,7 @@ const props = withDefaults(
|
|
|
56
57
|
* watched being drawn — not a figure mostly spent easing out.
|
|
57
58
|
*/
|
|
58
59
|
duration?: number
|
|
60
|
+
labels?: Partial<Record<"empty" | "up" | "down" | "flat" | "latest", string>>
|
|
59
61
|
}>(),
|
|
60
62
|
{ width: 84, height: 24, tone: "brand", smooth: 0.9, animate: true, duration: 900 },
|
|
61
63
|
)
|
|
@@ -131,14 +133,20 @@ const lastPoint = computed(() => {
|
|
|
131
133
|
const hasData = computed(() => series.value[0].values.some((v) => v != null))
|
|
132
134
|
|
|
133
135
|
/* A bare <svg> is invisible to a screen reader; say the shape out loud. */
|
|
136
|
+
const text = useLabels(
|
|
137
|
+
"sparkline",
|
|
138
|
+
{ empty: "No data", up: "trending up", down: "trending down", flat: "flat", latest: "latest" },
|
|
139
|
+
() => props.labels,
|
|
140
|
+
)
|
|
141
|
+
|
|
134
142
|
const label = computed(() => {
|
|
135
143
|
if (props.ariaLabel) return props.ariaLabel
|
|
136
144
|
const values = series.value[0].values.filter((v): v is number => v != null)
|
|
137
|
-
if (!values.length) return
|
|
145
|
+
if (!values.length) return text.value.empty
|
|
138
146
|
const first = values[0]
|
|
139
147
|
const last = values[values.length - 1]
|
|
140
|
-
const dir = last > first ?
|
|
141
|
-
return `${dir}, latest ${last}`
|
|
148
|
+
const dir = last > first ? text.value.up : last < first ? text.value.down : text.value.flat
|
|
149
|
+
return `${dir}, ${text.value.latest} ${last}`
|
|
142
150
|
})
|
|
143
151
|
|
|
144
152
|
/*
|
|
@@ -8,6 +8,7 @@ export default { inheritAttrs: false }
|
|
|
8
8
|
<script setup lang="ts">
|
|
9
9
|
import { computed } from "vue"
|
|
10
10
|
import LpIcon from "./LpIcon.vue"
|
|
11
|
+
import LpRollingText from "./LpRollingText.vue"
|
|
11
12
|
import { useMergedAttrs } from "../composables/useMergedClass"
|
|
12
13
|
|
|
13
14
|
export interface Step {
|
|
@@ -65,19 +66,28 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(
|
|
|
65
66
|
>
|
|
66
67
|
<div class="flex items-center gap-2">
|
|
67
68
|
<span
|
|
68
|
-
class="flex size-7 shrink-0 items-center justify-center rounded-pill border text-xs font-semibold transition-colors"
|
|
69
|
+
class="flex size-7 shrink-0 items-center justify-center rounded-pill border text-xs font-semibold transition-colors duration-[var(--duration-medium)]"
|
|
69
70
|
:class="isCompleted(step, i)
|
|
70
71
|
? 'border-transparent bg-brand text-ink-inverse'
|
|
71
72
|
: isCurrent(i)
|
|
72
73
|
? 'border-brand text-brand'
|
|
73
74
|
: 'border-line text-muted'"
|
|
74
75
|
>
|
|
75
|
-
|
|
76
|
-
<
|
|
77
|
-
|
|
76
|
+
<!-- The number turns into the tick rather than swapping for it. -->
|
|
77
|
+
<LpRollingText
|
|
78
|
+
mode="flip"
|
|
79
|
+
:duration="260"
|
|
80
|
+
:value="isCompleted(step, i) ? 'done' : step.icon ? 'icon' : String(i + 1)"
|
|
81
|
+
>
|
|
82
|
+
<template #default="{ value }">
|
|
83
|
+
<LpIcon v-if="value === 'done'" name="lucide:check" :size="14" />
|
|
84
|
+
<LpIcon v-else-if="value === 'icon' && step.icon" :name="step.icon" :size="14" />
|
|
85
|
+
<template v-else>{{ value }}</template>
|
|
86
|
+
</template>
|
|
87
|
+
</LpRollingText>
|
|
78
88
|
</span>
|
|
79
89
|
<span
|
|
80
|
-
class="text-sm"
|
|
90
|
+
class="text-sm transition-colors duration-[var(--duration-medium)]"
|
|
81
91
|
:class="isCompleted(step, i) || isCurrent(i) ? 'text-ink' : 'text-muted'"
|
|
82
92
|
>
|
|
83
93
|
{{ step.label }}
|
|
@@ -91,11 +101,14 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(
|
|
|
91
101
|
}}</span>
|
|
92
102
|
</span>
|
|
93
103
|
</div>
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
104
|
+
<!-- The connector fills from the step it leaves towards the next one,
|
|
105
|
+
so finishing a step reads as moving forward. -->
|
|
106
|
+
<span v-if="i < steps.length - 1" class="relative h-px flex-1 overflow-hidden bg-line">
|
|
107
|
+
<span
|
|
108
|
+
class="absolute inset-0 origin-left bg-brand transition-transform duration-[var(--duration-medium)] ease-[var(--ease-emphasized)] motion-reduce:transition-none rtl:origin-right"
|
|
109
|
+
:class="isCompleted(step, i) ? 'scale-x-100' : 'scale-x-0'"
|
|
110
|
+
/>
|
|
111
|
+
</span>
|
|
99
112
|
</li>
|
|
100
113
|
</ol>
|
|
101
114
|
</template>
|
|
@@ -6,8 +6,9 @@ export default { inheritAttrs: false }
|
|
|
6
6
|
</script>
|
|
7
7
|
|
|
8
8
|
<script setup lang="ts">
|
|
9
|
-
import { computed, useSlots } from "vue"
|
|
9
|
+
import { computed, useId, useSlots } from "vue"
|
|
10
10
|
import { SwitchRoot, SwitchThumb } from "reka-ui"
|
|
11
|
+
import { useFieldControl } from "../composables/useField"
|
|
11
12
|
import { useMergedAttrs } from "../composables/useMergedClass"
|
|
12
13
|
|
|
13
14
|
const props = withDefaults(
|
|
@@ -34,7 +35,7 @@ const labelled = computed(() => Boolean(props.label || props.description || slot
|
|
|
34
35
|
const TRACK =
|
|
35
36
|
"group inline-flex h-5 w-9 shrink-0 items-center rounded-pill border border-line bg-surface-soft px-0.5 outline-none transition-colors duration-[var(--duration-fast)] focus-visible:ring-2 focus-visible:ring-ring data-[state=checked]:border-transparent data-[state=checked]:bg-brand disabled:cursor-not-allowed disabled:opacity-55"
|
|
36
37
|
const THUMB =
|
|
37
|
-
"h-3.5 w-3.5 rounded-full bg-ink shadow transition-[translate,width,background-color] duration-[var(--duration-fast)] ease-[var(--ease-emphasized)] group-active:w-5 group-data-[state=checked]:translate-x-4 group-data-[state=checked]:bg-ink-inverse group-data-[state=checked]:group-active
|
|
38
|
+
"h-3.5 w-3.5 rounded-full bg-ink shadow transition-[translate,width,background-color] duration-[var(--duration-fast)] ease-[var(--ease-emphasized)] group-active:w-5 group-data-[state=checked]:translate-x-4 group-data-[state=checked]:bg-ink-inverse group-data-[state=checked]:group-active:translate-x-2.5 motion-reduce:group-active:w-3.5"
|
|
38
39
|
|
|
39
40
|
// Bare, the switch is the root, so a consumer asking for a bigger track must not
|
|
40
41
|
// have to depend on stylesheet order to get it. With text, the row is the root
|
|
@@ -46,31 +47,53 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(() => {
|
|
|
46
47
|
: "inline-flex cursor-pointer items-center gap-2 text-sm text-ink"
|
|
47
48
|
})
|
|
48
49
|
|
|
50
|
+
// Whatever is not class (name, aria-*, @focus…) belongs to the switch itself,
|
|
51
|
+
// labelled or not: on the label row it would land on the <label>.
|
|
52
|
+
const field = useFieldControl(() => ({
|
|
53
|
+
wrapped: false,
|
|
54
|
+
id: typeof rest.value.id === "string" ? rest.value.id : undefined,
|
|
55
|
+
disabled: props.disabled,
|
|
56
|
+
}))
|
|
57
|
+
const descriptionId = `${useId()}-description`
|
|
58
|
+
const describedBy = computed(
|
|
59
|
+
() => [props.description && labelled.value ? descriptionId : "", field.value.describedBy ?? ""].filter(Boolean).join(" ") || undefined,
|
|
60
|
+
)
|
|
61
|
+
|
|
49
62
|
function onUpdate(value: boolean) {
|
|
50
63
|
emit("update:modelValue", value)
|
|
51
64
|
}
|
|
52
65
|
</script>
|
|
53
66
|
|
|
54
67
|
<template>
|
|
55
|
-
<label v-if="labelled" :class="[rootClass, disabled && 'cursor-not-allowed']"
|
|
68
|
+
<label v-if="labelled" :class="[rootClass, field.disabled && 'cursor-not-allowed']">
|
|
56
69
|
<span v-if="labelPosition === 'start'" class="flex min-w-0 flex-col">
|
|
57
70
|
<slot>{{ label }}</slot>
|
|
58
|
-
<span v-if="description" class="text-xs text-muted">{{ description }}</span>
|
|
71
|
+
<span v-if="description" :id="descriptionId" class="text-xs text-muted">{{ description }}</span>
|
|
59
72
|
</span>
|
|
60
|
-
<SwitchRoot
|
|
73
|
+
<SwitchRoot
|
|
74
|
+
v-bind="rest"
|
|
75
|
+
:id="field.id"
|
|
76
|
+
:model-value="modelValue"
|
|
77
|
+
:disabled="field.disabled"
|
|
78
|
+
:aria-describedby="describedBy"
|
|
79
|
+
:class="TRACK"
|
|
80
|
+
@update:model-value="onUpdate"
|
|
81
|
+
>
|
|
61
82
|
<SwitchThumb :class="THUMB" />
|
|
62
83
|
</SwitchRoot>
|
|
63
84
|
<span v-if="labelPosition === 'end'" class="flex min-w-0 flex-col">
|
|
64
85
|
<slot>{{ label }}</slot>
|
|
65
|
-
<span v-if="description" class="text-xs text-muted">{{ description }}</span>
|
|
86
|
+
<span v-if="description" :id="descriptionId" class="text-xs text-muted">{{ description }}</span>
|
|
66
87
|
</span>
|
|
67
88
|
</label>
|
|
68
89
|
<SwitchRoot
|
|
69
90
|
v-else
|
|
91
|
+
v-bind="rest"
|
|
92
|
+
:id="field.id"
|
|
70
93
|
:model-value="modelValue"
|
|
71
|
-
:disabled="disabled"
|
|
94
|
+
:disabled="field.disabled"
|
|
95
|
+
:aria-describedby="describedBy"
|
|
72
96
|
:class="rootClass"
|
|
73
|
-
v-bind="rest"
|
|
74
97
|
@update:model-value="onUpdate"
|
|
75
98
|
>
|
|
76
99
|
<SwitchThumb :class="THUMB" />
|