@leavepulse/ui 0.68.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 (640) 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.d.ts +10 -0
  177. package/dist/components/LpChart.vue.js +122 -142
  178. package/dist/components/LpCheckbox.vue.d.ts +2 -2
  179. package/dist/components/LpCheckbox.vue.js +1 -1
  180. package/dist/components/LpCodeBlock.vue.js +1 -1
  181. package/dist/components/LpCodeDisplay.vue.d.ts +89 -0
  182. package/dist/components/LpCodeDisplay.vue.js +4 -0
  183. package/dist/components/LpCollapse.vue.d.ts +58 -0
  184. package/dist/components/LpCollapse.vue.js +4 -0
  185. package/dist/components/LpColorPicker.vue.d.ts +2 -2
  186. package/dist/components/LpColorPicker.vue.js +1 -1
  187. package/dist/components/LpCommandPalette.vue.js +34 -23
  188. package/dist/components/LpConfirmDialog.vue.js +1 -1
  189. package/dist/components/LpConfirmHost.vue.js +1 -1
  190. package/dist/components/LpContextMenu.vue.js +1 -1
  191. package/dist/components/LpCopyButton.vue.d.ts +82 -0
  192. package/dist/components/LpCopyButton.vue.js +4 -0
  193. package/dist/components/LpCountdown.vue.d.ts +100 -0
  194. package/dist/components/LpCountdown.vue.js +4 -0
  195. package/dist/components/LpDataList.vue.d.ts +66 -0
  196. package/dist/components/LpDataList.vue.js +4 -0
  197. package/dist/components/LpDatePicker.vue.d.ts +1 -1
  198. package/dist/components/LpDatePicker.vue.js +1 -1
  199. package/dist/components/LpDateRangePicker.vue.d.ts +1 -1
  200. package/dist/components/LpDateRangePicker.vue.js +1 -1
  201. package/dist/components/LpDisclosure.vue.js +1 -1
  202. package/dist/components/LpDock.vue.d.ts +74 -0
  203. package/dist/components/LpDock.vue.js +204 -0
  204. package/dist/components/LpDrawer.vue.js +1 -1
  205. package/dist/components/LpDropdownMenu.vue.js +1 -1
  206. package/dist/components/LpDropzone.vue.d.ts +8 -1
  207. package/dist/components/LpDropzone.vue.js +36 -15
  208. package/dist/components/LpEditable.vue.d.ts +85 -0
  209. package/dist/components/LpEditable.vue.js +4 -0
  210. package/dist/components/LpEmptyState.vue.js +1 -1
  211. package/dist/components/LpFieldNotice.vue.js +1 -1
  212. package/dist/components/LpFileTree.vue.js +1 -1
  213. package/dist/components/LpFileTreeNode.vue.js +1 -1
  214. package/dist/components/LpFormField.vue.js +1 -1
  215. package/dist/components/LpFrame.vue.d.ts +22 -0
  216. package/dist/components/LpFrame.vue.js +4 -0
  217. package/dist/components/LpGauge.vue.d.ts +116 -0
  218. package/dist/components/LpGauge.vue.js +4 -0
  219. package/dist/components/LpGlowBorder.vue.d.ts +47 -0
  220. package/dist/components/LpGlowBorder.vue.js +4 -0
  221. package/dist/components/LpHintExample.vue.d.ts +2 -2
  222. package/dist/components/LpHintExample.vue.js +1 -1
  223. package/dist/components/LpHintLayer.vue.js +1 -1
  224. package/dist/components/LpHints.vue.js +1 -1
  225. package/dist/components/LpHoverCard.vue.d.ts +60 -0
  226. package/dist/components/LpHoverCard.vue.js +4 -0
  227. package/dist/components/LpIcon.vue.js +1 -1
  228. package/dist/components/LpIdenticon.vue.d.ts +37 -0
  229. package/dist/components/LpIdenticon.vue.js +4 -0
  230. package/dist/components/LpImageEditor.vue.js +13 -19
  231. package/dist/components/LpInfraNode.vue.js +1 -1
  232. package/dist/components/LpInput.vue.d.ts +10 -0
  233. package/dist/components/LpInput.vue.js +1 -1
  234. package/dist/components/LpLightbox.vue.js +1 -1
  235. package/dist/components/LpLoader.vue.d.ts +106 -0
  236. package/dist/components/LpLoader.vue.js +4 -0
  237. package/dist/components/LpLogViewer.vue.js +1 -1
  238. package/dist/components/LpMagnetic.vue.d.ts +28 -0
  239. package/dist/components/LpMagnetic.vue.js +4 -0
  240. package/dist/components/LpMapPicker.vue.js +1 -1
  241. package/dist/components/LpMasonry.vue.d.ts +42 -0
  242. package/dist/components/LpMasonry.vue.js +4 -0
  243. package/dist/components/LpMediaGallery.vue.js +1 -1
  244. package/dist/components/LpModal.vue.js +1 -1
  245. package/dist/components/LpModalNav.vue.js +1 -1
  246. package/dist/components/LpNotificationBell.vue.d.ts +15 -6
  247. package/dist/components/LpNotificationBell.vue.js +1 -1
  248. package/dist/components/LpNumberField.vue.d.ts +57 -0
  249. package/dist/components/LpNumberField.vue.js +1 -1
  250. package/dist/components/LpNumberFlow.vue.js +1 -1
  251. package/dist/components/LpOtpInput.vue.d.ts +12 -4
  252. package/dist/components/LpOtpInput.vue.js +1 -1
  253. package/dist/components/LpPagination.vue.js +1 -1
  254. package/dist/components/LpPaletteFacts.vue.js +1 -1
  255. package/dist/components/LpPaletteHeader.vue.js +2 -2
  256. package/dist/components/LpPalettePreview.vue.js +1 -1
  257. package/dist/components/LpPaletteStats.vue.js +1 -1
  258. package/dist/components/LpPasswordInput.vue.d.ts +12 -1
  259. package/dist/components/LpPasswordInput.vue.js +1 -1
  260. package/dist/components/LpPhoneInput.vue.js +1 -1
  261. package/dist/components/LpPie.vue.d.ts +3 -1
  262. package/dist/components/LpPie.vue.js +1 -1
  263. package/dist/components/LpPipeline.vue.d.ts +91 -0
  264. package/dist/components/LpPipeline.vue.js +4 -0
  265. package/dist/components/LpPopover.vue.d.ts +2 -2
  266. package/dist/components/LpPopover.vue.js +1 -1
  267. package/dist/components/LpProgress.vue.d.ts +11 -4
  268. package/dist/components/LpProgress.vue.js +1 -1
  269. package/dist/components/LpQuota.vue.d.ts +68 -0
  270. package/dist/components/LpQuota.vue.js +4 -0
  271. package/dist/components/LpRadioGroup.vue.js +1 -1
  272. package/dist/components/LpRangeCalendar.vue.js +1 -1
  273. package/dist/components/LpRangeSlider.vue.js +1 -1
  274. package/dist/components/LpRelativeTime.vue.d.ts +41 -0
  275. package/dist/components/LpRelativeTime.vue.js +4 -0
  276. package/dist/components/LpRepeater.vue.d.ts +48 -0
  277. package/dist/components/LpRepeater.vue.js +4 -0
  278. package/dist/components/LpRevealOnScroll.vue.d.ts +67 -0
  279. package/dist/components/LpRevealOnScroll.vue.js +4 -0
  280. package/dist/components/LpRollingText.vue.d.ts +1 -1
  281. package/dist/components/LpScramble.vue.d.ts +55 -0
  282. package/dist/components/LpScramble.vue.js +4 -0
  283. package/dist/components/LpScrollArea.vue.d.ts +1 -1
  284. package/dist/components/LpSecretField.vue.d.ts +108 -0
  285. package/dist/components/LpSecretField.vue.js +4 -0
  286. package/dist/components/LpSection.vue.js +1 -1
  287. package/dist/components/LpSegmented.vue.js +1 -1
  288. package/dist/components/LpSelect.vue.d.ts +2 -0
  289. package/dist/components/LpSelect.vue.js +1 -1
  290. package/dist/components/LpShaderBackdrop.vue.d.ts +39 -0
  291. package/dist/components/LpShaderBackdrop.vue.js +4 -0
  292. package/dist/components/LpShinyText.vue.d.ts +39 -0
  293. package/dist/components/LpShinyText.vue.js +4 -0
  294. package/dist/components/LpShortcutsDialog.vue.js +1 -1
  295. package/dist/components/LpSidebar.vue.js +1 -1
  296. package/dist/components/LpSidebarNav.vue.js +1 -1
  297. package/dist/components/LpSlider.vue.js +1 -1
  298. package/dist/components/LpSparkline.vue.d.ts +4 -3
  299. package/dist/components/LpSparkline.vue.js +1 -1
  300. package/dist/components/LpSpotlight.vue.d.ts +37 -0
  301. package/dist/components/LpSpotlight.vue.js +4 -0
  302. package/dist/components/LpStat.vue.js +1 -1
  303. package/dist/components/LpStatus.vue.d.ts +65 -0
  304. package/dist/components/LpStatus.vue.js +4 -0
  305. package/dist/components/LpStepMark.vue.d.ts +31 -0
  306. package/dist/components/LpStepMark.vue.js +4 -0
  307. package/dist/components/LpStepper.vue.js +1 -1
  308. package/dist/components/LpSwap.vue.js +1 -1
  309. package/dist/components/LpSwitch.vue.d.ts +2 -2
  310. package/dist/components/LpSwitch.vue.js +1 -1
  311. package/dist/components/LpTable.vue.js +104 -120
  312. package/dist/components/LpTableFilter.vue.js +1 -1
  313. package/dist/components/LpTableOfContents.vue.d.ts +6 -1
  314. package/dist/components/LpTableOfContents.vue.js +1 -1
  315. package/dist/components/LpTabs.vue.d.ts +5 -5
  316. package/dist/components/LpTabs.vue.js +25 -33
  317. package/dist/components/LpTagsInput.vue.js +1 -1
  318. package/dist/components/LpTextReveal.vue.d.ts +58 -0
  319. package/dist/components/LpTextReveal.vue.js +4 -0
  320. package/dist/components/LpTextarea.vue.js +1 -1
  321. package/dist/components/LpThemeProvider.vue.js +1 -1
  322. package/dist/components/LpThemeStudio.vue.d.ts +54 -0
  323. package/dist/components/LpThemeStudio.vue.js +4 -0
  324. package/dist/components/LpThemeStudioSection.vue.d.ts +16 -0
  325. package/dist/components/LpThemeStudioSection.vue.js +4 -0
  326. package/dist/components/LpThemeSwitcher.vue.d.ts +32 -1
  327. package/dist/components/LpThemeSwitcher.vue.js +1 -1
  328. package/dist/components/LpTimeField.vue.d.ts +2 -0
  329. package/dist/components/LpTimeField.vue.js +1 -1
  330. package/dist/components/LpToaster.vue.js +1 -1
  331. package/dist/components/LpTooltip.vue.d.ts +2 -2
  332. package/dist/components/LpTooltip.vue.js +1 -1
  333. package/dist/components/LpTopologyCanvas.vue.js +1 -1
  334. package/dist/components/LpTour.vue.js +1 -1
  335. package/dist/components/LpTruncate.vue.d.ts +34 -0
  336. package/dist/components/LpTruncate.vue.js +4 -0
  337. package/dist/components/LpTypewriter.vue.d.ts +61 -0
  338. package/dist/components/LpTypewriter.vue.js +4 -0
  339. package/dist/components/LpUptimeBar.vue.js +1 -1
  340. package/dist/components/LpVideoBackdrop.vue.js +1 -1
  341. package/dist/components/MenuTitle.vue.js +1 -1
  342. package/dist/components/OptionContent.vue.d.ts +7 -0
  343. package/dist/components/OptionContent.vue.js +4 -0
  344. package/dist/components/PickerField.vue.d.ts +43 -0
  345. package/dist/components/PickerField.vue.js +4 -0
  346. package/dist/components/RevealToggle.vue.d.ts +21 -0
  347. package/dist/components/RevealToggle.vue.js +4 -0
  348. package/dist/components/StepConnector.vue.d.ts +19 -0
  349. package/dist/components/StepConnector.vue.js +4 -0
  350. package/dist/components/TourCard.vue.js +1 -1
  351. package/dist/components/badge.d.ts +1 -0
  352. package/dist/components/badge.js +4 -0
  353. package/dist/components/chart.d.ts +5 -1
  354. package/dist/components/chart.js +2 -21
  355. package/dist/components/dateRange.d.ts +11 -0
  356. package/dist/components/dateRange.js +12 -0
  357. package/dist/components/dock.d.ts +19 -0
  358. package/dist/components/dock.js +16 -0
  359. package/dist/components/dropdown.d.ts +10 -1
  360. package/dist/components/dropdown.js +7 -2
  361. package/dist/components/fieldText.d.ts +38 -0
  362. package/dist/components/fieldText.js +53 -0
  363. package/dist/components/fileTree.d.ts +7 -3
  364. package/dist/components/fileTree.js +12 -18
  365. package/dist/components/format.d.ts +41 -0
  366. package/dist/components/format.js +67 -0
  367. package/dist/components/identicon.d.ts +38 -0
  368. package/dist/components/identicon.js +85 -0
  369. package/dist/components/masonry.d.ts +32 -0
  370. package/dist/components/masonry.js +40 -0
  371. package/dist/components/menuWhen.js +1 -1
  372. package/dist/components/meter.d.ts +64 -0
  373. package/dist/components/meter.js +53 -0
  374. package/dist/components/otp.d.ts +1 -1
  375. package/dist/components/otp.js +7 -2
  376. package/dist/components/pipeline.d.ts +55 -0
  377. package/dist/components/pipeline.js +51 -0
  378. package/dist/components/quota.d.ts +57 -0
  379. package/dist/components/quota.js +40 -0
  380. package/dist/components/relativeTime.d.ts +24 -0
  381. package/dist/components/relativeTime.js +56 -0
  382. package/dist/components/reveal.d.ts +18 -0
  383. package/dist/components/reveal.js +32 -0
  384. package/dist/components/scramble.d.ts +68 -0
  385. package/dist/components/scramble.js +58 -0
  386. package/dist/components/shaderBackdrop.d.ts +20 -0
  387. package/dist/components/shaderBackdrop.js +156 -0
  388. package/dist/components/slider.d.ts +5 -0
  389. package/dist/components/slider.js +24 -0
  390. package/dist/components/slotText.d.ts +2 -0
  391. package/dist/components/slotText.js +9 -0
  392. package/dist/components/status.d.ts +14 -0
  393. package/dist/components/status.js +22 -0
  394. package/dist/components/tableFacets.d.ts +8 -0
  395. package/dist/components/tableFacets.js +19 -0
  396. package/dist/components/textSplit.d.ts +17 -0
  397. package/dist/components/textSplit.js +24 -0
  398. package/dist/components/timeSpan.d.ts +78 -0
  399. package/dist/components/timeSpan.js +85 -0
  400. package/dist/components/tone.d.ts +43 -0
  401. package/dist/components/tone.js +82 -0
  402. package/dist/components/tour.js +3 -2
  403. package/dist/components/typewriter.d.ts +36 -0
  404. package/dist/components/typewriter.js +53 -0
  405. package/dist/components/videoBackdrop.js +5 -6
  406. package/dist/composables/easing.d.ts +22 -1
  407. package/dist/composables/easing.js +42 -1
  408. package/dist/composables/pseudoLocale.d.ts +15 -0
  409. package/dist/composables/pseudoLocale.js +96 -0
  410. package/dist/composables/scroll.js +5 -3
  411. package/dist/composables/useClipboard.d.ts +4 -1
  412. package/dist/composables/useClipboard.js +12 -2
  413. package/dist/composables/useField.d.ts +8 -0
  414. package/dist/composables/useField.js +5 -0
  415. package/dist/composables/useForm.js +19 -5
  416. package/dist/composables/useHintSystem.d.ts +4 -0
  417. package/dist/composables/useHintSystem.js +33 -1
  418. package/dist/composables/useHints.js +9 -3
  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 +61 -0
  451. package/dist/icons-all.js +1 -1
  452. package/dist/index.d.ts +98 -1
  453. package/dist/index.js +262 -104
  454. package/dist/theme/define.d.ts +12 -0
  455. package/dist/theme/studio.d.ts +90 -0
  456. package/package.json +5 -2
  457. package/src/component-names.ts +33 -0
  458. package/src/components/AttentionDot.vue +27 -0
  459. package/src/components/FieldWrapper.vue +38 -0
  460. package/src/components/LayoutNode.vue +5 -9
  461. package/src/components/LegendSwatch.vue +15 -0
  462. package/src/components/LoaderMark.vue +90 -0
  463. package/src/components/LpActionBar.vue +12 -20
  464. package/src/components/LpActivityLine.vue +186 -0
  465. package/src/components/LpAlert.vue +54 -24
  466. package/src/components/LpAppShell.vue +7 -11
  467. package/src/components/LpAutocomplete.vue +16 -14
  468. package/src/components/LpAvatar.vue +17 -2
  469. package/src/components/LpBadge.vue +77 -13
  470. package/src/components/LpBreadcrumbs.vue +101 -35
  471. package/src/components/LpButton.vue +15 -3
  472. package/src/components/LpCard.vue +30 -7
  473. package/src/components/LpChart.vue +152 -156
  474. package/src/components/LpCheckbox.vue +10 -4
  475. package/src/components/LpCodeBlock.vue +11 -19
  476. package/src/components/LpCodeDisplay.vue +228 -0
  477. package/src/components/LpCollapse.vue +162 -0
  478. package/src/components/LpColorPicker.vue +10 -1
  479. package/src/components/LpCommandPalette.vue +38 -24
  480. package/src/components/LpContextMenu.vue +10 -1
  481. package/src/components/LpCopyButton.vue +185 -0
  482. package/src/components/LpCountdown.vue +308 -0
  483. package/src/components/LpDataList.vue +154 -0
  484. package/src/components/LpDatePicker.vue +53 -104
  485. package/src/components/LpDateRangePicker.vue +49 -95
  486. package/src/components/LpDisclosure.vue +58 -36
  487. package/src/components/LpDock.vue +274 -0
  488. package/src/components/LpDrawer.vue +10 -1
  489. package/src/components/LpDropdownMenu.vue +10 -1
  490. package/src/components/LpDropzone.vue +34 -13
  491. package/src/components/LpEditable.vue +293 -0
  492. package/src/components/LpFileTree.vue +5 -1
  493. package/src/components/LpFileTreeNode.vue +25 -50
  494. package/src/components/LpFormField.vue +22 -3
  495. package/src/components/LpFrame.vue +200 -0
  496. package/src/components/LpGauge.vue +287 -0
  497. package/src/components/LpGlowBorder.vue +60 -0
  498. package/src/components/LpHintExample.vue +14 -38
  499. package/src/components/LpHintLayer.vue +13 -3
  500. package/src/components/LpHoverCard.vue +175 -0
  501. package/src/components/LpIdenticon.vue +69 -0
  502. package/src/components/LpImageEditor.vue +15 -18
  503. package/src/components/LpInfraNode.vue +27 -16
  504. package/src/components/LpInput.vue +30 -16
  505. package/src/components/LpLightbox.vue +44 -23
  506. package/src/components/LpLoader.vue +145 -0
  507. package/src/components/LpLogViewer.vue +311 -82
  508. package/src/components/LpMagnetic.vue +97 -0
  509. package/src/components/LpMapPicker.vue +26 -28
  510. package/src/components/LpMasonry.vue +247 -0
  511. package/src/components/LpModal.vue +10 -1
  512. package/src/components/LpNotificationBell.vue +33 -49
  513. package/src/components/LpNumberField.vue +79 -14
  514. package/src/components/LpNumberFlow.vue +10 -35
  515. package/src/components/LpOtpInput.vue +7 -2
  516. package/src/components/LpPagination.vue +38 -4
  517. package/src/components/LpPalettePreview.vue +2 -7
  518. package/src/components/LpPasswordInput.vue +16 -14
  519. package/src/components/LpPhoneInput.vue +12 -3
  520. package/src/components/LpPie.vue +197 -36
  521. package/src/components/LpPipeline.vue +366 -0
  522. package/src/components/LpPopover.vue +10 -1
  523. package/src/components/LpProgress.vue +22 -84
  524. package/src/components/LpQuota.vue +197 -0
  525. package/src/components/LpRangeSlider.vue +5 -1
  526. package/src/components/LpRelativeTime.vue +90 -0
  527. package/src/components/LpRepeater.vue +80 -0
  528. package/src/components/LpRevealOnScroll.vue +125 -0
  529. package/src/components/LpScramble.vue +107 -0
  530. package/src/components/LpSecretField.vue +313 -0
  531. package/src/components/LpSegmented.vue +3 -10
  532. package/src/components/LpSelect.vue +78 -64
  533. package/src/components/LpShaderBackdrop.vue +434 -0
  534. package/src/components/LpShinyText.vue +139 -0
  535. package/src/components/LpSidebar.vue +2 -0
  536. package/src/components/LpSlider.vue +5 -1
  537. package/src/components/LpSparkline.vue +55 -37
  538. package/src/components/LpSpotlight.vue +51 -0
  539. package/src/components/LpStat.vue +6 -2
  540. package/src/components/LpStatus.vue +127 -0
  541. package/src/components/LpStepMark.vue +138 -0
  542. package/src/components/LpStepper.vue +37 -43
  543. package/src/components/LpSwap.vue +2 -2
  544. package/src/components/LpSwitch.vue +15 -22
  545. package/src/components/LpTable.vue +47 -63
  546. package/src/components/LpTableFilter.vue +1 -0
  547. package/src/components/LpTableOfContents.vue +53 -29
  548. package/src/components/LpTabs.vue +10 -21
  549. package/src/components/LpTagsInput.vue +53 -37
  550. package/src/components/LpTextReveal.vue +236 -0
  551. package/src/components/LpTextarea.vue +11 -11
  552. package/src/components/LpThemeStudio.vue +216 -0
  553. package/src/components/LpThemeStudioSection.vue +16 -0
  554. package/src/components/LpThemeSwitcher.vue +156 -47
  555. package/src/components/LpTimeField.vue +9 -1
  556. package/src/components/LpToaster.vue +63 -83
  557. package/src/components/LpTooltip.vue +10 -1
  558. package/src/components/LpTour.vue +24 -13
  559. package/src/components/LpTruncate.vue +135 -0
  560. package/src/components/LpTypewriter.vue +236 -0
  561. package/src/components/LpUptimeBar.vue +6 -5
  562. package/src/components/LpVideoBackdrop.vue +15 -13
  563. package/src/components/OptionContent.vue +17 -0
  564. package/src/components/PickerField.vue +58 -0
  565. package/src/components/RevealToggle.vue +51 -0
  566. package/src/components/StepConnector.vue +54 -0
  567. package/src/components/TourCard.vue +29 -16
  568. package/src/components/badge.ts +8 -0
  569. package/src/components/chart.ts +8 -23
  570. package/src/components/dateRange.ts +25 -0
  571. package/src/components/dock.ts +31 -0
  572. package/src/components/dropdown.ts +15 -3
  573. package/src/components/fieldText.ts +95 -0
  574. package/src/components/fileTree.ts +19 -21
  575. package/src/components/format.ts +136 -0
  576. package/src/components/identicon.ts +160 -0
  577. package/src/components/masonry.ts +73 -0
  578. package/src/components/meter.ts +122 -0
  579. package/src/components/otp.ts +14 -3
  580. package/src/components/pipeline.ts +101 -0
  581. package/src/components/quota.ts +111 -0
  582. package/src/components/relativeTime.ts +118 -0
  583. package/src/components/reveal.ts +56 -0
  584. package/src/components/scramble.ts +138 -0
  585. package/src/components/shaderBackdrop.ts +208 -0
  586. package/src/components/slider.ts +30 -0
  587. package/src/components/slotText.ts +13 -0
  588. package/src/components/status.ts +46 -0
  589. package/src/components/tableFacets.ts +25 -0
  590. package/src/components/textSplit.ts +55 -0
  591. package/src/components/timeSpan.ts +183 -0
  592. package/src/components/tone.ts +144 -0
  593. package/src/components/tour.ts +3 -2
  594. package/src/components/typewriter.ts +104 -0
  595. package/src/components/videoBackdrop.ts +7 -6
  596. package/src/composables/easing.ts +66 -1
  597. package/src/composables/pseudoLocale.ts +105 -0
  598. package/src/composables/scroll.ts +6 -3
  599. package/src/composables/useClipboard.ts +25 -3
  600. package/src/composables/useField.ts +12 -0
  601. package/src/composables/useForm.ts +27 -6
  602. package/src/composables/useHintSystem.ts +40 -0
  603. package/src/composables/useHints.ts +14 -3
  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 +93 -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
