@leavepulse/ui 0.71.2 → 0.72.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 (276) hide show
  1. package/dist/assets/{LpKeys-BxRhfQda.css → LpKeys-C5VMcBOW.css} +10 -5
  2. package/dist/assets/LpTabs-CDchzoRL.css +18 -0
  3. package/dist/chunks/{ContextMenuItems-eS7qx9gD.js → ContextMenuItems-BXumicbh.js} +1 -1
  4. package/dist/chunks/{DropzoneLinkField-DkFhdfEJ.js → DropzoneLinkField-DpOB20Lx.js} +2 -2
  5. package/dist/chunks/{FieldWrapper-YzbvvC3M.js → FieldWrapper-DHhRxO5G.js} +1 -1
  6. package/dist/chunks/{LayoutCanvas-Ba4A9QC5.js → LayoutCanvas-CNOAUk7D.js} +1 -1
  7. package/dist/chunks/{LayoutNode-CTTTLMDM.js → LayoutNode-DF5BMN0J.js} +1 -1
  8. package/dist/chunks/{LpActionBar-B7anGlkI.js → LpActionBar-BqicINE_.js} +3 -3
  9. package/dist/chunks/{LpAddressInput-Bu6ws3Fp.js → LpAddressInput-CkbKLufb.js} +7 -7
  10. package/dist/chunks/{LpAlert-BHi7ARqu.js → LpAlert-BigMdAbu.js} +3 -3
  11. package/dist/chunks/{LpAppShell-C5YW5pI7.js → LpAppShell-DIMy-vjP.js} +68 -18
  12. package/dist/chunks/{LpAutocomplete-DDqe2M5g.js → LpAutocomplete-DOu7FN5P.js} +2 -2
  13. package/dist/chunks/{LpAvatar-DqfKCIdr.js → LpAvatar-Cg6Az3wz.js} +1 -1
  14. package/dist/chunks/{LpBadge-C8fKEmTF.js → LpBadge-Huo8EKew.js} +3 -3
  15. package/dist/chunks/LpBottomNav-BZIpahzA.js +89 -0
  16. package/dist/chunks/{LpBreadcrumbs-DhcoStFa.js → LpBreadcrumbs-DGtpBhWt.js} +3 -3
  17. package/dist/chunks/{LpButton-BQDAFXBd.js → LpButton-CW34A1e4.js} +1 -1
  18. package/dist/chunks/{LpCalendar-NmrA47J9.js → LpCalendar-CuoWks-0.js} +1 -1
  19. package/dist/chunks/{LpCard-CqKLnEhl.js → LpCard-B0sFXQzc.js} +1 -1
  20. package/dist/chunks/{LpCheckbox-BoOuLnGB.js → LpCheckbox-iaD63DEF.js} +2 -2
  21. package/dist/chunks/{LpCodeBlock-Czu-fq1M.js → LpCodeBlock-CFFa_pJb.js} +2 -2
  22. package/dist/chunks/{LpCodeDisplay-C9pIMF2R.js → LpCodeDisplay-CFmGMAmP.js} +6 -6
  23. package/dist/chunks/{LpColorPicker-Ee1DZiRd.js → LpColorPicker-1y1QJHZR.js} +56 -28
  24. package/dist/chunks/{LpConfirmDialog-i15pulMT.js → LpConfirmDialog-BDystNtm.js} +3 -3
  25. package/dist/chunks/{LpConfirmHost-D0oGavtd.js → LpConfirmHost-oOsxJHfQ.js} +1 -1
  26. package/dist/chunks/{LpContextMenu-DXpFJjlO.js → LpContextMenu-rx2tCjwk.js} +2 -2
  27. package/dist/chunks/{LpCopyButton-Dmq7DmFw.js → LpCopyButton-BNcGbVXF.js} +2 -2
  28. package/dist/chunks/{LpCountdown-CXrEK0ev.js → LpCountdown-Cak7cq3X.js} +3 -3
  29. package/dist/chunks/{LpDataList-CFPtSsBB.js → LpDataList-B6Meb4M9.js} +3 -3
  30. package/dist/chunks/{LpDatePicker-cC9K-Pk8.js → LpDatePicker-CA0QTfBC.js} +4 -4
  31. package/dist/chunks/{LpDateRangePicker-BVQKPbvo.js → LpDateRangePicker-u3J51xXk.js} +2 -2
  32. package/dist/chunks/{LpDisclosure-hRnX3FWL.js → LpDisclosure-Cpa7Hc5T.js} +1 -1
  33. package/dist/chunks/{LpDrawer-u4rxnuR-.js → LpDrawer-RRamxbLV.js} +1 -1
  34. package/dist/chunks/{LpDropdownMenu-BgZ0Z_Im.js → LpDropdownMenu-Dl7Z4ZhS.js} +2 -2
  35. package/dist/chunks/{LpEditable-CjxuOVh_.js → LpEditable-BNogo5DL.js} +5 -5
  36. package/dist/chunks/{LpEmptyState-CKFTtQgJ.js → LpEmptyState-EQHiRYhG.js} +7 -3
  37. package/dist/chunks/{LpFieldNotice-CPI8EwtU.js → LpFieldNotice-CzQ2_5rQ.js} +1 -1
  38. package/dist/chunks/{LpFileTree-BH0gNlSJ.js → LpFileTree-CHgtVh14.js} +2 -2
  39. package/dist/chunks/{LpFileTreeNode-gPVB1oXM.js → LpFileTreeNode-LqHgHd3B.js} +5 -5
  40. package/dist/chunks/{LpFormField-gRASfyj2.js → LpFormField-CC57DdTi.js} +2 -2
  41. package/dist/chunks/{LpGauge-DFdt33x8.js → LpGauge-BO1PYYqD.js} +2 -2
  42. package/dist/chunks/{LpHintLayer-C2asBIfs.js → LpHintLayer-CvAj4aa6.js} +2 -2
  43. package/dist/chunks/{LpHints-CNZQ76JV.js → LpHints-BtRvHQQ0.js} +3 -3
  44. package/dist/chunks/{LpIcon-DkP-9mzK.js → LpIcon--5WSb3jJ.js} +1 -1
  45. package/dist/chunks/{LpInfraNode-yTh4-5qa.js → LpInfraNode-CxngdQAG.js} +2 -2
  46. package/dist/chunks/{LpInput-2H-5ILOB.js → LpInput-DqmL-438.js} +2 -2
  47. package/dist/chunks/{LpLightbox-lAt5uIfx.js → LpLightbox-7YP6zSDm.js} +3 -3
  48. package/dist/chunks/{LpLoader-DjJEX8hL.js → LpLoader-CUo1MX_0.js} +1 -1
  49. package/dist/chunks/{LpLogViewer-x78YfhJf.js → LpLogViewer-DQOIsnZ1.js} +6 -6
  50. package/dist/chunks/{LpMapPicker-Dp5RSCi9.js → LpMapPicker-Dm3vJHN2.js} +2 -2
  51. package/dist/chunks/{LpMediaGallery-D92oJfY_.js → LpMediaGallery-znEbvIEo.js} +3 -3
  52. package/dist/chunks/{LpModal-CpH0bNo7.js → LpModal-BnjZ2iem.js} +1 -1
  53. package/dist/chunks/{LpModalNav-Cuna8c_3.js → LpModalNav-CH1UE9Ch.js} +4 -4
  54. package/dist/chunks/{LpNotificationBell-BdUQqZhs.js → LpNotificationBell-CrywodQ_.js} +8 -8
  55. package/dist/chunks/{LpNumberField-DZY3Z670.js → LpNumberField-e0IBkWU1.js} +1 -1
  56. package/dist/chunks/{LpNumberFlow-Dwb9MV1A.js → LpNumberFlow-CcxEGUy0.js} +4 -2
  57. package/dist/chunks/{LpPagination-DbeACavM.js → LpPagination-BIIiYHXR.js} +1 -1
  58. package/dist/chunks/{LpPaletteTheme-DkikZ362.js → LpPaletteTheme-BzHBh-mN.js} +4 -4
  59. package/dist/chunks/{LpPasswordInput-BzAZsf5V.js → LpPasswordInput-DVgRgTVx.js} +2 -2
  60. package/dist/chunks/{LpPhoneInput-BMpd-0QR.js → LpPhoneInput-CETEp5W7.js} +2 -2
  61. package/dist/chunks/{LpPie-C1uIUFxu.js → LpPie-BjDbeytx.js} +6 -6
  62. package/dist/chunks/{LpPipeline-zjEM1Lwc.js → LpPipeline-zZUj7I6K.js} +4 -4
  63. package/dist/chunks/{LpProgress-WNaH4emv.js → LpProgress-rOlyafqp.js} +1 -1
  64. package/dist/chunks/{LpQuota-Cz9PvklM.js → LpQuota-B12yijdB.js} +3 -3
  65. package/dist/chunks/{LpRadioGroup-CsXeV9Ct.js → LpRadioGroup-ggaPL92T.js} +1 -1
  66. package/dist/chunks/{LpRangeCalendar-l-0nSFmY.js → LpRangeCalendar-CYYUYqJ7.js} +1 -1
  67. package/dist/chunks/{LpRelativeTime-UM8EkfrN.js → LpRelativeTime-DwgCb5-8.js} +1 -1
  68. package/dist/chunks/{LpRepeater-OvzByE5L.js → LpRepeater-BQB0twJ5.js} +3 -3
  69. package/dist/chunks/LpRollingText-B54Pje7P.js +86 -0
  70. package/dist/chunks/{LpScramble-TDO5Kdou.js → LpScramble-DbQyBjUY.js} +1 -1
  71. package/dist/chunks/{LpSecretField-DwQiPOko.js → LpSecretField-uoD6Fngf.js} +7 -7
  72. package/dist/chunks/{LpSection-DcQsieHG.js → LpSection-DFK_uoJE.js} +1 -1
  73. package/dist/chunks/{LpSegmented-D2VST0o3.js → LpSegmented-CeACsMMA.js} +4 -2
  74. package/dist/chunks/{LpSelect-D3pRJfRY.js → LpSelect-Cxq4yBGd.js} +3 -3
  75. package/dist/chunks/LpShift-C-UGuKMN.js +171 -0
  76. package/dist/chunks/LpSidebar-DXdbvgM6.js +494 -0
  77. package/dist/chunks/LpSidebarNav-CE6CVCb0.js +367 -0
  78. package/dist/chunks/LpSidebarRow-CF9VFZ2w.js +304 -0
  79. package/dist/chunks/{LpStat-Dzn6WFzi.js → LpStat-CjpXrC8R.js} +6 -4
  80. package/dist/chunks/{LpStatus-BQU1TUsv.js → LpStatus-g-8z9b_u.js} +3 -3
  81. package/dist/chunks/{LpStepMark-CXa7DJy_.js → LpStepMark-DU7xalwW.js} +3 -3
  82. package/dist/chunks/{LpStepper-C9RM_yTG.js → LpStepper-CbRXiXNs.js} +1 -1
  83. package/dist/chunks/{LpSwap-DzE6M3Mg.js → LpSwap-Xi4j9PR_.js} +1 -1
  84. package/dist/chunks/{LpSwitch-bGZxUDSx.js → LpSwitch-BWcXEahf.js} +1 -1
  85. package/dist/chunks/LpTabFace-CG0VqD8I.js +77 -0
  86. package/dist/chunks/{LpTableFilter-CTZMqFDU.js → LpTableFilter-CYtK9GsF.js} +3 -3
  87. package/dist/chunks/{LpTagsInput-DrjmrOge.js → LpTagsInput-D1RzCwb5.js} +5 -5
  88. package/dist/chunks/{LpTextarea-BbYqmG1S.js → LpTextarea-MdIzNTjw.js} +32 -7
  89. package/dist/chunks/{useTheme-BOV_-AiY.js → LpThemeProvider-8MG6yqU9.js} +66 -1
  90. package/dist/chunks/{LpThemeStudio-IupHqP0x.js → LpThemeStudio-B0Kk1bX0.js} +138 -104
  91. package/dist/chunks/LpThemeStudioSection-B7bt8Iyg.js +32 -0
  92. package/dist/chunks/{LpThemeSwitcher-DarPHuX8.js → LpThemeSwitcher-CI4I7ygL.js} +6 -6
  93. package/dist/chunks/{LpTimeField-DQ8WvPr2.js → LpTimeField-BawSVsmt.js} +1 -1
  94. package/dist/chunks/{LpToaster-BTTl_wuy.js → LpToaster-C-P1nmMS.js} +2 -2
  95. package/dist/chunks/{LpTopologyCanvas-Cq-MiJwo.js → LpTopologyCanvas-CbEZhsP1.js} +1 -1
  96. package/dist/chunks/{LpTour-BgCfNlaW.js → LpTour-DRyzgpjt.js} +1 -1
  97. package/dist/chunks/{LpTruncate-TcqfkyJM.js → LpTruncate-4WvCWqnW.js} +1 -1
  98. package/dist/chunks/{LpUptimeBar-BbhVTPnL.js → LpUptimeBar-B2LNSNxs.js} +4 -4
  99. package/dist/chunks/{MenuTitle-Dab3EGOp.js → MenuTitle-BmCNNTKH.js} +1 -1
  100. package/dist/chunks/{OptionContent-DPzNsybd.js → OptionContent-22UT8zLn.js} +1 -1
  101. package/dist/chunks/{PickerField-DwLw7j0L.js → PickerField-Bfh8id3d.js} +2 -2
  102. package/dist/chunks/{RevealToggle-BVFM_FAU.js → RevealToggle-jBLJwVwO.js} +2 -2
  103. package/dist/chunks/{TourCard--2IfgnUU.js → TourCard-BOBcGbEo.js} +5 -5
  104. package/dist/chunks/{icons-CLu1iR1j.js → icons-DMITlfw5.js} +1 -1
  105. package/dist/component-names.d.ts +1 -1
  106. package/dist/components/ContextMenuItems.vue.js +1 -1
  107. package/dist/components/DropzoneLinkField.vue.js +1 -1
  108. package/dist/components/FieldWrapper.vue.js +1 -1
  109. package/dist/components/LayoutCanvas.vue.js +1 -1
  110. package/dist/components/LayoutNode.vue.js +1 -1
  111. package/dist/components/LpActionBar.vue.js +1 -1
  112. package/dist/components/LpAddressInput.vue.js +1 -1
  113. package/dist/components/LpAlert.vue.js +1 -1
  114. package/dist/components/LpAppShell.vue.d.ts +67 -2
  115. package/dist/components/LpAppShell.vue.js +1 -1
  116. package/dist/components/LpAutocomplete.vue.js +1 -1
  117. package/dist/components/LpAvatar.vue.js +1 -1
  118. package/dist/components/LpBadge.vue.js +1 -1
  119. package/dist/components/LpBottomNav.vue.d.ts +28 -0
  120. package/dist/components/LpBottomNav.vue.js +4 -0
  121. package/dist/components/LpBreadcrumbs.vue.js +1 -1
  122. package/dist/components/LpButton.vue.js +1 -1
  123. package/dist/components/LpCalendar.vue.js +1 -1
  124. package/dist/components/LpCard.vue.js +1 -1
  125. package/dist/components/LpChart.vue.js +4 -4
  126. package/dist/components/LpCheckbox.vue.js +1 -1
  127. package/dist/components/LpCodeBlock.vue.js +1 -1
  128. package/dist/components/LpCodeDisplay.vue.js +1 -1
  129. package/dist/components/LpColorPicker.vue.d.ts +15 -2
  130. package/dist/components/LpColorPicker.vue.js +1 -1
  131. package/dist/components/LpCommandPalette.vue.js +4 -4
  132. package/dist/components/LpConfirmDialog.vue.js +1 -1
  133. package/dist/components/LpConfirmHost.vue.js +1 -1
  134. package/dist/components/LpContextMenu.vue.js +1 -1
  135. package/dist/components/LpCopyButton.vue.js +1 -1
  136. package/dist/components/LpCountdown.vue.js +1 -1
  137. package/dist/components/LpDataList.vue.js +1 -1
  138. package/dist/components/LpDatePicker.vue.js +1 -1
  139. package/dist/components/LpDateRangePicker.vue.js +1 -1
  140. package/dist/components/LpDisclosure.vue.js +1 -1
  141. package/dist/components/LpDock.vue.js +1 -1
  142. package/dist/components/LpDrawer.vue.js +1 -1
  143. package/dist/components/LpDropdownMenu.vue.js +1 -1
  144. package/dist/components/LpDropzone.vue.js +2 -2
  145. package/dist/components/LpEditable.vue.js +1 -1
  146. package/dist/components/LpEmptyState.vue.d.ts +2 -0
  147. package/dist/components/LpEmptyState.vue.js +1 -1
  148. package/dist/components/LpFieldNotice.vue.js +1 -1
  149. package/dist/components/LpFileTree.vue.js +1 -1
  150. package/dist/components/LpFileTreeNode.vue.js +1 -1
  151. package/dist/components/LpFormField.vue.js +1 -1
  152. package/dist/components/LpGauge.vue.js +1 -1
  153. package/dist/components/LpHintLayer.vue.js +1 -1
  154. package/dist/components/LpHints.vue.js +1 -1
  155. package/dist/components/LpIcon.vue.js +1 -1
  156. package/dist/components/LpImageEditor.vue.js +3 -3
  157. package/dist/components/LpInfraNode.vue.js +1 -1
  158. package/dist/components/LpInput.vue.js +1 -1
  159. package/dist/components/LpKeys.vue.js +13 -10
  160. package/dist/components/LpLightbox.vue.js +1 -1
  161. package/dist/components/LpLoader.vue.js +1 -1
  162. package/dist/components/LpLogViewer.vue.d.ts +1 -1
  163. package/dist/components/LpLogViewer.vue.js +1 -1
  164. package/dist/components/LpMapPicker.vue.js +1 -1
  165. package/dist/components/LpMediaGallery.vue.js +1 -1
  166. package/dist/components/LpModal.vue.js +1 -1
  167. package/dist/components/LpModalNav.vue.js +1 -1
  168. package/dist/components/LpNotificationBell.vue.js +1 -1
  169. package/dist/components/LpNumberField.vue.js +1 -1
  170. package/dist/components/LpNumberFlow.vue.js +1 -1
  171. package/dist/components/LpPagination.vue.js +1 -1
  172. package/dist/components/LpPaletteFacts.vue.js +2 -2
  173. package/dist/components/LpPaletteHeader.vue.js +2 -2
  174. package/dist/components/LpPaletteStats.vue.js +2 -2
  175. package/dist/components/LpPaletteTheme.vue.js +1 -1
  176. package/dist/components/LpPasswordInput.vue.js +1 -1
  177. package/dist/components/LpPhoneInput.vue.js +1 -1
  178. package/dist/components/LpPie.vue.js +1 -1
  179. package/dist/components/LpPipeline.vue.js +1 -1
  180. package/dist/components/LpProgress.vue.js +1 -1
  181. package/dist/components/LpQuota.vue.js +1 -1
  182. package/dist/components/LpRadioGroup.vue.js +1 -1
  183. package/dist/components/LpRangeCalendar.vue.js +1 -1
  184. package/dist/components/LpRelativeTime.vue.js +1 -1
  185. package/dist/components/LpRepeater.vue.js +1 -1
  186. package/dist/components/LpRollingText.vue.d.ts +2 -2
  187. package/dist/components/LpRollingText.vue.js +1 -1
  188. package/dist/components/LpScramble.vue.js +1 -1
  189. package/dist/components/LpSecretField.vue.js +1 -1
  190. package/dist/components/LpSection.vue.js +1 -1
  191. package/dist/components/LpSegmented.vue.js +1 -1
  192. package/dist/components/LpSelect.vue.js +1 -1
  193. package/dist/components/LpShift.vue.d.ts +20 -0
  194. package/dist/components/LpShift.vue.js +1 -1
  195. package/dist/components/LpShortcutsDialog.vue.js +1 -1
  196. package/dist/components/LpSidebar.vue.d.ts +74 -23
  197. package/dist/components/LpSidebar.vue.js +1 -1
  198. package/dist/components/LpSidebarNav.vue.d.ts +31 -3
  199. package/dist/components/LpSidebarNav.vue.js +1 -1
  200. package/dist/components/LpSidebarRow.vue.d.ts +49 -0
  201. package/dist/components/LpSidebarRow.vue.js +4 -0
  202. package/dist/components/LpStat.vue.d.ts +11 -0
  203. package/dist/components/LpStat.vue.js +1 -1
  204. package/dist/components/LpStatus.vue.js +1 -1
  205. package/dist/components/LpStepMark.vue.js +1 -1
  206. package/dist/components/LpStepper.vue.js +1 -1
  207. package/dist/components/LpSwap.vue.js +1 -1
  208. package/dist/components/LpSwitch.vue.js +1 -1
  209. package/dist/components/LpTabFace.vue.d.ts +14 -0
  210. package/dist/components/LpTabFace.vue.js +4 -0
  211. package/dist/components/LpTable.vue.js +11 -11
  212. package/dist/components/LpTableFilter.vue.js +1 -1
  213. package/dist/components/LpTabs.vue.d.ts +4 -4
  214. package/dist/components/LpTabs.vue.js +18 -72
  215. package/dist/components/LpTagsInput.vue.js +1 -1
  216. package/dist/components/LpTextarea.vue.d.ts +19 -1
  217. package/dist/components/LpTextarea.vue.js +1 -1
  218. package/dist/components/LpThemeProvider.vue.js +1 -1
  219. package/dist/components/LpThemeStudio.vue.d.ts +2 -2
  220. package/dist/components/LpThemeStudio.vue.js +1 -1
  221. package/dist/components/LpThemeStudioSection.vue.d.ts +4 -1
  222. package/dist/components/LpThemeStudioSection.vue.js +1 -1
  223. package/dist/components/LpThemeSwitcher.vue.js +1 -1
  224. package/dist/components/LpTimeField.vue.js +1 -1
  225. package/dist/components/LpToaster.vue.js +1 -1
  226. package/dist/components/LpTopologyCanvas.vue.js +1 -1
  227. package/dist/components/LpTour.vue.js +1 -1
  228. package/dist/components/LpTruncate.vue.js +1 -1
  229. package/dist/components/LpUptimeBar.vue.js +1 -1
  230. package/dist/components/MenuTitle.vue.js +1 -1
  231. package/dist/components/OptionContent.vue.js +1 -1
  232. package/dist/components/PickerField.vue.js +1 -1
  233. package/dist/components/RevealToggle.vue.js +1 -1
  234. package/dist/components/TourCard.vue.js +1 -1
  235. package/dist/components/menuWhen.js +1 -1
  236. package/dist/components/rolling.d.ts +5 -0
  237. package/dist/components/rolling.js +23 -0
  238. package/dist/components/sidebar.d.ts +38 -0
  239. package/dist/components/sidebar.js +6 -1
  240. package/dist/components/tabs.d.ts +3 -0
  241. package/dist/components/tabs.js +6 -0
  242. package/dist/icons-all.js +1 -1
  243. package/dist/index.d.ts +1 -0
  244. package/dist/index.js +154 -153
  245. package/package.json +1 -1
  246. package/src/component-names.ts +1 -0
  247. package/src/components/LpAppShell.vue +75 -7
  248. package/src/components/LpBottomNav.vue +84 -0
  249. package/src/components/LpColorPicker.vue +32 -1
  250. package/src/components/LpEmptyState.vue +4 -1
  251. package/src/components/LpKeys.vue +10 -1
  252. package/src/components/LpNumberFlow.vue +4 -2
  253. package/src/components/LpRollingText.vue +27 -2
  254. package/src/components/LpSegmented.vue +3 -1
  255. package/src/components/LpShift.vue +189 -2
  256. package/src/components/LpSidebar.vue +304 -18
  257. package/src/components/LpSidebarNav.vue +211 -78
  258. package/src/components/LpSidebarRow.vue +242 -0
  259. package/src/components/LpStat.vue +7 -1
  260. package/src/components/LpTabFace.vue +52 -0
  261. package/src/components/LpTabs.vue +6 -41
  262. package/src/components/LpTextarea.vue +34 -4
  263. package/src/components/LpThemeStudio.vue +91 -55
  264. package/src/components/LpThemeStudioSection.vue +15 -7
  265. package/src/components/rolling.ts +28 -0
  266. package/src/components/sidebar.ts +41 -0
  267. package/src/components/tabs.ts +9 -0
  268. package/src/index.ts +1 -0
  269. package/src/kit-icons.ts +1 -1
  270. package/dist/assets/LpTabs-DT0XPTc2.css +0 -18
  271. package/dist/chunks/LpRollingText-DiL717LK.js +0 -51
  272. package/dist/chunks/LpShift-DXNsauQZ.js +0 -40
  273. package/dist/chunks/LpSidebar-Bk7b-K4l.js +0 -256
  274. package/dist/chunks/LpSidebarNav-BR2AW3KT.js +0 -216
  275. package/dist/chunks/LpThemeProvider-DcbfOxsU.js +0 -69
  276. package/dist/chunks/LpThemeStudioSection-BwhqYDLf.js +0 -20
