@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
@@ -14,6 +14,7 @@ export default { inheritAttrs: false }
14
14
  * viewport element and re-emits the native scroll event — exactly what tailing
15
15
  * needs.
16
16
  */
17
+ import { clamp } from "../composables/clamp"
17
18
  import {
18
19
  computed,
19
20
  nextTick,
@@ -38,7 +39,27 @@ import LpScrollArea from "./LpScrollArea.vue"
38
39
  import { useMergedAttrs } from "../composables/useMergedClass"
39
40
  import { useLabels } from "../composables/useLpConfig"
40
41
  import { useResizeObserver } from "../composables/useResizeObserver"
42
+ import { inTextField } from "../composables/textEntry"
43
+ import { isElement, nodeWindow } from "../composables/useView"
41
44
  import { countLevels, matchPositions, ringWindow, stepMatch } from "./logSearch"
45
+ import { downloadFile } from "./exportData"
46
+ import LpLogInspector from "./LpLogInspector.vue"
47
+ import {
48
+ compilePattern,
49
+ exportLines,
50
+ findIds,
51
+ groupRepeats,
52
+ inTimeRange,
53
+ messageParts,
54
+ nearestByTime,
55
+ patternPositions,
56
+ rowSpan,
57
+ termRanges,
58
+ type LogExportFormat,
59
+ type LogId,
60
+ type LogTimeRange,
61
+ type MessagePart,
62
+ } from "./logTools"
42
63
  import { TONES, toneLook, type ToneName } from "./tone"
43
64
 
44
65
  export interface LogViewerLabels {
@@ -66,6 +87,13 @@ export interface LogViewerLabels {
66
87
  matchCount: string
67
88
  noMatches: string
68
89
  levels: string
90
+ /** Toggle for reading the search as a regular expression. */
91
+ regex: string
92
+ invalidPattern: string
93
+ sources: string
94
+ groupRepeats: string
95
+ download: string
96
+ copySelection: string
69
97
  }
70
98
 
71
99
  export type LogLevel = "trace" | "debug" | "info" | "warn" | "error" | "fatal" | "success"
@@ -157,6 +185,29 @@ const props = withDefaults(
157
185
  * not pick them again every time.
158
186
  */
159
187
  persist?: string
188
+ /**
189
+ * Adds to the toolbar what reading a busy stream calls for: a regular
190
+ * expression toggle, source chips, folding repeats, and copy and download
191
+ * of the selection. Each is also its own model or prop.
192
+ */
193
+ tools?: boolean
194
+ /** Only lines inside this span (inclusive). A line with no readable time stays. */
195
+ timeRange?: LogTimeRange
196
+ /**
197
+ * Fold every repeat of a message into its first line with a count, wherever
198
+ * they sit: numbers, ids and hashes are blanked first, so "job 41 failed"
199
+ * and "job 42 failed" count as one. Stronger than `compact`, which keeps
200
+ * chronology by folding runs of the same text only.
201
+ */
202
+ group?: boolean
203
+ /** Make trace, request, span and correlation ids in a message clickable (`id-click`). */
204
+ linkIds?: boolean
205
+ /** Click selects a line, Shift+click a range (`v-model:selection`, `select`). */
206
+ selectable?: boolean
207
+ /** Show the selected line in an LpLogInspector under the stream. Needs `selectable`. */
208
+ inspector?: boolean
209
+ /** File name for a download, without its extension. */
210
+ fileName?: string
160
211
  labels?: Partial<LogViewerLabels>
161
212
  }>(),
162
213
  {
@@ -180,12 +231,25 @@ const emit = defineEmits<{
180
231
  * fires once. The viewer keeps the scroll anchored when the page prepends.
181
232
  */
182
233
  (e: "reach-top"): void
234
+ /** A line was selected: the link to whatever else on the page follows it. */
235
+ (e: "select", payload: { line: LogLine; index: number }): void
236
+ /** A correlation id was clicked (`linkIds`). */
237
+ (e: "id-click", payload: { kind: LogId["kind"]; value: string; line: LogLine }): void
183
238
  }>()
184
239
 
185
240
  /** The toolbar's search term. Without the toolbar, `highlight` is the term. */
186
241
  const query = defineModel<string>("search", { default: "" })
187
242
  /** Levels to show. Empty shows every level. */
188
243
  const levels = defineModel<LogLevel[]>("levels", { default: () => [] })
244
+ /** Read the search as a regular expression. */
245
+ const regex = defineModel<boolean>("regex", { default: false })
246
+ /** Sources to show. Empty shows every source. */
247
+ const sources = defineModel<string[]>("sources", { default: () => [] })
248
+ /** The selected span as original line numbers, first to last. */
249
+ const selection = defineModel<[number, number] | null>("selection", { default: null })
250
+ /** Fold repeats; the prop sets it, the toolbar's toggle flips it. */
251
+ const grouped = ref(!!props.group)
252
+ watch(() => props.group, (on) => (grouped.value = !!on))
189
253
  const storedLevels = usePersisted<string[] | null>(
190
254
  () => props.persist && `lp-log-viewer:${props.persist}:levels`,
191
255
  null,
@@ -221,6 +285,12 @@ const text = useLabels<LogViewerLabels>(
221
285
  matchCount: "{current} / {total}",
222
286
  noMatches: "No matches",
223
287
  levels: "Levels",
288
+ regex: "Regular expression",
289
+ invalidPattern: "Invalid pattern",
290
+ sources: "Sources",
291
+ groupRepeats: "Group repeats",
292
+ download: "Download",
293
+ copySelection: "Copy selection",
224
294
  },
225
295
  () => props.labels,
226
296
  )
@@ -354,12 +424,9 @@ function freeze(): boolean {
354
424
  // page and swallowing it would break them all.
355
425
  if (!hovered.value && !focusWithin()) return false
356
426
  if (frozen.value) return true
357
- // Snapshotted by reference, not copied: the array the consumer hands over is
358
- // replaced wholesale on every update, so holding the old one is enough — and
359
- // a copy of ten thousand lines on every keypress is not.
360
- // A capped stream is usually one array pushed into in place, which a
361
- // reference would not hold still; its window is small enough to copy.
362
- frozenLines.value = props.maxLines ? props.lines.slice(-props.maxLines) : props.lines
427
+ // Copied, whatever the cap: a stream pushed into in place would move under a
428
+ // reference. This runs once per hold, not per keypress or per line.
429
+ frozenLines.value = props.maxLines ? props.lines.slice(-props.maxLines) : props.lines.slice()
363
430
  frozen.value = true
364
431
  return true
365
432
  }
@@ -382,7 +449,7 @@ const hovered = ref(false)
382
449
 
383
450
  function focusWithin() {
384
451
  const el = root.value
385
- return !!el && el.contains(document.activeElement)
452
+ return !!el && el.contains(el.ownerDocument.activeElement)
386
453
  }
387
454
 
388
455
  // `when` rather than a bare decline: several viewers on one page all bind these
@@ -401,13 +468,21 @@ function onKeyup(event: KeyboardEvent) {
401
468
  if (event.key === "Control" || event.key === "Meta") thaw()
402
469
  }
403
470
 
471
+ // Inside an LpFrame the keyup lands in whichever window holds the focus: the
472
+ // frame's, or the page's, which is where a hold over the frame can start.
473
+ let keyWindows: Window[] = []
404
474
  onMounted(() => {
405
- window.addEventListener("keyup", onKeyup)
406
- window.addEventListener("blur", thaw)
475
+ keyWindows = [...new Set<Window>([window, root.value ? nodeWindow(root.value) : window])]
476
+ for (const win of keyWindows) {
477
+ win.addEventListener("keyup", onKeyup as EventListener)
478
+ win.addEventListener("blur", thaw)
479
+ }
407
480
  })
408
481
  onBeforeUnmount(() => {
409
- window.removeEventListener("keyup", onKeyup)
410
- window.removeEventListener("blur", thaw)
482
+ for (const win of keyWindows) {
483
+ win.removeEventListener("keyup", onKeyup as EventListener)
484
+ win.removeEventListener("blur", thaw)
485
+ }
411
486
  })
412
487
 
413
488
  const parsedLines = computed<LogLine[]>(() =>
@@ -418,13 +493,28 @@ const parsedLines = computed<LogLine[]>(() =>
418
493
  // truthful when filtering, plus a `count` for compact mode (1 unless folded).
419
494
  // With filterMatches + a search term, keep only lines whose message contains it
420
495
  // (case-insensitive); otherwise pass everything.
496
+ const compiled = computed(() => (regex.value && term.value ? compilePattern(term.value) : null))
497
+ const pattern = computed(() => compiled.value?.pattern ?? null)
498
+ const patternFailed = computed(() => !!compiled.value?.error)
499
+
421
500
  const visibleLines = computed<{ line: LogLine; n: number; count: number }[]>(() => {
422
501
  const needle = props.filterMatches ? term.value.toLowerCase() : ""
502
+ const wantedSources = sources.value.length ? new Set(sources.value) : null
503
+ const inRegex = regex.value && !!needle
423
504
  const shown = levels.value.length ? new Set<LogLevel>(levels.value) : null
424
505
  const filtered = parsedLines.value
425
506
  .map((line, n) => ({ line, n }))
426
507
  .filter(({ line }) => !shown || shown.has(line.level ?? "info"))
427
- .filter(({ line }) => !needle || matchPositions([line], needle).length > 0)
508
+ .filter(({ line }) => !wantedSources || (line.source !== undefined && wantedSources.has(line.source)))
509
+ .filter(({ line }) => inTimeRange(line.time, props.timeRange))
510
+ .filter(({ line }) => inRegex || !needle || matchPositions([line], needle).length > 0)
511
+
512
+ if (inRegex) {
513
+ const found = pattern.value ? patternPositions(filtered.map((row) => row.line), pattern.value) : []
514
+ const kept = found.map((i) => filtered[i])
515
+ return grouped.value ? groupRepeats(kept) : kept.map((row) => ({ ...row, count: 1 }))
516
+ }
517
+ if (grouped.value) return groupRepeats(filtered)
428
518
 
429
519
  if (!props.compact) return filtered.map((row) => ({ ...row, count: 1 }))
430
520
 
@@ -470,6 +560,13 @@ function lineKey(n: number): number {
470
560
  const LEVEL_ORDER: LogLevel[] = ["trace", "debug", "info", "success", "warn", "error", "fatal"]
471
561
  const levelCounts = computed(() => countLevels<LogLevel>(parsedLines.value, "info"))
472
562
  const presentLevels = computed(() => LEVEL_ORDER.filter((l) => levelCounts.value.has(l)))
563
+ const presentSources = computed(() => [...new Set(parsedLines.value.flatMap((l) => (l.source ? [l.source] : [])))].sort())
564
+
565
+ function toggleSource(source: string) {
566
+ sources.value = sources.value.includes(source)
567
+ ? sources.value.filter((s) => s !== source)
568
+ : [...sources.value, source]
569
+ }
473
570
 
474
571
  function toggleLevel(level: LogLevel) {
475
572
  levels.value = levels.value.includes(level)
@@ -477,7 +574,11 @@ function toggleLevel(level: LogLevel) {
477
574
  : [...levels.value, level]
478
575
  }
479
576
 
480
- const matches = computed(() => matchPositions(visibleLines.value.map((r) => r.line), term.value))
577
+ const matches = computed(() => {
578
+ const rows = visibleLines.value.map((r) => r.line)
579
+ if (!regex.value) return matchPositions(rows, term.value)
580
+ return pattern.value ? patternPositions(rows, pattern.value) : []
581
+ })
481
582
  const current = ref(-1)
482
583
  const currentRow = computed(() => {
483
584
  const pos = matches.value[current.value]
@@ -492,6 +593,7 @@ watch(matches, (list) => {
492
593
 
493
594
  const matchLabel = computed(() => {
494
595
  if (!term.value) return ""
596
+ if (patternFailed.value) return text.value.invalidPattern
495
597
  const total = matches.value.length
496
598
  if (!total) return text.value.noMatches
497
599
  return text.value.matchCount
@@ -542,10 +644,62 @@ useHotkeys(() => [
542
644
  { key: "f3", shift: true, allowInInput: true, when: searching, handler: () => step(-1) },
543
645
  ])
544
646
 
647
+ // ── selection, export, jump ─────────────────────────────────────────
648
+ let selectAnchor: number | null = null
649
+
650
+ function onRowClick(event: MouseEvent) {
651
+ if (!props.selectable || !isElement(event.target)) return
652
+ // The end of a drag across text is the user copying it, not choosing a line.
653
+ if (nodeWindow(event.target).getSelection()?.isCollapsed === false) return
654
+ if (event.target.closest("button")) return
655
+ const el = event.target.closest<HTMLElement>("[data-log-row]")
656
+ const n = el ? Number(el.dataset.logRow) : Number.NaN
657
+ const line = parsedLines.value[n]
658
+ if (!line) return
659
+ const range = event.shiftKey && selectAnchor !== null
660
+ if (!range) selectAnchor = n
661
+ selection.value = range ? rowSpan(selectAnchor as number, n) : [n, n]
662
+ emit("select", { line, index: n })
663
+ }
664
+
665
+ const isSelected = (n: number) => !!selection.value && n >= selection.value[0] && n <= selection.value[1]
666
+ const selectedLine = computed(() => (selection.value ? parsedLines.value[selection.value[0]] : undefined))
667
+
668
+ // What a selection covers, or everything shown when nothing is selected. Hidden
669
+ // lines inside the span stay out: what is exported is what was on screen.
670
+ function chosenLines(): LogLine[] {
671
+ const span = selection.value
672
+ const rows = visibleLines.value.filter((row) => !span || (row.n >= span[0] && row.n <= span[1]))
673
+ return rows.map((row) => row.line)
674
+ }
675
+
676
+ function copySelection() {
677
+ return copy(exportLines(chosenLines(), "text", lineText))
678
+ }
679
+
680
+ function downloadSelection(format: LogExportFormat = "text") {
681
+ const extension = format === "ndjson" ? "ndjson" : "log"
682
+ downloadFile(`${props.fileName ?? "logs"}.${extension}`, exportLines(chosenLines(), format, lineText), undefined, root.value?.ownerDocument)
683
+ }
684
+
685
+ /** Scrolls to the line closest to `time` and selects it. False when no line has a readable time. */
686
+ function jumpToTime(time: number | string): boolean {
687
+ const position = nearestByTime(visibleLines.value.map((row) => row.line), time)
688
+ if (position < 0) return false
689
+ const { n } = visibleLines.value[position]
690
+ selection.value = [n, n]
691
+ pinned.value = false
692
+ nextTick(() => revealMatch(position))
693
+ return true
694
+ }
695
+
545
696
  defineExpose({
546
697
  next: () => step(1),
547
698
  previous: () => step(-1),
548
699
  focusSearch: () => searchEl.value?.focus(),
700
+ jumpToTime,
701
+ copySelection,
702
+ downloadSelection,
549
703
  })
550
704
 
551
705
  // True when filtering has emptied an otherwise non-empty stream.
@@ -642,11 +796,12 @@ function menuFor(line: LogLine, index: number): ContextMenuItemDef[] {
642
796
 
643
797
  // Split a message around the (case-insensitive) highlight term so we can wrap
644
798
  // matches in <mark> without v-html. Empty/absent term → single plain part.
645
- interface Part {
646
- text: string
647
- hit: boolean
648
- }
799
+ type Part = MessagePart
649
800
  function splitHighlight(message: string): Part[] {
801
+ if (props.linkIds || regex.value) {
802
+ const hits = regex.value ? (pattern.value?.ranges(message) ?? []) : termRanges(message, term.value)
803
+ return messageParts(message, hits, props.linkIds ? findIds(message) : [])
804
+ }
650
805
  if (!term.value) return [{ text: message, hit: false }]
651
806
  const parts: Part[] = []
652
807
  const lower = message.toLowerCase()
@@ -859,7 +1014,7 @@ function rideToBottom() {
859
1014
  const ease = tokenEase("ease-emphasized")
860
1015
  const started = performance.now()
861
1016
  const step = (now: number) => {
862
- const t = Math.min(1, Math.max(0, (now - started) / ms))
1017
+ const t = clamp((now - started) / ms, 0, 1)
863
1018
  el.scrollTop = from + (end() - from) * ease(t)
864
1019
  glide = t < 1 ? requestAnimationFrame(step) : 0
865
1020
  }
@@ -897,27 +1052,31 @@ function onWheel(event: WheelEvent) {
897
1052
  const UPWARD_KEYS = new Set(["ArrowUp", "PageUp", "Home"])
898
1053
 
899
1054
  function onKeydown(event: KeyboardEvent) {
900
- const field = event.target instanceof HTMLElement && event.target.closest("input, textarea, [contenteditable]")
901
- if (!field && UPWARD_KEYS.has(event.key)) leaveTail()
1055
+ if (!inTextField(event.target) && UPWARD_KEYS.has(event.key)) leaveTail()
902
1056
  }
903
1057
 
1058
+ let holdWindow: Window | null = null
1059
+
904
1060
  function release() {
905
1061
  holding = false
906
- window.removeEventListener("pointerup", release)
907
- window.removeEventListener("pointercancel", release)
908
- window.removeEventListener("touchend", release)
1062
+ holdWindow?.removeEventListener("pointerup", release)
1063
+ holdWindow?.removeEventListener("pointercancel", release)
1064
+ holdWindow?.removeEventListener("touchend", release)
1065
+ holdWindow = null
909
1066
  }
910
1067
 
911
1068
  function hold(event: Event) {
912
1069
  // The scroll area's root, so its scrollbar (a sibling of the viewport)
913
1070
  // counts, and the toolbar and jump pill above it do not.
914
1071
  const area = viewport()?.parentElement
915
- if (!area || !(event.target instanceof Node) || !area.contains(event.target)) return
1072
+ if (!area || !isElement(event.target) || !area.contains(event.target)) return
916
1073
  stopGlide()
1074
+ release()
917
1075
  holding = true
918
- window.addEventListener("pointerup", release)
919
- window.addEventListener("pointercancel", release)
920
- window.addEventListener("touchend", release)
1076
+ holdWindow = nodeWindow(area)
1077
+ holdWindow.addEventListener("pointerup", release)
1078
+ holdWindow.addEventListener("pointercancel", release)
1079
+ holdWindow.addEventListener("touchend", release)
921
1080
  }
922
1081
 
923
1082
  function scrollToBottom() {
@@ -1141,6 +1300,43 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(() =>
1141
1300
  <span class="font-normal tabular-nums text-muted">{{ levelCounts.get(level) }}</span>
1142
1301
  </button>
1143
1302
  </div>
1303
+ <template v-if="tools">
1304
+ <button
1305
+ type="button"
1306
+ class="rounded-xs px-1.5 py-0.5 font-mono text-[11px] outline-none focus-visible:ring-2 focus-visible:ring-ring"
1307
+ :class="regex ? 'bg-surface-soft text-ink' : 'text-muted hover:text-ink'"
1308
+ :aria-label="text.regex"
1309
+ :aria-pressed="regex"
1310
+ @click="regex = !regex"
1311
+ >.*</button>
1312
+ <button
1313
+ type="button"
1314
+ class="rounded-xs p-1 outline-none focus-visible:ring-2 focus-visible:ring-ring"
1315
+ :class="grouped ? 'bg-surface-soft text-ink' : 'text-muted hover:text-ink'"
1316
+ :aria-label="text.groupRepeats"
1317
+ :aria-pressed="grouped"
1318
+ @click="grouped = !grouped"
1319
+ >
1320
+ <LpIcon name="lucide:layers" :size="14" />
1321
+ </button>
1322
+ <button type="button" class="rounded-xs p-1 text-muted outline-none hover:text-ink focus-visible:ring-2 focus-visible:ring-ring" :aria-label="text.copySelection" @click="copySelection">
1323
+ <LpIcon name="lucide:copy" :size="14" />
1324
+ </button>
1325
+ <button type="button" class="rounded-xs p-1 text-muted outline-none hover:text-ink focus-visible:ring-2 focus-visible:ring-ring" :aria-label="text.download" @click="downloadSelection()">
1326
+ <LpIcon name="lucide:download" :size="14" />
1327
+ </button>
1328
+ <div v-if="presentSources.length > 1" role="group" :aria-label="text.sources" class="flex flex-wrap items-center gap-1">
1329
+ <button
1330
+ v-for="source in presentSources"
1331
+ :key="source"
1332
+ type="button"
1333
+ class="rounded-pill border px-2 py-0.5 text-[10px] outline-none transition-colors focus-visible:ring-2 focus-visible:ring-ring"
1334
+ :class="sources.includes(source) ? 'border-line-strong bg-surface-soft text-ink' : 'border-line text-muted hover:text-ink'"
1335
+ :aria-pressed="sources.includes(source)"
1336
+ @click="toggleSource(source)"
1337
+ >{{ source }}</button>
1338
+ </div>
1339
+ </template>
1144
1340
  </div>
1145
1341
 
1146
1342
  <!-- `instant`: this viewer decides for itself when a jump animates (see
@@ -1196,6 +1392,7 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(() =>
1196
1392
  :is="virtualise ? 'ol' : TransitionGroup"
1197
1393
  v-bind="virtualise ? {} : transitionProps"
1198
1394
  class="py-1"
1395
+ @click="onRowClick"
1199
1396
  @contextmenu="onRowContext"
1200
1397
  @pointerdown="onRowPointerDown"
1201
1398
  >
@@ -1210,8 +1407,9 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(() =>
1210
1407
  :key="lineKey(n)"
1211
1408
  :data-log-row="n"
1212
1409
  class="group relative flex items-start gap-0 px-0 leading-5 transition-colors hover:bg-surface-soft/60"
1213
- :class="[metaFor(line.level).sel, n === currentRow ? 'bg-accent/15' : '', isFresh(n) ? 'lp-log-row-fresh' : '']"
1410
+ :class="[metaFor(line.level).sel, n === currentRow ? 'bg-accent/15' : '', isFresh(n) ? 'lp-log-row-fresh' : '', isSelected(n) ? 'bg-brand/15' : '']"
1214
1411
  :aria-current="n === currentRow ? 'true' : undefined"
1412
+ :data-selected="isSelected(n) ? '' : undefined"
1215
1413
  >
1216
1414
  <!-- level rail -->
1217
1415
  <!-- Level rail: absolutely positioned so it spans the FULL row height
@@ -1262,8 +1460,14 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(() =>
1262
1460
  v-for="(part, p) in splitHighlight(virtualise ? line.message.replace(/\r?\n/g, ' ↵ ') : line.message)"
1263
1461
  :key="p"
1264
1462
  >
1463
+ <button
1464
+ v-if="part.id"
1465
+ type="button"
1466
+ class="rounded-xs text-brand underline outline-none hover:text-ink focus-visible:ring-2 focus-visible:ring-ring"
1467
+ @click="emit('id-click', { kind: part.id.kind, value: part.id.value, line })"
1468
+ >{{ part.text }}</button>
1265
1469
  <mark
1266
- v-if="part.hit"
1470
+ v-else-if="part.hit"
1267
1471
  class="rounded-xs bg-accent/30 text-ink"
1268
1472
  >{{ part.text }}</mark>
1269
1473
  <template v-else>{{ part.text }}</template>
@@ -1296,6 +1500,12 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(() =>
1296
1500
  </template>
1297
1501
  </LpScrollArea>
1298
1502
 
1503
+ <LpLogInspector
1504
+ v-if="inspector && selectedLine"
1505
+ :message="selectedLine.message"
1506
+ class="max-h-64 overflow-auto border-t border-line p-3"
1507
+ />
1508
+
1299
1509
  <!-- jump-to-latest: shown only when tailing and scrolled away. The
1300
1510
  Transition rides an outer wrapper so its transform/opacity don't fight
1301
1511
  the button's own -translate-x-1/2 centring and hover colour transition. -->
@@ -20,6 +20,7 @@ export default { inheritAttrs: false }
20
20
  * layer first and swaps the tile pyramid only once the animation lands, which
21
21
  * is how the zoom reads as continuous instead of as a hard cut between levels.
22
22
  */
23
+ import { clamp } from "../composables/clamp"
23
24
  import { computed, onBeforeUnmount, ref, watch } from "vue"
24
25
  import { prefersReducedMotion } from "../composables/easing"
25
26
  import { type LatLon, OSM_TILES, type TileSource, project, tileUrl, unproject } from "./address"
@@ -107,7 +108,7 @@ let zoomTimer: ReturnType<typeof setTimeout> | undefined
107
108
  let pruneTimer: ReturnType<typeof setTimeout> | undefined
108
109
 
109
110
  function clampZoom(value: number) {
110
- return Math.round(Math.min(maxZoom.value, Math.max(minZoom.value, value)))
111
+ return Math.round(clamp(value, minZoom.value, maxZoom.value))
111
112
  }
112
113
 
113
114
  /** World-pixel coordinate of the viewport's top-left corner, at `level`. */
@@ -26,6 +26,7 @@ export default { inheritAttrs: false }
26
26
  * DOM order is the items' order, which is also the reading order for
27
27
  * keyboard and screen readers.
28
28
  */
29
+ import { isHTMLElement, nodeWindow } from "../composables/useView"
29
30
  import { computed, onBeforeUnmount, onMounted, reactive, ref, watch } from "vue"
30
31
  import { easingToken, prefersReducedMotion } from "../composables/easing"
31
32
  import { useMergedAttrs } from "../composables/useMergedClass"
@@ -91,7 +92,7 @@ function heightOf(entry: ResizeObserverEntry): number {
91
92
 
92
93
  function setItem(key: string | number, el: unknown) {
93
94
  const previous = elements.get(key)
94
- if (el instanceof HTMLElement) {
95
+ if (isHTMLElement(el)) {
95
96
  if (previous === el) return
96
97
  if (previous) observer?.unobserve(previous)
97
98
  elements.set(key, el)
@@ -108,11 +109,12 @@ function setItem(key: string | number, el: unknown) {
108
109
  }
109
110
 
110
111
  onMounted(() => {
111
- if (typeof ResizeObserver === "undefined") {
112
+ const Observer = root.value ? nodeWindow(root.value).ResizeObserver : undefined
113
+ if (!Observer) {
112
114
  width.value = root.value?.clientWidth ?? 0
113
115
  return
114
116
  }
115
- observer = new ResizeObserver((entries) => {
117
+ observer = new Observer((entries) => {
116
118
  for (const entry of entries) {
117
119
  if (entry.target === root.value) {
118
120
  width.value = entry.contentRect.width
@@ -195,8 +197,9 @@ const hidden = computed(() => !ready.value || !revealed.value)
195
197
  watch(
196
198
  () => ready.value && revealed.value,
197
199
  (go) => {
198
- if (!go || !props.entrance || prefersReducedMotion()) return
199
- const easing = easingToken("ease-emphasized")
200
+ const box = root.value
201
+ if (!go || !box || !props.entrance || prefersReducedMotion(nodeWindow(box))) return
202
+ const easing = easingToken("ease-emphasized", undefined, box)
200
203
  // Stagger by the order items are placed in, which reads top to bottom.
201
204
  keys.value.forEach((key, index) => {
202
205
  const el = elements.get(key)
@@ -1,4 +1,5 @@
1
1
  <script setup lang="ts">
2
+ import { isElement } from "../composables/realm"
2
3
  import {
3
4
  DialogClose,
4
5
  DialogContent,
@@ -11,7 +12,7 @@ import {
11
12
  import { computed, onBeforeUnmount, ref, useSlots, watch } from "vue"
12
13
  import { useCloseGuard, type CloseGuard } from "../composables/useCloseGuard"
13
14
  import { useGlass } from "../composables/useGlass"
14
- import { useOverlayHistory, type OverlayHistoryMode } from "../composables/useOverlayHistory"
15
+ import { useModelOverlayHistory, type OverlayHistoryMode } from "../composables/useOverlayHistory"
15
16
  import { useLabels } from "../composables/useLpConfig"
16
17
  import { useShift } from "../composables/useShift"
17
18
  import { useModalLayer } from "./modalDepth"
@@ -65,7 +66,9 @@ const props = withDefaults(
65
66
  * happens if the DOM order is left to decide.
66
67
  *
67
68
  * `"none"` leaves reka's own behaviour alone; pass a CSS selector to name
68
- * the element yourself.
69
+ * the element yourself. A custom control the list cannot recognise (a
70
+ * canvas editor, a composite widget) marks its entry point with
71
+ * `data-lp-autofocus` and a tabindex.
69
72
  */
70
73
  autoFocus?: "auto" | "none" | string
71
74
  /**
@@ -129,16 +132,11 @@ function close() {
129
132
  void onOpenChange(false)
130
133
  }
131
134
 
132
- useOverlayHistory({
135
+ useModelOverlayHistory({
133
136
  mode: () => props.history,
134
137
  open: () => !!props.open,
135
- close: async () => {
136
- if (!(await allowClose())) return false
137
- emit("update:open", false)
138
- return true
139
- },
140
- reopen: () => emit("update:open", true),
141
- navigated: () => emit("update:open", false),
138
+ setOpen: (open) => emit("update:open", open),
139
+ allowClose,
142
140
  })
143
141
  defineExpose({ close })
144
142
 
@@ -161,7 +159,7 @@ const onInteractOutside = (event: Event) => {
161
159
  guardOutside(event)
162
160
  if (!props.dismissible) return event.preventDefault()
163
161
  const target = event.target
164
- if (target instanceof Element && target.closest("[data-lp-modal-aside]")) {
162
+ if (isElement(target) && target.closest("[data-lp-modal-aside]")) {
165
163
  event.preventDefault()
166
164
  }
167
165
  }
@@ -233,6 +231,8 @@ const AUTO_FOCUS_ORDER = [
233
231
  "input:not([type=hidden]):not([disabled]):not([readonly]):not([tabindex='-1'])",
234
232
  "textarea:not([disabled]):not([readonly])",
235
233
  "select:not([disabled])",
234
+ "[contenteditable]:not([contenteditable='false'])",
235
+ "[role='textbox']",
236
236
  "[data-lp-autofocus]",
237
237
  "button:not([disabled]):not([data-lp-dialog-close])",
238
238
  "[href]",
@@ -273,7 +273,7 @@ function onOpenAutoFocus(event: Event) {
273
273
  target.focus()
274
274
  // Only once focus really landed: a prevented auto-focus that failed would
275
275
  // leave the keyboard on the page behind the dialog.
276
- if (document.activeElement !== target) continue
276
+ if (target.ownerDocument.activeElement !== target) continue
277
277
  event.preventDefault()
278
278
  // `focus-visible` is the browser's own heuristic and cannot be forced, so
279
279
  // the ring is driven off an attribute the kit owns. Skipped for a control
@@ -138,6 +138,7 @@ const railPanel = computed(() => [
138
138
  "rounded-card border border-line p-2 shadow-panel",
139
139
  frosted.value ? "lp-glass-overlay" : "bg-surface-raised",
140
140
  ])
141
+ const railSlot = computed(() => (props.navSide === "end" ? "asideEnd" : "aside"))
141
142
  </script>
142
143
 
143
144
  <template>
@@ -154,27 +155,7 @@ const railPanel = computed(() => [
154
155
  <!-- The gap sits on a wrapper rather than on LpSidebar itself: LpSidebar
155
156
  splits its `class` between its root and the inner `nav`, so a margin
156
157
  given to it lands on both. -->
157
- <template v-if="hasNav && navSide === 'start'" #aside>
158
- <div :class="railClass">
159
- <LpSidebar
160
- v-model="active"
161
- v-model:open="navOpen"
162
- variant="panel"
163
- :items="items"
164
- :sections="sections"
165
- :width="navWidth"
166
- :searchable="searchable"
167
- :search-placeholder="searchPlaceholder"
168
- :loading="loading"
169
- responsive
170
- :mobile-breakpoint="mobileBreakpoint"
171
- :style="railStyle"
172
- :class="railPanel"
173
- />
174
- </div>
175
- </template>
176
-
177
- <template v-if="hasNav && navSide === 'end'" #asideEnd>
158
+ <template v-if="hasNav" #[railSlot]>
178
159
  <div :class="railClass">
179
160
  <LpSidebar
180
161
  v-model="active"