@@ -44,11 +44,15 @@ import { useShift } from "../composables/useShift"
44
44
  import { useLabels } from "../composables/useLpConfig"
45
45
  import { mergeClass } from "../composables/useMergedClass"
46
46
  import LpFieldNotice from "./LpFieldNotice.vue"
47
- import LpFormField from "./LpFormField.vue"
47
+ import FieldWrapper from "./FieldWrapper.vue"
48
+ import { BADGE_REMOVE } from "./badge"
49
+ import LpBadge from "./LpBadge.vue"
48
50
  import LpIcon from "./LpIcon.vue"
49
- import { OPTION_ITEM, POPOVER_PANEL } from "./dropdown"
51
+ import OptionContent from "./OptionContent.vue"
52
+ import { OPTION_ITEM, optionStagger, POPOVER_PANEL } from "./dropdown"
50
53
  import type { LpOptionBase, OptionSelection } from "./options"
51
54
  import { addTags, splitTags, type TagDuplicates, type TagRejection, type TagValidator } from "./tags"
55
+ import { useOutsideGuard, usePortalTarget } from "../composables/useView"
52
56
 
53
57
  const props = withDefaults(
54
58
  defineProps<{
@@ -327,6 +331,7 @@ function choose(opt: LpOptionBase<string>): void {
327
331
 
328
332
  /** Clicks on the box itself are not "outside" the list: they are typing. */
329
333
  function keepOpenInside(event: Event): void {
334
+ guardOutside(event)
330
335
  const target = event.target
331
336
  if (target instanceof Node && boxEl.value?.contains(target)) event.preventDefault()
332
337
  }
@@ -413,19 +418,25 @@ function onModel(value: (string | Record<string, unknown>)[] | null): void {
413
418
  }
414
419
 
415
420
  defineExpose({ focus: () => inputEl.value?.focus(), add: (value: string) => add(value) })
421
+
422
+ // Overlays open in the window this component renders in (an LpFrame's, inside one).
423
+ const portalTo = usePortalTarget()
424
+ // What happens in another document (the page around a frame, or a frame in
425
+ // the page) is not "outside" for this layer.
426
+ const guardOutside = useOutsideGuard()
416
427
  </script>
417
428
 
418
429
  <template>
419
- <component
420
- :is="hasField ? LpFormField : 'div'"
430
+ <FieldWrapper
431
+ :wrapped="hasField"
421
432
  :ref="bindField"
422
- :label="hasField ? label : undefined"
423
- :hint="hasField ? hint : undefined"
424
- :error="hasField ? error : undefined"
425
- :required="hasField ? required : undefined"
426
- :id="hasField ? field.id : undefined"
427
- :class="hasField ? attrs.class : 'contents'"
428
- :style="hasField ? attrs.style : undefined"
433
+ :id="field.id"
434
+ :label="label"
435
+ :hint="hint"
436
+ :error="error"
437
+ :required="required"
438
+ :class="attrs.class"
439
+ :style="attrs.style"
429
440
  >
430
441
  <div class="relative">
431
442
  <TagsInputRoot
@@ -458,29 +469,39 @@ defineExpose({ focus: () => inputEl.value?.focus(), add: (value: string) => add(
458
469
  enter-active-class="animate-[chip-in_var(--duration-fast)_var(--ease-emphasized)] motion-reduce:animate-none"
459
470
  leave-active-class="animate-[chip-out_var(--duration-fast)_ease] motion-reduce:animate-none"
460
471
  >
472
+ <!-- The chip is the kit's removable badge; reka's item and delete
473
+ primitives ride on it (as-child, the #remove slot) because they
474
+ own the keyboard: arrows between tags, Backspace to remove. -->
461
475
  <TagsInputItem
462
476
  v-for="{ tag, key, shown } in keyed"
463
477
  :key="key"
464
- :data-tag-key="key"
478
+ as-child
465
479
  :value="tag"
466
- class="inline-flex max-w-full items-center gap-1 rounded-pill bg-surface-raised py-0.5 pr-1 text-xs font-medium text-ink outline-none data-[state=active]:ring-2 data-[state=active]:ring-ring"
467
- :class="shown?.image ? 'pl-0.5' : 'pl-2.5'"
468
480
  >
469
- <img v-if="shown?.image" :src="shown.image" alt="" class="size-4 shrink-0 rounded-full object-cover" />
470
- <TagsInputItemText class="flex min-w-0 items-baseline gap-1">
471
- <template v-if="shown">
472
- <span class="truncate">{{ shown.label }}</span>
473
- <span v-if="shown.hint" class="truncate font-normal text-muted">{{ shown.hint }}</span>
474
- </template>
475
- <span v-else class="truncate">{{ tag }}</span>
476
- </TagsInputItemText>
477
- <TagsInputItemDelete
478
- :aria-labelledby="undefined"
479
- :aria-label="text.remove.replace('{tag}', shown?.label ?? tag)"
480
- class="grid size-4 shrink-0 place-items-center rounded-pill text-muted transition-colors hover:bg-ink/10 hover:text-ink"
481
+ <LpBadge
482
+ removable
483
+ :data-tag-key="key"
484
+ class="max-w-full bg-surface-raised text-ink outline-none data-[state=active]:ring-2 data-[state=active]:ring-ring"
485
+ :class="shown?.image ? 'pl-0.5' : ''"
481
486
  >
482
- <LpIcon name="lucide:x" :size="12" />
483
- </TagsInputItemDelete>
487
+ <img v-if="shown?.image" :src="shown.image" alt="" class="size-4 shrink-0 rounded-full object-cover" />
488
+ <TagsInputItemText class="flex min-w-0 items-baseline gap-1">
489
+ <template v-if="shown">
490
+ <span class="truncate">{{ shown.label }}</span>
491
+ <span v-if="shown.hint" class="truncate font-normal text-muted">{{ shown.hint }}</span>
492
+ </template>
493
+ <span v-else class="truncate">{{ tag }}</span>
494
+ </TagsInputItemText>
495
+ <template #remove>
496
+ <TagsInputItemDelete
497
+ :aria-labelledby="undefined"
498
+ :aria-label="text.remove.replace('{tag}', shown?.label ?? tag)"
499
+ :class="BADGE_REMOVE"
500
+ >
501
+ <LpIcon name="lucide:x" :size="12" />
502
+ </TagsInputItemDelete>
503
+ </template>
504
+ </LpBadge>
484
505
  </TagsInputItem>
485
506
  </TransitionGroup>
486
507
  <TagsInputInput
@@ -505,7 +526,7 @@ defineExpose({ focus: () => inputEl.value?.focus(), add: (value: string) => add(
505
526
  <LpFieldNotice v-if="standalone" :notice="notice" :id="noticeId" />
506
527
  <PopoverRoot v-if="options" :open="listOpen" @update:open="(o) => !o && (dismissed = true)">
507
528
  <PopoverAnchor v-if="boxEl" :reference="boxEl" class="hidden" />
508
- <PopoverPortal>
529
+ <PopoverPortal :to="portalTo">
509
530
  <PopoverContent
510
531
  :id="listId"
511
532
  role="listbox"
@@ -533,18 +554,13 @@ defineExpose({ focus: () => inputEl.value?.focus(), add: (value: string) => add(
533
554
  :aria-disabled="opt.disabled || undefined"
534
555
  :data-highlighted="i === activeIndex ? '' : undefined"
535
556
  :data-disabled="opt.disabled ? '' : undefined"
536
- :style="{ animationDelay: `${Math.min(i, 12) * 22}ms` }"
557
+ :style="optionStagger(i)"
537
558
  :class="[OPTION_ITEM, 'data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50']"
538
559
  @pointerdown.prevent
539
560
  @pointermove="activeIndex = i"
540
561
  @click="!opt.disabled && choose(opt)"
541
562
  >
542
- <img v-if="opt.image" :src="opt.image" alt="" class="size-6 shrink-0 rounded-full object-cover" />
543
- <LpIcon v-else-if="opt.icon" :name="opt.icon" :size="16" class="shrink-0 text-muted" />
544
- <span class="flex min-w-0 flex-col">
545
- <span class="truncate">{{ opt.label ?? opt.value }}</span>
546
- <span v-if="opt.description" class="truncate text-xs text-muted">{{ opt.description }}</span>
547
- </span>
563
+ <OptionContent :option="opt" />
548
564
  </div>
549
565
  </template>
550
566
  </PopoverContent>
@@ -552,5 +568,5 @@ defineExpose({ focus: () => inputEl.value?.focus(), add: (value: string) => add(
552
568
  </PopoverRoot>
553
569
  </div>
554
570
  <span class="sr-only" aria-live="polite">{{ announcement }}</span>
555
- </component>
571
+ </FieldWrapper>
556
572
  </template>
@@ -0,0 +1,236 @@
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
+ * Text that arrives word by word (or letter by letter): each piece fades in,
9
+ * rises a few pixels and comes into focus, one after another.
10
+ *
11
+ * For a line that is the point of the screen: a hero heading, an empty state's
12
+ * message, a result that was just computed. On body copy it only slows reading
13
+ * down, so it is not a default for text in general.
14
+ *
15
+ * <LpTextReveal text="Your server is ready" as="h2" />
16
+ * <LpTextReveal :text="summary" by="letter" :stagger="15" />
17
+ *
18
+ * It plays the first time the text is on screen (useReveal), not at mount, so
19
+ * a heading below the fold is still arriving when it is scrolled to. `play`
20
+ * takes over when the moment is the app's to decide (a step becoming active),
21
+ * and a new `replayKey` plays it again.
22
+ *
23
+ * When `text` changes, the words that stay keep their place and do not replay:
24
+ * the words that are gone fade out, the new ones arrive in their spot. A status
25
+ * line going from "3 builds running" to "4 builds running" moves one word, not
26
+ * the whole sentence.
27
+ *
28
+ * Screen readers get the whole string once; the split pieces are hidden from
29
+ * them, so the sentence is not read as a list of separate words. The pieces
30
+ * are inline boxes separated by real spaces, so the text wraps like any other.
31
+ */
32
+ import { computed, onBeforeUnmount, ref, watch } from "vue"
33
+ import { prefersReducedMotion } from "../composables/easing"
34
+ import { useMergedAttrs } from "../composables/useMergedClass"
35
+ import { useReveal } from "../composables/useReveal"
36
+ import { splitText, wordKeys, type TextPiece } from "./textSplit"
37
+
38
+ const props = withDefaults(
39
+ defineProps<{
40
+ /** The text. A change animates only the words that changed. */
41
+ text: string
42
+ /** The unit that animates. Letters suit a short heading; words read better on a sentence. */
43
+ by?: "word" | "letter"
44
+ /** Delay between pieces in ms. Defaults to 70 for words, 22 for letters. */
45
+ stagger?: number
46
+ /** Each piece's entrance in ms. */
47
+ duration?: number
48
+ /** How far a piece rises, in px. 0 for a pure fade. */
49
+ rise?: number
50
+ /** Start out of focus and sharpen. Off for long text on a slow machine, where a blur per piece costs frames. */
51
+ blur?: boolean
52
+ /**
53
+ * Hold the text hidden until true. Leave unset to play the first time the
54
+ * text is on screen.
55
+ */
56
+ play?: boolean
57
+ /** Changing this plays the whole text again (the old one fades out first). */
58
+ replayKey?: unknown
59
+ /** Element to render: `h1`…`h6` or `p` for a heading or a paragraph. */
60
+ as?: string
61
+ }>(),
62
+ { by: "word", duration: 560, rise: 8, blur: true, play: undefined, as: "span" },
63
+ )
64
+
65
+ const emit = defineEmits<{
66
+ /** The last piece has arrived. */
67
+ done: []
68
+ }>()
69
+
70
+ const { class: rootClass, attrs: rest } = useMergedAttrs(() => "lp-reveal")
71
+
72
+ const LEAVE_MS = 180
73
+
74
+ const { el, revealed } = useReveal({ immediate: () => props.play !== undefined })
75
+ const ready = computed(() => props.play ?? revealed.value)
76
+
77
+ const shown = ref(props.text)
78
+ const generation = ref(0)
79
+ const pieces = computed<TextPiece[]>(() =>
80
+ splitText(shown.value, props.by).map((p) => ({ ...p, key: `${generation.value}:${p.key}` })),
81
+ )
82
+ // The words that animate in on this pass; everything else stays as it is.
83
+ const fresh = ref<Set<string>>(wordKeys(pieces.value))
84
+ const leaving = ref<Set<string>>(new Set())
85
+
86
+ const stagger = computed(() => props.stagger ?? (props.by === "letter" ? 22 : 70))
87
+
88
+ // The position of each fresh part in the cascade. Counted over fresh parts only,
89
+ // so a single changed word in a long line starts at once instead of waiting for
90
+ // the words before it.
91
+ const order = computed(() => {
92
+ const map = new Map<string, number>()
93
+ let i = 0
94
+ for (const piece of pieces.value) {
95
+ if (piece.kind !== "word" || !fresh.value.has(piece.key)) continue
96
+ map.set(piece.key, i)
97
+ i += piece.parts.length
98
+ }
99
+ return { map, count: i }
100
+ })
101
+
102
+ let leaveTimer: ReturnType<typeof setTimeout> | undefined
103
+ let doneTimer: ReturnType<typeof setTimeout> | undefined
104
+
105
+ function scheduleDone() {
106
+ clearTimeout(doneTimer)
107
+ if (!ready.value) return
108
+ const count = order.value.count
109
+ const ms = prefersReducedMotion() || count === 0 ? 0 : props.duration + stagger.value * (count - 1)
110
+ doneTimer = setTimeout(() => emit("done"), ms)
111
+ }
112
+
113
+ function apply(text: string, bump: boolean) {
114
+ const before = wordKeys(pieces.value)
115
+ if (bump) generation.value++
116
+ shown.value = text
117
+ const after = wordKeys(pieces.value)
118
+ // Before the reveal everything is still to come; after it, only what is new.
119
+ fresh.value = ready.value ? new Set([...after].filter((k) => !before.has(k))) : after
120
+ leaving.value = new Set()
121
+ scheduleDone()
122
+ }
123
+
124
+ function change(text: string, bump: boolean) {
125
+ clearTimeout(leaveTimer)
126
+ if (!ready.value || prefersReducedMotion()) return apply(text, bump)
127
+ const next = new Set(
128
+ splitText(text, props.by).map((p) => `${generation.value + (bump ? 1 : 0)}:${p.key}`),
129
+ )
130
+ const gone = [...wordKeys(pieces.value)].filter((k) => !next.has(k))
131
+ if (!gone.length) return apply(text, bump)
132
+ leaving.value = new Set(gone)
133
+ leaveTimer = setTimeout(() => apply(text, bump), LEAVE_MS)
134
+ }
135
+
136
+ watch(() => props.text, (text) => change(text, false))
137
+ watch(() => props.replayKey, () => change(props.text, true))
138
+ watch(() => props.by, () => apply(props.text, true))
139
+ watch(ready, (now) => now && scheduleDone(), { immediate: true })
140
+
141
+ onBeforeUnmount(() => {
142
+ clearTimeout(leaveTimer)
143
+ clearTimeout(doneTimer)
144
+ })
145
+
146
+ const style = computed(() => ({
147
+ "--lp-reveal-duration": `${props.duration}ms`,
148
+ "--lp-reveal-stagger": `${stagger.value}ms`,
149
+ "--lp-reveal-rise": `${props.rise}px`,
150
+ "--lp-reveal-blur": props.blur ? "4px" : "0px",
151
+ "--lp-reveal-leave": `${LEAVE_MS}ms`,
152
+ }))
153
+
154
+ // A leaving word drops its entrance: an animation's fill outranks the fade-out
155
+ // declaration, and the word would stay fully visible until it is removed.
156
+ function partClass(key: string) {
157
+ if (leaving.value.has(key)) return "lp-reveal__part lp-reveal__part--out"
158
+ return ready.value && fresh.value.has(key) ? "lp-reveal__part lp-reveal__part--in" : "lp-reveal__part"
159
+ }
160
+ </script>
161
+
162
+ <template>
163
+ <component
164
+ :is="as"
165
+ ref="el"
166
+ :class="[rootClass, ready ? '' : 'lp-reveal--waiting']"
167
+ :style="style"
168
+ v-bind="rest"
169
+ >
170
+ <span class="sr-only">{{ text }}</span>
171
+ <span aria-hidden="true"
172
+ ><template v-for="piece in pieces" :key="piece.key"
173
+ ><template v-if="piece.kind === 'space'">{{ piece.text }}</template
174
+ ><span
175
+ v-else-if="by === 'word'"
176
+ :class="partClass(piece.key)"
177
+ :style="{ '--lp-reveal-i': order.map.get(piece.key) ?? 0 }"
178
+ >{{ piece.text }}</span
179
+ ><span
180
+ v-else
181
+ class="inline-block whitespace-nowrap"
182
+ :class="leaving.has(piece.key) ? 'lp-reveal__part--out' : ''"
183
+ ><span
184
+ v-for="(letter, j) in piece.parts"
185
+ :key="j"
186
+ :class="leaving.has(piece.key) ? 'lp-reveal__part' : partClass(piece.key)"
187
+ :style="{ '--lp-reveal-i': (order.map.get(piece.key) ?? 0) + j }"
188
+ >{{ letter }}</span
189
+ ></span
190
+ ></template
191
+ ></span
192
+ >
193
+ </component>
194
+ </template>
195
+
196
+ <style>
197
+ /* Unscoped and namespaced, like LpRollingText: the classes are toggled on
198
+ elements rendered inside a v-for of fragments. */
199
+ .lp-reveal__part {
200
+ display: inline-block;
201
+ }
202
+
203
+ .lp-reveal--waiting .lp-reveal__part {
204
+ opacity: 0;
205
+ }
206
+
207
+ .lp-reveal__part--in {
208
+ animation: lp-reveal-in var(--lp-reveal-duration) var(--ease-emphasized) both;
209
+ animation-delay: calc(var(--lp-reveal-i, 0) * var(--lp-reveal-stagger));
210
+ }
211
+
212
+ .lp-reveal__part--out {
213
+ opacity: 0;
214
+ filter: blur(var(--lp-reveal-blur));
215
+ transition:
216
+ opacity var(--lp-reveal-leave) ease-in,
217
+ filter var(--lp-reveal-leave) ease-in;
218
+ }
219
+
220
+ @keyframes lp-reveal-in {
221
+ from {
222
+ opacity: 0;
223
+ transform: translateY(var(--lp-reveal-rise));
224
+ filter: blur(var(--lp-reveal-blur));
225
+ }
226
+ }
227
+
228
+ @media (prefers-reduced-motion: reduce) {
229
+ .lp-reveal__part--in {
230
+ animation: none;
231
+ }
232
+ .lp-reveal__part--out {
233
+ transition: none;
234
+ }
235
+ }
236
+ </style>
@@ -6,7 +6,7 @@ export default { inheritAttrs: false }
6
6
  import { computed, useAttrs } from "vue"
7
7
  import { useFieldControl } from "../composables/useField"
8
8
  import { mergeClass } from "../composables/useMergedClass"
9
- import LpFormField from "./LpFormField.vue"
9
+ import FieldWrapper from "./FieldWrapper.vue"
10
10
 
11
11
  const props = defineProps<{
12
12
  modelValue?: string
@@ -56,15 +56,15 @@ const textareaClass = computed(() =>
56
56
  </script>
57
57
 
58
58
  <template>
59
- <component
60
- :is="hasField ? LpFormField : 'div'"
61
- :id="hasField ? field.id : undefined"
62
- :label="hasField ? label : undefined"
63
- :hint="hasField ? hint : undefined"
64
- :error="hasField ? error : undefined"
65
- :required="hasField ? required : undefined"
66
- :class="hasField ? attrs.class : 'contents'"
67
- :style="hasField ? attrs.style : undefined"
59
+ <FieldWrapper
60
+ :wrapped="hasField"
61
+ :id="field.id"
62
+ :label="label"
63
+ :hint="hint"
64
+ :error="error"
65
+ :required="required"
66
+ :class="attrs.class"
67
+ :style="attrs.style"
68
68
  >
69
69
  <textarea
70
70
  v-bind="textareaAttrs"
@@ -80,5 +80,5 @@ const textareaClass = computed(() =>
80
80
  :style="hasField ? undefined : (attrs.style as never)"
81
81
  @input="$emit('update:modelValue', ($event.target as HTMLTextAreaElement).value)"
82
82
  />
83
- </component>
83
+ </FieldWrapper>
84
84
  </template>
@@ -0,0 +1,216 @@
1
+ <script setup lang="ts">
2
+ /*
3
+ * The theme, tuned in place: a base theme, any brand colour, corners, control
4
+ * size and motion speed, all applied live, and the result ready to take away
5
+ * as code, JSON or CSS. State lives in useThemeStudio (remembered, shared with
6
+ * an LpThemeSwitcher opened with `studio`), so the panel can sit in a popover,
7
+ * a settings page or a drawer.
8
+ *
9
+ * An app adds its own rows through `#start` and `#end` (LpThemeStudioSection
10
+ * gives them the panel's look) and drops built-in ones with `hide`.
11
+ */
12
+ import { computed, ref } from "vue"
13
+ import { useLabels } from "../composables/useLpConfig"
14
+ import { STUDIO_BRANDS, STUDIO_SYSTEM, useThemeStudio, type StudioState, type ThemeStudio } from "../theme/studio"
15
+ import type { TokenSet } from "../theme/tokens"
16
+ import type { RevealOrigin } from "../theme/useTheme"
17
+ import LpButton from "./LpButton.vue"
18
+ import LpCodeBlock from "./LpCodeBlock.vue"
19
+ import LpColorPicker from "./LpColorPicker.vue"
20
+ import LpIcon from "./LpIcon.vue"
21
+ import LpSegmented from "./LpSegmented.vue"
22
+ import LpThemeStudioSection from "./LpThemeStudioSection.vue"
23
+
24
+ export type ThemeStudioPart = "themes" | "brand" | "corners" | "size" | "motion" | "export"
25
+
26
+ export interface ThemeStudioLabels extends Record<string, string> {
27
+ title: string
28
+ reset: string
29
+ themes: string
30
+ system: string
31
+ brand: string
32
+ anyBrand: string
33
+ corners: string
34
+ sharp: string
35
+ round: string
36
+ size: string
37
+ compact: string
38
+ comfortable: string
39
+ motion: string
40
+ fast: string
41
+ normal: string
42
+ slow: string
43
+ default: string
44
+ export: string
45
+ }
46
+
47
+ const props = defineProps<{
48
+ /** A studio from useThemeStudio; by default the shared one for `storageKey`. */
49
+ studio?: ThemeStudio
50
+ /** Base themes, when the panel makes its own studio. */
51
+ themes?: TokenSet[]
52
+ storageKey?: string
53
+ /** Brand swatches offered beside the free colour picker. */
54
+ brands?: string[]
55
+ /** Built-in rows to leave out. */
56
+ hide?: ThemeStudioPart[]
57
+ labels?: Partial<ThemeStudioLabels>
58
+ }>()
59
+
60
+ const studio = props.studio ?? useThemeStudio({ themes: props.themes, storageKey: props.storageKey })
61
+ const { state, brand, changed, exported } = studio
62
+ // Assigned through the ref: a destructured binding assigned in the template
63
+ // would replace the local name, not write the studio's state.
64
+ const setBrand = (color: string) => (brand.value = color)
65
+
66
+ const text = useLabels<ThemeStudioLabels>(
67
+ "themeStudio",
68
+ {
69
+ title: "Theme",
70
+ reset: "Reset",
71
+ themes: "Theme",
72
+ system: "System",
73
+ brand: "Brand colour",
74
+ anyBrand: "Any brand colour",
75
+ corners: "Corners",
76
+ sharp: "Sharp",
77
+ round: "Round",
78
+ size: "Control size",
79
+ compact: "Compact",
80
+ comfortable: "Roomy",
81
+ motion: "Motion",
82
+ fast: "Fast",
83
+ normal: "Normal",
84
+ slow: "Slow",
85
+ default: "Default",
86
+ export: "Use this theme",
87
+ },
88
+ () => props.labels,
89
+ )
90
+
91
+ const shows = (part: ThemeStudioPart) => !props.hide?.includes(part)
92
+ const swatches = computed(() => props.brands ?? STUDIO_BRANDS)
93
+ const format = ref<"code" | "json" | "css">("code")
94
+
95
+ // A new base theme reveals from the swatch that picked it; Reset from itself.
96
+ function origin(event: Event): RevealOrigin | undefined {
97
+ const r = (event.currentTarget as Element | null)?.getBoundingClientRect()
98
+ return r ? { x: r.left + r.width / 2, y: r.top + r.height / 2 } : undefined
99
+ }
100
+
101
+ const TILE =
102
+ "flex min-w-0 flex-col items-center gap-1 rounded-control p-1.5 text-[11px] text-muted transition-colors duration-(--duration-fast) hover:bg-surface-soft hover:text-ink"
103
+ const SWATCH = "relative size-8 overflow-hidden rounded-full ring-2 transition-[box-shadow] duration-(--duration-fast)"
104
+
105
+ const tuneTo = <K extends keyof Omit<StudioState, "theme">>(key: K) =>
106
+ (value: string) => studio.tune({ [key]: value } as Partial<StudioState>)
107
+ </script>
108
+
109
+ <template>
110
+ <div class="flex flex-col gap-4">
111
+ <div class="flex items-center justify-between">
112
+ <p class="text-sm font-semibold text-ink">{{ text.title }}</p>
113
+ <LpButton v-if="changed" variant="ghost" size="xs" @click="studio.reset(origin($event))">
114
+ <LpIcon name="lucide:rotate-ccw" :size="12" />{{ text.reset }}
115
+ </LpButton>
116
+ </div>
117
+
118
+ <slot name="start" :studio="studio" />
119
+
120
+ <LpThemeStudioSection v-if="shows('themes')" :label="text.themes">
121
+ <div class="grid grid-cols-4 gap-2">
122
+ <!-- Follows the OS between its pair: drawn as both halves. -->
123
+ <button
124
+ v-if="studio.system.value"
125
+ type="button"
126
+ :class="[TILE, state.theme === STUDIO_SYSTEM && 'bg-surface-soft text-ink']"
127
+ :aria-pressed="state.theme === STUDIO_SYSTEM"
128
+ @click="studio.pickTheme(STUDIO_SYSTEM, origin($event))"
129
+ >
130
+ <span
131
+ :class="[SWATCH, state.theme === STUDIO_SYSTEM ? 'ring-brand' : 'ring-line']"
132
+ :style="{ background: `linear-gradient(135deg, ${studio.system.value.light.colors.surface} 50%, ${studio.system.value.dark.colors.surface} 50%)` }"
133
+ />
134
+ <span class="max-w-full truncate">{{ text.system }}</span>
135
+ </button>
136
+ <button
137
+ v-for="t in studio.themes.value"
138
+ :key="t.name"
139
+ type="button"
140
+ :class="[TILE, state.theme === t.name && 'bg-surface-soft text-ink']"
141
+ :aria-pressed="state.theme === t.name"
142
+ @click="studio.pickTheme(t.name, origin($event))"
143
+ >
144
+ <span :class="[SWATCH, state.theme === t.name ? 'ring-brand' : 'ring-line']" :style="{ background: t.colors.surface }">
145
+ <span class="absolute inset-x-0 bottom-0 h-1/2" :style="{ background: t.colors.brand }" />
146
+ </span>
147
+ <span class="max-w-full truncate">{{ t.name }}</span>
148
+ </button>
149
+ </div>
150
+ </LpThemeStudioSection>
151
+
152
+ <LpThemeStudioSection v-if="shows('brand')" :label="text.brand">
153
+ <div class="flex flex-wrap items-center gap-1.5">
154
+ <button
155
+ v-for="color in swatches"
156
+ :key="color"
157
+ type="button"
158
+ class="size-6 rounded-full ring-2 ring-offset-2 ring-offset-surface-raised transition-[box-shadow,scale] duration-(--duration-fast) hover:scale-110"
159
+ :class="brand === color ? 'ring-ink' : 'ring-transparent'"
160
+ :style="{ background: color }"
161
+ :aria-label="`${text.brand} ${color}`"
162
+ :aria-pressed="brand === color"
163
+ @click="setBrand(color)"
164
+ />
165
+ <LpColorPicker :model-value="brand" size="sm" :aria-label="text.anyBrand" @update:model-value="setBrand" />
166
+ </div>
167
+ </LpThemeStudioSection>
168
+
169
+ <LpThemeStudioSection v-if="shows('corners')" :label="text.corners">
170
+ <LpSegmented
171
+ :model-value="state.corners"
172
+ size="sm"
173
+ :options="[{ value: 'sharp', label: text.sharp }, { value: 'default', label: text.default }, { value: 'round', label: text.round }]"
174
+ @update:model-value="tuneTo('corners')"
175
+ />
176
+ </LpThemeStudioSection>
177
+
178
+ <LpThemeStudioSection v-if="shows('size')" :label="text.size">
179
+ <LpSegmented
180
+ :model-value="state.size"
181
+ size="sm"
182
+ :options="[{ value: 'compact', label: text.compact }, { value: 'default', label: text.default }, { value: 'comfortable', label: text.comfortable }]"
183
+ @update:model-value="tuneTo('size')"
184
+ />
185
+ </LpThemeStudioSection>
186
+
187
+ <LpThemeStudioSection v-if="shows('motion')" :label="text.motion">
188
+ <LpSegmented
189
+ :model-value="state.motion"
190
+ size="sm"
191
+ :options="[{ value: 'fast', label: text.fast }, { value: 'normal', label: text.normal }, { value: 'slow', label: text.slow }]"
192
+ @update:model-value="tuneTo('motion')"
193
+ />
194
+ </LpThemeStudioSection>
195
+
196
+ <slot name="end" :studio="studio" />
197
+
198
+ <div v-if="shows('export')" class="flex flex-col gap-2 border-t border-line pt-3">
199
+ <div class="flex items-center justify-between gap-2">
200
+ <span class="text-[11px] font-medium tracking-wide text-muted uppercase">{{ text.export }}</span>
201
+ <LpSegmented
202
+ v-model="format"
203
+ size="sm"
204
+ :options="[{ value: 'code', label: 'Code' }, { value: 'json', label: 'JSON' }, { value: 'css', label: 'CSS' }]"
205
+ />
206
+ </div>
207
+ <LpCodeBlock
208
+ :model-value="exported[format]"
209
+ :lang="format === 'json' ? 'json' : format === 'css' ? 'plain' : 'ts'"
210
+ copyable
211
+ height="140px"
212
+ class="text-[11px]"
213
+ />
214
+ </div>
215
+ </div>
216
+ </template>
@@ -0,0 +1,16 @@
1
+ <script setup lang="ts">
2
+ /*
3
+ * One row of LpThemeStudio: a small caps label over its controls. The studio
4
+ * builds its own rows with it, and an app adding its own (a font, a density
5
+ * of its own, a layout switch) through the studio's slots uses it too, so the
6
+ * added row reads as part of the panel.
7
+ */
8
+ defineProps<{ label: string }>()
9
+ </script>
10
+
11
+ <template>
12
+ <div class="flex flex-col gap-2">
13
+ <span class="text-[11px] font-medium tracking-wide text-muted uppercase">{{ label }}</span>
14
+ <slot />
15
+ </div>
16
+ </template>