@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
@@ -0,0 +1,46 @@
1
+ import type { MeterTone } from "./meter"
2
+
3
+ /*
4
+ * The states a service, a bot or a person can be in, and what each one looks
5
+ * like. Named by meaning so a table of servers and a header pill agree on what
6
+ * "degraded" is without each picking a colour.
7
+ */
8
+ export type StatusKind =
9
+ | "online"
10
+ | "offline"
11
+ | "degraded"
12
+ | "down"
13
+ | "maintenance"
14
+ | "starting"
15
+ | "unknown"
16
+
17
+ export interface StatusLook {
18
+ tone: MeterTone
19
+ /**
20
+ * Whether the light breathes. Reserved for states that are LIVE (online:
21
+ * something is answering right now) or IN MOTION (starting: it will not stay
22
+ * like this) or demand attention (down). A pulse on every row would make the
23
+ * pulse mean nothing, so steady states stay still.
24
+ */
25
+ pulse: boolean
26
+ }
27
+
28
+ export const STATUS_LOOK: Record<StatusKind, StatusLook> = {
29
+ online: { tone: "ok", pulse: true },
30
+ offline: { tone: "neutral", pulse: false },
31
+ degraded: { tone: "warning", pulse: false },
32
+ down: { tone: "danger", pulse: true },
33
+ maintenance: { tone: "brand", pulse: false },
34
+ starting: { tone: "brand", pulse: true },
35
+ unknown: { tone: "neutral", pulse: false },
36
+ }
37
+
38
+ export const STATUS_LABELS: Record<StatusKind, string> = {
39
+ online: "Online",
40
+ offline: "Offline",
41
+ degraded: "Degraded",
42
+ down: "Down",
43
+ maintenance: "Maintenance",
44
+ starting: "Starting",
45
+ unknown: "Unknown",
46
+ }
@@ -0,0 +1,25 @@
1
+ import { computed } from "vue"
2
+ import { countValues } from "./tableFilter"
3
+
4
+ export function useTableFacets<T extends Record<string, unknown>>(options: {
5
+ rows: () => T[]
6
+ columns: () => string[]
7
+ hidden: () => Record<string, ReadonlySet<unknown>>
8
+ }) {
9
+ // Each column stays lazy: opening one filter must not compute every other filter.
10
+ const columns = computed(() => new Map(options.columns().map((key) => [key, {
11
+ distinct: computed(() => [...new Set(options.rows().map((row) => row[key]))]),
12
+ counts: computed(() => {
13
+ const others = Object.entries(options.hidden()).filter(([column, values]) => column !== key && values.size)
14
+ const rows = others.length
15
+ ? options.rows().filter((row) => others.every(([column, values]) => !values.has(row[column])))
16
+ : options.rows()
17
+ return countValues(rows, key)
18
+ }),
19
+ }])))
20
+
21
+ return {
22
+ distinct: (key: string): unknown[] => columns.value.get(key)?.distinct.value ?? [],
23
+ counts: (key: string): Map<unknown, number> | undefined => columns.value.get(key)?.counts.value,
24
+ }
25
+ }
@@ -0,0 +1,55 @@
1
+ import { graphemes } from "./scramble"
2
+
3
+ /*
4
+ * Splitting text into the pieces an entrance animates (LpTextReveal).
5
+ *
6
+ * Words are the unit of identity: each gets a key from its text and how many
7
+ * times that text appeared before it, so when the sentence changes the words
8
+ * that are still there keep their key (and their DOM node, and do not replay),
9
+ * and only the new ones animate in. Keying by position instead would replay
10
+ * every word after an insertion.
11
+ *
12
+ * Whitespace is kept as its own piece and is never animated: it stays a real
13
+ * space in the flow, which is what lets the line wrap between words. Letters
14
+ * of one word stay inside that word's box, so letter mode never breaks a word
15
+ * across lines.
16
+ */
17
+
18
+ export interface TextWord {
19
+ kind: "word"
20
+ /** Stable across edits for the same word in the same order. */
21
+ key: string
22
+ text: string
23
+ /** Letters (graphemes), or the whole word as one piece in word mode. */
24
+ parts: string[]
25
+ }
26
+
27
+ export interface TextSpace {
28
+ kind: "space"
29
+ key: string
30
+ text: string
31
+ }
32
+
33
+ export type TextPiece = TextWord | TextSpace
34
+
35
+ export function splitText(text: string, by: "word" | "letter"): TextPiece[] {
36
+ const pieces: TextPiece[] = []
37
+ const seen = new Map<string, number>()
38
+ let spaces = 0
39
+ for (const token of text.split(/(\s+)/)) {
40
+ if (!token) continue
41
+ if (/^\s+$/.test(token)) {
42
+ pieces.push({ kind: "space", key: `s${spaces++}`, text: token })
43
+ continue
44
+ }
45
+ const n = seen.get(token) ?? 0
46
+ seen.set(token, n + 1)
47
+ pieces.push({ kind: "word", key: `${token}#${n}`, text: token, parts: by === "letter" ? graphemes(token) : [token] })
48
+ }
49
+ return pieces
50
+ }
51
+
52
+ /** Keys of the words in `pieces`. */
53
+ export function wordKeys(pieces: TextPiece[]): Set<string> {
54
+ return new Set(pieces.filter((p) => p.kind === "word").map((p) => p.key))
55
+ }
@@ -0,0 +1,183 @@
1
+ /*
2
+ * Spans of time as people read them: "0:42", "2d 3h", "1m 12s".
3
+ *
4
+ * Pure functions, shared by LpCountdown (time left) and LpPipeline (time
5
+ * taken), so a job that ran for 72 seconds and a code that can be resent in 72
6
+ * seconds are written the same way. Nothing here reads the clock: callers pass
7
+ * milliseconds, which is what makes the formatting testable and lets the
8
+ * components decide how often to look at the time.
9
+ */
10
+
11
+ export interface TimeSplit {
12
+ days: number
13
+ hours: number
14
+ minutes: number
15
+ seconds: number
16
+ /** Whole milliseconds left over below a second. */
17
+ ms: number
18
+ }
19
+
20
+ export type TimeUnit = "d" | "h" | "m" | "s"
21
+
22
+ /** Unit suffixes, so an app can write "2 д 3 ч" without reformatting. */
23
+ export type TimeUnitLabels = Record<TimeUnit, string>
24
+
25
+ export const DEFAULT_UNIT_LABELS: TimeUnitLabels = { d: "d", h: "h", m: "m", s: "s" }
26
+
27
+ /**
28
+ * How a span is written.
29
+ *
30
+ * `clock` is for a short wait the eye follows second by second ("0:42",
31
+ * "1:05:09"); `units` is for a long one read at a glance ("2d 3h"); `auto` is
32
+ * clock below an hour and units above it, which is what both examples above
33
+ * want without the caller choosing.
34
+ */
35
+ export type TimeFormat = "auto" | "clock" | "units"
36
+
37
+ const SECOND = 1000
38
+ const MINUTE = 60 * SECOND
39
+ const HOUR = 60 * MINUTE
40
+ const DAY = 24 * HOUR
41
+
42
+ /** Splits a span into calendar-free parts. Negative spans count as zero. */
43
+ export function splitTime(ms: number): TimeSplit {
44
+ const total = Number.isFinite(ms) ? Math.max(0, Math.floor(ms)) : 0
45
+ return {
46
+ days: Math.floor(total / DAY),
47
+ hours: Math.floor((total % DAY) / HOUR),
48
+ minutes: Math.floor((total % HOUR) / MINUTE),
49
+ seconds: Math.floor((total % MINUTE) / SECOND),
50
+ ms: total % SECOND,
51
+ }
52
+ }
53
+
54
+ /** One printed piece of a span: a number and what follows it. */
55
+ export interface TimePart {
56
+ unit: TimeUnit
57
+ value: number
58
+ /** Digits to pad to: 2 for a clock's minutes and seconds after the first. */
59
+ pad: number
60
+ /** Text printed after the number: a unit suffix, or ":" between clock fields. */
61
+ after: string
62
+ }
63
+
64
+ /**
65
+ * A countdown rounds UP: with 41.2 s left it says 0:42, so the display only
66
+ * reaches 0:00 at the moment the wait is over. Rounding down would show 0:00
67
+ * for most of the last second while the thing is still not ready.
68
+ */
69
+ export function ceilToSecond(ms: number): number {
70
+ if (!Number.isFinite(ms) || ms <= 0) return 0
71
+ return Math.ceil(ms / SECOND) * SECOND
72
+ }
73
+
74
+ /** Which of `clock` and `units` an `auto` span resolves to. */
75
+ export function resolveFormat(ms: number, format: TimeFormat): "clock" | "units" {
76
+ if (format !== "auto") return format
77
+ return ms >= HOUR ? "units" : "clock"
78
+ }
79
+
80
+ /**
81
+ * The parts of a span in the given format.
82
+ *
83
+ * Units keep the two largest non-zero places ("2d 3h", not "2d 3h 4m 5s"): a
84
+ * long wait is read for its size, and the extra places only flicker. A span
85
+ * under a minute keeps its seconds, and zero is "0s" rather than nothing.
86
+ * The clock always has minutes and seconds and grows hours when it needs
87
+ * them; days fold into hours, since a clock reading of days is not a clock.
88
+ */
89
+ export function timeParts(
90
+ ms: number,
91
+ format: TimeFormat = "auto",
92
+ labels: TimeUnitLabels = DEFAULT_UNIT_LABELS,
93
+ places = 2,
94
+ ): TimePart[] {
95
+ const t = splitTime(ms)
96
+ if (resolveFormat(ms, format) === "clock") {
97
+ const hours = t.days * 24 + t.hours
98
+ const parts: TimePart[] = []
99
+ if (hours > 0) parts.push({ unit: "h", value: hours, pad: 1, after: ":" })
100
+ parts.push({ unit: "m", value: t.minutes, pad: hours > 0 ? 2 : 1, after: ":" })
101
+ parts.push({ unit: "s", value: t.seconds, pad: 2, after: "" })
102
+ return parts
103
+ }
104
+ const all: Array<[TimeUnit, number]> = [["d", t.days], ["h", t.hours], ["m", t.minutes], ["s", t.seconds]]
105
+ const first = all.findIndex(([, v]) => v > 0)
106
+ if (first === -1) return [{ unit: "s", value: 0, pad: 1, after: labels.s }]
107
+ return all
108
+ .slice(first, first + Math.max(1, places))
109
+ // A trailing zero place says nothing ("2d 0h"); a middle one would, but
110
+ // with two places there is no middle.
111
+ .filter(([, v], i) => i === 0 || v > 0)
112
+ .map(([unit, value]) => ({ unit, value, pad: 1, after: labels[unit] }))
113
+ }
114
+
115
+ /** Pads a part's number the way the clock prints it. */
116
+ export function padPart(part: Pick<TimePart, "value" | "pad">): string {
117
+ return String(part.value).padStart(part.pad, "0")
118
+ }
119
+
120
+ /** The span as one string — for titles, aria text and anything not animated. */
121
+ export function formatTime(
122
+ ms: number,
123
+ format: TimeFormat = "auto",
124
+ labels: TimeUnitLabels = DEFAULT_UNIT_LABELS,
125
+ places = 2,
126
+ ): string {
127
+ const parts = timeParts(ms, format, labels, places)
128
+ if (resolveFormat(ms, format) === "clock") return parts.map((p) => padPart(p) + p.after).join("")
129
+ return parts.map((p) => `${p.value}${p.after}`).join(" ")
130
+ }
131
+
132
+ /**
133
+ * Time a job took, as a CI log writes it: "850ms" under a second (a step that
134
+ * fast is still worth telling apart from one that took nothing), then "42s",
135
+ * "1m 12s", "1h 3m".
136
+ */
137
+ export function formatElapsed(ms: number, labels: TimeUnitLabels = DEFAULT_UNIT_LABELS): string {
138
+ if (!Number.isFinite(ms) || ms < 0) return ""
139
+ if (ms < SECOND) return `${Math.round(ms)}ms`
140
+ return formatTime(ms, "units", labels)
141
+ }
142
+
143
+ /**
144
+ * Milliseconds until the display next changes, so a ticking timer wakes on the
145
+ * second boundary instead of every 1000 ms from whenever it started. Started
146
+ * mid-second, a plain interval shows each value late by that fraction — and
147
+ * keeps drifting as timers fire late. Never zero: a tick that lands exactly on
148
+ * the boundary waits a whole second rather than spinning.
149
+ */
150
+ export function msToNextSecond(remaining: number): number {
151
+ if (!Number.isFinite(remaining) || remaining <= 0) return SECOND
152
+ const rest = remaining % SECOND
153
+ return rest === 0 ? SECOND : rest
154
+ }
155
+
156
+ /**
157
+ * Remaining time worth saying aloud. A timer re-read every second is noise to
158
+ * a screen reader; one that speaks when it crosses a round mark ("5 minutes
159
+ * left", "10 seconds left") is information. Returns the mark crossed going
160
+ * from `before` to `after`, or null.
161
+ */
162
+ export const DEFAULT_MILESTONES = [3600_000, 1800_000, 600_000, 300_000, 60_000, 30_000, 10_000]
163
+
164
+ export function crossedMilestone(
165
+ before: number,
166
+ after: number,
167
+ milestones: readonly number[] = DEFAULT_MILESTONES,
168
+ ): number | null {
169
+ if (!(after < before)) return null
170
+ let hit: number | null = null
171
+ for (const mark of milestones) {
172
+ if (before > mark && after <= mark) hit = hit === null ? mark : Math.min(hit, mark)
173
+ }
174
+ return hit
175
+ }
176
+
177
+ /** A date-ish input as epoch milliseconds, or NaN when it is not one. */
178
+ export function toEpoch(value: Date | string | number | null | undefined): number {
179
+ if (value === null || value === undefined || value === "") return Number.NaN
180
+ if (value instanceof Date) return value.getTime()
181
+ if (typeof value === "number") return value
182
+ return new Date(value).getTime()
183
+ }
@@ -0,0 +1,144 @@
1
+ /*
2
+ * The kit's semantic tones, once.
3
+ *
4
+ * Badges, alerts, toasts, loaders, meters, log levels and notification rows all
5
+ * colour themselves by what something MEANS: fine, worrying, broken, brand,
6
+ * nothing in particular. Each used to keep its own little map from a tone name
7
+ * to classes, and the maps drifted: a warning badge was tinted `bg-accent/15`
8
+ * while a warning row used `--color-accent-soft`, and a toaster called it
9
+ * `error` where an alert called it `danger`. Here every component looks the
10
+ * tone up, so the same meaning paints the same colour everywhere, and a theme
11
+ * that recolours `accent` recolours every warning at once.
12
+ *
13
+ * Class strings are spelled out whole on purpose. Tailwind finds classes by
14
+ * scanning source text, so a class assembled at runtime (`bg-${name}`) would
15
+ * never be emitted and the tone would silently paint nothing.
16
+ */
17
+
18
+ /** The canonical tones. Everything else is an alias of one of these. */
19
+ export type Tone = "neutral" | "brand" | "success" | "warning" | "danger"
20
+
21
+ /**
22
+ * Every name a component's `tone` prop accepts. The aliases are the names the
23
+ * kit's components grew up with (a meter says `ok`, a button palette says
24
+ * `action`, a toast says `error`), kept so no caller has to rename anything.
25
+ */
26
+ export type ToneName = Tone | "info" | "ok" | "action" | "accent" | "error" | "muted"
27
+
28
+ /** Which canonical tone each name stands for. */
29
+ export const TONE_ALIASES: Readonly<Record<ToneName, Tone>> = {
30
+ neutral: "neutral",
31
+ muted: "neutral",
32
+ brand: "brand",
33
+ info: "brand",
34
+ success: "success",
35
+ ok: "success",
36
+ action: "success",
37
+ warning: "warning",
38
+ accent: "warning",
39
+ danger: "danger",
40
+ error: "danger",
41
+ }
42
+
43
+ /** What a component needs to paint one tone. */
44
+ export interface ToneLook {
45
+ /** The solid colour, as a CSS value for a style or an SVG stroke. */
46
+ color: string
47
+ /** The tinted background colour, as a CSS value. */
48
+ soft: string
49
+ /** The solid colour as text: an icon, a label, a spinner. */
50
+ text: string
51
+ /** The solid colour as a fill: a bar, a dot, a rail. */
52
+ bg: string
53
+ /** The tinted background alone. */
54
+ softBg: string
55
+ /**
56
+ * A chip: the tinted background with text that reads on it. Not always
57
+ * `softBg + text`: neutral text on its soft surface steps up to
58
+ * muted-strong, because plain muted on surface-soft is too faint to read.
59
+ */
60
+ //
61
+ // The text is the tone mixed 60/40 with ink, not the tone itself: a light
62
+ // theme's green or amber on its own soft tint read at 2.8 to 3.4:1, under
63
+ // the 4.5 small text needs. Mixed toward ink it darkens on light themes and
64
+ // lightens on dark ones, and stays recognisably the tone (5.6 to 6.4:1 on
65
+ // light, higher on dark).
66
+ chip: string
67
+ /** The solid colour as a border. */
68
+ border: string
69
+ /** A quiet panel in the tone: a faint tint with a faint edge (an alert, a callout). */
70
+ panel: string
71
+ /** Selected text highlighted in the tone. */
72
+ selection: string
73
+ }
74
+
75
+ export const TONES: Readonly<Record<Tone, ToneLook>> = {
76
+ neutral: {
77
+ color: "var(--color-muted)",
78
+ soft: "var(--color-surface-soft)",
79
+ text: "text-muted",
80
+ bg: "bg-muted",
81
+ softBg: "bg-surface-soft",
82
+ chip: "bg-surface-soft text-muted-strong",
83
+ border: "border-line-strong",
84
+ panel: "border-line bg-surface-soft",
85
+ selection: "selection:bg-muted/40",
86
+ },
87
+ brand: {
88
+ color: "var(--color-brand)",
89
+ soft: "var(--color-brand-soft)",
90
+ text: "text-brand",
91
+ bg: "bg-brand",
92
+ softBg: "bg-brand-soft",
93
+ chip: "bg-brand-soft text-[color-mix(in_oklab,var(--color-brand)_60%,var(--color-ink))]",
94
+ border: "border-brand",
95
+ panel: "border-brand/30 bg-brand/10",
96
+ selection: "selection:bg-brand/40",
97
+ },
98
+ success: {
99
+ color: "var(--color-action)",
100
+ soft: "var(--color-action-soft)",
101
+ text: "text-action",
102
+ bg: "bg-action",
103
+ softBg: "bg-action-soft",
104
+ chip: "bg-action-soft text-[color-mix(in_oklab,var(--color-action)_60%,var(--color-ink))]",
105
+ border: "border-action",
106
+ panel: "border-action/30 bg-action/10",
107
+ selection: "selection:bg-action/40",
108
+ },
109
+ warning: {
110
+ color: "var(--color-accent)",
111
+ soft: "var(--color-accent-soft)",
112
+ text: "text-accent",
113
+ bg: "bg-accent",
114
+ softBg: "bg-accent-soft",
115
+ chip: "bg-accent-soft text-[color-mix(in_oklab,var(--color-accent)_60%,var(--color-ink))]",
116
+ border: "border-accent",
117
+ panel: "border-accent/30 bg-accent/10",
118
+ selection: "selection:bg-accent/40",
119
+ },
120
+ danger: {
121
+ color: "var(--color-danger)",
122
+ soft: "var(--color-danger-soft)",
123
+ text: "text-danger",
124
+ bg: "bg-danger",
125
+ softBg: "bg-danger-soft",
126
+ chip: "bg-danger-soft text-[color-mix(in_oklab,var(--color-danger)_60%,var(--color-ink))]",
127
+ border: "border-danger",
128
+ panel: "border-danger/30 bg-danger/10",
129
+ selection: "selection:bg-danger/40",
130
+ },
131
+ }
132
+
133
+ /**
134
+ * The canonical tone a name stands for. An unknown name (a typo, a tone from a
135
+ * newer kit read by an older one) falls back rather than painting nothing.
136
+ */
137
+ export function toneOf(name: string | null | undefined, fallback: Tone = "neutral"): Tone {
138
+ return (name && TONE_ALIASES[name as ToneName]) || fallback
139
+ }
140
+
141
+ /** How a tone is painted, by any of its names. */
142
+ export function toneLook(name: string | null | undefined, fallback: Tone = "neutral"): ToneLook {
143
+ return TONES[toneOf(name, fallback)]
144
+ }
@@ -82,7 +82,8 @@ export function openContextMenu(el: Element): () => void {
82
82
  )
