@leavepulse/ui 0.69.0 → 0.70.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 (640) hide show
  1. package/README.md +49 -0
  2. package/dist/assets/LoaderMark-DxBV2iDJ.css +43 -0
  3. package/dist/assets/LpActivityLine-B3EwNQEB.css +33 -0
  4. package/dist/assets/{LpCommandPalette-DxyjhYn_.css → LpCommandPalette-u-zOxKWa.css} +21 -31
  5. package/dist/assets/LpDock-Cbh0wQUv.css +17 -0
  6. package/dist/assets/{LpDropzone-Qb8k7cg4.css → LpDropzone-Bb1vBTeU.css} +12 -17
  7. package/dist/assets/{LpImageEditor-CElPDzpF.css → LpImageEditor-XM5bAziW.css} +6 -6
  8. package/dist/assets/LpLogViewer-BDNW6P52.css +38 -0
  9. package/dist/assets/{LpPalettePreview-CJmAKgYW.css → LpPalettePreview-B9VKDrvA.css} +2 -7
  10. package/dist/assets/LpRepeater-C1Cw27hj.css +21 -0
  11. package/dist/assets/{LpRollingText-BGnE6q9j.css → LpRollingText-dyOXedGO.css} +7 -0
  12. package/dist/assets/LpShinyText-D69cBYDR.css +61 -0
  13. package/dist/assets/LpStatus-430OGTZY.css +17 -0
  14. package/dist/assets/LpStepMark-Drvx33Vg.css +10 -0
  15. package/dist/assets/{LpTable-BPERfJIk.css → LpTable-DHxEQ_-3.css} +19 -19
  16. package/dist/assets/LpTabs-BJ-nrJuI.css +18 -0
  17. package/dist/assets/LpTextReveal-DjI1MsDS.css +35 -0
  18. package/dist/assets/LpTypewriter-CXAm9Nca.css +27 -0
  19. package/dist/chunks/AttentionDot-DCBf4aWg.js +25 -0
  20. package/dist/chunks/{ContextMenuItems-B7XFHksm.js → ContextMenuItems-6kxEivBI.js} +11 -5
  21. package/dist/chunks/{DropzoneLinkField-CjkrpDqO.js → DropzoneLinkField-Bw8Flkhk.js} +2 -2
  22. package/dist/chunks/FieldWrapper-BiennROB.js +43 -0
  23. package/dist/chunks/{LayoutCanvas-DF9CovaK.js → LayoutCanvas-BsJIzhdd.js} +1 -1
  24. package/dist/chunks/{LayoutNode-D9bIFzk0.js → LayoutNode-DJVhkSGk.js} +6 -8
  25. package/dist/chunks/LegendSwatch-BhRjrtzv.js +18 -0
  26. package/dist/chunks/LoaderMark-C1dubiKn.js +85 -0
  27. package/dist/chunks/{LpActionBar-MPKMu3pz.js → LpActionBar-CzOFar5t.js} +14 -20
  28. package/dist/chunks/LpActivityLine-CJvzrNpj.js +95 -0
  29. package/dist/chunks/{LpAddressInput-DG0BTqdH.js → LpAddressInput-Chv_Xf8q.js} +7 -7
  30. package/dist/chunks/LpAlert-C5igj802.js +119 -0
  31. package/dist/chunks/{LpAppShell-DPh1756q.js → LpAppShell-BiWByLmt.js} +15 -16
  32. package/dist/chunks/{LpAutocomplete-Dgn6hw3p.js → LpAutocomplete-D92niDHE.js} +15 -32
  33. package/dist/chunks/{LpAvatar-Bs0Fb1lC.js → LpAvatar-CLPl-qOF.js} +18 -6
  34. package/dist/chunks/LpBadge-BBq1Er9T.js +126 -0
  35. package/dist/chunks/LpBreadcrumbs-JKEi_yFF.js +144 -0
  36. package/dist/chunks/{LpButton-DNR-YAq5.js → LpButton-CVxBfGjd.js} +12 -4
  37. package/dist/chunks/{LpCalendar-BLya39Fh.js → LpCalendar-pVL91-Pl.js} +1 -1
  38. package/dist/chunks/{LpCard-Bf71NXZq.js → LpCard-CqKLnEhl.js} +18 -8
  39. package/dist/chunks/{LpCheckbox-Da5oZPHo.js → LpCheckbox-DHc2bHDe.js} +9 -6
  40. package/dist/chunks/{LpCodeBlock-lLbmslfs.js → LpCodeBlock-BGsQhxw8.js} +24 -32
  41. package/dist/chunks/LpCodeDisplay-CbJMs-IK.js +189 -0
  42. package/dist/chunks/LpCollapse-CWS9M_lm.js +115 -0
  43. package/dist/chunks/{LpColorPicker-DtEfBAcK.js → LpColorPicker-B7HSIFmn.js} +11 -6
  44. package/dist/chunks/{LpConfirmDialog-D7s4jakB.js → LpConfirmDialog-CfGCux8m.js} +3 -3
  45. package/dist/chunks/{LpConfirmHost-DrYI5y1K.js → LpConfirmHost-exB7JmcO.js} +1 -1
  46. package/dist/chunks/{LpContextMenu-CRnjoqSt.js → LpContextMenu-Cj96ENDC.js} +16 -7
  47. package/dist/chunks/LpCopyButton-DzHjnFs0.js +133 -0
  48. package/dist/chunks/LpCountdown-BQnmB4gq.js +231 -0
  49. package/dist/chunks/LpDataList-CHNYQw7h.js +121 -0
  50. package/dist/chunks/LpDatePicker-ac1_6o5P.js +169 -0
  51. package/dist/chunks/LpDateRangePicker-B15gYrZJ.js +127 -0
  52. package/dist/chunks/{LpDisclosure-6AplYBub.js → LpDisclosure-DOarzlAG.js} +22 -11
  53. package/dist/chunks/{LpDrawer-Q4SOxM4s.js → LpDrawer-DGNKRsGq.js} +9 -4
  54. package/dist/chunks/{LpDropdownMenu-DWTt0ooM.js → LpDropdownMenu-R4aYVtVV.js} +14 -6
  55. package/dist/chunks/LpEditable-Ws3DNQHn.js +238 -0
  56. package/dist/chunks/{LpEmptyState-om1UnFjV.js → LpEmptyState-KTKipws2.js} +1 -1
  57. package/dist/chunks/{LpFieldNotice-CHuDeLjc.js → LpFieldNotice-CurbNuXI.js} +1 -1
  58. package/dist/chunks/{LpFileTree-CW24YsVX.js → LpFileTree-DDNg34tJ.js} +5 -3
  59. package/dist/chunks/{LpFileTreeNode-BXhTHaKW.js → LpFileTreeNode-DmPuYNZ_.js} +42 -55
  60. package/dist/chunks/{LpFormField-DPb47HEm.js → LpFormField-BWwgm1E4.js} +23 -9
  61. package/dist/chunks/LpFrame-BVQCQLDI.js +155 -0
  62. package/dist/chunks/LpGauge-C14Z9503.js +204 -0
  63. package/dist/chunks/LpGlowBorder-B8V-QzIl.js +40 -0
  64. package/dist/chunks/{LpHintExample-C1eKYdeL.js → LpHintExample-9Py0wc-L.js} +11 -34
  65. package/dist/chunks/{LpHintLayer-7UOdWQG3.js → LpHintLayer-HvwUA5Ec.js} +27 -14
  66. package/dist/chunks/{LpHints-BUtBp9-w.js → LpHints-DxbPKOzQ.js} +3 -3
  67. package/dist/chunks/LpHoverCard-spGxyw7T.js +130 -0
  68. package/dist/chunks/{LpIcon-6tSrZ3Zy.js → LpIcon-HJP5xMz4.js} +1 -1
  69. package/dist/chunks/LpIdenticon-BzdC_qz9.js +63 -0
  70. package/dist/chunks/{LpInfraNode-Ds_8SZgN.js → LpInfraNode-D64hywJI.js} +39 -25
  71. package/dist/chunks/{LpInput-CUyr6PIE.js → LpInput-CDuwODJG.js} +44 -18
  72. package/dist/chunks/{LpLightbox-B9J8rzsj.js → LpLightbox-XJ0LpTcZ.js} +69 -69
  73. package/dist/chunks/LpLoader-DjJEX8hL.js +92 -0
  74. package/dist/chunks/{LpLogViewer-4QFc-sVN.js → LpLogViewer-DKK4ySZl.js} +225 -129
  75. package/dist/chunks/LpMagnetic-CtXKLa2Y.js +62 -0
  76. package/dist/chunks/{LpMapPicker-BTbkFeSG.js → LpMapPicker-BtIl7NOM.js} +34 -31
  77. package/dist/chunks/LpMasonry--k0571qG.js +185 -0
  78. package/dist/chunks/{LpMediaGallery-CuPcscx3.js → LpMediaGallery-rmI1DjKN.js} +3 -3
  79. package/dist/chunks/{LpModal-hk1noDcr.js → LpModal-eBMt2Fqn.js} +8 -3
  80. package/dist/chunks/{LpModalNav-DQd2keZm.js → LpModalNav-DiyFCHiZ.js} +4 -4
  81. package/dist/chunks/{LpNotificationBell-X84PJIxD.js → LpNotificationBell-D-WhE5m2.js} +32 -48
  82. package/dist/chunks/LpNumberField-B9k-h2HE.js +140 -0
  83. package/dist/chunks/{LpNumberFlow-z4WPZcZu.js → LpNumberFlow-Cfyh033Q.js} +8 -28
  84. package/dist/chunks/{LpOtpInput-PbeNJ5In.js → LpOtpInput-CeBPsM7D.js} +2 -1
  85. package/dist/chunks/{LpPagination-Bx-VG4Ag.js → LpPagination-VNCX6pFC.js} +37 -6
  86. package/dist/chunks/{LpPalettePreview-CFav_7co.js → LpPalettePreview-BNB8T_MY.js} +1 -1
  87. package/dist/chunks/{LpPasswordInput-CbnXitAS.js → LpPasswordInput-GL2KOFK8.js} +26 -22
  88. package/dist/chunks/{LpPhoneInput-DP69HONS.js → LpPhoneInput-C60tx1tC.js} +12 -7
  89. package/dist/chunks/{LpPie-yLF9-aDR.js → LpPie-BgXZ3xmm.js} +159 -48
  90. package/dist/chunks/LpPipeline-B31h41Mu.js +329 -0
  91. package/dist/chunks/{LpPopover-DVnkHaOu.js → LpPopover-DmZ3wUtP.js} +13 -7
  92. package/dist/chunks/{LpProgress-CA86wxXu.js → LpProgress-CE-m5OpD.js} +23 -63
  93. package/dist/chunks/LpQuota-DaL8TgNe.js +162 -0
  94. package/dist/chunks/{LpRadioGroup-8S5hf8lE.js → LpRadioGroup-CGBr5nIp.js} +1 -1
  95. package/dist/chunks/{LpRangeCalendar-ByQi-WUz.js → LpRangeCalendar-c5qj7YcC.js} +1 -1
  96. package/dist/chunks/{LpRangeSlider-C1yF9-nP.js → LpRangeSlider-Dv6lNvHY.js} +6 -2
  97. package/dist/chunks/LpRelativeTime-yin9uQP7.js +73 -0
  98. package/dist/chunks/LpRepeater-D0S7jjwr.js +180 -0
  99. package/dist/chunks/LpRevealOnScroll-DcQjexLy.js +76 -0
  100. package/dist/chunks/{LpRollingText-DB7upf-5.js → LpRollingText-DiL717LK.js} +4 -3
  101. package/dist/chunks/LpScramble-TDO5Kdou.js +85 -0
  102. package/dist/chunks/LpSecretField-CfWyHv9m.js +316 -0
  103. package/dist/chunks/{LpSection-BmRXe6ZP.js → LpSection-BW4xJ-Li.js} +1 -1
  104. package/dist/chunks/{LpSegmented-CW3bFHM4.js → LpSegmented-BO99Sr4m.js} +11 -14
  105. package/dist/chunks/{LpSelect-BCyDYoih.js → LpSelect-C_8cJtj6.js} +91 -111
  106. package/dist/chunks/LpShaderBackdrop-Bote0iuy.js +332 -0
  107. package/dist/chunks/LpShinyText-DX2ajtWq.js +48 -0
  108. package/dist/chunks/{LpSidebar-DfIiS-lB.js → LpSidebar-CZRXtvem.js} +5 -3
  109. package/dist/chunks/{LpSidebarNav-C5FDNI0t.js → LpSidebarNav-DBg1U1oW.js} +3 -3
  110. package/dist/chunks/{LpSlider-Cuzmrd7p.js → LpSlider-DuoRpOrH.js} +6 -2
  111. package/dist/chunks/{LpSparkline-DXT4KrSi.js → LpSparkline-CExIRDb3.js} +32 -27
  112. package/dist/chunks/LpSpotlight-4F3NeUMY.js +41 -0
  113. package/dist/chunks/{LpStat-iBMF5QNk.js → LpStat-DFKlPJgy.js} +38 -35
  114. package/dist/chunks/LpStatus-BsGLrpor.js +86 -0
  115. package/dist/chunks/LpStepMark-TrzOioa9.js +101 -0
  116. package/dist/chunks/LpStepper-BbnS5jUr.js +76 -0
  117. package/dist/chunks/{LpSwap-D82jiecV.js → LpSwap-DzE6M3Mg.js} +1 -1
  118. package/dist/chunks/LpSwitch-DrzKrZZV.js +112 -0
  119. package/dist/chunks/{LpTableFilter-CuIbgdW0.js → LpTableFilter-DyvHGbOk.js} +3 -2
  120. package/dist/chunks/{LpTableOfContents-C_4VBktT.js → LpTableOfContents-rYvo8z5T.js} +34 -21
  121. package/dist/chunks/{LpTagsInput-DiXrpYeE.js → LpTagsInput-DZg80W-B.js} +68 -71
  122. package/dist/chunks/LpTextReveal-CtAnOUkp.js +140 -0
  123. package/dist/chunks/{LpTextarea-xoQd5Lnp.js → LpTextarea-DiWjeVoJ.js} +12 -11
  124. package/dist/chunks/{LpThemeProvider-CQ2jC9TA.js → LpThemeProvider-DcbfOxsU.js} +1 -1
  125. package/dist/chunks/LpThemeStudio-DxVZMtzN.js +416 -0
  126. package/dist/chunks/LpThemeStudioSection-BwhqYDLf.js +20 -0
  127. package/dist/chunks/LpThemeSwitcher-CadVBTBn.js +278 -0
  128. package/dist/chunks/{LpTimeField-MFgAsNc5.js → LpTimeField-BFQVf_PW.js} +13 -5
  129. package/dist/chunks/{LpToaster-C4zE9zB7.js → LpToaster-Wv9ksj4q.js} +49 -82
  130. package/dist/chunks/{LpTooltip-suFCM34F.js → LpTooltip-Cz8SQwRt.js} +8 -3
  131. package/dist/chunks/{LpTopologyCanvas-6ozNrQKh.js → LpTopologyCanvas-C17A1XCb.js} +1 -1
  132. package/dist/chunks/{LpTour-BUp3Jt2e.js → LpTour-CY2bFXge.js} +24 -18
  133. package/dist/chunks/LpTruncate-D_5Pfv5B.js +112 -0
  134. package/dist/chunks/LpTypewriter-BCL_a6wE.js +159 -0
  135. package/dist/chunks/{LpUptimeBar-B6kHw4Cj.js → LpUptimeBar-Tew1Ykx4.js} +10 -9
  136. package/dist/chunks/{LpVideoBackdrop-qWRYBOTQ.js → LpVideoBackdrop-DS1wGv-X.js} +7 -8
  137. package/dist/chunks/{MenuTitle-obgek0B7.js → MenuTitle-BjQZX8tQ.js} +1 -1
  138. package/dist/chunks/OptionContent-CmYUUeWj.js +40 -0
  139. package/dist/chunks/PickerField-DoHv0WMH.js +125 -0
  140. package/dist/chunks/RevealToggle-C-KzaQGJ.js +65 -0
  141. package/dist/chunks/StepConnector-37OgEOXA.js +41 -0
  142. package/dist/chunks/TourCard-BJ8i7dk0.js +123 -0
  143. package/dist/chunks/backdrop-Dkf2vM81.js +59 -0
  144. package/dist/chunks/{icons-DVhZ_plB.js → icons-4IywzkHk.js} +1 -1
  145. package/dist/chunks/{useTheme-2qHG8NEU.js → useTheme-BOV_-AiY.js} +9 -65
  146. package/dist/component-names.d.ts +1 -1
  147. package/dist/components/AttentionDot.vue.d.ts +9 -0
  148. package/dist/components/AttentionDot.vue.js +4 -0
  149. package/dist/components/ContextMenuItems.vue.js +1 -1
  150. package/dist/components/DropzoneLinkField.vue.js +1 -1
  151. package/dist/components/FieldWrapper.vue.d.ts +25 -0
  152. package/dist/components/FieldWrapper.vue.js +4 -0
  153. package/dist/components/LayoutCanvas.vue.js +1 -1
  154. package/dist/components/LayoutNode.vue.d.ts +4 -4
  155. package/dist/components/LayoutNode.vue.js +1 -1
  156. package/dist/components/LegendSwatch.vue.d.ts +6 -0
  157. package/dist/components/LegendSwatch.vue.js +4 -0
  158. package/dist/components/LoaderMark.vue.d.ts +12 -0
  159. package/dist/components/LoaderMark.vue.js +4 -0
  160. package/dist/components/LpActionBar.vue.js +1 -1
  161. package/dist/components/LpActivityLine.vue.d.ts +58 -0
  162. package/dist/components/LpActivityLine.vue.js +4 -0
  163. package/dist/components/LpAddressInput.vue.js +1 -1
  164. package/dist/components/LpAlert.vue.d.ts +2 -2
  165. package/dist/components/LpAlert.vue.js +1 -1
  166. package/dist/components/LpAppShell.vue.d.ts +8 -7
  167. package/dist/components/LpAppShell.vue.js +1 -1
  168. package/dist/components/LpAutocomplete.vue.js +1 -1
  169. package/dist/components/LpAvatar.vue.d.ts +16 -0
  170. package/dist/components/LpAvatar.vue.js +1 -1
  171. package/dist/components/LpBadge.vue.d.ts +19 -5
  172. package/dist/components/LpBadge.vue.js +1 -1
  173. package/dist/components/LpBreadcrumbs.vue.js +1 -1
  174. package/dist/components/LpButton.vue.d.ts +2 -2
  175. package/dist/components/LpButton.vue.js +1 -1
  176. package/dist/components/LpCalendar.vue.js +1 -1
  177. package/dist/components/LpCard.vue.d.ts +24 -0
  178. package/dist/components/LpCard.vue.js +1 -1
  179. package/dist/components/LpChart.vue.js +131 -160
  180. package/dist/components/LpCheckbox.vue.d.ts +2 -2
  181. package/dist/components/LpCheckbox.vue.js +1 -1
  182. package/dist/components/LpCodeBlock.vue.js +1 -1
  183. package/dist/components/LpCodeDisplay.vue.d.ts +89 -0
  184. package/dist/components/LpCodeDisplay.vue.js +4 -0
  185. package/dist/components/LpCollapse.vue.d.ts +58 -0
  186. package/dist/components/LpCollapse.vue.js +4 -0
  187. package/dist/components/LpColorPicker.vue.d.ts +2 -2
  188. package/dist/components/LpColorPicker.vue.js +1 -1
  189. package/dist/components/LpCommandPalette.vue.js +34 -23
  190. package/dist/components/LpConfirmDialog.vue.js +1 -1
  191. package/dist/components/LpConfirmHost.vue.js +1 -1
  192. package/dist/components/LpContextMenu.vue.js +1 -1
  193. package/dist/components/LpCopyButton.vue.d.ts +82 -0
  194. package/dist/components/LpCopyButton.vue.js +4 -0
  195. package/dist/components/LpCountdown.vue.d.ts +100 -0
  196. package/dist/components/LpCountdown.vue.js +4 -0
  197. package/dist/components/LpDataList.vue.d.ts +66 -0
  198. package/dist/components/LpDataList.vue.js +4 -0
  199. package/dist/components/LpDatePicker.vue.d.ts +3 -1
  200. package/dist/components/LpDatePicker.vue.js +1 -1
  201. package/dist/components/LpDateRangePicker.vue.d.ts +3 -1
  202. package/dist/components/LpDateRangePicker.vue.js +1 -1
  203. package/dist/components/LpDisclosure.vue.js +1 -1
  204. package/dist/components/LpDock.vue.d.ts +74 -0
  205. package/dist/components/LpDock.vue.js +204 -0
  206. package/dist/components/LpDrawer.vue.js +1 -1
  207. package/dist/components/LpDropdownMenu.vue.js +1 -1
  208. package/dist/components/LpDropzone.vue.d.ts +8 -1
  209. package/dist/components/LpDropzone.vue.js +36 -15
  210. package/dist/components/LpEditable.vue.d.ts +85 -0
  211. package/dist/components/LpEditable.vue.js +4 -0
  212. package/dist/components/LpEmptyState.vue.js +1 -1
  213. package/dist/components/LpFieldNotice.vue.js +1 -1
  214. package/dist/components/LpFileTree.vue.js +1 -1
  215. package/dist/components/LpFileTreeNode.vue.js +1 -1
  216. package/dist/components/LpFormField.vue.js +1 -1
  217. package/dist/components/LpFrame.vue.d.ts +22 -0
  218. package/dist/components/LpFrame.vue.js +4 -0
  219. package/dist/components/LpGauge.vue.d.ts +116 -0
  220. package/dist/components/LpGauge.vue.js +4 -0
  221. package/dist/components/LpGlowBorder.vue.d.ts +47 -0
  222. package/dist/components/LpGlowBorder.vue.js +4 -0
  223. package/dist/components/LpHintExample.vue.d.ts +2 -2
  224. package/dist/components/LpHintExample.vue.js +1 -1
  225. package/dist/components/LpHintLayer.vue.js +1 -1
  226. package/dist/components/LpHints.vue.js +1 -1
  227. package/dist/components/LpHoverCard.vue.d.ts +60 -0
  228. package/dist/components/LpHoverCard.vue.js +4 -0
  229. package/dist/components/LpIcon.vue.js +1 -1
  230. package/dist/components/LpIdenticon.vue.d.ts +37 -0
  231. package/dist/components/LpIdenticon.vue.js +4 -0
  232. package/dist/components/LpImageEditor.vue.js +13 -19
  233. package/dist/components/LpInfraNode.vue.js +1 -1
  234. package/dist/components/LpInput.vue.d.ts +10 -0
  235. package/dist/components/LpInput.vue.js +1 -1
  236. package/dist/components/LpLightbox.vue.js +1 -1
  237. package/dist/components/LpLoader.vue.d.ts +106 -0
  238. package/dist/components/LpLoader.vue.js +4 -0
  239. package/dist/components/LpLogViewer.vue.js +1 -1
  240. package/dist/components/LpMagnetic.vue.d.ts +28 -0
  241. package/dist/components/LpMagnetic.vue.js +4 -0
  242. package/dist/components/LpMapPicker.vue.js +1 -1
  243. package/dist/components/LpMasonry.vue.d.ts +42 -0
  244. package/dist/components/LpMasonry.vue.js +4 -0
  245. package/dist/components/LpMediaGallery.vue.js +1 -1
  246. package/dist/components/LpModal.vue.js +1 -1
  247. package/dist/components/LpModalNav.vue.js +1 -1
  248. package/dist/components/LpNotificationBell.vue.d.ts +15 -6
  249. package/dist/components/LpNotificationBell.vue.js +1 -1
  250. package/dist/components/LpNumberField.vue.d.ts +57 -0
  251. package/dist/components/LpNumberField.vue.js +1 -1
  252. package/dist/components/LpNumberFlow.vue.js +1 -1
  253. package/dist/components/LpOtpInput.vue.d.ts +12 -4
  254. package/dist/components/LpOtpInput.vue.js +1 -1
  255. package/dist/components/LpPagination.vue.js +1 -1
  256. package/dist/components/LpPaletteFacts.vue.js +2 -2
  257. package/dist/components/LpPaletteHeader.vue.js +2 -2
  258. package/dist/components/LpPalettePreview.vue.js +1 -1
  259. package/dist/components/LpPaletteStats.vue.js +2 -2
  260. package/dist/components/LpPasswordInput.vue.d.ts +19 -2
  261. package/dist/components/LpPasswordInput.vue.js +1 -1
  262. package/dist/components/LpPhoneInput.vue.js +1 -1
  263. package/dist/components/LpPie.vue.d.ts +3 -1
  264. package/dist/components/LpPie.vue.js +1 -1
  265. package/dist/components/LpPipeline.vue.d.ts +91 -0
  266. package/dist/components/LpPipeline.vue.js +4 -0
  267. package/dist/components/LpPopover.vue.d.ts +2 -2
  268. package/dist/components/LpPopover.vue.js +1 -1
  269. package/dist/components/LpProgress.vue.d.ts +11 -4
  270. package/dist/components/LpProgress.vue.js +1 -1
  271. package/dist/components/LpQuota.vue.d.ts +68 -0
  272. package/dist/components/LpQuota.vue.js +4 -0
  273. package/dist/components/LpRadioGroup.vue.js +1 -1
  274. package/dist/components/LpRangeCalendar.vue.js +1 -1
  275. package/dist/components/LpRangeSlider.vue.js +1 -1
  276. package/dist/components/LpRelativeTime.vue.d.ts +41 -0
  277. package/dist/components/LpRelativeTime.vue.js +4 -0
  278. package/dist/components/LpRepeater.vue.d.ts +48 -0
  279. package/dist/components/LpRepeater.vue.js +4 -0
  280. package/dist/components/LpRevealOnScroll.vue.d.ts +67 -0
  281. package/dist/components/LpRevealOnScroll.vue.js +4 -0
  282. package/dist/components/LpRollingText.vue.d.ts +3 -1
  283. package/dist/components/LpRollingText.vue.js +1 -1
  284. package/dist/components/LpScramble.vue.d.ts +55 -0
  285. package/dist/components/LpScramble.vue.js +4 -0
  286. package/dist/components/LpScrollArea.vue.d.ts +1 -1
  287. package/dist/components/LpSecretField.vue.d.ts +108 -0
  288. package/dist/components/LpSecretField.vue.js +4 -0
  289. package/dist/components/LpSection.vue.js +1 -1
  290. package/dist/components/LpSegmented.vue.js +1 -1
  291. package/dist/components/LpSelect.vue.d.ts +2 -0
  292. package/dist/components/LpSelect.vue.js +1 -1
  293. package/dist/components/LpShaderBackdrop.vue.d.ts +39 -0
  294. package/dist/components/LpShaderBackdrop.vue.js +4 -0
  295. package/dist/components/LpShinyText.vue.d.ts +39 -0
  296. package/dist/components/LpShinyText.vue.js +4 -0
  297. package/dist/components/LpShortcutsDialog.vue.js +1 -1
  298. package/dist/components/LpSidebar.vue.js +1 -1
  299. package/dist/components/LpSidebarNav.vue.js +1 -1
  300. package/dist/components/LpSlider.vue.js +1 -1
  301. package/dist/components/LpSparkline.vue.d.ts +4 -3
  302. package/dist/components/LpSparkline.vue.js +1 -1
  303. package/dist/components/LpSpotlight.vue.d.ts +37 -0
  304. package/dist/components/LpSpotlight.vue.js +4 -0
  305. package/dist/components/LpStat.vue.js +1 -1
  306. package/dist/components/LpStatus.vue.d.ts +65 -0
  307. package/dist/components/LpStatus.vue.js +4 -0
  308. package/dist/components/LpStepMark.vue.d.ts +31 -0
  309. package/dist/components/LpStepMark.vue.js +4 -0
  310. package/dist/components/LpStepper.vue.js +1 -1
  311. package/dist/components/LpSwap.vue.js +1 -1
  312. package/dist/components/LpSwitch.vue.d.ts +2 -2
  313. package/dist/components/LpSwitch.vue.js +1 -1
  314. package/dist/components/LpTable.vue.js +104 -120
  315. package/dist/components/LpTableFilter.vue.js +1 -1
  316. package/dist/components/LpTableOfContents.vue.d.ts +6 -1
  317. package/dist/components/LpTableOfContents.vue.js +1 -1
  318. package/dist/components/LpTabs.vue.d.ts +5 -5
  319. package/dist/components/LpTabs.vue.js +25 -33
  320. package/dist/components/LpTagsInput.vue.js +1 -1
  321. package/dist/components/LpTextReveal.vue.d.ts +58 -0
  322. package/dist/components/LpTextReveal.vue.js +4 -0
  323. package/dist/components/LpTextarea.vue.js +1 -1
  324. package/dist/components/LpThemeProvider.vue.js +1 -1
  325. package/dist/components/LpThemeStudio.vue.d.ts +54 -0
  326. package/dist/components/LpThemeStudio.vue.js +4 -0
  327. package/dist/components/LpThemeStudioSection.vue.d.ts +16 -0
  328. package/dist/components/LpThemeStudioSection.vue.js +4 -0
  329. package/dist/components/LpThemeSwitcher.vue.d.ts +32 -1
  330. package/dist/components/LpThemeSwitcher.vue.js +1 -1
  331. package/dist/components/LpTimeField.vue.d.ts +2 -0
  332. package/dist/components/LpTimeField.vue.js +1 -1
  333. package/dist/components/LpToaster.vue.js +1 -1
  334. package/dist/components/LpTooltip.vue.d.ts +2 -2
  335. package/dist/components/LpTooltip.vue.js +1 -1
  336. package/dist/components/LpTopologyCanvas.vue.js +1 -1
  337. package/dist/components/LpTour.vue.js +1 -1
  338. package/dist/components/LpTruncate.vue.d.ts +34 -0
  339. package/dist/components/LpTruncate.vue.js +4 -0
  340. package/dist/components/LpTypewriter.vue.d.ts +61 -0
  341. package/dist/components/LpTypewriter.vue.js +4 -0
  342. package/dist/components/LpUptimeBar.vue.js +1 -1
  343. package/dist/components/LpVideoBackdrop.vue.js +1 -1
  344. package/dist/components/MenuTitle.vue.js +1 -1
  345. package/dist/components/OptionContent.vue.d.ts +7 -0
  346. package/dist/components/OptionContent.vue.js +4 -0
  347. package/dist/components/PickerField.vue.d.ts +45 -0
  348. package/dist/components/PickerField.vue.js +4 -0
  349. package/dist/components/RevealToggle.vue.d.ts +21 -0
  350. package/dist/components/RevealToggle.vue.js +4 -0
  351. package/dist/components/StepConnector.vue.d.ts +19 -0
  352. package/dist/components/StepConnector.vue.js +4 -0
  353. package/dist/components/TourCard.vue.js +1 -1
  354. package/dist/components/badge.d.ts +1 -0
  355. package/dist/components/badge.js +4 -0
  356. package/dist/components/chart.d.ts +5 -1
  357. package/dist/components/chart.js +2 -21
  358. package/dist/components/dateRange.d.ts +11 -0
  359. package/dist/components/dateRange.js +12 -0
  360. package/dist/components/dock.d.ts +19 -0
  361. package/dist/components/dock.js +16 -0
  362. package/dist/components/dropdown.d.ts +10 -1
  363. package/dist/components/dropdown.js +7 -2
  364. package/dist/components/fieldText.d.ts +38 -0
  365. package/dist/components/fieldText.js +53 -0
  366. package/dist/components/fileTree.d.ts +7 -3
  367. package/dist/components/fileTree.js +12 -18
  368. package/dist/components/format.d.ts +41 -0
  369. package/dist/components/format.js +67 -0
  370. package/dist/components/identicon.d.ts +38 -0
  371. package/dist/components/identicon.js +85 -0
  372. package/dist/components/masonry.d.ts +32 -0
  373. package/dist/components/masonry.js +40 -0
  374. package/dist/components/menuWhen.js +1 -1
  375. package/dist/components/meter.d.ts +64 -0
  376. package/dist/components/meter.js +53 -0
  377. package/dist/components/otp.d.ts +1 -1
  378. package/dist/components/otp.js +7 -2
  379. package/dist/components/pipeline.d.ts +55 -0
  380. package/dist/components/pipeline.js +51 -0
  381. package/dist/components/quota.d.ts +57 -0
  382. package/dist/components/quota.js +40 -0
  383. package/dist/components/relativeTime.d.ts +24 -0
  384. package/dist/components/relativeTime.js +56 -0
  385. package/dist/components/reveal.d.ts +18 -0
  386. package/dist/components/reveal.js +32 -0
  387. package/dist/components/scramble.d.ts +68 -0
  388. package/dist/components/scramble.js +58 -0
  389. package/dist/components/shaderBackdrop.d.ts +20 -0
  390. package/dist/components/shaderBackdrop.js +156 -0
  391. package/dist/components/slider.d.ts +5 -0
  392. package/dist/components/slider.js +24 -0
  393. package/dist/components/slotText.d.ts +2 -0
  394. package/dist/components/slotText.js +9 -0
  395. package/dist/components/status.d.ts +14 -0
  396. package/dist/components/status.js +22 -0
  397. package/dist/components/tableFacets.d.ts +8 -0
  398. package/dist/components/tableFacets.js +19 -0
  399. package/dist/components/textSplit.d.ts +17 -0
  400. package/dist/components/textSplit.js +24 -0
  401. package/dist/components/timeSpan.d.ts +78 -0
  402. package/dist/components/timeSpan.js +85 -0
  403. package/dist/components/tone.d.ts +43 -0
  404. package/dist/components/tone.js +82 -0
  405. package/dist/components/tour.js +3 -2
  406. package/dist/components/typewriter.d.ts +36 -0
  407. package/dist/components/typewriter.js +53 -0
  408. package/dist/components/videoBackdrop.js +5 -6
  409. package/dist/composables/easing.d.ts +22 -1
  410. package/dist/composables/easing.js +42 -1
  411. package/dist/composables/pseudoLocale.d.ts +15 -0
  412. package/dist/composables/pseudoLocale.js +96 -0
  413. package/dist/composables/scroll.js +5 -3
  414. package/dist/composables/useClipboard.d.ts +4 -1
  415. package/dist/composables/useClipboard.js +12 -2
  416. package/dist/composables/useField.d.ts +13 -0
  417. package/dist/composables/useField.js +26 -1
  418. package/dist/composables/useForm.js +32 -9
  419. package/dist/composables/useInView.d.ts +11 -0
  420. package/dist/composables/useInView.js +39 -0
  421. package/dist/composables/useLoadingGate.d.ts +8 -0
  422. package/dist/composables/useLoadingGate.js +38 -0
  423. package/dist/composables/useLpConfig.d.ts +10 -0
  424. package/dist/composables/useLpConfig.js +11 -1
  425. package/dist/composables/useMediaQuery.js +3 -1
  426. package/dist/composables/useNow.d.ts +16 -0
  427. package/dist/composables/useNow.js +39 -0
  428. package/dist/composables/usePersisted.js +14 -7
  429. package/dist/composables/usePillTransition.d.ts +5 -2
  430. package/dist/composables/usePillTransition.js +4 -3
  431. package/dist/composables/usePointerFrame.d.ts +18 -0
  432. package/dist/composables/usePointerFrame.js +31 -0
  433. package/dist/composables/useReducedMotion.d.ts +2 -0
  434. package/dist/composables/useReducedMotion.js +7 -0
  435. package/dist/composables/useRepeater.d.ts +17 -0
  436. package/dist/composables/useRepeater.js +31 -0
  437. package/dist/composables/useResizeObserver.d.ts +8 -0
  438. package/dist/composables/useResizeObserver.js +33 -0
  439. package/dist/composables/useRevealedValue.d.ts +31 -0
  440. package/dist/composables/useRevealedValue.js +26 -0
  441. package/dist/composables/useScramble.d.ts +42 -0
  442. package/dist/composables/useScramble.js +76 -0
  443. package/dist/composables/useShift.js +2 -10
  444. package/dist/composables/useSpotlight.d.ts +18 -0
  445. package/dist/composables/useSpotlight.js +53 -0
  446. package/dist/composables/useTilt.js +26 -18
  447. package/dist/composables/useTween.d.ts +43 -0
  448. package/dist/composables/useTween.js +69 -0
  449. package/dist/composables/useView.d.ts +18 -0
  450. package/dist/composables/useView.js +64 -0
  451. package/dist/icons-all.js +1 -1
  452. package/dist/index.d.ts +98 -1
  453. package/dist/index.js +263 -105
  454. package/dist/theme/define.d.ts +12 -0
  455. package/dist/theme/studio.d.ts +90 -0
  456. package/package.json +8 -2
  457. package/src/component-names.ts +33 -0
  458. package/src/components/AttentionDot.vue +27 -0
  459. package/src/components/ContextMenuItems.vue +5 -2
  460. package/src/components/FieldWrapper.vue +38 -0
  461. package/src/components/LayoutNode.vue +5 -9
  462. package/src/components/LegendSwatch.vue +15 -0
  463. package/src/components/LoaderMark.vue +90 -0
  464. package/src/components/LpActionBar.vue +12 -20
  465. package/src/components/LpActivityLine.vue +186 -0
  466. package/src/components/LpAlert.vue +54 -24
  467. package/src/components/LpAppShell.vue +7 -11
  468. package/src/components/LpAutocomplete.vue +16 -14
  469. package/src/components/LpAvatar.vue +17 -2
  470. package/src/components/LpBadge.vue +77 -13
  471. package/src/components/LpBreadcrumbs.vue +101 -35
  472. package/src/components/LpButton.vue +15 -3
  473. package/src/components/LpCard.vue +30 -7
  474. package/src/components/LpChart.vue +162 -171
  475. package/src/components/LpCheckbox.vue +10 -4
  476. package/src/components/LpCodeBlock.vue +11 -19
  477. package/src/components/LpCodeDisplay.vue +228 -0
  478. package/src/components/LpCollapse.vue +162 -0
  479. package/src/components/LpColorPicker.vue +10 -1
  480. package/src/components/LpCommandPalette.vue +38 -24
  481. package/src/components/LpContextMenu.vue +13 -3
  482. package/src/components/LpCopyButton.vue +185 -0
  483. package/src/components/LpCountdown.vue +308 -0
  484. package/src/components/LpDataList.vue +154 -0
  485. package/src/components/LpDatePicker.vue +55 -104
  486. package/src/components/LpDateRangePicker.vue +51 -95
  487. package/src/components/LpDisclosure.vue +58 -36
  488. package/src/components/LpDock.vue +274 -0
  489. package/src/components/LpDrawer.vue +10 -1
  490. package/src/components/LpDropdownMenu.vue +11 -2
  491. package/src/components/LpDropzone.vue +34 -13
  492. package/src/components/LpEditable.vue +295 -0
  493. package/src/components/LpFileTree.vue +5 -1
  494. package/src/components/LpFileTreeNode.vue +25 -50
  495. package/src/components/LpFormField.vue +22 -3
  496. package/src/components/LpFrame.vue +200 -0
  497. package/src/components/LpGauge.vue +287 -0
  498. package/src/components/LpGlowBorder.vue +60 -0
  499. package/src/components/LpHintExample.vue +9 -32
  500. package/src/components/LpHintLayer.vue +13 -3
  501. package/src/components/LpHoverCard.vue +175 -0
  502. package/src/components/LpIdenticon.vue +69 -0
  503. package/src/components/LpImageEditor.vue +15 -18
  504. package/src/components/LpInfraNode.vue +27 -16
  505. package/src/components/LpInput.vue +30 -16
  506. package/src/components/LpLightbox.vue +44 -23
  507. package/src/components/LpLoader.vue +145 -0
  508. package/src/components/LpLogViewer.vue +311 -82
  509. package/src/components/LpMagnetic.vue +97 -0
  510. package/src/components/LpMapPicker.vue +26 -28
  511. package/src/components/LpMasonry.vue +247 -0
  512. package/src/components/LpModal.vue +10 -1
  513. package/src/components/LpNotificationBell.vue +33 -49
  514. package/src/components/LpNumberField.vue +79 -14
  515. package/src/components/LpNumberFlow.vue +10 -35
  516. package/src/components/LpOtpInput.vue +7 -2
  517. package/src/components/LpPagination.vue +38 -4
  518. package/src/components/LpPalettePreview.vue +2 -7
  519. package/src/components/LpPasswordInput.vue +25 -18
  520. package/src/components/LpPhoneInput.vue +12 -3
  521. package/src/components/LpPie.vue +197 -36
  522. package/src/components/LpPipeline.vue +366 -0
  523. package/src/components/LpPopover.vue +14 -1
  524. package/src/components/LpProgress.vue +22 -84
  525. package/src/components/LpQuota.vue +197 -0
  526. package/src/components/LpRangeSlider.vue +5 -1
  527. package/src/components/LpRelativeTime.vue +90 -0
  528. package/src/components/LpRepeater.vue +131 -0
  529. package/src/components/LpRevealOnScroll.vue +125 -0
  530. package/src/components/LpRollingText.vue +12 -1
  531. package/src/components/LpScramble.vue +107 -0
  532. package/src/components/LpSecretField.vue +320 -0
  533. package/src/components/LpSegmented.vue +3 -10
  534. package/src/components/LpSelect.vue +74 -65
  535. package/src/components/LpShaderBackdrop.vue +434 -0
  536. package/src/components/LpShinyText.vue +139 -0
  537. package/src/components/LpSidebar.vue +2 -0
  538. package/src/components/LpSlider.vue +5 -1
  539. package/src/components/LpSparkline.vue +55 -37
  540. package/src/components/LpSpotlight.vue +51 -0
  541. package/src/components/LpStat.vue +6 -2
  542. package/src/components/LpStatus.vue +127 -0
  543. package/src/components/LpStepMark.vue +138 -0
  544. package/src/components/LpStepper.vue +37 -43
  545. package/src/components/LpSwap.vue +2 -2
  546. package/src/components/LpSwitch.vue +15 -22
  547. package/src/components/LpTable.vue +47 -63
  548. package/src/components/LpTableFilter.vue +1 -0
  549. package/src/components/LpTableOfContents.vue +53 -29
  550. package/src/components/LpTabs.vue +10 -21
  551. package/src/components/LpTagsInput.vue +53 -37
  552. package/src/components/LpTextReveal.vue +236 -0
  553. package/src/components/LpTextarea.vue +11 -11
  554. package/src/components/LpThemeStudio.vue +216 -0
  555. package/src/components/LpThemeStudioSection.vue +16 -0
  556. package/src/components/LpThemeSwitcher.vue +156 -47
  557. package/src/components/LpTimeField.vue +9 -1
  558. package/src/components/LpToaster.vue +63 -83
  559. package/src/components/LpTooltip.vue +10 -1
  560. package/src/components/LpTour.vue +24 -13
  561. package/src/components/LpTruncate.vue +135 -0
  562. package/src/components/LpTypewriter.vue +236 -0
  563. package/src/components/LpUptimeBar.vue +6 -5
  564. package/src/components/LpVideoBackdrop.vue +15 -13
  565. package/src/components/OptionContent.vue +17 -0
  566. package/src/components/PickerField.vue +59 -0
  567. package/src/components/RevealToggle.vue +51 -0
  568. package/src/components/StepConnector.vue +54 -0
  569. package/src/components/TourCard.vue +29 -16
  570. package/src/components/badge.ts +8 -0
  571. package/src/components/chart.ts +8 -23
  572. package/src/components/dateRange.ts +25 -0
  573. package/src/components/dock.ts +31 -0
  574. package/src/components/dropdown.ts +15 -3
  575. package/src/components/fieldText.ts +95 -0
  576. package/src/components/fileTree.ts +19 -21
  577. package/src/components/format.ts +136 -0
  578. package/src/components/identicon.ts +160 -0
  579. package/src/components/masonry.ts +73 -0
  580. package/src/components/meter.ts +122 -0
  581. package/src/components/otp.ts +14 -3
  582. package/src/components/pipeline.ts +101 -0
  583. package/src/components/quota.ts +111 -0
  584. package/src/components/relativeTime.ts +118 -0
  585. package/src/components/reveal.ts +56 -0
  586. package/src/components/scramble.ts +138 -0
  587. package/src/components/shaderBackdrop.ts +208 -0
  588. package/src/components/slider.ts +30 -0
  589. package/src/components/slotText.ts +13 -0
  590. package/src/components/status.ts +46 -0
  591. package/src/components/tableFacets.ts +25 -0
  592. package/src/components/textSplit.ts +55 -0
  593. package/src/components/timeSpan.ts +183 -0
  594. package/src/components/tone.ts +144 -0
  595. package/src/components/tour.ts +3 -2
  596. package/src/components/typewriter.ts +104 -0
  597. package/src/components/videoBackdrop.ts +7 -6
  598. package/src/composables/easing.ts +66 -1
  599. package/src/composables/pseudoLocale.ts +105 -0
  600. package/src/composables/scroll.ts +6 -3
  601. package/src/composables/useClipboard.ts +25 -3
  602. package/src/composables/useField.ts +38 -1
  603. package/src/composables/useForm.ts +41 -11
  604. package/src/composables/useInView.ts +61 -0
  605. package/src/composables/useLoadingGate.ts +63 -0
  606. package/src/composables/useLpConfig.ts +20 -1
  607. package/src/composables/useMediaQuery.ts +6 -2
  608. package/src/composables/useNow.ts +84 -0
  609. package/src/composables/usePersisted.ts +19 -8
  610. package/src/composables/usePillTransition.ts +21 -13
  611. package/src/composables/usePointerFrame.ts +72 -0
  612. package/src/composables/useReducedMotion.ts +22 -0
  613. package/src/composables/useRepeater.ts +44 -0
  614. package/src/composables/useResizeObserver.ts +59 -0
  615. package/src/composables/useRevealedValue.ts +84 -0
  616. package/src/composables/useScramble.ts +152 -0
  617. package/src/composables/useShift.ts +10 -16
  618. package/src/composables/useSpotlight.ts +82 -0
  619. package/src/composables/useTilt.ts +40 -23
  620. package/src/composables/useTween.ts +149 -0
  621. package/src/composables/useView.ts +96 -0
  622. package/src/index.css +1 -0
  623. package/src/index.ts +143 -1
  624. package/src/kit-icons.ts +1 -1
  625. package/src/theme/define.ts +65 -0
  626. package/src/theme/studio.ts +202 -0
  627. package/src/tokens/effects.css +151 -0
  628. package/src/tokens/tokens.css +131 -39
  629. package/src/tokens/utilities.css +81 -0
  630. package/dist/assets/LpTabs-Bk7v4bZz.css +0 -18
  631. package/dist/chunks/LpAlert-BdvxvcWE.js +0 -85
  632. package/dist/chunks/LpBadge-Fe0D1bYx.js +0 -62
  633. package/dist/chunks/LpBreadcrumbs-rzOKkLiI.js +0 -98
  634. package/dist/chunks/LpDatePicker-BMfM454Y.js +0 -243
  635. package/dist/chunks/LpDateRangePicker-CNb9X3eL.js +0 -195
  636. package/dist/chunks/LpNumberField-DO1ufKvE.js +0 -107
  637. package/dist/chunks/LpStepper-C2slwObu.js +0 -90
  638. package/dist/chunks/LpSwitch-CZy9_IoA.js +0 -132
  639. package/dist/chunks/LpThemeSwitcher-CDoziW0z.js +0 -166
  640. package/dist/chunks/TourCard-BKI7X9-r.js +0 -105
