@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,139 @@
1
+ <script lang="ts">
2
+ // The root class is merged with the consumer's (useMergedAttrs).
3
+ export default { inheritAttrs: false }
4
+ </script>
5
+
6
+ <script setup lang="ts">
7
+ /*
8
+ * Accent text with light moving through it.
9
+ *
10
+ * Two looks, for two jobs:
11
+ *
12
+ * "shine" — the text keeps its tone and a soft band sweeps across it now
13
+ * and then. Draws the eye to one word without changing what it says: a
14
+ * "New" next to a menu item, the plan name on an upgrade card, a status
15
+ * that is still working ("Deploying…").
16
+ * "gradient" — the text is painted with the theme's brand, accent and action
17
+ * colours drifting across it. A display headline, a logo word.
18
+ *
19
+ * <LpShinyText>Pro</LpShinyText>
20
+ * <LpShinyText variant="gradient" as="h1" class="text-4xl font-bold">Leave Pulse</LpShinyText>
21
+ *
22
+ * Pure CSS: the text is clipped to an animated background. The sheen moves
23
+ * toward the theme's ink, not toward white, so it lightens the text on a dark
24
+ * theme and darkens it on a light one and the word never washes out into the
25
+ * page. The loop pauses while the text is off screen or the tab is hidden;
26
+ * under reduced motion it stands still (the gradient stays, the sheen goes).
27
+ */
28
+ import { computed } from "vue"
29
+ import { useInView } from "../composables/useInView"
30
+ import { useMergedAttrs } from "../composables/useMergedClass"
31
+ import { toneLook, type ToneName } from "./tone"
32
+
33
+ const props = withDefaults(
34
+ defineProps<{
35
+ /** `shine` sweeps a band over toned text; `gradient` paints it with drifting theme colours. */
36
+ variant?: "shine" | "gradient"
37
+ /** Base colour for `shine`. `ink` sweeps the brand colour over plain text. */
38
+ tone?: ToneName | "ink"
39
+ /** Seconds per sweep. Slower reads as ambient; under ~1.5 s it starts to nag. */
40
+ speed?: number
41
+ /** Stop the motion (keeps the look). For a word that should only shine while something is happening. */
42
+ paused?: boolean
43
+ /** Element to render. */
44
+ as?: string
45
+ }>(),
46
+ { variant: "shine", tone: "brand", speed: 3, paused: false, as: "span" },
47
+ )
48
+
49
+ const { el, inView } = useInView()
50
+ const { class: rootClass, attrs: rest } = useMergedAttrs(() => `lp-shiny lp-shiny--${props.variant}`)
51
+
52
+ const style = computed(() => {
53
+ const base = props.tone === "ink" ? "var(--color-ink)" : toneLook(props.tone).color
54
+ return {
55
+ "--lp-shiny-base": base,
56
+ // Toward ink, so the band is the contrast direction in either theme; plain
57
+ // ink text gets a brand band instead, since ink toward ink is no band.
58
+ "--lp-shiny-sheen":
59
+ props.tone === "ink" ? "var(--color-brand)" : `color-mix(in oklab, ${base}, var(--color-ink) 65%)`,
60
+ "--lp-shiny-speed": `${Math.max(0.3, props.speed)}s`,
61
+ animationPlayState: props.paused || !inView.value ? "paused" : "running",
62
+ }
63
+ })
64
+ </script>
65
+
66
+ <template>
67
+ <component :is="as" ref="el" :class="rootClass" :style="style" v-bind="rest">
68
+ <slot />
69
+ </component>
70
+ </template>
71
+
72
+ <style>
73
+ .lp-shiny {
74
+ color: var(--lp-shiny-base);
75
+ background-repeat: repeat-x;
76
+ -webkit-background-clip: text;
77
+ background-clip: text;
78
+ -webkit-text-fill-color: transparent;
79
+ /* Descenders and italics poke out of the content box; the clip follows the
80
+ background box, so give it room instead of cutting a tail off. */
81
+ padding-block: 0.08em;
82
+ animation: lp-shiny-move var(--lp-shiny-speed) linear infinite;
83
+ }
84
+
85
+ .lp-shiny--shine {
86
+ /* The band is a third of a 300% wide image; the image moves by its own
87
+ width, so the band crosses the text and then rests off to the side for
88
+ a while, which is what makes it an occasional glint and not a strobe. */
89
+ background-image: linear-gradient(
90
+ 105deg,
91
+ var(--lp-shiny-base) 0%,
92
+ var(--lp-shiny-base) 40%,
93
+ var(--lp-shiny-sheen) 50%,
94
+ var(--lp-shiny-base) 60%,
95
+ var(--lp-shiny-base) 100%
96
+ );
97
+ background-size: 300% 100%;
98
+ }
99
+
100
+ .lp-shiny--gradient {
101
+ /* First and last stops match, so the repeat has no seam as it drifts. */
102
+ background-image: linear-gradient(
103
+ 90deg,
104
+ var(--color-brand),
105
+ var(--color-accent),
106
+ var(--color-action),
107
+ var(--color-brand)
108
+ );
109
+ background-size: 200% 100%;
110
+ }
111
+
112
+ @keyframes lp-shiny-move {
113
+ from {
114
+ background-position: 100% 0;
115
+ }
116
+ to {
117
+ background-position: -200% 0;
118
+ }
119
+ }
120
+
121
+ .lp-shiny--gradient {
122
+ animation-name: lp-shiny-drift;
123
+ }
124
+
125
+ @keyframes lp-shiny-drift {
126
+ from {
127
+ background-position: 0% 0;
128
+ }
129
+ to {
130
+ background-position: -200% 0;
131
+ }
132
+ }
133
+
134
+ @media (prefers-reduced-motion: reduce) {
135
+ .lp-shiny {
136
+ animation: none;
137
+ }
138
+ }
139
+ </style>
@@ -320,6 +320,7 @@ defineOptions({ inheritAttrs: false })
320
320
  v-model="query"