@@ -13,11 +13,14 @@
13
13
  * auto-closes the drawer. With `responsive` off the component renders exactly
14
14
  * the static <nav> it always has — existing call sites are unaffected.
15
15
  */
16
- import { computed, ref, useId } from "vue"
16
+ import { computed, nextTick, ref, useId } from "vue"
17
+ import { parseCombo, useHotkeys } from "../composables/useHotkeys"
17
18
  import { usePersisted } from "../composables/usePersisted"
18
19
  import { useLabels } from "../composables/useLpConfig"
19
20
  import LpDrawer from "./LpDrawer.vue"
21
+ import LpIcon from "./LpIcon.vue"
20
22
  import LpInput from "./LpInput.vue"
23
+ import LpTooltip from "./LpTooltip.vue"
21
24
  import LpSidebarNav from "./LpSidebarNav.vue"
22
25
  import type { SidebarItem, SidebarSection } from "./sidebar"
23
26
 
@@ -50,7 +53,17 @@ const props = withDefaults(
50
53
  /** Placeholder for that field (defaults to the `search` label). */
51
54
  searchPlaceholder?: string
52
55
  /** Text overrides: `nav` names the landmark, `search` the filter field. */
53
- labels?: Partial<{ nav: string; search: string }>
56
+ labels?: Partial<{
57
+ nav: string
58
+ search: string
59
+ pinned: string
60
+ pin: string
61
+ unpin: string
62
+ expand: string
63
+ compact: string
64
+ expandRail: string
65
+ resize: string
66
+ }>
54
67
  /** The query, when the app wants to own it (v-model:search). */
55
68
  search?: string
56
69
  /** Show a skeleton placeholder instead of the items. */
@@ -126,6 +139,44 @@ const props = withDefaults(
126
139
  * see LpSidebarNav for why a tall nav keeps it pinned.
127
140
  */
128
141
  hoverFollow?: boolean
142
+ /**
143
+ * Icons only (v-model:compact): each row's name, count and the pages under
144
+ * it move into a card beside the icon. With `resizable` the person decides,
145
+ * and the choice is remembered under `persist`.
146
+ */
147
+ compact?: boolean
148
+ /**
149
+ * The person sizes the rail: drag its edge (double-click resets), drag it
150
+ * narrow enough and it folds to icons, and a button and Ctrl+B fold it
151
+ * outright. One mechanism, not two: a narrow rail that only truncates its
152
+ * labels is the worst of both, so below a point it becomes the icon rail.
153
+ */
154
+ resizable?: boolean
155
+ /** Rail width bounds while resizing, in px. */
156
+ minWidth?: number
157
+ maxWidth?: number
158
+ /** The key that folds the rail when `resizable`. False turns it off. */
159
+ compactHotkey?: string | false
160
+ /**
161
+ * Rows offer "Pin to top" in their menu, and pinned pages lead the nav
162
+ * (v-model:pinned, ids; remembered under `persist` when unbound).
163
+ */
164
+ pinnable?: boolean
165
+ pinned?: string[]
166
+ /** How long the pointer rests on a row with a `preview` before its card opens, in ms. */
167
+ previewDelay?: number
168
+ /**
169
+ * Mark the app as not production: a coloured band along the top of the rail
170
+ * with the label hanging from it ("staging", "local"). It is there so an
171
+ * edit on the test copy is not mistaken for one on the real thing; leave it
172
+ * unset in production.
173
+ */
174
+ environment?: string | { label: string; tone?: "warning" | "danger" | "action" | "brand" }
175
+ /**
176
+ * The app's hint system (createHintSystem). Rows that name a `hintPage`
177
+ * then mark unread news on it with a dot, with nothing for the app to wire.
178
+ */
179
+ hints?: { unreadNews: (page?: string) => readonly unknown[] }
129
180
  }>(),
130
181
  {
131
182
  skeletonRows: 6,
@@ -136,6 +187,11 @@ const props = withDefaults(
136
187
  variant: "rail",
137
188
  autoCollapseAfter: 14,
138
189
  hoverFollow: false,
190
+ compact: undefined,
191
+ minWidth: 180,
192
+ maxWidth: 420,
193
+ compactHotkey: "Ctrl+B",
194
+ previewDelay: 900,
139
195
  },
140
196
  )
141
197
 
@@ -145,15 +201,47 @@ const emit = defineEmits<{
145
201
  (e: "update:collapsed", keys: string[]): void
146
202
  (e: "select", item: SidebarItem): void
147
203
  (e: "update:search", value: string): void
204
+ (e: "update:compact", value: boolean): void
205
+ (e: "update:pinned", ids: string[]): void
148
206
  }>()
149
207
 
150
- const text = useLabels("sidebar", { nav: "Sidebar", search: "Search" }, () => props.labels)
208
+ defineSlots<{
209
+ /** The brand; `compact` says the rail is down to icons. */
210
+ header?: (props: { compact?: boolean }) => unknown
211
+ actions?: (props: { compact?: boolean }) => unknown
212
+ footer?: (props: { compact?: boolean }) => unknown
213
+ item?: (props: { item: SidebarItem; active: boolean }) => unknown
214
+ }>()
215
+
216
+ const text = useLabels(
217
+ "sidebar",
218
+ {
219
+ nav: "Sidebar",
220
+ search: "Search",
221
+ pinned: "Pinned",
222
+ pin: "Pin to top",
223
+ unpin: "Unpin",
224
+ expand: "Show the pages under it",
225
+ compact: "Collapse the sidebar",
226
+ expandRail: "Expand the sidebar",
227
+ resize: "Drag to resize, double-click to reset",
228
+ },
229
+ () => props.labels,
230
+ )
151
231
  const placeholder = computed(() => props.searchPlaceholder ?? text.value.search)
152
232
 
233
+ function withNews(item: SidebarItem): SidebarItem {
234
+ const children = item.children?.map(withNews)
235
+ const pages = item.hintPage === undefined ? [] : Array.isArray(item.hintPage) ? item.hintPage : [item.hintPage]
236
+ const fresh = !!props.hints && pages.some((p) => props.hints!.unreadNews(p).length > 0)
237
+ return fresh || children ? { ...item, children, dot: item.dot || fresh } : item
238
+ }
239
+
153
240
  // Normalise both inputs to a single section list.
154
- const allGroups = computed<SidebarSection[]>(() =>
155
- props.sections ?? (props.items ? [{ items: props.items }] : []),
156
- )
241
+ const allGroups = computed<SidebarSection[]>(() => {
242
+ const groups = props.sections ?? (props.items ? [{ items: props.items }] : [])
243
+ return props.hints ? groups.map((g) => ({ ...g, items: g.items.map(withNews) })) : groups
244
+ })
157
245
 
158
246
  /*
159
247
  * The filter query. Controlled through v-model:search when the app wants it —
@@ -179,6 +267,13 @@ function matches(item: SidebarItem, needle: string): boolean {
179
267
  return (item.keywords ?? []).some((k) => normalise(k).includes(needle))
180
268
  }
181
269
 
270
+ /** The item if it matches, with every page under it; else only the pages under it that match. */
271
+ function narrowed(item: SidebarItem, needle: string): SidebarItem | null {
272
+ if (matches(item, needle)) return item
273
+ const children = (item.children ?? []).filter((c) => matches(c, needle))
274
+ return children.length ? { ...item, children } : null
275
+ }
276
+
182
277
  const groups = computed<SidebarSection[]>(() => {
183
278
  const needle = normalise(query.value.trim())
184
279
  if (!needle) return allGroups.value
@@ -186,7 +281,10 @@ const groups = computed<SidebarSection[]>(() => {
186
281
  // under it reads as a section that failed to load rather than one that
187
282
  // matched nothing.
188
283
  return allGroups.value
189
- .map((section) => ({ ...section, items: section.items.filter((i) => matches(i, needle)) }))
284
+ .map((section) => ({
285
+ ...section,
286
+ items: section.items.map((i) => narrowed(i, needle)).filter((i): i is SidebarItem => i !== null),
287
+ }))
190
288
  .filter((section) => section.items.length > 0)
191
289
  })
192
290
 
@@ -226,7 +324,7 @@ const autoCollapsed = computed<string[]>(() => {
226
324
  const limit = props.autoCollapseAfter
227
325
  if (!limit || navLength.value <= limit) return []
228
326
  return groups.value
229
- .filter((g) => g.collapsible && !g.items.some(itemActive))
327
+ .filter((g) => g.collapsible && !g.items.some((i) => itemActive(i) || !!i.children?.some(itemActive)))
230
328
  .map(keyOf)
231
329
  .filter(Boolean)
232
330
  })
@@ -246,6 +344,117 @@ function toggleSection(key: string, collapsed: boolean) {
246
344
  emit("update:collapsed", next)
247
345
  }
248
346
 
347
+ /*
348
+ * Compact and width. Bound, the app owns them; unbound, the sidebar keeps them,
349
+ * across visits under `persist`.
350
+ */
351
+ const ownCompact = usePersisted<boolean>(() => props.persist && `lp-sidebar:${props.persist}:compact`, false)
352
+ const isCompact = computed(() => props.compact ?? ownCompact.value)
353
+ function setCompact(value: boolean) {
354
+ ownCompact.value = value
355
+ emit("update:compact", value)
356
+ }
357
+
358
+ const ENV_TONE = {
359
+ warning: "bg-accent text-ink-inverse",
360
+ danger: "bg-danger text-white",
361
+ action: "bg-action text-ink-inverse",
362
+ brand: "bg-brand text-ink-inverse",
363
+ } as const
364
+ const env = computed(() => {
365
+ const e = props.environment
366
+ if (!e) return null
367
+ const { label, tone = "warning" } = typeof e === "string" ? { label: e } : e
368
+ return { label, tone: ENV_TONE[tone] }
369
+ })
370
+
371
+ const DEFAULT_WIDTH = 240
372
+ const COMPACT_WIDTH = 64
373
+ const ownWidth = usePersisted<number>(() => props.resizable && props.persist && `lp-sidebar:${props.persist}:width`, DEFAULT_WIDTH)
374
+ const dragging = ref(false)
375
+
376
+ const railWidth = computed(() => {
377
+ if (isCompact.value) return `${COMPACT_WIDTH}px`
378
+ if (props.resizable) return `${ownWidth.value}px`
379
+ return props.width
380
+ })
381
+
382
+ /*
383
+ * Dragging past the narrowest width folds the rail to icons, and dragging a
384
+ * folded rail out unfolds it: below a point labels only truncate to nothing
385
+ * useful, and the icon rail is the honest form of "narrow".
386
+ */
387
+ const FOLD_AT = 132
388
+ function startResize(event: PointerEvent) {
389
+ if (event.button !== 0) return
390
+ const handle = event.currentTarget as HTMLElement
391
+ handle.setPointerCapture(event.pointerId)
392
+ const from = event.clientX
393
+ const start = isCompact.value ? COMPACT_WIDTH : ownWidth.value
394
+ dragging.value = true
395
+ const move = (e: PointerEvent) => {
396
+ const wanted = start + (e.clientX - from)
397
+ if (wanted < FOLD_AT) {
398
+ // Folded by dragging: the width it unfolds to is the one it had, not
399
+ // the narrowest the drag passed through on its way down.
400
+ if (!isCompact.value) setCompact(true)
401
+ if (start !== COMPACT_WIDTH) ownWidth.value = start
402
+ return
403
+ }
404
+ if (isCompact.value) setCompact(false)
405
+ ownWidth.value = Math.round(Math.min(props.maxWidth, Math.max(props.minWidth, wanted)))
406
+ }
407
+ const stop = () => {
408
+ dragging.value = false
409
+ handle.removeEventListener("pointermove", move)
410
+ handle.removeEventListener("pointerup", stop)
411
+ handle.removeEventListener("pointercancel", stop)
412
+ }
413
+ handle.addEventListener("pointermove", move)
414
+ handle.addEventListener("pointerup", stop)
415
+ handle.addEventListener("pointercancel", stop)
416
+ }
417
+ const railEl = ref<HTMLElement | null>(null)
418
+ async function searchFromCompact() {
419
+ setCompact(false)
420
+ await nextTick()
421
+ railEl.value?.querySelector<HTMLInputElement>("input")?.focus()
422
+ }
423
+
424
+ function resetWidth() {
425
+ ownWidth.value = DEFAULT_WIDTH
426
+ setCompact(false)
427
+ }
428
+
429
+ useHotkeys(() =>
430
+ props.resizable && props.compactHotkey
431
+ ? [
432
+ {
433
+ ...parseCombo(props.compactHotkey),
434
+ help: { group: text.value.nav, label: text.value.compact, combo: props.compactHotkey },
435
+ handler: () => setCompact(!isCompact.value),
436
+ },
437
+ ]
438
+ : [],
439
+ )
440
+
441
+ /* Pinned pages, by id; unbound they are kept under `persist`. */
442
+ const ownPinned = usePersisted<string[]>(() => props.persist && `lp-sidebar:${props.persist}:pinned`, [], {
443
+ validate: (value): value is string[] => Array.isArray(value) && value.every((k) => typeof k === "string"),
444
+ })
445
+ const pinnedIds = computed(() => props.pinned ?? ownPinned.value)
446
+ const everyItem = computed(() => allGroups.value.flatMap((g) => g.items.flatMap((i) => [i, ...(i.children ?? [])])))
447
+ const pinnedItems = computed<SidebarItem[]>(() =>
448
+ props.pinnable
449
+ ? pinnedIds.value.map((id) => everyItem.value.find((i) => i.id === id)).filter((i): i is SidebarItem => !!i)
450
+ : [],
451
+ )
452
+ function togglePin(id: string) {
453
+ const next = pinnedIds.value.includes(id) ? pinnedIds.value.filter((k) => k !== id) : [...pinnedIds.value, id]
454
+ ownPinned.value = next
455
+ emit("update:pinned", next)
456
+ }
457
+
249
458
  function activate(item: SidebarItem) {
250
459
  if (item.disabled) return
251
460
  emit("update:modelValue", item.id)
@@ -291,12 +500,28 @@ defineOptions({ inheritAttrs: false })
291
500
  <template>
292
501
  <!-- Desktop / always-on rail -->
293
502
  <nav
294
- class="h-full flex-col gap-1 p-3"
295
- :class="[railClass, chromeClass, width ? '' : 'w-60']"
296
- :style="width ? { width } : undefined"
503
+ ref="railEl"
504
+ class="relative h-full shrink-0 flex-col gap-1"
505
+ :class="[
506
+ railClass,
507
+ chromeClass,
508
+ isCompact ? 'px-2 py-3' : 'p-3',
509
+ railWidth ? '' : 'w-60',
510
+ dragging ? '' : 'transition-[width] duration-(--duration-medium) ease-[var(--ease-emphasized)] motion-reduce:transition-none',
511
+ ]"
512
+ :style="railWidth ? { width: railWidth } : undefined"
513
+ :data-compact="isCompact || undefined"
297
514
  :aria-label="text.nav"
298
515
  v-bind="$attrs"
299
516
  >
517
+ <div v-if="env" class="pointer-events-none absolute inset-x-0 top-0 z-20 h-[3px]" :class="env.tone" />
518
+ <span
519
+ v-if="env && !isCompact"
520
+ class="pointer-events-none absolute left-1/2 top-0 z-20 -translate-x-1/2 rounded-b-small px-2 pb-0.5 text-[10px] font-semibold uppercase tracking-wide"
521
+ :class="env.tone"
522
+ >
523
+ {{ env.label }}
524
+ </span>
300
525
  <!-- Rail: edge-to-edge (negative margins cancel the p-3) and h-16 to match
301
526
  the app header, so its bottom hairline continues the header's border-b.
302
527
  Panel: kept inside the padding — bleeding to the edge would cut across
@@ -305,18 +530,33 @@ defineOptions({ inheritAttrs: false })
305
530
  v-if="$slots.header"
306
531
  class="mb-3 flex shrink-0 items-center"
307
532
  :class="[
308
- variant === 'panel' ? 'pb-3' : '-mx-3 -mt-3 h-16 px-3',
533
+ variant === 'panel' ? 'pb-3' : isCompact ? '-mx-2 -mt-3 h-16 overflow-hidden' : '-mx-3 -mt-3 h-16 px-3',
309
534
  divider ? 'border-b border-line' : '',
310
535
  ]"
311
536
  >
312
- <slot name="header" />
537
+ <div v-if="isCompact" class="flex w-16 shrink-0 justify-center">
538
+ <slot name="header" :compact="true" />
539
+ </div>
540
+ <slot v-else name="header" :compact="false" />
313
541
  </div>
314
542
 
315
543
  <!-- The filter sits between the brand and the nav: it belongs to the list,
316
544
  not to the header, and a person reaching for it is already looking at
317
545
  the items. -->
546
+ <!-- Folded, the filter is a button: a field forty pixels wide holds no
547
+ query, so the rail opens to give it room and puts the caret in it. -->
548
+ <LpTooltip v-if="searchable && isCompact" :content="placeholder" side="right">
549
+ <button
550
+ type="button"
551
+ class="mb-2 ml-1 grid size-10 shrink-0 place-items-center rounded-control text-muted outline-none transition-colors hover:bg-ink/[0.05] hover:text-ink focus-visible:ring-2 focus-visible:ring-ring"
552
+ :aria-label="placeholder"
553
+ @click="searchFromCompact"
554
+ >
555
+ <LpIcon name="lucide:search" :size="17" />
556
+ </button>
557
+ </LpTooltip>
318
558
  <LpInput
319
- v-if="searchable"
559
+ v-if="searchable && !isCompact"
320
560
  v-model="query"
321
561
  size="sm"
322
562
  icon="lucide:search"
@@ -328,6 +568,11 @@ defineOptions({ inheritAttrs: false })
328
568
  <LpSidebarNav
329
569
  :groups="groups"
330
570
  :pill-id="railPillId"
571
+ :compact="isCompact"
572
+ :pinnable="pinnable"
573
+ :pinned="pinnedItems"
574
+ :preview-delay="previewDelay"
575
+ :labels="text"
331
576
  :item-active="itemActive"
332
577
  :loading="loading"
333
578
  :skeleton-rows="skeletonRows"
@@ -336,21 +581,57 @@ defineOptions({ inheritAttrs: false })
336
581
  :hover-follow="hoverFollow"
337
582
  @activate="activate"
338
583
  @toggle-section="toggleSection"
584
+ @toggle-pin="togglePin"
339
585
  >
340
586
  <template v-if="$slots.item" #item="slotProps">
341
587
  <slot name="item" v-bind="slotProps" />
342
588
  </template>
343
589
  </LpSidebarNav>
344
590
 
591
+ <LpTooltip v-if="resizable" :content="isCompact ? text.expandRail : text.compact" side="right">
592
+ <button
593
+ type="button"
594
+ class="mt-1 flex h-8 shrink-0 items-center gap-2 rounded-control px-3 text-xs text-muted outline-none transition-colors hover:bg-ink/[0.05] hover:text-ink focus-visible:ring-2 focus-visible:ring-ring"
595
+ :class="isCompact ? 'ml-1 w-10 justify-center px-0' : ''"
596
+ :aria-label="isCompact ? text.expandRail : text.compact"
597
+ :aria-pressed="isCompact"
598
+ @click="setCompact(!isCompact)"
599
+ >
600
+ <LpIcon :name="isCompact ? 'lucide:panel-left-open' : 'lucide:panel-left-close'" :size="16" class="shrink-0" />
601
+ <span v-if="!isCompact" class="truncate">{{ text.compact }}</span>
602
+ </button>
603
+ </LpTooltip>
604
+
345
605
  <!-- Actions (search, "new …") sit just above the footer, pinned to the
346
606
  bottom of the rail and outside the scroll region — not trailing the
347
607
  nav list. -->
348
- <div v-if="$slots.actions" class="mt-2 flex shrink-0 flex-col gap-2">
349
- <slot name="actions" />
608
+ <div v-if="$slots.actions" class="mt-2 flex shrink-0 flex-col gap-2" :class="isCompact ? 'w-12 items-center' : ''">
609
+ <slot name="actions" :compact="isCompact" />
350
610
  </div>
351
611
 
352
- <div v-if="$slots.footer" class="mt-2 shrink-0 border-t border-line pt-3">
353
- <slot name="footer" />
612
+ <div v-if="$slots.footer" class="mt-2 shrink-0 overflow-hidden border-t border-line pt-3">
613
+ <div v-if="isCompact" class="flex w-12 justify-center">
614
+ <slot name="footer" :compact="true" />
615
+ </div>
616
+ <slot v-else name="footer" :compact="false" />
617
+ </div>
618
+
619
+ <!-- The edge itself is the handle: a few pixels either side of the
620
+ hairline, a brand line while it is held. -->
621
+ <div
622
+ v-if="resizable && variant === 'rail'"
623
+ role="separator"
624
+ aria-orientation="vertical"
625
+ :aria-label="text.resize"
626
+ :title="text.resize"
627
+ class="group/resize absolute inset-y-0 -right-1.5 z-10 w-3 cursor-col-resize touch-none"
628
+ @pointerdown="startResize"
629
+ @dblclick="resetWidth"
630
+ >
631
+ <span
632
+ class="absolute inset-y-0 left-1/2 w-0.5 -translate-x-1/2 bg-brand opacity-0 transition-opacity duration-(--duration-fast) group-hover/resize:opacity-60"
633
+ :class="dragging ? '!opacity-100' : ''"
634
+ />
354
635
  </div>
355
636
  </nav>
356
637
 
@@ -389,6 +670,10 @@ defineOptions({ inheritAttrs: false })
389
670
  <LpSidebarNav
390
671
  :groups="groups"
391
672
  :pill-id="drawerPillId"
673
+ :pinnable="pinnable"
674
+ :pinned="pinnedItems"
675
+ :preview-delay="previewDelay"
676
+ :labels="text"
392
677
  :item-active="itemActive"
393
678
  :loading="loading"
394
679
  :skeleton-rows="skeletonRows"
@@ -397,6 +682,7 @@ defineOptions({ inheritAttrs: false })
397
682
  :hover-follow="hoverFollow"
398
683
  @activate="activate"
399
684
  @toggle-section="toggleSection"
685
+ @toggle-pin="togglePin"
400
686
  >
401
687
  <template v-if="$slots.item" #item="slotProps">
402
688
  <slot name="item" v-bind="slotProps" />