83
83
  return () => {
84
84
  const outside = { bubbles: true, cancelable: true, clientX: 0, clientY: 0 }
85
- document.body.dispatchEvent(new PointerEvent("pointerdown", outside))
86
- document.body.dispatchEvent(new PointerEvent("pointerup", outside))
85
+ const body = el.ownerDocument.body
86
+ body.dispatchEvent(new PointerEvent("pointerdown", outside))
87
+ body.dispatchEvent(new PointerEvent("pointerup", outside))
87
88
  }
88
89
  }
@@ -0,0 +1,104 @@
1
+ import type { Random } from "./scramble"
2
+
3
+ /*
4
+ * The typewriter's timeline as a pure state machine (LpTypewriter).
5
+ *
6
+ * One call advances one keystroke and says how long to wait before the next,
7
+ * so the component only runs a timer, and a test can walk the whole cycle with
8
+ * a fixed random source. Strings are passed as grapheme arrays: an emoji is one
9
+ * keystroke, not two halves.
10
+ */
11
+
12
+ export interface TypewriterState {
13
+ /** The string being shown. */
14
+ index: number
15
+ /** How many of its characters are shown. */
16
+ length: number
17
+ phase: "typing" | "holding" | "erasing" | "done"
18
+ /** The string to type once erasing has gone far enough. */
19
+ to: number
20
+ }
21
+
22
+ export interface TypewriterOptions {
23
+ /** Ms per typed character, before variance. */
24
+ speed: number
25
+ /** Ms per erased character. Erasing is steady: nobody holds backspace unevenly. */
26
+ eraseSpeed: number
27
+ /** Ms a finished string stays before it is erased. */
28
+ hold: number
29
+ /** Start over after the last string instead of stopping on it. */
30
+ loop: boolean
31
+ }
32
+
33
+ export interface TypewriterStep {
34
+ state: TypewriterState
35
+ /** Ms until the next call. Infinity: nothing more to do. */
36
+ wait: number
37
+ /** Set when this step finished typing a string: its index. */
38
+ typed?: number
39
+ }
40
+
41
+ export const typewriterStart = (): TypewriterState => ({ index: 0, length: 0, phase: "typing", to: 0 })
42
+
43
+ /**
44
+ * A keystroke's delay: the base speed with some unevenness, and a pause after
45
+ * punctuation, which is where a person typing actually stops.
46
+ */
47
+ export function keystrokeDelay(char: string, speed: number, random: Random): number {
48
+ const jitter = speed * (0.55 + 0.9 * random())
49
+ if (/[.!?…]/.test(char)) return jitter + speed * 5
50
+ if (/[,;:]/.test(char)) return jitter + speed * 2.5
51
+ return jitter
52
+ }
53
+
54
+ /** Characters two strings share at the start: erasing stops there and typing goes on from it. */
55
+ export function sharedPrefix(a: string[], b: string[]): number {
56
+ let n = 0
57
+ while (n < a.length && n < b.length && a[n] === b[n]) n++
58
+ return n
59
+ }
60
+
61
+ export function typewriterNext(
62
+ state: TypewriterState,
63
+ strings: string[][],
64
+ options: TypewriterOptions,
65
+ random: Random = Math.random,
66
+ ): TypewriterStep {
67
+ const count = strings.length
68
+ if (!count) return { state: { ...state, phase: "done" }, wait: Infinity }
69
+ const current = strings[state.index] ?? []
70
+
71
+ switch (state.phase) {
72
+ case "typing": {
73
+ if (state.length >= current.length) return finish(state, count, options)
74
+ const length = state.length + 1
75
+ const next = { ...state, length }
76
+ if (length < current.length) return { state: next, wait: keystrokeDelay(current[length - 1]!, options.speed, random) }
77
+ return finish(next, count, options)
78
+ }
79
+ case "holding": {
80
+ const to = (state.index + 1) % count
81
+ return erase({ ...state, phase: "erasing", to }, strings, options)
82
+ }
83
+ case "erasing":
84
+ return erase(state, strings, options)
85
+ case "done":
86
+ return { state, wait: Infinity }
87
+ }
88
+ }
89
+
90
+ function finish(state: TypewriterState, count: number, options: TypewriterOptions): TypewriterStep {
91
+ const last = state.index === count - 1
92
+ if (last && !options.loop) return { state: { ...state, phase: "done" }, wait: Infinity, typed: state.index }
93
+ return { state: { ...state, phase: "holding" }, wait: options.hold, typed: state.index }
94
+ }
95
+
96
+ function erase(state: TypewriterState, strings: string[][], options: TypewriterOptions): TypewriterStep {
97
+ const keep = sharedPrefix(strings[state.index] ?? [], strings[state.to] ?? [])
98
+ if (state.length > keep) {
99
+ const length = state.length - 1
100
+ // The last backspace is followed by a beat before typing starts again.
101
+ return { state: { ...state, length }, wait: length > keep ? options.eraseSpeed : options.speed * 4 }
102
+ }
103
+ return { state: { index: state.to, length: state.length, phase: "typing", to: state.to }, wait: 0 }
104
+ }
@@ -3,6 +3,8 @@
3
3
  * so they can be tested without a media element.
