@leavepulse/ui 0.69.0 → 0.70.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (634) hide show
  1. package/README.md +37 -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/LpShinyText-D69cBYDR.css +61 -0
  11. package/dist/assets/LpStatus-430OGTZY.css +17 -0
  12. package/dist/assets/LpStepMark-Drvx33Vg.css +10 -0
  13. package/dist/assets/{LpTable-BPERfJIk.css → LpTable-DHxEQ_-3.css} +19 -19
  14. package/dist/assets/LpTabs-BJ-nrJuI.css +18 -0
  15. package/dist/assets/LpTextReveal-DjI1MsDS.css +35 -0
  16. package/dist/assets/LpTypewriter-CXAm9Nca.css +27 -0
  17. package/dist/chunks/AttentionDot-DCBf4aWg.js +25 -0
  18. package/dist/chunks/{ContextMenuItems-B7XFHksm.js → ContextMenuItems-B5uE8Znw.js} +1 -1
  19. package/dist/chunks/{DropzoneLinkField-CjkrpDqO.js → DropzoneLinkField-Bw8Flkhk.js} +2 -2
  20. package/dist/chunks/FieldWrapper-BiennROB.js +43 -0
  21. package/dist/chunks/{LayoutCanvas-DF9CovaK.js → LayoutCanvas-BsJIzhdd.js} +1 -1
  22. package/dist/chunks/{LayoutNode-D9bIFzk0.js → LayoutNode-DJVhkSGk.js} +6 -8
  23. package/dist/chunks/LegendSwatch-BhRjrtzv.js +18 -0
  24. package/dist/chunks/LoaderMark-C1dubiKn.js +85 -0
  25. package/dist/chunks/{LpActionBar-MPKMu3pz.js → LpActionBar-CzOFar5t.js} +14 -20
  26. package/dist/chunks/LpActivityLine-CJvzrNpj.js +95 -0
  27. package/dist/chunks/{LpAddressInput-DG0BTqdH.js → LpAddressInput-CNnLTDZg.js} +7 -7
  28. package/dist/chunks/LpAlert-C5igj802.js +119 -0
  29. package/dist/chunks/{LpAppShell-DPh1756q.js → LpAppShell-CEUAB8kK.js} +15 -16
  30. package/dist/chunks/{LpAutocomplete-Dgn6hw3p.js → LpAutocomplete-D92niDHE.js} +15 -32
  31. package/dist/chunks/{LpAvatar-Bs0Fb1lC.js → LpAvatar-CLPl-qOF.js} +18 -6
  32. package/dist/chunks/LpBadge-HOEPBYmi.js +126 -0
  33. package/dist/chunks/LpBreadcrumbs-DYoPc3P4.js +144 -0
  34. package/dist/chunks/{LpButton-DNR-YAq5.js → LpButton-CVxBfGjd.js} +12 -4
  35. package/dist/chunks/{LpCalendar-BLya39Fh.js → LpCalendar-pVL91-Pl.js} +1 -1
  36. package/dist/chunks/{LpCard-Bf71NXZq.js → LpCard-CqKLnEhl.js} +18 -8
  37. package/dist/chunks/{LpCheckbox-Da5oZPHo.js → LpCheckbox-DHc2bHDe.js} +9 -6
  38. package/dist/chunks/{LpCodeBlock-lLbmslfs.js → LpCodeBlock-BGsQhxw8.js} +24 -32
  39. package/dist/chunks/LpCodeDisplay-CIKKT2iW.js +189 -0
  40. package/dist/chunks/LpCollapse-CWS9M_lm.js +115 -0
  41. package/dist/chunks/{LpColorPicker-DtEfBAcK.js → LpColorPicker-DFugXNUi.js} +10 -5
  42. package/dist/chunks/{LpConfirmDialog-D7s4jakB.js → LpConfirmDialog-CfGCux8m.js} +3 -3
  43. package/dist/chunks/{LpConfirmHost-DrYI5y1K.js → LpConfirmHost-exB7JmcO.js} +1 -1
  44. package/dist/chunks/{LpContextMenu-CRnjoqSt.js → LpContextMenu-COwOwRgI.js} +13 -5
  45. package/dist/chunks/LpCopyButton-DzHjnFs0.js +133 -0
  46. package/dist/chunks/LpCountdown-Dtq1ihlJ.js +231 -0
  47. package/dist/chunks/LpDataList-B-5nHfNw.js +120 -0
  48. package/dist/chunks/LpDatePicker-BUe1VUC0.js +168 -0
  49. package/dist/chunks/LpDateRangePicker-C_k65vGR.js +126 -0
  50. package/dist/chunks/{LpDisclosure-6AplYBub.js → LpDisclosure-DOarzlAG.js} +22 -11
  51. package/dist/chunks/{LpDrawer-Q4SOxM4s.js → LpDrawer-DGNKRsGq.js} +9 -4
  52. package/dist/chunks/{LpDropdownMenu-DWTt0ooM.js → LpDropdownMenu-CRgrhdAH.js} +10 -5
  53. package/dist/chunks/LpEditable-DTqLt2lT.js +236 -0
  54. package/dist/chunks/{LpEmptyState-om1UnFjV.js → LpEmptyState-KTKipws2.js} +1 -1
  55. package/dist/chunks/{LpFieldNotice-CHuDeLjc.js → LpFieldNotice-CurbNuXI.js} +1 -1
  56. package/dist/chunks/{LpFileTree-CW24YsVX.js → LpFileTree-DMISXVHC.js} +5 -3
  57. package/dist/chunks/{LpFileTreeNode-BXhTHaKW.js → LpFileTreeNode-CPXB_Yy3.js} +42 -55
  58. package/dist/chunks/{LpFormField-DPb47HEm.js → LpFormField-BWwgm1E4.js} +23 -9
  59. package/dist/chunks/LpFrame-BVQCQLDI.js +155 -0
  60. package/dist/chunks/LpGauge-Bk8TwJj0.js +204 -0
  61. package/dist/chunks/LpGlowBorder-B8V-QzIl.js +40 -0
  62. package/dist/chunks/{LpHintExample-C1eKYdeL.js → LpHintExample-9Py0wc-L.js} +11 -34
  63. package/dist/chunks/{LpHintLayer-7UOdWQG3.js → LpHintLayer-p4hqzdyA.js} +27 -14
  64. package/dist/chunks/{LpHints-BUtBp9-w.js → LpHints-CCrhRfy9.js} +3 -3
  65. package/dist/chunks/LpHoverCard-spGxyw7T.js +130 -0
  66. package/dist/chunks/{LpIcon-6tSrZ3Zy.js → LpIcon-HJP5xMz4.js} +1 -1
  67. package/dist/chunks/LpIdenticon-BzdC_qz9.js +63 -0
  68. package/dist/chunks/{LpInfraNode-Ds_8SZgN.js → LpInfraNode-CUC3t4na.js} +39 -25
  69. package/dist/chunks/{LpInput-CUyr6PIE.js → LpInput-CDuwODJG.js} +44 -18
  70. package/dist/chunks/{LpLightbox-B9J8rzsj.js → LpLightbox-XJ0LpTcZ.js} +69 -69
  71. package/dist/chunks/LpLoader-DjJEX8hL.js +92 -0
  72. package/dist/chunks/{LpLogViewer-4QFc-sVN.js → LpLogViewer-elZHbj85.js} +225 -129
  73. package/dist/chunks/LpMagnetic-CtXKLa2Y.js +62 -0
  74. package/dist/chunks/{LpMapPicker-BTbkFeSG.js → LpMapPicker-BtIl7NOM.js} +34 -31
  75. package/dist/chunks/LpMasonry--k0571qG.js +185 -0
  76. package/dist/chunks/{LpMediaGallery-CuPcscx3.js → LpMediaGallery-D5swlmZ_.js} +3 -3
  77. package/dist/chunks/{LpModal-hk1noDcr.js → LpModal-eBMt2Fqn.js} +8 -3
  78. package/dist/chunks/{LpModalNav-DQd2keZm.js → LpModalNav-D4Z0wVHR.js} +4 -4
  79. package/dist/chunks/{LpNotificationBell-X84PJIxD.js → LpNotificationBell-DPZmP5dM.js} +32 -48
  80. package/dist/chunks/LpNumberField-B9k-h2HE.js +140 -0
  81. package/dist/chunks/{LpNumberFlow-z4WPZcZu.js → LpNumberFlow-Cfyh033Q.js} +8 -28
  82. package/dist/chunks/{LpOtpInput-PbeNJ5In.js → LpOtpInput-CeBPsM7D.js} +2 -1
  83. package/dist/chunks/{LpPagination-Bx-VG4Ag.js → LpPagination-VNCX6pFC.js} +37 -6
  84. package/dist/chunks/{LpPalettePreview-CFav_7co.js → LpPalettePreview-BNB8T_MY.js} +1 -1
  85. package/dist/chunks/{LpPasswordInput-CbnXitAS.js → LpPasswordInput-DTV18FIh.js} +20 -20
  86. package/dist/chunks/{LpPhoneInput-DP69HONS.js → LpPhoneInput-C60tx1tC.js} +12 -7
  87. package/dist/chunks/{LpPie-yLF9-aDR.js → LpPie-CFuV7pZv.js} +158 -47
  88. package/dist/chunks/LpPipeline-D81yh_NX.js +329 -0
  89. package/dist/chunks/{LpPopover-DVnkHaOu.js → LpPopover-BEIcqb9p.js} +8 -3
  90. package/dist/chunks/{LpProgress-CA86wxXu.js → LpProgress-CE-m5OpD.js} +23 -63
  91. package/dist/chunks/LpQuota-2Sw_gqcJ.js +162 -0
  92. package/dist/chunks/{LpRadioGroup-8S5hf8lE.js → LpRadioGroup-CGBr5nIp.js} +1 -1
  93. package/dist/chunks/{LpRangeCalendar-ByQi-WUz.js → LpRangeCalendar-c5qj7YcC.js} +1 -1
  94. package/dist/chunks/{LpRangeSlider-C1yF9-nP.js → LpRangeSlider-Dv6lNvHY.js} +6 -2
  95. package/dist/chunks/LpRelativeTime-CKzVqAo9.js +73 -0
  96. package/dist/chunks/LpRepeater-D0VjmD6y.js +140 -0
  97. package/dist/chunks/LpRevealOnScroll-DcQjexLy.js +76 -0
  98. package/dist/chunks/LpScramble-TDO5Kdou.js +85 -0
  99. package/dist/chunks/LpSecretField-DMfdJ1cQ.js +307 -0
  100. package/dist/chunks/{LpSection-BmRXe6ZP.js → LpSection-BW4xJ-Li.js} +1 -1
  101. package/dist/chunks/{LpSegmented-CW3bFHM4.js → LpSegmented-BO99Sr4m.js} +11 -14
  102. package/dist/chunks/{LpSelect-BCyDYoih.js → LpSelect-B4f_yRi5.js} +93 -108
  103. package/dist/chunks/LpShaderBackdrop-Bote0iuy.js +332 -0
  104. package/dist/chunks/LpShinyText-DX2ajtWq.js +48 -0
  105. package/dist/chunks/{LpSidebar-DfIiS-lB.js → LpSidebar-D-M0Y_7U.js} +5 -3
  106. package/dist/chunks/{LpSidebarNav-C5FDNI0t.js → LpSidebarNav-DF-TYxOV.js} +3 -3
  107. package/dist/chunks/{LpSlider-Cuzmrd7p.js → LpSlider-DuoRpOrH.js} +6 -2
  108. package/dist/chunks/{LpSparkline-DXT4KrSi.js → LpSparkline-CExIRDb3.js} +32 -27
  109. package/dist/chunks/LpSpotlight-4F3NeUMY.js +41 -0
  110. package/dist/chunks/{LpStat-iBMF5QNk.js → LpStat-B2ix1Q7t.js} +38 -35
  111. package/dist/chunks/LpStatus-C7kx5PKE.js +86 -0
  112. package/dist/chunks/LpStepMark-DK-5BKAt.js +101 -0
  113. package/dist/chunks/LpStepper-DRFfdJaq.js +76 -0
  114. package/dist/chunks/{LpSwap-D82jiecV.js → LpSwap-DzE6M3Mg.js} +1 -1
  115. package/dist/chunks/LpSwitch-DrzKrZZV.js +112 -0
  116. package/dist/chunks/{LpTableFilter-CuIbgdW0.js → LpTableFilter-DyvHGbOk.js} +3 -2
  117. package/dist/chunks/{LpTableOfContents-C_4VBktT.js → LpTableOfContents-rYvo8z5T.js} +34 -21
  118. package/dist/chunks/{LpTagsInput-DiXrpYeE.js → LpTagsInput-DgpBFRV2.js} +68 -71
  119. package/dist/chunks/LpTextReveal-CtAnOUkp.js +140 -0
  120. package/dist/chunks/{LpTextarea-xoQd5Lnp.js → LpTextarea-DiWjeVoJ.js} +12 -11
  121. package/dist/chunks/{LpThemeProvider-CQ2jC9TA.js → LpThemeProvider-DcbfOxsU.js} +1 -1
  122. package/dist/chunks/LpThemeStudio-DguwHdGt.js +416 -0
  123. package/dist/chunks/LpThemeStudioSection-BwhqYDLf.js +20 -0
  124. package/dist/chunks/LpThemeSwitcher-D5uz0MhK.js +278 -0
  125. package/dist/chunks/{LpTimeField-MFgAsNc5.js → LpTimeField-BFQVf_PW.js} +13 -5
  126. package/dist/chunks/{LpToaster-C4zE9zB7.js → LpToaster-Wv9ksj4q.js} +49 -82
  127. package/dist/chunks/{LpTooltip-suFCM34F.js → LpTooltip-Cz8SQwRt.js} +8 -3
  128. package/dist/chunks/{LpTopologyCanvas-6ozNrQKh.js → LpTopologyCanvas-ZhKthfgz.js} +1 -1
  129. package/dist/chunks/{LpTour-BUp3Jt2e.js → LpTour-NfRJNEIP.js} +24 -18
  130. package/dist/chunks/LpTruncate-D_5Pfv5B.js +112 -0
  131. package/dist/chunks/LpTypewriter-BCL_a6wE.js +159 -0
  132. package/dist/chunks/{LpUptimeBar-B6kHw4Cj.js → LpUptimeBar-DWegV2p6.js} +9 -8
  133. package/dist/chunks/{LpVideoBackdrop-qWRYBOTQ.js → LpVideoBackdrop-DS1wGv-X.js} +7 -8
  134. package/dist/chunks/{MenuTitle-obgek0B7.js → MenuTitle-BjQZX8tQ.js} +1 -1
  135. package/dist/chunks/OptionContent-CmYUUeWj.js +40 -0
  136. package/dist/chunks/PickerField-CHRS1h7K.js +116 -0
  137. package/dist/chunks/RevealToggle-C-KzaQGJ.js +65 -0
  138. package/dist/chunks/StepConnector-37OgEOXA.js +41 -0
  139. package/dist/chunks/TourCard-BXuVHsfn.js +123 -0
  140. package/dist/chunks/backdrop-Dkf2vM81.js +59 -0
  141. package/dist/chunks/{icons-DVhZ_plB.js → icons-4IywzkHk.js} +1 -1
  142. package/dist/chunks/{useTheme-2qHG8NEU.js → useTheme-BOV_-AiY.js} +9 -65
  143. package/dist/component-names.d.ts +1 -1
  144. package/dist/components/AttentionDot.vue.d.ts +9 -0
  145. package/dist/components/AttentionDot.vue.js +4 -0
  146. package/dist/components/ContextMenuItems.vue.js +1 -1
  147. package/dist/components/DropzoneLinkField.vue.js +1 -1
  148. package/dist/components/FieldWrapper.vue.d.ts +25 -0
  149. package/dist/components/FieldWrapper.vue.js +4 -0
  150. package/dist/components/LayoutCanvas.vue.js +1 -1
  151. package/dist/components/LayoutNode.vue.d.ts +4 -4
  152. package/dist/components/LayoutNode.vue.js +1 -1
  153. package/dist/components/LegendSwatch.vue.d.ts +6 -0
  154. package/dist/components/LegendSwatch.vue.js +4 -0
  155. package/dist/components/LoaderMark.vue.d.ts +12 -0
  156. package/dist/components/LoaderMark.vue.js +4 -0
  157. package/dist/components/LpActionBar.vue.js +1 -1
  158. package/dist/components/LpActivityLine.vue.d.ts +58 -0
  159. package/dist/components/LpActivityLine.vue.js +4 -0
  160. package/dist/components/LpAddressInput.vue.js +1 -1
  161. package/dist/components/LpAlert.vue.d.ts +2 -2
  162. package/dist/components/LpAlert.vue.js +1 -1
  163. package/dist/components/LpAppShell.vue.d.ts +8 -7
  164. package/dist/components/LpAppShell.vue.js +1 -1
  165. package/dist/components/LpAutocomplete.vue.js +1 -1
  166. package/dist/components/LpAvatar.vue.d.ts +16 -0
  167. package/dist/components/LpAvatar.vue.js +1 -1
  168. package/dist/components/LpBadge.vue.d.ts +19 -5
  169. package/dist/components/LpBadge.vue.js +1 -1
  170. package/dist/components/LpBreadcrumbs.vue.js +1 -1
  171. package/dist/components/LpButton.vue.d.ts +2 -2
  172. package/dist/components/LpButton.vue.js +1 -1
  173. package/dist/components/LpCalendar.vue.js +1 -1
  174. package/dist/components/LpCard.vue.d.ts +24 -0
  175. package/dist/components/LpCard.vue.js +1 -1
  176. package/dist/components/LpChart.vue.js +107 -138
  177. package/dist/components/LpCheckbox.vue.d.ts +2 -2
  178. package/dist/components/LpCheckbox.vue.js +1 -1
  179. package/dist/components/LpCodeBlock.vue.js +1 -1
  180. package/dist/components/LpCodeDisplay.vue.d.ts +89 -0
  181. package/dist/components/LpCodeDisplay.vue.js +4 -0
  182. package/dist/components/LpCollapse.vue.d.ts +58 -0
  183. package/dist/components/LpCollapse.vue.js +4 -0
  184. package/dist/components/LpColorPicker.vue.d.ts +2 -2
  185. package/dist/components/LpColorPicker.vue.js +1 -1
  186. package/dist/components/LpCommandPalette.vue.js +34 -23
  187. package/dist/components/LpConfirmDialog.vue.js +1 -1
  188. package/dist/components/LpConfirmHost.vue.js +1 -1
  189. package/dist/components/LpContextMenu.vue.js +1 -1
  190. package/dist/components/LpCopyButton.vue.d.ts +82 -0
  191. package/dist/components/LpCopyButton.vue.js +4 -0
  192. package/dist/components/LpCountdown.vue.d.ts +100 -0
  193. package/dist/components/LpCountdown.vue.js +4 -0
  194. package/dist/components/LpDataList.vue.d.ts +66 -0
  195. package/dist/components/LpDataList.vue.js +4 -0
  196. package/dist/components/LpDatePicker.vue.d.ts +1 -1
  197. package/dist/components/LpDatePicker.vue.js +1 -1
  198. package/dist/components/LpDateRangePicker.vue.d.ts +1 -1
  199. package/dist/components/LpDateRangePicker.vue.js +1 -1
  200. package/dist/components/LpDisclosure.vue.js +1 -1
  201. package/dist/components/LpDock.vue.d.ts +74 -0
  202. package/dist/components/LpDock.vue.js +204 -0
  203. package/dist/components/LpDrawer.vue.js +1 -1
  204. package/dist/components/LpDropdownMenu.vue.js +1 -1
  205. package/dist/components/LpDropzone.vue.d.ts +8 -1
  206. package/dist/components/LpDropzone.vue.js +36 -15
  207. package/dist/components/LpEditable.vue.d.ts +85 -0
  208. package/dist/components/LpEditable.vue.js +4 -0
  209. package/dist/components/LpEmptyState.vue.js +1 -1
  210. package/dist/components/LpFieldNotice.vue.js +1 -1
  211. package/dist/components/LpFileTree.vue.js +1 -1
  212. package/dist/components/LpFileTreeNode.vue.js +1 -1
  213. package/dist/components/LpFormField.vue.js +1 -1
  214. package/dist/components/LpFrame.vue.d.ts +22 -0
  215. package/dist/components/LpFrame.vue.js +4 -0
  216. package/dist/components/LpGauge.vue.d.ts +116 -0
  217. package/dist/components/LpGauge.vue.js +4 -0
  218. package/dist/components/LpGlowBorder.vue.d.ts +47 -0
  219. package/dist/components/LpGlowBorder.vue.js +4 -0
  220. package/dist/components/LpHintExample.vue.d.ts +2 -2
  221. package/dist/components/LpHintExample.vue.js +1 -1
  222. package/dist/components/LpHintLayer.vue.js +1 -1
  223. package/dist/components/LpHints.vue.js +1 -1
  224. package/dist/components/LpHoverCard.vue.d.ts +60 -0
  225. package/dist/components/LpHoverCard.vue.js +4 -0
  226. package/dist/components/LpIcon.vue.js +1 -1
  227. package/dist/components/LpIdenticon.vue.d.ts +37 -0
  228. package/dist/components/LpIdenticon.vue.js +4 -0
  229. package/dist/components/LpImageEditor.vue.js +13 -19
  230. package/dist/components/LpInfraNode.vue.js +1 -1
  231. package/dist/components/LpInput.vue.d.ts +10 -0
  232. package/dist/components/LpInput.vue.js +1 -1
  233. package/dist/components/LpLightbox.vue.js +1 -1
  234. package/dist/components/LpLoader.vue.d.ts +106 -0
  235. package/dist/components/LpLoader.vue.js +4 -0
  236. package/dist/components/LpLogViewer.vue.js +1 -1
  237. package/dist/components/LpMagnetic.vue.d.ts +28 -0
  238. package/dist/components/LpMagnetic.vue.js +4 -0
  239. package/dist/components/LpMapPicker.vue.js +1 -1
  240. package/dist/components/LpMasonry.vue.d.ts +42 -0
  241. package/dist/components/LpMasonry.vue.js +4 -0
  242. package/dist/components/LpMediaGallery.vue.js +1 -1
  243. package/dist/components/LpModal.vue.js +1 -1
  244. package/dist/components/LpModalNav.vue.js +1 -1
  245. package/dist/components/LpNotificationBell.vue.d.ts +15 -6
  246. package/dist/components/LpNotificationBell.vue.js +1 -1
  247. package/dist/components/LpNumberField.vue.d.ts +57 -0
  248. package/dist/components/LpNumberField.vue.js +1 -1
  249. package/dist/components/LpNumberFlow.vue.js +1 -1
  250. package/dist/components/LpOtpInput.vue.d.ts +12 -4
  251. package/dist/components/LpOtpInput.vue.js +1 -1
  252. package/dist/components/LpPagination.vue.js +1 -1
  253. package/dist/components/LpPaletteFacts.vue.js +1 -1
  254. package/dist/components/LpPaletteHeader.vue.js +2 -2
  255. package/dist/components/LpPalettePreview.vue.js +1 -1
  256. package/dist/components/LpPaletteStats.vue.js +1 -1
  257. package/dist/components/LpPasswordInput.vue.d.ts +12 -1
  258. package/dist/components/LpPasswordInput.vue.js +1 -1
  259. package/dist/components/LpPhoneInput.vue.js +1 -1
  260. package/dist/components/LpPie.vue.d.ts +3 -1
  261. package/dist/components/LpPie.vue.js +1 -1
  262. package/dist/components/LpPipeline.vue.d.ts +91 -0
  263. package/dist/components/LpPipeline.vue.js +4 -0
  264. package/dist/components/LpPopover.vue.d.ts +2 -2
  265. package/dist/components/LpPopover.vue.js +1 -1
  266. package/dist/components/LpProgress.vue.d.ts +11 -4
  267. package/dist/components/LpProgress.vue.js +1 -1
  268. package/dist/components/LpQuota.vue.d.ts +68 -0
  269. package/dist/components/LpQuota.vue.js +4 -0
  270. package/dist/components/LpRadioGroup.vue.js +1 -1
  271. package/dist/components/LpRangeCalendar.vue.js +1 -1
  272. package/dist/components/LpRangeSlider.vue.js +1 -1
  273. package/dist/components/LpRelativeTime.vue.d.ts +41 -0
  274. package/dist/components/LpRelativeTime.vue.js +4 -0
  275. package/dist/components/LpRepeater.vue.d.ts +48 -0
  276. package/dist/components/LpRepeater.vue.js +4 -0
  277. package/dist/components/LpRevealOnScroll.vue.d.ts +67 -0
  278. package/dist/components/LpRevealOnScroll.vue.js +4 -0
  279. package/dist/components/LpRollingText.vue.d.ts +1 -1
  280. package/dist/components/LpScramble.vue.d.ts +55 -0
  281. package/dist/components/LpScramble.vue.js +4 -0
  282. package/dist/components/LpScrollArea.vue.d.ts +1 -1
  283. package/dist/components/LpSecretField.vue.d.ts +108 -0
  284. package/dist/components/LpSecretField.vue.js +4 -0
  285. package/dist/components/LpSection.vue.js +1 -1
  286. package/dist/components/LpSegmented.vue.js +1 -1
  287. package/dist/components/LpSelect.vue.d.ts +2 -0
  288. package/dist/components/LpSelect.vue.js +1 -1
  289. package/dist/components/LpShaderBackdrop.vue.d.ts +39 -0
  290. package/dist/components/LpShaderBackdrop.vue.js +4 -0
  291. package/dist/components/LpShinyText.vue.d.ts +39 -0
  292. package/dist/components/LpShinyText.vue.js +4 -0
  293. package/dist/components/LpShortcutsDialog.vue.js +1 -1
  294. package/dist/components/LpSidebar.vue.js +1 -1
  295. package/dist/components/LpSidebarNav.vue.js +1 -1
  296. package/dist/components/LpSlider.vue.js +1 -1
  297. package/dist/components/LpSparkline.vue.d.ts +4 -3
  298. package/dist/components/LpSparkline.vue.js +1 -1
  299. package/dist/components/LpSpotlight.vue.d.ts +37 -0
  300. package/dist/components/LpSpotlight.vue.js +4 -0
  301. package/dist/components/LpStat.vue.js +1 -1
  302. package/dist/components/LpStatus.vue.d.ts +65 -0
  303. package/dist/components/LpStatus.vue.js +4 -0
  304. package/dist/components/LpStepMark.vue.d.ts +31 -0
  305. package/dist/components/LpStepMark.vue.js +4 -0
  306. package/dist/components/LpStepper.vue.js +1 -1
  307. package/dist/components/LpSwap.vue.js +1 -1
  308. package/dist/components/LpSwitch.vue.d.ts +2 -2
  309. package/dist/components/LpSwitch.vue.js +1 -1
  310. package/dist/components/LpTable.vue.js +104 -120
  311. package/dist/components/LpTableFilter.vue.js +1 -1
  312. package/dist/components/LpTableOfContents.vue.d.ts +6 -1
  313. package/dist/components/LpTableOfContents.vue.js +1 -1
  314. package/dist/components/LpTabs.vue.d.ts +5 -5
  315. package/dist/components/LpTabs.vue.js +25 -33
  316. package/dist/components/LpTagsInput.vue.js +1 -1
  317. package/dist/components/LpTextReveal.vue.d.ts +58 -0
  318. package/dist/components/LpTextReveal.vue.js +4 -0
  319. package/dist/components/LpTextarea.vue.js +1 -1
  320. package/dist/components/LpThemeProvider.vue.js +1 -1
  321. package/dist/components/LpThemeStudio.vue.d.ts +54 -0
  322. package/dist/components/LpThemeStudio.vue.js +4 -0
  323. package/dist/components/LpThemeStudioSection.vue.d.ts +16 -0
  324. package/dist/components/LpThemeStudioSection.vue.js +4 -0
  325. package/dist/components/LpThemeSwitcher.vue.d.ts +32 -1
  326. package/dist/components/LpThemeSwitcher.vue.js +1 -1
  327. package/dist/components/LpTimeField.vue.d.ts +2 -0
  328. package/dist/components/LpTimeField.vue.js +1 -1
  329. package/dist/components/LpToaster.vue.js +1 -1
  330. package/dist/components/LpTooltip.vue.d.ts +2 -2
  331. package/dist/components/LpTooltip.vue.js +1 -1
  332. package/dist/components/LpTopologyCanvas.vue.js +1 -1
  333. package/dist/components/LpTour.vue.js +1 -1
  334. package/dist/components/LpTruncate.vue.d.ts +34 -0
  335. package/dist/components/LpTruncate.vue.js +4 -0
  336. package/dist/components/LpTypewriter.vue.d.ts +61 -0
  337. package/dist/components/LpTypewriter.vue.js +4 -0
  338. package/dist/components/LpUptimeBar.vue.js +1 -1
  339. package/dist/components/LpVideoBackdrop.vue.js +1 -1
  340. package/dist/components/MenuTitle.vue.js +1 -1
  341. package/dist/components/OptionContent.vue.d.ts +7 -0
  342. package/dist/components/OptionContent.vue.js +4 -0
  343. package/dist/components/PickerField.vue.d.ts +43 -0
  344. package/dist/components/PickerField.vue.js +4 -0
  345. package/dist/components/RevealToggle.vue.d.ts +21 -0
  346. package/dist/components/RevealToggle.vue.js +4 -0
  347. package/dist/components/StepConnector.vue.d.ts +19 -0
  348. package/dist/components/StepConnector.vue.js +4 -0
  349. package/dist/components/TourCard.vue.js +1 -1
  350. package/dist/components/badge.d.ts +1 -0
  351. package/dist/components/badge.js +4 -0
  352. package/dist/components/chart.d.ts +5 -1
  353. package/dist/components/chart.js +2 -21
  354. package/dist/components/dateRange.d.ts +11 -0
  355. package/dist/components/dateRange.js +12 -0
  356. package/dist/components/dock.d.ts +19 -0
  357. package/dist/components/dock.js +16 -0
  358. package/dist/components/dropdown.d.ts +10 -1
  359. package/dist/components/dropdown.js +7 -2
  360. package/dist/components/fieldText.d.ts +38 -0
  361. package/dist/components/fieldText.js +53 -0
  362. package/dist/components/fileTree.d.ts +7 -3
  363. package/dist/components/fileTree.js +12 -18
  364. package/dist/components/format.d.ts +41 -0
  365. package/dist/components/format.js +67 -0
  366. package/dist/components/identicon.d.ts +38 -0
  367. package/dist/components/identicon.js +85 -0
  368. package/dist/components/masonry.d.ts +32 -0
  369. package/dist/components/masonry.js +40 -0
  370. package/dist/components/menuWhen.js +1 -1
  371. package/dist/components/meter.d.ts +64 -0
  372. package/dist/components/meter.js +53 -0
  373. package/dist/components/otp.d.ts +1 -1
  374. package/dist/components/otp.js +7 -2
  375. package/dist/components/pipeline.d.ts +55 -0
  376. package/dist/components/pipeline.js +51 -0
  377. package/dist/components/quota.d.ts +57 -0
  378. package/dist/components/quota.js +40 -0
  379. package/dist/components/relativeTime.d.ts +24 -0
  380. package/dist/components/relativeTime.js +56 -0
  381. package/dist/components/reveal.d.ts +18 -0
  382. package/dist/components/reveal.js +32 -0
  383. package/dist/components/scramble.d.ts +68 -0
  384. package/dist/components/scramble.js +58 -0
  385. package/dist/components/shaderBackdrop.d.ts +20 -0
  386. package/dist/components/shaderBackdrop.js +156 -0
  387. package/dist/components/slider.d.ts +5 -0
  388. package/dist/components/slider.js +24 -0
  389. package/dist/components/slotText.d.ts +2 -0
  390. package/dist/components/slotText.js +9 -0
  391. package/dist/components/status.d.ts +14 -0
  392. package/dist/components/status.js +22 -0
  393. package/dist/components/tableFacets.d.ts +8 -0
  394. package/dist/components/tableFacets.js +19 -0
  395. package/dist/components/textSplit.d.ts +17 -0
  396. package/dist/components/textSplit.js +24 -0
  397. package/dist/components/timeSpan.d.ts +78 -0
  398. package/dist/components/timeSpan.js +85 -0
  399. package/dist/components/tone.d.ts +43 -0
  400. package/dist/components/tone.js +82 -0
  401. package/dist/components/tour.js +3 -2
  402. package/dist/components/typewriter.d.ts +36 -0
  403. package/dist/components/typewriter.js +53 -0
  404. package/dist/components/videoBackdrop.js +5 -6
  405. package/dist/composables/easing.d.ts +22 -1
  406. package/dist/composables/easing.js +42 -1
  407. package/dist/composables/pseudoLocale.d.ts +15 -0
  408. package/dist/composables/pseudoLocale.js +96 -0
  409. package/dist/composables/scroll.js +5 -3
  410. package/dist/composables/useClipboard.d.ts +4 -1
  411. package/dist/composables/useClipboard.js +12 -2
  412. package/dist/composables/useField.d.ts +8 -0
  413. package/dist/composables/useField.js +5 -0
  414. package/dist/composables/useForm.js +19 -5
  415. package/dist/composables/useInView.d.ts +11 -0
  416. package/dist/composables/useInView.js +39 -0
  417. package/dist/composables/useLoadingGate.d.ts +8 -0
  418. package/dist/composables/useLoadingGate.js +38 -0
  419. package/dist/composables/useLpConfig.d.ts +10 -0
  420. package/dist/composables/useLpConfig.js +11 -1
  421. package/dist/composables/useMediaQuery.js +3 -1
  422. package/dist/composables/useNow.d.ts +16 -0
  423. package/dist/composables/useNow.js +39 -0
  424. package/dist/composables/usePersisted.js +14 -7
  425. package/dist/composables/usePillTransition.d.ts +5 -2
  426. package/dist/composables/usePillTransition.js +4 -3
  427. package/dist/composables/usePointerFrame.d.ts +18 -0
  428. package/dist/composables/usePointerFrame.js +31 -0
  429. package/dist/composables/useReducedMotion.d.ts +2 -0
  430. package/dist/composables/useReducedMotion.js +7 -0
  431. package/dist/composables/useRepeater.d.ts +17 -0
  432. package/dist/composables/useRepeater.js +31 -0
  433. package/dist/composables/useResizeObserver.d.ts +8 -0
  434. package/dist/composables/useResizeObserver.js +33 -0
  435. package/dist/composables/useRevealedValue.d.ts +31 -0
  436. package/dist/composables/useRevealedValue.js +26 -0
  437. package/dist/composables/useScramble.d.ts +42 -0
  438. package/dist/composables/useScramble.js +76 -0
  439. package/dist/composables/useShift.js +2 -10
  440. package/dist/composables/useSpotlight.d.ts +18 -0
  441. package/dist/composables/useSpotlight.js +53 -0
  442. package/dist/composables/useTilt.js +26 -18
  443. package/dist/composables/useTween.d.ts +43 -0
  444. package/dist/composables/useTween.js +69 -0
  445. package/dist/composables/useView.d.ts +18 -0
  446. package/dist/composables/useView.js +61 -0
  447. package/dist/icons-all.js +1 -1
  448. package/dist/index.d.ts +98 -1
  449. package/dist/index.js +262 -104
  450. package/dist/theme/define.d.ts +12 -0
  451. package/dist/theme/studio.d.ts +90 -0
  452. package/package.json +5 -2
  453. package/src/component-names.ts +33 -0
  454. package/src/components/AttentionDot.vue +27 -0
  455. package/src/components/FieldWrapper.vue +38 -0
  456. package/src/components/LayoutNode.vue +5 -9
  457. package/src/components/LegendSwatch.vue +15 -0
  458. package/src/components/LoaderMark.vue +90 -0
  459. package/src/components/LpActionBar.vue +12 -20
  460. package/src/components/LpActivityLine.vue +186 -0
  461. package/src/components/LpAlert.vue +54 -24
  462. package/src/components/LpAppShell.vue +7 -11
  463. package/src/components/LpAutocomplete.vue +16 -14
  464. package/src/components/LpAvatar.vue +17 -2
  465. package/src/components/LpBadge.vue +77 -13
  466. package/src/components/LpBreadcrumbs.vue +101 -35
  467. package/src/components/LpButton.vue +15 -3
  468. package/src/components/LpCard.vue +30 -7
  469. package/src/components/LpChart.vue +143 -154
  470. package/src/components/LpCheckbox.vue +10 -4
  471. package/src/components/LpCodeBlock.vue +11 -19
  472. package/src/components/LpCodeDisplay.vue +228 -0
  473. package/src/components/LpCollapse.vue +162 -0
  474. package/src/components/LpColorPicker.vue +10 -1
  475. package/src/components/LpCommandPalette.vue +38 -24
  476. package/src/components/LpContextMenu.vue +10 -1
  477. package/src/components/LpCopyButton.vue +185 -0
  478. package/src/components/LpCountdown.vue +308 -0
  479. package/src/components/LpDataList.vue +154 -0
  480. package/src/components/LpDatePicker.vue +53 -104
  481. package/src/components/LpDateRangePicker.vue +49 -95
  482. package/src/components/LpDisclosure.vue +58 -36
  483. package/src/components/LpDock.vue +274 -0
  484. package/src/components/LpDrawer.vue +10 -1
  485. package/src/components/LpDropdownMenu.vue +10 -1
  486. package/src/components/LpDropzone.vue +34 -13
  487. package/src/components/LpEditable.vue +293 -0
  488. package/src/components/LpFileTree.vue +5 -1
  489. package/src/components/LpFileTreeNode.vue +25 -50
  490. package/src/components/LpFormField.vue +22 -3
  491. package/src/components/LpFrame.vue +200 -0
  492. package/src/components/LpGauge.vue +287 -0
  493. package/src/components/LpGlowBorder.vue +60 -0
  494. package/src/components/LpHintExample.vue +9 -32
  495. package/src/components/LpHintLayer.vue +13 -3
  496. package/src/components/LpHoverCard.vue +175 -0
  497. package/src/components/LpIdenticon.vue +69 -0
  498. package/src/components/LpImageEditor.vue +15 -18
  499. package/src/components/LpInfraNode.vue +27 -16
  500. package/src/components/LpInput.vue +30 -16
  501. package/src/components/LpLightbox.vue +44 -23
  502. package/src/components/LpLoader.vue +145 -0
  503. package/src/components/LpLogViewer.vue +311 -82
  504. package/src/components/LpMagnetic.vue +97 -0
  505. package/src/components/LpMapPicker.vue +26 -28
  506. package/src/components/LpMasonry.vue +247 -0
  507. package/src/components/LpModal.vue +10 -1
  508. package/src/components/LpNotificationBell.vue +33 -49
  509. package/src/components/LpNumberField.vue +79 -14
  510. package/src/components/LpNumberFlow.vue +10 -35
  511. package/src/components/LpOtpInput.vue +7 -2
  512. package/src/components/LpPagination.vue +38 -4
  513. package/src/components/LpPalettePreview.vue +2 -7
  514. package/src/components/LpPasswordInput.vue +16 -14
  515. package/src/components/LpPhoneInput.vue +12 -3
  516. package/src/components/LpPie.vue +197 -36
  517. package/src/components/LpPipeline.vue +366 -0
  518. package/src/components/LpPopover.vue +10 -1
  519. package/src/components/LpProgress.vue +22 -84
  520. package/src/components/LpQuota.vue +197 -0
  521. package/src/components/LpRangeSlider.vue +5 -1
  522. package/src/components/LpRelativeTime.vue +90 -0
  523. package/src/components/LpRepeater.vue +80 -0
  524. package/src/components/LpRevealOnScroll.vue +125 -0
  525. package/src/components/LpScramble.vue +107 -0
  526. package/src/components/LpSecretField.vue +313 -0
  527. package/src/components/LpSegmented.vue +3 -10
  528. package/src/components/LpSelect.vue +78 -64
  529. package/src/components/LpShaderBackdrop.vue +434 -0
  530. package/src/components/LpShinyText.vue +139 -0
  531. package/src/components/LpSidebar.vue +2 -0
  532. package/src/components/LpSlider.vue +5 -1
  533. package/src/components/LpSparkline.vue +55 -37
  534. package/src/components/LpSpotlight.vue +51 -0
  535. package/src/components/LpStat.vue +6 -2
  536. package/src/components/LpStatus.vue +127 -0
  537. package/src/components/LpStepMark.vue +138 -0
  538. package/src/components/LpStepper.vue +37 -43
  539. package/src/components/LpSwap.vue +2 -2
  540. package/src/components/LpSwitch.vue +15 -22
  541. package/src/components/LpTable.vue +47 -63
  542. package/src/components/LpTableFilter.vue +1 -0
  543. package/src/components/LpTableOfContents.vue +53 -29
  544. package/src/components/LpTabs.vue +10 -21
  545. package/src/components/LpTagsInput.vue +53 -37
  546. package/src/components/LpTextReveal.vue +236 -0
  547. package/src/components/LpTextarea.vue +11 -11
  548. package/src/components/LpThemeStudio.vue +216 -0
  549. package/src/components/LpThemeStudioSection.vue +16 -0
  550. package/src/components/LpThemeSwitcher.vue +156 -47
  551. package/src/components/LpTimeField.vue +9 -1
  552. package/src/components/LpToaster.vue +63 -83
  553. package/src/components/LpTooltip.vue +10 -1
  554. package/src/components/LpTour.vue +24 -13
  555. package/src/components/LpTruncate.vue +135 -0
  556. package/src/components/LpTypewriter.vue +236 -0
  557. package/src/components/LpUptimeBar.vue +6 -5
  558. package/src/components/LpVideoBackdrop.vue +15 -13
  559. package/src/components/OptionContent.vue +17 -0
  560. package/src/components/PickerField.vue +58 -0
  561. package/src/components/RevealToggle.vue +51 -0
  562. package/src/components/StepConnector.vue +54 -0
  563. package/src/components/TourCard.vue +29 -16
  564. package/src/components/badge.ts +8 -0
  565. package/src/components/chart.ts +8 -23
  566. package/src/components/dateRange.ts +25 -0
  567. package/src/components/dock.ts +31 -0
  568. package/src/components/dropdown.ts +15 -3
  569. package/src/components/fieldText.ts +95 -0
  570. package/src/components/fileTree.ts +19 -21
  571. package/src/components/format.ts +136 -0
  572. package/src/components/identicon.ts +160 -0
  573. package/src/components/masonry.ts +73 -0
  574. package/src/components/meter.ts +122 -0
  575. package/src/components/otp.ts +14 -3
  576. package/src/components/pipeline.ts +101 -0
  577. package/src/components/quota.ts +111 -0
  578. package/src/components/relativeTime.ts +118 -0
  579. package/src/components/reveal.ts +56 -0
  580. package/src/components/scramble.ts +138 -0
  581. package/src/components/shaderBackdrop.ts +208 -0
  582. package/src/components/slider.ts +30 -0
  583. package/src/components/slotText.ts +13 -0
  584. package/src/components/status.ts +46 -0
  585. package/src/components/tableFacets.ts +25 -0
  586. package/src/components/textSplit.ts +55 -0
  587. package/src/components/timeSpan.ts +183 -0
  588. package/src/components/tone.ts +144 -0
  589. package/src/components/tour.ts +3 -2
  590. package/src/components/typewriter.ts +104 -0
  591. package/src/components/videoBackdrop.ts +7 -6
  592. package/src/composables/easing.ts +66 -1
  593. package/src/composables/pseudoLocale.ts +105 -0
  594. package/src/composables/scroll.ts +6 -3
  595. package/src/composables/useClipboard.ts +25 -3
  596. package/src/composables/useField.ts +12 -0
  597. package/src/composables/useForm.ts +27 -6
  598. package/src/composables/useInView.ts +61 -0
  599. package/src/composables/useLoadingGate.ts +63 -0
  600. package/src/composables/useLpConfig.ts +20 -1
  601. package/src/composables/useMediaQuery.ts +6 -2
  602. package/src/composables/useNow.ts +84 -0
  603. package/src/composables/usePersisted.ts +19 -8
  604. package/src/composables/usePillTransition.ts +21 -13
  605. package/src/composables/usePointerFrame.ts +72 -0
  606. package/src/composables/useReducedMotion.ts +22 -0
  607. package/src/composables/useRepeater.ts +44 -0
  608. package/src/composables/useResizeObserver.ts +59 -0
  609. package/src/composables/useRevealedValue.ts +84 -0
  610. package/src/composables/useScramble.ts +152 -0
  611. package/src/composables/useShift.ts +10 -16
  612. package/src/composables/useSpotlight.ts +82 -0
  613. package/src/composables/useTilt.ts +40 -23
  614. package/src/composables/useTween.ts +149 -0
  615. package/src/composables/useView.ts +93 -0
  616. package/src/index.css +1 -0
  617. package/src/index.ts +143 -1
  618. package/src/kit-icons.ts +1 -1
  619. package/src/theme/define.ts +65 -0
  620. package/src/theme/studio.ts +202 -0
  621. package/src/tokens/effects.css +151 -0
  622. package/src/tokens/tokens.css +131 -39
  623. package/src/tokens/utilities.css +81 -0
  624. package/dist/assets/LpTabs-Bk7v4bZz.css +0 -18
  625. package/dist/chunks/LpAlert-BdvxvcWE.js +0 -85
  626. package/dist/chunks/LpBadge-Fe0D1bYx.js +0 -62
  627. package/dist/chunks/LpBreadcrumbs-rzOKkLiI.js +0 -98
  628. package/dist/chunks/LpDatePicker-BMfM454Y.js +0 -243
  629. package/dist/chunks/LpDateRangePicker-CNb9X3eL.js +0 -195
  630. package/dist/chunks/LpNumberField-DO1ufKvE.js +0 -107
  631. package/dist/chunks/LpStepper-C2slwObu.js +0 -90
  632. package/dist/chunks/LpSwitch-CZy9_IoA.js +0 -132
  633. package/dist/chunks/LpThemeSwitcher-CDoziW0z.js +0 -166
  634. package/dist/chunks/TourCard-BKI7X9-r.js +0 -105
