@leavepulse/ui 0.77.2 → 0.78.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 +68 -0
- package/dist/assets/{LpCommandPalette-DOIZHw-g.css → LpCommandPalette-DDJKICKh.css} +19 -19
- package/dist/assets/{LpDock-Cbh0wQUv.css → LpDock-Dw82tWVD.css} +3 -3
- package/dist/assets/{LpDropzone-B_qRq1-R.css → LpDropzone-DNbh_NFJ.css} +10 -10
- package/dist/assets/{LpImageEditor-XM5bAziW.css → LpImageEditor-Bgu20XLs.css} +6 -6
- package/dist/assets/{LpTable-Bv-EcQs7.css → LpTable-CCk0ZHo7.css} +19 -19
- package/dist/assets/LpTabs-Bh7a-Bdl.css +18 -0
- package/dist/chunks/AppShellContextNav-C6Ho2mof.js +49 -0
- package/dist/chunks/ChartRangeSelector-HO0sMMz6.js +129 -0
- package/dist/chunks/{ContextMenuItems-BXumicbh.js → ContextMenuItems-DmaKSJVv.js} +1 -1
- package/dist/chunks/{DropzoneLinkField-C-9BCGJn.js → DropzoneLinkField-DXIr0eFz.js} +2 -2
- package/dist/chunks/{FieldWrapper-CORPzo9s.js → FieldWrapper-DnuMTrqW.js} +1 -1
- package/dist/chunks/IconCloseButton-COZEsa9u.js +29 -0
- package/dist/chunks/{LayoutCanvas-CNOAUk7D.js → LayoutCanvas-CZKOltfA.js} +1 -1
- package/dist/chunks/{LayoutNode-DF5BMN0J.js → LayoutNode-D2f7v683.js} +45 -45
- package/dist/chunks/{LpActionBar-BP1ld7-S.js → LpActionBar-BGMk5KoG.js} +3 -3
- package/dist/chunks/{LpActivityLine-CJvzrNpj.js → LpActivityLine-Ea-t5Vza.js} +4 -2
- package/dist/chunks/{LpAddressInput-sYMvYzcY.js → LpAddressInput-ZqoZ-N2Y.js} +12 -11
- package/dist/chunks/{LpAlert-n5XPAZfv.js → LpAlert-CjvTZIKF.js} +3 -3
- package/dist/chunks/LpAppShell-BNAVTQsY.js +582 -0
- package/dist/chunks/{LpAutocomplete-DOu7FN5P.js → LpAutocomplete-DkY6CSyD.js} +26 -42
- package/dist/chunks/{LpAvatar-Cg6Az3wz.js → LpAvatar-cQVsNk6F.js} +2 -2
- package/dist/chunks/{LpBadge-wUYLN4U9.js → LpBadge-D5QQdDQ_.js} +2 -2
- package/dist/chunks/{LpBottomNav-CbNQQPuL.js → LpBottomNav-zxLGGbjm.js} +9 -2
- package/dist/chunks/{LpBreadcrumbs-DPdbth-c.js → LpBreadcrumbs-CIIBsygI.js} +4 -3
- package/dist/chunks/{LpButton-CFb44IjC.js → LpButton-DSHioIfD.js} +5 -4
- package/dist/chunks/{LpCalendar-CuoWks-0.js → LpCalendar-D4-LVjfF.js} +1 -1
- package/dist/chunks/{LpCard-r13WRqox.js → LpCard-BPtYXwnT.js} +1 -1
- package/dist/chunks/{LpCheckbox-Cs4SHaHX.js → LpCheckbox-D6RuDW4X.js} +38 -16
- package/dist/chunks/{LpCodeBlock-DRC8VbXW.js → LpCodeBlock-DuzmnIHl.js} +19 -41
- package/dist/chunks/{LpCodeDisplay-CE9TxCA4.js → LpCodeDisplay-CO8fngxa.js} +5 -5
- package/dist/chunks/{LpCollapse-CWS9M_lm.js → LpCollapse-DrAw5DBZ.js} +5 -4
- package/dist/chunks/{LpColorPicker-1y1QJHZR.js → LpColorPicker-BxAHEnR5.js} +11 -12
- package/dist/chunks/{LpCommandScope-CtUhJe8T.js → LpCommandScope-DRUvHiX7.js} +1 -1
- package/dist/chunks/{LpConfirmDialog-DlD45Bi_.js → LpConfirmDialog-6oCIJTDa.js} +3 -3
- package/dist/chunks/{LpConfirmHost-BIWjBLmI.js → LpConfirmHost-DgHvfT6s.js} +1 -1
- package/dist/chunks/{LpContextMenu-rx2tCjwk.js → LpContextMenu--eMGIql6.js} +13 -15
- package/dist/chunks/{LpContextSwitcher-Dwh6dyID.js → LpContextSwitcher-1C1tExdl.js} +2 -2
- package/dist/chunks/{LpCopyButton-xF7wFVoU.js → LpCopyButton-7EOSIuwa.js} +3 -3
- package/dist/chunks/{LpCountdown-DgeY3cLG.js → LpCountdown-DVl7vXI1.js} +4 -3
- package/dist/chunks/{LpDataList-Jxyl9H5w.js → LpDataList-DgBeM01y.js} +13 -4
- package/dist/chunks/{LpDatePicker-CA0QTfBC.js → LpDatePicker-DwSDY0mt.js} +12 -18
- package/dist/chunks/{LpDateRangePicker-u3J51xXk.js → LpDateRangePicker-CNQXdTVv.js} +10 -16
- package/dist/chunks/{LpDisclosure-Cpa7Hc5T.js → LpDisclosure-DG7JCo-d.js} +2 -2
- package/dist/chunks/{LpDrawer-CrG8t_KP.js → LpDrawer-Bt9UUqt_.js} +61 -61
- package/dist/chunks/{LpDropdownMenu-Dl7Z4ZhS.js → LpDropdownMenu-CLzxIOgM.js} +9 -17
- package/dist/chunks/{LpEditable-Cy6GLbFx.js → LpEditable-DVT0Rh8F.js} +9 -6
- package/dist/chunks/{LpEmptyState-EQHiRYhG.js → LpEmptyState-DurPF001.js} +1 -1
- package/dist/chunks/{LpFieldNotice-CzQ2_5rQ.js → LpFieldNotice-DJ10cYIo.js} +1 -1
- package/dist/chunks/LpFileTree-BSx1kBoV.js +735 -0
- package/dist/chunks/{LpFileTreeNode-cT6BIWvz.js → LpFileTreeNode-4dVmFHb3.js} +116 -34
- package/dist/chunks/{LpFormField-Ch69Jd-X.js → LpFormField-BKYn9dyP.js} +3 -3
- package/dist/chunks/{LpFrame-BVQCQLDI.js → LpFrame-Bv5Fphte.js} +25 -11
- package/dist/chunks/{LpHintExample-9Py0wc-L.js → LpHintExample-YzCXiSUp.js} +1 -1
- package/dist/chunks/{LpHintLayer-CgObdUsM.js → LpHintLayer-BeKRsRon.js} +2 -2
- package/dist/chunks/{LpHints-Bz-BlaSl.js → LpHints-qf3xYsza.js} +3 -3
- package/dist/chunks/{LpHoverCard-spGxyw7T.js → LpHoverCard-DanH3Nz1.js} +23 -5
- package/dist/chunks/{LpIcon--5WSb3jJ.js → LpIcon-C6JpQ5td.js} +6 -3
- package/dist/chunks/{LpIdenticon-BzdC_qz9.js → LpIdenticon-Dbbr4fvt.js} +2 -1
- package/dist/chunks/{LpInfraNode-46XOCkfq.js → LpInfraNode-BAU40Km2.js} +2 -2
- package/dist/chunks/{LpInput-Tw-yxT4I.js → LpInput-DL6HEJdi.js} +16 -28
- package/dist/chunks/LpInspector-CuoMAhiw.js +209 -0
- package/dist/chunks/{LpLightbox-B95yu22B.js → LpLightbox-xvpQ64MM.js} +57 -32
- package/dist/chunks/{LpLoader-DVwkOmt9.js → LpLoader-Bf1yZwaU.js} +1 -1
- package/dist/chunks/LpLogInspector-6cNnXqp4.js +119 -0
- package/dist/chunks/{LpLogViewer-ngqkns4m.js → LpLogViewer-Dvb1E9_G.js} +234 -53
- package/dist/chunks/{LpMapPicker-DRGgh89B.js → LpMapPicker-D5_YLLBC.js} +4 -3
- package/dist/chunks/{LpMasonry--k0571qG.js → LpMasonry-DPYekFxs.js} +8 -5
- package/dist/chunks/{LpMediaGallery-Bkram-MO.js → LpMediaGallery-Df-tiWeq.js} +3 -3
- package/dist/chunks/{LpModal-CoGhLTyH.js → LpModal-DrtQ_1A2.js} +11 -13
- package/dist/chunks/{LpModalNav-BGvs2y5Q.js → LpModalNav-DkmGCnZE.js} +11 -37
- package/dist/chunks/{LpNotificationBell-B0034Lk-.js → LpNotificationBell-D_wklO1m.js} +9 -9
- package/dist/chunks/{LpNumberField-e0IBkWU1.js → LpNumberField-CNHsmSDZ.js} +7 -16
- package/dist/chunks/{LpOtpInput-CeBPsM7D.js → LpOtpInput-BRpLBbOD.js} +2 -2
- package/dist/chunks/{LpPagination-BIIiYHXR.js → LpPagination-snQ020xQ.js} +6 -4
- package/dist/chunks/{LpPaletteTheme-DiLYKQiZ.js → LpPaletteTheme-dVtxHx-F.js} +4 -4
- package/dist/chunks/{LpPasswordInput-BkHKQDhM.js → LpPasswordInput-B-zD6tUS.js} +2 -2
- package/dist/chunks/{LpPhoneInput-CETEp5W7.js → LpPhoneInput-BSL7NX4z.js} +15 -26
- package/dist/chunks/{LpPie-DrZepi0p.js → LpPie-9t_guO49.js} +22 -21
- package/dist/chunks/{LpPipeline-B3aOVOkV.js → LpPipeline-rjXvEDRJ.js} +16 -7
- package/dist/chunks/{LpPopover-DmZ3wUtP.js → LpPopover-BQSuxtai.js} +10 -1
- package/dist/chunks/{LpProgress-Yr6ONG5t.js → LpProgress-D_MSjowb.js} +2 -1
- package/dist/chunks/{LpQuota-Dk2MyI2Z.js → LpQuota-CgWPgdVt.js} +1 -1
- package/dist/chunks/{LpRadioGroup-ggaPL92T.js → LpRadioGroup-BrazjLY_.js} +4 -4
- package/dist/chunks/{LpRangeCalendar-CYYUYqJ7.js → LpRangeCalendar-BrqlGZzE.js} +1 -1
- package/dist/chunks/{LpRangeSlider-CM-0ZITZ.js → LpRangeSlider-fz61tzc-.js} +5 -9
- package/dist/chunks/{LpRelativeTime-DwgCb5-8.js → LpRelativeTime-BovUk8MP.js} +1 -1
- package/dist/chunks/{LpRepeater-D7ZmnIYd.js → LpRepeater-BkJHSPI1.js} +3 -3
- package/dist/chunks/{LpRevealOnScroll-DcQjexLy.js → LpRevealOnScroll-CPwyiQAr.js} +1 -1
- package/dist/chunks/{LpScramble-Bn9OoOtC.js → LpScramble-DsE77iVp.js} +1 -1
- package/dist/chunks/{LpScrollArea-MyEnVB_5.js → LpScrollArea-ay4Xo_hg.js} +22 -10
- package/dist/chunks/{LpSecretField-BbmqM9ye.js → LpSecretField-DBvU6iAw.js} +10 -9
- package/dist/chunks/{LpSection-DFK_uoJE.js → LpSection-BfteipxU.js} +1 -1
- package/dist/chunks/{LpSegmented-CeACsMMA.js → LpSegmented-DbEJhbv-.js} +8 -10
- package/dist/chunks/{LpSelect-Cxq4yBGd.js → LpSelect-Y-iuSymW.js} +47 -30
- package/dist/chunks/{LpShaderBackdrop-Bote0iuy.js → LpShaderBackdrop-wQygYb5h.js} +13 -10
- package/dist/chunks/{LpShift-CCq7dofl.js → LpShift-DAgS_d2x.js} +18 -15
- package/dist/chunks/{LpSidebar-DzE1783C.js → LpSidebar-kSkpPh3-.js} +74 -87
- package/dist/chunks/{LpSidebarNav-DE3PhXVP.js → LpSidebarNav-C2mvqrY2.js} +8 -6
- package/dist/chunks/{LpSidebarRow-BRYhNDSo.js → LpSidebarRow-eRP4Q31q.js} +6 -5
- package/dist/chunks/{LpSlider-DxYoCJJO.js → LpSlider-A4ixovgS.js} +5 -9
- package/dist/chunks/{LpSpotlight-4F3NeUMY.js → LpSpotlight-DwxkhFgR.js} +2 -1
- package/dist/chunks/{LpStat-f2LfDCJ4.js → LpStat-pMNZgFcq.js} +2 -2
- package/dist/chunks/{LpStatus-DglxttQ7.js → LpStatus-DGJFwk5F.js} +2 -2
- package/dist/chunks/{LpStepMark-DpzKVyh8.js → LpStepMark-Dw2MRTrt.js} +2 -2
- package/dist/chunks/{LpStepper-DpsocBNJ.js → LpStepper-DNnh7lCu.js} +1 -1
- package/dist/chunks/{LpSwap-C96c0LWh.js → LpSwap-M7nFeW3C.js} +1 -1
- package/dist/chunks/{LpSwitch-BnXd1llc.js → LpSwitch-DnC2-0aV.js} +3 -3
- package/dist/chunks/{LpTabFace-DPCwKkH2.js → LpTabFace-DQoV8mQG.js} +2 -2
- package/dist/chunks/{LpTableFilter-CiVBpaq0.js → LpTableFilter-DgARTsA1.js} +4 -4
- package/dist/chunks/{LpTableOfContents-BN5zvpnx.js → LpTableOfContents-CKkWEK6R.js} +14 -9
- package/dist/chunks/{LpTagsInput-C-mDG648.js → LpTagsInput-Dt0mteSj.js} +19 -27
- package/dist/chunks/{LpTextarea-TE-yZv2U.js → LpTextarea-Co0b9PVx.js} +8 -16
- package/dist/chunks/LpThemeProvider-XK6ZeWAE.js +81 -0
- package/dist/chunks/{LpThemeStudio-BpORDvH6.js → LpThemeStudio-DzYfE-5k.js} +12 -195
- package/dist/chunks/{LpThemeSwitcher-BnEn_mvf.js → LpThemeSwitcher-CFLkdbBL.js} +8 -6
- package/dist/chunks/{LpTimeField-BawSVsmt.js → LpTimeField-DeOcKWJq.js} +6 -9
- package/dist/chunks/{LpToaster-IwTXjbbU.js → LpToaster-QFj0P-5m.js} +10 -8
- package/dist/chunks/{LpTooltip-BcBvIx4z.js → LpTooltip-BJf3lZMq.js} +51 -19
- package/dist/chunks/LpTopologyCanvas-BOHHHZ_6.js +673 -0
- package/dist/chunks/{LpTour-BZq-mUMv.js → LpTour-ClKYhx4h.js} +7 -5
- package/dist/chunks/{LpTruncate-CflAIwiJ.js → LpTruncate-C6u3gjc6.js} +6 -5
- package/dist/chunks/{LpTypewriter-BCL_a6wE.js → LpTypewriter-CZIzpdbe.js} +2 -1
- package/dist/chunks/{LpUptimeBar-DqNvvMBK.js → LpUptimeBar-BnYmR2rj.js} +3 -3
- package/dist/chunks/{LpVideoBackdrop-DS1wGv-X.js → LpVideoBackdrop-Ct4St4ZL.js} +10 -13
- package/dist/chunks/LpWindow-B8YSRVTH.js +297 -0
- package/dist/chunks/LpWorkspaceSwitcher-D0e9upAy.js +139 -0
- package/dist/chunks/{MenuTitle-BmCNNTKH.js → MenuTitle-Bh5dAdV1.js} +1 -1
- package/dist/chunks/{OptionContent-22UT8zLn.js → OptionContent-CGb8QlHA.js} +1 -1
- package/dist/chunks/{PickerField-Bfh8id3d.js → PickerField-BM1dyafh.js} +4 -4
- package/dist/chunks/{RevealToggle-BEit1n6Z.js → RevealToggle-CCPDE8Mv.js} +3 -3
- package/dist/chunks/SliderRail-DhPREa_R.js +18 -0
- package/dist/chunks/{TourCard-DNclH3u_.js → TourCard-DAzTYfav.js} +4 -4
- package/dist/chunks/{icons-DMITlfw5.js → icons-CYfcpSDS.js} +26 -10
- package/dist/component-names.d.ts +1 -1
- package/dist/components/AppShellContextNav.vue.d.ts +13 -0
- package/dist/components/AppShellContextNav.vue.js +4 -0
- package/dist/components/ChartRangeSelector.vue.d.ts +21 -0
- package/dist/components/ChartRangeSelector.vue.js +4 -0
- package/dist/components/ContextMenuItems.vue.js +1 -1
- package/dist/components/DropzoneLinkField.vue.d.ts +2 -2
- package/dist/components/DropzoneLinkField.vue.js +1 -1
- package/dist/components/FieldWrapper.vue.js +1 -1
- package/dist/components/IconCloseButton.vue.d.ts +7 -0
- package/dist/components/IconCloseButton.vue.js +4 -0
- package/dist/components/LayoutCanvas.vue.js +1 -1
- package/dist/components/LayoutNode.vue.js +1 -1
- package/dist/components/LpActionBar.vue.js +1 -1
- package/dist/components/LpActivityLine.vue.js +1 -1
- package/dist/components/LpAddressInput.vue.js +1 -1
- package/dist/components/LpAlert.vue.js +1 -1
- package/dist/components/LpAppShell.vue.d.ts +110 -2
- package/dist/components/LpAppShell.vue.js +1 -1
- package/dist/components/LpAutocomplete.vue.js +1 -1
- package/dist/components/LpAvatar.vue.js +1 -1
- package/dist/components/LpBadge.vue.js +1 -1
- package/dist/components/LpBottomNav.vue.d.ts +5 -0
- package/dist/components/LpBottomNav.vue.js +1 -1
- package/dist/components/LpBreadcrumbs.vue.js +1 -1
- package/dist/components/LpButton.vue.d.ts +14 -2
- 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 +74 -2
- package/dist/components/LpChart.vue.js +326 -85
- package/dist/components/LpCheckbox.vue.d.ts +6 -2
- package/dist/components/LpCheckbox.vue.js +1 -1
- package/dist/components/LpCodeBlock.vue.js +1 -1
- package/dist/components/LpCodeDisplay.vue.js +1 -1
- package/dist/components/LpCollapse.vue.js +1 -1
- package/dist/components/LpColorPicker.vue.js +1 -1
- package/dist/components/LpCommandPalette.vue.d.ts +8 -0
- package/dist/components/LpCommandPalette.vue.js +107 -56
- package/dist/components/LpCommandScope.vue.js +1 -1
- package/dist/components/LpConfirmDialog.vue.js +1 -1
- package/dist/components/LpConfirmHost.vue.js +1 -1
- package/dist/components/LpContextMenu.vue.js +1 -1
- package/dist/components/LpContextSwitcher.vue.js +1 -1
- package/dist/components/LpCopyButton.vue.js +1 -1
- package/dist/components/LpCountdown.vue.js +1 -1
- package/dist/components/LpDataList.vue.d.ts +1 -1
- package/dist/components/LpDataList.vue.js +1 -1
- package/dist/components/LpDatePicker.vue.d.ts +3 -15
- package/dist/components/LpDatePicker.vue.js +1 -1
- package/dist/components/LpDateRangePicker.vue.d.ts +3 -13
- package/dist/components/LpDateRangePicker.vue.js +1 -1
- package/dist/components/LpDisclosure.vue.js +1 -1
- package/dist/components/LpDock.vue.js +21 -18
- package/dist/components/LpDrawer.vue.d.ts +1 -1
- package/dist/components/LpDrawer.vue.js +1 -1
- package/dist/components/LpDropdownMenu.vue.js +1 -1
- package/dist/components/LpDropzone.vue.js +14 -11
- package/dist/components/LpEditable.vue.js +1 -1
- package/dist/components/LpEmptyState.vue.js +1 -1
- package/dist/components/LpFieldNotice.vue.js +1 -1
- package/dist/components/LpFileTree.vue.d.ts +96 -6
- package/dist/components/LpFileTree.vue.js +1 -1
- package/dist/components/LpFileTreeNode.vue.d.ts +48 -0
- package/dist/components/LpFileTreeNode.vue.js +1 -1
- package/dist/components/LpFormField.vue.js +1 -1
- package/dist/components/LpFrame.vue.js +1 -1
- package/dist/components/LpGauge.vue.d.ts +1 -1
- package/dist/components/LpHintExample.vue.js +1 -1
- package/dist/components/LpHintLayer.vue.js +1 -1
- package/dist/components/LpHints.vue.js +1 -1
- package/dist/components/LpHoverCard.vue.js +1 -1
- package/dist/components/LpIcon.vue.d.ts +2 -0
- package/dist/components/LpIcon.vue.js +1 -1
- package/dist/components/LpIdenticon.vue.js +1 -1
- package/dist/components/LpImageEditor.vue.js +7 -6
- package/dist/components/LpInfraNode.vue.js +1 -1
- package/dist/components/LpInput.vue.d.ts +1 -1
- package/dist/components/LpInput.vue.js +1 -1
- package/dist/components/LpInspector.vue.d.ts +87 -0
- package/dist/components/LpInspector.vue.js +4 -0
- package/dist/components/LpLightbox.vue.d.ts +8 -0
- package/dist/components/LpLightbox.vue.js +1 -1
- package/dist/components/LpLoader.vue.d.ts +1 -1
- package/dist/components/LpLoader.vue.js +1 -1
- package/dist/components/LpLogInspector.vue.d.ts +18 -0
- package/dist/components/LpLogInspector.vue.js +4 -0
- package/dist/components/LpLogViewer.vue.d.ts +93 -0
- package/dist/components/LpLogViewer.vue.js +1 -1
- package/dist/components/LpMapPicker.vue.js +1 -1
- package/dist/components/LpMasonry.vue.js +1 -1
- package/dist/components/LpMediaGallery.vue.js +1 -1
- package/dist/components/LpModal.vue.d.ts +4 -2
- package/dist/components/LpModal.vue.js +1 -1
- package/dist/components/LpModalNav.vue.d.ts +5 -5
- package/dist/components/LpModalNav.vue.js +1 -1
- package/dist/components/LpNotificationBell.vue.d.ts +2 -2
- package/dist/components/LpNotificationBell.vue.js +1 -1
- package/dist/components/LpNumberField.vue.js +1 -1
- package/dist/components/LpOtpInput.vue.js +1 -1
- package/dist/components/LpPagination.vue.js +1 -1
- package/dist/components/LpPaletteFacts.vue.js +1 -1
- package/dist/components/LpPaletteHeader.vue.js +2 -2
- package/dist/components/LpPaletteTheme.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 +2 -2
- package/dist/components/LpPie.vue.js +1 -1
- package/dist/components/LpPipeline.vue.d.ts +4 -0
- package/dist/components/LpPipeline.vue.js +1 -1
- package/dist/components/LpPopover.vue.d.ts +7 -3
- package/dist/components/LpPopover.vue.js +1 -1
- package/dist/components/LpProgress.vue.d.ts +1 -1
- package/dist/components/LpProgress.vue.js +1 -1
- package/dist/components/LpQuota.vue.js +1 -1
- package/dist/components/LpRadioGroup.vue.js +1 -1
- package/dist/components/LpRangeCalendar.vue.js +1 -1
- package/dist/components/LpRangeSlider.vue.js +1 -1
- package/dist/components/LpRelativeTime.vue.js +1 -1
- package/dist/components/LpRepeater.vue.js +1 -1
- package/dist/components/LpRevealOnScroll.vue.js +1 -1
- package/dist/components/LpScramble.vue.js +1 -1
- package/dist/components/LpScrollArea.vue.js +1 -1
- package/dist/components/LpSecretField.vue.js +1 -1
- package/dist/components/LpSection.vue.js +1 -1
- package/dist/components/LpSegmented.vue.js +1 -1
- package/dist/components/LpSelect.vue.js +1 -1
- package/dist/components/LpShaderBackdrop.vue.js +1 -1
- package/dist/components/LpShift.vue.js +1 -1
- package/dist/components/LpShortcutsDialog.vue.js +1 -1
- package/dist/components/LpSidebar.vue.d.ts +1 -1
- package/dist/components/LpSidebar.vue.js +1 -1
- package/dist/components/LpSidebarNav.vue.js +1 -1
- package/dist/components/LpSidebarRow.vue.js +1 -1
- package/dist/components/LpSlider.vue.js +1 -1
- package/dist/components/LpSparkline.vue.d.ts +1 -1
- package/dist/components/LpSpotlight.vue.js +1 -1
- package/dist/components/LpStat.vue.js +1 -1
- package/dist/components/LpStatus.vue.js +1 -1
- package/dist/components/LpStepMark.vue.js +1 -1
- package/dist/components/LpStepper.vue.js +1 -1
- package/dist/components/LpSwap.vue.js +1 -1
- package/dist/components/LpSwitch.vue.js +1 -1
- package/dist/components/LpTabFace.vue.js +1 -1
- package/dist/components/LpTable.vue.d.ts +132 -0
- package/dist/components/LpTable.vue.js +547 -135
- package/dist/components/LpTableFilter.vue.js +1 -1
- package/dist/components/LpTableOfContents.vue.js +1 -1
- package/dist/components/LpTabs.vue.js +6 -5
- package/dist/components/LpTagsInput.vue.js +1 -1
- package/dist/components/LpTextarea.vue.js +1 -1
- package/dist/components/LpThemeProvider.vue.d.ts +2 -0
- package/dist/components/LpThemeProvider.vue.js +1 -1
- package/dist/components/LpThemeStudio.vue.js +1 -1
- package/dist/components/LpThemeSwitcher.vue.js +1 -1
- package/dist/components/LpTimeField.vue.js +1 -1
- package/dist/components/LpToaster.vue.js +1 -1
- package/dist/components/LpTooltip.vue.js +1 -1
- package/dist/components/LpTopologyCanvas.vue.d.ts +131 -5
- package/dist/components/LpTopologyCanvas.vue.js +1 -1
- package/dist/components/LpTour.vue.js +1 -1
- package/dist/components/LpTruncate.vue.js +1 -1
- package/dist/components/LpTypewriter.vue.js +1 -1
- package/dist/components/LpUptimeBar.vue.js +1 -1
- package/dist/components/LpVideoBackdrop.vue.js +1 -1
- package/dist/components/LpWindow.vue.d.ts +99 -0
- package/dist/components/LpWindow.vue.js +4 -0
- package/dist/components/LpWorkspaceSwitcher.vue.d.ts +18 -0
- package/dist/components/LpWorkspaceSwitcher.vue.js +4 -0
- package/dist/components/MenuTitle.vue.js +1 -1
- package/dist/components/OptionContent.vue.js +1 -1
- package/dist/components/PickerField.vue.d.ts +2 -2
- package/dist/components/PickerField.vue.js +1 -1
- package/dist/components/RevealToggle.vue.js +1 -1
- package/dist/components/SliderRail.vue.d.ts +3 -0
- package/dist/components/SliderRail.vue.js +4 -0
- package/dist/components/TourCard.vue.js +1 -1
- package/dist/components/address.js +2 -1
- package/dist/components/appShell.d.ts +36 -0
- package/dist/components/appShell.js +30 -0
- package/dist/components/calendar.d.ts +12 -3
- package/dist/components/calendar.js +2 -5
- package/dist/components/chart.d.ts +21 -0
- package/dist/components/chart.js +4 -3
- package/dist/components/chartWindow.d.ts +57 -0
- package/dist/components/chartWindow.js +136 -0
- package/dist/components/color.js +1 -1
- package/dist/components/commandPalette.d.ts +16 -2
- package/dist/components/commandPalette.js +39 -4
- package/dist/components/controlSize.d.ts +5 -0
- package/dist/components/controlSize.js +8 -0
- package/dist/components/dropdown.d.ts +5 -0
- package/dist/components/dropdown.js +2 -0
- package/dist/components/exportData.d.ts +6 -1
- package/dist/components/exportData.js +25 -18
- package/dist/components/fileTree.d.ts +67 -0
- package/dist/components/fileTree.js +141 -1
- package/dist/components/identicon.js +3 -2
- package/dist/components/logTools.d.ts +93 -0
- package/dist/components/logTools.js +210 -0
- package/dist/components/menuWhen.js +1 -1
- package/dist/components/meter.js +2 -1
- package/dist/components/pipeline.d.ts +2 -0
- package/dist/components/pipeline.js +5 -0
- package/dist/components/relativeTime.js +2 -1
- package/dist/components/reveal.js +2 -1
- package/dist/components/select.d.ts +5 -0
- package/dist/components/select.js +10 -0
- package/dist/components/sidebar.d.ts +1 -0
- package/dist/components/tableFeatures.d.ts +58 -0
- package/dist/components/tableFeatures.js +87 -0
- package/dist/components/topologyGraph.d.ts +164 -0
- package/dist/components/topologyGraph.js +416 -0
- package/dist/components/tour.js +5 -3
- package/dist/components/videoBackdrop.js +7 -6
- package/dist/composables/clamp.d.ts +2 -0
- package/dist/composables/clamp.js +4 -0
- package/dist/composables/devWarn.d.ts +3 -0
- package/dist/composables/devWarn.js +14 -0
- package/dist/composables/easing.d.ts +13 -4
- package/dist/composables/easing.js +16 -10
- package/dist/composables/overlayHistory.js +14 -1
- package/dist/composables/pointerDrag.d.ts +15 -0
- package/dist/composables/pointerDrag.js +40 -0
- package/dist/composables/propCheck.d.ts +10 -0
- package/dist/composables/propCheck.js +78 -0
- package/dist/composables/realm.d.ts +6 -0
- package/dist/composables/realm.js +23 -0
- package/dist/composables/scroll.js +4 -2
- package/dist/composables/scrollMemory.d.ts +12 -1
- package/dist/composables/scrollMemory.js +36 -12
- package/dist/composables/spatialNav.js +2 -1
- package/dist/composables/textEntry.d.ts +17 -0
- package/dist/composables/textEntry.js +19 -0
- package/dist/composables/useAsyncTask.d.ts +6 -0
- package/dist/composables/useChartSync.d.ts +5 -0
- package/dist/composables/useChartSync.js +33 -0
- package/dist/composables/useCloseGuard.d.ts +3 -1
- package/dist/composables/useCloseGuard.js +6 -3
- package/dist/composables/useCommands.d.ts +50 -0
- package/dist/composables/useCommands.js +66 -0
- package/dist/composables/useField.d.ts +37 -0
- package/dist/composables/useField.js +27 -2
- package/dist/composables/useFitScale.js +4 -1
- package/dist/composables/useFormDraft.d.ts +13 -2
- package/dist/composables/useFormDraft.js +17 -9
- package/dist/composables/useHintSystem.js +2 -2
- package/dist/composables/useHotkeys.js +11 -32
- package/dist/composables/useInView.js +2 -1
- package/dist/composables/useInputFilter.js +7 -5
- package/dist/composables/useInputMask.js +5 -3
- package/dist/composables/useLinkedView.d.ts +97 -0
- package/dist/composables/useLinkedView.js +139 -0
- package/dist/composables/useOptimisticToggle.d.ts +3 -1
- package/dist/composables/useOptimisticToggle.js +2 -1
- package/dist/composables/useOverlayHistory.d.ts +7 -0
- package/dist/composables/useOverlayHistory.js +16 -2
- package/dist/composables/usePaintSelect.js +18 -14
- package/dist/composables/usePaletteCommands.d.ts +7 -0
- package/dist/composables/usePaletteCommands.js +12 -1
- package/dist/composables/usePersisted.d.ts +10 -0
- package/dist/composables/usePersisted.js +1 -1
- package/dist/composables/usePillTransition.d.ts +2 -2
- package/dist/composables/usePillTransition.js +5 -5
- package/dist/composables/useResizeObserver.js +2 -1
- package/dist/composables/useReveal.js +2 -1
- package/dist/composables/useRovingFocus.d.ts +2 -2
- package/dist/composables/useRovingFocus.js +9 -11
- package/dist/composables/useScramble.js +7 -1
- package/dist/composables/useShift.js +8 -6
- package/dist/composables/useTilt.js +2 -1
- package/dist/composables/useTween.js +9 -5
- package/dist/composables/useView.d.ts +1 -0
- package/dist/composables/useView.js +14 -2
- package/dist/composables/useZoomPan.js +2 -4
- package/dist/composables/windowing.d.ts +40 -0
- package/dist/composables/windowing.js +118 -0
- package/dist/icons-all.js +1 -1
- package/dist/icons.d.ts +4 -0
- package/dist/index.d.ts +30 -5
- package/dist/index.js +310 -264
- package/dist/layout/tree.js +19 -15
- package/dist/layout/useLayout.d.ts +2 -0
- package/dist/layout/useLayout.js +5 -1
- package/dist/layout/useWorkspaces.d.ts +52 -0
- package/dist/layout/useWorkspaces.js +140 -0
- package/dist/{chunks/backdrop-Dkf2vM81.js → theme/backdrop.js} +5 -5
- package/dist/theme/config.js +25 -0
- package/dist/theme/define.js +61 -0
- package/dist/{chunks/palette-Co8tSASo.js → theme/palette.js} +2 -2
- package/dist/theme/presets.js +239 -0
- package/dist/theme/studio.js +134 -0
- package/dist/theme/tokens.js +63 -0
- package/dist/theme/useTheme.d.ts +3 -2
- package/dist/theme/useTheme.js +325 -0
- package/package.json +8 -1
- package/src/component-names.ts +5 -1
- package/src/components/AppShellContextNav.vue +44 -0
- package/src/components/ChartRangeSelector.vue +120 -0
- package/src/components/IconCloseButton.vue +21 -0
- package/src/components/LayoutCanvas.vue +3 -0
- package/src/components/LayoutNode.vue +37 -38
- package/src/components/LpActivityLine.vue +4 -2
- package/src/components/LpAddressInput.vue +3 -3
- package/src/components/LpAppShell.vue +362 -24
- package/src/components/LpAutocomplete.vue +18 -30
- package/src/components/LpBottomNav.vue +9 -1
- package/src/components/LpBreadcrumbs.vue +2 -1
- package/src/components/LpButton.vue +11 -4
- package/src/components/LpChart.vue +336 -37
- package/src/components/LpCheckbox.vue +43 -9
- package/src/components/LpCodeBlock.vue +17 -23
- package/src/components/LpCollapse.vue +5 -4
- package/src/components/LpColorPicker.vue +8 -9
- package/src/components/LpCommandPalette.vue +133 -50
- package/src/components/LpContextMenu.vue +15 -13
- package/src/components/LpCountdown.vue +2 -1
- package/src/components/LpDataList.vue +13 -1
- package/src/components/LpDatePicker.vue +5 -17
- package/src/components/LpDateRangePicker.vue +5 -16
- package/src/components/LpDock.vue +25 -16
- package/src/components/LpDrawer.vue +70 -61
- package/src/components/LpDropdownMenu.vue +6 -10
- package/src/components/LpDropzone.vue +12 -7
- package/src/components/LpEditable.vue +6 -2
- package/src/components/LpFileTree.vue +507 -66
- package/src/components/LpFileTreeNode.vue +106 -5
- package/src/components/LpFormField.vue +1 -1
- package/src/components/LpFrame.vue +33 -13
- package/src/components/LpHoverCard.vue +30 -5
- package/src/components/LpIcon.vue +6 -2
- package/src/components/LpIdenticon.vue +2 -1
- package/src/components/LpImageEditor.vue +5 -2
- package/src/components/LpInput.vue +15 -23
- package/src/components/LpInspector.vue +197 -0
- package/src/components/LpLightbox.vue +74 -29
- package/src/components/LpLogInspector.vue +85 -0
- package/src/components/LpLogViewer.vue +239 -29
- package/src/components/LpMapPicker.vue +2 -1
- package/src/components/LpMasonry.vue +8 -5
- package/src/components/LpModal.vue +12 -12
- package/src/components/LpModalNav.vue +2 -21
- package/src/components/LpNumberField.vue +6 -15
- package/src/components/LpOtpInput.vue +2 -2
- package/src/components/LpPagination.vue +5 -3
- package/src/components/LpPhoneInput.vue +8 -19
- package/src/components/LpPie.vue +25 -23
- package/src/components/LpPipeline.vue +14 -1
- package/src/components/LpPopover.vue +23 -2
- package/src/components/LpProgress.vue +2 -1
- package/src/components/LpRadioGroup.vue +2 -2
- package/src/components/LpRangeSlider.vue +5 -6
- package/src/components/LpRevealOnScroll.vue +1 -1
- package/src/components/LpScrollArea.vue +28 -11
- package/src/components/LpSecretField.vue +2 -1
- package/src/components/LpSegmented.vue +6 -8
- package/src/components/LpSelect.vue +54 -24
- package/src/components/LpShaderBackdrop.vue +12 -9
- package/src/components/LpShift.vue +18 -15
- package/src/components/LpSidebar.vue +77 -74
- package/src/components/LpSidebarNav.vue +3 -2
- package/src/components/LpSidebarRow.vue +2 -1
- package/src/components/LpSlider.vue +5 -6
- package/src/components/LpSpotlight.vue +2 -1
- package/src/components/LpSwitch.vue +5 -3
- package/src/components/LpTable.vue +609 -93
- package/src/components/LpTableFilter.vue +1 -1
- package/src/components/LpTableOfContents.vue +16 -9
- package/src/components/LpTabs.vue +2 -1
- package/src/components/LpTagsInput.vue +12 -19
- package/src/components/LpTextarea.vue +5 -11
- package/src/components/LpThemeProvider.vue +29 -13
- package/src/components/LpTimeField.vue +4 -7
- package/src/components/LpToaster.vue +7 -6
- package/src/components/LpTooltip.vue +62 -18
- package/src/components/LpTopologyCanvas.vue +567 -42
- package/src/components/LpTour.vue +7 -5
- package/src/components/LpTruncate.vue +4 -3
- package/src/components/LpTypewriter.vue +2 -1
- package/src/components/LpVideoBackdrop.vue +11 -13
- package/src/components/LpWindow.vue +373 -0
- package/src/components/LpWorkspaceSwitcher.vue +116 -0
- package/src/components/PickerField.vue +2 -2
- package/src/components/SliderRail.vue +10 -0
- package/src/components/address.ts +3 -1
- package/src/components/appShell.ts +74 -0
- package/src/components/calendar.ts +12 -5
- package/src/components/chart.ts +27 -3
- package/src/components/chartWindow.ts +198 -0
- package/src/components/color.ts +2 -1
- package/src/components/commandPalette.ts +66 -5
- package/src/components/controlSize.ts +6 -0
- package/src/components/dropdown.ts +3 -0
- package/src/components/exportData.ts +33 -18
- package/src/components/fileTree.ts +215 -0
- package/src/components/identicon.ts +4 -2
- package/src/components/logTools.ts +298 -0
- package/src/components/meter.ts +2 -1
- package/src/components/pipeline.ts +6 -0
- package/src/components/relativeTime.ts +2 -1
- package/src/components/reveal.ts +3 -1
- package/src/components/select.ts +14 -0
- package/src/components/sidebar.ts +1 -0
- package/src/components/tableFeatures.ts +149 -0
- package/src/components/topologyGraph.ts +655 -0
- package/src/components/tour.ts +5 -3
- package/src/components/videoBackdrop.ts +7 -6
- package/src/composables/clamp.ts +2 -0
- package/src/composables/devWarn.ts +19 -0
- package/src/composables/easing.ts +37 -12
- package/src/composables/overlayHistory.ts +24 -0
- package/src/composables/pointerDrag.ts +54 -0
- package/src/composables/propCheck.ts +90 -0
- package/src/composables/realm.ts +25 -0
- package/src/composables/scroll.ts +4 -2
- package/src/composables/scrollMemory.ts +56 -14
- package/src/composables/spatialNav.ts +2 -1
- package/src/composables/textEntry.ts +33 -0
- package/src/composables/useAsyncTask.ts +6 -0
- package/src/composables/useChartSync.ts +52 -0
- package/src/composables/useCloseGuard.ts +22 -10
- package/src/composables/useCommands.ts +123 -0
- package/src/composables/useField.ts +41 -2
- package/src/composables/useFitScale.ts +4 -1
- package/src/composables/useFormDraft.ts +38 -14
- package/src/composables/useHintSystem.ts +2 -2
- package/src/composables/useHotkeys.ts +19 -48
- package/src/composables/useInView.ts +2 -1
- package/src/composables/useInputFilter.ts +8 -5
- package/src/composables/useInputMask.ts +8 -3
- package/src/composables/useLinkedView.ts +222 -0
- package/src/composables/useOptimisticToggle.ts +7 -1
- package/src/composables/useOverlayHistory.ts +20 -0
- package/src/composables/usePaintSelect.ts +20 -14
- package/src/composables/usePaletteCommands.ts +13 -0
- package/src/composables/usePersisted.ts +10 -0
- package/src/composables/usePillTransition.ts +9 -6
- package/src/composables/useResizeObserver.ts +2 -1
- package/src/composables/useReveal.ts +2 -1
- package/src/composables/useRovingFocus.ts +11 -14
- package/src/composables/useScramble.ts +12 -1
- package/src/composables/useShift.ts +8 -6
- package/src/composables/useTilt.ts +2 -1
- package/src/composables/useTween.ts +10 -5
- package/src/composables/useView.ts +17 -3
- package/src/composables/useZoomPan.ts +2 -5
- package/src/composables/windowing.ts +190 -0
- package/src/icons.ts +27 -6
- package/src/index.ts +41 -4
- package/src/kit-icons.ts +1 -1
- package/src/layout/tree.ts +31 -16
- package/src/layout/useLayout.ts +6 -0
- package/src/layout/useWorkspaces.ts +234 -0
- package/src/nuxt.ts +9 -1
- package/src/runtime/propCheck.plugin.ts +10 -0
- package/src/theme/studio.ts +7 -5
- package/src/theme/useTheme.ts +89 -15
- package/src/tokens/tokens.css +8 -1
- package/dist/assets/LpTabs-CJ0rYQbx.css +0 -18
- package/dist/chunks/LpAppShell-Dgejipzz.js +0 -319
- package/dist/chunks/LpFileTree-CooHinsC.js +0 -425
- package/dist/chunks/LpThemeProvider-8MG6yqU9.js +0 -640
- package/dist/chunks/LpTopologyCanvas-B1gIbS0n.js +0 -298
|
@@ -8,7 +8,9 @@ import { useLabels } from "./useLpConfig"
|
|
|
8
8
|
* - `true`: there is something unsaved. Closing asks "Discard changes?" through
|
|
9
9
|
* the kit's confirm, and leaving the page asks the browser's own question.
|
|
10
10
|
* - a function: the app asks its own question (or saves first) and answers
|
|
11
|
-
* whether the window may close.
|
|
11
|
+
* whether the window may close. It covers the window's own ways out only:
|
|
12
|
+
* a browser cannot wait for it, so closing the tab or reloading goes
|
|
13
|
+
* unguarded. Only `true` raises the browser's question.
|
|
12
14
|
* - `false` / unset: nothing to lose, the window closes as always.
|
|
13
15
|
*
|
|
14
16
|
* Usually bound straight to a form's state: `:guard="form.dirty"`.
|
|
@@ -39,6 +41,13 @@ export function useCloseGuard(
|
|
|
39
41
|
)
|
|
40
42
|
|
|
41
43
|
let asking = false
|
|
44
|
+
/*
|
|
45
|
+
* Counts every open and close. An answer takes as long as the person does,
|
|
46
|
+
* and meanwhile the window can close another way and open again: a "yes"
|
|
47
|
+
* given about that earlier window must not close the new one.
|
|
48
|
+
*/
|
|
49
|
+
let session = 0
|
|
50
|
+
watch(() => !!toValue(open), () => (session += 1), { flush: "sync" })
|
|
42
51
|
|
|
43
52
|
/** Whether the window may close now. Asks at most once at a time. */
|
|
44
53
|
async function allowClose(): Promise<boolean> {
|
|
@@ -46,16 +55,19 @@ export function useCloseGuard(
|
|
|
46
55
|
if (!current) return true
|
|
47
56
|
if (asking) return false
|
|
48
57
|
asking = true
|
|
58
|
+
const mine = session
|
|
49
59
|
try {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
60
|
+
const allowed = await (typeof current === "function"
|
|
61
|
+
? current()
|
|
62
|
+
: confirm({
|
|
63
|
+
title: labels.value.title,
|
|
64
|
+
description: labels.value.description,
|
|
65
|
+
danger: true,
|
|
66
|
+
icon: "lucide:triangle-alert",
|
|
67
|
+
confirmLabel: labels.value.discard,
|
|
68
|
+
cancelLabel: labels.value.keep,
|
|
69
|
+
}))
|
|
70
|
+
return allowed && mine === session
|
|
59
71
|
} finally {
|
|
60
72
|
asking = false
|
|
61
73
|
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { computed, toValue, type MaybeRefOrGetter } from "vue"
|
|
2
|
+
import type { Command } from "../components/LpCommandPalette.vue"
|
|
3
|
+
import type { ContextMenuItemDef } from "../components/LpContextMenu.vue"
|
|
4
|
+
import { parseCombo, useHotkeys, type HotkeyBinding, type ShortcutGroup, type UseHotkeysOptions } from "./useHotkeys"
|
|
5
|
+
import { usePaletteCommands, type PaletteScope } from "./usePaletteCommands"
|
|
6
|
+
|
|
7
|
+
/*
|
|
8
|
+
* One definition of an application command, read by every place that offers it.
|
|
9
|
+
*
|
|
10
|
+
* Without this an action is written three times: a `useHotkeys` binding, a
|
|
11
|
+
* palette command, a menu item, and the three drift. This adds no registry of
|
|
12
|
+
* its own: the palette's registry (`usePaletteCommands`) lists the command and
|
|
13
|
+
* the hotkey registry (`useHotkeys`) binds it and feeds `activeShortcuts`, so
|
|
14
|
+
* LpShortcutsDialog lists it while it is mounted. A menu takes `menuItems`.
|
|
15
|
+
*
|
|
16
|
+
* const { menuItems } = useCommands(() => [{
|
|
17
|
+
* id: "server/restart", label: "Restart", group: "Server",
|
|
18
|
+
* shortcut: "Ctrl+R", disabled: !canRestart.value, run: restart,
|
|
19
|
+
* }])
|
|
20
|
+
*
|
|
21
|
+
* The commands are read when asked for, so availability written as a plain
|
|
22
|
+
* expression in the getter stays live.
|
|
23
|
+
*/
|
|
24
|
+
export interface AppCommand {
|
|
25
|
+
/** Stable: the palette keeps recents and pins by it. */
|
|
26
|
+
id: string
|
|
27
|
+
label: string
|
|
28
|
+
/** Section in the palette and in the key reference. */
|
|
29
|
+
group?: string
|
|
30
|
+
description?: string
|
|
31
|
+
icon?: string
|
|
32
|
+
keywords?: string[]
|
|
33
|
+
/**
|
|
34
|
+
* Written as it reads: "Ctrl+K", "Shift+Alt+N", or spaces for a sequence,
|
|
35
|
+
* "G I". Binds the key and labels it in the palette, the menu and the reference.
|
|
36
|
+
*/
|
|
37
|
+
shortcut?: string
|
|
38
|
+
/** Listed but not runnable: greyed in the palette and the menu, the key does nothing. */
|
|
39
|
+
disabled?: boolean
|
|
40
|
+
/** Gone everywhere, key included. For what this user or this page cannot do at all. */
|
|
41
|
+
hidden?: boolean
|
|
42
|
+
/** Marked as dangerous in a menu; the palette has no such mark. */
|
|
43
|
+
danger?: boolean
|
|
44
|
+
/** The key also works while a text field has focus. */
|
|
45
|
+
allowInInput?: boolean
|
|
46
|
+
/** The key also works while an overlay owns the keyboard. */
|
|
47
|
+
overLayers?: boolean
|
|
48
|
+
run: () => unknown | Promise<unknown>
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const DEFAULT_GROUP = "Commands"
|
|
52
|
+
|
|
53
|
+
const available = (commands: readonly AppCommand[]) => commands.filter((command) => !command.hidden)
|
|
54
|
+
|
|
55
|
+
/** What the palette lists for a command. */
|
|
56
|
+
export function commandToPalette(command: AppCommand): Command {
|
|
57
|
+
const { id, label, group, description, icon, keywords, shortcut, disabled, run } = command
|
|
58
|
+
return { id, label, group, description, icon, keywords, shortcut, disabled, onSelect: run }
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** What a menu shows for a command: LpContextMenu and LpDropdownMenu take these. */
|
|
62
|
+
export function commandToMenuItem(command: AppCommand): ContextMenuItemDef {
|
|
63
|
+
const { label, icon, shortcut, disabled, danger, run } = command
|
|
64
|
+
return { label, icon, shortcut, disabled, danger, onSelect: () => void run() }
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** The binding for a command, or null when it has no key. */
|
|
68
|
+
export function commandToHotkey(command: AppCommand): HotkeyBinding | null {
|
|
69
|
+
const shortcut = command.shortcut?.trim()
|
|
70
|
+
if (!shortcut) return null
|
|
71
|
+
const steps = shortcut.split(/\s+/).map(parseCombo)
|
|
72
|
+
const keys = steps.length > 1 ? { sequence: steps } : steps[0]
|
|
73
|
+
return {
|
|
74
|
+
...keys,
|
|
75
|
+
allowInInput: command.allowInInput,
|
|
76
|
+
overLayers: command.overLayers,
|
|
77
|
+
help: { group: command.group ?? DEFAULT_GROUP, label: command.label, combo: shortcut },
|
|
78
|
+
// A disabled command leaves the key alone, for the page or the browser.
|
|
79
|
+
handler: () => {
|
|
80
|
+
if (command.disabled) return false
|
|
81
|
+
void command.run()
|
|
82
|
+
},
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** The key reference of these commands alone, in LpShortcutsDialog's shape. */
|
|
87
|
+
export function commandShortcuts(commands: readonly AppCommand[]): ShortcutGroup[] {
|
|
88
|
+
const groups = new Map<string, ShortcutGroup["entries"]>()
|
|
89
|
+
for (const command of available(commands)) {
|
|
90
|
+
if (!command.shortcut) continue
|
|
91
|
+
const title = command.group ?? DEFAULT_GROUP
|
|
92
|
+
const entries = groups.get(title) ?? []
|
|
93
|
+
entries.push({ combo: command.shortcut, label: command.label })
|
|
94
|
+
groups.set(title, entries)
|
|
95
|
+
}
|
|
96
|
+
return [...groups].map(([title, entries]) => ({ title, entries }))
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export interface UseCommandsOptions extends Pick<UseHotkeysOptions, "enabled" | "priority" | "scope"> {
|
|
100
|
+
/** The palette scope to list in. Defaults to the one this component sits in. */
|
|
101
|
+
palette?: PaletteScope
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export function useCommands(commands: MaybeRefOrGetter<readonly AppCommand[]>, options: UseCommandsOptions = {}) {
|
|
105
|
+
const { palette, ...hotkeys } = options
|
|
106
|
+
const current = computed(() => available(toValue(commands)))
|
|
107
|
+
|
|
108
|
+
usePaletteCommands(() => current.value.map(commandToPalette), { scope: palette })
|
|
109
|
+
useHotkeys(() => current.value.flatMap((command) => commandToHotkey(command) ?? []), hotkeys)
|
|
110
|
+
|
|
111
|
+
return {
|
|
112
|
+
commands: current,
|
|
113
|
+
menuItems: computed(() => current.value.map(commandToMenuItem)),
|
|
114
|
+
shortcuts: computed(() => commandShortcuts(current.value)),
|
|
115
|
+
/** Runs a command by id, unless it is disabled or hidden. Returns whether it ran. */
|
|
116
|
+
run(id: string): boolean {
|
|
117
|
+
const command = current.value.find((candidate) => candidate.id === id)
|
|
118
|
+
if (!command || command.disabled) return false
|
|
119
|
+
void command.run()
|
|
120
|
+
return true
|
|
121
|
+
},
|
|
122
|
+
}
|
|
123
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { computed, inject, onScopeDispose, provide, useId, type ComputedRef, type InjectionKey } from "vue"
|
|
1
|
+
import { computed, inject, onScopeDispose, provide, useAttrs, useId, type ComputedRef, type InjectionKey } from "vue"
|
|
2
2
|
import type { FieldNoticeOptions } from "./useFieldNotice"
|
|
3
|
+
import { isElement } from "./useView"
|
|
3
4
|
|
|
4
5
|
/*
|
|
5
6
|
* What a form field tells the control inside it: the id its label points at,
|
|
@@ -39,6 +40,22 @@ export function fieldMessageId(id: string): string {
|
|
|
39
40
|
return `${id}-message`
|
|
40
41
|
}
|
|
41
42
|
|
|
43
|
+
/**
|
|
44
|
+
* The `aria-describedby` of a control: the consumer's own ids, the field's and
|
|
45
|
+
* whatever the control adds, each once. A template's explicit binding replaces
|
|
46
|
+
* what `v-bind` passed, undefined included, so every control merges here
|
|
47
|
+
* instead of dropping the consumer's description.
|
|
48
|
+
*/
|
|
49
|
+
export function mergeDescribedBy(...ids: unknown[]): string | undefined {
|
|
50
|
+
const all = ids.flatMap((id) => (typeof id === "string" ? id.split(/\s+/) : [])).filter(Boolean)
|
|
51
|
+
return [...new Set(all)].join(" ") || undefined
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Is a boolean attribute that arrived through `$attrs` on? The same test Vue renders it by. */
|
|
55
|
+
export function isAttrOn(value: unknown): boolean {
|
|
56
|
+
return !!value || value === ""
|
|
57
|
+
}
|
|
58
|
+
|
|
42
59
|
export interface FieldControlState {
|
|
43
60
|
/** The control wraps itself in its own LpFormField (it has a label, hint or error prop). */
|
|
44
61
|
wrapped: boolean
|
|
@@ -98,7 +115,7 @@ export function useFieldControl(
|
|
|
98
115
|
*/
|
|
99
116
|
export function focusLeft(event: FocusEvent): boolean {
|
|
100
117
|
const next = event.relatedTarget
|
|
101
|
-
return !(next
|
|
118
|
+
return !(isElement(next) && (event.currentTarget as Node | null)?.contains(next))
|
|
102
119
|
}
|
|
103
120
|
|
|
104
121
|
/** Trigger and portalled content share a boundary for the control's public blur. */
|
|
@@ -125,3 +142,25 @@ export function useFieldBlur(blur: (event: FocusEvent) => void) {
|
|
|
125
142
|
onScopeDispose(() => cancelPending?.())
|
|
126
143
|
return { partId, onFocusOut }
|
|
127
144
|
}
|
|
145
|
+
|
|
146
|
+
/** What a control hands the FieldWrapper around it: its id, its texts, and the classes it takes from the app. */
|
|
147
|
+
export function fieldWrapperBinds(
|
|
148
|
+
wrapped: boolean,
|
|
149
|
+
field: { id?: string },
|
|
150
|
+
props: { label?: string; hint?: string; error?: string; required?: boolean },
|
|
151
|
+
attrs: Record<string, unknown>,
|
|
152
|
+
) {
|
|
153
|
+
const { label, hint, error, required } = props
|
|
154
|
+
return { wrapped, id: field.id, label, hint, error, required, class: attrs.class, style: attrs.style }
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/** The state of a control that takes its id from the app and draws no wrapper of its own. */
|
|
158
|
+
export function useAttrsField(state: () => { invalid?: boolean; disabled?: boolean }) {
|
|
159
|
+
const attrs = useAttrs()
|
|
160
|
+
const field = useFieldControl(() => ({
|
|
161
|
+
wrapped: false,
|
|
162
|
+
id: typeof attrs.id === "string" ? attrs.id : undefined,
|
|
163
|
+
...state(),
|
|
164
|
+
}))
|
|
165
|
+
return { attrs, field }
|
|
166
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { nodeWindow } from "./realm"
|
|
1
2
|
import { onBeforeUnmount, onMounted, ref, watch, type Ref } from "vue"
|
|
2
3
|
|
|
3
4
|
/*
|
|
@@ -29,7 +30,9 @@ export function useFitScale(
|
|
|
29
30
|
function observe() {
|
|
30
31
|
observer?.disconnect()
|
|
31
32
|
if (typeof ResizeObserver === "undefined") return
|
|
32
|
-
|
|
33
|
+
const el = box.value ?? content.value
|
|
34
|
+
if (!el) return measure()
|
|
35
|
+
observer = new (nodeWindow(el).ResizeObserver)(measure)
|
|
33
36
|
if (box.value) observer.observe(box.value)
|
|
34
37
|
if (content.value) observer.observe(content.value)
|
|
35
38
|
measure()
|
|
@@ -67,6 +67,12 @@ export interface UseFormDraftOptions<T> {
|
|
|
67
67
|
maxAgeMs?: number
|
|
68
68
|
/** Skip the write without tearing the composable out of the component. */
|
|
69
69
|
disabled?: MaybeRefOrGetter<boolean>
|
|
70
|
+
/**
|
|
71
|
+
* Accept a stored value or reject it. The envelope's version follows the
|
|
72
|
+
* kit, not this form: a draft written before the form changed shape needs
|
|
73
|
+
* this to be turned away. A rejected draft reads as no draft.
|
|
74
|
+
*/
|
|
75
|
+
validate?: (value: unknown) => value is T
|
|
70
76
|
}
|
|
71
77
|
|
|
72
78
|
export interface UseFormDraft<T> {
|
|
@@ -86,8 +92,13 @@ export interface UseFormDraft<T> {
|
|
|
86
92
|
* what to do with each field, because only it knows the form's shape.
|
|
87
93
|
*/
|
|
88
94
|
read: () => T | null
|
|
89
|
-
/**
|
|
90
|
-
|
|
95
|
+
/**
|
|
96
|
+
* Forget the draft. Call after applying it, and after a successful save.
|
|
97
|
+
* With no argument it acts on the key as it is now; a callback that may
|
|
98
|
+
* outlive the subject (an awaited save) passes the key it started under, so
|
|
99
|
+
* it cannot delete the draft of whatever the form moved on to.
|
|
100
|
+
*/
|
|
101
|
+
discard: (key?: string) => void
|
|
91
102
|
/** Write now, ignoring `dirty` and a pending draft. For "save and come back to this later". */
|
|
92
103
|
save: () => void
|
|
93
104
|
}
|
|
@@ -128,19 +139,28 @@ export function useFormDraft<T>(options: UseFormDraftOptions<T>): UseFormDraft<T
|
|
|
128
139
|
const savedAt = ref<string | null>(null)
|
|
129
140
|
const maxAge = options.maxAgeMs ?? WEEK_MS
|
|
130
141
|
|
|
142
|
+
function normalizeKey(key: unknown): string {
|
|
143
|
+
return String(key || "").trim()
|
|
144
|
+
}
|
|
145
|
+
|
|
131
146
|
function currentKey(): string {
|
|
132
|
-
return
|
|
147
|
+
return normalizeKey(toValue(options.key))
|
|
133
148
|
}
|
|
134
149
|
|
|
135
150
|
// An envelope still worth offering, or null. No side effects: the key watcher
|
|
136
151
|
// only looks, and `read` decides what to clear.
|
|
152
|
+
//
|
|
153
|
+
// Only this composable writes these, so a missing value or an unreadable
|
|
154
|
+
// stamp is damage rather than a draft of unknown age: offering it would make
|
|
155
|
+
// it immortal, since its age could never pass `maxAge`. A stamp from the
|
|
156
|
+
// future is measured the same way as one from the past, so a clock corrected
|
|
157
|
+
// by minutes keeps the draft and a stamp years ahead cannot outlive `maxAge`.
|
|
137
158
|
function fresh(parsed: DraftEnvelope<T> | null): boolean {
|
|
138
|
-
if (!parsed || parsed.version !== ENVELOPE_VERSION) return false
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
return !(Date.now() - Date.parse(parsed.savedAt) > maxAge)
|
|
159
|
+
if (!parsed || parsed.version !== ENVELOPE_VERSION || !("value" in Object(parsed))) return false
|
|
160
|
+
const stamp = typeof parsed.savedAt === "string" ? Date.parse(parsed.savedAt) : Number.NaN
|
|
161
|
+
if (Number.isNaN(stamp)) return false
|
|
162
|
+
if (options.validate && !options.validate(parsed.value)) return false
|
|
163
|
+
return maxAge <= 0 || Math.abs(Date.now() - stamp) <= maxAge
|
|
144
164
|
}
|
|
145
165
|
|
|
146
166
|
function read(): T | null {
|
|
@@ -178,11 +198,15 @@ export function useFormDraft<T>(options: UseFormDraftOptions<T>): UseFormDraft<T
|
|
|
178
198
|
)
|
|
179
199
|
}
|
|
180
200
|
|
|
181
|
-
function discard() {
|
|
182
|
-
const
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
if (
|
|
201
|
+
function discard(key?: string) {
|
|
202
|
+
const current = currentKey()
|
|
203
|
+
// Not a string when bound straight to an event: `@click="draft.discard"`.
|
|
204
|
+
const target = typeof key === "string" ? normalizeKey(key) : current
|
|
205
|
+
if (target === current) {
|
|
206
|
+
hasDraft.value = false
|
|
207
|
+
savedAt.value = null
|
|
208
|
+
}
|
|
209
|
+
if (target) store.remove(target)
|
|
186
210
|
}
|
|
187
211
|
|
|
188
212
|
function save() {
|
|
@@ -2,6 +2,7 @@ import { computed, inject, onBeforeUnmount, provide, reactive, shallowRef, watch
|
|
|
2
2
|
import type { HintNote } from "../components/LpHintLayer.vue"
|
|
3
3
|
import type { TourContext, TourStep } from "../components/LpTour.vue"
|
|
4
4
|
import { anyModalOpen } from "../components/modalDepth"
|
|
5
|
+
import { isTextEntry } from "./textEntry"
|
|
5
6
|
import { hints } from "./useHints"
|
|
6
7
|
|
|
7
8
|
/*
|
|
@@ -355,8 +356,7 @@ export function hintSummary(
|
|
|
355
356
|
}
|
|
356
357
|
|
|
357
358
|
function typing(): boolean {
|
|
358
|
-
|
|
359
|
-
return el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement || (el instanceof HTMLElement && el.isContentEditable)
|
|
359
|
+
return isTextEntry(document.activeElement, { inputType: () => true })
|
|
360
360
|
}
|
|
361
361
|
|
|
362
362
|
export function createHintSystem(options: HintSystemOptions) {
|
|
@@ -9,6 +9,9 @@ import {
|
|
|
9
9
|
type MaybeRefOrGetter,
|
|
10
10
|
} from "vue"
|
|
11
11
|
import { topModalElement } from "../components/modalDepth"
|
|
12
|
+
import { isDev } from "./devWarn"
|
|
13
|
+
import { isNode } from "./realm"
|
|
14
|
+
import { isTextEntry } from "./textEntry"
|
|
12
15
|
|
|
13
16
|
/*
|
|
14
17
|
* One keydown listener over a registry of bindings, so a shortcut is declared
|
|
@@ -29,7 +32,9 @@ import { topModalElement } from "../components/modalDepth"
|
|
|
29
32
|
* except for the few that mean something in a field (Escape, a palette).
|
|
30
33
|
*
|
|
31
34
|
* Modifier note: Ctrl and Meta are one modifier here, since macOS binds ⌘ where
|
|
32
|
-
* the rest bind Ctrl. Label the difference in the UI, not in the binding.
|
|
35
|
+
* the rest bind Ctrl. Label the difference in the UI, not in the binding. These
|
|
36
|
+
* are cross-platform commands, not a model of the keyboard: Ctrl+Meta+K apart
|
|
37
|
+
* from Ctrl+K cannot be written.
|
|
33
38
|
*
|
|
34
39
|
* Sequences ("g i", as on GitHub and Gmail) are bindings with `sequence`. A key
|
|
35
40
|
* that starts a sequence is held while the next one is awaited: if it
|
|
@@ -162,31 +167,6 @@ export function appleModifierLabel(key: string, apple = isAppleKeyboard): string
|
|
|
162
167
|
return key
|
|
163
168
|
}
|
|
164
169
|
|
|
165
|
-
const TEXT_INPUT_TYPES = new Set([
|
|
166
|
-
"text",
|
|
167
|
-
"search",
|
|
168
|
-
"email",
|
|
169
|
-
"number",
|
|
170
|
-
"password",
|
|
171
|
-
"tel",
|
|
172
|
-
"url",
|
|
173
|
-
])
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
* Whether the event lands in something the user is typing into. Checked off the
|
|
177
|
-
* event target rather than `document.activeElement` so it stays right inside a
|
|
178
|
-
* dialog's focus trap.
|
|
179
|
-
*/
|
|
180
|
-
function isTextEntry(target: EventTarget | null): boolean {
|
|
181
|
-
if (!(target instanceof HTMLElement)) return false
|
|
182
|
-
if (target.isContentEditable) return true
|
|
183
|
-
if (target instanceof HTMLTextAreaElement) return true
|
|
184
|
-
if (target instanceof HTMLInputElement) {
|
|
185
|
-
return TEXT_INPUT_TYPES.has(target.type)
|
|
186
|
-
}
|
|
187
|
-
return false
|
|
188
|
-
}
|
|
189
|
-
|
|
190
170
|
const MODIFIER_KEYS = new Set(["control", "meta", "shift", "alt"])
|
|
191
171
|
|
|
192
172
|
type KeyLike = Pick<KeyboardEvent, "key" | "code" | "ctrlKey" | "metaKey" | "shiftKey" | "altKey">
|
|
@@ -325,12 +305,13 @@ const mounted = state.mounted
|
|
|
325
305
|
function inScope(target: EventTarget | null, scope: MountedHotkeys["scope"]): boolean {
|
|
326
306
|
const el = toValue(scope)
|
|
327
307
|
if (!el) return true
|
|
328
|
-
|
|
329
|
-
return !!node && (el === node || el.contains(node))
|
|
308
|
+
return isNode(target) && (el === target || el.contains(target))
|
|
330
309
|
}
|
|
331
310
|
|
|
332
|
-
|
|
333
|
-
|
|
311
|
+
/* The layer on top in the document the key came from: a frame has its own. */
|
|
312
|
+
function topLayer(origin: EventTarget | null): Element | null {
|
|
313
|
+
const doc = isNode(origin) ? (origin.ownerDocument ?? document) : document
|
|
314
|
+
const layers = doc.querySelectorAll("[data-dismissable-layer]")
|
|
334
315
|
return layers[layers.length - 1] ?? null
|
|
335
316
|
}
|
|
336
317
|
|
|
@@ -364,7 +345,7 @@ function snapshot(event: KeyboardEvent): KeyLike {
|
|
|
364
345
|
|
|
365
346
|
function eligible(event: KeyboardEvent): HotkeyBinding[] {
|
|
366
347
|
const inTextEntry = isTextEntry(event.target)
|
|
367
|
-
const blocker = event.key === "Escape" ? topLayer() : topModalElement()
|
|
348
|
+
const blocker = event.key === "Escape" ? topLayer(event.target) : topModalElement()
|
|
368
349
|
const entries = [...mounted].sort(
|
|
369
350
|
(a, b) => Number(toValue(b.priority) || 0) - Number(toValue(a.priority) || 0) || b.order - a.order,
|
|
370
351
|
)
|
|
@@ -407,6 +388,9 @@ function flushHeld() {
|
|
|
407
388
|
function onKeydown(event: KeyboardEvent) {
|
|
408
389
|
if (event.isComposing || event.defaultPrevented) return
|
|
409
390
|
if (pressed.length && MODIFIER_KEYS.has(event.key.toLowerCase())) return
|
|
391
|
+
// A key held down is one press: its auto-repeat must not end the wait, or
|
|
392
|
+
// complete a "g g" nobody typed.
|
|
393
|
+
if (pressed.length && event.repeat) return
|
|
410
394
|
if (pressed.length && event.key === "Escape") {
|
|
411
395
|
resetSequence()
|
|
412
396
|
}
|
|
@@ -463,7 +447,7 @@ export function useHotkeys(
|
|
|
463
447
|
order: ++state.order,
|
|
464
448
|
host: () => {
|
|
465
449
|
const el = instance?.vnode.el
|
|
466
|
-
return el
|
|
450
|
+
return isNode(el) ? el : null
|
|
467
451
|
},
|
|
468
452
|
}
|
|
469
453
|
onMounted(() => {
|
|
@@ -477,11 +461,13 @@ export function useHotkeys(
|
|
|
477
461
|
})
|
|
478
462
|
onBeforeUnmount(() => {
|
|
479
463
|
mounted.delete(entry)
|
|
464
|
+
// What is held may be the handler of the component going away; a sequence
|
|
465
|
+
// waits for up to its timeout, and must not run into a dead component.
|
|
466
|
+
resetSequence()
|
|
480
467
|
if (!mounted.size && state.listening) {
|
|
481
468
|
window.removeEventListener("keydown", onKeydown)
|
|
482
469
|
window.removeEventListener("blur", resetSequence)
|
|
483
470
|
state.listening = false
|
|
484
|
-
resetSequence()
|
|
485
471
|
}
|
|
486
472
|
})
|
|
487
473
|
}
|
|
@@ -576,21 +562,6 @@ export const hotkeyConflicts = computed<HotkeyConflict[]>(() =>
|
|
|
576
562
|
|
|
577
563
|
const warned = new Set<string>()
|
|
578
564
|
|
|
579
|
-
declare const process: { env: { NODE_ENV?: string } }
|
|
580
|
-
|
|
581
|
-
/*
|
|
582
|
-
* Written as the literal `process.env.NODE_ENV` so the consumer's bundler
|
|
583
|
-
* replaces it (Vite and webpack both do for dependencies); where nothing
|
|
584
|
-
* replaces it and no `process` exists, the warning simply stays off.
|
|
585
|
-
*/
|
|
586
|
-
function isDev(): boolean {
|
|
587
|
-
try {
|
|
588
|
-
return process.env.NODE_ENV !== "production"
|
|
589
|
-
} catch {
|
|
590
|
-
return false
|
|
591
|
-
}
|
|
592
|
-
}
|
|
593
|
-
|
|
594
565
|
function warnConflicts() {
|
|
595
566
|
if (!isDev()) return
|
|
596
567
|
for (const conflict of hotkeyConflicts.value) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { nodeWindow } from "./realm"
|
|
1
2
|
import { onBeforeUnmount, ref, watch, type Ref } from "vue"
|
|
2
3
|
|
|
3
4
|
/*
|
|
@@ -40,7 +41,7 @@ export function useInView(options: { rootMargin?: string; threshold?: number } =
|
|
|
40
41
|
observer?.disconnect()
|
|
41
42
|
observer = null
|
|
42
43
|
if (!node || typeof IntersectionObserver === "undefined") return sync()
|
|
43
|
-
observer = new IntersectionObserver(
|
|
44
|
+
observer = new (nodeWindow(node).IntersectionObserver)(
|
|
44
45
|
(entries) => {
|
|
45
46
|
intersecting.value = entries.some((entry) => entry.isIntersecting)
|
|
46
47
|
sync()
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { computed, type MaybeRefOrGetter, toValue } from "vue"
|
|
2
|
+
import { isElement } from "./useView"
|
|
2
3
|
|
|
3
4
|
/*
|
|
4
5
|
* Cursor- and IME-safe input filtering + pattern validation for native <input>.
|
|
@@ -111,12 +112,14 @@ export function useInputFilter(options: UseInputFilterOptions = {}) {
|
|
|
111
112
|
function sanitize(target: EventTarget | null): boolean {
|
|
112
113
|
const re = restrict.value
|
|
113
114
|
if (!re) return false
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
115
|
+
// By tag: a field of an LpFrame is no instance of this window's classes.
|
|
116
|
+
if (!isElement(target) || !["INPUT", "TEXTAREA"].includes(target.tagName)) return false
|
|
117
|
+
const field = target as HTMLInputElement | HTMLTextAreaElement
|
|
118
|
+
const { text, caret } = stripDisallowed(field.value, re, field.selectionStart ?? field.value.length)
|
|
119
|
+
if (text === field.value) return false
|
|
120
|
+
field.value = text
|
|
118
121
|
try {
|
|
119
|
-
|
|
122
|
+
field.setSelectionRange(caret, caret)
|
|
120
123
|
} catch {
|
|
121
124
|
// Input types without a selection (number, email) cannot place a caret.
|
|
122
125
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { computed, toValue, type MaybeRefOrGetter } from "vue"
|
|
2
|
+
import { isElement } from "./useView"
|
|
2
3
|
|
|
3
4
|
/*
|
|
4
5
|
* Format-as-you-type for a native <input> without losing the caret.
|
|
@@ -193,6 +194,10 @@ export interface UseInputMaskOptions {
|
|
|
193
194
|
onChange?: (masked: string, raw: string, complete: boolean) => void
|
|
194
195
|
}
|
|
195
196
|
|
|
197
|
+
/* By tag: a field of an LpFrame is no instance of this window's classes. */
|
|
198
|
+
const isInput = (target: EventTarget | null): target is HTMLInputElement =>
|
|
199
|
+
isElement(target) && target.tagName === "INPUT"
|
|
200
|
+
|
|
196
201
|
/**
|
|
197
202
|
* Bind `onBeforeInput`, `onInput` and `onCompositionEnd` to the input, and show
|
|
198
203
|
* `format(model).masked` as its value.
|
|
@@ -224,7 +229,7 @@ export function useInputMask(options: UseInputMaskOptions) {
|
|
|
224
229
|
function onBeforeInput(event: InputEvent): void {
|
|
225
230
|
const s = spec.value
|
|
226
231
|
const el = event.target
|
|
227
|
-
if (!s || event.isComposing || !(el
|
|
232
|
+
if (!s || event.isComposing || !isInput(el)) return
|
|
228
233
|
const backward = event.inputType === "deleteContentBackward"
|
|
229
234
|
if (!backward && event.inputType !== "deleteContentForward") return
|
|
230
235
|
const start = el.selectionStart
|
|
@@ -242,12 +247,12 @@ export function useInputMask(options: UseInputMaskOptions) {
|
|
|
242
247
|
|
|
243
248
|
/** Attach to `input`. Composition is left alone until it ends. */
|
|
244
249
|
function onInput(event: Event): void {
|
|
245
|
-
if ((event as InputEvent).isComposing || !(event.target
|
|
250
|
+
if ((event as InputEvent).isComposing || !isInput(event.target)) return
|
|
246
251
|
reformat(event.target)
|
|
247
252
|
}
|
|
248
253
|
|
|
249
254
|
function onCompositionEnd(event: CompositionEvent): void {
|
|
250
|
-
if (event.target
|
|
255
|
+
if (isInput(event.target)) reformat(event.target)
|
|
251
256
|
}
|
|
252
257
|
|
|
253
258
|
return { active: computed(() => !!spec.value), format, onBeforeInput, onInput, onCompositionEnd }
|