4
4
  */
5
5
 
6
+ import { splitTime } from "./timeSpan"
7
+
6
8
  /** The stretch of a clip that loops, and how long two passes overlap at the seam. */
7
9
  export interface LoopPlan {
8
10
  /** Where every pass starts, in seconds of media time. */
@@ -63,11 +65,10 @@ export function isNativeLoop(plan: LoopPlan, duration: number): boolean {
63
65
 
64
66
  /** "1:05", "0:07.5": a position on a clip as a range slider labels it. */
65
67
  export function formatClipTime(seconds: number, precise = false): string {
66
- const safe = Math.max(0, Number.isFinite(seconds) ? seconds : 0)
67
- const minutes = Math.floor(safe / 60)
68
- const rest = safe - minutes * 60
69
- const whole = Math.floor(rest)
70
- const tenth = Math.floor((rest - whole) * 10)
71
- const secs = String(whole).padStart(2, "0")
68
+ const t = splitTime(Number.isFinite(seconds) ? seconds * 1000 : 0)
69
+ // Hours fold into minutes: a slider over a clip reads "75:00", not "1:15:00".
70
+ const minutes = (t.days * 24 + t.hours) * 60 + t.minutes
71
+ const secs = String(t.seconds).padStart(2, "0")
72
+ const tenth = Math.floor(t.ms / 100)
72
73
  return precise && tenth ? `${minutes}:${secs}.${tenth}` : `${minutes}:${secs}`
73
74
  }
@@ -27,7 +27,7 @@
27
27
  *
28
28
  * A plain function, not a reactive composable: it is read at the moment an
29
29
  * animation starts, and a component that also needs to RE-RENDER when the
30
- * setting changes mid-session should use motion-v's `useReducedMotion`.
30
+ * setting changes mid-session should use `usePrefersReducedMotion`.
31
31
  */
32
32
  export const prefersReducedMotion = (): boolean =>
33
33
  typeof window !== "undefined" &&
@@ -98,3 +98,68 @@ export const easeTravel = (t: number): number => {
98
98
  const head = (EDGE * EDGE) / (2 * EDGE) + EDGE * 0.1
99
99
  return head + ((t - EDGE) / (1 - 2 * EDGE)) * (1 - 2 * head)
100
100
  }
101
+
102
+ /**
103
+ * A cubic-bezier as a function of time, solved per call.
104
+ *
105
+ * The curves above are hand-shaped stand-ins for tokens a component reaches for
106
+ * by feel. A tween that has to match a CSS transition running beside it (a
107
+ * slice's arc easing while its colour and lift move on `--ease-emphasized`)
108
+ * needs the token's actual curve, and a theme may retune it — so this reads the
109
+ * four numbers and solves for them rather than approximating one fixed shape.
110
+ *
111
+ * Newton's method on x(s) = t, falling back to bisection where the slope is
112
+ * too flat to step on; a handful of iterations is far below a pixel.
113
+ */
114
+ export const cubicBezier = (x1: number, y1: number, x2: number, y2: number) => {
115
+ const cx = 3 * x1
116
+ const bx = 3 * (x2 - x1) - cx
117
+ const ax = 1 - cx - bx
118
+ const cy = 3 * y1
119
+ const by = 3 * (y2 - y1) - cy
120
+ const ay = 1 - cy - by
121
+ const x = (s: number) => ((ax * s + bx) * s + cx) * s
122
+ const y = (s: number) => ((ay * s + by) * s + cy) * s
123
+ const dx = (s: number) => (3 * ax * s + 2 * bx) * s + cx
124
+
125
+ return (t: number): number => {
126
+ if (t <= 0) return 0
127
+ if (t >= 1) return 1
128
+ let s = t
129
+ for (let i = 0; i < 6; i++) {
130
+ const err = x(s) - t
131
+ if (Math.abs(err) < 1e-5) return y(s)
132
+ const slope = dx(s)
133
+ if (Math.abs(slope) < 1e-6) break
134
+ s -= err / slope
135
+ }
136
+ let lo = 0
137
+ let hi = 1
138
+ s = t
139
+ for (let i = 0; i < 20; i++) {
140
+ const v = x(s)
141
+ if (Math.abs(v - t) < 1e-5) break
142
+ if (v < t) lo = s
143
+ else hi = s
144
+ s = (lo + hi) / 2
145
+ }
146
+ return y(s)
147
+ }
148
+ }
149
+
150
+ /**
151
+ * An easing token as a function, for a value tweened in script.
152
+ *
153
+ * Anything the token does not spell as a `cubic-bezier()` (a keyword, a
154
+ * `linear()` list) falls back to `easeOut`, which has the same "arrives and
155
+ * settles" intent as every curve the kit defines.
156
+ */
157
+ export const tokenEase = (
158
+ name: "ease-emphasized" | "ease-travel" | "ease-settle",
159
+ ): ((t: number) => number) => {
160
+ const match = /cubic-bezier\(([^)]+)\)/.exec(easingToken(name))
161
+ const n = match?.[1].split(",").map((p) => Number.parseFloat(p))
162
+ return n && n.length === 4 && n.every(Number.isFinite)
163
+ ? cubicBezier(n[0], n[1], n[2], n[3])
164
+ : easeOut
165
+ }