321
321
  size="sm"
322
322
  icon="lucide:search"
323
+ clearable
323
324
  class="mb-2 shrink-0"
324
325
  :placeholder="placeholder"
325
326
  :aria-label="placeholder"
@@ -380,6 +381,7 @@ defineOptions({ inheritAttrs: false })
380
381
  v-model="query"
381
382
  size="sm"
382
383
  icon="lucide:search"
384
+ clearable
383
385
  class="mb-2 shrink-0"
384
386
  :placeholder="placeholder"
385
387
  :aria-label="placeholder"
@@ -11,6 +11,7 @@ export default { inheritAttrs: false }
11
11
  import { SliderRange, SliderRoot, SliderThumb, SliderTrack } from "reka-ui"
12
12
  import { useFieldControl } from "../composables/useField"
13
13
  import { useMergedAttrs } from "../composables/useMergedClass"
14
+ import { SLIDER_GLIDE, useSliderDrag } from "./slider"
14
15
 
15
16
  const props = withDefaults(
16
17
  defineProps<{
@@ -43,8 +44,9 @@ const field = useFieldControl(() => ({ wrapped: false, disabled: props.disabled
43
44
 
44
45
  // A slider is full-width by default; putting one in a toolbar means constraining it, and a fixed h-5 has to yield to a denser row.
45
46
  const { class: rootClass, attrs: rest } = useMergedAttrs(
46
- "relative flex h-5 w-full touch-none select-none items-center data-[disabled]:opacity-55",
47
+ `relative flex h-5 w-full touch-none select-none items-center data-[disabled]:opacity-55 ${SLIDER_GLIDE}`,
47
48
  )
49
+ const { dragging, onPointerDown } = useSliderDrag()
48
50
  </script>
49
51
 
50
52
  <template>
@@ -56,6 +58,8 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(
56
58
  :disabled="field.disabled"
57
59
  :class="rootClass"
58
60
  v-bind="rest"
61
+ :data-dragging="dragging || undefined"
62
+ @pointerdown="onPointerDown"
59
63
  @update:model-value="onUpdate"
60
64
  @value-commit="onCommit"
61
65
  >
@@ -19,8 +19,10 @@ import LpSkeleton from "./LpSkeleton.vue"
19
19
  import { sampleValues } from "./chartSkeleton"
20
20
  import { useSample } from "../composables/useSample"
21
21
  import { useReveal } from "../composables/useReveal"
22
+ import { mixValues, useTween } from "../composables/useTween"
22
23
  import { useLabels } from "../composables/useLpConfig"
23
24
  import { areaPath, extent, linePath, normalise, type Box } from "./chart"
25
+ import { toneLook, type ToneName } from "./tone"
24
26
 
25
27
  const props = withDefaults(
26
28
  defineProps<{
@@ -32,7 +34,7 @@ const props = withDefaults(
32
34
  /** Any CSS colour. Defaults to the brand token. */
33
35
  color?: string
34
36
  /** Named theme tones, for callers that don't want to spell a var(). */
35
- tone?: "brand" | "action" | "danger" | "accent" | "muted"
37
+ tone?: ToneName
36
38
  /** Fill under the line. */
37
39
  area?: boolean
38
40
  /** Curve tension, as in LpChart. 0 draws a polyline. */
@@ -77,15 +79,23 @@ const props = withDefaults(
77
79
  { width: 84, height: 24, tone: "brand", smooth: 0.9, animate: true, duration: 900, sample: true },
78
80
  )
79
81
 
80
- const TONE: Record<string, string> = {
81
- brand: "var(--color-brand)",
82
- action: "var(--color-action)",
83
- danger: "var(--color-danger)",
84
- accent: "var(--color-accent)",
85
- muted: "var(--color-muted)",
86
- }
82
+ const stroke = computed(() => props.color ?? toneLook(props.tone).color)
83
+
84
+ /*
85
+ * The sweep is held until the svg is actually on screen. Forty of these sit in
86
+ * a list, most of them below the fold; started on mount they would all have
87
+ * finished before the rows carrying them were ever scrolled to.
88
+ */
89
+ const { el, revealed } = useReveal({ immediate: () => !props.animate })
87
90
 
88
- const stroke = computed(() => props.color ?? TONE[props.tone])
91
+ // The stub holds the place when there is nothing to draw, so the sample can
92
+ // still find the hint it sits in.
93
+ const stub = ref<Element | null>(null)
94
+ const sampling = useSample(
95
+ computed(() => el.value ?? stub.value),
96
+ () => !props.loading && !props.data.some((v) => v != null),
97
+ () => props.sample,
98
+ )
89
99
 
90
100
  const data = computed(() => (sampling.value ? sampleValues(props.data.length || 12) : props.data))
91
101
 
@@ -116,32 +126,56 @@ const bounds = computed(() => {
116
126
  return { min: props.min ?? auto.min, max: props.max ?? auto.max }
117
127
  })
118
128
 
129
+ /*
130
+ * What is DRAWN: each reading as its height in the box, 0 at the bottom and 1
131
+ * at the top, travelling from the last line to the new one.
132
+ *
133
+ * Heights, not raw values, because the range moves with the data. New values
134
+ * on the old range overshoot the box and old values on the new range redraw the
135
+ * line at another height, and tweening values and range side by side has a
136
+ * blind spot of its own: when the new range collapses (a flat series), values
137
+ * and range shrink in proportion, the line holds its old shape the whole way
138
+ * and then drops on the last frame. Heights are already on the range, so a
139
+ * frame partway is a line partway, whatever happened to the scale.
140
+ */
141
+ const heights = computed(() => {
142
+ const { min, max } = bounds.value
143
+ const span = max - min || 1
144
+ return series.value[0].values.map((v) => (v == null ? null : (v - min) / span))
145
+ })
146
+
147
+ const shown = useTween(() => heights.value, mixValues, {
148
+ /*
149
+ * Only a line already on screen morphs. Before it is revealed the draw-on
150
+ * is still to come, and while the loading band or the stub stands in (`el`
151
+ * unset) the line will mount fresh and draw itself in — a morph from
152
+ * readings nobody saw would only blur that entrance.
153
+ */
154
+ enabled: () => props.animate && revealed.value && !!el.value,
155
+ })
156
+
119
157
  const geo = computed(() => ({
120
- min: bounds.value.min,
121
- max: bounds.value.max,
158
+ min: 0,
159
+ max: 1,
122
160
  box: box.value,
123
- count: data.value.length,
161
+ count: shown.value.length,
124
162
  banded: false,
125
163
  }))
126
164
 
127
- const d = computed(() => linePath(series.value[0].values, geo.value, props.smooth))
128
- const fill = computed(() =>
129
- props.area ? areaPath(series.value[0].values, geo.value, props.smooth) : "",
130
- )
165
+ const d = computed(() => linePath(shown.value, geo.value, props.smooth))
166
+ const fill = computed(() => (props.area ? areaPath(shown.value, geo.value, props.smooth) : ""))
131
167
 
132
168
  /** Last point that actually has a value — the dot goes there, not on a gap. */
133
169
  const lastPoint = computed(() => {
134
- const values = series.value[0].values
170
+ const values = shown.value
135
171
  for (let i = values.length - 1; i >= 0; i--) {
136
172
  const v = values[i]
137
173
  if (v == null) continue
138
- const span = bounds.value.max - bounds.value.min || 1
139
174
  const w = props.width - PAD * 2
140
175
  const h = props.height - PAD * 2
141
176
  return {
142
- x: data.value.length <= 1 ? PAD + w / 2 : PAD + (w / (data.value.length - 1)) * i,
143
- y: PAD + h - ((v - bounds.value.min) / span) * h,
144
- v,
177
+ x: values.length <= 1 ? PAD + w / 2 : PAD + (w / (values.length - 1)) * i,
178
+ y: PAD + h - v * h,
145
179
  }
146
180
  }
147
181
  return null
@@ -186,22 +220,6 @@ const pathLength = computed(() => {
186
220
  return Math.ceil(segment * n + 4)
187
221
  })
188
222
 
189
- /*
190
- * The sweep is held until the svg is actually on screen. Forty of these sit in
191
- * a list, most of them below the fold; started on mount they would all have
192
- * finished before the rows carrying them were ever scrolled to.
193
- */
194
- const { el, revealed } = useReveal({ immediate: () => !props.animate })
195
-
196
- // The stub holds the place when there is nothing to draw, so the sample can
197
- // still find the hint it sits in.
198
- const stub = ref<Element | null>(null)
199
- const sampling = useSample(
200
- computed(() => el.value ?? stub.value),
201
- () => !props.loading && !props.data.some((v) => v != null),
202
- () => props.sample,
203
- )
204
-
205
223
  const revealStyle = computed(() =>
206
224
  props.animate
207
225
  ? {
@@ -0,0 +1,51 @@
1
+ <script lang="ts">
2
+ export default { inheritAttrs: false }
3
+ </script>
4
+
5
+ <script setup lang="ts">
6
+ /*
7
+ * LpSpotlight — a soft glow that follows the pointer inside whatever it wraps.
8
+ *
9
+ * <LpSpotlight class="rounded-card"><MyTile /></LpSpotlight>
10
+ *
11
+ * For a grid of tiles the eye should scan with the mouse: the lit one is the
12
+ * one about to be clicked, without a hover border shouting it. LpCard has the
13
+ * same effect as its `spotlight` prop; reach for this wrapper around anything
14
+ * that is not a card. Mouse only; reduced motion draws nothing. The glow is
15
+ * painted by `.lp-spotlight` in tokens/effects.css.
16
+ */
17
+ import { computed } from "vue"
18
+ import { useMergedAttrs } from "../composables/useMergedClass"
19
+ import { useSpotlight } from "../composables/useSpotlight"
20
+
21
+ const props = withDefaults(
22
+ defineProps<{
23
+ /** Any CSS colour. Defaults to the brand colour, so it follows the theme. */
24
+ color?: string
25
+ /** Diameter of the lit circle, in px. Larger reads as ambient, smaller as a torch. */
26
+ size?: number
27
+ /** How much of the colour mixes in, 0–100. Keep it low on text-heavy surfaces. */
28
+ strength?: number
29
+ /** Keep the wrapper but draw nothing — for a tile that is disabled or busy. */
30
+ disabled?: boolean
31
+ /** Element to render as. */
32
+ as?: string
33
+ }>(),
34
+ { size: 280, strength: 18, disabled: false, as: "div" },
35
+ )
36
+
37
+ const { el } = useSpotlight({ disabled: () => props.disabled })
38
+ const { class: classes, attrs: rest } = useMergedAttrs(() => "lp-spotlight rounded-card")
39
+
40
+ const style = computed(() => ({
41
+ "--lp-spot-size": `${props.size}px`,
42
+ "--lp-spot-strength": `${Math.min(100, Math.max(0, props.strength))}%`,
43
+ ...(props.color ? { "--lp-spot-color": props.color } : {}),
44
+ }))
45
+ </script>
46
+
47
+ <template>
48
+ <component :is="as" ref="el" :class="classes" :style="style" v-bind="rest">
49
+ <slot />
50
+ </component>
51
+ </template>
@@ -12,7 +12,9 @@ import { computed } from "vue"
12
12
  import LpIcon from "./LpIcon.vue"
13
13
  import LpNumberFlow from "./LpNumberFlow.vue"
14
14
  import LpSkeleton from "./LpSkeleton.vue"
15
+ import LpStatus from "./LpStatus.vue"
15
16
  import { useMergedAttrs } from "../composables/useMergedClass"
17
+ import { TONES } from "./tone"
16
18
 
17
19
  const props = withDefaults(
18
20
  defineProps<{
@@ -77,7 +79,7 @@ const trendIcon = computed(() =>
77
79
  const trendColor = computed(() => {
78
80
  if (dir.value === "flat") return "text-muted"
79
81
  const good = props.invertTrend ? dir.value === "down" : dir.value === "up"
80
- return good ? "text-action" : "text-danger"
82
+ return good ? TONES.success.text : TONES.danger.text
81
83
  })
82
84
 
83
85
  // Numeric delta gets an explicit sign; string deltas are shown as given.
@@ -128,7 +130,9 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(
128
130
  :class="rootClass"
129
131
  v-bind="rest">
130
132
  <div class="flex items-center gap-2">
131
- <span v-if="online" class="size-1.5 rounded-full bg-action" />
133
+ <!-- The kit's own "online" light, so a live tile reads (and is spoken)
134
+ the same as a live server row elsewhere on the page. -->
135
+ <LpStatus v-if="online" state="online" size="sm" hide-label />
132
136
  <LpIcon v-if="icon" :name="icon" :size="14" class="text-muted" />
133
137
  <span class="text-[11px] font-semibold uppercase tracking-[0.08em] text-muted">
134
138
  <Transition v-bind="FADE">
@@ -0,0 +1,127 @@
1
+ <script lang="ts">
2
+ // The consumer's `class` is merged into the root's own rather than appended to
3
+ // it, so opt out of the automatic pass-through that would add it unmerged.
4
+ export default { inheritAttrs: false }
5
+ </script>
6
+
7
+ <script setup lang="ts">
8
+ /*
9
+ * What state something is in, as a light and a word: a server online, a bot
10
+ * starting, a region degraded.
11
+ *
12
+ * Not LpBadge with a dot. A badge is a label whose text is the point and whose
13
+ * dot is decoration; here the STATE is the point and the caller passes a state,
14
+ * not a colour and a word. The light, the word, the pulse and the spoken text
15
+ * all follow from it, so every status in an app looks and sounds the same, and
16
+ * a change of state (starting → online) reads as one thing changing: the light
17
+ * crossfades, the word rolls, the pulse starts or stops.
18
+ */
19
+ import { computed } from "vue"
20
+ import { useLabels } from "../composables/useLpConfig"
21
+ import { useMergedAttrs } from "../composables/useMergedClass"
22
+ import LpBadge from "./LpBadge.vue"
23
+ import LpRollingText from "./LpRollingText.vue"
24
+ import LpShift from "./LpShift.vue"
25
+ import { TONE_COLOR, type MeterTone } from "./meter"
26
+ import { STATUS_LABELS, STATUS_LOOK, type StatusKind } from "./status"
27
+
28
+ const props = withDefaults(
29
+ defineProps<{
30
+ state: StatusKind
31
+ /** The word shown, when the state's own name is not the right one ("Ready", "In a match"). */
32
+ label?: string
33
+ /** Overrides the state's tone, for an app whose "offline" is an alarm rather than a rest state. */
34
+ tone?: MeterTone
35
+ /** Overrides whether the light pulses. */
36
+ pulse?: boolean
37
+ /**
38
+ * `inline` (default) is a light and a word in running text or a table cell;
39
+ * `pill` puts them on a chip, which is LpBadge's own: the chip is the
40
+ * badge, the state (light, word, pulse, tone) is what this adds to it.
41
+ */
42
+ variant?: "inline" | "pill"
43
+ size?: "sm" | "md"
44
+ /**
45
+ * Light only. The word is still there for screen readers and as a native
46
+ * hint on hover, so a dense list can drop it visually without going silent.
47
+ */
48
+ hideLabel?: boolean
49
+ /**
50
+ * Speak changes as they happen (`role="status"`). Off by default: a table
51
+ * of twenty servers announcing each flip would drown everything else.
52
+ * Turn it on for the one status the user is waiting on.
53
+ */
54
+ announce?: boolean
55
+ labels?: Partial<Record<StatusKind, string>>
56
+ }>(),
57
+ { variant: "inline", size: "md", hideLabel: false, announce: false, pulse: undefined },
58
+ )
59
+
60
+ const names = useLabels<Record<StatusKind, string>>("status", STATUS_LABELS, () => props.labels)
61
+
62
+ const look = computed(() => STATUS_LOOK[props.state] ?? STATUS_LOOK.unknown)
63
+ const tone = computed(() => props.tone ?? look.value.tone)
64
+ const pulsing = computed(() => props.pulse ?? look.value.pulse)
65
+ const word = computed(() => props.label ?? names.value[props.state] ?? props.state)
66
+
67
+ const { class: rootClass, attrs: rest } = useMergedAttrs(() =>
68
+ props.variant === "pill"
69
+ ? ""
70
+ : [
71
+ "inline-flex shrink-0 items-center align-middle font-medium leading-[1.2] whitespace-nowrap text-muted-strong",
72
+ props.size === "sm" ? "gap-1.5 text-[11px]" : "gap-2 text-xs",
73
+ ].join(" "),
74
+ )
75
+
76
+
77
+ const dotSize = computed(() => (props.size === "sm" ? "size-1.5" : "size-2"))
78
+ </script>
79
+
80
+ <template>
81
+ <component
82
+ :is="variant === 'pill' ? LpBadge : 'span'"
83
+ :role="announce ? 'status' : undefined"
84
+ :title="hideLabel ? word : undefined"
85
+ :class="rootClass"
86
+ v-bind="variant === 'pill' ? { ...rest, tone, size } : rest"
87
+ >
88
+ <span class="relative inline-flex shrink-0" :class="dotSize" aria-hidden="true">
89
+ <!-- The halo is the same colour as the light and scales out from it, so
90
+ it stays in step with a tone change instead of lagging a beat. -->
91
+ <span
92
+ class="lp-status-halo absolute inset-0 rounded-full transition-[background-color,opacity] duration-(--duration-medium)"
93
+ :class="pulsing ? 'lp-status-halo--on' : 'opacity-0'"
94
+ :style="{ backgroundColor: TONE_COLOR[tone] }"
95
+ />
96
+ <span
97
+ class="relative inline-flex size-full rounded-full transition-[background-color] duration-(--duration-medium) ease-(--ease-emphasized) motion-reduce:transition-none"
98
+ :style="{ backgroundColor: TONE_COLOR[tone] }"
99
+ />
100
+ </span>
101
+ <span v-if="hideLabel" class="sr-only">{{ word }}</span>
102
+ <LpRollingText v-else-if="variant === 'pill'" :value="word" align="start" />
103
+ <LpShift v-else axis="width">
104
+ <LpRollingText :value="word" align="start" />
105
+ </LpShift>
106
+ </component>
107
+ </template>
108
+
109
+ <style>
110
+ /*
111
+ * Unscoped and namespaced, like LpSkeleton's pulse. The keyframe is the kit's
112
+ * halo (tokens.css): one animation name keeps every live light on a page
113
+ * breathing in phase, because CSS animations are timed against the document
114
+ * rather than against when each one mounted. A column of servers pulsing out
115
+ * of step reads as flicker. A small light swells to 2.6x, the halo's default.
116
+ */
117
+ .lp-status-halo--on {
118
+ animation: lp-halo 2s cubic-bezier(0, 0, 0.2, 1) infinite;
119
+ }
120
+
121
+ @media (prefers-reduced-motion: reduce) {
122
+ .lp-status-halo--on {
123
+ animation: none;
124
+ opacity: 0;
125
+ }
126
+ }
127
+ </style>
@@ -0,0 +1,138 @@
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 state of one job as a round glyph: hollow while it waits, spinning while
11
+ * it runs, a tick, a cross, a dash for skipped, a slash for cancelled.
12
+ *
13
+ * LpPipeline draws its steps with it, and it stands alone wherever a single
14
+ * job's state sits next to its name: a row in a deploys table, a check in a
15
+ * list, a toast about a build. A change of status is a change the viewer is
16
+ * waiting for, so it shows as one: the colours ease, the glyph flips to the
17
+ * new one (LpRollingText), and a running mark breathes a halo so it reads as
18
+ * live even while the spinner is small.
19
+ *
20
+ * Decorative by default (the text next to it says the state); pass `label`
21
+ * when the mark is all there is.
22
+ *
23
+ * `variant="step"` is the same mark as a wizard draws it (LpStepper): the
24
+ * step you are on is a brand ring with its number (`status="current"`), a
25
+ * finished one is filled with the brand colour rather than the "passed"
26
+ * green, and the ones ahead are a quiet ring with no fill of their own.
27
+ */
28
+ import { computed } from "vue"
29
+ import { useMergedAttrs } from "../composables/useMergedClass"
30
+ import LpIcon from "./LpIcon.vue"
31
+ import LpLoader from "./LpLoader.vue"
32
+ import LpRollingText from "./LpRollingText.vue"
33
+ import type { StepStatus } from "./pipeline"
34
+ import { TONES } from "./tone"
35
+
36
+ /** A job's state, plus `current`: the step a person is on in a flow they drive. */
37
+ export type StepMarkStatus = StepStatus | "current"
38
+
39
+ const props = withDefaults(
40
+ defineProps<{
41
+ status: StepMarkStatus
42
+ /** `status` (default) colours a job's outcome; `step` is a wizard's step (see above). */
43
+ variant?: "status" | "step"
44
+ size?: "sm" | "md" | "lg"
45
+ /** Shown inside a pending mark: the step's number in a numbered flow. */
46
+ number?: number | string
47
+ /** Shown inside a pending mark instead of the number. */
48
+ icon?: string
49
+ /** Accessible name; without it the mark is hidden from assistive tech. */
50
+ label?: string
51
+ }>(),
52
+ { variant: "status", size: "md" },
53
+ )
54
+
55
+ const BOX = { sm: "size-4 text-[9px]", md: "size-6 text-[11px]", lg: "size-8 text-xs" }
56
+ const GLYPH = { sm: 10, md: 14, lg: 18 }
57
+
58
+ // Outcomes in the kit's tones (tone.ts): a ring for what is under way, a solid
59
+ // disc for what is decided. The quiet states are greys, not tones.
60
+ const TONE: Record<StepMarkStatus, string> = {
61
+ pending: "border-line-strong bg-surface text-muted",
62
+ current: `bg-surface ${TONES.brand.border} ${TONES.brand.text}`,
63
+ running: `${TONES.brand.border} ${TONES.brand.chip}`,
64
+ success: `border-transparent text-ink-inverse ${TONES.success.bg}`,
65
+ failed: `border-transparent text-ink-inverse ${TONES.danger.bg}`,
66
+ skipped: "border-dashed border-line-strong bg-surface text-muted",
67
+ cancelled: "border-line-strong bg-surface-soft text-muted-strong",
68
+ }
69
+
70
+ // A wizard's step sits on whatever surface the form has, so only its ring and number are its own.
71
+ const STEP_TONE: Partial<Record<StepMarkStatus, string>> = {
72
+ pending: "border-line text-muted",
73
+ current: `${TONES.brand.border} ${TONES.brand.text}`,
74
+ success: `border-transparent text-ink-inverse ${TONES.brand.bg}`,
75
+ }
76
+
77
+ const ICON: Partial<Record<StepMarkStatus, string>> = {
78
+ success: "lucide:check",
79
+ failed: "lucide:x",
80
+ skipped: "lucide:minus",
81
+ cancelled: "lucide:slash",
82
+ }
83
+
84
+ /*
85
+ * What the glyph shows, as one value the roll keys on: a status change flips
86
+ * it, a pending step's number changing (a reordered flow) flips it too.
87
+ */
88
+ const glyph = computed(() => {
89
+ // Pending and current show the same thing, so arriving at a step keeps its number in place.
90
+ if (props.status !== "pending" && props.status !== "current") return props.status
91
+ if (props.icon) return "icon"
92
+ return props.number !== undefined ? `n:${props.number}` : "pending"
93
+ })
94
+
95
+ const { class: rootClass, attrs: rest } = useMergedAttrs(() =>
96
+ `relative inline-flex shrink-0 items-center justify-center rounded-pill border font-semibold tabular-nums transition-[color,background-color,border-color] duration-(--duration-medium) ease-(--ease-emphasized) motion-reduce:transition-none ${BOX[props.size]} ${(props.variant === "step" && STEP_TONE[props.status]) || TONE[props.status]}`,
97
+ )
98
+ </script>
99
+
100
+ <template>
101
+ <span
102
+ :class="rootClass"
103
+ :role="label ? 'img' : undefined"
104
+ :aria-label="label || undefined"
105
+ :aria-hidden="label ? undefined : 'true'"
106
+ :data-status="status"
107
+ v-bind="rest"
108
+ >
109
+ <span v-if="status === 'running'" class="lp-step-halo pointer-events-none absolute -inset-px rounded-pill border border-brand" />
110
+ <LpRollingText mode="flip" :duration="260" :value="glyph">
111
+ <template #default="{ value }">
112
+ <LpLoader
113
+ v-if="value === 'running'"
114
+ :delay="0"
115
+ :min-visible="0"
116
+ size="inline"
117
+ :class="size === 'sm' ? 'text-[10px]' : size === 'md' ? 'text-sm' : 'text-lg'"
118
+ />
119
+ <LpIcon v-else-if="ICON[value as StepMarkStatus]" :name="ICON[value as StepMarkStatus]!" :size="GLYPH[size]" />
120
+ <LpIcon v-else-if="value === 'icon' && icon" :name="icon" :size="variant === 'step' ? GLYPH[size] : GLYPH[size] - 2" />
121
+ <template v-else-if="String(value).startsWith('n:')">{{ number }}</template>
122
+ <!-- An empty slot would fall back to printing the raw key. -->
123
+ <span v-else class="block size-0" />
124
+ </template>
125
+ </LpRollingText>
126
+ </span>
127
+ </template>
128
+
129
+ <style>
130
+ /* The kit's halo (tokens.css), swelling less: this ring already starts at the mark's own size. */
131
+ .lp-step-halo {
132
+ --halo-scale: 1.6;
133
+ animation: lp-halo 1.6s var(--ease-emphasized, ease-out) infinite;
134
+ }
135
+ @media (prefers-reduced-motion: reduce) {
136
+ .lp-step-halo { animation: none; opacity: 0; }
137
+ }
138
+ </style>