@leavepulse/ui 0.77.3 → 0.78.1

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.
Files changed (621) hide show
  1. package/README.md +68 -0
  2. package/dist/assets/{LpCommandPalette-DOIZHw-g.css → LpCommandPalette-DDJKICKh.css} +19 -19
  3. package/dist/assets/{LpDock-Cbh0wQUv.css → LpDock-Dw82tWVD.css} +3 -3
  4. package/dist/assets/{LpDropzone-B_qRq1-R.css → LpDropzone-DNbh_NFJ.css} +10 -10
  5. package/dist/assets/{LpImageEditor-XM5bAziW.css → LpImageEditor-Bgu20XLs.css} +6 -6
  6. package/dist/assets/{LpTable-Bv-EcQs7.css → LpTable-CCk0ZHo7.css} +19 -19
  7. package/dist/assets/LpTabs-Bh7a-Bdl.css +18 -0
  8. package/dist/chunks/AppShellContextNav-C6Ho2mof.js +49 -0
  9. package/dist/chunks/ChartRangeSelector-HO0sMMz6.js +129 -0
  10. package/dist/chunks/{ContextMenuItems-BXumicbh.js → ContextMenuItems-DmaKSJVv.js} +1 -1
  11. package/dist/chunks/{DropzoneLinkField-C-9BCGJn.js → DropzoneLinkField-CLLhd3WB.js} +2 -2
  12. package/dist/chunks/FieldLeading-mr81aEAP.js +27 -0
  13. package/dist/chunks/{FieldWrapper-CORPzo9s.js → FieldWrapper-DnuMTrqW.js} +1 -1
  14. package/dist/chunks/IconCloseButton-COZEsa9u.js +29 -0
  15. package/dist/chunks/{LayoutCanvas-CNOAUk7D.js → LayoutCanvas-CZKOltfA.js} +1 -1
  16. package/dist/chunks/{LayoutNode-DF5BMN0J.js → LayoutNode-D2f7v683.js} +45 -45
  17. package/dist/chunks/{LpActionBar-BP1ld7-S.js → LpActionBar-BGMk5KoG.js} +3 -3
  18. package/dist/chunks/{LpActivityLine-CJvzrNpj.js → LpActivityLine-Ea-t5Vza.js} +4 -2
  19. package/dist/chunks/{LpAddressInput-E8KtwU7-.js → LpAddressInput-BSS49jpm.js} +12 -11
  20. package/dist/chunks/{LpAlert-n5XPAZfv.js → LpAlert-CjvTZIKF.js} +3 -3
  21. package/dist/chunks/LpAppShell-BKbYCHkx.js +601 -0
  22. package/dist/chunks/{LpAutocomplete-C-SpPfBG.js → LpAutocomplete-DkY6CSyD.js} +24 -42
  23. package/dist/chunks/{LpAvatar-Cg6Az3wz.js → LpAvatar-cQVsNk6F.js} +2 -2
  24. package/dist/chunks/{LpBadge-wUYLN4U9.js → LpBadge-D5QQdDQ_.js} +2 -2
  25. package/dist/chunks/{LpBottomNav-CbNQQPuL.js → LpBottomNav-zxLGGbjm.js} +9 -2
  26. package/dist/chunks/{LpBreadcrumbs-DPdbth-c.js → LpBreadcrumbs-CIIBsygI.js} +4 -3
  27. package/dist/chunks/{LpButton-CFb44IjC.js → LpButton-DSHioIfD.js} +5 -4
  28. package/dist/chunks/{LpCalendar-CuoWks-0.js → LpCalendar-D4-LVjfF.js} +1 -1
  29. package/dist/chunks/{LpCard-r13WRqox.js → LpCard-BPtYXwnT.js} +1 -1
  30. package/dist/chunks/{LpCheckbox-Cs4SHaHX.js → LpCheckbox-D6RuDW4X.js} +38 -16
  31. package/dist/chunks/{LpCodeBlock-DRC8VbXW.js → LpCodeBlock-DBqy4RLd.js} +19 -41
  32. package/dist/chunks/{LpCodeDisplay-CE9TxCA4.js → LpCodeDisplay-D3BUAhV1.js} +5 -5
  33. package/dist/chunks/{LpCollapse-CWS9M_lm.js → LpCollapse-DrAw5DBZ.js} +5 -4
  34. package/dist/chunks/{LpColorPicker-1y1QJHZR.js → LpColorPicker-COHzV68R.js} +11 -12
  35. package/dist/chunks/{LpCommandScope-CtUhJe8T.js → LpCommandScope-DRUvHiX7.js} +1 -1
  36. package/dist/chunks/{LpConfirmDialog-DlD45Bi_.js → LpConfirmDialog-CnrmzkuN.js} +3 -3
  37. package/dist/chunks/{LpConfirmHost-BIWjBLmI.js → LpConfirmHost-CwbObVGH.js} +1 -1
  38. package/dist/chunks/{LpContextMenu-rx2tCjwk.js → LpContextMenu-Bx_IhQDS.js} +17 -19
  39. package/dist/chunks/{LpContextSwitcher-Dwh6dyID.js → LpContextSwitcher-1C1tExdl.js} +2 -2
  40. package/dist/chunks/{LpCopyButton-xF7wFVoU.js → LpCopyButton-sAMvWeLP.js} +3 -3
  41. package/dist/chunks/{LpCountdown-DgeY3cLG.js → LpCountdown-DVl7vXI1.js} +4 -3
  42. package/dist/chunks/{LpDataList-Jxyl9H5w.js → LpDataList-CaVfsozH.js} +13 -4
  43. package/dist/chunks/{LpDatePicker-CA0QTfBC.js → LpDatePicker-DwSDY0mt.js} +12 -18
  44. package/dist/chunks/{LpDateRangePicker-u3J51xXk.js → LpDateRangePicker-CNQXdTVv.js} +10 -16
  45. package/dist/chunks/{LpDisclosure-Cpa7Hc5T.js → LpDisclosure-DG7JCo-d.js} +2 -2
  46. package/dist/chunks/{LpDrawer-CrG8t_KP.js → LpDrawer-DXNQFpAA.js} +61 -61
  47. package/dist/chunks/{LpDropdownMenu-Dl7Z4ZhS.js → LpDropdownMenu-CLzxIOgM.js} +9 -17
  48. package/dist/chunks/{LpEditable-Cy6GLbFx.js → LpEditable-DVT0Rh8F.js} +9 -6
  49. package/dist/chunks/{LpEmptyState-EQHiRYhG.js → LpEmptyState-DurPF001.js} +1 -1
  50. package/dist/chunks/{LpFieldNotice-CzQ2_5rQ.js → LpFieldNotice-DJ10cYIo.js} +1 -1
  51. package/dist/chunks/LpFileTree-C-rJKzEQ.js +735 -0
  52. package/dist/chunks/{LpFileTreeNode-cT6BIWvz.js → LpFileTreeNode-BgYn4U1J.js} +116 -34
  53. package/dist/chunks/{LpFormField-Ch69Jd-X.js → LpFormField-BKYn9dyP.js} +3 -3
  54. package/dist/chunks/{LpFrame-BVQCQLDI.js → LpFrame-Bv5Fphte.js} +25 -11
  55. package/dist/chunks/{LpHintExample-9Py0wc-L.js → LpHintExample-YzCXiSUp.js} +1 -1
  56. package/dist/chunks/{LpHintLayer-CgObdUsM.js → LpHintLayer-BeKRsRon.js} +2 -2
  57. package/dist/chunks/{LpHints-Bz-BlaSl.js → LpHints-qf3xYsza.js} +3 -3
  58. package/dist/chunks/{LpHoverCard-spGxyw7T.js → LpHoverCard-CHE9jAJG.js} +29 -11
  59. package/dist/chunks/{LpIcon--5WSb3jJ.js → LpIcon-C6JpQ5td.js} +6 -3
  60. package/dist/chunks/{LpIdenticon-BzdC_qz9.js → LpIdenticon-Dbbr4fvt.js} +2 -1
  61. package/dist/chunks/{LpInfraNode-46XOCkfq.js → LpInfraNode-Bb5nbuFY.js} +19 -2
  62. package/dist/chunks/{LpInput-Tw-yxT4I.js → LpInput-D0O6dpuA.js} +32 -47
  63. package/dist/chunks/LpInspector-DO3fTCQ1.js +209 -0
  64. package/dist/chunks/{LpLaneNode-HtnQf2FF.js → LpLaneNode-Bqcdm8Rf.js} +19 -1
  65. package/dist/chunks/{LpLightbox-B95yu22B.js → LpLightbox-CtDTQV01.js} +57 -32
  66. package/dist/chunks/{LpLoader-DVwkOmt9.js → LpLoader-Bf1yZwaU.js} +1 -1
  67. package/dist/chunks/LpLogInspector-BdQlX6S-.js +119 -0
  68. package/dist/chunks/{LpLogViewer-ngqkns4m.js → LpLogViewer-umCZBapN.js} +234 -53
  69. package/dist/chunks/{LpMapPicker-DRGgh89B.js → LpMapPicker-D5_YLLBC.js} +4 -3
  70. package/dist/chunks/{LpMasonry--k0571qG.js → LpMasonry-DPYekFxs.js} +8 -5
  71. package/dist/chunks/{LpMediaGallery-Bkram-MO.js → LpMediaGallery-BYEwySoF.js} +3 -3
  72. package/dist/chunks/{LpModal-CoGhLTyH.js → LpModal-DDvrSAnf.js} +11 -13
  73. package/dist/chunks/{LpModalNav-BGvs2y5Q.js → LpModalNav-gOi1Giz1.js} +11 -37
  74. package/dist/chunks/{LpNotificationBell-B0034Lk-.js → LpNotificationBell-DUbVyK6R.js} +9 -9
  75. package/dist/chunks/{LpNumberField-e0IBkWU1.js → LpNumberField-Csg-1Zh_.js} +25 -20
  76. package/dist/chunks/{LpOtpInput-CeBPsM7D.js → LpOtpInput-BRpLBbOD.js} +2 -2
  77. package/dist/chunks/LpPageScrollbar-D2O0xhJw.js +164 -0
  78. package/dist/chunks/{LpPagination-BIIiYHXR.js → LpPagination-snQ020xQ.js} +6 -4
  79. package/dist/chunks/{LpPaletteTheme-DiLYKQiZ.js → LpPaletteTheme-BIXpZLGe.js} +4 -4
  80. package/dist/chunks/{LpPasswordInput-BkHKQDhM.js → LpPasswordInput-D4HPhqfV.js} +2 -2
  81. package/dist/chunks/{LpPhoneInput-CETEp5W7.js → LpPhoneInput-BSL7NX4z.js} +15 -26
  82. package/dist/chunks/{LpPie-DrZepi0p.js → LpPie-oVNHjsKD.js} +22 -21
  83. package/dist/chunks/{LpPipeline-B3aOVOkV.js → LpPipeline-BSXT6oUJ.js} +16 -7
  84. package/dist/chunks/{LpPopover-DmZ3wUtP.js → LpPopover-BQSuxtai.js} +10 -1
  85. package/dist/chunks/{LpProgress-Yr6ONG5t.js → LpProgress-D_MSjowb.js} +2 -1
  86. package/dist/chunks/{LpQuota-Dk2MyI2Z.js → LpQuota-CgWPgdVt.js} +1 -1
  87. package/dist/chunks/{LpRadioGroup-ggaPL92T.js → LpRadioGroup-BrazjLY_.js} +4 -4
  88. package/dist/chunks/{LpRangeCalendar-CYYUYqJ7.js → LpRangeCalendar-BrqlGZzE.js} +1 -1
  89. package/dist/chunks/{LpRangeSlider-CM-0ZITZ.js → LpRangeSlider-fz61tzc-.js} +5 -9
  90. package/dist/chunks/{LpRelativeTime-DwgCb5-8.js → LpRelativeTime-0zI-44ve.js} +1 -1
  91. package/dist/chunks/{LpRepeater-D7ZmnIYd.js → LpRepeater-BkJHSPI1.js} +3 -3
  92. package/dist/chunks/{LpRevealOnScroll-DcQjexLy.js → LpRevealOnScroll-CPwyiQAr.js} +1 -1
  93. package/dist/chunks/{LpScramble-Bn9OoOtC.js → LpScramble-DsE77iVp.js} +1 -1
  94. package/dist/chunks/{LpScrollArea-MyEnVB_5.js → LpScrollArea-CqvwfZs2.js} +31 -22
  95. package/dist/chunks/{LpSecretField-BbmqM9ye.js → LpSecretField-B2roc4Iz.js} +10 -9
  96. package/dist/chunks/{LpSection-DFK_uoJE.js → LpSection-BfteipxU.js} +1 -1
  97. package/dist/chunks/{LpSegmented-CeACsMMA.js → LpSegmented-DbEJhbv-.js} +8 -10
  98. package/dist/chunks/{LpSelect-Cxq4yBGd.js → LpSelect-Y-iuSymW.js} +47 -30
  99. package/dist/chunks/{LpServiceNode-D8uJ8sGk.js → LpServiceNode-Cln2ntdw.js} +17 -0
  100. package/dist/chunks/{LpShaderBackdrop-Bote0iuy.js → LpShaderBackdrop-wQygYb5h.js} +13 -10
  101. package/dist/chunks/{LpShift-CCq7dofl.js → LpShift-DAgS_d2x.js} +18 -15
  102. package/dist/chunks/{LpSidebar-DzE1783C.js → LpSidebar-DDNJzb69.js} +74 -87
  103. package/dist/chunks/{LpSidebarNav-DE3PhXVP.js → LpSidebarNav-CE0jQS8i.js} +8 -6
  104. package/dist/chunks/{LpSidebarRow-BRYhNDSo.js → LpSidebarRow-DOTg1txp.js} +6 -5
  105. package/dist/chunks/{LpSlider-DxYoCJJO.js → LpSlider-A4ixovgS.js} +5 -9
  106. package/dist/chunks/{LpSpotlight-4F3NeUMY.js → LpSpotlight-DwxkhFgR.js} +2 -1
  107. package/dist/chunks/{LpStat-f2LfDCJ4.js → LpStat-DPjc6_fX.js} +19 -6
  108. package/dist/chunks/{LpStatus-DglxttQ7.js → LpStatus-DGJFwk5F.js} +2 -2
  109. package/dist/chunks/{LpStepMark-DpzKVyh8.js → LpStepMark-Dw2MRTrt.js} +2 -2
  110. package/dist/chunks/{LpStepper-DpsocBNJ.js → LpStepper-DNnh7lCu.js} +1 -1
  111. package/dist/chunks/{LpSwap-C96c0LWh.js → LpSwap-M7nFeW3C.js} +1 -1
  112. package/dist/chunks/{LpSwitch-BnXd1llc.js → LpSwitch-DnC2-0aV.js} +3 -3
  113. package/dist/chunks/{LpTabFace-DPCwKkH2.js → LpTabFace-DQoV8mQG.js} +2 -2
  114. package/dist/chunks/{LpTableFilter-CiVBpaq0.js → LpTableFilter-B_XMOeAh.js} +4 -4
  115. package/dist/chunks/{LpTableOfContents-BN5zvpnx.js → LpTableOfContents-CKkWEK6R.js} +14 -9
  116. package/dist/chunks/{LpTagsInput-C-mDG648.js → LpTagsInput-Dt0mteSj.js} +19 -27
  117. package/dist/chunks/{LpTextarea-TE-yZv2U.js → LpTextarea-Co0b9PVx.js} +8 -16
  118. package/dist/chunks/LpThemeProvider-XK6ZeWAE.js +81 -0
  119. package/dist/chunks/{LpThemeStudio-BpORDvH6.js → LpThemeStudio-ChU0_Ga8.js} +12 -195
  120. package/dist/chunks/{LpThemeSwitcher-BnEn_mvf.js → LpThemeSwitcher-DmCZ21P_.js} +8 -6
  121. package/dist/chunks/{LpTimeField-BawSVsmt.js → LpTimeField-DeOcKWJq.js} +6 -9
  122. package/dist/chunks/{LpToaster-IwTXjbbU.js → LpToaster-Ct_ZOhCh.js} +10 -8
  123. package/dist/chunks/{LpTooltip-BcBvIx4z.js → LpTooltip-Bz_rrq5S.js} +56 -24
  124. package/dist/chunks/LpTopologyCanvas-jqz1KCq2.js +678 -0
  125. package/dist/chunks/{LpTour-BZq-mUMv.js → LpTour-ClKYhx4h.js} +7 -5
  126. package/dist/chunks/{LpTruncate-CflAIwiJ.js → LpTruncate-ellq9RYM.js} +6 -5
  127. package/dist/chunks/{LpTypewriter-BCL_a6wE.js → LpTypewriter-CZIzpdbe.js} +2 -1
  128. package/dist/chunks/{LpUptimeBar-DqNvvMBK.js → LpUptimeBar-BoxcCDVY.js} +3 -3
  129. package/dist/chunks/{LpVideoBackdrop-DS1wGv-X.js → LpVideoBackdrop-Ct4St4ZL.js} +10 -13
  130. package/dist/chunks/LpWindow-B8YSRVTH.js +297 -0
  131. package/dist/chunks/LpWorkspaceSwitcher-BeNHCLd5.js +139 -0
  132. package/dist/chunks/{MenuTitle-BmCNNTKH.js → MenuTitle-Bh5dAdV1.js} +1 -1
  133. package/dist/chunks/{OptionContent-22UT8zLn.js → OptionContent-CGb8QlHA.js} +1 -1
  134. package/dist/chunks/{PickerField-Bfh8id3d.js → PickerField-BM1dyafh.js} +4 -4
  135. package/dist/chunks/{RevealToggle-BEit1n6Z.js → RevealToggle-D_iyrB8d.js} +3 -3
  136. package/dist/chunks/SliderRail-DhPREa_R.js +18 -0
  137. package/dist/chunks/{TourCard-DNclH3u_.js → TourCard-DAzTYfav.js} +4 -4
  138. package/dist/chunks/{icons-DMITlfw5.js → icons-CYfcpSDS.js} +26 -10
  139. package/dist/component-names.d.ts +1 -1
  140. package/dist/components/AppShellContextNav.vue.d.ts +13 -0
  141. package/dist/components/AppShellContextNav.vue.js +4 -0
  142. package/dist/components/ChartRangeSelector.vue.d.ts +21 -0
  143. package/dist/components/ChartRangeSelector.vue.js +4 -0
  144. package/dist/components/ContextMenuItems.vue.js +1 -1
  145. package/dist/components/DropzoneLinkField.vue.d.ts +2 -2
  146. package/dist/components/DropzoneLinkField.vue.js +1 -1
  147. package/dist/components/FieldLeading.vue.d.ts +16 -0
  148. package/dist/components/FieldLeading.vue.js +4 -0
  149. package/dist/components/FieldWrapper.vue.js +1 -1
  150. package/dist/components/IconCloseButton.vue.d.ts +7 -0
  151. package/dist/components/IconCloseButton.vue.js +4 -0
  152. package/dist/components/LayoutCanvas.vue.js +1 -1
  153. package/dist/components/LayoutNode.vue.js +1 -1
  154. package/dist/components/LpActionBar.vue.js +1 -1
  155. package/dist/components/LpActivityLine.vue.js +1 -1
  156. package/dist/components/LpAddressInput.vue.js +1 -1
  157. package/dist/components/LpAlert.vue.js +1 -1
  158. package/dist/components/LpAppShell.vue.d.ts +125 -2
  159. package/dist/components/LpAppShell.vue.js +1 -1
  160. package/dist/components/LpAutocomplete.vue.js +1 -1
  161. package/dist/components/LpAvatar.vue.js +1 -1
  162. package/dist/components/LpBadge.vue.js +1 -1
  163. package/dist/components/LpBottomNav.vue.d.ts +5 -0
  164. package/dist/components/LpBottomNav.vue.js +1 -1
  165. package/dist/components/LpBreadcrumbs.vue.js +1 -1
  166. package/dist/components/LpButton.vue.d.ts +14 -2
  167. package/dist/components/LpButton.vue.js +1 -1
  168. package/dist/components/LpCalendar.vue.js +1 -1
  169. package/dist/components/LpCard.vue.js +1 -1
  170. package/dist/components/LpChart.vue.d.ts +74 -2
  171. package/dist/components/LpChart.vue.js +326 -85
  172. package/dist/components/LpCheckbox.vue.d.ts +6 -2
  173. package/dist/components/LpCheckbox.vue.js +1 -1
  174. package/dist/components/LpCodeBlock.vue.js +1 -1
  175. package/dist/components/LpCodeDisplay.vue.js +1 -1
  176. package/dist/components/LpCollapse.vue.js +1 -1
  177. package/dist/components/LpColorPicker.vue.js +1 -1
  178. package/dist/components/LpCommandPalette.vue.d.ts +8 -0
  179. package/dist/components/LpCommandPalette.vue.js +107 -56
  180. package/dist/components/LpCommandScope.vue.js +1 -1
  181. package/dist/components/LpConfirmDialog.vue.js +1 -1
  182. package/dist/components/LpConfirmHost.vue.js +1 -1
  183. package/dist/components/LpContextMenu.vue.js +1 -1
  184. package/dist/components/LpContextSwitcher.vue.js +1 -1
  185. package/dist/components/LpCopyButton.vue.js +1 -1
  186. package/dist/components/LpCountdown.vue.js +1 -1
  187. package/dist/components/LpDataList.vue.d.ts +1 -1
  188. package/dist/components/LpDataList.vue.js +1 -1
  189. package/dist/components/LpDatePicker.vue.d.ts +3 -15
  190. package/dist/components/LpDatePicker.vue.js +1 -1
  191. package/dist/components/LpDateRangePicker.vue.d.ts +3 -13
  192. package/dist/components/LpDateRangePicker.vue.js +1 -1
  193. package/dist/components/LpDisclosure.vue.js +1 -1
  194. package/dist/components/LpDock.vue.js +21 -18
  195. package/dist/components/LpDrawer.vue.d.ts +1 -1
  196. package/dist/components/LpDrawer.vue.js +1 -1
  197. package/dist/components/LpDropdownMenu.vue.js +1 -1
  198. package/dist/components/LpDropzone.vue.js +14 -11
  199. package/dist/components/LpEditable.vue.js +1 -1
  200. package/dist/components/LpEmptyState.vue.js +1 -1
  201. package/dist/components/LpFieldNotice.vue.js +1 -1
  202. package/dist/components/LpFileTree.vue.d.ts +96 -6
  203. package/dist/components/LpFileTree.vue.js +1 -1
  204. package/dist/components/LpFileTreeNode.vue.d.ts +48 -0
  205. package/dist/components/LpFileTreeNode.vue.js +1 -1
  206. package/dist/components/LpFormField.vue.js +1 -1
  207. package/dist/components/LpFrame.vue.js +1 -1
  208. package/dist/components/LpGauge.vue.d.ts +1 -1
  209. package/dist/components/LpHintExample.vue.js +1 -1
  210. package/dist/components/LpHintLayer.vue.js +1 -1
  211. package/dist/components/LpHints.vue.js +1 -1
  212. package/dist/components/LpHoverCard.vue.js +1 -1
  213. package/dist/components/LpIcon.vue.d.ts +2 -0
  214. package/dist/components/LpIcon.vue.js +1 -1
  215. package/dist/components/LpIdenticon.vue.js +1 -1
  216. package/dist/components/LpImageEditor.vue.js +7 -6
  217. package/dist/components/LpInfraNode.vue.d.ts +11 -2
  218. package/dist/components/LpInfraNode.vue.js +1 -1
  219. package/dist/components/LpInput.vue.d.ts +1 -1
  220. package/dist/components/LpInput.vue.js +1 -1
  221. package/dist/components/LpInspector.vue.d.ts +87 -0
  222. package/dist/components/LpInspector.vue.js +4 -0
  223. package/dist/components/LpLaneNode.vue.d.ts +2 -3
  224. package/dist/components/LpLaneNode.vue.js +1 -1
  225. package/dist/components/LpLightbox.vue.d.ts +8 -0
  226. package/dist/components/LpLightbox.vue.js +1 -1
  227. package/dist/components/LpLoader.vue.d.ts +1 -1
  228. package/dist/components/LpLoader.vue.js +1 -1
  229. package/dist/components/LpLogInspector.vue.d.ts +18 -0
  230. package/dist/components/LpLogInspector.vue.js +4 -0
  231. package/dist/components/LpLogViewer.vue.d.ts +93 -0
  232. package/dist/components/LpLogViewer.vue.js +1 -1
  233. package/dist/components/LpMapPicker.vue.js +1 -1
  234. package/dist/components/LpMasonry.vue.js +1 -1
  235. package/dist/components/LpMediaGallery.vue.js +1 -1
  236. package/dist/components/LpModal.vue.d.ts +4 -2
  237. package/dist/components/LpModal.vue.js +1 -1
  238. package/dist/components/LpModalNav.vue.d.ts +5 -5
  239. package/dist/components/LpModalNav.vue.js +1 -1
  240. package/dist/components/LpNotificationBell.vue.d.ts +2 -2
  241. package/dist/components/LpNotificationBell.vue.js +1 -1
  242. package/dist/components/LpNumberField.vue.d.ts +13 -2
  243. package/dist/components/LpNumberField.vue.js +1 -1
  244. package/dist/components/LpOtpInput.vue.js +1 -1
  245. package/dist/components/LpPageScrollbar.vue.d.ts +10 -0
  246. package/dist/components/LpPageScrollbar.vue.js +4 -0
  247. package/dist/components/LpPagination.vue.js +1 -1
  248. package/dist/components/LpPaletteFacts.vue.js +1 -1
  249. package/dist/components/LpPaletteHeader.vue.js +2 -2
  250. package/dist/components/LpPaletteTheme.vue.js +1 -1
  251. package/dist/components/LpPasswordInput.vue.js +1 -1
  252. package/dist/components/LpPhoneInput.vue.js +1 -1
  253. package/dist/components/LpPie.vue.d.ts +2 -2
  254. package/dist/components/LpPie.vue.js +1 -1
  255. package/dist/components/LpPipeline.vue.d.ts +4 -0
  256. package/dist/components/LpPipeline.vue.js +1 -1
  257. package/dist/components/LpPopover.vue.d.ts +7 -3
  258. package/dist/components/LpPopover.vue.js +1 -1
  259. package/dist/components/LpProgress.vue.d.ts +1 -1
  260. package/dist/components/LpProgress.vue.js +1 -1
  261. package/dist/components/LpQuota.vue.js +1 -1
  262. package/dist/components/LpRadioGroup.vue.js +1 -1
  263. package/dist/components/LpRangeCalendar.vue.js +1 -1
  264. package/dist/components/LpRangeSlider.vue.js +1 -1
  265. package/dist/components/LpRelativeTime.vue.js +1 -1
  266. package/dist/components/LpRepeater.vue.js +1 -1
  267. package/dist/components/LpRevealOnScroll.vue.js +1 -1
  268. package/dist/components/LpScramble.vue.js +1 -1
  269. package/dist/components/LpScrollArea.vue.js +1 -1
  270. package/dist/components/LpSecretField.vue.js +1 -1
  271. package/dist/components/LpSection.vue.js +1 -1
  272. package/dist/components/LpSegmented.vue.js +1 -1
  273. package/dist/components/LpSelect.vue.js +1 -1
  274. package/dist/components/LpServiceNode.vue.d.ts +8 -2
  275. package/dist/components/LpServiceNode.vue.js +1 -1
  276. package/dist/components/LpShaderBackdrop.vue.js +1 -1
  277. package/dist/components/LpShift.vue.js +1 -1
  278. package/dist/components/LpShortcutsDialog.vue.js +1 -1
  279. package/dist/components/LpSidebar.vue.d.ts +1 -1
  280. package/dist/components/LpSidebar.vue.js +1 -1
  281. package/dist/components/LpSidebarNav.vue.js +1 -1
  282. package/dist/components/LpSidebarRow.vue.js +1 -1
  283. package/dist/components/LpSlider.vue.js +1 -1
  284. package/dist/components/LpSparkline.vue.d.ts +1 -1
  285. package/dist/components/LpSpotlight.vue.js +1 -1
  286. package/dist/components/LpStat.vue.d.ts +16 -0
  287. package/dist/components/LpStat.vue.js +1 -1
  288. package/dist/components/LpStatus.vue.js +1 -1
  289. package/dist/components/LpStepMark.vue.js +1 -1
  290. package/dist/components/LpStepper.vue.js +1 -1
  291. package/dist/components/LpSwap.vue.js +1 -1
  292. package/dist/components/LpSwitch.vue.js +1 -1
  293. package/dist/components/LpTabFace.vue.js +1 -1
  294. package/dist/components/LpTable.vue.d.ts +132 -0
  295. package/dist/components/LpTable.vue.js +547 -135
  296. package/dist/components/LpTableFilter.vue.js +1 -1
  297. package/dist/components/LpTableOfContents.vue.js +1 -1
  298. package/dist/components/LpTabs.vue.js +6 -5
  299. package/dist/components/LpTagsInput.vue.js +1 -1
  300. package/dist/components/LpTextarea.vue.js +1 -1
  301. package/dist/components/LpThemeProvider.vue.d.ts +2 -0
  302. package/dist/components/LpThemeProvider.vue.js +1 -1
  303. package/dist/components/LpThemeStudio.vue.js +1 -1
  304. package/dist/components/LpThemeSwitcher.vue.js +1 -1
  305. package/dist/components/LpTimeField.vue.js +1 -1
  306. package/dist/components/LpToaster.vue.js +1 -1
  307. package/dist/components/LpTooltip.vue.js +1 -1
  308. package/dist/components/LpTopologyCanvas.vue.d.ts +131 -5
  309. package/dist/components/LpTopologyCanvas.vue.js +1 -1
  310. package/dist/components/LpTour.vue.js +1 -1
  311. package/dist/components/LpTruncate.vue.js +1 -1
  312. package/dist/components/LpTypewriter.vue.js +1 -1
  313. package/dist/components/LpUptimeBar.vue.js +1 -1
  314. package/dist/components/LpVideoBackdrop.vue.js +1 -1
  315. package/dist/components/LpWindow.vue.d.ts +99 -0
  316. package/dist/components/LpWindow.vue.js +4 -0
  317. package/dist/components/LpWorkspaceSwitcher.vue.d.ts +18 -0
  318. package/dist/components/LpWorkspaceSwitcher.vue.js +4 -0
  319. package/dist/components/MenuTitle.vue.js +1 -1
  320. package/dist/components/OptionContent.vue.js +1 -1
  321. package/dist/components/PickerField.vue.d.ts +2 -2
  322. package/dist/components/PickerField.vue.js +1 -1
  323. package/dist/components/RevealToggle.vue.js +1 -1
  324. package/dist/components/SliderRail.vue.d.ts +3 -0
  325. package/dist/components/SliderRail.vue.js +4 -0
  326. package/dist/components/TourCard.vue.js +1 -1
  327. package/dist/components/address.js +2 -1
  328. package/dist/components/appShell.d.ts +36 -0
  329. package/dist/components/appShell.js +30 -0
  330. package/dist/components/calendar.d.ts +12 -3
  331. package/dist/components/calendar.js +2 -5
  332. package/dist/components/chart.d.ts +21 -0
  333. package/dist/components/chart.js +4 -3
  334. package/dist/components/chartWindow.d.ts +57 -0
  335. package/dist/components/chartWindow.js +136 -0
  336. package/dist/components/color.js +1 -1
  337. package/dist/components/commandPalette.d.ts +16 -2
  338. package/dist/components/commandPalette.js +39 -4
  339. package/dist/components/controlSize.d.ts +5 -0
  340. package/dist/components/controlSize.js +8 -0
  341. package/dist/components/dropdown.d.ts +5 -0
  342. package/dist/components/dropdown.js +2 -0
  343. package/dist/components/exportData.d.ts +6 -1
  344. package/dist/components/exportData.js +25 -18
  345. package/dist/components/fileTree.d.ts +67 -0
  346. package/dist/components/fileTree.js +141 -1
  347. package/dist/components/identicon.js +3 -2
  348. package/dist/components/logTools.d.ts +93 -0
  349. package/dist/components/logTools.js +210 -0
  350. package/dist/components/menuWhen.js +1 -1
  351. package/dist/components/meter.js +2 -1
  352. package/dist/components/pipeline.d.ts +2 -0
  353. package/dist/components/pipeline.js +5 -0
  354. package/dist/components/relativeTime.js +2 -1
  355. package/dist/components/reveal.js +2 -1
  356. package/dist/components/scrollbar.d.ts +34 -0
  357. package/dist/components/scrollbar.js +47 -0
  358. package/dist/components/select.d.ts +5 -0
  359. package/dist/components/select.js +10 -0
  360. package/dist/components/sidebar.d.ts +1 -0
  361. package/dist/components/tableFeatures.d.ts +58 -0
  362. package/dist/components/tableFeatures.js +87 -0
  363. package/dist/components/topologyGraph.d.ts +164 -0
  364. package/dist/components/topologyGraph.js +416 -0
  365. package/dist/components/tour.js +5 -3
  366. package/dist/components/videoBackdrop.js +7 -6
  367. package/dist/composables/clamp.d.ts +2 -0
  368. package/dist/composables/clamp.js +4 -0
  369. package/dist/composables/devWarn.d.ts +3 -0
  370. package/dist/composables/devWarn.js +14 -0
  371. package/dist/composables/easing.d.ts +13 -4
  372. package/dist/composables/easing.js +16 -10
  373. package/dist/composables/overlayHistory.js +14 -1
  374. package/dist/composables/pointerDrag.d.ts +15 -0
  375. package/dist/composables/pointerDrag.js +40 -0
  376. package/dist/composables/propCheck.d.ts +10 -0
  377. package/dist/composables/propCheck.js +89 -0
  378. package/dist/composables/realm.d.ts +6 -0
  379. package/dist/composables/realm.js +23 -0
  380. package/dist/composables/scroll.js +4 -2
  381. package/dist/composables/scrollMemory.d.ts +12 -1
  382. package/dist/composables/scrollMemory.js +36 -12
  383. package/dist/composables/spatialNav.js +2 -1
  384. package/dist/composables/textEntry.d.ts +17 -0
  385. package/dist/composables/textEntry.js +19 -0
  386. package/dist/composables/useAsyncTask.d.ts +6 -0
  387. package/dist/composables/useChartSync.d.ts +5 -0
  388. package/dist/composables/useChartSync.js +33 -0
  389. package/dist/composables/useCloseGuard.d.ts +3 -1
  390. package/dist/composables/useCloseGuard.js +6 -3
  391. package/dist/composables/useCommands.d.ts +50 -0
  392. package/dist/composables/useCommands.js +66 -0
  393. package/dist/composables/useField.d.ts +37 -0
  394. package/dist/composables/useField.js +27 -2
  395. package/dist/composables/useFitScale.js +4 -1
  396. package/dist/composables/useFormDraft.d.ts +13 -2
  397. package/dist/composables/useFormDraft.js +17 -9
  398. package/dist/composables/useHintSystem.js +2 -2
  399. package/dist/composables/useHotkeys.js +11 -32
  400. package/dist/composables/useInView.js +2 -1
  401. package/dist/composables/useInputFilter.js +7 -5
  402. package/dist/composables/useInputMask.js +5 -3
  403. package/dist/composables/useLinkedView.d.ts +97 -0
  404. package/dist/composables/useLinkedView.js +139 -0
  405. package/dist/composables/useOptimisticToggle.d.ts +3 -1
  406. package/dist/composables/useOptimisticToggle.js +2 -1
  407. package/dist/composables/useOverlayHistory.d.ts +7 -0
  408. package/dist/composables/useOverlayHistory.js +16 -2
  409. package/dist/composables/usePaintSelect.js +18 -14
  410. package/dist/composables/usePaletteCommands.d.ts +7 -0
  411. package/dist/composables/usePaletteCommands.js +16 -3
  412. package/dist/composables/usePersisted.d.ts +10 -0
  413. package/dist/composables/usePersisted.js +1 -1
  414. package/dist/composables/usePillTransition.d.ts +2 -2
  415. package/dist/composables/usePillTransition.js +5 -5
  416. package/dist/composables/useResizeObserver.js +2 -1
  417. package/dist/composables/useReveal.js +2 -1
  418. package/dist/composables/useRovingFocus.d.ts +2 -2
  419. package/dist/composables/useRovingFocus.js +9 -11
  420. package/dist/composables/useScramble.js +7 -1
  421. package/dist/composables/useShift.js +8 -6
  422. package/dist/composables/useTilt.js +2 -1
  423. package/dist/composables/useTween.js +9 -5
  424. package/dist/composables/useView.d.ts +1 -0
  425. package/dist/composables/useView.js +14 -2
  426. package/dist/composables/useZoomPan.js +2 -4
  427. package/dist/composables/windowing.d.ts +40 -0
  428. package/dist/composables/windowing.js +118 -0
  429. package/dist/icons-all.js +1 -1
  430. package/dist/icons.d.ts +4 -0
  431. package/dist/index.d.ts +31 -5
  432. package/dist/index.js +312 -264
  433. package/dist/layout/tree.js +19 -15
  434. package/dist/layout/useLayout.d.ts +2 -0
  435. package/dist/layout/useLayout.js +5 -1
  436. package/dist/layout/useWorkspaces.d.ts +52 -0
  437. package/dist/layout/useWorkspaces.js +140 -0
  438. package/dist/{chunks/backdrop-Dkf2vM81.js → theme/backdrop.js} +5 -5
  439. package/dist/theme/config.js +25 -0
  440. package/dist/theme/define.js +61 -0
  441. package/dist/{chunks/palette-Co8tSASo.js → theme/palette.js} +2 -2
  442. package/dist/theme/presets.js +239 -0
  443. package/dist/theme/studio.js +134 -0
  444. package/dist/theme/tokens.js +63 -0
  445. package/dist/theme/useTheme.d.ts +3 -2
  446. package/dist/theme/useTheme.js +325 -0
  447. package/package.json +8 -1
  448. package/src/component-names.ts +6 -1
  449. package/src/components/AppShellContextNav.vue +44 -0
  450. package/src/components/ChartRangeSelector.vue +120 -0
  451. package/src/components/FieldLeading.vue +17 -0
  452. package/src/components/IconCloseButton.vue +21 -0
  453. package/src/components/LayoutCanvas.vue +3 -0
  454. package/src/components/LayoutNode.vue +37 -38
  455. package/src/components/LpActivityLine.vue +4 -2
  456. package/src/components/LpAddressInput.vue +3 -3
  457. package/src/components/LpAppShell.vue +385 -24
  458. package/src/components/LpAutocomplete.vue +13 -30
  459. package/src/components/LpBottomNav.vue +9 -1
  460. package/src/components/LpBreadcrumbs.vue +2 -1
  461. package/src/components/LpButton.vue +11 -4
  462. package/src/components/LpChart.vue +336 -37
  463. package/src/components/LpCheckbox.vue +43 -9
  464. package/src/components/LpCodeBlock.vue +17 -23
  465. package/src/components/LpCollapse.vue +5 -4
  466. package/src/components/LpColorPicker.vue +8 -9
  467. package/src/components/LpCommandPalette.vue +133 -50
  468. package/src/components/LpContextMenu.vue +22 -13
  469. package/src/components/LpCountdown.vue +2 -1
  470. package/src/components/LpDataList.vue +13 -1
  471. package/src/components/LpDatePicker.vue +5 -17
  472. package/src/components/LpDateRangePicker.vue +5 -16
  473. package/src/components/LpDock.vue +25 -16
  474. package/src/components/LpDrawer.vue +70 -61
  475. package/src/components/LpDropdownMenu.vue +6 -10
  476. package/src/components/LpDropzone.vue +12 -7
  477. package/src/components/LpEditable.vue +6 -2
  478. package/src/components/LpFileTree.vue +507 -66
  479. package/src/components/LpFileTreeNode.vue +106 -5
  480. package/src/components/LpFormField.vue +1 -1
  481. package/src/components/LpFrame.vue +33 -13
  482. package/src/components/LpHoverCard.vue +37 -5
  483. package/src/components/LpIcon.vue +6 -2
  484. package/src/components/LpIdenticon.vue +2 -1
  485. package/src/components/LpImageEditor.vue +5 -2
  486. package/src/components/LpInfraNode.vue +4 -3
  487. package/src/components/LpInput.vue +19 -26
  488. package/src/components/LpInspector.vue +197 -0
  489. package/src/components/LpLaneNode.vue +5 -1
  490. package/src/components/LpLightbox.vue +74 -29
  491. package/src/components/LpLogInspector.vue +85 -0
  492. package/src/components/LpLogViewer.vue +239 -29
  493. package/src/components/LpMapPicker.vue +2 -1
  494. package/src/components/LpMasonry.vue +8 -5
  495. package/src/components/LpModal.vue +12 -12
  496. package/src/components/LpModalNav.vue +2 -21
  497. package/src/components/LpNumberField.vue +13 -16
  498. package/src/components/LpOtpInput.vue +2 -2
  499. package/src/components/LpPageScrollbar.vue +195 -0
  500. package/src/components/LpPagination.vue +5 -3
  501. package/src/components/LpPhoneInput.vue +8 -19
  502. package/src/components/LpPie.vue +25 -23
  503. package/src/components/LpPipeline.vue +14 -1
  504. package/src/components/LpPopover.vue +23 -2
  505. package/src/components/LpProgress.vue +2 -1
  506. package/src/components/LpRadioGroup.vue +2 -2
  507. package/src/components/LpRangeSlider.vue +5 -6
  508. package/src/components/LpRevealOnScroll.vue +1 -1
  509. package/src/components/LpScrollArea.vue +55 -34
  510. package/src/components/LpSecretField.vue +2 -1
  511. package/src/components/LpSegmented.vue +6 -8
  512. package/src/components/LpSelect.vue +54 -24
  513. package/src/components/LpServiceNode.vue +4 -2
  514. package/src/components/LpShaderBackdrop.vue +12 -9
  515. package/src/components/LpShift.vue +18 -15
  516. package/src/components/LpSidebar.vue +77 -74
  517. package/src/components/LpSidebarNav.vue +3 -2
  518. package/src/components/LpSidebarRow.vue +2 -1
  519. package/src/components/LpSlider.vue +5 -6
  520. package/src/components/LpSpotlight.vue +2 -1
  521. package/src/components/LpStat.vue +25 -5
  522. package/src/components/LpSwitch.vue +5 -3
  523. package/src/components/LpTable.vue +609 -93
  524. package/src/components/LpTableFilter.vue +1 -1
  525. package/src/components/LpTableOfContents.vue +16 -9
  526. package/src/components/LpTabs.vue +2 -1
  527. package/src/components/LpTagsInput.vue +12 -19
  528. package/src/components/LpTextarea.vue +5 -11
  529. package/src/components/LpThemeProvider.vue +29 -13
  530. package/src/components/LpTimeField.vue +4 -7
  531. package/src/components/LpToaster.vue +7 -6
  532. package/src/components/LpTooltip.vue +69 -18
  533. package/src/components/LpTopologyCanvas.vue +569 -42
  534. package/src/components/LpTour.vue +7 -5
  535. package/src/components/LpTruncate.vue +4 -3
  536. package/src/components/LpTypewriter.vue +2 -1
  537. package/src/components/LpVideoBackdrop.vue +11 -13
  538. package/src/components/LpWindow.vue +373 -0
  539. package/src/components/LpWorkspaceSwitcher.vue +116 -0
  540. package/src/components/PickerField.vue +2 -2
  541. package/src/components/SliderRail.vue +10 -0
  542. package/src/components/address.ts +3 -1
  543. package/src/components/appShell.ts +74 -0
  544. package/src/components/calendar.ts +12 -5
  545. package/src/components/chart.ts +27 -3
  546. package/src/components/chartWindow.ts +198 -0
  547. package/src/components/color.ts +2 -1
  548. package/src/components/commandPalette.ts +66 -5
  549. package/src/components/controlSize.ts +6 -0
  550. package/src/components/dropdown.ts +3 -0
  551. package/src/components/exportData.ts +33 -18
  552. package/src/components/fileTree.ts +215 -0
  553. package/src/components/identicon.ts +4 -2
  554. package/src/components/logTools.ts +298 -0
  555. package/src/components/meter.ts +2 -1
  556. package/src/components/pipeline.ts +6 -0
  557. package/src/components/relativeTime.ts +2 -1
  558. package/src/components/reveal.ts +3 -1
  559. package/src/components/scrollbar.ts +71 -0
  560. package/src/components/select.ts +14 -0
  561. package/src/components/sidebar.ts +1 -0
  562. package/src/components/tableFeatures.ts +149 -0
  563. package/src/components/topologyGraph.ts +655 -0
  564. package/src/components/tour.ts +5 -3
  565. package/src/components/videoBackdrop.ts +7 -6
  566. package/src/composables/clamp.ts +2 -0
  567. package/src/composables/devWarn.ts +19 -0
  568. package/src/composables/easing.ts +37 -12
  569. package/src/composables/overlayHistory.ts +24 -0
  570. package/src/composables/pointerDrag.ts +54 -0
  571. package/src/composables/propCheck.ts +105 -0
  572. package/src/composables/realm.ts +25 -0
  573. package/src/composables/scroll.ts +4 -2
  574. package/src/composables/scrollMemory.ts +56 -14
  575. package/src/composables/spatialNav.ts +2 -1
  576. package/src/composables/textEntry.ts +33 -0
  577. package/src/composables/useAsyncTask.ts +6 -0
  578. package/src/composables/useChartSync.ts +52 -0
  579. package/src/composables/useCloseGuard.ts +22 -10
  580. package/src/composables/useCommands.ts +123 -0
  581. package/src/composables/useField.ts +41 -2
  582. package/src/composables/useFitScale.ts +4 -1
  583. package/src/composables/useFormDraft.ts +38 -14
  584. package/src/composables/useHintSystem.ts +2 -2
  585. package/src/composables/useHotkeys.ts +19 -48
  586. package/src/composables/useInView.ts +2 -1
  587. package/src/composables/useInputFilter.ts +8 -5
  588. package/src/composables/useInputMask.ts +8 -3
  589. package/src/composables/useLinkedView.ts +222 -0
  590. package/src/composables/useOptimisticToggle.ts +7 -1
  591. package/src/composables/useOverlayHistory.ts +20 -0
  592. package/src/composables/usePaintSelect.ts +20 -14
  593. package/src/composables/usePaletteCommands.ts +18 -2
  594. package/src/composables/usePersisted.ts +10 -0
  595. package/src/composables/usePillTransition.ts +9 -6
  596. package/src/composables/useResizeObserver.ts +2 -1
  597. package/src/composables/useReveal.ts +2 -1
  598. package/src/composables/useRovingFocus.ts +11 -14
  599. package/src/composables/useScramble.ts +12 -1
  600. package/src/composables/useShift.ts +8 -6
  601. package/src/composables/useTilt.ts +2 -1
  602. package/src/composables/useTween.ts +10 -5
  603. package/src/composables/useView.ts +17 -3
  604. package/src/composables/useZoomPan.ts +2 -5
  605. package/src/composables/windowing.ts +190 -0
  606. package/src/icons.ts +27 -6
  607. package/src/index.ts +42 -4
  608. package/src/kit-icons.ts +1 -1
  609. package/src/layout/tree.ts +31 -16
  610. package/src/layout/useLayout.ts +6 -0
  611. package/src/layout/useWorkspaces.ts +234 -0
  612. package/src/nuxt.ts +9 -1
  613. package/src/runtime/propCheck.plugin.ts +10 -0
  614. package/src/theme/studio.ts +7 -5
  615. package/src/theme/useTheme.ts +89 -15
  616. package/src/tokens/tokens.css +8 -1
  617. package/dist/assets/LpTabs-CJ0rYQbx.css +0 -18
  618. package/dist/chunks/LpAppShell-Dgejipzz.js +0 -319
  619. package/dist/chunks/LpFileTree-CooHinsC.js +0 -425
  620. package/dist/chunks/LpThemeProvider-8MG6yqU9.js +0 -640
  621. package/dist/chunks/LpTopologyCanvas-B1gIbS0n.js +0 -298
