@leavepulse/ui 0.77.3 → 0.78.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (597) 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-DXIr0eFz.js} +2 -2
  12. package/dist/chunks/{FieldWrapper-CORPzo9s.js → FieldWrapper-DnuMTrqW.js} +1 -1
  13. package/dist/chunks/IconCloseButton-COZEsa9u.js +29 -0
  14. package/dist/chunks/{LayoutCanvas-CNOAUk7D.js → LayoutCanvas-CZKOltfA.js} +1 -1
  15. package/dist/chunks/{LayoutNode-DF5BMN0J.js → LayoutNode-D2f7v683.js} +45 -45
  16. package/dist/chunks/{LpActionBar-BP1ld7-S.js → LpActionBar-BGMk5KoG.js} +3 -3
  17. package/dist/chunks/{LpActivityLine-CJvzrNpj.js → LpActivityLine-Ea-t5Vza.js} +4 -2
  18. package/dist/chunks/{LpAddressInput-E8KtwU7-.js → LpAddressInput-ZqoZ-N2Y.js} +12 -11
  19. package/dist/chunks/{LpAlert-n5XPAZfv.js → LpAlert-CjvTZIKF.js} +3 -3
  20. package/dist/chunks/LpAppShell-BNAVTQsY.js +582 -0
  21. package/dist/chunks/{LpAutocomplete-C-SpPfBG.js → LpAutocomplete-DkY6CSyD.js} +24 -42
  22. package/dist/chunks/{LpAvatar-Cg6Az3wz.js → LpAvatar-cQVsNk6F.js} +2 -2
  23. package/dist/chunks/{LpBadge-wUYLN4U9.js → LpBadge-D5QQdDQ_.js} +2 -2
  24. package/dist/chunks/{LpBottomNav-CbNQQPuL.js → LpBottomNav-zxLGGbjm.js} +9 -2
  25. package/dist/chunks/{LpBreadcrumbs-DPdbth-c.js → LpBreadcrumbs-CIIBsygI.js} +4 -3
  26. package/dist/chunks/{LpButton-CFb44IjC.js → LpButton-DSHioIfD.js} +5 -4
  27. package/dist/chunks/{LpCalendar-CuoWks-0.js → LpCalendar-D4-LVjfF.js} +1 -1
  28. package/dist/chunks/{LpCard-r13WRqox.js → LpCard-BPtYXwnT.js} +1 -1
  29. package/dist/chunks/{LpCheckbox-Cs4SHaHX.js → LpCheckbox-D6RuDW4X.js} +38 -16
  30. package/dist/chunks/{LpCodeBlock-DRC8VbXW.js → LpCodeBlock-DuzmnIHl.js} +19 -41
  31. package/dist/chunks/{LpCodeDisplay-CE9TxCA4.js → LpCodeDisplay-CO8fngxa.js} +5 -5
  32. package/dist/chunks/{LpCollapse-CWS9M_lm.js → LpCollapse-DrAw5DBZ.js} +5 -4
  33. package/dist/chunks/{LpColorPicker-1y1QJHZR.js → LpColorPicker-BxAHEnR5.js} +11 -12
  34. package/dist/chunks/{LpCommandScope-CtUhJe8T.js → LpCommandScope-DRUvHiX7.js} +1 -1
  35. package/dist/chunks/{LpConfirmDialog-DlD45Bi_.js → LpConfirmDialog-6oCIJTDa.js} +3 -3
  36. package/dist/chunks/{LpConfirmHost-BIWjBLmI.js → LpConfirmHost-DgHvfT6s.js} +1 -1
  37. package/dist/chunks/{LpContextMenu-rx2tCjwk.js → LpContextMenu--eMGIql6.js} +13 -15
  38. package/dist/chunks/{LpContextSwitcher-Dwh6dyID.js → LpContextSwitcher-1C1tExdl.js} +2 -2
  39. package/dist/chunks/{LpCopyButton-xF7wFVoU.js → LpCopyButton-7EOSIuwa.js} +3 -3
  40. package/dist/chunks/{LpCountdown-DgeY3cLG.js → LpCountdown-DVl7vXI1.js} +4 -3
  41. package/dist/chunks/{LpDataList-Jxyl9H5w.js → LpDataList-DgBeM01y.js} +13 -4
  42. package/dist/chunks/{LpDatePicker-CA0QTfBC.js → LpDatePicker-DwSDY0mt.js} +12 -18
  43. package/dist/chunks/{LpDateRangePicker-u3J51xXk.js → LpDateRangePicker-CNQXdTVv.js} +10 -16
  44. package/dist/chunks/{LpDisclosure-Cpa7Hc5T.js → LpDisclosure-DG7JCo-d.js} +2 -2
  45. package/dist/chunks/{LpDrawer-CrG8t_KP.js → LpDrawer-Bt9UUqt_.js} +61 -61
  46. package/dist/chunks/{LpDropdownMenu-Dl7Z4ZhS.js → LpDropdownMenu-CLzxIOgM.js} +9 -17
  47. package/dist/chunks/{LpEditable-Cy6GLbFx.js → LpEditable-DVT0Rh8F.js} +9 -6
  48. package/dist/chunks/{LpEmptyState-EQHiRYhG.js → LpEmptyState-DurPF001.js} +1 -1
  49. package/dist/chunks/{LpFieldNotice-CzQ2_5rQ.js → LpFieldNotice-DJ10cYIo.js} +1 -1
  50. package/dist/chunks/LpFileTree-BSx1kBoV.js +735 -0
  51. package/dist/chunks/{LpFileTreeNode-cT6BIWvz.js → LpFileTreeNode-4dVmFHb3.js} +116 -34
  52. package/dist/chunks/{LpFormField-Ch69Jd-X.js → LpFormField-BKYn9dyP.js} +3 -3
  53. package/dist/chunks/{LpFrame-BVQCQLDI.js → LpFrame-Bv5Fphte.js} +25 -11
  54. package/dist/chunks/{LpHintExample-9Py0wc-L.js → LpHintExample-YzCXiSUp.js} +1 -1
  55. package/dist/chunks/{LpHintLayer-CgObdUsM.js → LpHintLayer-BeKRsRon.js} +2 -2
  56. package/dist/chunks/{LpHints-Bz-BlaSl.js → LpHints-qf3xYsza.js} +3 -3
  57. package/dist/chunks/{LpHoverCard-spGxyw7T.js → LpHoverCard-DanH3Nz1.js} +23 -5
  58. package/dist/chunks/{LpIcon--5WSb3jJ.js → LpIcon-C6JpQ5td.js} +6 -3
  59. package/dist/chunks/{LpIdenticon-BzdC_qz9.js → LpIdenticon-Dbbr4fvt.js} +2 -1
  60. package/dist/chunks/{LpInfraNode-46XOCkfq.js → LpInfraNode-BAU40Km2.js} +2 -2
  61. package/dist/chunks/{LpInput-Tw-yxT4I.js → LpInput-DL6HEJdi.js} +16 -28
  62. package/dist/chunks/LpInspector-CuoMAhiw.js +209 -0
  63. package/dist/chunks/{LpLightbox-B95yu22B.js → LpLightbox-xvpQ64MM.js} +57 -32
  64. package/dist/chunks/{LpLoader-DVwkOmt9.js → LpLoader-Bf1yZwaU.js} +1 -1
  65. package/dist/chunks/LpLogInspector-6cNnXqp4.js +119 -0
  66. package/dist/chunks/{LpLogViewer-ngqkns4m.js → LpLogViewer-Dvb1E9_G.js} +234 -53
  67. package/dist/chunks/{LpMapPicker-DRGgh89B.js → LpMapPicker-D5_YLLBC.js} +4 -3
  68. package/dist/chunks/{LpMasonry--k0571qG.js → LpMasonry-DPYekFxs.js} +8 -5
  69. package/dist/chunks/{LpMediaGallery-Bkram-MO.js → LpMediaGallery-Df-tiWeq.js} +3 -3
  70. package/dist/chunks/{LpModal-CoGhLTyH.js → LpModal-DrtQ_1A2.js} +11 -13
  71. package/dist/chunks/{LpModalNav-BGvs2y5Q.js → LpModalNav-DkmGCnZE.js} +11 -37
  72. package/dist/chunks/{LpNotificationBell-B0034Lk-.js → LpNotificationBell-D_wklO1m.js} +9 -9
  73. package/dist/chunks/{LpNumberField-e0IBkWU1.js → LpNumberField-CNHsmSDZ.js} +7 -16
  74. package/dist/chunks/{LpOtpInput-CeBPsM7D.js → LpOtpInput-BRpLBbOD.js} +2 -2
  75. package/dist/chunks/{LpPagination-BIIiYHXR.js → LpPagination-snQ020xQ.js} +6 -4
  76. package/dist/chunks/{LpPaletteTheme-DiLYKQiZ.js → LpPaletteTheme-dVtxHx-F.js} +4 -4
  77. package/dist/chunks/{LpPasswordInput-BkHKQDhM.js → LpPasswordInput-B-zD6tUS.js} +2 -2
  78. package/dist/chunks/{LpPhoneInput-CETEp5W7.js → LpPhoneInput-BSL7NX4z.js} +15 -26
  79. package/dist/chunks/{LpPie-DrZepi0p.js → LpPie-9t_guO49.js} +22 -21
  80. package/dist/chunks/{LpPipeline-B3aOVOkV.js → LpPipeline-rjXvEDRJ.js} +16 -7
  81. package/dist/chunks/{LpPopover-DmZ3wUtP.js → LpPopover-BQSuxtai.js} +10 -1
  82. package/dist/chunks/{LpProgress-Yr6ONG5t.js → LpProgress-D_MSjowb.js} +2 -1
  83. package/dist/chunks/{LpQuota-Dk2MyI2Z.js → LpQuota-CgWPgdVt.js} +1 -1
  84. package/dist/chunks/{LpRadioGroup-ggaPL92T.js → LpRadioGroup-BrazjLY_.js} +4 -4
  85. package/dist/chunks/{LpRangeCalendar-CYYUYqJ7.js → LpRangeCalendar-BrqlGZzE.js} +1 -1
  86. package/dist/chunks/{LpRangeSlider-CM-0ZITZ.js → LpRangeSlider-fz61tzc-.js} +5 -9
  87. package/dist/chunks/{LpRelativeTime-DwgCb5-8.js → LpRelativeTime-BovUk8MP.js} +1 -1
  88. package/dist/chunks/{LpRepeater-D7ZmnIYd.js → LpRepeater-BkJHSPI1.js} +3 -3
  89. package/dist/chunks/{LpRevealOnScroll-DcQjexLy.js → LpRevealOnScroll-CPwyiQAr.js} +1 -1
  90. package/dist/chunks/{LpScramble-Bn9OoOtC.js → LpScramble-DsE77iVp.js} +1 -1
  91. package/dist/chunks/{LpScrollArea-MyEnVB_5.js → LpScrollArea-ay4Xo_hg.js} +22 -10
  92. package/dist/chunks/{LpSecretField-BbmqM9ye.js → LpSecretField-DBvU6iAw.js} +10 -9
  93. package/dist/chunks/{LpSection-DFK_uoJE.js → LpSection-BfteipxU.js} +1 -1
  94. package/dist/chunks/{LpSegmented-CeACsMMA.js → LpSegmented-DbEJhbv-.js} +8 -10
  95. package/dist/chunks/{LpSelect-Cxq4yBGd.js → LpSelect-Y-iuSymW.js} +47 -30
  96. package/dist/chunks/{LpShaderBackdrop-Bote0iuy.js → LpShaderBackdrop-wQygYb5h.js} +13 -10
  97. package/dist/chunks/{LpShift-CCq7dofl.js → LpShift-DAgS_d2x.js} +18 -15
  98. package/dist/chunks/{LpSidebar-DzE1783C.js → LpSidebar-kSkpPh3-.js} +74 -87
  99. package/dist/chunks/{LpSidebarNav-DE3PhXVP.js → LpSidebarNav-C2mvqrY2.js} +8 -6
  100. package/dist/chunks/{LpSidebarRow-BRYhNDSo.js → LpSidebarRow-eRP4Q31q.js} +6 -5
  101. package/dist/chunks/{LpSlider-DxYoCJJO.js → LpSlider-A4ixovgS.js} +5 -9
  102. package/dist/chunks/{LpSpotlight-4F3NeUMY.js → LpSpotlight-DwxkhFgR.js} +2 -1
  103. package/dist/chunks/{LpStat-f2LfDCJ4.js → LpStat-pMNZgFcq.js} +2 -2
  104. package/dist/chunks/{LpStatus-DglxttQ7.js → LpStatus-DGJFwk5F.js} +2 -2
  105. package/dist/chunks/{LpStepMark-DpzKVyh8.js → LpStepMark-Dw2MRTrt.js} +2 -2
  106. package/dist/chunks/{LpStepper-DpsocBNJ.js → LpStepper-DNnh7lCu.js} +1 -1
  107. package/dist/chunks/{LpSwap-C96c0LWh.js → LpSwap-M7nFeW3C.js} +1 -1
  108. package/dist/chunks/{LpSwitch-BnXd1llc.js → LpSwitch-DnC2-0aV.js} +3 -3
  109. package/dist/chunks/{LpTabFace-DPCwKkH2.js → LpTabFace-DQoV8mQG.js} +2 -2
  110. package/dist/chunks/{LpTableFilter-CiVBpaq0.js → LpTableFilter-DgARTsA1.js} +4 -4
  111. package/dist/chunks/{LpTableOfContents-BN5zvpnx.js → LpTableOfContents-CKkWEK6R.js} +14 -9
  112. package/dist/chunks/{LpTagsInput-C-mDG648.js → LpTagsInput-Dt0mteSj.js} +19 -27
  113. package/dist/chunks/{LpTextarea-TE-yZv2U.js → LpTextarea-Co0b9PVx.js} +8 -16
  114. package/dist/chunks/LpThemeProvider-XK6ZeWAE.js +81 -0
  115. package/dist/chunks/{LpThemeStudio-BpORDvH6.js → LpThemeStudio-DzYfE-5k.js} +12 -195
  116. package/dist/chunks/{LpThemeSwitcher-BnEn_mvf.js → LpThemeSwitcher-CFLkdbBL.js} +8 -6
  117. package/dist/chunks/{LpTimeField-BawSVsmt.js → LpTimeField-DeOcKWJq.js} +6 -9
  118. package/dist/chunks/{LpToaster-IwTXjbbU.js → LpToaster-QFj0P-5m.js} +10 -8
  119. package/dist/chunks/{LpTooltip-BcBvIx4z.js → LpTooltip-BJf3lZMq.js} +51 -19
  120. package/dist/chunks/LpTopologyCanvas-BOHHHZ_6.js +673 -0
  121. package/dist/chunks/{LpTour-BZq-mUMv.js → LpTour-ClKYhx4h.js} +7 -5
  122. package/dist/chunks/{LpTruncate-CflAIwiJ.js → LpTruncate-C6u3gjc6.js} +6 -5
  123. package/dist/chunks/{LpTypewriter-BCL_a6wE.js → LpTypewriter-CZIzpdbe.js} +2 -1
  124. package/dist/chunks/{LpUptimeBar-DqNvvMBK.js → LpUptimeBar-BnYmR2rj.js} +3 -3
  125. package/dist/chunks/{LpVideoBackdrop-DS1wGv-X.js → LpVideoBackdrop-Ct4St4ZL.js} +10 -13
  126. package/dist/chunks/LpWindow-B8YSRVTH.js +297 -0
  127. package/dist/chunks/LpWorkspaceSwitcher-D0e9upAy.js +139 -0
  128. package/dist/chunks/{MenuTitle-BmCNNTKH.js → MenuTitle-Bh5dAdV1.js} +1 -1
  129. package/dist/chunks/{OptionContent-22UT8zLn.js → OptionContent-CGb8QlHA.js} +1 -1
  130. package/dist/chunks/{PickerField-Bfh8id3d.js → PickerField-BM1dyafh.js} +4 -4
  131. package/dist/chunks/{RevealToggle-BEit1n6Z.js → RevealToggle-CCPDE8Mv.js} +3 -3
  132. package/dist/chunks/SliderRail-DhPREa_R.js +18 -0
  133. package/dist/chunks/{TourCard-DNclH3u_.js → TourCard-DAzTYfav.js} +4 -4
  134. package/dist/chunks/{icons-DMITlfw5.js → icons-CYfcpSDS.js} +26 -10
  135. package/dist/component-names.d.ts +1 -1
  136. package/dist/components/AppShellContextNav.vue.d.ts +13 -0
  137. package/dist/components/AppShellContextNav.vue.js +4 -0
  138. package/dist/components/ChartRangeSelector.vue.d.ts +21 -0
  139. package/dist/components/ChartRangeSelector.vue.js +4 -0
  140. package/dist/components/ContextMenuItems.vue.js +1 -1
  141. package/dist/components/DropzoneLinkField.vue.d.ts +2 -2
  142. package/dist/components/DropzoneLinkField.vue.js +1 -1
  143. package/dist/components/FieldWrapper.vue.js +1 -1
  144. package/dist/components/IconCloseButton.vue.d.ts +7 -0
  145. package/dist/components/IconCloseButton.vue.js +4 -0
  146. package/dist/components/LayoutCanvas.vue.js +1 -1
  147. package/dist/components/LayoutNode.vue.js +1 -1
  148. package/dist/components/LpActionBar.vue.js +1 -1
  149. package/dist/components/LpActivityLine.vue.js +1 -1
  150. package/dist/components/LpAddressInput.vue.js +1 -1
  151. package/dist/components/LpAlert.vue.js +1 -1
  152. package/dist/components/LpAppShell.vue.d.ts +110 -2
  153. package/dist/components/LpAppShell.vue.js +1 -1
  154. package/dist/components/LpAutocomplete.vue.js +1 -1
  155. package/dist/components/LpAvatar.vue.js +1 -1
  156. package/dist/components/LpBadge.vue.js +1 -1
  157. package/dist/components/LpBottomNav.vue.d.ts +5 -0
  158. package/dist/components/LpBottomNav.vue.js +1 -1
  159. package/dist/components/LpBreadcrumbs.vue.js +1 -1
  160. package/dist/components/LpButton.vue.d.ts +14 -2
  161. package/dist/components/LpButton.vue.js +1 -1
  162. package/dist/components/LpCalendar.vue.js +1 -1
  163. package/dist/components/LpCard.vue.js +1 -1
  164. package/dist/components/LpChart.vue.d.ts +74 -2
  165. package/dist/components/LpChart.vue.js +326 -85
  166. package/dist/components/LpCheckbox.vue.d.ts +6 -2
  167. package/dist/components/LpCheckbox.vue.js +1 -1
  168. package/dist/components/LpCodeBlock.vue.js +1 -1
  169. package/dist/components/LpCodeDisplay.vue.js +1 -1
  170. package/dist/components/LpCollapse.vue.js +1 -1
  171. package/dist/components/LpColorPicker.vue.js +1 -1
  172. package/dist/components/LpCommandPalette.vue.d.ts +8 -0
  173. package/dist/components/LpCommandPalette.vue.js +107 -56
  174. package/dist/components/LpCommandScope.vue.js +1 -1
  175. package/dist/components/LpConfirmDialog.vue.js +1 -1
  176. package/dist/components/LpConfirmHost.vue.js +1 -1
  177. package/dist/components/LpContextMenu.vue.js +1 -1
  178. package/dist/components/LpContextSwitcher.vue.js +1 -1
  179. package/dist/components/LpCopyButton.vue.js +1 -1
  180. package/dist/components/LpCountdown.vue.js +1 -1
  181. package/dist/components/LpDataList.vue.d.ts +1 -1
  182. package/dist/components/LpDataList.vue.js +1 -1
  183. package/dist/components/LpDatePicker.vue.d.ts +3 -15
  184. package/dist/components/LpDatePicker.vue.js +1 -1
  185. package/dist/components/LpDateRangePicker.vue.d.ts +3 -13
  186. package/dist/components/LpDateRangePicker.vue.js +1 -1
  187. package/dist/components/LpDisclosure.vue.js +1 -1
  188. package/dist/components/LpDock.vue.js +21 -18
  189. package/dist/components/LpDrawer.vue.d.ts +1 -1
  190. package/dist/components/LpDrawer.vue.js +1 -1
  191. package/dist/components/LpDropdownMenu.vue.js +1 -1
  192. package/dist/components/LpDropzone.vue.js +14 -11
  193. package/dist/components/LpEditable.vue.js +1 -1
  194. package/dist/components/LpEmptyState.vue.js +1 -1
  195. package/dist/components/LpFieldNotice.vue.js +1 -1
  196. package/dist/components/LpFileTree.vue.d.ts +96 -6
  197. package/dist/components/LpFileTree.vue.js +1 -1
  198. package/dist/components/LpFileTreeNode.vue.d.ts +48 -0
  199. package/dist/components/LpFileTreeNode.vue.js +1 -1
  200. package/dist/components/LpFormField.vue.js +1 -1
  201. package/dist/components/LpFrame.vue.js +1 -1
  202. package/dist/components/LpGauge.vue.d.ts +1 -1
  203. package/dist/components/LpHintExample.vue.js +1 -1
  204. package/dist/components/LpHintLayer.vue.js +1 -1
  205. package/dist/components/LpHints.vue.js +1 -1
  206. package/dist/components/LpHoverCard.vue.js +1 -1
  207. package/dist/components/LpIcon.vue.d.ts +2 -0
  208. package/dist/components/LpIcon.vue.js +1 -1
  209. package/dist/components/LpIdenticon.vue.js +1 -1
  210. package/dist/components/LpImageEditor.vue.js +7 -6
  211. package/dist/components/LpInfraNode.vue.js +1 -1
  212. package/dist/components/LpInput.vue.d.ts +1 -1
  213. package/dist/components/LpInput.vue.js +1 -1
  214. package/dist/components/LpInspector.vue.d.ts +87 -0
  215. package/dist/components/LpInspector.vue.js +4 -0
  216. package/dist/components/LpLightbox.vue.d.ts +8 -0
  217. package/dist/components/LpLightbox.vue.js +1 -1
  218. package/dist/components/LpLoader.vue.d.ts +1 -1
  219. package/dist/components/LpLoader.vue.js +1 -1
  220. package/dist/components/LpLogInspector.vue.d.ts +18 -0
  221. package/dist/components/LpLogInspector.vue.js +4 -0
  222. package/dist/components/LpLogViewer.vue.d.ts +93 -0
  223. package/dist/components/LpLogViewer.vue.js +1 -1
  224. package/dist/components/LpMapPicker.vue.js +1 -1
  225. package/dist/components/LpMasonry.vue.js +1 -1
  226. package/dist/components/LpMediaGallery.vue.js +1 -1
  227. package/dist/components/LpModal.vue.d.ts +4 -2
  228. package/dist/components/LpModal.vue.js +1 -1
  229. package/dist/components/LpModalNav.vue.d.ts +5 -5
  230. package/dist/components/LpModalNav.vue.js +1 -1
  231. package/dist/components/LpNotificationBell.vue.d.ts +2 -2
  232. package/dist/components/LpNotificationBell.vue.js +1 -1
  233. package/dist/components/LpNumberField.vue.js +1 -1
  234. package/dist/components/LpOtpInput.vue.js +1 -1
  235. package/dist/components/LpPagination.vue.js +1 -1
  236. package/dist/components/LpPaletteFacts.vue.js +1 -1
  237. package/dist/components/LpPaletteHeader.vue.js +2 -2
  238. package/dist/components/LpPaletteTheme.vue.js +1 -1
  239. package/dist/components/LpPasswordInput.vue.js +1 -1
  240. package/dist/components/LpPhoneInput.vue.js +1 -1
  241. package/dist/components/LpPie.vue.d.ts +2 -2
  242. package/dist/components/LpPie.vue.js +1 -1
  243. package/dist/components/LpPipeline.vue.d.ts +4 -0
  244. package/dist/components/LpPipeline.vue.js +1 -1
  245. package/dist/components/LpPopover.vue.d.ts +7 -3
  246. package/dist/components/LpPopover.vue.js +1 -1
  247. package/dist/components/LpProgress.vue.d.ts +1 -1
  248. package/dist/components/LpProgress.vue.js +1 -1
  249. package/dist/components/LpQuota.vue.js +1 -1
  250. package/dist/components/LpRadioGroup.vue.js +1 -1
  251. package/dist/components/LpRangeCalendar.vue.js +1 -1
  252. package/dist/components/LpRangeSlider.vue.js +1 -1
  253. package/dist/components/LpRelativeTime.vue.js +1 -1
  254. package/dist/components/LpRepeater.vue.js +1 -1
  255. package/dist/components/LpRevealOnScroll.vue.js +1 -1
  256. package/dist/components/LpScramble.vue.js +1 -1
  257. package/dist/components/LpScrollArea.vue.js +1 -1
  258. package/dist/components/LpSecretField.vue.js +1 -1
  259. package/dist/components/LpSection.vue.js +1 -1
  260. package/dist/components/LpSegmented.vue.js +1 -1
  261. package/dist/components/LpSelect.vue.js +1 -1
  262. package/dist/components/LpShaderBackdrop.vue.js +1 -1
  263. package/dist/components/LpShift.vue.js +1 -1
  264. package/dist/components/LpShortcutsDialog.vue.js +1 -1
  265. package/dist/components/LpSidebar.vue.d.ts +1 -1
  266. package/dist/components/LpSidebar.vue.js +1 -1
  267. package/dist/components/LpSidebarNav.vue.js +1 -1
  268. package/dist/components/LpSidebarRow.vue.js +1 -1
  269. package/dist/components/LpSlider.vue.js +1 -1
  270. package/dist/components/LpSparkline.vue.d.ts +1 -1
  271. package/dist/components/LpSpotlight.vue.js +1 -1
  272. package/dist/components/LpStat.vue.js +1 -1
  273. package/dist/components/LpStatus.vue.js +1 -1
  274. package/dist/components/LpStepMark.vue.js +1 -1
  275. package/dist/components/LpStepper.vue.js +1 -1
  276. package/dist/components/LpSwap.vue.js +1 -1
  277. package/dist/components/LpSwitch.vue.js +1 -1
  278. package/dist/components/LpTabFace.vue.js +1 -1
  279. package/dist/components/LpTable.vue.d.ts +132 -0
  280. package/dist/components/LpTable.vue.js +547 -135
  281. package/dist/components/LpTableFilter.vue.js +1 -1
  282. package/dist/components/LpTableOfContents.vue.js +1 -1
  283. package/dist/components/LpTabs.vue.js +6 -5
  284. package/dist/components/LpTagsInput.vue.js +1 -1
  285. package/dist/components/LpTextarea.vue.js +1 -1
  286. package/dist/components/LpThemeProvider.vue.d.ts +2 -0
  287. package/dist/components/LpThemeProvider.vue.js +1 -1
  288. package/dist/components/LpThemeStudio.vue.js +1 -1
  289. package/dist/components/LpThemeSwitcher.vue.js +1 -1
  290. package/dist/components/LpTimeField.vue.js +1 -1
  291. package/dist/components/LpToaster.vue.js +1 -1
  292. package/dist/components/LpTooltip.vue.js +1 -1
  293. package/dist/components/LpTopologyCanvas.vue.d.ts +131 -5
  294. package/dist/components/LpTopologyCanvas.vue.js +1 -1
  295. package/dist/components/LpTour.vue.js +1 -1
  296. package/dist/components/LpTruncate.vue.js +1 -1
  297. package/dist/components/LpTypewriter.vue.js +1 -1
  298. package/dist/components/LpUptimeBar.vue.js +1 -1
  299. package/dist/components/LpVideoBackdrop.vue.js +1 -1
  300. package/dist/components/LpWindow.vue.d.ts +99 -0
  301. package/dist/components/LpWindow.vue.js +4 -0
  302. package/dist/components/LpWorkspaceSwitcher.vue.d.ts +18 -0
  303. package/dist/components/LpWorkspaceSwitcher.vue.js +4 -0
  304. package/dist/components/MenuTitle.vue.js +1 -1
  305. package/dist/components/OptionContent.vue.js +1 -1
  306. package/dist/components/PickerField.vue.d.ts +2 -2
  307. package/dist/components/PickerField.vue.js +1 -1
  308. package/dist/components/RevealToggle.vue.js +1 -1
  309. package/dist/components/SliderRail.vue.d.ts +3 -0
  310. package/dist/components/SliderRail.vue.js +4 -0
  311. package/dist/components/TourCard.vue.js +1 -1
  312. package/dist/components/address.js +2 -1
  313. package/dist/components/appShell.d.ts +36 -0
  314. package/dist/components/appShell.js +30 -0
  315. package/dist/components/calendar.d.ts +12 -3
  316. package/dist/components/calendar.js +2 -5
  317. package/dist/components/chart.d.ts +21 -0
  318. package/dist/components/chart.js +4 -3
  319. package/dist/components/chartWindow.d.ts +57 -0
  320. package/dist/components/chartWindow.js +136 -0
  321. package/dist/components/color.js +1 -1
  322. package/dist/components/commandPalette.d.ts +16 -2
  323. package/dist/components/commandPalette.js +39 -4
  324. package/dist/components/controlSize.d.ts +5 -0
  325. package/dist/components/controlSize.js +8 -0
  326. package/dist/components/dropdown.d.ts +5 -0
  327. package/dist/components/dropdown.js +2 -0
  328. package/dist/components/exportData.d.ts +6 -1
  329. package/dist/components/exportData.js +25 -18
  330. package/dist/components/fileTree.d.ts +67 -0
  331. package/dist/components/fileTree.js +141 -1
  332. package/dist/components/identicon.js +3 -2
  333. package/dist/components/logTools.d.ts +93 -0
  334. package/dist/components/logTools.js +210 -0
  335. package/dist/components/menuWhen.js +1 -1
  336. package/dist/components/meter.js +2 -1
  337. package/dist/components/pipeline.d.ts +2 -0
  338. package/dist/components/pipeline.js +5 -0
  339. package/dist/components/relativeTime.js +2 -1
  340. package/dist/components/reveal.js +2 -1
  341. package/dist/components/select.d.ts +5 -0
  342. package/dist/components/select.js +10 -0
  343. package/dist/components/sidebar.d.ts +1 -0
  344. package/dist/components/tableFeatures.d.ts +58 -0
  345. package/dist/components/tableFeatures.js +87 -0
  346. package/dist/components/topologyGraph.d.ts +164 -0
  347. package/dist/components/topologyGraph.js +416 -0
  348. package/dist/components/tour.js +5 -3
  349. package/dist/components/videoBackdrop.js +7 -6
  350. package/dist/composables/clamp.d.ts +2 -0
  351. package/dist/composables/clamp.js +4 -0
  352. package/dist/composables/devWarn.d.ts +3 -0
  353. package/dist/composables/devWarn.js +14 -0
  354. package/dist/composables/easing.d.ts +13 -4
  355. package/dist/composables/easing.js +16 -10
  356. package/dist/composables/overlayHistory.js +14 -1
  357. package/dist/composables/pointerDrag.d.ts +15 -0
  358. package/dist/composables/pointerDrag.js +40 -0
  359. package/dist/composables/propCheck.d.ts +10 -0
  360. package/dist/composables/propCheck.js +78 -0
  361. package/dist/composables/realm.d.ts +6 -0
  362. package/dist/composables/realm.js +23 -0
  363. package/dist/composables/scroll.js +4 -2
  364. package/dist/composables/scrollMemory.d.ts +12 -1
  365. package/dist/composables/scrollMemory.js +36 -12
  366. package/dist/composables/spatialNav.js +2 -1
  367. package/dist/composables/textEntry.d.ts +17 -0
  368. package/dist/composables/textEntry.js +19 -0
  369. package/dist/composables/useAsyncTask.d.ts +6 -0
  370. package/dist/composables/useChartSync.d.ts +5 -0
  371. package/dist/composables/useChartSync.js +33 -0
  372. package/dist/composables/useCloseGuard.d.ts +3 -1
  373. package/dist/composables/useCloseGuard.js +6 -3
  374. package/dist/composables/useCommands.d.ts +50 -0
  375. package/dist/composables/useCommands.js +66 -0
  376. package/dist/composables/useField.d.ts +37 -0
  377. package/dist/composables/useField.js +27 -2
  378. package/dist/composables/useFitScale.js +4 -1
  379. package/dist/composables/useFormDraft.d.ts +13 -2
  380. package/dist/composables/useFormDraft.js +17 -9
  381. package/dist/composables/useHintSystem.js +2 -2
  382. package/dist/composables/useHotkeys.js +11 -32
  383. package/dist/composables/useInView.js +2 -1
  384. package/dist/composables/useInputFilter.js +7 -5
  385. package/dist/composables/useInputMask.js +5 -3
  386. package/dist/composables/useLinkedView.d.ts +97 -0
  387. package/dist/composables/useLinkedView.js +139 -0
  388. package/dist/composables/useOptimisticToggle.d.ts +3 -1
  389. package/dist/composables/useOptimisticToggle.js +2 -1
  390. package/dist/composables/useOverlayHistory.d.ts +7 -0
  391. package/dist/composables/useOverlayHistory.js +16 -2
  392. package/dist/composables/usePaintSelect.js +18 -14
  393. package/dist/composables/usePaletteCommands.d.ts +7 -0
  394. package/dist/composables/usePaletteCommands.js +12 -1
  395. package/dist/composables/usePersisted.d.ts +10 -0
  396. package/dist/composables/usePersisted.js +1 -1
  397. package/dist/composables/usePillTransition.d.ts +2 -2
  398. package/dist/composables/usePillTransition.js +5 -5
  399. package/dist/composables/useResizeObserver.js +2 -1
  400. package/dist/composables/useReveal.js +2 -1
  401. package/dist/composables/useRovingFocus.d.ts +2 -2
  402. package/dist/composables/useRovingFocus.js +9 -11
  403. package/dist/composables/useScramble.js +7 -1
  404. package/dist/composables/useShift.js +8 -6
  405. package/dist/composables/useTilt.js +2 -1
  406. package/dist/composables/useTween.js +9 -5
  407. package/dist/composables/useView.d.ts +1 -0
  408. package/dist/composables/useView.js +14 -2
  409. package/dist/composables/useZoomPan.js +2 -4
  410. package/dist/composables/windowing.d.ts +40 -0
  411. package/dist/composables/windowing.js +118 -0
  412. package/dist/icons-all.js +1 -1
  413. package/dist/icons.d.ts +4 -0
  414. package/dist/index.d.ts +30 -5
  415. package/dist/index.js +310 -264
  416. package/dist/layout/tree.js +19 -15
  417. package/dist/layout/useLayout.d.ts +2 -0
  418. package/dist/layout/useLayout.js +5 -1
  419. package/dist/layout/useWorkspaces.d.ts +52 -0
  420. package/dist/layout/useWorkspaces.js +140 -0
  421. package/dist/{chunks/backdrop-Dkf2vM81.js → theme/backdrop.js} +5 -5
  422. package/dist/theme/config.js +25 -0
  423. package/dist/theme/define.js +61 -0
  424. package/dist/{chunks/palette-Co8tSASo.js → theme/palette.js} +2 -2
  425. package/dist/theme/presets.js +239 -0
  426. package/dist/theme/studio.js +134 -0
  427. package/dist/theme/tokens.js +63 -0
  428. package/dist/theme/useTheme.d.ts +3 -2
  429. package/dist/theme/useTheme.js +325 -0
  430. package/package.json +8 -1
  431. package/src/component-names.ts +5 -1
  432. package/src/components/AppShellContextNav.vue +44 -0
  433. package/src/components/ChartRangeSelector.vue +120 -0
  434. package/src/components/IconCloseButton.vue +21 -0
  435. package/src/components/LayoutCanvas.vue +3 -0
  436. package/src/components/LayoutNode.vue +37 -38
  437. package/src/components/LpActivityLine.vue +4 -2
  438. package/src/components/LpAddressInput.vue +3 -3
  439. package/src/components/LpAppShell.vue +362 -24
  440. package/src/components/LpAutocomplete.vue +13 -30
  441. package/src/components/LpBottomNav.vue +9 -1
  442. package/src/components/LpBreadcrumbs.vue +2 -1
  443. package/src/components/LpButton.vue +11 -4
  444. package/src/components/LpChart.vue +336 -37
  445. package/src/components/LpCheckbox.vue +43 -9
  446. package/src/components/LpCodeBlock.vue +17 -23
  447. package/src/components/LpCollapse.vue +5 -4
  448. package/src/components/LpColorPicker.vue +8 -9
  449. package/src/components/LpCommandPalette.vue +133 -50
  450. package/src/components/LpContextMenu.vue +15 -13
  451. package/src/components/LpCountdown.vue +2 -1
  452. package/src/components/LpDataList.vue +13 -1
  453. package/src/components/LpDatePicker.vue +5 -17
  454. package/src/components/LpDateRangePicker.vue +5 -16
  455. package/src/components/LpDock.vue +25 -16
  456. package/src/components/LpDrawer.vue +70 -61
  457. package/src/components/LpDropdownMenu.vue +6 -10
  458. package/src/components/LpDropzone.vue +12 -7
  459. package/src/components/LpEditable.vue +6 -2
  460. package/src/components/LpFileTree.vue +507 -66
  461. package/src/components/LpFileTreeNode.vue +106 -5
  462. package/src/components/LpFormField.vue +1 -1
  463. package/src/components/LpFrame.vue +33 -13
  464. package/src/components/LpHoverCard.vue +30 -5
  465. package/src/components/LpIcon.vue +6 -2
  466. package/src/components/LpIdenticon.vue +2 -1
  467. package/src/components/LpImageEditor.vue +5 -2
  468. package/src/components/LpInput.vue +15 -23
  469. package/src/components/LpInspector.vue +197 -0
  470. package/src/components/LpLightbox.vue +74 -29
  471. package/src/components/LpLogInspector.vue +85 -0
  472. package/src/components/LpLogViewer.vue +239 -29
  473. package/src/components/LpMapPicker.vue +2 -1
  474. package/src/components/LpMasonry.vue +8 -5
  475. package/src/components/LpModal.vue +12 -12
  476. package/src/components/LpModalNav.vue +2 -21
  477. package/src/components/LpNumberField.vue +6 -15
  478. package/src/components/LpOtpInput.vue +2 -2
  479. package/src/components/LpPagination.vue +5 -3
  480. package/src/components/LpPhoneInput.vue +8 -19
  481. package/src/components/LpPie.vue +25 -23
  482. package/src/components/LpPipeline.vue +14 -1
  483. package/src/components/LpPopover.vue +23 -2
  484. package/src/components/LpProgress.vue +2 -1
  485. package/src/components/LpRadioGroup.vue +2 -2
  486. package/src/components/LpRangeSlider.vue +5 -6
  487. package/src/components/LpRevealOnScroll.vue +1 -1
  488. package/src/components/LpScrollArea.vue +28 -11
  489. package/src/components/LpSecretField.vue +2 -1
  490. package/src/components/LpSegmented.vue +6 -8
  491. package/src/components/LpSelect.vue +54 -24
  492. package/src/components/LpShaderBackdrop.vue +12 -9
  493. package/src/components/LpShift.vue +18 -15
  494. package/src/components/LpSidebar.vue +77 -74
  495. package/src/components/LpSidebarNav.vue +3 -2
  496. package/src/components/LpSidebarRow.vue +2 -1
  497. package/src/components/LpSlider.vue +5 -6
  498. package/src/components/LpSpotlight.vue +2 -1
  499. package/src/components/LpSwitch.vue +5 -3
  500. package/src/components/LpTable.vue +609 -93
  501. package/src/components/LpTableFilter.vue +1 -1
  502. package/src/components/LpTableOfContents.vue +16 -9
  503. package/src/components/LpTabs.vue +2 -1
  504. package/src/components/LpTagsInput.vue +12 -19
  505. package/src/components/LpTextarea.vue +5 -11
  506. package/src/components/LpThemeProvider.vue +29 -13
  507. package/src/components/LpTimeField.vue +4 -7
  508. package/src/components/LpToaster.vue +7 -6
  509. package/src/components/LpTooltip.vue +62 -18
  510. package/src/components/LpTopologyCanvas.vue +567 -42
  511. package/src/components/LpTour.vue +7 -5
  512. package/src/components/LpTruncate.vue +4 -3
  513. package/src/components/LpTypewriter.vue +2 -1
  514. package/src/components/LpVideoBackdrop.vue +11 -13
  515. package/src/components/LpWindow.vue +373 -0
  516. package/src/components/LpWorkspaceSwitcher.vue +116 -0
  517. package/src/components/PickerField.vue +2 -2
  518. package/src/components/SliderRail.vue +10 -0
  519. package/src/components/address.ts +3 -1
  520. package/src/components/appShell.ts +74 -0
  521. package/src/components/calendar.ts +12 -5
  522. package/src/components/chart.ts +27 -3
  523. package/src/components/chartWindow.ts +198 -0
  524. package/src/components/color.ts +2 -1
  525. package/src/components/commandPalette.ts +66 -5
  526. package/src/components/controlSize.ts +6 -0
  527. package/src/components/dropdown.ts +3 -0
  528. package/src/components/exportData.ts +33 -18
  529. package/src/components/fileTree.ts +215 -0
  530. package/src/components/identicon.ts +4 -2
  531. package/src/components/logTools.ts +298 -0
  532. package/src/components/meter.ts +2 -1
  533. package/src/components/pipeline.ts +6 -0
  534. package/src/components/relativeTime.ts +2 -1
  535. package/src/components/reveal.ts +3 -1
  536. package/src/components/select.ts +14 -0
  537. package/src/components/sidebar.ts +1 -0
  538. package/src/components/tableFeatures.ts +149 -0
  539. package/src/components/topologyGraph.ts +655 -0
  540. package/src/components/tour.ts +5 -3
  541. package/src/components/videoBackdrop.ts +7 -6
  542. package/src/composables/clamp.ts +2 -0
  543. package/src/composables/devWarn.ts +19 -0
  544. package/src/composables/easing.ts +37 -12
  545. package/src/composables/overlayHistory.ts +24 -0
  546. package/src/composables/pointerDrag.ts +54 -0
  547. package/src/composables/propCheck.ts +90 -0
  548. package/src/composables/realm.ts +25 -0
  549. package/src/composables/scroll.ts +4 -2
  550. package/src/composables/scrollMemory.ts +56 -14
  551. package/src/composables/spatialNav.ts +2 -1
  552. package/src/composables/textEntry.ts +33 -0
  553. package/src/composables/useAsyncTask.ts +6 -0
  554. package/src/composables/useChartSync.ts +52 -0
  555. package/src/composables/useCloseGuard.ts +22 -10
  556. package/src/composables/useCommands.ts +123 -0
  557. package/src/composables/useField.ts +41 -2
  558. package/src/composables/useFitScale.ts +4 -1
  559. package/src/composables/useFormDraft.ts +38 -14
  560. package/src/composables/useHintSystem.ts +2 -2
  561. package/src/composables/useHotkeys.ts +19 -48
  562. package/src/composables/useInView.ts +2 -1
  563. package/src/composables/useInputFilter.ts +8 -5
  564. package/src/composables/useInputMask.ts +8 -3
  565. package/src/composables/useLinkedView.ts +222 -0
  566. package/src/composables/useOptimisticToggle.ts +7 -1
  567. package/src/composables/useOverlayHistory.ts +20 -0
  568. package/src/composables/usePaintSelect.ts +20 -14
  569. package/src/composables/usePaletteCommands.ts +13 -0
  570. package/src/composables/usePersisted.ts +10 -0
  571. package/src/composables/usePillTransition.ts +9 -6
  572. package/src/composables/useResizeObserver.ts +2 -1
  573. package/src/composables/useReveal.ts +2 -1
  574. package/src/composables/useRovingFocus.ts +11 -14
  575. package/src/composables/useScramble.ts +12 -1
  576. package/src/composables/useShift.ts +8 -6
  577. package/src/composables/useTilt.ts +2 -1
  578. package/src/composables/useTween.ts +10 -5
  579. package/src/composables/useView.ts +17 -3
  580. package/src/composables/useZoomPan.ts +2 -5
  581. package/src/composables/windowing.ts +190 -0
  582. package/src/icons.ts +27 -6
  583. package/src/index.ts +41 -4
  584. package/src/kit-icons.ts +1 -1
  585. package/src/layout/tree.ts +31 -16
  586. package/src/layout/useLayout.ts +6 -0
  587. package/src/layout/useWorkspaces.ts +234 -0
  588. package/src/nuxt.ts +9 -1
  589. package/src/runtime/propCheck.plugin.ts +10 -0
  590. package/src/theme/studio.ts +7 -5
  591. package/src/theme/useTheme.ts +89 -15
  592. package/src/tokens/tokens.css +8 -1
  593. package/dist/assets/LpTabs-CJ0rYQbx.css +0 -18
  594. package/dist/chunks/LpAppShell-Dgejipzz.js +0 -319
  595. package/dist/chunks/LpFileTree-CooHinsC.js +0 -425
  596. package/dist/chunks/LpThemeProvider-8MG6yqU9.js +0 -640
  597. package/dist/chunks/LpTopologyCanvas-B1gIbS0n.js +0 -298
