@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,222 @@
1
+ import { computed, inject, provide, ref, shallowRef, toValue, watch, type InjectionKey, type MaybeRefOrGetter, type Ref, type ShallowRef } from "vue"
2
+ import type { ChartAnnotation } from "../components/chart"
3
+ import type { ChartRange } from "../components/chartWindow"
4
+ import { inTimeRange, nearestByTime, type LogId, type LogTimeRange } from "../components/logTools"
5
+ import { stepKey, type PipelineStep } from "../components/pipeline"
6
+
7
+ /*
8
+ * What a monitoring screen shares: which thing is selected, which stretch of
9
+ * time is on show, which request is being followed. The table, the graph, the
10
+ * log and the chart each keep their own API; a `link*` binder turns this state
11
+ * into the props and listeners of one of them, for `v-bind`:
12
+ *
13
+ * const view = provideLinkedView()
14
+ * const table = linkTable(view, { kind: "server" })
15
+ * const log = linkLog(view, { kind: "server" })
16
+ *
17
+ * <LpTable v-bind="table" :rows row-key="id" selectable />
18
+ * <LpLogViewer v-bind="log" :lines selectable />
19
+ *
20
+ * Set a kind when a screen holds several sorts of thing: a binder only answers
21
+ * to its own, so picking a deployment leaves the server graph where it was.
22
+ */
23
+ export type LinkedId = string | number
24
+
25
+ export interface LinkedEntity {
26
+ id: LinkedId
27
+ kind?: string
28
+ }
29
+
30
+ /** A point of interest on the shared timeline, such as a log line. */
31
+ export interface LinkedMoment {
32
+ time: number | string
33
+ label: string
34
+ }
35
+
36
+ export interface LinkedView {
37
+ entity: ShallowRef<LinkedEntity | null>
38
+ timeRange: ShallowRef<LogTimeRange | null>
39
+ moment: ShallowRef<LinkedMoment | null>
40
+ traceId: Ref<string | null>
41
+ select(entity: LinkedEntity | null): void
42
+ clear(): void
43
+ }
44
+
45
+ export function createLinkedView(): LinkedView {
46
+ const entity = shallowRef<LinkedEntity | null>(null)
47
+ const timeRange = shallowRef<LogTimeRange | null>(null)
48
+ const moment = shallowRef<LinkedMoment | null>(null)
49
+ const traceId = ref<string | null>(null)
50
+ return {
51
+ entity,
52
+ timeRange,
53
+ moment,
54
+ traceId,
55
+ // The same thing again is no change, so a binder echoing a selection back
56
+ // (a focused node reports itself selected) cannot start a loop.
57
+ select(next) {
58
+ const now = entity.value
59
+ if (next?.id !== now?.id || next?.kind !== now?.kind) entity.value = next
60
+ },
61
+ clear() {
62
+ entity.value = null
63
+ timeRange.value = null
64
+ moment.value = null
65
+ traceId.value = null
66
+ },
67
+ }
68
+ }
69
+
70
+ const LP_LINKED_VIEW: InjectionKey<LinkedView> = Symbol.for("lp-linked-view")
71
+
72
+ /** Shares a view with everything below the calling component. */
73
+ export function provideLinkedView(view: LinkedView = createLinkedView()): LinkedView {
74
+ provide(LP_LINKED_VIEW, view)
75
+ return view
76
+ }
77
+
78
+ /** The view provided above; a private one with none, so a panel works alone. */
79
+ export function useLinkedView(): LinkedView {
80
+ return inject(LP_LINKED_VIEW, null) ?? createLinkedView()
81
+ }
82
+
83
+ interface LinkOptions {
84
+ /** The sort of entity this component shows. Unset answers to any. */
85
+ kind?: string
86
+ }
87
+
88
+ const answersTo = (entity: LinkedEntity | null, kind: string | undefined): entity is LinkedEntity =>
89
+ !!entity && (kind === undefined || entity.kind === kind)
90
+
91
+ /** v-bind for LpTable: single selection, whatever the table's `selected` held before. */
92
+ export function linkTable(view: LinkedView, options: LinkOptions = {}) {
93
+ return computed(() => {
94
+ const entity = view.entity.value
95
+ const current = answersTo(entity, options.kind) ? entity.id : null
96
+ return {
97
+ selected: current === null ? [] : [current],
98
+ "onUpdate:selected": (keys: LinkedId[]) => {
99
+ const picked = keys.find((key) => key !== current) ?? keys[0]
100
+ view.select(picked === undefined ? null : { id: picked, kind: options.kind })
101
+ },
102
+ }
103
+ })
104
+ }
105
+
106
+ /** What linkTopology drives: LpTopologyCanvas's exposed `focusNode`. */
107
+ export interface LinkedCanvas {
108
+ focusNode(id: string, options?: { keepFocus?: boolean }): Promise<boolean>
109
+ }
110
+
111
+ /** v-bind for LpTopologyCanvas; `canvas` is its template ref, focused on a selection from elsewhere. */
112
+ export function linkTopology(view: LinkedView, canvas: Ref<LinkedCanvas | null>, options: LinkOptions = {}) {
113
+ watch(
114
+ view.entity,
115
+ (entity) => {
116
+ if (answersTo(entity, options.kind)) void canvas.value?.focusNode(String(entity.id), { keepFocus: true })
117
+ },
118
+ { flush: "post" },
119
+ )
120
+ return computed(() => ({
121
+ onNodeSelect: (id: string) => view.select({ id, kind: options.kind }),
122
+ }))
123
+ }
124
+
125
+ export interface LinkLogOptions extends LinkOptions {
126
+ /** The log sources of an entity. Defaults to its id. */
127
+ sourcesOf?: (entity: LinkedEntity) => string[]
128
+ }
129
+
130
+ /**
131
+ * v-bind for LpLogViewer. The filters the selection and the trace set stay
132
+ * local, so the viewer's own chips and search box go on working; typing over a
133
+ * followed trace stops following it. Picking a line marks it on the timeline.
134
+ */
135
+ export function linkLog(view: LinkedView, options: LinkLogOptions = {}) {
136
+ const sourcesOf = options.sourcesOf ?? ((entity: LinkedEntity) => [String(entity.id)])
137
+ const sources = shallowRef<string[]>([])
138
+ const search = ref("")
139
+ watch(view.entity, (entity) => (sources.value = answersTo(entity, options.kind) ? sourcesOf(entity) : []))
140
+ watch(view.traceId, (id, old) => {
141
+ if (id !== null) search.value = id
142
+ else if (search.value === old) search.value = ""
143
+ })
144
+ return computed(() => ({
145
+ sources: sources.value,
146
+ search: search.value,
147
+ // A viewer with no toolbar reads its term from here instead.
148
+ highlight: search.value,
149
+ // A search only marks its hits; a followed trace is meant to leave just its lines.
150
+ filterMatches: view.traceId.value !== null,
151
+ timeRange: view.timeRange.value ?? undefined,
152
+ "onUpdate:sources": (next: string[]) => (sources.value = next),
153
+ "onUpdate:search": (next: string) => {
154
+ search.value = next
155
+ if (next !== view.traceId.value) view.traceId.value = null
156
+ },
157
+ onSelect: ({ line }: { line: { time?: number | string; message: string } }) => {
158
+ view.moment.value = line.time === undefined ? null : { time: line.time, label: line.message }
159
+ },
160
+ onIdClick: ({ value }: { kind: LogId["kind"]; value: string }) => (view.traceId.value = value),
161
+ }))
162
+ }
163
+
164
+ export interface LinkChartOptions {
165
+ /** The time of each point, oldest first, in step with the chart's `labels`. */
166
+ times: MaybeRefOrGetter<readonly (number | string)[]>
167
+ /** The chart's own annotations, kept beside the linked one. */
168
+ annotations?: MaybeRefOrGetter<readonly ChartAnnotation[] | undefined>
169
+ }
170
+
171
+ /** v-bind for LpChart: the shared time range is its window, the marked moment an annotation. */
172
+ export function linkChart(view: LinkedView, options: LinkChartOptions) {
173
+ const rows = computed(() => toValue(options.times).map((time) => ({ time })))
174
+ return computed(() => {
175
+ const times = toValue(options.times)
176
+ const last = times.length - 1
177
+ const shared = view.timeRange.value
178
+ const moment = view.moment.value
179
+ const onChart = !!moment && last >= 0 && inTimeRange(moment.time, { from: times[0], to: times[last] })
180
+ const range: ChartRange | null = shared && last >= 0
181
+ ? {
182
+ start: shared.from === undefined ? 0 : Math.max(0, nearestByTime(rows.value, shared.from)),
183
+ end: shared.to === undefined ? last : Math.max(0, nearestByTime(rows.value, shared.to)),
184
+ }
185
+ : null
186
+ return {
187
+ range,
188
+ annotations: [
189
+ ...(toValue(options.annotations) ?? []),
190
+ ...(onChart ? [{ at: nearestByTime(rows.value, moment.time), label: moment.label }] : []),
191
+ ],
192
+ "onUpdate:range": (next: ChartRange | null) => {
193
+ view.timeRange.value = next && { from: times[next.start], to: times[next.end] }
194
+ },
195
+ }
196
+ })
197
+ }
198
+
199
+ export interface LinkPipelineOptions extends LinkOptions {
200
+ /** The steps on show; a getter, as they usually follow the selection. */
201
+ steps: MaybeRefOrGetter<readonly PipelineStep[]>
202
+ }
203
+
204
+ /** v-bind for LpPipeline: selecting opens what failed, and the rows stay the reader's to toggle. */
205
+ export function linkPipeline(view: LinkedView, options: LinkPipelineOptions) {
206
+ const expanded = shallowRef<string[]>([])
207
+ const failedKeys = (): string[] =>
208
+ toValue(options.steps).flatMap((step, index) => (step.status === "failed" ? [stepKey(step, index)] : []))
209
+ watch(
210
+ [view.entity, () => failedKeys().join("\0")],
211
+ ([entity]) => {
212
+ if (!answersTo(entity, options.kind)) return
213
+ expanded.value = [...new Set([...expanded.value, ...failedKeys()])]
214
+ },
215
+ { flush: "post" },
216
+ )
217
+ return computed(() => ({
218
+ expanded: expanded.value,
219
+ "onUpdate:expanded": (next: string[]) => (expanded.value = next),
220
+ }))
221
+ }
222
+
@@ -17,7 +17,12 @@ type ToggleEmit = {
17
17
  * Shared by LpSwitch and LpCheckbox so a setting saved from either behaves
18
18
  * the same.
19
19
  */
20
- export function useOptimisticToggle(action: () => ((value: boolean) => unknown) | undefined, emit: ToggleEmit) {
20
+ export function useOptimisticToggle(
21
+ action: () => ((value: boolean) => unknown) | undefined,
22
+ emit: ToggleEmit,
23
+ /** Puts back what a boolean cannot say: a checkbox's mixed state. */
24
+ rolledBack?: () => void,
25
+ ) {
21
26
  const toast = useToast()
22
27
  const instance = getCurrentInstance()
23
28
  const pending = ref(false)
@@ -33,6 +38,7 @@ export function useOptimisticToggle(action: () => ((value: boolean) => unknown)
33
38
  emit("done", value)
34
39
  } catch (error) {
35
40
  emit("update:modelValue", !value)
41
+ rolledBack?.()
36
42
  if (instance?.vnode.props?.onError) emit("error", error)
37
43
  else toast.error(error instanceof Error ? error : String(error))
38
44
  } finally {
@@ -77,6 +77,26 @@ export interface OverlayHistoryOptions {
77
77
  }
78
78
 
79
79
  /** Wire an overlay's `open` to a history entry. */
80
+ /** The wiring of an overlay driven by a v-model: closing asks its guard first. */
81
+ export function useModelOverlayHistory(options: {
82
+ mode: OverlayHistoryOptions["mode"]
83
+ open: () => boolean
84
+ setOpen: (open: boolean) => void
85
+ allowClose: () => Promise<boolean>
86
+ }): void {
87
+ useOverlayHistory({
88
+ mode: options.mode,
89
+ open: options.open,
90
+ close: async () => {
91
+ if (!(await options.allowClose())) return false
92
+ options.setOpen(false)
93
+ return true
94
+ },
95
+ reopen: () => options.setOpen(true),
96
+ navigated: () => options.setOpen(false),
97
+ })
98
+ }
99
+
80
100
  export function useOverlayHistory(options: OverlayHistoryOptions): void {
81
101
  const inherited = inject(MODE, false)
82
102
  const mode = computed<OverlayHistoryMode>(() => options.mode() ?? toValue(inherited))
@@ -1,6 +1,7 @@
1
1
  import { onBeforeUnmount, onMounted, readonly, ref, toValue, type MaybeRefOrGetter, type Ref } from "vue"
2
2
  import { useHotkeys, type HotkeyHelp } from "./useHotkeys"
3
3
  import { scrollParent } from "./scroll"
4
+ import { nodeWindow } from "./useView"
4
5
 
5
6
  /*
6
7
  * Paint selection: press on one item's tick and sweep across the others, and
@@ -76,8 +77,11 @@ export function usePaintSelect<K = string>(options: UsePaintSelectOptions<K>) {
76
77
  return out
77
78
  }
78
79
 
80
+ // Inside an LpFrame the pointer's events stay in the frame's window.
81
+ const hostWindow = (): Window => (options.root.value ? nodeWindow(options.root.value) : window)
82
+
79
83
  function keyAt(x: number, y: number): K | undefined {
80
- const item = document.elementFromPoint(x, y)?.closest<HTMLElement>("[data-paint-key]")
84
+ const item = options.root.value?.ownerDocument.elementFromPoint(x, y)?.closest<HTMLElement>("[data-paint-key]")
81
85
  if (!item || !options.root.value?.contains(item)) return undefined
82
86
  return resolve(item.dataset.paintKey ?? "")
83
87
  }
@@ -100,11 +104,11 @@ export function usePaintSelect<K = string>(options: UsePaintSelectOptions<K>) {
100
104
  function tick() {
101
105
  frame = 0
102
106
  if (!stroke) return
103
- const box = stroke.scroller?.getBoundingClientRect() ?? { top: 0, bottom: window.innerHeight }
107
+ const box = stroke.scroller?.getBoundingClientRect() ?? { top: 0, bottom: hostWindow().innerHeight }
104
108
  const delta = stroke.y > box.bottom - EDGE_PX ? SCROLL_STEP : stroke.y < box.top + EDGE_PX ? -SCROLL_STEP : 0
105
109
  if (delta) {
106
110
  if (stroke.scroller) stroke.scroller.scrollTop += delta
107
- else window.scrollBy(0, delta)
111
+ else hostWindow().scrollBy(0, delta)
108
112
  extend()
109
113
  }
110
114
  frame = requestAnimationFrame(tick)
@@ -119,7 +123,7 @@ export function usePaintSelect<K = string>(options: UsePaintSelectOptions<K>) {
119
123
  painting.value = true
120
124
  // A sweep over text would otherwise select it, and a hold that started
121
125
  // before the stroke may already have.
122
- window.getSelection()?.removeAllRanges()
126
+ hostWindow().getSelection()?.removeAllRanges()
123
127
  if (options.root.value) options.root.value.style.userSelect = "none"
124
128
  extend()
125
129
  if (!frame) frame = requestAnimationFrame(tick)
@@ -213,22 +217,24 @@ export function usePaintSelect<K = string>(options: UsePaintSelectOptions<K>) {
213
217
  { scope: options.root },
214
218
  )
215
219
 
220
+ let listening: Window | null = null
216
221
  onMounted(() => {
217
- window.addEventListener("pointermove", onMove)
218
- window.addEventListener("pointerup", onUp)
219
- window.addEventListener("pointercancel", onUp)
220
- window.addEventListener("click", onClickCapture, true)
221
- window.addEventListener("contextmenu", onContextMenu, true)
222
+ listening = hostWindow()
223
+ listening.addEventListener("pointermove", onMove)
224
+ listening.addEventListener("pointerup", onUp)
225
+ listening.addEventListener("pointercancel", onUp)
226
+ listening.addEventListener("click", onClickCapture, true)
227
+ listening.addEventListener("contextmenu", onContextMenu, true)
222
228
  options.root.value?.addEventListener("touchmove", onTouchMove, { passive: false })
223
229
  })
224
230
  onBeforeUnmount(() => {
225
231
  onUp()
226
232
  swallowClick = false
227
- window.removeEventListener("pointermove", onMove)
228
- window.removeEventListener("pointerup", onUp)
229
- window.removeEventListener("pointercancel", onUp)
230
- window.removeEventListener("click", onClickCapture, true)
231
- window.removeEventListener("contextmenu", onContextMenu, true)
233
+ listening?.removeEventListener("pointermove", onMove)
234
+ listening?.removeEventListener("pointerup", onUp)
235
+ listening?.removeEventListener("pointercancel", onUp)
236
+ listening?.removeEventListener("click", onClickCapture, true)
237
+ listening?.removeEventListener("contextmenu", onContextMenu, true)
232
238
  options.root.value?.removeEventListener("touchmove", onTouchMove)
233
239
  })
234
240
 
@@ -1,5 +1,7 @@
1
1
  import { computed, getCurrentInstance, h, inject, onMounted, onUpdated, onScopeDispose, provide, ref, shallowReactive, shallowRef, toValue, useId, type Component, type Directive, type InjectionKey, type MaybeRefOrGetter } from "vue"
2
+ import { menuPaletteCommands } from "../components/commandPalette"
2
3
  import type { Command } from "../components/LpCommandPalette.vue"
4
+ import type { ContextMenuItemDef } from "../components/LpContextMenu.vue"
3
5
  import { provideField, useField } from "./useField"
4
6
  import { useLabels } from "./useLpConfig"
5
7
 
@@ -104,6 +106,17 @@ export function usePaletteCommands(commands: MaybeRefOrGetter<readonly Command[]
104
106
  }
105
107
 
106
108
  /** Manual definitions override a discovered command without changing its place. */
109
+ /** A titled menu as one command of the palette, with its items inside. */
110
+ export function useMenuPalette(menu: { palette?: PaletteControlOptions; title?: string; items: ContextMenuItemDef[] }) {
111
+ const scope = usePaletteScope()
112
+ const generated = useId()
113
+ usePaletteCommands(() => {
114
+ if (menu.palette === false || !menu.title || !menu.items.length) return []
115
+ const id = `${scope?.id}/${menu.palette?.id ?? generated}`
116
+ return [{ id, label: menu.palette?.label ?? menu.title, children: menuPaletteCommands(menu.items, id) }]
117
+ }, { automatic: true })
118
+ }
119
+
107
120
  export function mergePaletteCommands(discovered: readonly Command[], manual: readonly Command[]): Command[] {
108
121
  const overrides = new Map(manual.map(command => [command.id, command]))
109
122
  return uniqueCommands([...discovered.map(command => overrides.get(command.id) ?? command), ...manual])
@@ -205,8 +218,11 @@ export function usePaletteControl(options: {
205
218
  h(raw.label ? "h3" : "label", { id: `${editorId}-label`, for: raw.label ? undefined : editorId, class: "text-sm font-semibold text-ink" }, label()),
206
219
  h(instance.type as Component, {
207
220
  ...raw, id: undefined, name: undefined, form: undefined, autofocus: undefined, palette: false,
208
- disabled: options.disabled?.() || !writable(), invalid: options.invalid?.(),
209
- required: field?.value.required ?? instance.props.required,
221
+ disabled: options.disabled?.() || !writable(),
222
+ // Only to a control that declares them: elsewhere they fell through
223
+ // as attributes onto its root (a switch's button took `required`).
224
+ ...("invalid" in instance.props ? { invalid: options.invalid?.() } : {}),
225
+ ...("required" in instance.props ? { required: field?.value.required ?? instance.props.required } : {}),
210
226
  "aria-label": label(), class: "w-full", style: undefined,
211
227
  }, instance.slots),
212
228
  error() || hint() ? h("p", { id: `${editorId}-message`, class: error() ? "text-xs text-danger" : "text-xs text-muted", role: error() ? "alert" : undefined }, error() || hint()) : null,
@@ -59,6 +59,16 @@ export interface PersistedOptions<T> {
59
59
  *
60
60
  * A changed key reads the new key's value, so one component instance can
61
61
  * follow the thing it shows (a drawer per record).
62
+ *
63
+ * Made for small preferences, and this is the contract:
64
+ * - JSON values only, `initial` included. A Map, Set or Date does not survive
65
+ * the round trip, a key holding `undefined` is dropped, and a BigInt or a
66
+ * cycle throws here, however `T` reads.
67
+ * - Every change walks the value and rewrites it whole, synchronously. A large
68
+ * document wants its own saving: debounced, with dirty state and versions.
69
+ * - One owner per key. Two refs on one key do not see each other's writes
70
+ * (the `storage` event only reaches other tabs) and the last write wins, so
71
+ * share the ref instead.
62
72
  */
63
73
  export function usePersisted<T>(
64
74
  key: MaybeRefOrGetter<string | false | null | undefined>,
@@ -22,15 +22,18 @@ import { usePrefersReducedMotion } from "./useReducedMotion"
22
22
  */
23
23
  export type PillTransition =
24
24
  | { duration: number }
25
- | { type: "spring"; stiffness: number; damping: number; mass?: number }
25
+ | Readonly<{ type: "spring"; stiffness: number; damping: number; mass?: number }>
26
26
 
27
27
  export type PillFeel = "pill" | "float" | "layout"
28
28
 
29
- const SPRING: Record<PillFeel, { type: "spring"; stiffness: number; damping: number; mass?: number }> = {
30
- pill: { type: "spring", stiffness: 520, damping: 40 },
31
- float: { type: "spring", stiffness: 210, damping: 26 },
32
- layout: { type: "spring", stiffness: 520, damping: 42, mass: 0.9 },
33
- }
29
+ type Spring = Readonly<{ type: "spring"; stiffness: number; damping: number; mass?: number }>
30
+
31
+ // Frozen: every consumer holds the same object, so one write would retune them all.
32
+ const SPRING: Readonly<Record<PillFeel, Spring>> = Object.freeze({
33
+ pill: Object.freeze({ type: "spring", stiffness: 520, damping: 40 }),
34
+ float: Object.freeze({ type: "spring", stiffness: 210, damping: 26 }),
35
+ layout: Object.freeze({ type: "spring", stiffness: 520, damping: 42, mass: 0.9 }),
36
+ })
34
37
 
35
38
  export function usePillTransition(feel: PillFeel = "pill"): ComputedRef<PillTransition> {
36
39
  const reduceMotion = usePrefersReducedMotion()
@@ -1,3 +1,4 @@
1
+ import { nodeWindow } from "./realm"
1
2
  import { onScopeDispose, toValue, watch, type MaybeRefOrGetter } from "vue"
2
3
 
3
4
  /*
@@ -41,7 +42,7 @@ export function useResizeObserver(
41
42
  if (!el) return
42
43
  if (immediate) callback(undefined, el)
43
44
  if (typeof ResizeObserver === "undefined") return
44
- observer = new ResizeObserver((entries) => {
45
+ observer = new (nodeWindow(el).ResizeObserver)((entries) => {
45
46
  const entry = entries[entries.length - 1]
46
47
  if (entry) callback(entry, el)
47
48
  })
@@ -1,3 +1,4 @@
1
+ import { nodeWindow } from "./realm"
1
2
  import { onBeforeUnmount, ref, toValue, watch, type MaybeRefOrGetter, type Ref } from "vue"
2
3
  import { prefersReducedMotion } from "./easing"
3
4
 
@@ -102,7 +103,7 @@ export function useReveal(options: UseRevealOptions = {}): UseReveal {
102
103
  return
103
104
  }
104
105
 
105
- observer = new IntersectionObserver(
106
+ observer = new (nodeWindow(node).IntersectionObserver)(
106
107
  (entries) => {
107
108
  if (entries.some((entry) => entry.isIntersecting)) reveal()
108
109
  },
@@ -1,6 +1,9 @@
1
1
  import { computed, ref, watch, type MaybeRefOrGetter, toValue } from "vue"
2
+ import { isTextEntry } from "./textEntry"
3
+ import { isHTMLElement } from "./useView"
2
4
 
3
5
  const NON_TEXT_INPUTS = new Set(["checkbox", "radio", "button", "submit", "reset", "range", "color", "file", "image"])
6
+ const ROW_FIELD = { select: true, inputType: (type: string) => !NON_TEXT_INPUTS.has(type) }
4
7
 
5
8
  /*
6
9
  * Arrow-key navigation over a list, with a roving tabindex.
@@ -40,9 +43,9 @@ export interface UseRovingFocusOptions {
40
43
  /**
41
44
  * Which axis the arrows follow. `vertical` (default) uses ↑↓, `horizontal`
42
45
  * uses ←→, `both` accepts either — for a grid whose wrapping the caller
43
- * cannot describe here.
46
+ * cannot describe here. A ref or getter follows a list that changes axis.
44
47
  */
45
- orientation?: "vertical" | "horizontal" | "both"
48
+ orientation?: MaybeRefOrGetter<"vertical" | "horizontal" | "both">
46
49
  /** Wrap around at the ends instead of stopping. Default true. */
47
50
  loop?: boolean
48
51
  /** Jump to an item by typing its first letters. Default true. */
@@ -154,18 +157,13 @@ export function useRovingFocus(
154
157
  }
155
158
  }
156
159
 
157
- function isTextEntry(target: EventTarget | null): boolean {
158
- if (!(target instanceof HTMLElement)) return false
159
- if (target.isContentEditable || target instanceof HTMLTextAreaElement || target instanceof HTMLSelectElement) return true
160
- return target instanceof HTMLInputElement && !NON_TEXT_INPUTS.has(target.type)
161
- }
162
-
163
160
  function onKeydown(event: KeyboardEvent) {
164
161
  // A field inside a row (an inline rename, a filter) owns its keys: the list
165
162
  // taking letters for typeahead or Space for activation made it untypeable.
166
- if (event.isComposing || isTextEntry(event.target)) return
167
- const vertical = orientation === "vertical" || orientation === "both"
168
- const horizontal = orientation === "horizontal" || orientation === "both"
163
+ if (event.isComposing || isTextEntry(event.target, ROW_FIELD)) return
164
+ const axis = toValue(orientation)
165
+ const vertical = axis === "vertical" || axis === "both"
166
+ const horizontal = axis === "horizontal" || axis === "both"
169
167
 
170
168
  switch (event.key) {
171
169
  case "ArrowDown":
@@ -234,9 +232,8 @@ export function useRovingFocus(
234
232
  * narrowed the rows would yank the user out of the field they are typing in.
235
233
  */
236
234
  watch(activeId, (id) => {
237
- if (!id || typeof document === "undefined") return
238
235
  const container = containerEl.value
239
- if (!container || !container.contains(document.activeElement)) return
236
+ if (!id || !container || !container.contains(container.ownerDocument.activeElement)) return
240
237
  const target = container.querySelector<HTMLElement>(
241
238
  `[data-roving-id="${CSS.escape(id)}"]`,
242
239
  )
@@ -254,7 +251,7 @@ export function useRovingFocus(
254
251
 
255
252
  /** Bind on the element wrapping the rows. */
256
253
  const containerProps = computed(() => ({
257
- ref: (el: unknown) => setContainer(el instanceof HTMLElement ? el : null),
254
+ ref: (el: unknown) => setContainer(isHTMLElement(el) ? el : null),
258
255
  onKeydown,
259
256
  }))
260
257
 
@@ -65,15 +65,26 @@ export interface UseScramble {
65
65
  settle: () => void
66
66
  }
67
67
 
68
+ const SEED_MULTIPLIER = 16807
69
+ const SEED_MODULUS = 2147483647
70
+
71
+ /* A small Lehmer generator: the same numbers in every render. */
72
+ function seededRandom(seed = 1): () => number {
73
+ return () => (seed = (seed * SEED_MULTIPLIER) % SEED_MODULUS) / SEED_MODULUS
74
+ }
75
+
68
76
  export function useScramble(source: MaybeRefOrGetter<string>, options: UseScrambleOptions = {}): UseScramble {
69
77
  const random = options.random ?? Math.random
78
+ // The masked first frame is drawn on the server too, so it may not differ
79
+ // from the client's: it rolls a fixed sequence, the animation a live one.
80
+ const firstRoll = options.random ?? seededRandom()
70
81
  const tick = options.tick ?? 50
71
82
  const glyphs = () => toValue(options.glyphs) || SCRAMBLE_GLYPHS
72
83
 
73
84
  const initial = toValue(source)
74
85
  const cells = shallowRef<ScrambleFrameCell[]>(
75
86
  options.start === "masked"
76
- ? scrambleFrame(planScramble(initial, initial, { duration: 1, keep: options.keep }, random), 0, random, glyphs())
87
+ ? scrambleFrame(planScramble(initial, initial, { duration: 1, keep: options.keep }, firstRoll), 0, firstRoll, glyphs())
77
88
  : settledCells(initial),
78
89
  )
79
90
  const running = shallowRef(false)
@@ -1,3 +1,4 @@
1
+ import { isElement, nodeWindow } from "./useView"
1
2
  import { nextTick, onBeforeUnmount, ref, toValue, watch, type MaybeRefOrGetter, type Ref } from "vue"
2
3
  import { prefersReducedMotion } from "./easing"
3
4
 
@@ -118,7 +119,7 @@ export function useShift(
118
119
  const scrolled = new Set<Element>()
119
120
  const rememberScroll = (event: Event) => {
120
121
  const target = event.target
121
- if (target instanceof Element) scrolled.add(target)
122
+ if (isElement(target)) scrolled.add(target)
122
123
  }
123
124
  function readScroll(): Map<Element, number> {
124
125
  const tops = new Map<Element, number>()
@@ -221,7 +222,7 @@ export function useShift(
221
222
  tweenStart = performance.now()
222
223
  resizing.value = true
223
224
  clearTimeout(settleTimer)
224
- const wait = prefersReducedMotion() ? 0 : (toValue(options.duration) ?? TWEEN_MS)
225
+ const wait = prefersReducedMotion(nodeWindow(node)) ? 0 : (toValue(options.duration) ?? TWEEN_MS)
225
226
  settleTimer = setTimeout(() => {
226
227
  inFlight = false
227
228
  resizing.value = false
@@ -303,12 +304,13 @@ export function useShift(
303
304
  ro.disconnect()
304
305
  for (const child of Array.from(node.children)) ro.observe(child)
305
306
  }
306
- if (typeof ResizeObserver !== "undefined") {
307
- ro = new ResizeObserver(() => retune())
307
+ const win = nodeWindow(node)
308
+ if (typeof win.ResizeObserver !== "undefined") {
309
+ ro = new win.ResizeObserver(() => retune())
308
310
  watchChildren()
309
311
  }
310
- if (typeof MutationObserver !== "undefined") {
311
- mo = new MutationObserver(() => {
312
+ if (typeof win.MutationObserver !== "undefined") {
313
+ mo = new win.MutationObserver(() => {
312
314
  watchChildren()
313
315
  retune()
314
316
  })
@@ -1,3 +1,4 @@
1
+ import { isHTMLElement } from "./useView"
1
2
  import { computed, ref, toValue, type ComputedRef, type CSSProperties, type MaybeRefOrGetter, type Ref } from "vue"
2
3
  import { usePointerFrame } from "./usePointerFrame"
3
4
  import { usePrefersReducedMotion } from "./useReducedMotion"
@@ -67,7 +68,7 @@ export function useTilt(source: MaybeRefOrGetter<UseTiltOptions> = {}): UseTilt
67
68
  })
68
69
 
69
70
  function onPointerMove(e: PointerEvent): void {
70
- if (e.currentTarget instanceof HTMLElement) target = e.currentTarget
71
+ if (isHTMLElement(e.currentTarget)) target = e.currentTarget
71
72
  pointer.move(e)
72
73
  }
73
74
 
@@ -1,4 +1,6 @@
1
- import { onScopeDispose, shallowRef, toValue, watch, type MaybeRefOrGetter, type ShallowRef } from "vue"
1
+ import { clamp } from "./clamp"
2
+ import { useView } from "./useView"
3
+ import { hasInjectionContext, type MaybeRefOrGetter, onScopeDispose, shallowRef, type ShallowRef, toValue, watch } from "vue"
2
4
  import { durationToken, prefersReducedMotion, tokenEase } from "./easing"
3
5
 
4
6
  /*
@@ -47,6 +49,8 @@ export function useTween<T>(
47
49
  mix: (from: T, to: T, t: number) => T,
48
50
  options: TweenOptions<T> = {},
49
51
  ): Readonly<ShallowRef<T>> {
52
+ // Reads tokens where it animates; a store outside setup has only the page.
53
+ const view = hasInjectionContext() ? useView() : null
50
54
  const shown = shallowRef(source())
51
55
  let target = shown.value
52
56
  let frame = 0
@@ -59,11 +63,12 @@ export function useTween<T>(
59
63
  watch(source, (to) => {
60
64
  if (options.equal?.(target, to)) return
61
65
  target = to
62
- const ms = toValue(options.duration) ?? durationToken("duration-medium")
66
+ const scope = view?.value?.document
67
+ const ms = toValue(options.duration) ?? durationToken("duration-medium", undefined, scope)
63
68
  if (
64
69
  toValue(options.enabled) === false ||
65
70
  ms <= 0 ||
66
- prefersReducedMotion() ||
71
+ prefersReducedMotion(view?.value?.window) ||
67
72
  typeof requestAnimationFrame === "undefined"
68
73
  ) {
69
74
  stop()
@@ -72,12 +77,12 @@ export function useTween<T>(
72
77
  }
73
78
 
74
79
  const from = shown.value
75
- const ease = options.ease ?? tokenEase("ease-emphasized")
80
+ const ease = options.ease ?? tokenEase("ease-emphasized", scope)
76
81
  const started = performance.now()
77
82
  stop()
78
83
  const step = (now: number) => {
79
84
  // rAF stamps the frame's start, which can precede the watcher by a few ms.
80
- const t = Math.min(1, Math.max(0, (now - started) / ms))
85
+ const t = clamp((now - started) / ms, 0, 1)
81
86
  // The last frame is the target itself, not a mix that rounds near it, so
82
87
  // whatever the mix carried for the journey (ghosts, resampled points)
83
88
  // is gone once it lands.