@@ -0,0 +1,52 @@
1
+ import { computed, onScopeDispose, shallowRef, toValue, type MaybeRefOrGetter, type ShallowRef } from "vue"
2
+
3
+ /*
4
+ * One crosshair across charts of the same period: the x label hovered in one is
5
+ * marked in the others. Matched by label rather than by index, because two
6
+ * charts can hold different points or different windows of the same timeline.
7
+ *
8
+ * Pinned to a global symbol so a barrel and a deep import share the groups.
9
+ */
10
+ interface Hovered {
11
+ owner: symbol
12
+ label: string
13
+ }
14
+
15
+ const SYNC_KEY = Symbol.for("@leavepulse/ui:chart-sync")
16
+ type GlobalWithSync = typeof globalThis & { [SYNC_KEY]?: Map<string, ShallowRef<Hovered | null>> }
17
+ const groups = ((globalThis as GlobalWithSync)[SYNC_KEY] ??= new Map())
18
+
19
+ function groupOf(name: string): ShallowRef<Hovered | null> {
20
+ let group = groups.get(name)
21
+ if (!group) {
22
+ group = shallowRef<Hovered | null>(null)
23
+ groups.set(name, group)
24
+ }
25
+ return group
26
+ }
27
+
28
+ export function useChartSync(group: MaybeRefOrGetter<string | undefined>) {
29
+ const owner = Symbol("chart")
30
+ const shared = computed(() => {
31
+ const name = toValue(group)
32
+ return name ? groupOf(name) : null
33
+ })
34
+
35
+ /** The label another chart of the group is hovering. */
36
+ const peerLabel = computed(() => {
37
+ const hovered = shared.value?.value
38
+ return hovered && hovered.owner !== owner ? hovered.label : null
39
+ })
40
+
41
+ /** Tell the group what this chart hovers; null when the pointer left. */
42
+ function publish(label: string | null) {
43
+ const target = shared.value
44
+ if (!target) return
45
+ if (label != null) target.value = { owner, label }
46
+ else if (target.value?.owner === owner) target.value = null
47
+ }
48
+
49
+ onScopeDispose(() => publish(null))
50
+
51
+ return { peerLabel, publish }
52
+ }
@@ -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
- if (typeof current === "function") return await current()
51
- return await confirm({
52
- title: labels.value.title,
53
- description: labels.value.description,
54
- danger: true,
55
- icon: "lucide:triangle-alert",
56
- confirmLabel: labels.value.discard,
57
- cancelLabel: labels.value.keep,
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 instanceof Node && (event.currentTarget as Node | null)?.contains(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
- observer = new ResizeObserver(measure)
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
- /** Forget the draft. Call after applying it, and after a successful save. */
90
- discard: () => void
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 String(toValue(options.key) || "").trim()
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
- if (maxAge <= 0) return true
140
- // NaN when the stamp is unreadable, and NaN > maxAge is false — an
141
- // unreadable stamp is treated as "no idea how old", which errs towards
142
- // offering the draft rather than throwing away somebody's typing.
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 key = currentKey()
183
- hasDraft.value = false
184
- savedAt.value = null
185
- if (key) store.remove(key)
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
- const el = document.activeElement
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
- const node = target instanceof Node ? target : null
329
- return !!node && (el === node || el.contains(node))
308
+ return isNode(target) && (el === target || el.contains(target))
330
309
  }
331
310
 
332
- function topLayer(): Element | null {
333
- const layers = document.querySelectorAll("[data-dismissable-layer]")
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 instanceof Node ? el : null
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
- if (!(target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement)) return false
115
- const { text, caret } = stripDisallowed(target.value, re, target.selectionStart ?? target.value.length)
116
- if (text === target.value) return false
117
- target.value = text
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
- target.setSelectionRange(caret, caret)
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 instanceof HTMLInputElement)) return
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 instanceof HTMLInputElement)) return
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 instanceof HTMLInputElement) reformat(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 }