@@ -0,0 +1,145 @@
1
+ <script lang="ts">
2
+ // The consumer's `class` is merged into the root's own (below) rather than
3
+ // appended to it, so opt out of the automatic pass-through that would add it
4
+ // a second time, unmerged.
5
+ export default { inheritAttrs: false }
6
+ </script>
7
+
8
+ <script setup lang="ts">
9
+ /*
10
+ * The kit's loading indicator: a spinner, three dots or an indeterminate bar.
11
+ *
12
+ * Every component that waits used to draw its own (a lucide loader-circle
13
+ * with `animate-spin`, toned by hand), so each one blinked on fast loads in
14
+ * its own way and none told a screen reader anything. This one owns the three
15
+ * things they all needed and none had:
16
+ *
17
+ * - timing: `delay` before it appears, so a load that finishes quickly shows
18
+ * nothing at all, and `minVisible` once it has, so it never flashes
19
+ * (see useLoadingGate);
20
+ * - a status: role="status" with a polite label, so "loading" is announced
21
+ * rather than only drawn;
22
+ * - reduced motion: a spinner that simply stops reads as a frozen page, so
23
+ * under reduced motion every variant breathes (a slow fade) instead of
24
+ * moving — a change of state the eye can still see, without travel.
25
+ *
26
+ * <LpLoader /> inline spinner
27
+ * <LpLoader variant="dots" label="Connecting" />
28
+ * <LpLoader :active="loading"><Results /></LpLoader> placeholder → content
29
+ *
30
+ * Determinate progress (a known fraction) is LpProgress; this is for waits
31
+ * whose length is unknown.
32
+ */
33
+ import { computed, useSlots } from "vue"
34
+ import { useLabels } from "../composables/useLpConfig"
35
+ import { useLoadingGate } from "../composables/useLoadingGate"
36
+ import { useMergedAttrs } from "../composables/useMergedClass"
37
+ import LoaderMark from "./LoaderMark.vue"
38
+ import LpSwap from "./LpSwap.vue"
39
+ import { toneLook, type ToneName } from "./tone"
40
+
41
+ export type LoaderVariant = "spinner" | "dots" | "bar"
42
+ export type LoaderSize = "inline" | "sm" | "md" | "lg"
43
+ /** `current` inherits the text colour around it; the rest are the kit's tones (tone.ts). */
44
+ export type LoaderTone = "current" | ToneName
45
+ export type LoaderLabels = { loading: string }
46
+
47
+ const props = withDefaults(
48
+ defineProps<{
49
+ /**
50
+ * `spinner` for a spot (a button, a row, a field); `dots` for something
51
+ * conversational (typing, connecting); `bar` for a region across its width
52
+ * (the top of a card or a page).
53
+ */
54
+ variant?: LoaderVariant
55
+ /**
56
+ * `inline` sizes the mark from the font (a 1em spinner), so it fits a
57
+ * button or a line of text at whatever size that text is.
58
+ */
59
+ size?: LoaderSize
60
+ /**
61
+ * `current` takes the surrounding text colour, which is what a loader
62
+ * inside a button or a coloured badge wants; the others pin a kit tone.
63
+ */
64
+ tone?: LoaderTone
65
+ /**
66
+ * Whether work is under way. Off, the loader is not shown (or, with a
67
+ * default slot, the content is). Leave it on and mount the loader with
68
+ * `v-if` when it has nothing to swap with.
69
+ */
70
+ active?: boolean
71
+ /**
72
+ * Ms of loading before anything appears. Most requests finish inside 150
73
+ * ms; a spinner for those is a blink, not information. 0 shows at once —
74
+ * the right call where the trigger already acknowledged the click (a
75
+ * button that faded its label).
76
+ */
77
+ delay?: number
78
+ /** Ms the loader stays once shown, so a load ending just after it appeared does not blink it away. */
79
+ minVisible?: number
80
+ /**
81
+ * Visible text beside the indicator. Without it the indicator is still
82
+ * announced, with the `loading` label, to screen readers only.
83
+ */
84
+ label?: string
85
+ /** Spinner only: draw the faint full circle the arc runs along. */
86
+ track?: boolean
87
+ labels?: Partial<LoaderLabels>
88
+ }>(),
89
+ {
90
+ variant: "spinner",
91
+ size: "md",
92
+ tone: "current",
93
+ active: true,
94
+ delay: 150,
95
+ minVisible: 400,
96
+ track: false,
97
+ },
98
+ )
99
+
100
+ const text = useLabels<LoaderLabels>("loader", { loading: "Loading…" }, () => props.labels)
101
+ const shown = useLoadingGate(() => props.active, {
102
+ delay: () => props.delay,
103
+ minVisible: () => props.minVisible,
104
+ })
105
+
106
+ const slots = useSlots()
107
+ const wraps = computed(() => !!slots.default)
108
+
109
+
110
+ /*
111
+ * The consumer's class lands on the indicator's own box (the status element),
112
+ * so `class="w-40"` narrows a bar and `class="text-lg"` scales an `inline`
113
+ * loader, rather than styling a wrapper around them.
114
+ */
115
+ const { class: rootClass, attrs: rest } = useMergedAttrs(() => {
116
+ const tone = props.tone === "current" ? "" : toneLook(props.tone).text
117
+ if (props.variant === "bar") {
118
+ return `flex w-full min-w-12 flex-col gap-1.5 ${tone}`
119
+ }
120
+ return `inline-flex items-center gap-2 align-middle ${tone}`
121
+ })
122
+
123
+ const spoken = computed(() => props.label || text.value.loading)
124
+ </script>
125
+
126
+ <template>
127
+ <div v-if="wraps" :aria-busy="shown ? 'true' : undefined">
128
+ <LpSwap :swap-key="shown ? 'loading' : 'content'">
129
+ <div v-if="shown" class="flex justify-center py-8">
130
+ <LoaderMark :class="rootClass" v-bind="rest" :variant="variant" :size="size" :track="track" :label="label" :spoken="spoken" />
131
+ </div>
132
+ <slot v-else />
133
+ </LpSwap>
134
+ </div>
135
+
136
+ <Transition
137
+ v-else
138
+ enter-active-class="transition-opacity duration-(--duration-fast) ease-(--ease-emphasized) motion-reduce:transition-none"
139
+ enter-from-class="opacity-0"
140
+ leave-active-class="transition-opacity duration-(--duration-fast) ease-out motion-reduce:transition-none"
141
+ leave-to-class="opacity-0"
142
+ >
143
+ <LoaderMark v-if="shown" :class="rootClass" v-bind="rest" :variant="variant" :size="size" :track="track" :label="label" :spoken="spoken" />
144
+ </Transition>
145
+ </template>
@@ -25,16 +25,21 @@ import {
25
25
  watch,
26
26
  } from "vue"
