@leavepulse/ui 0.43.4 → 0.45.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 (437) hide show
  1. package/README.md +121 -7
  2. package/dist/assets/{LpCommandPalette-B-0Est4Z.css → LpCommandPalette-nGNnzXqQ.css} +21 -21
  3. package/dist/assets/{LpDropzone-BBoWvi-J.css → LpDropzone-i4BdMi1H.css} +12 -12
  4. package/dist/assets/{LpImageEditor-Ct7Y3aNu.css → LpImageEditor-CbMA82g8.css} +6 -6
  5. package/dist/assets/{LpRollingText-CR1mb0Vt.css → LpRollingText-BGnE6q9j.css} +3 -0
  6. package/dist/assets/{LpShortcutsDialog-C6YoQ8_M.css → LpShortcutsDialog-CqYX3yy6.css} +28 -7
  7. package/dist/assets/{LpSkeleton-D7xU8IPV.css → LpSkeleton-H3Z5dEIk.css} +4 -1
  8. package/dist/assets/{LpTable-BgPLJOXa.css → LpTable-CPwWxTJS.css} +49 -9
  9. package/dist/chunks/ContextMenuItems-BtKU7074.js +124 -0
  10. package/dist/chunks/{LayoutCanvas-Dd20boUG.js → LayoutCanvas-BkaGXTjx.js} +26 -9
  11. package/dist/chunks/{LayoutNode-DGpZA9LX.js → LayoutNode-B3_9E1Xa.js} +28 -12
  12. package/dist/chunks/{LpActionBar-BlvtGB2P.js → LpActionBar-CnfFVIwC.js} +26 -12
  13. package/dist/chunks/{LpAddressInput-B-Zvxsn7.js → LpAddressInput-BwX8uo4_.js} +54 -49
  14. package/dist/chunks/{LpAlert-BAYHDSS1.js → LpAlert-B6ilrM7T.js} +16 -9
  15. package/dist/chunks/{LpAppShell-BGQVIY-3.js → LpAppShell-C53_RaGF.js} +53 -26
  16. package/dist/chunks/{LpAutocomplete-DExlIZe_.js → LpAutocomplete-C8IgSMsi.js} +52 -24
  17. package/dist/chunks/{LpAvatar-B3-xAOH3.js → LpAvatar-C1XStdOo.js} +19 -10
  18. package/dist/chunks/LpBreadcrumbs-CQJd73Gm.js +95 -0
  19. package/dist/chunks/{LpButton-5VXXCjwF.js → LpButton-CKSwC6Mu.js} +45 -15
  20. package/dist/chunks/{LpCalendar-B7Ko5RdR.js → LpCalendar-DrA2McTU.js} +1 -1
  21. package/dist/chunks/{LpCard-BhI1N_vL.js → LpCard-C2IvucmX.js} +1 -1
  22. package/dist/chunks/{LpCheckbox-CVccKYaH.js → LpCheckbox-Bkj13CbW.js} +8 -4
  23. package/dist/chunks/{LpCodeBlock-Bo0B4TFR.js → LpCodeBlock-ca7ANFyW.js} +49 -17
  24. package/dist/chunks/{LpColorPicker-BlXea7LM.js → LpColorPicker-zz4VGkG4.js} +75 -26
  25. package/dist/chunks/{LpConfirmDialog-Q-bxff8z.js → LpConfirmDialog-DCw5jR1t.js} +59 -17
  26. package/dist/chunks/LpConfirmHost-CbywMpMP.js +49 -0
  27. package/dist/chunks/LpContextMenu-BqkAYa9X.js +69 -0
  28. package/dist/chunks/LpDatePicker-DuusgT69.js +195 -0
  29. package/dist/chunks/LpDateRangePicker-DHeuznfC.js +208 -0
  30. package/dist/chunks/{LpDisclosure-ChQYmjlR.js → LpDisclosure-Cc23-JOT.js} +1 -1
  31. package/dist/chunks/{LpDrawer-BZ6k3hvo.js → LpDrawer-Dt4aB4Fr.js} +65 -28
  32. package/dist/chunks/{LpDropdownMenu-DJpoqRCb.js → LpDropdownMenu-DdJGQzPn.js} +2 -1
  33. package/dist/chunks/{LpEmptyState-Dsdqz1Wj.js → LpEmptyState-BJbZXC8D.js} +1 -1
  34. package/dist/chunks/LpFieldNotice-wtieLUTj.js +64 -0
  35. package/dist/chunks/{LpFileTree-_5vFBgaK.js → LpFileTree-CNurOvkV.js} +25 -10
  36. package/dist/chunks/{LpFileTreeNode-BdcIYKIE.js → LpFileTreeNode-D_qRRdsH.js} +3 -3
  37. package/dist/chunks/LpFormField-CtVYj6tO.js +101 -0
  38. package/dist/chunks/{LpIcon-CCnX5_2j.js → LpIcon-DYtaid0K.js} +20 -6
  39. package/dist/chunks/{LpInput-9EXWUM9B.js → LpInput-D-YGQbEv.js} +58 -20
  40. package/dist/chunks/{LpLightbox-2sYVMY-S.js → LpLightbox-DSDahF23.js} +148 -61
  41. package/dist/chunks/{LpLink-DCND-zyu.js → LpLink-Krkjhe_y.js} +15 -6
  42. package/dist/chunks/{LpLogViewer-CaRy5MeS.js → LpLogViewer-KypbgOyo.js} +300 -72
  43. package/dist/chunks/{LpMapPicker-ul4oYno6.js → LpMapPicker-Cc84LaM3.js} +39 -14
  44. package/dist/chunks/{LpMediaGallery-FF-NquIo.js → LpMediaGallery-YKr-cQPN.js} +7 -4
  45. package/dist/chunks/{LpModal-Bt0pQCI_.js → LpModal-DMMDQHAu.js} +52 -29
  46. package/dist/chunks/{LpModalNav-YaifHrXC.js → LpModalNav-BVPDyIup.js} +10 -7
  47. package/dist/chunks/{LpNotificationBell-DyGGsMAM.js → LpNotificationBell-CCwyJP5C.js} +79 -33
  48. package/dist/chunks/{LpNumberField-CWuX08iX.js → LpNumberField-B77O-z28.js} +21 -8
  49. package/dist/chunks/{LpNumberFlow-amWYaeuA.js → LpNumberFlow-z4WPZcZu.js} +22 -12
  50. package/dist/chunks/{LpOtpInput-y2v-pmiN.js → LpOtpInput-CziPF3Oq.js} +37 -8
  51. package/dist/chunks/{LpPagination-5FxjmmB5.js → LpPagination-BcDlo3r_.js} +31 -20
  52. package/dist/chunks/{LpPasswordInput--sjYCkLS.js → LpPasswordInput-eKzQhbQP.js} +11 -8
  53. package/dist/chunks/LpPhoneInput-BCbrrhgE.js +336 -0
  54. package/dist/chunks/{LpPie-D6OnzwlJ.js → LpPie-BEJ2SfI6.js} +84 -28
  55. package/dist/chunks/{LpPopover-8268UmlC.js → LpPopover-DCKeqiVn.js} +5 -2
  56. package/dist/chunks/{LpProgress-Btq5W4Ut.js → LpProgress-CBU1iI69.js} +5 -4
  57. package/dist/chunks/{LpRadioGroup-xPIuVDO_.js → LpRadioGroup-DmEW0l78.js} +9 -2
  58. package/dist/chunks/LpRangeCalendar-DZuaRV0W.js +331 -0
  59. package/dist/chunks/{LpRollingText-CM5gkSeF.js → LpRollingText-DB7upf-5.js} +1 -1
  60. package/dist/chunks/{LpScrollArea-D8xyKXcF.js → LpScrollArea-Bry1fdOM.js} +14 -2
  61. package/dist/chunks/{LpSection-aM6J_u51.js → LpSection-tKEH0jYf.js} +1 -1
  62. package/dist/chunks/{LpSegmented-fV0Sk92p.js → LpSegmented-C09EEam2.js} +8 -4
  63. package/dist/chunks/{LpSelect-ANIVtrpM.js → LpSelect-DNIL6MB9.js} +50 -31
  64. package/dist/chunks/{LpSidebar-ClBUwoEz.js → LpSidebar-CQNB0-yU.js} +30 -22
  65. package/dist/chunks/{LpSidebarNav-llOcs_Fn.js → LpSidebarNav-kx-LdqNU.js} +16 -11
  66. package/dist/chunks/{LpSkeleton-CTI-vBgW.js → LpSkeleton-BB6XIV-w.js} +1 -1
  67. package/dist/chunks/{LpSlider-BwNIBkAK.js → LpSlider-Cuzmrd7p.js} +7 -2
  68. package/dist/chunks/{LpSparkline-C6xQ2dwv.js → LpSparkline-CB80N8SJ.js} +11 -4
  69. package/dist/chunks/{LpStat-CQaW8R--.js → LpStat-B-7udBRP.js} +2 -2
  70. package/dist/chunks/{LpStepper-Bk-XaQYU.js → LpStepper-C7XiVKZj.js} +34 -19
  71. package/dist/chunks/{LpSwitch-Blizvqyt.js → LpSwitch-OrcOJX9m.js} +41 -27
  72. package/dist/chunks/LpTableFilter-BV8PpLM9.js +158 -0
  73. package/dist/chunks/{LpTableOfContents-CjvxPMpU.js → LpTableOfContents-BUcAfGPQ.js} +36 -41
  74. package/dist/chunks/{LpTabs-Cefe_lys.js → LpTabs-29iW1XOx.js} +20 -6
  75. package/dist/chunks/LpTagsInput-D1SuqbhB.js +300 -0
  76. package/dist/chunks/LpTextarea-uuScWo6-.js +77 -0
  77. package/dist/chunks/LpThemeProvider-Be4r2TQX.js +35 -0
  78. package/dist/chunks/LpThemeSwitcher-B4aVPbNC.js +166 -0
  79. package/dist/chunks/{LpTilt-DuyKbpkA.js → LpTilt-B7KHX1zH.js} +2 -2
  80. package/dist/chunks/{LpTimeField-K6nAGboX.js → LpTimeField-Cqe7fXnh.js} +14 -8
  81. package/dist/chunks/{LpToaster-gDB1EaU3.js → LpToaster-DpJvoCOh.js} +94 -31
  82. package/dist/chunks/{LpTooltip-hCLPAqMG.js → LpTooltip-CXVKcOXT.js} +14 -6
  83. package/dist/chunks/LpTooltipProvider-CftjV7Xc.js +25 -0
  84. package/dist/chunks/{LpTopologyCanvas-Cm1L39uL.js → LpTopologyCanvas-6ozNrQKh.js} +8 -2
  85. package/dist/chunks/{LpUptimeBar-DvAMno0S.js → LpUptimeBar-ugcv25xj.js} +44 -15
  86. package/dist/chunks/icons-CkA0njzm.js +43 -0
  87. package/dist/chunks/{LpThemeSwitcher-Cue-myST.js → useTheme-DJm1JSsY.js} +215 -260
  88. package/dist/component-names.d.ts +1 -1
  89. package/dist/components/ContextMenuItems.vue.d.ts +8 -0
  90. package/dist/components/ContextMenuItems.vue.js +4 -0
  91. package/dist/components/LayoutCanvas.vue.js +1 -1
  92. package/dist/components/LayoutNode.vue.d.ts +4 -0
  93. package/dist/components/LayoutNode.vue.js +1 -1
  94. package/dist/components/LpActionBar.vue.d.ts +3 -0
  95. package/dist/components/LpActionBar.vue.js +1 -1
  96. package/dist/components/LpAddressInput.vue.d.ts +1 -1
  97. package/dist/components/LpAddressInput.vue.js +1 -1
  98. package/dist/components/LpAlert.vue.d.ts +9 -0
  99. package/dist/components/LpAlert.vue.js +1 -1
  100. package/dist/components/LpAppShell.vue.d.ts +10 -0
  101. package/dist/components/LpAppShell.vue.js +1 -1
  102. package/dist/components/LpAutocomplete.vue.d.ts +31 -6
  103. package/dist/components/LpAutocomplete.vue.js +1 -1
  104. package/dist/components/LpAvatar.vue.d.ts +3 -3
  105. package/dist/components/LpAvatar.vue.js +1 -1
  106. package/dist/components/LpBadge.vue.d.ts +2 -2
  107. package/dist/components/LpBreadcrumbs.vue.d.ts +13 -9
  108. package/dist/components/LpBreadcrumbs.vue.js +1 -1
  109. package/dist/components/LpButton.vue.d.ts +35 -98
  110. package/dist/components/LpButton.vue.js +1 -1
  111. package/dist/components/LpCalendar.vue.js +1 -1
  112. package/dist/components/LpCard.vue.js +1 -1
  113. package/dist/components/LpChart.vue.d.ts +47 -3
  114. package/dist/components/LpChart.vue.js +377 -97
  115. package/dist/components/LpCheckbox.vue.js +1 -1
  116. package/dist/components/LpCodeBlock.vue.d.ts +2 -0
  117. package/dist/components/LpCodeBlock.vue.js +1 -1
  118. package/dist/components/LpColorPicker.vue.d.ts +2 -2
  119. package/dist/components/LpColorPicker.vue.js +1 -1
  120. package/dist/components/LpCommandPalette.vue.d.ts +14 -3
  121. package/dist/components/LpCommandPalette.vue.js +142 -77
  122. package/dist/components/LpConfirmDialog.vue.d.ts +15 -3
  123. package/dist/components/LpConfirmDialog.vue.js +1 -1
  124. package/dist/components/LpConfirmHost.vue.d.ts +9 -0
  125. package/dist/components/LpConfirmHost.vue.js +4 -0
  126. package/dist/components/LpContextMenu.vue.d.ts +3 -5
  127. package/dist/components/LpContextMenu.vue.js +1 -1
  128. package/dist/components/LpDatePicker.vue.d.ts +24 -6
  129. package/dist/components/LpDatePicker.vue.js +1 -1
  130. package/dist/components/LpDateRangePicker.vue.d.ts +60 -0
  131. package/dist/components/LpDateRangePicker.vue.js +4 -0
  132. package/dist/components/LpDisclosure.vue.js +1 -1
  133. package/dist/components/LpDrawer.vue.d.ts +10 -0
  134. package/dist/components/LpDrawer.vue.js +1 -1
  135. package/dist/components/LpDropdownMenu.vue.js +1 -1
  136. package/dist/components/LpDropzone.vue.js +23 -7
  137. package/dist/components/LpEmptyState.vue.js +1 -1
  138. package/dist/components/LpFieldNotice.vue.d.ts +8 -0
  139. package/dist/components/LpFieldNotice.vue.js +4 -0
  140. package/dist/components/LpFileTree.vue.d.ts +11 -2
  141. package/dist/components/LpFileTree.vue.js +1 -1
  142. package/dist/components/LpFileTreeNode.vue.js +1 -1
  143. package/dist/components/LpFormField.vue.d.ts +13 -1
  144. package/dist/components/LpFormField.vue.js +1 -1
  145. package/dist/components/LpIcon.vue.d.ts +0 -1
  146. package/dist/components/LpIcon.vue.js +1 -1
  147. package/dist/components/LpImageEditor.vue.js +93 -58
  148. package/dist/components/LpInput.vue.d.ts +22 -3
  149. package/dist/components/LpInput.vue.js +1 -1
  150. package/dist/components/LpLightbox.vue.d.ts +17 -0
  151. package/dist/components/LpLightbox.vue.js +1 -1
  152. package/dist/components/LpLink.vue.d.ts +11 -11
  153. package/dist/components/LpLink.vue.js +1 -1
  154. package/dist/components/LpLogViewer.vue.d.ts +72 -3
  155. package/dist/components/LpLogViewer.vue.js +1 -1
  156. package/dist/components/LpMapPicker.vue.d.ts +4 -4
  157. package/dist/components/LpMapPicker.vue.js +1 -1
  158. package/dist/components/LpMediaGallery.vue.js +1 -1
  159. package/dist/components/LpModal.vue.d.ts +16 -6
  160. package/dist/components/LpModal.vue.js +1 -1
  161. package/dist/components/LpModalNav.vue.d.ts +0 -1
  162. package/dist/components/LpModalNav.vue.js +1 -1
  163. package/dist/components/LpNotificationBell.vue.d.ts +11 -2
  164. package/dist/components/LpNotificationBell.vue.js +1 -1
  165. package/dist/components/LpNumberField.vue.d.ts +2 -0
  166. package/dist/components/LpNumberField.vue.js +1 -1
  167. package/dist/components/LpNumberFlow.vue.js +1 -1
  168. package/dist/components/LpOtpInput.vue.js +1 -1
  169. package/dist/components/LpPagination.vue.d.ts +2 -0
  170. package/dist/components/LpPagination.vue.js +1 -1
  171. package/dist/components/LpPasswordInput.vue.js +1 -1
  172. package/dist/components/LpPhoneInput.vue.d.ts +13 -0
  173. package/dist/components/LpPhoneInput.vue.js +1 -1
  174. package/dist/components/LpPie.vue.d.ts +21 -2
  175. package/dist/components/LpPie.vue.js +1 -1
  176. package/dist/components/LpPopover.vue.d.ts +2 -0
  177. package/dist/components/LpPopover.vue.js +1 -1
  178. package/dist/components/LpProgress.vue.d.ts +1 -1
  179. package/dist/components/LpProgress.vue.js +1 -1
  180. package/dist/components/LpRadioGroup.vue.js +1 -1
  181. package/dist/components/LpRangeCalendar.vue.d.ts +51 -0
  182. package/dist/components/LpRangeCalendar.vue.js +4 -0
  183. package/dist/components/LpRollingText.vue.d.ts +1 -1
  184. package/dist/components/LpRollingText.vue.js +1 -1
  185. package/dist/components/LpScrollArea.vue.d.ts +2 -2
  186. package/dist/components/LpScrollArea.vue.js +1 -1
  187. package/dist/components/LpSection.vue.d.ts +1 -1
  188. package/dist/components/LpSection.vue.js +1 -1
  189. package/dist/components/LpSegmented.vue.d.ts +5 -0
  190. package/dist/components/LpSegmented.vue.js +1 -1
  191. package/dist/components/LpSelect.vue.d.ts +1 -0
  192. package/dist/components/LpSelect.vue.js +1 -1
  193. package/dist/components/LpShortcutsDialog.vue.d.ts +7 -1
  194. package/dist/components/LpShortcutsDialog.vue.js +60 -15
  195. package/dist/components/LpSidebar.vue.d.ts +6 -2
  196. package/dist/components/LpSidebar.vue.js +1 -1
  197. package/dist/components/LpSidebarNav.vue.js +1 -1
  198. package/dist/components/LpSkeleton.vue.js +1 -1
  199. package/dist/components/LpSlider.vue.js +1 -1
  200. package/dist/components/LpSparkline.vue.d.ts +1 -0
  201. package/dist/components/LpSparkline.vue.js +1 -1
  202. package/dist/components/LpStat.vue.js +1 -1
  203. package/dist/components/LpStepper.vue.js +1 -1
  204. package/dist/components/LpSwitch.vue.js +1 -1
  205. package/dist/components/LpTable.vue.d.ts +107 -3
  206. package/dist/components/LpTable.vue.js +540 -128
  207. package/dist/components/LpTableFilter.vue.d.ts +31 -0
  208. package/dist/components/LpTableFilter.vue.js +4 -0
  209. package/dist/components/LpTableOfContents.vue.d.ts +4 -2
  210. package/dist/components/LpTableOfContents.vue.js +1 -1
  211. package/dist/components/LpTabs.vue.d.ts +2 -0
  212. package/dist/components/LpTabs.vue.js +1 -1
  213. package/dist/components/LpTagsInput.vue.d.ts +77 -0
  214. package/dist/components/LpTagsInput.vue.js +4 -0
  215. package/dist/components/LpTextarea.vue.d.ts +19 -6
  216. package/dist/components/LpTextarea.vue.js +1 -1
  217. package/dist/components/LpThemeProvider.vue.d.ts +22 -0
  218. package/dist/components/LpThemeProvider.vue.js +4 -0
  219. package/dist/components/LpThemeSwitcher.vue.d.ts +15 -2
  220. package/dist/components/LpThemeSwitcher.vue.js +1 -1
  221. package/dist/components/LpTilt.vue.js +1 -1
  222. package/dist/components/LpTimeField.vue.js +1 -1
  223. package/dist/components/LpToaster.vue.d.ts +6 -1
  224. package/dist/components/LpToaster.vue.js +1 -1
  225. package/dist/components/LpTooltip.vue.d.ts +1 -2
  226. package/dist/components/LpTooltip.vue.js +1 -1
  227. package/dist/components/LpTooltipProvider.vue.d.ts +22 -0
  228. package/dist/components/LpTooltipProvider.vue.js +4 -0
  229. package/dist/components/LpTopologyCanvas.vue.js +1 -1
  230. package/dist/components/LpUptimeBar.vue.d.ts +4 -0
  231. package/dist/components/LpUptimeBar.vue.js +1 -1
  232. package/dist/components/chart.d.ts +32 -1
  233. package/dist/components/chart.js +42 -6
  234. package/dist/components/codeHighlight.d.ts +6 -0
  235. package/dist/components/codeHighlight.js +92 -20
  236. package/dist/components/color.d.ts +1 -1
  237. package/dist/components/color.js +20 -9
  238. package/dist/components/commandSearch.js +3 -0
  239. package/dist/components/confirm.d.ts +25 -0
  240. package/dist/components/confirm.js +26 -0
  241. package/dist/components/countries.d.ts +6 -0
  242. package/dist/components/countries.js +7 -0
  243. package/dist/components/dateRange.d.ts +43 -0
  244. package/dist/components/dateRange.js +76 -0
  245. package/dist/components/exportData.d.ts +58 -0
  246. package/dist/components/exportData.js +165 -0
  247. package/dist/components/fileTree.js +16 -7
  248. package/dist/components/imageCrop.d.ts +42 -0
  249. package/dist/components/imageCrop.js +47 -0
  250. package/dist/components/link.d.ts +12 -0
  251. package/dist/components/link.js +19 -0
  252. package/dist/components/logSearch.d.ts +18 -0
  253. package/dist/components/logSearch.js +36 -0
  254. package/dist/components/modalDepth.d.ts +18 -2
  255. package/dist/components/modalDepth.js +17 -5
  256. package/dist/components/otp.d.ts +5 -0
  257. package/dist/components/otp.js +10 -0
  258. package/dist/components/phone.d.ts +41 -0
  259. package/dist/components/phone.js +80 -0
  260. package/dist/components/sidebar.d.ts +7 -1
  261. package/dist/components/tableFilter.d.ts +36 -0
  262. package/dist/components/tableFilter.js +84 -0
  263. package/dist/components/tableSort.d.ts +8 -0
  264. package/dist/components/tableSort.js +31 -0
  265. package/dist/components/tags.d.ts +20 -0
  266. package/dist/components/tags.js +37 -0
  267. package/dist/composables/useField.d.ts +38 -0
  268. package/dist/composables/useField.js +45 -0
  269. package/dist/composables/useFieldNotice.d.ts +17 -0
  270. package/dist/composables/useFieldNotice.js +28 -0
  271. package/dist/composables/useForm.d.ts +53 -0
  272. package/dist/composables/useForm.js +207 -0
  273. package/dist/composables/useFormDraft.d.ts +10 -3
  274. package/dist/composables/useFormDraft.js +9 -14
  275. package/dist/composables/useHotkeys.d.ts +81 -5
  276. package/dist/composables/useHotkeys.js +223 -25
  277. package/dist/composables/useInputFilter.d.ts +17 -0
  278. package/dist/composables/useInputFilter.js +47 -10
  279. package/dist/composables/useInputMask.d.ts +59 -0
  280. package/dist/composables/useInputMask.js +170 -0
  281. package/dist/composables/useLpConfig.d.ts +24 -0
  282. package/dist/composables/useLpConfig.js +44 -0
  283. package/dist/composables/usePaintSelect.d.ts +22 -0
  284. package/dist/composables/usePaintSelect.js +169 -0
  285. package/dist/composables/useRovingFocus.js +7 -0
  286. package/dist/composables/useShift.js +7 -2
  287. package/dist/composables/useTilt.d.ts +2 -2
  288. package/dist/composables/useTilt.js +5 -6
  289. package/dist/composables/useToast.d.ts +20 -0
  290. package/dist/composables/useToast.js +28 -4
  291. package/dist/composables/useZoomPan.d.ts +3 -3
  292. package/dist/composables/useZoomPan.js +4 -4
  293. package/dist/icons-all.d.ts +1 -0
  294. package/dist/icons-all.js +3 -0
  295. package/dist/icons.d.ts +14 -1
  296. package/dist/index.d.ts +60 -4
  297. package/dist/index.js +245 -141
  298. package/dist/kit-icons.d.ts +2 -0
  299. package/dist/layout/tree.d.ts +2 -0
  300. package/dist/layout/tree.js +16 -1
  301. package/dist/layout/useLayout.d.ts +15 -0
  302. package/dist/layout/useLayout.js +41 -14
  303. package/dist/theme/backdrop.d.ts +12 -0
  304. package/dist/theme/presets.d.ts +0 -2
  305. package/dist/theme/useTheme.d.ts +32 -9
  306. package/package.json +18 -8
  307. package/src/component-names.ts +9 -7
  308. package/src/components/ContextMenuItems.vue +88 -0
  309. package/src/components/LayoutCanvas.vue +26 -6
  310. package/src/components/LayoutNode.vue +30 -4
  311. package/src/components/LpActionBar.vue +31 -8
  312. package/src/components/LpAddressInput.vue +57 -41
  313. package/src/components/LpAlert.vue +16 -3
  314. package/src/components/LpAppShell.vue +45 -12
  315. package/src/components/LpAutocomplete.vue +47 -10
  316. package/src/components/LpAvatar.vue +20 -6
  317. package/src/components/LpBreadcrumbs.vue +65 -41
  318. package/src/components/LpButton.vue +60 -14
  319. package/src/components/LpChart.vue +351 -28
  320. package/src/components/LpCheckbox.vue +7 -3
  321. package/src/components/LpCodeBlock.vue +50 -14
  322. package/src/components/LpColorPicker.vue +73 -10
  323. package/src/components/LpCommandPalette.vue +115 -20
  324. package/src/components/LpConfirmDialog.vue +68 -17
  325. package/src/components/LpConfirmHost.vue +59 -0
  326. package/src/components/LpContextMenu.vue +15 -116
  327. package/src/components/LpDatePicker.vue +104 -68
  328. package/src/components/LpDateRangePicker.vue +224 -0
  329. package/src/components/LpDrawer.vue +56 -19
  330. package/src/components/LpDropdownMenu.vue +1 -0
  331. package/src/components/LpDropzone.vue +21 -4
  332. package/src/components/LpFieldNotice.vue +65 -0
  333. package/src/components/LpFileTree.vue +33 -7
  334. package/src/components/LpFormField.vue +59 -7
  335. package/src/components/LpIcon.vue +22 -4
  336. package/src/components/LpImageEditor.vue +96 -57
  337. package/src/components/LpInput.vue +62 -11
  338. package/src/components/LpLightbox.vue +140 -29
  339. package/src/components/LpLink.vue +24 -13
  340. package/src/components/LpLogViewer.vue +311 -39
  341. package/src/components/LpMapPicker.vue +36 -13
  342. package/src/components/LpMediaGallery.vue +8 -2
  343. package/src/components/LpModal.vue +54 -28
  344. package/src/components/LpModalNav.vue +5 -2
  345. package/src/components/LpNotificationBell.vue +77 -23
  346. package/src/components/LpNumberField.vue +21 -6
  347. package/src/components/LpNumberFlow.vue +26 -10
  348. package/src/components/LpOtpInput.vue +43 -8
  349. package/src/components/LpPagination.vue +23 -7
  350. package/src/components/LpPasswordInput.vue +4 -1
  351. package/src/components/LpPhoneInput.vue +224 -39
  352. package/src/components/LpPie.vue +102 -20
  353. package/src/components/LpPopover.vue +4 -0
  354. package/src/components/LpProgress.vue +5 -3
  355. package/src/components/LpRadioGroup.vue +9 -2
  356. package/src/components/LpRangeCalendar.vue +365 -0
  357. package/src/components/LpRollingText.vue +3 -0
  358. package/src/components/LpScrollArea.vue +22 -2
  359. package/src/components/LpSegmented.vue +12 -2
  360. package/src/components/LpSelect.vue +0 -0
  361. package/src/components/LpShortcutsDialog.vue +83 -9
  362. package/src/components/LpSidebar.vue +14 -9
  363. package/src/components/LpSidebarNav.vue +17 -5
  364. package/src/components/LpSkeleton.vue +4 -1
  365. package/src/components/LpSlider.vue +7 -1
  366. package/src/components/LpSparkline.vue +11 -3
  367. package/src/components/LpStepper.vue +23 -10
  368. package/src/components/LpSwitch.vue +31 -8
  369. package/src/components/LpTable.vue +668 -90
  370. package/src/components/LpTableFilter.vue +175 -0
  371. package/src/components/LpTableOfContents.vue +50 -32
  372. package/src/components/LpTabs.vue +23 -6
  373. package/src/components/LpTagsInput.vue +364 -0
  374. package/src/components/LpTextarea.vue +44 -6
  375. package/src/components/LpThemeProvider.vue +41 -0
  376. package/src/components/LpThemeSwitcher.vue +76 -33
  377. package/src/components/LpTilt.vue +2 -2
  378. package/src/components/LpTimeField.vue +14 -3
  379. package/src/components/LpToaster.vue +115 -27
  380. package/src/components/LpTooltip.vue +29 -5
  381. package/src/components/LpTooltipProvider.vue +24 -0
  382. package/src/components/LpTopologyCanvas.vue +19 -2
  383. package/src/components/LpUptimeBar.vue +46 -8
  384. package/src/components/chart.ts +82 -8
  385. package/src/components/codeHighlight.ts +111 -15
  386. package/src/components/color.ts +30 -9
  387. package/src/components/commandSearch.ts +6 -0
  388. package/src/components/confirm.ts +58 -0
  389. package/src/components/countries.ts +12 -0
  390. package/src/components/dateRange.ts +134 -0
  391. package/src/components/exportData.ts +228 -0
  392. package/src/components/fileTree.ts +19 -7
  393. package/src/components/imageCrop.ts +107 -0
  394. package/src/components/link.ts +34 -0
  395. package/src/components/logSearch.ts +46 -0
  396. package/src/components/modalDepth.ts +48 -6
  397. package/src/components/otp.ts +16 -0
  398. package/src/components/phone.ts +140 -0
  399. package/src/components/sidebar.ts +7 -1
  400. package/src/components/tableFilter.ts +122 -0
  401. package/src/components/tableSort.ts +37 -0
  402. package/src/components/tags.ts +62 -0
  403. package/src/composables/useField.ts +83 -0
  404. package/src/composables/useFieldNotice.ts +59 -0
  405. package/src/composables/useForm.ts +314 -0
  406. package/src/composables/useFormDraft.ts +25 -20
  407. package/src/composables/useHotkeys.ts +355 -28
  408. package/src/composables/useInputFilter.ts +77 -14
  409. package/src/composables/useInputMask.ts +254 -0
  410. package/src/composables/useLpConfig.ts +87 -0
  411. package/src/composables/usePaintSelect.ts +243 -0
  412. package/src/composables/useRovingFocus.ts +11 -0
  413. package/src/composables/useShift.ts +13 -2
  414. package/src/composables/useTilt.ts +5 -6
  415. package/src/composables/useToast.ts +56 -4
  416. package/src/composables/useZoomPan.ts +6 -6
  417. package/src/iconSubset.d.mts +10 -0
  418. package/src/iconSubset.mjs +51 -0
  419. package/src/icons-all.ts +10 -0
  420. package/src/icons.ts +59 -8
  421. package/src/index.ts +73 -4
  422. package/src/kit-icons.ts +5 -0
  423. package/src/layout/tree.ts +30 -0
  424. package/src/layout/useLayout.ts +68 -18
  425. package/src/nuxt.ts +87 -17
  426. package/src/runtime/config.plugin.ts +14 -0
  427. package/src/runtime/theme.plugin.ts +43 -23
  428. package/src/theme/backdrop.ts +69 -0
  429. package/src/theme/presets.ts +6 -64
  430. package/src/theme/useTheme.ts +206 -100
  431. package/src/tokens/tokens.css +46 -0
  432. package/dist/chunks/LpBreadcrumbs-p4jHe_V-.js +0 -62
  433. package/dist/chunks/LpContextMenu-CwW1QXe_.js +0 -217
  434. package/dist/chunks/LpDatePicker-CwOToxGq.js +0 -164
  435. package/dist/chunks/LpFormField-CazBc2-a.js +0 -62
  436. package/dist/chunks/LpPhoneInput-BDSKVl_z.js +0 -209
  437. package/dist/chunks/LpTextarea-t7F6gv8E.js +0 -47