@@ -1,3 +1,4 @@
1
+ import { clamp } from "../composables/clamp"
1
2
  import { reactive } from "vue"
2
3
 
3
4
  /*
@@ -221,11 +222,11 @@ export function moveLeaf(
221
222
  ): void {
222
223
  if (movingId === targetId) return
223
224
  const moving = findLeaf(root, movingId)
224
- if (!moving) return
225
+ // Checked before the cell is detached: with nowhere to land it would be lost.
226
+ const target = findLeaf(root, targetId)
227
+ if (!moving || !target) return
225
228
 
226
229
  if (side === "center") {
227
- const target = findLeaf(root, targetId)
228
- if (!target) return
229
230
  const merged = moving.blocks
230
231
  detach(root, movingId)
231
232
  target.active = target.blocks.length
@@ -275,23 +276,37 @@ export function serializeLayout(root: Split): SerializedNode {
275
276
  return strip(root) as SerializedSplit
276
277
  }
277
278
 
279
+ const validSize = (size: unknown): number =>
280
+ typeof size === "number" && Number.isFinite(size) && size > 0 ? size : 1
281
+
282
+ /*
283
+ * The data may come from a file or an older version, so nothing about its
284
+ * shape is taken on trust: a bad size or direction falls back to the default
285
+ * and a node that cannot be drawn (no tabs, no children, an unknown kind) is
286
+ * left out, so one damaged cell does not cost the person the whole layout.
287
+ * Only a root that is no layout at all throws. Block ids are the app's, so an
288
+ * id that repeats across cells is kept.
289
+ */
278
290
  export function deserializeLayout(data: SerializedNode): Split {
279
- const hydrate = (n: SerializedNode): LayoutNode => {
280
- if (n.kind === "leaf") {
291
+ const hydrate = (n: SerializedNode | null | undefined): LayoutNode | null => {
292
+ if (n?.kind === "leaf") {
281
293
  // Accept both the tabbed form and the legacy single-`block` form.
282
- const blocks = n.blocks ?? (n.block != null ? [n.block] : [])
283
- const active = Math.min(Math.max(n.active ?? 0, 0), Math.max(blocks.length - 1, 0))
284
- return { kind: "leaf", id: nid(), blocks, active, size: n.size ?? 1 }
285
- }
286
- return {
287
- kind: "split",
288
- id: nid(),
289
- dir: n.dir,
290
- size: n.size ?? 1,
291
- children: n.children.map(hydrate),
294
+ const listed = Array.isArray(n.blocks) ? n.blocks : n.block != null ? [n.block] : []
295
+ const blocks = listed.filter((block) => typeof block === "string")
296
+ if (!blocks.length) return null
297
+ const wanted = Number.isInteger(n.active) ? n.active : 0
298
+ const active = clamp(wanted, 0, blocks.length - 1)
299
+ return { kind: "leaf", id: nid(), blocks, active, size: validSize(n.size) }
292
300
  }
301
+ if (n?.kind !== "split" || !Array.isArray(n.children)) return null
302
+ const children = n.children.map(hydrate).filter((child) => child !== null)
303
+ if (!children.length) return null
304
+ return { kind: "split", id: nid(), dir: n.dir === "col" ? "col" : "row", size: validSize(n.size), children }
293
305
  }
294
- return reactive(hydrate(data) as Split)
306
+ if (data?.kind !== "leaf" && data?.kind !== "split") throw new Error("Invalid layout")
307
+ const root = hydrate(data)
308
+ if (root?.kind === "split") return reactive(root)
309
+ return reactive<Split>({ kind: "split", id: nid(), dir: "row", size: 1, children: root ? [root] : [] })
295
310
  }
296
311
 
297
312
  // ── history snapshots ────────────────────────────────────────
@@ -90,6 +90,8 @@ export interface UseLayout {
90
90
  serialize: () => unknown
91
91
  /** Replace the layout from previously serialized data. */
92
92
  hydrate: (data: unknown) => void
93
+ /** Forget undo and redo, for a layout that replaces this one rather than edits it. */
94
+ clearHistory: () => void
93
95
  }
94
96
 
95
97
  export function useLayout(options: UseLayoutOptions): UseLayout {
@@ -180,5 +182,9 @@ export function useLayout(options: UseLayoutOptions): UseLayout {
180
182
  record(() => {
181
183
  layout.value = deserializeLayout(data as Parameters<typeof deserializeLayout>[0])
182
184
  }),
185
+ clearHistory: () => {
186
+ past.value = []
187
+ future.value = []
188
+ },
183
189
  }
184
190
  }
@@ -0,0 +1,234 @@
1
+ import { computed, getCurrentScope, onScopeDispose, watch, type ComputedRef } from "vue"
2
+ import { useKitStorage, usePersisted } from "../composables/usePersisted"
3
+ import { deserializeLayout, makeLayout, serializeLayout } from "./tree"
4
+ import { useLayout, type UseLayout } from "./useLayout"
5
+
6
+ /*
7
+ * useWorkspaces — several named layouts over one useLayout.
8
+ *
9
+ * `controller` is the plain useLayout, so a <LayoutCanvas> binds to it as to
10
+ * any other and never learns workspaces exist. This adds the shelf around it:
11
+ * the saved layouts, which one is showing, and keeping both across a restart.
12
+ * Edits land on the active workspace by themselves, debounced, because a
13
+ * divider drag changes the tree on every frame.
14
+ *
15
+ * What comes back from storage or an import goes through `deserializeLayout`,
16
+ * so a broken record costs that workspace its layout, not the page. Undo
17
+ * history belongs to one workspace: a switch clears it, or Undo would walk
18
+ * back into a layout from another one.
19
+ */
20
+
21
+ const STORE_VERSION = 1
22
+ const SAVE_DELAY_MS = 300
23
+ const DEFAULT_NAME = "Workspace"
24
+
25
+ export interface WorkspaceSeed {
26
+ id?: string
27
+ name: string
28
+ blocks: string[]
29
+ }
30
+
31
+ export interface WorkspaceEntry {
32
+ id: string
33
+ name: string
34
+ layout: unknown
35
+ }
36
+
37
+ export interface WorkspaceSummary {
38
+ id: string
39
+ name: string
40
+ }
41
+
42
+ /** One workspace as a file: what export gives and import takes. */
43
+ export interface WorkspaceExport {
44
+ name: string
45
+ layout: unknown
46
+ }
47
+
48
+ interface WorkspaceStore {
49
+ version: number
50
+ active: string
51
+ items: WorkspaceEntry[]
52
+ }
53
+
54
+ export interface UseWorkspacesOptions {
55
+ /** Block ids of a new or unreadable workspace. */
56
+ initial: string[]
57
+ /** The workspaces a first visit starts with. One from `initial` when unset. */
58
+ defaults?: WorkspaceSeed[]
59
+ /** Keep them across visits under this key (see `usePersisted`). In memory without one. */
60
+ persist?: string
61
+ historyLimit?: number
62
+ }
63
+
64
+ export interface UseWorkspaces {
65
+ /** The live layout of the active workspace, for <LayoutCanvas v-model>. */
66
+ controller: UseLayout
67
+ workspaces: ComputedRef<WorkspaceSummary[]>
68
+ activeId: ComputedRef<string>
69
+ switchTo: (id: string) => void
70
+ /** Add one and show it. From `blocks`, else from `initial`. Returns its id. */
71
+ create: (name: string, blocks?: string[]) => string
72
+ /** Copy a workspace (the active one by default) and show the copy. */
73
+ duplicate: (id?: string, name?: string) => string | null
74
+ rename: (id: string, name: string) => void
75
+ /** The last workspace stays: there is always one to show. */
76
+ remove: (id: string) => void
77
+ /** Back to `initial`, for the active workspace. */
78
+ resetActive: () => void
79
+ exportWorkspace: (id?: string) => WorkspaceExport | null
80
+ /** Add a workspace from an export. Null, and nothing added, when it does not read as a layout. */
81
+ importWorkspace: (data: unknown) => string | null
82
+ /** Write pending edits now instead of after the debounce. */
83
+ save: () => void
84
+ }
85
+
86
+ function isStore(value: unknown): value is WorkspaceStore {
87
+ const store = value as WorkspaceStore | null
88
+ if (!store || store.version !== STORE_VERSION || typeof store.active !== "string") return false
89
+ if (!Array.isArray(store.items) || store.items.length === 0) return false
90
+ const ids = new Set<string>()
91
+ for (const item of store.items) {
92
+ if (!item || typeof item.id !== "string" || typeof item.name !== "string" || ids.has(item.id)) return false
93
+ ids.add(item.id)
94
+ }
95
+ return true
96
+ }
97
+
98
+ let idCount = 0
99
+ const newId = () => `ws-${Date.now().toString(36)}-${(idCount++).toString(36)}`
100
+
101
+ export function useWorkspaces(options: UseWorkspacesOptions): UseWorkspaces {
102
+ const seed = (blocks: string[]) => serializeLayout(makeLayout(blocks))
103
+ const seeds = options.defaults?.length ? options.defaults : [{ name: DEFAULT_NAME, blocks: options.initial }]
104
+ const items = seeds.map((s, i) => ({ id: s.id ?? `ws-default-${i}`, name: s.name, layout: seed(s.blocks) }))
105
+
106
+ const store = usePersisted<WorkspaceStore>(
107
+ () => options.persist && `lp-workspaces:${options.persist}`,
108
+ { version: STORE_VERSION, active: items[0]!.id, items },
109
+ { validate: isStore },
110
+ )
111
+ const controller = useLayout({ initial: options.initial, historyLimit: options.historyLimit })
112
+
113
+ const entry = (id: string) => store.value.items.find((item) => item.id === id)
114
+ const activeId = computed(() => (entry(store.value.active) ? store.value.active : store.value.items[0]!.id))
115
+ const workspaces = computed(() => store.value.items.map(({ id, name }) => ({ id, name })))
116
+
117
+ let timer: ReturnType<typeof setTimeout> | undefined
118
+
119
+ function save() {
120
+ clearTimeout(timer)
121
+ timer = undefined
122
+ const current = entry(activeId.value)
123
+ if (!current) return
124
+ const layout = controller.serialize()
125
+ if (JSON.stringify(layout) !== JSON.stringify(current.layout)) current.layout = layout
126
+ }
127
+
128
+ function show(id: string) {
129
+ const target = entry(id)
130
+ if (!target) return
131
+ try {
132
+ controller.hydrate(target.layout)
133
+ } catch {
134
+ // Unreadable: this workspace starts over, the others are untouched.
135
+ controller.reset()
136
+ }
137
+ controller.clearHistory()
138
+ }
139
+
140
+ function switchTo(id: string) {
141
+ if (!entry(id) || id === activeId.value) return
142
+ save()
143
+ store.value.active = id
144
+ show(id)
145
+ }
146
+
147
+ function add(name: string, layout: unknown): string {
148
+ save()
149
+ const id = newId()
150
+ store.value.items.push({ id, name: name.trim() || DEFAULT_NAME, layout })
151
+ store.value.active = id
152
+ show(id)
153
+ return id
154
+ }
155
+
156
+ function duplicate(id = activeId.value, name?: string): string | null {
157
+ save()
158
+ const source = entry(id)
159
+ if (!source) return null
160
+ return add(name ?? source.name, JSON.parse(JSON.stringify(source.layout)))
161
+ }
162
+
163
+ function rename(id: string, name: string) {
164
+ const target = entry(id)
165
+ const trimmed = name.trim()
166
+ if (target && trimmed) target.name = trimmed
167
+ }
168
+
169
+ function remove(id: string) {
170
+ if (store.value.items.length <= 1) return
171
+ const at = store.value.items.findIndex((item) => item.id === id)
172
+ if (at === -1) return
173
+ const wasActive = id === activeId.value
174
+ if (!wasActive) save()
175
+ store.value.items.splice(at, 1)
176
+ if (!wasActive) return
177
+ clearTimeout(timer)
178
+ const next = store.value.items[Math.min(at, store.value.items.length - 1)]!
179
+ store.value.active = next.id
180
+ show(next.id)
181
+ }
182
+
183
+ function exportWorkspace(id = activeId.value): WorkspaceExport | null {
184
+ save()
185
+ const source = entry(id)
186
+ return source ? JSON.parse(JSON.stringify({ name: source.name, layout: source.layout })) : null
187
+ }
188
+
189
+ function importWorkspace(data: unknown): string | null {
190
+ const candidate = data as WorkspaceExport | null
191
+ if (!candidate || typeof candidate.name !== "string") return null
192
+ try {
193
+ return add(candidate.name, serializeLayout(deserializeLayout(candidate.layout as Parameters<typeof deserializeLayout>[0])))
194
+ } catch {
195
+ return null
196
+ }
197
+ }
198
+
199
+ show(activeId.value)
200
+
201
+ watch(
202
+ () => JSON.stringify(controller.serialize()),
203
+ () => {
204
+ clearTimeout(timer)
205
+ timer = setTimeout(save, SAVE_DELAY_MS)
206
+ },
207
+ )
208
+ // Direct: by now the persisted ref's own watcher has stopped with the scope.
209
+ const storage = useKitStorage()
210
+ if (getCurrentScope()) {
211
+ onScopeDispose(() => {
212
+ save()
213
+ if (options.persist) storage.set(`lp-workspaces:${options.persist}`, JSON.stringify(store.value))
214
+ })
215
+ }
216
+
217
+ return {
218
+ controller,
219
+ workspaces,
220
+ activeId,
221
+ switchTo,
222
+ create: (name, blocks) => add(name, seed(blocks ?? options.initial)),
223
+ duplicate,
224
+ rename,
225
+ remove,
226
+ resetActive: () => {
227
+ controller.reset()
228
+ save()
229
+ },
230
+ exportWorkspace,
231
+ importWorkspace,
232
+ save,
233
+ }
234
+ }
package/src/nuxt.ts CHANGED
@@ -23,6 +23,8 @@
23
23
  * app's source, "all" registers the whole set, "kit" only the
24
24
  * kit's own, or a list of names. Anything else still renders,
25
25
  * from a lazily loaded chunk of the bundled collection.
26
+ * propCheck false to skip the dev warning for an unknown prop on a kit
27
+ * component (default: on in `nuxt dev`, never in a build)
26
28
  */
27
29
  import { readFileSync } from "node:fs"
28
30
  import { createRequire } from "node:module"
@@ -43,6 +45,8 @@ export interface LeavepulseUiOptions {
43
45
  exclude?: string[]
44
46
  /** Lucide icons registered up front (default "scan"). */
45
47
  icons?: "scan" | "all" | "kit" | string[]
48
+ /** Warn in `nuxt dev` about an unknown prop on a kit component (default true). */
49
+ propCheck?: boolean
46
50
  }
47
51
 
48
52
  function iconsPlugin(mode: LeavepulseUiOptions["icons"], srcDir: string): string {
@@ -55,7 +59,7 @@ function iconsPlugin(mode: LeavepulseUiOptions["icons"], srcDir: string): string
55
59
 
56
60
  export default defineNuxtModule<LeavepulseUiOptions>({
57
61
  meta: { name: "@leavepulse/ui", configKey: "leavepulseUi" },
58
- defaults: { theme: true, link: true, icons: "scan" },
62
+ defaults: { theme: true, link: true, icons: "scan", propCheck: true },
59
63
  setup(options, nuxt) {
60
64
  const resolver = createResolver(import.meta.url)
61
65
  const skip = new Set(options.exclude ?? [])
@@ -79,6 +83,10 @@ export default defineNuxtModule<LeavepulseUiOptions>({
79
83
  })
80
84
  }
81
85
 
86
+ if (nuxt.options.dev && options.propCheck !== false) {
87
+ addPlugin({ src: resolver.resolve("./runtime/propCheck.plugin"), mode: "client" })
88
+ }
89
+
82
90
  if (options.link !== false) {
83
91
  addPlugin({ src: resolver.resolve("./runtime/config.plugin"), mode: "all" })
84
92
  }
@@ -0,0 +1,10 @@
1
+ /*
2
+ * Nuxt runtime plugin: warns in `nuxt dev` about an unknown prop on a kit
3
+ * component. Registered by the kit's Nuxt module, never in a build.
4
+ */
5
+ import { lpPropCheck } from "@leavepulse/ui"
6
+ import { defineNuxtPlugin } from "#imports"
7
+
8
+ export default defineNuxtPlugin((nuxtApp) => {
9
+ nuxtApp.vueApp.use(lpPropCheck)
10
+ })
@@ -1,4 +1,4 @@
1
- import { computed, ref, shallowRef, watch, watchEffect, type ComputedRef, type Ref } from "vue"
1
+ import { computed, getCurrentScope, onScopeDispose, ref, shallowRef, watch, watchEffect, type ComputedRef, type Ref } from "vue"
2
2
  import { usePersisted } from "../composables/usePersisted"
3
3
  import { defineTheme, withBrand } from "./define"
4
4
  import { presets } from "./presets"
@@ -110,10 +110,12 @@ function create(key: string, config: Ref<Omit<ThemeStudioOptions, "storageKey">>
110
110
  const dark = pair && themes.value.find((t) => t.name === pair.dark)
111
111
  return light && dark ? { light, dark } : null
112
112
  })
113
- const prefersDark = ref(typeof window !== "undefined" && !!window.matchMedia?.("(prefers-color-scheme: dark)").matches)
114
- if (typeof window !== "undefined") {
115
- window.matchMedia?.("(prefers-color-scheme: dark)").addEventListener("change", (e) => (prefersDark.value = e.matches))
116
- }
113
+ const scheme = typeof window === "undefined" ? undefined : window.matchMedia?.("(prefers-color-scheme: dark)")
114
+ const prefersDark = ref(!!scheme?.matches)
115
+ const onScheme = (e: MediaQueryListEvent) => (prefersDark.value = e.matches)
116
+ scheme?.addEventListener("change", onScheme)
117
+ // A studio opened and closed again left its listener on the page.
118
+ if (getCurrentScope()) onScopeDispose(() => scheme?.removeEventListener("change", onScheme))
117
119
  const engine = useTheme()
118
120
  const defaults = (): StudioState => ({
119
121
  theme: engine.currentName.value || themes.value[0]?.name || "",
@@ -36,7 +36,9 @@ type Cached = { theme: TokenSet; system?: undefined } | { system: SystemThemes;
36
36
  // ── self-managed theme state (singleton) ─────────────────────────────────
37
37
  // The kit owns the active theme, like an i18n locale, so every consumer shares
38
38
  // one source of truth. Lazily hydrated from the cache on the client; on the
39
- // server `current` stays null.
39
+ // server `current` stays null and `init` writes nothing, because this module
40
+ // outlives a request and one visitor's theme must not reach the next. A server
41
+ // renders from `themeFromCookie` + `themeToCssRule`; the setters are client-only.
40
42
  const _current = shallowRef<TokenSet | null>(null)
41
43
  const _system = shallowRef<SystemThemes | null>(null)
42
44
  let _hydrated = false
@@ -182,22 +184,31 @@ export function revealTransition(
182
184
  update: () => void | Promise<void>,
183
185
  origin?: RevealOrigin,
184
186
  durationMs = 480,
187
+ page: Document = document,
185
188
  ): void {
186
- const doc = document as ViewTransitionDocument
187
- if (typeof doc.startViewTransition !== "function" || prefersReducedMotion()) {
189
+ const doc = page as ViewTransitionDocument
190
+ const win = page.defaultView ?? window
191
+ if (typeof doc.startViewTransition !== "function" || prefersReducedMotion(win)) {
188
192
  void update()
189
193
  return
190
194
  }
191
195
 
192
- const x = origin?.x ?? window.innerWidth / 2
193
- const y = origin?.y ?? window.innerHeight / 2
196
+ const x = origin?.x ?? win.innerWidth / 2
197
+ const y = origin?.y ?? win.innerHeight / 2
194
198
  // Radius that reaches the farthest viewport corner from the origin.
195
199
  const endRadius = Math.hypot(
196
- Math.max(x, window.innerWidth - x),
197
- Math.max(y, window.innerHeight - y),
200
+ Math.max(x, win.innerWidth - x),
201
+ Math.max(y, win.innerHeight - y),
198
202
  )
199
203
 
200
204
  const transition = doc.startViewTransition(update)
205
+ /*
206
+ * `ready` rejects when there will be nothing to animate: a newer transition
207
+ * replaced this one (the browser skips it by itself, and its `update` still
208
+ * runs, so quick switches land in order) or the page went hidden. An `update`
209
+ * that throws still reports, through `finished`.
210
+ */
211
+ const skipped = () => {}
201
212
  transition.ready.then(() => {
202
213
  // Animate the OLD snapshot shrinking to a point, revealing the (already
203
214
  // repainted) live page underneath through the growing hole. Clipping the
@@ -205,13 +216,13 @@ export function revealTransition(
205
216
  // theme before the circle starts, which read as the theme "changing twice".
206
217
  // The pseudo-elements belong to the document element whatever was updated,
207
218
  // so the animation always targets it.
208
- document.documentElement.animate(
219
+ page.documentElement.animate(
209
220
  {
210
221
  clipPath: [`circle(${endRadius}px at ${x}px ${y}px)`, `circle(0px at ${x}px ${y}px)`],
211
222
  },
212
223
  {
213
224
  duration: durationMs,
214
- easing: easingToken("ease-emphasized"),
225
+ easing: easingToken("ease-emphasized", undefined, page),
215
226
  // Hold the fully-shrunk circle after the keyframes end. Without it the
216
227
  // old snapshot snaps back to its default (un-clipped) state for the one
217
228
  // frame between animation-end and the browser tearing down the
@@ -221,7 +232,7 @@ export function revealTransition(
221
232
  pseudoElement: "::view-transition-old(root)",
222
233
  },
223
234
  )
224
- })
235
+ }, skipped)
225
236
  }
226
237
 
227
238
  /*
@@ -235,7 +246,7 @@ export function applyThemeWithTransition(
235
246
  root: HTMLElement = document.documentElement,
236
247
  durationMs = 480,
237
248
  ): void {
238
- revealTransition(() => applyTheme(theme, root), origin, durationMs)
249
+ revealTransition(() => applyTheme(theme, root), origin, durationMs, root.ownerDocument)
239
250
  }
240
251
 
241
252
  export function serializeTheme(theme: TokenSet): string {
@@ -279,12 +290,72 @@ export function normalizeTheme(raw: Partial<TokenSet> & { name?: string }): Toke
279
290
  }
280
291
  }
281
292
 
282
- /** Parse + validate a theme JSON; throws on a malformed shape. */
293
+ const THEME_NAME_MAX = 64
294
+ /* Past the 9999 a pill radius is spelt with: beyond that a size is a typo, not a design. */
295
+ const THEME_SIZE_MAX = 99_999
296
+ /* A value goes into a stylesheet as text (themeToCssRule), so it must not be able to leave its declaration. */
297
+ const CSS_BREAKOUT = /[{}<>]/
298
+ const CSS_URL = /url\([^()]*\)/g
299
+
300
+ function cssValueProblem(value: unknown): string | null {
301
+ if (typeof value !== "string" || !value.trim()) return "must be a non-empty string"
302
+ // A `;` belongs inside a data: url, and nowhere else in a value.
303
+ if (CSS_BREAKOUT.test(value) || value.replace(CSS_URL, "").includes(";")) return "is not a single CSS value"
304
+ return null
305
+ }
306
+
307
+ function sizeProblem(value: unknown): string | null {
308
+ if (typeof value !== "number" || !Number.isFinite(value)) return "must be a finite number"
309
+ if (value < 0 || value > THEME_SIZE_MAX) return `must be between 0 and ${THEME_SIZE_MAX}`
310
+ return null
311
+ }
312
+
313
+ function axisProblem(
314
+ axis: string,
315
+ values: unknown,
316
+ keys: object,
317
+ check: (value: unknown) => string | null,
318
+ ): string | null {
319
+ if (values === undefined) return null
320
+ if (!values || typeof values !== "object") return `${axis} must be an object`
321
+ for (const key of Object.keys(keys)) {
322
+ const value = (values as Record<string, unknown>)[key]
323
+ if (value === undefined) continue
324
+ const problem = check(value)
325
+ if (problem) return `${axis}.${key} ${problem}`
326
+ }
327
+ return null
328
+ }
329
+
330
+ /*
331
+ * What is wrong with a theme read from storage or a file, or null. Types stop
332
+ * at the JSON boundary: `radiusCard: "huge"` would reach the page as `hugepx`.
333
+ * A token that is simply missing is fine: normalizeTheme fills it, which is how
334
+ * a theme saved before that token existed keeps working.
335
+ */
336
+ export function themeProblem(raw: Partial<TokenSet>): string | null {
337
+ const { name, mode } = raw as { name?: unknown; mode?: unknown }
338
+ if (name !== undefined && (typeof name !== "string" || !name.trim() || name.length > THEME_NAME_MAX)) {
339
+ return `name must be 1 to ${THEME_NAME_MAX} characters`
340
+ }
341
+ if (mode !== undefined && mode !== "light" && mode !== "dark") return 'mode must be "light" or "dark"'
342
+ return (
343
+ axisProblem("colors", raw.colors, COLOR_VARS, cssValueProblem) ??
344
+ axisProblem("shape", raw.shape, SHAPE_VARS, sizeProblem) ??
345
+ axisProblem("density", raw.density, DENSITY_VARS, sizeProblem) ??
346
+ axisProblem("font", raw.font, FONT_VARS, cssValueProblem) ??
347
+ axisProblem("surface", raw.surface, SURFACE_VARS, cssValueProblem)
348
+ )
349
+ }
350
+
351
+ /** Parse + validate a theme JSON; throws on a malformed shape or a bad token value. */
283
352
  export function parseTheme(json: string): TokenSet {
284
353
  const raw = JSON.parse(json) as Partial<TokenSet>
285
354
  if (!raw || typeof raw !== "object" || !raw.colors || !raw.shape || !raw.density) {
286
355
  throw new Error("Invalid theme: missing colors/shape/density")
287
356
  }
357
+ const problem = themeProblem(raw)
358
+ if (problem) throw new Error(`Invalid theme: ${problem}`)
288
359
  return normalizeTheme(raw)
289
360
  }
290
361
 
@@ -321,7 +392,8 @@ export function cacheSystemThemes(system: SystemThemes): void {
321
392
  /*
322
393
  * SSR handoff. localStorage is invisible to the server, so the theme NAME rides
323
394
  * along in a cookie and the server resolves it against the themes it knows
324
- * (see themeFromCookie). "Follow the OS" is stored as `system:<light>|<dark>`.
395
+ * (see themeFromCookie). "Follow the OS" is stored as `system:<light>|<dark>`,
396
+ * each name encoded on its own so a `|` in a name stays part of that name.
325
397
  */
326
398
  export const THEME_COOKIE = "lp-theme"
327
399
  const SYSTEM_PREFIX = "system:"
@@ -329,7 +401,7 @@ const SYSTEM_PREFIX = "system:"
329
401
  const COOKIE_MAX_AGE = 60 * 60 * 24 * 365
330
402
 
331
403
  function systemCookieValue(system: SystemThemes): string {
332
- return `${SYSTEM_PREFIX}${system.light.name}|${system.dark.name}`
404
+ return `${SYSTEM_PREFIX}${encodeURIComponent(system.light.name)}|${encodeURIComponent(system.dark.name)}`
333
405
  }
334
406
 
335
407
  function writeThemeCookie(value: string): void {
@@ -368,7 +440,8 @@ export function themeFromCookie(
368
440
  if (value.startsWith(SYSTEM_PREFIX)) {
369
441
  const [lightName = "", darkName = ""] = value.slice(SYSTEM_PREFIX.length).split("|")
370
442
  const wanted = options.prefersDark === false ? lightName : darkName
371
- const found = find(wanted)
443
+ // Raw too: a cookie from before the names were encoded.
444
+ const found = find(safeDecode(wanted)) ?? find(wanted)
372
445
  if (found) return found
373
446
  continue
374
447
  }
@@ -427,6 +500,7 @@ export function useTheme(): UseTheme {
427
500
  _current.value = theme
428
501
  },
429
502
  init: (fallback: TokenSet) => {
503
+ if (typeof window === "undefined") return fallback
430
504
  _fallback = fallback
431
505
  hydrateOnce()
432
506
  if (!_current.value) _current.value = bootstrapTheme(fallback)
@@ -173,6 +173,8 @@
173
173
  for it, and below the toasts one on a toast's own button (the error
174
174
  toast's copy) opened underneath the toast stacked above it. */
175
175
  @theme {
176
+ /* The app shell's header, rail and bars over a page that scrolls under them. */
177
+ --z-sticky: 40;
176
178
  --z-dropdown: 50;
177
179
  --z-overlay: 100;
178
180
  --z-modal: 110;
@@ -823,7 +825,12 @@
823
825
  CSS transitions/animate-pulse used across the kit collapse to a near-instant
824
826
  state change — content still mounts/unmounts, it just doesn't travel. This is
825
827
  the CSS half; motion-v springs (Tabs/Layout) opt out in JS via
826
- usePrefersReducedMotion() (usePillTransition). */
828
+ usePrefersReducedMotion() (usePillTransition).
829
+
830
+ Global on purpose, and part of this stylesheet's contract: it also covers the
831
+ host app's own elements, so an app that imports the kit's CSS gets reduced
832
+ motion for free. An animation that must keep running (a status spinner) sets
833
+ its own `animation-duration` with `!important` in a later layer. */
827
834
  @media (prefers-reduced-motion: reduce) {
828
835
  *,
829
836
  *::before,
@@ -1,18 +0,0 @@
1
-
2
- .lp-tab-badge-enter-active[data-v-1d673b52],
3
- .lp-tab-badge-leave-active[data-v-1d673b52] {
4
- transition:
5
- opacity var(--duration-fast) var(--ease-emphasized),
6
- transform var(--duration-fast) var(--ease-emphasized);
7
- }
8
- .lp-tab-badge-enter-from[data-v-1d673b52],
9
- .lp-tab-badge-leave-to[data-v-1d673b52] {
10
- opacity: 0;
11
- transform: scale(0.6);
12
- }
13
- @media (prefers-reduced-motion: reduce) {
14
- .lp-tab-badge-enter-active[data-v-1d673b52],
15
- .lp-tab-badge-leave-active[data-v-1d673b52] {
16
- transition: none;
17
- }
18
- }