27
27
  import { usePersisted } from "../composables/usePersisted"
28
- import { prefersReducedMotion } from "../composables/easing"
28
+ import { durationToken, prefersReducedMotion, tokenEase } from "../composables/easing"
29
29
  import { useClipboard } from "../composables/useClipboard"
30
30
  import { useHotkeys } from "../composables/useHotkeys"
31
+ import LpBadge from "./LpBadge.vue"
31
32
  import LpContextMenu, { type ContextMenuItemDef } from "./LpContextMenu.vue"
32
33
  import LpEmptyState from "./LpEmptyState.vue"
33
34
  import LpIcon from "./LpIcon.vue"
35
+ import LpLoader from "./LpLoader.vue"
36
+ import LpInput from "./LpInput.vue"
34
37
  import LpScrollArea from "./LpScrollArea.vue"
35
38
  import { useMergedAttrs } from "../composables/useMergedClass"
36
39
  import { useLabels } from "../composables/useLpConfig"
40
+ import { useResizeObserver } from "../composables/useResizeObserver"
37
41
  import { countLevels, matchPositions, ringWindow, stepMatch } from "./logSearch"
42
+ import { TONES, toneLook, type ToneName } from "./tone"
38
43
 
39
44
  export interface LogViewerLabels {
40
45
  [key: string]: string
@@ -225,16 +230,21 @@ const text = useLabels<LogViewerLabels>(
225
230
  // red (fatal gets a filled chip to stand apart from plain error).
226
231
  // `sel` tints ::selection in the row's semantic colour (info→brand, warn→accent,
227
232
  // error/fatal→danger) via Tailwind's `selection:` variant — the highlight then
228
- // matches the level instead of the browser default. Static classes (not built
229
- // from a var) so Tailwind emits them from the @source scan.
233
+ // matches the level instead of the browser default. The toned levels read the
234
+ // kit's tones (tone.ts, where the classes are spelled out whole for Tailwind's
235
+ // scan); trace and debug are quieter than any tone, two steps of grey.
236
+ const toned = (tone: ToneName) => {
237
+ const look = toneLook(tone)
238
+ return { rail: look.bg, text: "text-ink", chip: look.text, sel: look.selection }
239
+ }
230
240
  const levelMeta: Record<LogLevel, { rail: string; text: string; chip: string; sel: string }> = {
231
- trace: { rail: "bg-line-strong", text: "text-muted", chip: "text-muted", sel: "selection:bg-muted/40" },
241
+ trace: { rail: "bg-line-strong", text: "text-muted", chip: "text-muted", sel: TONES.neutral.selection },
232
242
  debug: { rail: "bg-line-strong", text: "text-muted-strong", chip: "text-muted-strong", sel: "selection:bg-muted-strong/40" },
233
- info: { rail: "bg-brand", text: "text-ink", chip: "text-brand", sel: "selection:bg-brand/40" },
234
- success: { rail: "bg-action", text: "text-ink", chip: "text-action", sel: "selection:bg-action/40" },
235
- warn: { rail: "bg-accent", text: "text-ink", chip: "text-accent", sel: "selection:bg-accent/40" },
236
- error: { rail: "bg-danger", text: "text-ink", chip: "text-danger", sel: "selection:bg-danger/40" },
237
- fatal: { rail: "bg-danger", text: "text-ink", chip: "rounded-xs bg-danger px-1 text-ink-inverse", sel: "selection:bg-danger/40" },
243
+ info: toned("info"),
244
+ success: toned("success"),
245
+ warn: toned("warning"),
246
+ error: toned("error"),
247
+ fatal: { ...toned("error"), chip: `rounded-xs px-1 text-ink-inverse ${TONES.danger.bg}` },
238
248
  }
239
249
 
240
250
  function metaFor(level?: LogLevel) {
@@ -511,7 +521,7 @@ function revealMatch(position: number | undefined) {
511
521
  el.querySelector<HTMLElement>(`[data-log-row="${n}"]`)?.scrollIntoView({ block: "center", behavior })
512
522
  }
513
523
 
514
- const searchEl = ref<HTMLInputElement | null>(null)
524
+ const searchEl = ref<InstanceType<typeof LpInput> | null>(null)
515
525
 
516
526
  function onSearchKeydown(event: KeyboardEvent) {
517
527
  if (event.isComposing) return
@@ -727,7 +737,12 @@ let topArmed = true
727
737
 
728
738
  function onScroll(e: Event) {
729
739
  const el = e.target as HTMLElement
730
- pinned.value = atBottom(el)
740
+ // The glide's own writes are not the user leaving the tail: a burst taller
741
+ // than NEAR would read as "scrolled up" on its first frame and unpin it.
742
+ // Anything the user does to scroll cancels the glide before this runs. Nor
743
+ // may a scroll event the glide queued before an upward wheel re-pin the
744
+ // tail the wheel just left (see `leaveTail`).
745
+ if (!glide && performance.now() - leftAt > LEAVE_GRACE_MS) pinned.value = atBottom(el)
731
746
  // Feed the virtual window. Reading clientHeight here keeps it in sync with
732
747
  // runtime resizes (drawer drag, window resize) without a ResizeObserver.
733
748
  scrollTop.value = el.scrollTop
@@ -743,38 +758,171 @@ function onScroll(e: Event) {
743
758
  }
744
759
  }
745
760
 
746
- // Preserve scroll position across a prepend: when older lines are added at the
747
- // top, scrollTop must grow by the height they introduced or the view jumps. We
748
- // snapshot scrollHeight before the lines change and restore the offset after.
749
- let prevScrollHeight = 0
750
- let prevScrollTop = 0
761
+ /*
762
+ * Keep the line being read where it is when the lines change under it.
763
+ *
764
+ * Anchored on a row, not on the total height. Measuring how much scrollHeight
765
+ * grew and adding all of it to scrollTop is right for older lines prepended
766
+ * above, but a line appended BELOW grows it just the same, so every pushed
767
+ * line dragged a reader who had scrolled up one row further down. The absolute
768
+ * write also cancelled the browser's own animated wheel scroll, so with a busy
769
+ * stream a wheel turn up never got anywhere.
770
+ *
771
+ * The first row in view is remembered with its offset; afterwards scrollTop
772
+ * moves by however far that row was displaced, and is not written at all when
773
+ * it stayed put. Rows above that leave (a capped stream) are covered the same
774
+ * way.
775
+ */
776
+ let anchorRow: HTMLElement | null = null
777
+ let anchorOffset = 0
778
+
779
+ function firstRowInView(el: HTMLElement): HTMLElement | null {
780
+ const top = el.getBoundingClientRect().top
781
+ for (const row of el.querySelectorAll<HTMLElement>("[data-log-row]")) {
782
+ if (row.getBoundingClientRect().bottom > top) return row
783
+ }
784
+ return null
785
+ }
786
+
751
787
  function captureScrollAnchor() {
752
788
  const el = viewport()
753
- if (!el) return
754
- prevScrollHeight = el.scrollHeight
755
- prevScrollTop = el.scrollTop
789
+ anchorRow = el ? firstRowInView(el) : null
790
+ if (el && anchorRow) anchorOffset = anchorRow.getBoundingClientRect().top - el.getBoundingClientRect().top
756
791
  }
792
+
757
793
  function restoreScrollAnchor() {
758
794
  const el = viewport()
759
- if (!el) return
760
- const added = el.scrollHeight - prevScrollHeight
761
- if (added > 0) el.scrollTop = prevScrollTop + added
795
+ const row = anchorRow
796
+ anchorRow = null
797
+ if (!el || !row?.isConnected) return
798
+ const drift = row.getBoundingClientRect().top - el.getBoundingClientRect().top - anchorOffset
799
+ if (Math.abs(drift) >= 1) el.scrollTop += drift
762
800
  }
763
801
 
764
- // Glide to the bottom. Honours OS reduce-motion. For auto-tail we skip the
765
- // animation on large jumps (`far`), where a smooth chase would feel sluggish —
766
- // but a deliberate "jump to latest" passes force=true to always animate.
767
- function rideToBottom(smooth = true, force = false) {
802
+ /*
803
+ * Follow the tail by easing scrollTop toward the bottom over a frame loop.
804
+ *
805
+ * The browser's own smooth scroll covered one 20px row in three frames, so a
806
+ * pushed line still read as a jolt; it also cannot be retargeted, and a line
807
+ * arriving mid-scroll restarted it from wherever it stood. Here the target is
808
+ * re-read every frame, so lines landing during the glide (or rows collapsing
809
+ * above it) only move where it ends, and a fresh change restarts the easing
810
+ * from the position actually on screen.
811
+ *
812
+ * A jump of more than a viewport starts one viewport short of the end: easing
813
+ * across a whole burst is a smear of text nobody can follow, and snapping
814
+ * there outright was the jolt this replaces.
815
+ */
816
+ let glide = 0
817
+
818
+ function stopGlide() {
819
+ if (glide) cancelAnimationFrame(glide)
820
+ glide = 0
821
+ }
822
+
823
+ /*
824
+ * Where "the bottom" is: the newest row that is staying, not the end of the
825
+ * scroll height. Rows still collapsing out under it (a window that slid back,
826
+ * a filter that dropped the tail) briefly make the list overflow, and gliding
827
+ * down into them scrolled a list that fits by a few pixels and back again as
828
+ * they closed.
829
+ */
830
+ function tailEnd(el: HTMLElement): number {
831
+ const max = el.scrollHeight - el.clientHeight
832
+ const list = el.querySelector("[data-log-row]")?.parentElement
833
+ let row = list?.lastElementChild ?? null
834
+ const below = row ? max + el.clientHeight - contentBottom(el, row) : 0
835
+ while (row && (!row.hasAttribute("data-log-row") || row.classList.contains("lp-log-row-leave-active"))) {
836
+ row = row.previousElementSibling
837
+ }
838
+ if (!row) return max
839
+ return Math.max(0, Math.min(max, contentBottom(el, row) + below - el.clientHeight))
840
+ }
841
+
842
+ function contentBottom(el: HTMLElement, row: Element): number {
843
+ return row.getBoundingClientRect().bottom - el.getBoundingClientRect().top + el.scrollTop
844
+ }
845
+
846
+ function rideToBottom() {
768
847
  const el = viewport()
769
848
  if (!el) return
770
- const reduce = prefersReducedMotion()
771
- const far = !force && el.scrollHeight - el.scrollTop - el.clientHeight > el.clientHeight
772
- el.scrollTo({ top: el.scrollHeight, behavior: smooth && !reduce && !far ? "smooth" : "auto" })
849
+ stopGlide()
850
+ const end = () => tailEnd(el)
851
+ if (prefersReducedMotion()) {
852
+ el.scrollTop = end()
853
+ return
854
+ }
855
+ const from = Math.max(el.scrollTop, end() - el.clientHeight)
856
+ if (Math.abs(end() - from) < 1) return
857
+ el.scrollTop = from
858
+ const ms = durationToken("duration-medium")
859
+ const ease = tokenEase("ease-emphasized")
860
+ const started = performance.now()
861
+ const step = (now: number) => {
862
+ const t = Math.min(1, Math.max(0, (now - started) / ms))
863
+ el.scrollTop = from + (end() - from) * ease(t)
864
+ glide = t < 1 ? requestAnimationFrame(step) : 0
865
+ }
866
+ glide = requestAnimationFrame(step)
867
+ }
868
+
869
+ /*
870
+ * The user reaching for the stream ends the glide at once, and an upward
871
+ * gesture leaves the tail there and then rather than when its scroll lands.
872
+ *
873
+ * Waiting for the scroll event was not enough: a wheel turn is itself animated
874
+ * by the browser, the next pushed line arrived before it had moved past NEAR,
875
+ * the tail still counted as pinned, and the glide's first write cancelled the
876
+ * wheel's own animation. With lines every ~100ms the stream simply refused to
877
+ * be scrolled up. A pointer or finger held on the stream (dragging the
878
+ * scrollbar, selecting text) holds the tail for the same reason.
879
+ */
880
+ let holding = false
881
+ // Long enough for a scroll event already queued by the glide to arrive.
882
+ const LEAVE_GRACE_MS = 250
883
+ let leftAt = -Infinity
884
+
885
+ function leaveTail() {
886
+ stopGlide()
887
+ leftAt = performance.now()
888
+ const el = viewport()
889
+ if (el && el.scrollTop > 0) pinned.value = false
890
+ }
891
+
892
+ function onWheel(event: WheelEvent) {
893
+ if (event.deltaY < 0) leaveTail()
894
+ else stopGlide()
895
+ }
896
+
897
+ const UPWARD_KEYS = new Set(["ArrowUp", "PageUp", "Home"])
898
+
899
+ function onKeydown(event: KeyboardEvent) {
900
+ const field = event.target instanceof HTMLElement && event.target.closest("input, textarea, [contenteditable]")
901
+ if (!field && UPWARD_KEYS.has(event.key)) leaveTail()
902
+ }
903
+
904
+ function release() {
905
+ holding = false
906
+ window.removeEventListener("pointerup", release)
907
+ window.removeEventListener("pointercancel", release)
908
+ window.removeEventListener("touchend", release)
909
+ }
910
+
911
+ function hold(event: Event) {
912
+ // The scroll area's root, so its scrollbar (a sibling of the viewport)
913
+ // counts, and the toolbar and jump pill above it do not.
914
+ const area = viewport()?.parentElement
915
+ if (!area || !(event.target instanceof Node) || !area.contains(event.target)) return
916
+ stopGlide()
917
+ holding = true
918
+ window.addEventListener("pointerup", release)
919
+ window.addEventListener("pointercancel", release)
920
+ window.addEventListener("touchend", release)
773
921
  }
774
922
 
775
923
  function scrollToBottom() {
776
924
  current.value = -1
777
- rideToBottom(true, true)
925
+ rideToBottom()
778
926
  pinned.value = true
779
927
  }
780
928
 
@@ -802,8 +950,8 @@ watch(
802
950
  linesSignal,
803
951
  async () => {
804
952
  await nextTick()
805
- if (props.tail && pinned.value && current.value < 0) {
806
- requestAnimationFrame(() => rideToBottom(true))
953
+ if (props.tail && pinned.value && !holding && current.value < 0) {
954
+ rideToBottom()
807
955
  } else {
808
956
  restoreScrollAnchor()
809
957
  }
@@ -818,39 +966,77 @@ const showJump = computed(() => props.tail && !pinned.value && props.lines.lengt
818
966
  // collapsed to a single row, so there was nothing to scroll, and `onScroll` —
819
967
  // the only other place that refreshed the height — could never fire to correct
820
968
  // it. The list looked stuck and wouldn't scroll at all.
821
- let viewportResize: ResizeObserver | null = null
822
-
823
969
  function measureViewport() {
824
970
  const el = viewport()
825
971
  if (el) viewportHeight.value = el.clientHeight
826
972
  }
973
+ useResizeObserver(viewport, measureViewport)
827
974
 
828
975
  onMounted(() => {
829
976
  measureViewport()
830
977
  const el = viewport()
831
- if (el && typeof ResizeObserver !== "undefined") {
832
- viewportResize = new ResizeObserver(measureViewport)
833
- viewportResize.observe(el)
834
- }
978
+ // A tailing viewer opens on its newest lines. Opening at the top left the
979
+ // first pushed line to haul the whole history past in one go.
980
+ if (el && props.tail) el.scrollTop = el.scrollHeight
835
981
  })
836
982
 
837
983
  onBeforeUnmount(() => {
838
- viewportResize?.disconnect()
839
- viewportResize = null
984
+ stopGlide()
985
+ release()
840
986
  })
841
987
 
842
- // FLIP / enter / leave classes for the full-render TransitionGroup, bound via
843
- // v-bind so the same list element can fall back to a plain <ol> when virtualised
844
- // (a component :is can't carry TransitionGroup-only props inertly otherwise).
988
+ /*
989
+ * Enter / leave / move for the full-render TransitionGroup, bound via v-bind so
990
+ * the same list element can fall back to a plain <ol> when virtualised (a
991
+ * component :is can't carry TransitionGroup-only props inertly otherwise).
992
+ *
993
+ * Named classes from the <style> block rather than Tailwind utilities: every
994
+ * row carries `transition-colors` for its hover tint, and a utility that sets
995
+ * `transition` for the enter, leave or move lands in the same layer with the
996
+ * same specificity, so whichever Tailwind happened to emit last won. It was
997
+ * `transition-colors`: no row ever animated, a pushed line popped in and a
998
+ * dropped one took its height with it in a single frame.
999
+ *
1000
+ * A leaving row collapses from its own measured height. A fixed cap (it was
1001
+ * `max-h-8`) snapped a wrapped, three-line row down to the cap first.
1002
+ */
845
1003
  const transitionProps = {
846
1004
  tag: "ol",
847
- "enter-active-class": "transition duration-[var(--duration-medium)] ease-[var(--ease-emphasized)]",
848
- "enter-from-class": "-translate-x-1 opacity-0",
849
- "leave-active-class":
850
- "overflow-hidden transition-all duration-[var(--duration-medium)] ease-[var(--ease-emphasized)]",
851
- "leave-from-class": "max-h-8 opacity-100",
852
- "leave-to-class": "max-h-0 -translate-y-1 opacity-0",
853
- "move-class": "transition-transform duration-[var(--duration-medium)] ease-[var(--ease-emphasized)]",
1005
+ name: "lp-log-row",
1006
+ onBeforeLeave: (el: Element) => {
1007
+ const row = el as HTMLElement
1008
+ row.style.setProperty("--lp-log-row-h", `${row.offsetHeight}px`)
1009
+ },
1010
+ }
1011
+
1012
+ /*
1013
+ * Rows that just arrived while virtualised. The TransitionGroup is off there
1014
+ * (FLIP over thousands of rows is the cost virtualising avoids), but a pushed
1015
+ * line still should not pop in. Only the lines appended by the latest change
1016
+ * are marked, found by where the previous last line sits in the new array, so
1017
+ * a row scrolled into view later, or a whole replaced buffer, never plays it.
1018
+ * A burst taller than the viewport is not worth animating line by line.
1019
+ */
1020
+ const FRESH_CAP = 40
1021
+ const freshLines = shallowRef<WeakSet<LogLine>>(new WeakSet())
1022
+ let lastSeen: LogLine | undefined
1023
+ watch(
1024
+ linesSignal,
1025
+ () => {
1026
+ const lines = props.lines
1027
+ const fresh = new WeakSet<LogLine>()
1028
+ const at = lastSeen ? lines.lastIndexOf(lastSeen) : -1
1029
+ if (at >= 0 && lines.length - 1 - at <= FRESH_CAP) {
1030
+ for (let i = at + 1; i < lines.length; i++) fresh.add(lines[i])
1031
+ }
1032
+ lastSeen = lines[lines.length - 1]
1033
+ freshLines.value = fresh
1034
+ },
1035
+ { immediate: true },
1036
+ )
1037
+ function isFresh(n: number): boolean {
1038
+ const line = sourceLines.value[n]
1039
+ return virtualise.value && !!line && freshLines.value.has(line)
854
1040
  }
855
1041
 
856
1042
  // The viewer draws its own card frame and hides its overflow; a consumer
@@ -872,6 +1058,10 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(() =>
872
1058
  v-bind="rest"
873
1059
  @pointerenter="hovered = true"
874
1060
  @pointerleave="hovered = false"
1061
+ @wheel.passive="onWheel"
1062
+ @touchstart.passive="hold"
1063
+ @pointerdown="hold"
1064
+ @keydown="onKeydown"
875
1065
  >
876
1066
  <!-- Says which state it is in, because a stream that has simply gone quiet
877
1067
  looks exactly like a frozen one. -->
@@ -893,32 +1083,24 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(() =>
893
1083
  v-if="toolbar"
894
1084
  class="flex flex-wrap items-center gap-2 border-b border-line px-2 py-1.5 font-sans"
895
1085
  >
896
- <div class="flex min-w-48 flex-1 items-center gap-1.5 rounded-control bg-surface-soft px-2 focus-within:ring-2 focus-within:ring-ring">
897
- <LpIcon name="lucide:search" :size="14" class="shrink-0 text-muted" />
898
- <input
899
- ref="searchEl"
900
- v-model="query"
901
- type="search"
902
- :aria-label="text.search"
903
- :placeholder="text.search"
904
- class="h-7 min-w-0 flex-1 bg-transparent text-xs text-ink outline-none placeholder:text-muted [&::-webkit-search-cancel-button]:hidden"
905
- @keydown="onSearchKeydown"
906
- />
907
- <span
908
- v-if="term"
909
- class="shrink-0 text-[11px] tabular-nums text-muted"
910
- aria-live="polite"
911
- >{{ matchLabel }}</span>
912
- <button
913
- v-if="query"
914
- type="button"
915
- class="rounded-xs p-0.5 text-muted outline-none hover:text-ink focus-visible:ring-2 focus-visible:ring-ring"
916
- :aria-label="text.clearSearch"
917
- @click="query = ''; searchEl?.focus()"
918
- >
919
- <LpIcon name="lucide:x" :size="12" />
920
- </button>
921
- </div>
1086
+ <LpInput
1087
+ ref="searchEl"
1088
+ v-model="query"
1089
+ type="search"
1090
+ size="sm"
1091
+ icon="lucide:search"
1092
+ clearable
1093
+ class="min-w-48 flex-1"
1094
+ :aria-label="text.search"
1095
+ :placeholder="text.search"
1096
+ :labels="{ clear: text.clearSearch }"
1097
+ @keydown="onSearchKeydown"
1098
+ >
1099
+ <template #trailing>
1100
+ <span v-if="term" class="shrink-0 text-[11px] tabular-nums text-muted" aria-live="polite">{{ matchLabel }}</span>
1101
+ </template>
1102
+ </LpInput>
1103
+
922
1104
  <div class="flex items-center">
923
1105
  <button
924
1106
  type="button"
@@ -988,8 +1170,10 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(() =>
988
1170
  v-if="loadingOlder"
989
1171
  class="flex items-center justify-center gap-2 py-2 text-muted"
990
1172
  >
991
- <LpIcon name="lucide:loader-circle" :size="14" class="animate-spin" />
992
- <span class="text-[11px]">{{ text.loadingOlder }}</span>
1173
+ <!-- The loader speaks the row's words; the visible caption is hidden
1174
+ from screen readers so they are not read twice. -->
1175
+ <LpLoader size="inline" :delay="0" :labels="{ loading: text.loadingOlder }" class="text-[14px]" />
1176
+ <span class="text-[11px]" aria-hidden="true">{{ text.loadingOlder }}</span>
993
1177
  </div>
994
1178
 
995
1179
  <!-- ONE context menu wraps the whole list (not each row): @contextmenu
@@ -1026,7 +1210,7 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(() =>
1026
1210
  :key="lineKey(n)"
1027
1211
  :data-log-row="n"
1028
1212
  class="group relative flex items-start gap-0 px-0 leading-5 transition-colors hover:bg-surface-soft/60"
1029
- :class="[metaFor(line.level).sel, n === currentRow ? 'bg-accent/15' : '']"
1213
+ :class="[metaFor(line.level).sel, n === currentRow ? 'bg-accent/15' : '', isFresh(n) ? 'lp-log-row-fresh' : '']"
1030
1214
  :aria-current="n === currentRow ? 'true' : undefined"
1031
1215
  >
1032
1216
  <!-- level rail -->
@@ -1091,12 +1275,13 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(() =>
1091
1275
  enter-active-class="transition duration-[var(--duration-medium)] ease-[var(--ease-emphasized)]"
1092
1276
  enter-from-class="scale-50 opacity-0"
1093
1277
  >
1094
- <span
1278
+ <LpBadge
1095
1279
  v-if="count > 1"
1096
1280
  :key="count"
1097
- class="ml-2 inline-block select-none rounded-pill bg-surface-soft px-1.5 align-[1px] text-[10px] font-semibold tabular-nums text-muted-strong"
1281
+ size="sm"
1282
+ class="ml-2 select-none tabular-nums"
1098
1283
  :title="text.identical.replace('{n}', String(count))"
1099
- >×{{ count }}</span>
1284
+ >×{{ count }}</LpBadge>
1100
1285
  </Transition>
1101
1286
  </span>
1102
1287
  </li>
@@ -1137,3 +1322,47 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(() =>
1137
1322
  </Transition>
1138
1323
  </div>
1139
1324
  </template>
1325
+
1326
+ <style>
1327
+ /*
1328
+ * Unscoped and namespaced, like LpRollingText: Vue applies these to the row
1329
+ * while it leaves, and an unlayered rule is also what lets them outrank the
1330
+ * row's own `transition-colors` utility (see `transitionProps`).
1331
+ */
1332
+ /* Rises into place from just below, the direction a tail grows in (the kit's rise-in). */
1333
+ .lp-log-row-enter-active,
1334
+ .lp-log-row-fresh {
1335
+ --rise: 6px;
1336
+ animation: rise-in var(--duration-medium) var(--ease-emphasized);
1337
+ }
1338
+
1339
+ .lp-log-row-leave-active {
1340
+ overflow: hidden;
1341
+ animation: lp-log-row-out var(--duration-medium) var(--ease-emphasized) forwards;
1342
+ }
1343
+
1344
+ .lp-log-row-move {
1345
+ transition: transform var(--duration-medium) var(--ease-emphasized);
1346
+ }
1347
+
1348
+ @keyframes lp-log-row-out {
1349
+ from {
1350
+ height: var(--lp-log-row-h, 1.25rem);
1351
+ }
1352
+ to {
1353
+ height: 0;
1354
+ opacity: 0;
1355
+ }
1356
+ }
1357
+
1358
+ @media (prefers-reduced-motion: reduce) {
1359
+ .lp-log-row-enter-active,
1360
+ .lp-log-row-fresh,
1361
+ .lp-log-row-leave-active {
1362
+ animation: none;
1363
+ }
1364
+ .lp-log-row-move {
1365
+ transition: none;
1366
+ }
1367
+ }
1368
+ </style>