@@ -0,0 +1,185 @@
1
+ <script lang="ts">
2
+ // Attributes (class, aria-*, data-*) reach the button itself, merged by LpButton.
3
+ export default { inheritAttrs: false }
4
+
5
+ export interface CopyButtonLabels extends Record<string, string> {
6
+ copy: string
7
+ copied: string
8
+ failed: string
9
+ }
10
+
11
+ /**
12
+ * What to copy: the text, or a function that produces it when clicked. A
13
+ * `Blob` is copied as itself (an image as PNG, see useClipboard).
14
+ */
15
+ export type CopyValue =
16
+ | string
17
+ | number
18
+ | Blob
19
+ | (() => string | number | Blob | Promise<string | number | Blob>)
20
+ </script>
21
+
22
+ <script setup lang="ts">
23
+ /*
24
+ * The one copy button: an icon that turns into a tick for a moment, a tip
25
+ * that says "Copy" and then "Copied", and nothing thrown when the clipboard
26
+ * refuses.
27
+ *
28
+ * Several kit components drew their own (the code block's header, the
29
+ * toaster's message copy, the lightbox's image copy), each with its own icon
30
+ * swap that snapped from one glyph to the other. This one cross-fades the two
31
+ * glyphs in place — the copy icon shrinks and turns away as the tick grows in
32
+ * — so the confirmation reads as the button answering, not as a redraw.
33
+ *
34
+ * `value` may be a function, sync or async, for text that is expensive or
35
+ * secret enough to fetch only when someone actually asks for it (a token
36
+ * revealed by the server on demand). While it resolves the button shows its
37
+ * spinner. Note the browser's clipboard wants the write to stay close to the
38
+ * click; a getter that takes seconds may be refused, which surfaces as the
39
+ * `failed` state and the `error` event rather than as an exception.
40
+ */
41
+ import { computed, ref, useAttrs } from "vue"
42
+ import { useClipboard } from "../composables/useClipboard"
43
+ import { useLabels } from "../composables/useLpConfig"
44
+ import LpButton from "./LpButton.vue"
45
+ import LpIcon from "./LpIcon.vue"
46
+ import LpTooltip from "./LpTooltip.vue"
47
+
48
+ const props = withDefaults(
49
+ defineProps<{
50
+ /** The text to copy, or a (possibly async) function that returns it on click. */
51
+ value: CopyValue
52
+ /** LpButton's sizes, so it sits in a toolbar of buttons at the same height. */
53
+ size?: "xs" | "sm" | "md" | "lg"
54
+ /**
55
+ * Glyph size in px, for a toolbar whose other icons are drawn at their
56
+ * own size (the lightbox's 18px row). Defaults to what suits `size`.
57
+ */
58
+ iconSize?: number
59
+ /** LpButton's look. `ghost` by default: a copy button is a helper beside something, not a call to action. */
60
+ variant?: "solid" | "action" | "outline" | "soft" | "ghost" | "muted"
61
+ /**
62
+ * Visible text beside the icon. Without it the button is a square icon
63
+ * button and the tip names it.
64
+ */
65
+ label?: string
66
+ /** A toast on success too, for a copy whose button is about to leave the screen (a menu, a closing dialog). */
67
+ toast?: string | false
68
+ /**
69
+ * Show the tick now, for a copy made some other way: a Ctrl+C shortcut on
70
+ * the row, a "Copy" item in its menu. The button then confirms it too, so
71
+ * there is one place that says the clipboard holds this value.
72
+ */
73
+ copied?: boolean
74
+ disabled?: boolean
75
+ /** Where the tip opens. */
76
+ side?: "top" | "right" | "bottom" | "left"
77
+ labels?: Partial<CopyButtonLabels>
78
+ }>(),
79
+ { size: "sm", variant: "ghost", toast: false, side: "top" },
80
+ )
81
+
82
+ const emit = defineEmits<{
83
+ /**
84
+ * The value reached the clipboard: its text, or for a `Blob` an empty
85
+ * string and the blob itself second, so handlers written for text keep
86
+ * their `(text: string)` shape.
87
+ */
88
+ (e: "copied", text: string, blob?: Blob): void
89
+ /** The getter threw or the clipboard refused. */
90
+ (e: "error", error: unknown): void
91
+ }>()
92
+
93
+ const text = useLabels<CopyButtonLabels>(
94
+ "copyButton",
95
+ { copy: "Copy", copied: "Copied", failed: "Couldn't copy" },
96
+ () => props.labels,
97
+ )
98
+
99
+ const { copy, copied: justCopied } = useClipboard()
100
+ const busy = ref(false)
101
+ const failed = ref(false)
102
+ let failTimer: ReturnType<typeof setTimeout> | undefined
103
+
104
+ const state = computed<"idle" | "copied" | "failed">(() =>
105
+ failed.value ? "failed" : justCopied.value || props.copied ? "copied" : "idle",
106
+ )
107
+
108
+ async function run() {
109
+ if (busy.value || props.disabled) return
110
+ let value: string | Blob
111
+ try {
112
+ let raw = props.value
113
+ if (typeof raw === "function") {
114
+ busy.value = true
115
+ raw = await raw()
116
+ }
117
+ value = raw instanceof Blob ? raw : String(raw)
118
+ } catch (error) {
119
+ busy.value = false
120
+ fail(error)
121
+ return
122
+ }
123
+ busy.value = false
124
+ if (await copy(value, { toast: props.toast })) {
125
+ failed.value = false
126
+ if (value instanceof Blob) emit("copied", "", value)
127
+ else emit("copied", value)
128
+ } else fail(new Error("Clipboard unavailable"))
129
+ }
130
+
131
+ function fail(error: unknown) {
132
+ failed.value = true
133
+ clearTimeout(failTimer)
134
+ failTimer = setTimeout(() => (failed.value = false), 1800)
135
+ emit("error", error)
136
+ }
137
+
138
+ const tip = computed(() =>
139
+ state.value === "copied" ? text.value.copied : state.value === "failed" ? text.value.failed : text.value.copy,
140
+ )
141
+ const iconSize = computed(() => props.iconSize ?? { xs: 13, sm: 14, md: 16, lg: 16 }[props.size])
142
+ const attrs = useAttrs()
143
+ </script>
144
+
145
+ <template>
146
+ <LpTooltip :content="tip" :label="!label" :side="side">
147
+ <LpButton
148
+ v-bind="attrs"
149
+ :variant="variant"
150
+ :size="size"
151
+ :square="!label"
152
+ :disabled="disabled"
153
+ :loading="busy"
154
+ :data-state="state"
155
+ @click="run"
156
+ >
157
+ <span class="relative inline-grid shrink-0 place-items-center" :style="{ width: `${iconSize}px`, height: `${iconSize}px` }">
158
+ <!-- Both glyphs are always there and trade places, so the change is a
159
+ morph in one spot rather than one icon replacing another. -->
160
+ <LpIcon
161
+ name="lucide:copy"
162
+ :size="iconSize"
163
+ class="lp-glyph-swap col-start-1 row-start-1"
164
+ :data-on="state === 'idle' || undefined"
165
+ />
166
+ <LpIcon
167
+ name="lucide:check"
168
+ :size="iconSize"
169
+ class="lp-glyph-swap col-start-1 row-start-1 text-action"
170
+ :data-on="state === 'copied' || undefined"
171
+ />
172
+ <LpIcon
173
+ name="lucide:x"
174
+ :size="iconSize"
175
+ class="lp-glyph-swap col-start-1 row-start-1 text-danger"
176
+ :data-on="state === 'failed' || undefined"
177
+ />
178
+ </span>
179
+ <span v-if="label">{{ label }}</span>
180
+ </LpButton>
181
+ </LpTooltip>
182
+ <!-- The tip only speaks on hover/focus; the result is announced either way. -->
183
+ <span class="sr-only" role="status" aria-live="polite">{{ state === "idle" ? "" : tip }}</span>
184
+ </template>
185
+
@@ -0,0 +1,308 @@
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
+ * Time left until something: "resend the code in 0:42", "maintenance in
11
+ * 2d 3h", "the lobby closes in 4:59".
12
+ *
13
+ * Resend in <LpCountdown :seconds="45" @done="canResend = true" />
14
+ * <LpCountdown :to="window.startsAt" format="units" />
15
+ * <LpCountdown :seconds="300" progress="ring" :urgent-at="30" />
16
+ *
17
+ * What it takes care of so the app does not:
18
+ *
19
+ * - the format adapts: a clock under an hour, the two largest units above
20
+ * it (timeSpan.ts), and it rounds up, so 0:00 means "now", not "nearly";
21
+ * - no drift: the remaining time is always deadline − now, read from the
22
+ * clock on each tick (useNow), and ticks land on the second boundary; a
23
+ * tab left in the background stops ticking and is right again the
24
+ * moment it is looked at;
25
+ * - digits roll individually (LpRollingText), so 0:42 → 0:41 moves one
26
+ * digit and a minute rolling over moves three;
27
+ * - role="timer", which is silent by design, plus a polite announcement at
28
+ * round marks (10 minutes, 1 minute, 10 seconds…) and at the end — a
29
+ * screen reader hears the countdown matter, not every second of it.
30
+ */
31
+ import { computed, ref, watch } from "vue"
32
+ import { useLabels } from "../composables/useLpConfig"
33
+ import { useMergedAttrs } from "../composables/useMergedClass"
34
+ import { useNow } from "../composables/useNow"
35
+ import LpProgress from "./LpProgress.vue"
36
+ import LpRollingText from "./LpRollingText.vue"
37
+ import LpShift from "./LpShift.vue"
38
+ import {
39
+ ceilToSecond,
40
+ crossedMilestone,
41
+ DEFAULT_MILESTONES,
42
+ DEFAULT_UNIT_LABELS,
43
+ formatTime,
44
+ msToNextSecond,
45
+ padPart,
46
+ resolveFormat,
47
+ timeParts,
48
+ toEpoch,
49
+ type TimeFormat,
50
+ type TimeUnitLabels,
51
+ } from "./timeSpan"
52
+
53
+ export type CountdownLabels = {
54
+ /** Spoken at a milestone; `{time}` is the time left in words. */
55
+ left: string
56
+ /** Spoken when the time is up, and the timer's name from then on. */
57
+ done: string
58
+ }
59
+
60
+ const props = withDefaults(
61
+ defineProps<{
62
+ /** The moment to count down to. Takes precedence over `seconds`. */
63
+ to?: Date | string | number
64
+ /**
65
+ * Count down this many seconds from when the countdown mounts — or from
66
+ * when this value changes, or `restart()` is called. For "try again in 45
67
+ * s", where the app has a wait rather than a moment.
68
+ */
69
+ seconds?: number
70
+ /**
71
+ * `to` only: when the wait began, so the ring or bar can show how much of
72
+ * it is left. Without it a `to` countdown draws no progress.
73
+ */
74
+ from?: Date | string | number
75
+ /** `auto` is a clock under an hour and units above it. */
76
+ format?: TimeFormat
77
+ /** Units format: how many places to keep ("2d 3h" is 2). */
78
+ places?: number
79
+ /**
80
+ * Freeze the count. A `seconds` countdown resumes where it stopped; a `to`
81
+ * countdown is tied to a real moment, so it resumes at the true time left.
82
+ */
83
+ paused?: boolean
84
+ /** Draw the time left as a ring around the digits, or a bar under them. */
85
+ progress?: "ring" | "bar"
86
+ /** Ring only: outer diameter in px. */
87
+ ringSize?: number
88
+ /** Seconds left at which it turns danger: the end is close enough to act on. */
89
+ urgentAt?: number
90
+ /**
91
+ * Announce the time left at these marks (ms remaining) and at the end.
92
+ * `false` keeps it silent apart from what the timer role itself offers.
93
+ */
94
+ announce?: boolean | number[]
95
+ labels?: Partial<CountdownLabels>
96
+ }>(),
97
+ { format: "auto", places: 2, ringSize: 56, announce: true },
98
+ )
99
+
100
+ const emit = defineEmits<{
101
+ /** The time is up. Fires once per countdown (again after a restart). */
102
+ done: []
103
+ }>()
104
+
105
+ defineSlots<{
106
+ /** Replaces the digits once the time is up: a "Resend" button, "Live now". */
107
+ done?: () => unknown
108
+ }>()
109
+
110
+ const text = useLabels<CountdownLabels>("countdown", { left: "{time} left", done: "Time is up" }, () => props.labels)
111
+ const units = useLabels<TimeUnitLabels>("time", DEFAULT_UNIT_LABELS)
112
+
113
+ /* What the polite live region last said. */
114
+ const announcement = ref("")
115
+
116
+ /* ── The deadline, and the start it is measured from. */
117
+ const startedAt = ref(Date.now())
118
+
119
+ const deadline = computed(() => {
120
+ const to = toEpoch(props.to)
121
+ if (!Number.isNaN(to)) return to
122
+ if (typeof props.seconds === "number" && Number.isFinite(props.seconds)) return startedAt.value + props.seconds * 1000
123
+ return Number.NaN
124
+ })
125
+
126
+ const total = computed(() => {
127
+ if (!Number.isNaN(toEpoch(props.to))) {
128
+ const from = toEpoch(props.from)
129
+ return Number.isNaN(from) ? Number.NaN : deadline.value - from
130
+ }
131
+ return typeof props.seconds === "number" ? props.seconds * 1000 : Number.NaN
132
+ })
133
+
134
+ /*
135
+ * Pausing freezes the remaining time; resuming a `seconds` countdown moves
136
+ * its start forward by the pause, so the wait continues where it stood.
137
+ */
138
+ const frozen = ref<number | null>(null)
139
+ let pausedAt = 0
140
+
141
+ watch(
142
+ () => props.paused,
143
+ (paused) => {
144
+ if (paused) {
145
+ pausedAt = Date.now()
146
+ frozen.value = Math.max(0, deadline.value - pausedAt)
147
+ } else if (frozen.value !== null) {
148
+ if (Number.isNaN(toEpoch(props.to))) startedAt.value += Date.now() - pausedAt
149
+ frozen.value = null
150
+ }
151
+ },
152
+ { immediate: true },
153
+ )
154
+
155
+ const running = ref(true)
156
+ const now = useNow(() => running.value && !props.paused && Number.isFinite(deadline.value), {
157
+ nextIn: (at) => msToNextSecond(deadline.value - at),
158
+ })
159
+
160
+ const remaining = computed(() => {
161
+ if (frozen.value !== null) return frozen.value
162
+ const left = deadline.value - now.value
163
+ return Number.isFinite(left) ? Math.max(0, left) : 0
164
+ })
165
+
166
+ const shown = computed(() => ceilToSecond(remaining.value))
167
+ const isDone = computed(() => !Number.isNaN(deadline.value) && remaining.value <= 0)
168
+
169
+ watch(isDone, (done) => { running.value = !done }, { immediate: true })
170
+
171
+ /* ── The end, once per countdown. */
172
+ let fired = false
173
+ watch(
174
+ isDone,
175
+ (done) => {
176
+ if (!done) { fired = false; return }
177
+ if (fired) return
178
+ fired = true
179
+ emit("done")
180
+ if (props.announce !== false) announcement.value = text.value.done
181
+ },
182
+ { immediate: true },
183
+ )
184
+
185
+ /** Starts a `seconds` countdown again from the full wait. */
186
+ function restart() {
187
+ // Cleared so the next "time is up" is a change the live region announces.
188
+ announcement.value = ""
189
+ startedAt.value = Date.now()
190
+ now.value = startedAt.value
191
+ if (props.paused) {
192
+ pausedAt = startedAt.value
193
+ frozen.value = Math.max(0, deadline.value - pausedAt)
194
+ }
195
+ }
196
+
197
+ watch(() => props.seconds, () => { if (Number.isNaN(toEpoch(props.to))) restart() })
198
+
199
+ defineExpose({ restart, remaining })
200
+
201
+ /* ── What is printed and what is said. */
202
+ const parts = computed(() => timeParts(shown.value, props.format, units.value, props.places))
203
+ const clock = computed(() => resolveFormat(shown.value, props.format) === "clock")
204
+
205
+ /*
206
+ * Each part's digits, keyed from the right: a part that gains a digit (9:59 →
207
+ * 10:00) grows it on the left without re-keying the ones that were there.
208
+ */
209
+ const cells = computed(() =>
210
+ parts.value.map((part) => {
211
+ const digits = padPart(part).split("")
212
+ return { part, digits: digits.map((d, i) => ({ d, key: `${part.unit}${digits.length - i}` })) }
213
+ }),
214
+ )
215
+
216
+ const spokenTime = computed(() => formatTime(shown.value, "units", units.value, 2))
217
+
218
+ const milestones = computed(() => (Array.isArray(props.announce) ? props.announce : DEFAULT_MILESTONES))
219
+
220
+ watch(remaining, (after, before) => {
221
+ if (props.announce === false || before === undefined || props.paused) return
222
+ const mark = crossedMilestone(before, after, milestones.value)
223
+ if (mark !== null && after > 0) {
224
+ announcement.value = text.value.left.replace("{time}", formatTime(ceilToSecond(after), "units", units.value, 2))
225
+ }
226
+ })
227
+
228
+ const urgent = computed(() =>
229
+ props.urgentAt !== undefined && !isDone.value && remaining.value <= props.urgentAt * 1000,
230
+ )
231
+
232
+ const fraction = computed(() => {
233
+ if (!(total.value > 0)) return null
234
+ return Math.max(0, Math.min(1, remaining.value / total.value))
235
+ })
236
+
237
+ const { class: rootClass, attrs: rest } = useMergedAttrs(() =>
238
+ props.progress === "bar"
239
+ ? "flex w-full min-w-0 flex-col gap-1.5"
240
+ : "relative inline-flex items-center justify-center align-baseline",
241
+ )
242
+ </script>
243
+
244
+ <template>
245
+ <span
246
+ :class="rootClass"
247
+ :data-urgent="urgent || undefined"
248
+ :data-done="isDone || undefined"
249
+ v-bind="rest"
250
+ >
251
+ <LpProgress
252
+ v-if="progress === 'ring' && fraction !== null"
253
+ variant="ring"
254
+ :value="fraction * 100"
255
+ :size="ringSize"
256
+ :thickness="Math.max(3, Math.round(ringSize / 14))"
257
+ :tone="urgent ? 'danger' : 'brand'"
258
+ :animate-on-mount="false"
259
+ :duration="1000"
260
+ aria-hidden="true"
261
+ />
262
+ <span
263
+ role="timer"
264
+ :aria-label="isDone ? text.done : spokenTime"
265
+ class="inline-flex items-baseline font-mono tabular-nums transition-colors duration-(--duration-medium) motion-reduce:transition-none"
266
+ :class="[
267
+ urgent ? 'text-danger' : '',
268
+ progress === 'ring' && fraction !== null ? 'absolute text-xs font-medium' : '',
269
+ ]"
270
+ >
271
+ <LpShift axis="width">
272
+ <Transition
273
+ mode="out-in"
274
+ enter-active-class="transition-opacity duration-(--duration-fast) ease-(--ease-emphasized) motion-reduce:transition-none"
275
+ enter-from-class="opacity-0"
276
+ leave-active-class="transition-opacity duration-(--duration-fast) ease-out motion-reduce:transition-none"
277
+ leave-to-class="opacity-0"
278
+ >
279
+ <span v-if="isDone && $slots.done" key="done" class="inline-flex font-sans">
280
+ <slot name="done" />
281
+ </span>
282
+ <span v-else key="time" class="inline-flex items-baseline whitespace-nowrap" aria-hidden="true">
283
+ <template v-for="(cell, ci) in cells" :key="cell.part.unit">
284
+ <LpRollingText
285
+ v-for="digit in cell.digits"
286
+ :key="digit.key"
287
+ :value="digit.d"
288
+ direction="down"
289
+ :duration="260"
290
+ />
291
+ <span v-if="clock" class="px-px">{{ cell.part.after }}</span>
292
+ <span v-else class="font-sans text-[0.85em] text-muted" :class="ci < cells.length - 1 && 'mr-[0.35em]'">{{ cell.part.after }}</span>
293
+ </template>
294
+ </span>
295
+ </Transition>
296
+ </LpShift>
297
+ </span>
298
+ <LpProgress
299
+ v-if="progress === 'bar' && fraction !== null"
300
+ :value="fraction * 100"
301
+ :tone="urgent ? 'danger' : 'brand'"
302
+ :animate-on-mount="false"
303
+ :duration="1000"
304
+ aria-hidden="true"
305
+ />
306
+ <span v-if="announce !== false" class="sr-only" aria-live="polite" aria-atomic="true">{{ announcement }}</span>
307
+ </span>
308
+ </template>
@@ -0,0 +1,154 @@
1
+ <script lang="ts">
2
+ export default { inheritAttrs: false }
3
+
4
+ export interface DataListItem {
5
+ /** Stable key, used for slots (`#value-<key>`, `#label-<key>`) and list identity. Defaults to the label. */
6
+ key?: string
7
+ label: string
8
+ /** The value. Empty (`null`, `undefined`, `""`) shows the placeholder. */
9
+ value?: string | number | null
10
+ /** Offer a copy button for this value. */
11
+ copyable?: boolean
12
+ /** Monospace, for ids, addresses, hashes, versions. */
13
+ mono?: boolean
14
+ /** A note on what the label means, behind an info icon. */
15
+ hint?: string
16
+ }
17
+
18
+ export interface DataListLabels extends Record<string, string> {
19
+ empty: string
20
+ }
21
+ </script>
22
+
23
+ <script setup lang="ts">
24
+ /*
25
+ * Facts about one thing, as label and value pairs: a server's address,
26
+ * region, uptime and version; an account's id, plan and creation date.
27
+ *
28
+ * <LpDataList :items="[
29
+ * { label: 'Address', value: '10.0.4.12:25565', mono: true, copyable: true },
30
+ * { label: 'Region', value: 'Frankfurt' },
31
+ * { label: 'Players', value: online },
32
+ * ]" />
33
+ *
34
+ * Rendered as a real description list (<dl>/<dt>/<dd>), so assistive tech
35
+ * reads each value with its label.
36
+ *
37
+ * Side by side when there is room, label above value when there is not —
38
+ * decided by the list's OWN width (a container query), not the window's: the
39
+ * same list sits in a wide page and in a narrow side panel, and only its own
40
+ * width says which reads better. Labels share one column, so values line up.
41
+ *
42
+ * Values are watched things — a player count, a status — so a short value
43
+ * that changes rolls to the new one (LpRollingText) instead of flicking.
44
+ */
45
+ import { computed, useSlots } from "vue"
46
+ import { useLabels } from "../composables/useLpConfig"
47
+ import { useMergedAttrs } from "../composables/useMergedClass"
48
+ import LpCopyButton from "./LpCopyButton.vue"
49
+ import LpIcon from "./LpIcon.vue"
50
+ import LpRollingText from "./LpRollingText.vue"
51
+ import LpTooltip from "./LpTooltip.vue"
52
+
53
+ const props = withDefaults(
54
+ defineProps<{
55
+ items: DataListItem[]
56
+ /**
57
+ * `auto` (default) is side by side, stacking when the list itself is
58
+ * narrower than ~20rem. `horizontal` and `stacked` fix one.
59
+ */
60
+ layout?: "auto" | "horizontal" | "stacked"
61
+ /** Hairlines between rows, for a long list read as a table. */
62
+ divided?: boolean
63
+ size?: "sm" | "md"
64
+ labels?: Partial<DataListLabels>
65
+ }>(),
66
+ { layout: "auto", size: "md" },
67
+ )
68
+
69
+ const text = useLabels<DataListLabels>("dataList", { empty: "—" }, () => props.labels)
70
+ const slots = useSlots()
71
+
72
+ const keyOf = (item: DataListItem) => item.key ?? item.label
73
+ const isEmpty = (value: DataListItem["value"]) => value === null || value === undefined || value === ""
74
+ // Long text wraps; rolling a paragraph would clip it to one line.
75
+ const rolls = (value: DataListItem["value"]) => !isEmpty(value) && String(value).length <= 48
76
+
77
+ /*
78
+ * Literal classes per layout: the consuming app's Tailwind scans this file as
79
+ * text, so container variants built at runtime would never be emitted.
80
+ * - the list is a two-column grid, each row a subgrid, so every label
81
+ * shares the first column and every value starts on one line;
82
+ * - stacked collapses it to one column.
83
+ */
84
+ const GRID = {
85
+ auto: "grid-cols-1 @xs:grid-cols-[fit-content(40%)_minmax(0,1fr)]",
86
+ horizontal: "grid-cols-[fit-content(40%)_minmax(0,1fr)]",
87
+ stacked: "grid-cols-1",
88
+ } as const
89
+ const ROW = {
90
+ auto: "gap-0.5 @xs:col-span-2 @xs:grid-cols-subgrid @xs:gap-x-6",
91
+ horizontal: "col-span-2 grid-cols-subgrid gap-x-6",
92
+ stacked: "gap-0.5",
93
+ } as const
94
+
95
+ const { class: rootClass, attrs: rest } = useMergedAttrs(() => "@container w-full")
96
+ const pad = computed(() => (props.size === "sm" ? "py-1.5 text-xs" : "py-2.5 text-sm"))
97
+ </script>
98
+
99
+ <template>
100
+ <div :class="rootClass" v-bind="rest">
101
+ <TransitionGroup
102
+ tag="dl"
103
+ class="grid"
104
+ :class="GRID[layout]"
105
+ move-class="transition-transform duration-(--duration-medium) ease-(--ease-emphasized) motion-reduce:transition-none"
106
+ enter-active-class="transition-opacity duration-(--duration-medium) motion-reduce:transition-none"
107
+ enter-from-class="opacity-0"
108
+ leave-active-class="hidden"
109
+ >
110
+ <div
111
+ v-for="(item, i) in items"
112
+ :key="keyOf(item)"
113
+ class="group/row grid items-baseline"
114
+ :class="[ROW[layout], pad, divided && i > 0 ? 'border-t border-line' : '']"
115
+ >
116
+ <dt class="flex min-w-0 items-center gap-1 text-muted">
117
+ <slot :name="`label-${keyOf(item)}`" :item="item">
118
+ <slot name="label" :item="item">{{ item.label }}</slot>
119
+ </slot>
120
+ <LpTooltip v-if="item.hint" :content="item.hint">
121
+ <button
122
+ type="button"
123
+ class="grid size-4 shrink-0 place-items-center rounded-full text-muted/80 outline-none hover:text-ink focus-visible:ring-2 focus-visible:ring-ring"
124
+ :aria-label="item.hint"
125
+ >
126
+ <LpIcon name="lucide:info" :size="12" />
127
+ </button>
128
+ </LpTooltip>
129
+ </dt>
130
+ <dd class="flex min-w-0 items-center gap-1.5 text-ink" :class="item.mono ? 'font-mono' : ''">
131
+ <span class="min-w-0 break-words">
132
+ <slot
133
+ v-if="slots[`value-${keyOf(item)}`] || slots.value"
134
+ :name="slots[`value-${keyOf(item)}`] ? `value-${keyOf(item)}` : 'value'"
135
+ :item="item"
136
+ :value="item.value"
137
+ />
138
+ <span v-else-if="isEmpty(item.value)" class="text-muted">{{ text.empty }}</span>
139
+ <LpRollingText v-else-if="rolls(item.value)" :value="item.value!" align="start" />
140
+ <template v-else>{{ item.value }}</template>
141
+ </span>
142
+ <!-- Quiet until the row is hovered or focused; always there on touch,
143
+ where nothing hovers. -->
144
+ <LpCopyButton
145
+ v-if="item.copyable && !isEmpty(item.value)"
146
+ :value="String(item.value)"
147
+ size="xs"
148
+ class="-my-1 size-6 shrink-0 opacity-0 transition-opacity duration-(--duration-fast) group-hover/row:opacity-100 focus-visible:opacity-100 data-[state=copied]:opacity-100 [@media(hover:none)]:opacity-100"
149
+ />
150
+ </dd>
151
+ </div>
152
+ </TransitionGroup>
153
+ </div>
154
+ </template>