@@ -173,23 +173,58 @@ const BOOLEANS = /* @__PURE__ */ new Set([
173
173
  "Err"
174
174
  // rust common variants read as constants
175
175
  ]);
176
- const MASTER = new RegExp(
177
- [
178
- "(\\/\\/[^\\n]*|#[^\\n]*|\\/\\*[\\s\\S]*?\\*\\/)",
179
- // 1 comment
180
- "(\"(?:\\\\.|[^\"\\\\])*\"|'(?:\\\\.|[^'\\\\])*'|`(?:\\\\.|[^`\\\\])*`)",
181
- // 2 string
182
- "(@[A-Za-z_$][\\w$]*)",
183
- // 3 annotation (@Override, @ConfigSerializable — JVM)
184
- "(\\b\\d[\\d_]*(?:\\.\\d+)?(?:e[+-]?\\d+)?[fFlLdD]?\\b)",
185
- // 4 number (JVM suffixes)
186
- "([A-Za-z_$][\\w$]*)",
187
- // 5 identifier (keyword/bool/func/prop/plain)
188
- "([{}()\\[\\];:,.<>=+\\-*/%!&|?]+)"
189
- // 6 punctuation
190
- ].join("|"),
191
- "g"
192
- );
176
+ const COMMENTS = {
177
+ ts: "c",
178
+ js: "c",
179
+ json: "none",
180
+ bash: "hash",
181
+ html: "html",
182
+ python: "hash",
183
+ rust: "c",
184
+ yaml: "hash",
185
+ toml: "hash",
186
+ kotlin: "c",
187
+ java: "c",
188
+ groovy: "c",
189
+ plain: "none"
190
+ };
191
+ const COMMENT_PATTERN = {
192
+ c: "\\/\\/[^\\n]*|\\/\\*[\\s\\S]*?\\*\\/",
193
+ // A `#` only starts a comment at the start of a word, so `a#b` in a URL or
194
+ // `${#arr[@]}` in shell stay code.
195
+ hash: "(?<![\\w$])#[^\\n]*",
196
+ html: "<!--[\\s\\S]*?-->",
197
+ none: "(?!)"
198
+ };
199
+ const BLOCK = {
200
+ c: { open: "/*", close: "*/" },
201
+ html: { open: "<!--", close: "-->" }
202
+ };
203
+ const masters = /* @__PURE__ */ new Map();
204
+ function masterFor(style) {
205
+ let re = masters.get(style);
206
+ if (!re) {
207
+ re = new RegExp(
208
+ [
209
+ `(${COMMENT_PATTERN[style]})`,
210
+ // 1 comment
211
+ "(\"(?:\\\\.|[^\"\\\\])*\"|'(?:\\\\.|[^'\\\\])*'|`(?:\\\\.|[^`\\\\])*`)",
212
+ // 2 string
213
+ "(@[A-Za-z_$][\\w$]*)",
214
+ // 3 annotation (@Override, @ConfigSerializable — JVM)
215
+ "(\\b\\d[\\d_]*(?:\\.\\d+)?(?:e[+-]?\\d+)?[fFlLdD]?\\b)",
216
+ // 4 number (JVM suffixes)
217
+ "(#?[A-Za-z_$][\\w$]*)",
218
+ // 5 identifier (keyword/bool/func/prop/plain), incl. #private
219
+ "([{}()\\[\\];:,.<>=+\\-*/%!&|?]+)"
220
+ // 6 punctuation
221
+ ].join("|"),
222
+ "g"
223
+ );
224
+ masters.set(style, re);
225
+ }
226
+ return re;
227
+ }
193
228
  function classifyIdent(name, before, after) {
194
229
  if (KEYWORDS.has(name)) return C.keyword;
195
230
  if (BOOLEANS.has(name)) return C.boolean;
@@ -198,11 +233,13 @@ function classifyIdent(name, before, after) {
198
233
  return "";
199
234
  }
200
235
  function tokenizeLine(line, lang) {
236
+ if (lang === "plain") return line ? [{ text: line, cls: "" }] : [];
201
237
  const out = [];
202
238
  let last = 0;
203
239
  let m;
204
- MASTER.lastIndex = 0;
205
- while ((m = MASTER.exec(line)) !== null) {
240
+ const master = masterFor(COMMENTS[lang]);
241
+ master.lastIndex = 0;
242
+ while ((m = master.exec(line)) !== null) {
206
243
  if (m.index > last) out.push({ text: line.slice(last, m.index), cls: "" });
207
244
  const [full, comment, str, annotation, num, ident, punct] = m;
208
245
  if (comment != null) out.push({ text: full, cls: C.comment });
@@ -225,6 +262,41 @@ function tokenizeLine(line, lang) {
225
262
  if (last < line.length) out.push({ text: line.slice(last), cls: "" });
226
263
  return out;
227
264
  }
265
+ function tokenizeLines(lines, lang) {
266
+ const block = BLOCK[COMMENTS[lang]];
267
+ if (!block) return lines.map((line) => tokenizeLine(line, lang));
268
+ const out = [];
269
+ let open = false;
270
+ for (const line of lines) {
271
+ let rest = line;
272
+ const tokens = [];
273
+ if (open) {
274
+ const end = rest.indexOf(block.close);
275
+ if (end === -1) {
276
+ out.push(rest ? [{ text: rest, cls: C.comment }] : []);
277
+ continue;
278
+ }
279
+ tokens.push({ text: rest.slice(0, end + block.close.length), cls: C.comment });
280
+ rest = rest.slice(end + block.close.length);
281
+ open = false;
282
+ }
283
+ const lineTokens = tokenizeLine(rest, lang);
284
+ const at = lineTokens.findIndex(
285
+ (t) => t.cls !== C.comment && t.cls !== C.string && t.text.includes(block.open)
286
+ );
287
+ if (at >= 0) {
288
+ const cut = lineTokens[at].text.indexOf(block.open);
289
+ const tail = lineTokens.slice(at).map((t) => t.text).join("").slice(cut);
290
+ tokens.push(...lineTokens.slice(0, at));
291
+ if (cut > 0) tokens.push({ text: lineTokens[at].text.slice(0, cut), cls: lineTokens[at].cls });
292
+ tokens.push({ text: tail, cls: C.comment });
293
+ open = true;
294
+ } else tokens.push(...lineTokens);
295
+ out.push(tokens);
296
+ }
297
+ return out;
298
+ }
228
299
  export {
229
- tokenizeLine
300
+ tokenizeLine,
301
+ tokenizeLines
230
302
  };
@@ -17,7 +17,7 @@ export type ColorFormat = "hex" | "rgb" | "hsl";
17
17
  /** Wraps rather than clamps: hue is a circle, and 370° is 10°, not 360°. */
18
18
  export declare function normalizeHue(h: number): number;
19
19
  export declare function clampHsv(c: Hsv): Hsv;
20
- export declare function hsvToRgb({ h, s, v, a }: Hsv): Rgb;
20
+ export declare function hsvToRgb(color: Hsv): Rgb;
21
21
  export declare function rgbToHsv({ r, g, b, a }: Rgb): Hsv;
22
22
  /** "#rrggbb", or "#rrggbbaa" when the colour is not fully opaque. */
23
23
  export declare function rgbToHex({ r, g, b, a }: Rgb): string;
@@ -11,7 +11,12 @@ function clampHsv(c) {
11
11
  a: clamp(c.a, 0, 1)
12
12
  };
13
13
  }
14
- function hsvToRgb({ h, s, v, a }) {
14
+ const finite = (n) => Number.isFinite(n) ? n : 0;
15
+ function hsvToRgb(color) {
16
+ const h = finite(color.h);
17
+ const s = clamp(finite(color.s), 0, 1);
18
+ const v = clamp(finite(color.v), 0, 1);
19
+ const a = Number.isFinite(color.a) ? color.a : 1;
15
20
  const hue = normalizeHue(h) / 60;
16
21
  const c = v * s;
17
22
  const x = c * (1 - Math.abs(hue % 2 - 1));
@@ -52,9 +57,13 @@ function rgbToHsv({ r, g, b, a }) {
52
57
  };
53
58
  }
54
59
  const hex2 = (n) => clamp(Math.round(n), 0, 255).toString(16).padStart(2, "0");
60
+ function alphaByte(a) {
61
+ return Math.round(clamp(a, 0, 1) * 255);
62
+ }
55
63
  function rgbToHex({ r, g, b, a }) {
56
64
  const base = `#${hex2(r)}${hex2(g)}${hex2(b)}`;
57
- return a >= 1 ? base : base + hex2(a * 255);
65
+ const byte = alphaByte(a);
66
+ return byte >= 255 ? base : base + hex2(byte);
58
67
  }
59
68
  function parseHex(input) {
60
69
  const s = input.trim().replace(/^#/, "");
@@ -105,16 +114,18 @@ function hsvToHsl({ h, s, v }) {
105
114
  }
106
115
  function formatColor(c, format) {
107
116
  const rgb = hsvToRgb(c);
108
- const a = Math.round(clamp(c.a, 0, 1) * 100) / 100;
117
+ const byte = alphaByte(rgb.a);
118
+ const a = Math.round(byte / 255 * 1e3) / 1e3;
109
119
  if (format === "hex") return rgbToHex(rgb);
110
120
  if (format === "rgb") {
111
- return a >= 1 ? `rgb(${rgb.r}, ${rgb.g}, ${rgb.b})` : `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${a})`;
121
+ return byte >= 255 ? `rgb(${rgb.r}, ${rgb.g}, ${rgb.b})` : `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${a})`;
112
122
  }
113
- const { h, s, l } = hsvToHsl(c);
114
- const hh = Math.round(h);
115
- const ss = Math.round(s * 100);
116
- const ll = Math.round(l * 100);
117
- return a >= 1 ? `hsl(${hh}, ${ss}%, ${ll}%)` : `hsla(${hh}, ${ss}%, ${ll}%, ${a})`;
123
+ const { h, s, l } = hsvToHsl({ ...c, h: finite(c.h), s: clamp(finite(c.s), 0, 1), v: clamp(finite(c.v), 0, 1) });
124
+ const dec = (n) => Math.round(n * 10) / 10;
125
+ const hh = dec(h) % 360;
126
+ const ss = dec(s * 100);
127
+ const ll = dec(l * 100);
128
+ return byte >= 255 ? `hsl(${hh}, ${ss}%, ${ll}%)` : `hsla(${hh}, ${ss}%, ${ll}%, ${a})`;
118
129
  }
119
130
  function opaqueCss(c) {
120
131
  const { r, g, b } = hsvToRgb({ ...c, a: 1 });
@@ -39,6 +39,9 @@ function score(command, terms) {
39
39
  if (!hit) return 0;
40
40
  total += hit;
41
41
  }
42
+ const typed = terms.include.join(" ");
43
+ if (typed && label === typed) total += 6;
44
+ else if (typed && label.startsWith(typed)) total += 2;
42
45
  return total;
43
46
  }
44
47
  function rankCommandItems(items, terms) {
@@ -0,0 +1,25 @@
1
+ export interface ConfirmOptions {
2
+ title: string;
3
+ description?: string;
4
+ danger?: boolean;
5
+ icon?: string;
6
+ confirmLabel?: string;
7
+ cancelLabel?: string;
8
+ loadingLabel?: string;
9
+ /**
10
+ * Work to run on confirm. The dialog stays open with a loading state while it
11
+ * runs and shows the error's message if it rejects; the promise from
12
+ * `confirm()` resolves true only once it succeeded.
13
+ */
14
+ action?: () => unknown;
15
+ }
16
+ export interface ConfirmRequest extends ConfirmOptions {
17
+ id: number;
18
+ resolve: (confirmed: boolean) => void;
19
+ }
20
+ export declare const confirmQueue: ConfirmRequest[];
21
+ /** Ask for confirmation. Resolves false when the user cancels or dismisses. */
22
+ export declare function confirm(options: ConfirmOptions): Promise<boolean>;
23
+ /** Settle a request and drop it from the queue. Used by the host. */
24
+ export declare function settleConfirm(id: number, confirmed: boolean): void;
25
+ export declare function useConfirm(): typeof confirm;
@@ -0,0 +1,26 @@
1
+ import { reactive } from "vue";
2
+ const STATE_KEY = /* @__PURE__ */ Symbol.for("@leavepulse/ui:confirm-queue");
3
+ const g = globalThis;
4
+ const state = g[STATE_KEY] ??= { queue: reactive([]), nextId: 0 };
5
+ const confirmQueue = state.queue;
6
+ function confirm(options) {
7
+ if (typeof window === "undefined") return Promise.resolve(false);
8
+ return new Promise((resolve) => {
9
+ state.queue.push({ ...options, id: state.nextId++, resolve });
10
+ });
11
+ }
12
+ function settleConfirm(id, confirmed) {
13
+ const i = state.queue.findIndex((r) => r.id === id);
14
+ if (i === -1) return;
15
+ const [request] = state.queue.splice(i, 1);
16
+ request?.resolve(confirmed);
17
+ }
18
+ function useConfirm() {
19
+ return confirm;
20
+ }
21
+ export {
22
+ confirm,
23
+ confirmQueue,
24
+ settleConfirm,
25
+ useConfirm
26
+ };
@@ -18,3 +18,9 @@ export declare function loadCountries(): Promise<Country[]>;
18
18
  * country is preferred. Pass the list (from loadCountries). Undefined if none.
19
19
  */
20
20
  export declare function matchCountryByValue(value: string, list: Country[]): Country | undefined;
21
+ /**
22
+ * Countries matching a search query: by name, or by dial code when the query
23
+ * carries digits ("+44", "44"). A query without digits must not match on the
24
+ * dial code at all, or every country would match the empty string.
25
+ */
26
+ export declare function filterCountries(list: Country[], query: string): Country[];
@@ -31,7 +31,14 @@ function matchCountryByValue(value, list) {
31
31
  }
32
32
  return best;
33
33
  }
34
+ function filterCountries(list, query) {
35
+ const q = query.trim().toLowerCase();
36
+ if (!q) return list;
37
+ const digits = q.replace(/\D/g, "");
38
+ return list.filter((c) => c.name.toLowerCase().includes(q) || digits !== "" && c.dial.includes(digits));
39
+ }
34
40
  export {
41
+ filterCountries,
35
42
  flagEmoji,
36
43
  loadCountries,
37
44
  matchCountryByValue
@@ -0,0 +1,43 @@
1
+ import { type CalendarDate } from "@internationalized/date";
2
+ export interface DateRange {
3
+ start: string;
4
+ end: string;
5
+ }
6
+ export interface DateRangePreset {
7
+ label: string;
8
+ range: () => DateRange;
9
+ }
10
+ export interface DateRangePresetLabels {
11
+ today: string;
12
+ last7: string;
13
+ last30: string;
14
+ thisMonth: string;
15
+ lastMonth: string;
16
+ }
17
+ /** The default preset list. `now` is injectable so the set can be tested. */
18
+ export declare function defaultRangePresets(labels: DateRangePresetLabels, now?: () => CalendarDate): DateRangePreset[];
19
+ export declare function parseIsoDay(iso: string | undefined): CalendarDate | undefined;
20
+ /** A range with both ends parsed and in order, or undefined. */
21
+ export declare function normalizeRange(range: Partial<DateRange> | undefined): DateRange | undefined;
22
+ export declare function sameRange(a: Partial<DateRange> | undefined, b: Partial<DateRange> | undefined): boolean;
23
+ /** Clip a preset to the allowed bounds; undefined when nothing of it is left. */
24
+ export declare function clampRange(range: DateRange, min?: string, max?: string): DateRange | undefined;
25
+ /**
26
+ * "Jun 3 – 18, 2026" style text: Intl's own range formatting collapses the
27
+ * shared month and year, which is how a range reads naturally in every locale.
28
+ */
29
+ export declare function formatRange(range: DateRange, locale?: string, format?: Intl.DateTimeFormatOptions): string;
30
+ export interface ReshapeRules {
31
+ /** Whether the moving end may land on this day (min, max, disabled). */
32
+ allowed?: (iso: string) => boolean;
33
+ /** Days a range may not include. */
34
+ unavailable?: (iso: string) => boolean;
35
+ /** Longest range, in days, counting both ends. */
36
+ maximumDays?: number;
37
+ }
38
+ /**
39
+ * The range one end makes when it is dragged to `moving` while the other stays
40
+ * at `anchor`; passing the anchor flips which end is which. Null when the result
41
+ * would break a rule, so a drag simply does not follow onto that day.
42
+ */
43
+ export declare function reshapeRange(anchor: string, moving: string, rules?: ReshapeRules): DateRange | null;
@@ -0,0 +1,76 @@
1
+ import { endOfMonth, startOfMonth, today, getLocalTimeZone, parseDate } from "@internationalized/date";
2
+ function span(start, end) {
3
+ return { start: start.toString(), end: end.toString() };
4
+ }
5
+ function defaultRangePresets(labels, now = () => today(getLocalTimeZone())) {
6
+ return [
7
+ { label: labels.today, range: () => span(now(), now()) },
8
+ { label: labels.last7, range: () => span(now().subtract({ days: 6 }), now()) },
9
+ { label: labels.last30, range: () => span(now().subtract({ days: 29 }), now()) },
10
+ { label: labels.thisMonth, range: () => span(startOfMonth(now()), endOfMonth(now())) },
11
+ {
12
+ label: labels.lastMonth,
13
+ range: () => {
14
+ const previous = now().subtract({ months: 1 });
15
+ return span(startOfMonth(previous), endOfMonth(previous));
16
+ }
17
+ }
18
+ ];
19
+ }
20
+ function parseIsoDay(iso) {
21
+ if (!iso) return void 0;
22
+ try {
23
+ return parseDate(iso.slice(0, 10));
24
+ } catch {
25
+ return void 0;
26
+ }
27
+ }
28
+ function normalizeRange(range) {
29
+ const start = parseIsoDay(range?.start);
30
+ const end = parseIsoDay(range?.end);
31
+ if (!start || !end) return void 0;
32
+ return start.compare(end) <= 0 ? span(start, end) : span(end, start);
33
+ }
34
+ function sameRange(a, b) {
35
+ const x = normalizeRange(a);
36
+ const y = normalizeRange(b);
37
+ return !!x && !!y && x.start === y.start && x.end === y.end;
38
+ }
39
+ function clampRange(range, min, max) {
40
+ const r = normalizeRange(range);
41
+ if (!r) return void 0;
42
+ const start = min && r.start < min ? min : r.start;
43
+ const end = max && r.end > max ? max : r.end;
44
+ return start <= end ? { start, end } : void 0;
45
+ }
46
+ function formatRange(range, locale, format = { year: "numeric", month: "short", day: "numeric" }) {
47
+ const start = parseIsoDay(range.start);
48
+ const end = parseIsoDay(range.end);
49
+ if (!start || !end) return "";
50
+ const zone = "UTC";
51
+ const fmt = new Intl.DateTimeFormat(locale, { ...format, timeZone: zone });
52
+ return fmt.formatRange(start.toDate(zone), end.toDate(zone));
53
+ }
54
+ function reshapeRange(anchor, moving, rules = {}) {
55
+ const a = parseIsoDay(anchor);
56
+ const m = parseIsoDay(moving);
57
+ if (!a || !m) return null;
58
+ if (rules.allowed && !rules.allowed(m.toString())) return null;
59
+ const [start, end] = a.compare(m) <= 0 ? [a, m] : [m, a];
60
+ if (rules.maximumDays && end.compare(start) + 1 > rules.maximumDays) return null;
61
+ if (rules.unavailable) {
62
+ for (let d = start; d.compare(end) <= 0; d = d.add({ days: 1 })) {
63
+ if (rules.unavailable(d.toString())) return null;
64
+ }
65
+ }
66
+ return { start: start.toString(), end: end.toString() };
67
+ }
68
+ export {
69
+ clampRange,
70
+ defaultRangePresets,
71
+ formatRange,
72
+ normalizeRange,
73
+ parseIsoDay,
74
+ reshapeRange,
75
+ sameRange
76
+ };
@@ -0,0 +1,58 @@
1
+ export interface CsvColumn<Row> {
2
+ key: string;
3
+ /** Header cell. Defaults to the key. */
4
+ label?: string;
5
+ /** The value written for a row; the row's `key` field when omitted. */
6
+ value?: (row: Row) => unknown;
7
+ }
8
+ export interface CsvOptions {
9
+ /** Field separator. Default ",". Some locales' spreadsheets expect ";". */
10
+ separator?: string;
11
+ /** Prefix a UTF-8 byte order mark so Excel reads non-ASCII text correctly. */
12
+ bom?: boolean;
13
+ /**
14
+ * Neutralise cells a spreadsheet would run as a formula (leading = + - @,
15
+ * tab or CR) by prefixing a quote. On by default: exported data is often
16
+ * user-supplied, and opening it is enough to trigger a formula.
17
+ */
18
+ guardFormulas?: boolean;
19
+ /** Line ending. Default "\r\n", as RFC 4180 specifies. */
20
+ newline?: string;
21
+ }
22
+ /** One CSV field, quoted when it holds a separator, a quote or a line break. */
23
+ export declare function csvField(value: unknown, options?: CsvOptions): string;
24
+ /** Rows as CSV text, a header line first. */
25
+ export declare function toCsv<Row>(rows: readonly Row[], columns: readonly CsvColumn<Row>[], options?: CsvOptions): string;
26
+ /**
27
+ * Hand the viewer a file to save. Does nothing outside a browser, so a call
28
+ * that runs during SSR is harmless.
29
+ */
30
+ export declare function downloadFile(name: string, data: Blob | string, type?: string): void;
31
+ /**
32
+ * A standalone copy of a live SVG: every element carries its computed paint as
33
+ * an inline style, so CSS custom properties and classes from the page's
34
+ * stylesheet survive being rendered as an image, and running SMIL animations
35
+ * are frozen at their end state.
36
+ */
37
+ export declare function inlineSvg(svg: SVGSVGElement): SVGSVGElement;
38
+ export interface RasterOptions {
39
+ /** Device pixels per CSS pixel. Default: the screen's ratio, at least 2. */
40
+ scale?: number;
41
+ /** Fill behind the drawing; transparent when omitted. */
42
+ background?: string;
43
+ /** Extra space around the drawing, in CSS pixels. */
44
+ padding?: number;
45
+ /** Drawn above the SVG, in the page's own font. */
46
+ header?: (ctx: CanvasRenderingContext2D, width: number) => number;
47
+ }
48
+ /** Rasterise an SVG element to a PNG blob with its theme resolved. */
49
+ export declare function svgToPng(svg: SVGSVGElement, options?: RasterOptions): Promise<Blob>;
50
+ /** The first non-transparent background at or above an element. */
51
+ export declare function backgroundOf(el: Element | null): string | undefined;
52
+ /**
53
+ * A colour as the browser resolves it where `within` sits, for APIs that cannot
54
+ * read custom properties (canvas, an SVG drawn as an image).
55
+ */
56
+ export declare function resolveCssColor(value: string, within: Element): string;
57
+ /** A filesystem-safe name from a title. */
58
+ export declare function fileStem(title: string | undefined, fallback: string): string;
@@ -0,0 +1,165 @@
1
+ const FORMULA_START = /^[=+\-@\t\r]/;
2
+ function cellText(value) {
3
+ if (value == null) return "";
4
+ if (value instanceof Date) return Number.isNaN(value.getTime()) ? "" : value.toISOString();
5
+ if (typeof value === "object") return JSON.stringify(value);
6
+ return String(value);
7
+ }
8
+ function csvField(value, options = {}) {
9
+ const separator = options.separator ?? ",";
10
+ let text = cellText(value);
11
+ if ((options.guardFormulas ?? true) && typeof value === "string" && FORMULA_START.test(text)) {
12
+ text = `'${text}`;
13
+ }
14
+ const needsQuotes = text.includes(separator) || /["\r\n]/.test(text) || /^\s|\s$/.test(text);
15
+ return needsQuotes ? `"${text.replace(/"/g, '""')}"` : text;
16
+ }
17
+ function toCsv(rows, columns, options = {}) {
18
+ const separator = options.separator ?? ",";
19
+ const newline = options.newline ?? "\r\n";
20
+ const line = (cells) => cells.map((c) => csvField(c, options)).join(separator);
21
+ const out = [line(columns.map((c) => c.label ?? c.key))];
22
+ for (const row of rows) {
23
+ out.push(
24
+ line(columns.map((c) => c.value ? c.value(row) : row[c.key]))
25
+ );
26
+ }
27
+ return (options.bom ? "\uFEFF" : "") + out.join(newline) + newline;
28
+ }
29
+ function downloadFile(name, data, type = "text/plain;charset=utf-8") {
30
+ if (typeof document === "undefined" || typeof URL === "undefined") return;
31
+ const blob = typeof data === "string" ? new Blob([data], { type }) : data;
32
+ const url = URL.createObjectURL(blob);
33
+ const a = document.createElement("a");
34
+ a.href = url;
35
+ a.download = name;
36
+ a.rel = "noopener";
37
+ a.style.display = "none";
38
+ document.body.append(a);
39
+ a.click();
40
+ a.remove();
41
+ setTimeout(() => URL.revokeObjectURL(url), 0);
42
+ }
43
+ const PAINT_PROPS = [
44
+ "fill",
45
+ "fill-opacity",
46
+ "fill-rule",
47
+ "stroke",
48
+ "stroke-opacity",
49
+ "stroke-width",
50
+ "stroke-dasharray",
51
+ "stroke-dashoffset",
52
+ "stroke-linecap",
53
+ "stroke-linejoin",
54
+ "opacity",
55
+ "stop-color",
56
+ "stop-opacity",
57
+ "color",
58
+ "font-family",
59
+ "font-size",
60
+ "font-weight",
61
+ "letter-spacing",
62
+ "text-anchor",
63
+ "dominant-baseline",
64
+ "visibility",
65
+ "display"
66
+ ];
67
+ function inlineSvg(svg) {
68
+ const clone = svg.cloneNode(true);
69
+ const source = [svg, ...svg.querySelectorAll("*")];
70
+ const target = [clone, ...clone.querySelectorAll("*")];
71
+ source.forEach((el, i) => {
72
+ const copy = target[i];
73
+ if (!(copy instanceof Element)) return;
74
+ const computed = getComputedStyle(el);
75
+ const style = PAINT_PROPS.map((p) => `${p}:${computed.getPropertyValue(p)}`).filter((d) => !d.endsWith(":")).join(";");
76
+ copy.setAttribute("style", style);
77
+ copy.removeAttribute("class");
78
+ });
79
+ const comments = document.createTreeWalker(clone, NodeFilter.SHOW_COMMENT);
80
+ const dead = [];
81
+ while (comments.nextNode()) dead.push(comments.currentNode);
82
+ for (const node of dead) node.parentNode?.removeChild(node);
83
+ for (const anim of clone.querySelectorAll("animate")) {
84
+ const attr = anim.getAttribute("attributeName");
85
+ const to = anim.getAttribute("to");
86
+ if (attr && to != null) anim.parentElement?.setAttribute(attr, to);
87
+ anim.remove();
88
+ }
89
+ clone.setAttribute("xmlns", "http://www.w3.org/2000/svg");
90
+ const { width, height } = svg.getBoundingClientRect();
91
+ clone.setAttribute("width", String(width));
92
+ clone.setAttribute("height", String(height));
93
+ clone.style.overflow = "visible";
94
+ return clone;
95
+ }
96
+ async function svgToPng(svg, options = {}) {
97
+ const copy = inlineSvg(svg);
98
+ const width = Number(copy.getAttribute("width"));
99
+ const height = Number(copy.getAttribute("height"));
100
+ const markup = new XMLSerializer().serializeToString(copy);
101
+ const url = URL.createObjectURL(new Blob([markup], { type: "image/svg+xml;charset=utf-8" }));
102
+ try {
103
+ const img = new Image();
104
+ img.decoding = "async";
105
+ const loaded = new Promise((resolve, reject) => {
106
+ img.onload = () => resolve();
107
+ img.onerror = () => reject(new Error("SVG could not be rasterised"));
108
+ });
109
+ img.src = url;
110
+ await loaded;
111
+ const scale = options.scale ?? Math.max(2, globalThis.devicePixelRatio || 1);
112
+ const pad = options.padding ?? 0;
113
+ const measure = document.createElement("canvas").getContext("2d");
114
+ const headerHeight = measure && options.header ? options.header(measure, width) : 0;
115
+ const canvas = document.createElement("canvas");
116
+ canvas.width = Math.ceil((width + pad * 2) * scale);
117
+ canvas.height = Math.ceil((height + headerHeight + pad * 2) * scale);
118
+ const ctx = canvas.getContext("2d");
119
+ if (!ctx) throw new Error("Canvas 2D is unavailable");
120
+ ctx.scale(scale, scale);
121
+ if (options.background) {
122
+ ctx.fillStyle = options.background;
123
+ ctx.fillRect(0, 0, width + pad * 2, height + headerHeight + pad * 2);
124
+ }
125
+ ctx.translate(pad, pad);
126
+ if (options.header) options.header(ctx, width);
127
+ ctx.drawImage(img, 0, headerHeight, width, height);
128
+ return await new Promise(
129
+ (resolve, reject) => canvas.toBlob((b) => b ? resolve(b) : reject(new Error("PNG encoding failed")), "image/png")
130
+ );
131
+ } finally {
132
+ URL.revokeObjectURL(url);
133
+ }
134
+ }
135
+ function backgroundOf(el) {
136
+ for (let node = el; node; node = node.parentElement) {
137
+ const bg = getComputedStyle(node).backgroundColor;
138
+ if (bg && bg !== "transparent" && !/rgba\([^)]*,\s*0\)$/.test(bg)) return bg;
139
+ }
140
+ return void 0;
141
+ }
142
+ function resolveCssColor(value, within) {
143
+ if (!value.includes("var(") && !value.toLowerCase().includes("currentcolor")) return value;
144
+ const probe = document.createElement("span");
145
+ probe.style.color = value;
146
+ probe.style.display = "none";
147
+ within.append(probe);
148
+ const resolved = getComputedStyle(probe).color;
149
+ probe.remove();
150
+ return resolved || value;
151
+ }
152
+ function fileStem(title, fallback) {
153
+ const stem = (title ?? "").trim().replace(/[\\/:*?"<>|\u0000-\u001f]+/g, "").replace(/\s+/g, "-");
154
+ return stem || fallback;
155
+ }
156
+ export {
157
+ backgroundOf,
158
+ csvField,
159
+ downloadFile,
160
+ fileStem,
161
+ inlineSvg,
162
+ resolveCssColor,
163
+ svgToPng,
164
+ toCsv
165
+ };