@leavepulse/ui 0.43.3 → 0.44.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 +75 -7
- package/dist/assets/{LpCommandPalette-DH7sPcKP.css → LpCommandPalette-DCP5g2ik.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/{LpShortcutsDialog-C6YoQ8_M.css → LpShortcutsDialog-ChUyU7oV.css} +7 -7
- package/dist/assets/{LpSkeleton-D7xU8IPV.css → LpSkeleton-H3Z5dEIk.css} +4 -1
- package/dist/assets/{LpTable-BgPLJOXa.css → LpTable-DDQNdf86.css} +9 -9
- package/dist/chunks/ContextMenuItems-CrfeNPWT.js +123 -0
- package/dist/chunks/{LayoutCanvas-Dd20boUG.js → LayoutCanvas-D-jPOAvg.js} +26 -9
- package/dist/chunks/{LayoutNode-DGpZA9LX.js → LayoutNode-D8Xy9N-o.js} +20 -8
- package/dist/chunks/{LpActionBar-BlvtGB2P.js → LpActionBar-BbwCF6l5.js} +24 -10
- package/dist/chunks/{LpAddressInput-B-Zvxsn7.js → LpAddressInput-BrOqkZqg.js} +53 -48
- package/dist/chunks/{LpAlert-BAYHDSS1.js → LpAlert-DkOIjsbq.js} +15 -8
- package/dist/chunks/{LpAppShell-BGQVIY-3.js → LpAppShell-BUKPcHco.js} +51 -24
- package/dist/chunks/{LpAutocomplete-DExlIZe_.js → LpAutocomplete-DxV3Y9h4.js} +50 -23
- package/dist/chunks/{LpAvatar-B3-xAOH3.js → LpAvatar-ClBbEYZN.js} +17 -8
- package/dist/chunks/LpBreadcrumbs-B8IJgFIc.js +95 -0
- package/dist/chunks/{LpButton-5VXXCjwF.js → LpButton-kqJBHIIb.js} +44 -14
- package/dist/chunks/{LpCard-BhI1N_vL.js → LpCard-CpRByR0q.js} +1 -1
- package/dist/chunks/{LpCheckbox-CVccKYaH.js → LpCheckbox-DpqchzH4.js} +7 -3
- package/dist/chunks/{LpCodeBlock-Bo0B4TFR.js → LpCodeBlock-DeHJPq7p.js} +48 -16
- package/dist/chunks/{LpColorPicker-BlXea7LM.js → LpColorPicker-Bhf1qxhB.js} +32 -9
- package/dist/chunks/{LpConfirmDialog-Q-bxff8z.js → LpConfirmDialog-CIUOSnWo.js} +58 -16
- package/dist/chunks/LpConfirmHost-CDm0Wtpv.js +49 -0
- package/dist/chunks/LpContextMenu-DQw5dGfG.js +68 -0
- package/dist/chunks/LpDatePicker-Drirx1AK.js +191 -0
- package/dist/chunks/{LpDrawer-BZ6k3hvo.js → LpDrawer-bScx-KMO.js} +63 -26
- package/dist/chunks/{LpFileTree-_5vFBgaK.js → LpFileTree-CSI_5SK2.js} +23 -8
- package/dist/chunks/{LpFileTreeNode-BdcIYKIE.js → LpFileTreeNode-B4MiSQX2.js} +2 -2
- package/dist/chunks/LpFormField-CIk5qosh.js +87 -0
- package/dist/chunks/{LpInput-9EXWUM9B.js → LpInput-C0e8y8_d.js} +26 -11
- package/dist/chunks/{LpLightbox-2sYVMY-S.js → LpLightbox-Mr0W_6HK.js} +147 -60
- package/dist/chunks/{LpLink-DCND-zyu.js → LpLink-Krkjhe_y.js} +15 -6
- package/dist/chunks/{LpLogViewer-CaRy5MeS.js → LpLogViewer-YBOaFnc_.js} +68 -34
- package/dist/chunks/{LpMapPicker-ul4oYno6.js → LpMapPicker-NUzS9e37.js} +38 -13
- package/dist/chunks/{LpMediaGallery-FF-NquIo.js → LpMediaGallery-DfJmMW0I.js} +6 -3
- package/dist/chunks/{LpModal-Bt0pQCI_.js → LpModal-DPwGKBPv.js} +49 -26
- package/dist/chunks/{LpModalNav-YaifHrXC.js → LpModalNav-DPg5H9f3.js} +9 -6
- package/dist/chunks/{LpNotificationBell-DyGGsMAM.js → LpNotificationBell-t5yn-siX.js} +58 -24
- package/dist/chunks/{LpNumberField-CWuX08iX.js → LpNumberField-DWnQKktS.js} +20 -7
- 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-DFngX7Xo.js} +30 -19
- package/dist/chunks/{LpPasswordInput--sjYCkLS.js → LpPasswordInput-CWVDuBJ5.js} +10 -7
- package/dist/chunks/{LpPhoneInput-BDSKVl_z.js → LpPhoneInput-CD-ZTeSd.js} +57 -33
- package/dist/chunks/{LpPie-D6OnzwlJ.js → LpPie-BLco31Nx.js} +78 -21
- package/dist/chunks/{LpPopover-8268UmlC.js → LpPopover-p_e_shN3.js} +4 -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/{LpSegmented-fV0Sk92p.js → LpSegmented-Dejd7cIx.js} +7 -3
- package/dist/chunks/{LpSelect-ANIVtrpM.js → LpSelect-DrRD9I7L.js} +40 -18
- package/dist/chunks/{LpSidebar-ClBUwoEz.js → LpSidebar-BgwUNWpJ.js} +30 -22
- package/dist/chunks/{LpSidebarNav-llOcs_Fn.js → LpSidebarNav-Bqxz8aWT.js} +14 -9
- 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-dXtyrdX9.js} +1 -1
- package/dist/chunks/{LpSwitch-Blizvqyt.js → LpSwitch-B1aLKulj.js} +40 -26
- package/dist/chunks/{LpTableOfContents-CjvxPMpU.js → LpTableOfContents-BUcAfGPQ.js} +36 -41
- package/dist/chunks/{LpTabs-Cefe_lys.js → LpTabs-_qMVaZJ6.js} +19 -5
- package/dist/chunks/LpTextarea-yP8hGedR.js +77 -0
- package/dist/chunks/LpThemeProvider-Wjm7Tuit.js +35 -0
- package/dist/chunks/LpThemeSwitcher-CKLc10KZ.js +169 -0
- package/dist/chunks/{LpTilt-DuyKbpkA.js → LpTilt-B7KHX1zH.js} +2 -2
- package/dist/chunks/{LpTimeField-K6nAGboX.js → LpTimeField-C5HRgS5H.js} +13 -7
- package/dist/chunks/{LpToaster-gDB1EaU3.js → LpToaster--oT6lfhL.js} +57 -28
- package/dist/chunks/{LpTooltip-hCLPAqMG.js → LpTooltip-CBdzeKNf.js} +13 -6
- package/dist/chunks/LpTooltipProvider-CftjV7Xc.js +25 -0
- package/dist/chunks/{LpTopologyCanvas-Cm1L39uL.js → LpTopologyCanvas-DocsLal3.js} +6 -1
- package/dist/chunks/{LpUptimeBar-DvAMno0S.js → LpUptimeBar-DLtxOMRy.js} +43 -14
- package/dist/chunks/{LpThemeSwitcher-Cue-myST.js → useTheme-C8JHUlPM.js} +173 -215
- 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/LpCard.vue.js +1 -1
- package/dist/components/LpChart.vue.d.ts +31 -2
- package/dist/components/LpChart.vue.js +317 -95
- 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.js +1 -1
- package/dist/components/LpCommandPalette.vue.d.ts +8 -10
- package/dist/components/LpCommandPalette.vue.js +88 -78
- 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/LpDrawer.vue.d.ts +10 -0
- package/dist/components/LpDrawer.vue.js +1 -1
- package/dist/components/LpDropzone.vue.js +22 -6
- 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 +9 -0
- package/dist/components/LpFormField.vue.js +1 -1
- package/dist/components/LpImageEditor.vue.js +92 -57
- package/dist/components/LpInput.vue.d.ts +3 -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 +20 -2
- 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.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.js +1 -1
- package/dist/components/LpRadioGroup.vue.js +1 -1
- package/dist/components/LpSection.vue.d.ts +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 +1 -1
- package/dist/components/LpShortcutsDialog.vue.js +11 -8
- 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/LpSwitch.vue.js +1 -1
- package/dist/components/LpTable.vue.d.ts +23 -1
- package/dist/components/LpTable.vue.js +74 -36
- 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/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 +13 -0
- 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 +39 -4
- 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.d.ts +0 -1
- package/dist/components/commandSearch.js +1 -17
- 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/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/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/sidebar.d.ts +7 -1
- package/dist/components/tableSort.d.ts +8 -0
- package/dist/components/tableSort.js +31 -0
- package/dist/composables/useField.d.ts +34 -0
- package/dist/composables/useField.js +45 -0
- package/dist/composables/useFormDraft.d.ts +10 -3
- package/dist/composables/useFormDraft.js +9 -14
- package/dist/composables/useHotkeys.d.ts +17 -1
- package/dist/composables/useHotkeys.js +55 -18
- package/dist/composables/useInputFilter.d.ts +17 -0
- package/dist/composables/useInputFilter.js +47 -10
- package/dist/composables/useLpConfig.d.ts +24 -0
- package/dist/composables/useLpConfig.js +44 -0
- package/dist/composables/useRovingFocus.js +7 -0
- 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/index.d.ts +33 -3
- package/dist/index.js +185 -139
- 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/useTheme.d.ts +32 -9
- package/package.json +8 -7
- package/src/component-names.ts +5 -7
- package/src/components/ContextMenuItems.vue +88 -0
- package/src/components/LayoutCanvas.vue +26 -6
- package/src/components/LayoutNode.vue +19 -2
- package/src/components/LpActionBar.vue +30 -7
- 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 +46 -10
- package/src/components/LpAvatar.vue +19 -5
- package/src/components/LpBreadcrumbs.vue +65 -41
- package/src/components/LpButton.vue +59 -13
- package/src/components/LpChart.vue +272 -28
- package/src/components/LpCheckbox.vue +7 -3
- package/src/components/LpCodeBlock.vue +50 -14
- package/src/components/LpColorPicker.vue +39 -9
- package/src/components/LpCommandPalette.vue +36 -25
- package/src/components/LpConfirmDialog.vue +68 -17
- package/src/components/LpConfirmHost.vue +59 -0
- package/src/components/LpContextMenu.vue +14 -115
- package/src/components/LpDatePicker.vue +99 -68
- package/src/components/LpDrawer.vue +56 -19
- package/src/components/LpDropzone.vue +21 -4
- package/src/components/LpFileTree.vue +33 -7
- package/src/components/LpFormField.vue +30 -7
- package/src/components/LpImageEditor.vue +96 -57
- package/src/components/LpInput.vue +18 -7
- package/src/components/LpLightbox.vue +140 -29
- package/src/components/LpLink.vue +24 -13
- package/src/components/LpLogViewer.vue +86 -17
- package/src/components/LpMapPicker.vue +36 -13
- package/src/components/LpMediaGallery.vue +8 -2
- package/src/components/LpModal.vue +53 -27
- package/src/components/LpModalNav.vue +5 -2
- package/src/components/LpNotificationBell.vue +63 -17
- 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 +53 -27
- package/src/components/LpPie.vue +94 -15
- package/src/components/LpPopover.vue +3 -0
- package/src/components/LpProgress.vue +5 -3
- package/src/components/LpRadioGroup.vue +9 -2
- package/src/components/LpSegmented.vue +12 -2
- package/src/components/LpSelect.vue +0 -0
- package/src/components/LpShortcutsDialog.vue +8 -3
- 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/LpSwitch.vue +30 -7
- package/src/components/LpTable.vue +91 -32
- package/src/components/LpTableOfContents.vue +50 -32
- package/src/components/LpTabs.vue +23 -6
- package/src/components/LpTextarea.vue +44 -6
- package/src/components/LpThemeProvider.vue +41 -0
- package/src/components/LpThemeSwitcher.vue +64 -17
- package/src/components/LpTilt.vue +2 -2
- package/src/components/LpTimeField.vue +14 -3
- package/src/components/LpToaster.vue +66 -26
- package/src/components/LpTooltip.vue +22 -5
- package/src/components/LpTooltipProvider.vue +24 -0
- package/src/components/LpTopologyCanvas.vue +12 -1
- package/src/components/LpUptimeBar.vue +46 -8
- package/src/components/chart.ts +77 -5
- package/src/components/codeHighlight.ts +111 -15
- package/src/components/color.ts +30 -9
- package/src/components/commandSearch.ts +0 -17
- package/src/components/confirm.ts +58 -0
- package/src/components/countries.ts +12 -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/modalDepth.ts +48 -6
- package/src/components/otp.ts +16 -0
- package/src/components/sidebar.ts +7 -1
- package/src/components/tableSort.ts +37 -0
- package/src/composables/useField.ts +79 -0
- package/src/composables/useFormDraft.ts +25 -20
- package/src/composables/useHotkeys.ts +89 -18
- package/src/composables/useInputFilter.ts +77 -14
- package/src/composables/useLpConfig.ts +87 -0
- package/src/composables/useRovingFocus.ts +11 -0
- package/src/composables/useTilt.ts +5 -6
- package/src/composables/useToast.ts +56 -4
- package/src/composables/useZoomPan.ts +6 -6
- package/src/index.ts +38 -3
- package/src/layout/tree.ts +30 -0
- package/src/layout/useLayout.ts +68 -18
- package/src/nuxt.ts +59 -17
- package/src/runtime/config.plugin.ts +14 -0
- package/src/runtime/theme.plugin.ts +42 -22
- package/src/theme/useTheme.ts +206 -100
- 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/LpTextarea-t7F6gv8E.js +0 -47
|
@@ -173,23 +173,58 @@ const BOOLEANS = /* @__PURE__ */ new Set([
|
|
|
173
173
|
"Err"
|
|
174
174
|
// rust common variants read as constants
|
|
175
175
|
]);
|
|
176
|
-
const
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
176
|
+
const COMMENTS = {
|
|
177
|
+
ts: "c",
|
|
178
|
+
js: "c",
|
|
179
|
+
json: "none",
|
|
180
|
+
bash: "hash",
|
|
181
|
+
html: "html",
|
|
182
|
+
python: "hash",
|
|
183
|
+
rust: "c",
|
|
184
|
+
yaml: "hash",
|
|
185
|
+
toml: "hash",
|
|
186
|
+
kotlin: "c",
|
|
187
|
+
java: "c",
|
|
188
|
+
groovy: "c",
|
|
189
|
+
plain: "none"
|
|
190
|
+
};
|
|
191
|
+
const COMMENT_PATTERN = {
|
|
192
|
+
c: "\\/\\/[^\\n]*|\\/\\*[\\s\\S]*?\\*\\/",
|
|
193
|
+
// A `#` only starts a comment at the start of a word, so `a#b` in a URL or
|
|
194
|
+
// `${#arr[@]}` in shell stay code.
|
|
195
|
+
hash: "(?<![\\w$])#[^\\n]*",
|
|
196
|
+
html: "<!--[\\s\\S]*?-->",
|
|
197
|
+
none: "(?!)"
|
|
198
|
+
};
|
|
199
|
+
const BLOCK = {
|
|
200
|
+
c: { open: "/*", close: "*/" },
|
|
201
|
+
html: { open: "<!--", close: "-->" }
|
|
202
|
+
};
|
|
203
|
+
const masters = /* @__PURE__ */ new Map();
|
|
204
|
+
function masterFor(style) {
|
|
205
|
+
let re = masters.get(style);
|
|
206
|
+
if (!re) {
|
|
207
|
+
re = new RegExp(
|
|
208
|
+
[
|
|
209
|
+
`(${COMMENT_PATTERN[style]})`,
|
|
210
|
+
// 1 comment
|
|
211
|
+
"(\"(?:\\\\.|[^\"\\\\])*\"|'(?:\\\\.|[^'\\\\])*'|`(?:\\\\.|[^`\\\\])*`)",
|
|
212
|
+
// 2 string
|
|
213
|
+
"(@[A-Za-z_$][\\w$]*)",
|
|
214
|
+
// 3 annotation (@Override, @ConfigSerializable — JVM)
|
|
215
|
+
"(\\b\\d[\\d_]*(?:\\.\\d+)?(?:e[+-]?\\d+)?[fFlLdD]?\\b)",
|
|
216
|
+
// 4 number (JVM suffixes)
|
|
217
|
+
"(#?[A-Za-z_$][\\w$]*)",
|
|
218
|
+
// 5 identifier (keyword/bool/func/prop/plain), incl. #private
|
|
219
|
+
"([{}()\\[\\];:,.<>=+\\-*/%!&|?]+)"
|
|
220
|
+
// 6 punctuation
|
|
221
|
+
].join("|"),
|
|
222
|
+
"g"
|
|
223
|
+
);
|
|
224
|
+
masters.set(style, re);
|
|
225
|
+
}
|
|
226
|
+
return re;
|
|
227
|
+
}
|
|
193
228
|
function classifyIdent(name, before, after) {
|
|
194
229
|
if (KEYWORDS.has(name)) return C.keyword;
|
|
195
230
|
if (BOOLEANS.has(name)) return C.boolean;
|
|
@@ -198,11 +233,13 @@ function classifyIdent(name, before, after) {
|
|
|
198
233
|
return "";
|
|
199
234
|
}
|
|
200
235
|
function tokenizeLine(line, lang) {
|
|
236
|
+
if (lang === "plain") return line ? [{ text: line, cls: "" }] : [];
|
|
201
237
|
const out = [];
|
|
202
238
|
let last = 0;
|
|
203
239
|
let m;
|
|
204
|
-
|
|
205
|
-
|
|
240
|
+
const master = masterFor(COMMENTS[lang]);
|
|
241
|
+
master.lastIndex = 0;
|
|
242
|
+
while ((m = master.exec(line)) !== null) {
|
|
206
243
|
if (m.index > last) out.push({ text: line.slice(last, m.index), cls: "" });
|
|
207
244
|
const [full, comment, str, annotation, num, ident, punct] = m;
|
|
208
245
|
if (comment != null) out.push({ text: full, cls: C.comment });
|
|
@@ -225,6 +262,41 @@ function tokenizeLine(line, lang) {
|
|
|
225
262
|
if (last < line.length) out.push({ text: line.slice(last), cls: "" });
|
|
226
263
|
return out;
|
|
227
264
|
}
|
|
265
|
+
function tokenizeLines(lines, lang) {
|
|
266
|
+
const block = BLOCK[COMMENTS[lang]];
|
|
267
|
+
if (!block) return lines.map((line) => tokenizeLine(line, lang));
|
|
268
|
+
const out = [];
|
|
269
|
+
let open = false;
|
|
270
|
+
for (const line of lines) {
|
|
271
|
+
let rest = line;
|
|
272
|
+
const tokens = [];
|
|
273
|
+
if (open) {
|
|
274
|
+
const end = rest.indexOf(block.close);
|
|
275
|
+
if (end === -1) {
|
|
276
|
+
out.push(rest ? [{ text: rest, cls: C.comment }] : []);
|
|
277
|
+
continue;
|
|
278
|
+
}
|
|
279
|
+
tokens.push({ text: rest.slice(0, end + block.close.length), cls: C.comment });
|
|
280
|
+
rest = rest.slice(end + block.close.length);
|
|
281
|
+
open = false;
|
|
282
|
+
}
|
|
283
|
+
const lineTokens = tokenizeLine(rest, lang);
|
|
284
|
+
const at = lineTokens.findIndex(
|
|
285
|
+
(t) => t.cls !== C.comment && t.cls !== C.string && t.text.includes(block.open)
|
|
286
|
+
);
|
|
287
|
+
if (at >= 0) {
|
|
288
|
+
const cut = lineTokens[at].text.indexOf(block.open);
|
|
289
|
+
const tail = lineTokens.slice(at).map((t) => t.text).join("").slice(cut);
|
|
290
|
+
tokens.push(...lineTokens.slice(0, at));
|
|
291
|
+
if (cut > 0) tokens.push({ text: lineTokens[at].text.slice(0, cut), cls: lineTokens[at].cls });
|
|
292
|
+
tokens.push({ text: tail, cls: C.comment });
|
|
293
|
+
open = true;
|
|
294
|
+
} else tokens.push(...lineTokens);
|
|
295
|
+
out.push(tokens);
|
|
296
|
+
}
|
|
297
|
+
return out;
|
|
298
|
+
}
|
|
228
299
|
export {
|
|
229
|
-
tokenizeLine
|
|
300
|
+
tokenizeLine,
|
|
301
|
+
tokenizeLines
|
|
230
302
|
};
|
|
@@ -17,7 +17,7 @@ export type ColorFormat = "hex" | "rgb" | "hsl";
|
|
|
17
17
|
/** Wraps rather than clamps: hue is a circle, and 370° is 10°, not 360°. */
|
|
18
18
|
export declare function normalizeHue(h: number): number;
|
|
19
19
|
export declare function clampHsv(c: Hsv): Hsv;
|
|
20
|
-
export declare function hsvToRgb(
|
|
20
|
+
export declare function hsvToRgb(color: Hsv): Rgb;
|
|
21
21
|
export declare function rgbToHsv({ r, g, b, a }: Rgb): Hsv;
|
|
22
22
|
/** "#rrggbb", or "#rrggbbaa" when the colour is not fully opaque. */
|
|
23
23
|
export declare function rgbToHex({ r, g, b, a }: Rgb): string;
|
package/dist/components/color.js
CHANGED
|
@@ -11,7 +11,12 @@ function clampHsv(c) {
|
|
|
11
11
|
a: clamp(c.a, 0, 1)
|
|
12
12
|
};
|
|
13
13
|
}
|
|
14
|
-
|
|
14
|
+
const finite = (n) => Number.isFinite(n) ? n : 0;
|
|
15
|
+
function hsvToRgb(color) {
|
|
16
|
+
const h = finite(color.h);
|
|
17
|
+
const s = clamp(finite(color.s), 0, 1);
|
|
18
|
+
const v = clamp(finite(color.v), 0, 1);
|
|
19
|
+
const a = Number.isFinite(color.a) ? color.a : 1;
|
|
15
20
|
const hue = normalizeHue(h) / 60;
|
|
16
21
|
const c = v * s;
|
|
17
22
|
const x = c * (1 - Math.abs(hue % 2 - 1));
|
|
@@ -52,9 +57,13 @@ function rgbToHsv({ r, g, b, a }) {
|
|
|
52
57
|
};
|
|
53
58
|
}
|
|
54
59
|
const hex2 = (n) => clamp(Math.round(n), 0, 255).toString(16).padStart(2, "0");
|
|
60
|
+
function alphaByte(a) {
|
|
61
|
+
return Math.round(clamp(a, 0, 1) * 255);
|
|
62
|
+
}
|
|
55
63
|
function rgbToHex({ r, g, b, a }) {
|
|
56
64
|
const base = `#${hex2(r)}${hex2(g)}${hex2(b)}`;
|
|
57
|
-
|
|
65
|
+
const byte = alphaByte(a);
|
|
66
|
+
return byte >= 255 ? base : base + hex2(byte);
|
|
58
67
|
}
|
|
59
68
|
function parseHex(input) {
|
|
60
69
|
const s = input.trim().replace(/^#/, "");
|
|
@@ -105,16 +114,18 @@ function hsvToHsl({ h, s, v }) {
|
|
|
105
114
|
}
|
|
106
115
|
function formatColor(c, format) {
|
|
107
116
|
const rgb = hsvToRgb(c);
|
|
108
|
-
const
|
|
117
|
+
const byte = alphaByte(rgb.a);
|
|
118
|
+
const a = Math.round(byte / 255 * 1e3) / 1e3;
|
|
109
119
|
if (format === "hex") return rgbToHex(rgb);
|
|
110
120
|
if (format === "rgb") {
|
|
111
|
-
return
|
|
121
|
+
return byte >= 255 ? `rgb(${rgb.r}, ${rgb.g}, ${rgb.b})` : `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${a})`;
|
|
112
122
|
}
|
|
113
|
-
const { h, s, l } = hsvToHsl(c);
|
|
114
|
-
const
|
|
115
|
-
const
|
|
116
|
-
const
|
|
117
|
-
|
|
123
|
+
const { h, s, l } = hsvToHsl({ ...c, h: finite(c.h), s: clamp(finite(c.s), 0, 1), v: clamp(finite(c.v), 0, 1) });
|
|
124
|
+
const dec = (n) => Math.round(n * 10) / 10;
|
|
125
|
+
const hh = dec(h) % 360;
|
|
126
|
+
const ss = dec(s * 100);
|
|
127
|
+
const ll = dec(l * 100);
|
|
128
|
+
return byte >= 255 ? `hsl(${hh}, ${ss}%, ${ll}%)` : `hsla(${hh}, ${ss}%, ${ll}%, ${a})`;
|
|
118
129
|
}
|
|
119
130
|
function opaqueCss(c) {
|
|
120
131
|
const { r, g, b } = hsvToRgb({ ...c, a: 1 });
|
|
@@ -10,5 +10,4 @@ export interface CommandSearchTerms {
|
|
|
10
10
|
groups: string[];
|
|
11
11
|
}
|
|
12
12
|
export declare function parseCommandQuery(value: string): CommandSearchTerms;
|
|
13
|
-
export declare function swapCommandTerms(terms: CommandSearchTerms): CommandSearchTerms;
|
|
14
13
|
export declare function rankCommandItems<T extends SearchableCommand>(items: T[], terms: CommandSearchTerms): T[];
|
|
@@ -1,11 +1,4 @@
|
|
|
1
1
|
const QUERY_TOKEN = /(-?)(?:(in):)?(?:"([^"]*)"|(\S+))/giu;
|
|
2
|
-
const LATIN = "qwertyuiop[]asdfghjkl;'zxcvbnm,.`";
|
|
3
|
-
const CYRILLIC = "йцукенгшщзхъфывапролджэячсмитьбюё";
|
|
4
|
-
const SWAP = /* @__PURE__ */ new Map();
|
|
5
|
-
for (let i = 0; i < LATIN.length; i++) {
|
|
6
|
-
SWAP.set(LATIN[i], CYRILLIC[i]);
|
|
7
|
-
SWAP.set(CYRILLIC[i], LATIN[i]);
|
|
8
|
-
}
|
|
9
2
|
function parseCommandQuery(value) {
|
|
10
3
|
const out = { include: [], exclude: [], groups: [] };
|
|
11
4
|
QUERY_TOKEN.lastIndex = 0;
|
|
@@ -18,14 +11,6 @@ function parseCommandQuery(value) {
|
|
|
18
11
|
}
|
|
19
12
|
return out;
|
|
20
13
|
}
|
|
21
|
-
function swapCommandTerms(terms) {
|
|
22
|
-
const swap = (term) => [...term].map((ch) => SWAP.get(ch) ?? ch).join("");
|
|
23
|
-
return {
|
|
24
|
-
include: terms.include.map(swap),
|
|
25
|
-
exclude: terms.exclude.map(swap),
|
|
26
|
-
groups: terms.groups.map(swap)
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
14
|
function matches(command, term) {
|
|
30
15
|
return command.label.toLowerCase().includes(term) || (command.keywords ?? []).some((keyword) => keyword.toLowerCase().includes(term)) || (command.description?.toLowerCase().includes(term) ?? false);
|
|
31
16
|
}
|
|
@@ -61,6 +46,5 @@ function rankCommandItems(items, terms) {
|
|
|
61
46
|
}
|
|
62
47
|
export {
|
|
63
48
|
parseCommandQuery,
|
|
64
|
-
rankCommandItems
|
|
65
|
-
swapCommandTerms
|
|
49
|
+
rankCommandItems
|
|
66
50
|
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface ConfirmOptions {
|
|
2
|
+
title: string;
|
|
3
|
+
description?: string;
|
|
4
|
+
danger?: boolean;
|
|
5
|
+
icon?: string;
|
|
6
|
+
confirmLabel?: string;
|
|
7
|
+
cancelLabel?: string;
|
|
8
|
+
loadingLabel?: string;
|
|
9
|
+
/**
|
|
10
|
+
* Work to run on confirm. The dialog stays open with a loading state while it
|
|
11
|
+
* runs and shows the error's message if it rejects; the promise from
|
|
12
|
+
* `confirm()` resolves true only once it succeeded.
|
|
13
|
+
*/
|
|
14
|
+
action?: () => unknown;
|
|
15
|
+
}
|
|
16
|
+
export interface ConfirmRequest extends ConfirmOptions {
|
|
17
|
+
id: number;
|
|
18
|
+
resolve: (confirmed: boolean) => void;
|
|
19
|
+
}
|
|
20
|
+
export declare const confirmQueue: ConfirmRequest[];
|
|
21
|
+
/** Ask for confirmation. Resolves false when the user cancels or dismisses. */
|
|
22
|
+
export declare function confirm(options: ConfirmOptions): Promise<boolean>;
|
|
23
|
+
/** Settle a request and drop it from the queue. Used by the host. */
|
|
24
|
+
export declare function settleConfirm(id: number, confirmed: boolean): void;
|
|
25
|
+
export declare function useConfirm(): typeof confirm;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { reactive } from "vue";
|
|
2
|
+
const STATE_KEY = /* @__PURE__ */ Symbol.for("@leavepulse/ui:confirm-queue");
|
|
3
|
+
const g = globalThis;
|
|
4
|
+
const state = g[STATE_KEY] ??= { queue: reactive([]), nextId: 0 };
|
|
5
|
+
const confirmQueue = state.queue;
|
|
6
|
+
function confirm(options) {
|
|
7
|
+
if (typeof window === "undefined") return Promise.resolve(false);
|
|
8
|
+
return new Promise((resolve) => {
|
|
9
|
+
state.queue.push({ ...options, id: state.nextId++, resolve });
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
function settleConfirm(id, confirmed) {
|
|
13
|
+
const i = state.queue.findIndex((r) => r.id === id);
|
|
14
|
+
if (i === -1) return;
|
|
15
|
+
const [request] = state.queue.splice(i, 1);
|
|
16
|
+
request?.resolve(confirmed);
|
|
17
|
+
}
|
|
18
|
+
function useConfirm() {
|
|
19
|
+
return confirm;
|
|
20
|
+
}
|
|
21
|
+
export {
|
|
22
|
+
confirm,
|
|
23
|
+
confirmQueue,
|
|
24
|
+
settleConfirm,
|
|
25
|
+
useConfirm
|
|
26
|
+
};
|
|
@@ -18,3 +18,9 @@ export declare function loadCountries(): Promise<Country[]>;
|
|
|
18
18
|
* country is preferred. Pass the list (from loadCountries). Undefined if none.
|
|
19
19
|
*/
|
|
20
20
|
export declare function matchCountryByValue(value: string, list: Country[]): Country | undefined;
|
|
21
|
+
/**
|
|
22
|
+
* Countries matching a search query: by name, or by dial code when the query
|
|
23
|
+
* carries digits ("+44", "44"). A query without digits must not match on the
|
|
24
|
+
* dial code at all, or every country would match the empty string.
|
|
25
|
+
*/
|
|
26
|
+
export declare function filterCountries(list: Country[], query: string): Country[];
|
|
@@ -31,7 +31,14 @@ function matchCountryByValue(value, list) {
|
|
|
31
31
|
}
|
|
32
32
|
return best;
|
|
33
33
|
}
|
|
34
|
+
function filterCountries(list, query) {
|
|
35
|
+
const q = query.trim().toLowerCase();
|
|
36
|
+
if (!q) return list;
|
|
37
|
+
const digits = q.replace(/\D/g, "");
|
|
38
|
+
return list.filter((c) => c.name.toLowerCase().includes(q) || digits !== "" && c.dial.includes(digits));
|
|
39
|
+
}
|
|
34
40
|
export {
|
|
41
|
+
filterCountries,
|
|
35
42
|
flagEmoji,
|
|
36
43
|
loadCountries,
|
|
37
44
|
matchCountryByValue
|
|
@@ -75,7 +75,7 @@ function formatSize(bytes) {
|
|
|
75
75
|
const units = ["KB", "MB", "GB", "TB", "PB"];
|
|
76
76
|
let value = bytes / 1024;
|
|
77
77
|
let i = 0;
|
|
78
|
-
while (value >= 1024 && i < units.length - 1) {
|
|
78
|
+
while (Math.round(value) >= 1024 && i < units.length - 1) {
|
|
79
79
|
value /= 1024;
|
|
80
80
|
i++;
|
|
81
81
|
}
|
|
@@ -118,14 +118,18 @@ function checkStateOf(node, checked) {
|
|
|
118
118
|
}
|
|
119
119
|
let all = true;
|
|
120
120
|
let any = false;
|
|
121
|
+
let considered = 0;
|
|
121
122
|
for (const child of node.children) {
|
|
122
123
|
const state = checkStateOf(child, checked);
|
|
124
|
+
if (child.disabled && state === "unchecked") continue;
|
|
125
|
+
considered++;
|
|
123
126
|
if (state === "checked") any = true;
|
|
124
127
|
else if (state === "indeterminate") {
|
|
125
128
|
any = true;
|
|
126
129
|
all = false;
|
|
127
130
|
} else all = false;
|
|
128
131
|
}
|
|
132
|
+
if (!considered) return checked.has(node.id) ? "checked" : "unchecked";
|
|
129
133
|
if (all) return "checked";
|
|
130
134
|
return any ? "indeterminate" : "unchecked";
|
|
131
135
|
}
|
|
@@ -165,13 +169,17 @@ function computeStats(nodes, checked) {
|
|
|
165
169
|
let total = 0;
|
|
166
170
|
let bytes = 0;
|
|
167
171
|
let sized = node.size !== void 0;
|
|
172
|
+
let considered = 0;
|
|
168
173
|
for (const child of node.children) {
|
|
169
174
|
const childStats = visit(child);
|
|
170
|
-
if (childStats.state
|
|
171
|
-
|
|
172
|
-
any = true;
|
|
173
|
-
|
|
174
|
-
|
|
175
|
+
if (!child.disabled || childStats.state !== "unchecked") {
|
|
176
|
+
considered++;
|
|
177
|
+
if (childStats.state === "checked") any = true;
|
|
178
|
+
else if (childStats.state === "indeterminate") {
|
|
179
|
+
any = true;
|
|
180
|
+
all = false;
|
|
181
|
+
} else all = false;
|
|
182
|
+
}
|
|
175
183
|
count += childStats.checked;
|
|
176
184
|
total += childStats.total;
|
|
177
185
|
if (childStats.size !== void 0) {
|
|
@@ -179,8 +187,9 @@ function computeStats(nodes, checked) {
|
|
|
179
187
|
sized = true;
|
|
180
188
|
}
|
|
181
189
|
}
|
|
190
|
+
const own = checked.has(node.id) ? "checked" : "unchecked";
|
|
182
191
|
const self = {
|
|
183
|
-
state: all ? "checked" : any ? "indeterminate" : "unchecked",
|
|
192
|
+
state: !considered ? own : all ? "checked" : any ? "indeterminate" : "unchecked",
|
|
184
193
|
checked: count,
|
|
185
194
|
total,
|
|
186
195
|
// An explicit size on the directory wins: a server-side listing usually
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export interface Point {
|
|
2
|
+
x: number;
|
|
3
|
+
y: number;
|
|
4
|
+
}
|
|
5
|
+
export interface CropInput {
|
|
6
|
+
sourceWidth: number;
|
|
7
|
+
sourceHeight: number;
|
|
8
|
+
frameWidth: number;
|
|
9
|
+
frameHeight: number;
|
|
10
|
+
/** Accumulated rotation in degrees; any angle, not only quarter turns. */
|
|
11
|
+
rotation: number;
|
|
12
|
+
/** Zoom factor, 1 = the picture just covers the frame. */
|
|
13
|
+
scale: number;
|
|
14
|
+
/** Pan in frame pixels before the zoom, as useZoomPan reports it. */
|
|
15
|
+
offset: Point;
|
|
16
|
+
}
|
|
17
|
+
export interface CropGeometry {
|
|
18
|
+
/** CSS pixels per source pixel at zoom 1. */
|
|
19
|
+
cover: number;
|
|
20
|
+
/** Crop size in upright (source-pixel) units. */
|
|
21
|
+
width: number;
|
|
22
|
+
height: number;
|
|
23
|
+
/** Crop centre in upright space. */
|
|
24
|
+
centre: Point;
|
|
25
|
+
}
|
|
26
|
+
/** Rotate a point clockwise by `deg` in a y-down space. */
|
|
27
|
+
export declare function rotatePoint(p: Point, deg: number): Point;
|
|
28
|
+
/** The source pixel (from the source's top-left) under an upright-space point. */
|
|
29
|
+
export declare function uprightToSource(u: Point, rotation: number, sourceWidth: number, sourceHeight: number): Point;
|
|
30
|
+
/**
|
|
31
|
+
* Smallest scale at which the turned picture still covers the whole frame.
|
|
32
|
+
*
|
|
33
|
+
* Covering the bounding box of a turned picture is not enough at a free angle:
|
|
34
|
+
* its corners are empty. The frame, turned back by the same angle, has to fit
|
|
35
|
+
* inside the unturned picture; for a quarter turn this reduces to the usual
|
|
36
|
+
* object-cover of the swapped dimensions.
|
|
37
|
+
*/
|
|
38
|
+
export declare function coverScale(sourceWidth: number, sourceHeight: number, frameWidth: number, frameHeight: number, rotation: number): number;
|
|
39
|
+
/** What the frame holds, in upright space. */
|
|
40
|
+
export declare function cropGeometry(input: CropInput): CropGeometry;
|
|
41
|
+
/** Whether the turn is closer to sideways than to upright. */
|
|
42
|
+
export declare function isSideways(rotation: number): boolean;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
const radians = (deg) => deg * Math.PI / 180;
|
|
2
|
+
function rotatePoint(p, deg) {
|
|
3
|
+
const a = radians(deg);
|
|
4
|
+
const cos = Math.cos(a);
|
|
5
|
+
const sin = Math.sin(a);
|
|
6
|
+
return { x: p.x * cos - p.y * sin, y: p.x * sin + p.y * cos };
|
|
7
|
+
}
|
|
8
|
+
function uprightToSource(u, rotation, sourceWidth, sourceHeight) {
|
|
9
|
+
const q = rotatePoint(u, -rotation);
|
|
10
|
+
return { x: q.x + sourceWidth / 2, y: q.y + sourceHeight / 2 };
|
|
11
|
+
}
|
|
12
|
+
function coverScale(sourceWidth, sourceHeight, frameWidth, frameHeight, rotation) {
|
|
13
|
+
const a = radians(rotation);
|
|
14
|
+
const cos = Math.abs(Math.cos(a));
|
|
15
|
+
const sin = Math.abs(Math.sin(a));
|
|
16
|
+
return Math.max(
|
|
17
|
+
(frameWidth * cos + frameHeight * sin) / sourceWidth,
|
|
18
|
+
(frameWidth * sin + frameHeight * cos) / sourceHeight
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
function cropGeometry(input) {
|
|
22
|
+
const cover = coverScale(
|
|
23
|
+
input.sourceWidth,
|
|
24
|
+
input.sourceHeight,
|
|
25
|
+
input.frameWidth,
|
|
26
|
+
input.frameHeight,
|
|
27
|
+
input.rotation
|
|
28
|
+
);
|
|
29
|
+
const shown = cover * input.scale;
|
|
30
|
+
return {
|
|
31
|
+
cover,
|
|
32
|
+
width: input.frameWidth / shown,
|
|
33
|
+
height: input.frameHeight / shown,
|
|
34
|
+
centre: { x: -input.offset.x / cover, y: -input.offset.y / cover }
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
function isSideways(rotation) {
|
|
38
|
+
const quarters = Math.round(rotation / 90);
|
|
39
|
+
return (quarters % 2 + 2) % 2 === 1;
|
|
40
|
+
}
|
|
41
|
+
export {
|
|
42
|
+
coverScale,
|
|
43
|
+
cropGeometry,
|
|
44
|
+
isSideways,
|
|
45
|
+
rotatePoint,
|
|
46
|
+
uprightToSource
|
|
47
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Component } from "vue";
|
|
2
|
+
export type LinkTarget = string | Record<string, unknown>;
|
|
3
|
+
export interface ResolvedLink {
|
|
4
|
+
is: Component | string;
|
|
5
|
+
props: Record<string, unknown>;
|
|
6
|
+
}
|
|
7
|
+
/** An app-relative path: "/x", not "//host" or "https://…". */
|
|
8
|
+
export declare function isInternalHref(href: string): boolean;
|
|
9
|
+
export declare function resolveLink(linkComponent: Component | string, target: {
|
|
10
|
+
to?: LinkTarget;
|
|
11
|
+
href?: string;
|
|
12
|
+
}): ResolvedLink | null;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
function isInternalHref(href) {
|
|
2
|
+
return href.startsWith("/") && !href.startsWith("//");
|
|
3
|
+
}
|
|
4
|
+
function resolveLink(linkComponent, target) {
|
|
5
|
+
const router = linkComponent !== "a";
|
|
6
|
+
if (target.to != null) {
|
|
7
|
+
if (router) return { is: linkComponent, props: { to: target.to } };
|
|
8
|
+
return typeof target.to === "string" ? { is: "a", props: { href: target.to } } : null;
|
|
9
|
+
}
|
|
10
|
+
if (target.href != null) {
|
|
11
|
+
if (router && isInternalHref(target.href)) return { is: linkComponent, props: { to: target.href } };
|
|
12
|
+
return { is: "a", props: { href: target.href } };
|
|
13
|
+
}
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
export {
|
|
17
|
+
isInternalHref,
|
|
18
|
+
resolveLink
|
|
19
|
+
};
|
|
@@ -1,11 +1,27 @@
|
|
|
1
1
|
import { type ComputedRef } from "vue";
|
|
2
|
-
export
|
|
2
|
+
export interface ModalLayer {
|
|
3
|
+
/** Join the stack on top. Ignored on the server, where nothing would ever release it. */
|
|
3
4
|
claim: () => void;
|
|
4
5
|
release: () => void;
|
|
6
|
+
/** z-index values for this surface's scrim and panel, and whether another modal is under it. */
|
|
5
7
|
layer: ComputedRef<{
|
|
6
8
|
scrim: string;
|
|
7
9
|
panel: string;
|
|
8
10
|
nested: boolean;
|
|
9
11
|
}>;
|
|
10
|
-
|
|
12
|
+
/** Whether this surface is the topmost open one. */
|
|
13
|
+
top: ComputedRef<boolean>;
|
|
14
|
+
}
|
|
15
|
+
export interface ModalLayerOptions {
|
|
16
|
+
/** The surface's panel, so keyboard handling can tell what sits inside the top modal. */
|
|
17
|
+
element?: () => HTMLElement | null | undefined;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Put an overlay on the shared modal stack, so a surface opened from another
|
|
21
|
+
* one (a dialog from a drawer, a lightbox from a dialog) lands above it with
|
|
22
|
+
* its scrim, whatever component either of them is.
|
|
23
|
+
*/
|
|
24
|
+
export declare function useModalLayer(options?: ModalLayerOptions): ModalLayer;
|
|
11
25
|
export declare function anyModalOpen(): boolean;
|
|
26
|
+
/** The panel of the topmost modal, when it registered one. */
|
|
27
|
+
export declare function topModalElement(): HTMLElement | null;
|
|
@@ -1,18 +1,23 @@
|
|
|
1
1
|
import { ref, computed } from "vue";
|
|
2
2
|
const STEP = 20;
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
const STATE_KEY = /* @__PURE__ */ Symbol.for("@leavepulse/ui:modal-stack");
|
|
4
|
+
const g = globalThis;
|
|
5
|
+
const state = g[STATE_KEY] ??= { stack: ref([]), nextId: 0, elements: /* @__PURE__ */ new Map() };
|
|
6
|
+
const stack = state.stack;
|
|
7
|
+
function useModalLayer(options = {}) {
|
|
8
|
+
const id = state.nextId++;
|
|
7
9
|
const fromTop = computed(() => {
|
|
8
10
|
const at = stack.value.indexOf(id);
|
|
9
11
|
return at === -1 ? 0 : stack.value.length - 1 - at;
|
|
10
12
|
});
|
|
11
13
|
return {
|
|
12
14
|
claim: () => {
|
|
15
|
+
if (typeof window === "undefined") return;
|
|
16
|
+
if (options.element) state.elements.set(id, options.element);
|
|
13
17
|
if (!stack.value.includes(id)) stack.value = [...stack.value, id];
|
|
14
18
|
},
|
|
15
19
|
release: () => {
|
|
20
|
+
state.elements.delete(id);
|
|
16
21
|
stack.value = stack.value.filter((x) => x !== id);
|
|
17
22
|
},
|
|
18
23
|
layer: computed(() => {
|
|
@@ -22,13 +27,20 @@ function useModalLayer() {
|
|
|
22
27
|
panel: `calc(var(--z-modal) - ${drop})`,
|
|
23
28
|
nested: stack.value.indexOf(id) > 0
|
|
24
29
|
};
|
|
25
|
-
})
|
|
30
|
+
}),
|
|
31
|
+
top: computed(() => stack.value[stack.value.length - 1] === id)
|
|
26
32
|
};
|
|
27
33
|
}
|
|
28
34
|
function anyModalOpen() {
|
|
29
35
|
return stack.value.length > 0;
|
|
30
36
|
}
|
|
37
|
+
function topModalElement() {
|
|
38
|
+
const id = stack.value[stack.value.length - 1];
|
|
39
|
+
if (id === void 0) return null;
|
|
40
|
+
return state.elements.get(id)?.() ?? null;
|
|
41
|
+
}
|
|
31
42
|
export {
|
|
32
43
|
anyModalOpen,
|
|
44
|
+
topModalElement,
|
|
33
45
|
useModalLayer
|
|
34
46
|
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export type OtpCells = (string | number | undefined)[];
|
|
2
|
+
/** The code typed so far: the filled cells in order. */
|
|
3
|
+
export declare function joinCells(cells: OtpCells): string;
|
|
4
|
+
/** Cells for a code given from outside, one character each. */
|
|
5
|
+
export declare function splitCode(code: string | undefined, length: number): string[];
|
|
@@ -3,8 +3,14 @@ export interface SidebarItem {
|
|
|
3
3
|
id: string;
|
|
4
4
|
label: string;
|
|
5
5
|
icon?: string;
|
|
6
|
-
/**
|
|
6
|
+
/**
|
|
7
|
+
* Render as a link instead of a button. An app-relative path goes through
|
|
8
|
+
* the link component from provideLpConfig (NuxtLink under the Nuxt module),
|
|
9
|
+
* so it navigates client-side; other URLs render a plain anchor.
|
|
10
|
+
*/
|
|
7
11
|
href?: string;
|
|
12
|
+
/** Router destination (rendered through the configured link component). */
|
|
13
|
+
to?: string | Record<string, unknown>;
|
|
8
14
|
/** Count chip on the right (number or short string). */
|
|
9
15
|
badge?: number | string;
|
|
10
16
|
disabled?: boolean;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ascending order for raw cell values. Empty values (null, undefined, NaN, an
|
|
3
|
+
* invalid Date) come first; numbers, bigints and Dates compare by magnitude,
|
|
4
|
+
* booleans false before true, everything else as text with numeric runs read as
|
|
5
|
+
* numbers ("file 2" before "file 10"). Mixed kinds group by kind so the order
|
|
6
|
+
* is total and a sort is stable from one run to the next.
|
|
7
|
+
*/
|
|
8
|
+
export declare function compareValues(a: unknown, b: unknown): number;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
const COLLATOR = new Intl.Collator(void 0, { numeric: true });
|
|
2
|
+
const rank = (v) => {
|
|
3
|
+
if (v == null || typeof v === "number" && Number.isNaN(v)) return 0;
|
|
4
|
+
if (typeof v === "boolean") return 1;
|
|
5
|
+
if (typeof v === "number" || typeof v === "bigint") return 2;
|
|
6
|
+
if (v instanceof Date) return Number.isNaN(v.getTime()) ? 0 : 3;
|
|
7
|
+
return 4;
|
|
8
|
+
};
|
|
9
|
+
function compareValues(a, b) {
|
|
10
|
+
const ra = rank(a);
|
|
11
|
+
const rb = rank(b);
|
|
12
|
+
if (ra !== rb) return ra - rb;
|
|
13
|
+
switch (ra) {
|
|
14
|
+
case 0:
|
|
15
|
+
return 0;
|
|
16
|
+
case 1:
|
|
17
|
+
return Number(a) - Number(b);
|
|
18
|
+
case 2: {
|
|
19
|
+
const x = a;
|
|
20
|
+
const y = b;
|
|
21
|
+
return x < y ? -1 : x > y ? 1 : 0;
|
|
22
|
+
}
|
|
23
|
+
case 3:
|
|
24
|
+
return a.getTime() - b.getTime();
|
|
25
|
+
default:
|
|
26
|
+
return COLLATOR.compare(String(a), String(b));
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
export {
|
|
30
|
+
compareValues
|
|
31
|
+
};
|