@leavepulse/ui 0.44.0 → 0.45.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (271) hide show
  1. package/README.md +49 -3
  2. package/dist/assets/{LpCommandPalette-DCP5g2ik.css → LpCommandPalette-HzAA4gri.css} +21 -21
  3. package/dist/assets/{LpRollingText-CR1mb0Vt.css → LpRollingText-BGnE6q9j.css} +3 -0
  4. package/dist/assets/{LpShortcutsDialog-ChUyU7oV.css → LpShortcutsDialog-CqYX3yy6.css} +28 -7
  5. package/dist/assets/{LpTable-DDQNdf86.css → LpTable-CPwWxTJS.css} +49 -9
  6. package/dist/chunks/{ContextMenuItems-CrfeNPWT.js → ContextMenuItems-BtKU7074.js} +2 -1
  7. package/dist/chunks/{LayoutCanvas-D-jPOAvg.js → LayoutCanvas-BkaGXTjx.js} +1 -1
  8. package/dist/chunks/{LayoutNode-D8Xy9N-o.js → LayoutNode-B3_9E1Xa.js} +9 -5
  9. package/dist/chunks/{LpActionBar-BbwCF6l5.js → LpActionBar-CnfFVIwC.js} +3 -3
  10. package/dist/chunks/{LpAddressInput-BrOqkZqg.js → LpAddressInput-CJOYGZlI.js} +7 -7
  11. package/dist/chunks/{LpAlert-DkOIjsbq.js → LpAlert-B6ilrM7T.js} +1 -1
  12. package/dist/chunks/{LpAppShell-BUKPcHco.js → LpAppShell-B07Lf48e.js} +4 -4
  13. package/dist/chunks/{LpAutocomplete-DxV3Y9h4.js → LpAutocomplete-C8IgSMsi.js} +2 -1
  14. package/dist/chunks/{LpAvatar-ClBbEYZN.js → LpAvatar-C1XStdOo.js} +3 -3
  15. package/dist/chunks/{LpBreadcrumbs-B8IJgFIc.js → LpBreadcrumbs-CQJd73Gm.js} +1 -1
  16. package/dist/chunks/{LpButton-kqJBHIIb.js → LpButton-CKSwC6Mu.js} +1 -1
  17. package/dist/chunks/{LpCalendar-B7Ko5RdR.js → LpCalendar-DrA2McTU.js} +1 -1
  18. package/dist/chunks/{LpCard-CpRByR0q.js → LpCard-C2IvucmX.js} +1 -1
  19. package/dist/chunks/{LpCheckbox-DpqchzH4.js → LpCheckbox-Bkj13CbW.js} +1 -1
  20. package/dist/chunks/{LpCodeBlock-DeHJPq7p.js → LpCodeBlock-ca7ANFyW.js} +1 -1
  21. package/dist/chunks/{LpColorPicker-Bhf1qxhB.js → LpColorPicker-zz4VGkG4.js} +46 -20
  22. package/dist/chunks/{LpConfirmDialog-CIUOSnWo.js → LpConfirmDialog-BTVAR4tF.js} +3 -3
  23. package/dist/chunks/{LpConfirmHost-CDm0Wtpv.js → LpConfirmHost-Ci_uCHgQ.js} +1 -1
  24. package/dist/chunks/{LpContextMenu-DQw5dGfG.js → LpContextMenu-BqkAYa9X.js} +2 -1
  25. package/dist/chunks/{LpDatePicker-Drirx1AK.js → LpDatePicker-BrdFtSTy.js} +16 -10
  26. package/dist/chunks/LpDateRangePicker-Drd7EbIz.js +210 -0
  27. package/dist/chunks/{LpDisclosure-ChQYmjlR.js → LpDisclosure-Cc23-JOT.js} +1 -1
  28. package/dist/chunks/{LpDrawer-bScx-KMO.js → LpDrawer-CfRhHwmE.js} +3 -3
  29. package/dist/chunks/{LpDropdownMenu-DJpoqRCb.js → LpDropdownMenu-DdJGQzPn.js} +2 -1
  30. package/dist/chunks/{LpEmptyState-Dsdqz1Wj.js → LpEmptyState-BJbZXC8D.js} +1 -1
  31. package/dist/chunks/LpFieldNotice-wtieLUTj.js +64 -0
  32. package/dist/chunks/{LpFileTree-CSI_5SK2.js → LpFileTree-CNurOvkV.js} +3 -3
  33. package/dist/chunks/{LpFileTreeNode-B4MiSQX2.js → LpFileTreeNode-D_qRRdsH.js} +3 -3
  34. package/dist/chunks/{LpFormField-CIk5qosh.js → LpFormField-CtVYj6tO.js} +29 -15
  35. package/dist/chunks/{LpIcon-CCnX5_2j.js → LpIcon-DYtaid0K.js} +20 -6
  36. package/dist/chunks/{LpInput-C0e8y8_d.js → LpInput-D-YGQbEv.js} +39 -16
  37. package/dist/chunks/{LpLightbox-Mr0W_6HK.js → LpLightbox-DSDahF23.js} +1 -1
  38. package/dist/chunks/{LpLogViewer-YBOaFnc_.js → LpLogViewer-KypbgOyo.js} +252 -58
  39. package/dist/chunks/{LpMapPicker-NUzS9e37.js → LpMapPicker-Cc84LaM3.js} +1 -1
  40. package/dist/chunks/{LpMediaGallery-DfJmMW0I.js → LpMediaGallery-YKr-cQPN.js} +2 -2
  41. package/dist/chunks/{LpModal-DPwGKBPv.js → LpModal-BzTVeNqe.js} +3 -3
  42. package/dist/chunks/{LpModalNav-DPg5H9f3.js → LpModalNav-CjABSGCu.js} +14 -8
  43. package/dist/chunks/{LpNotificationBell-t5yn-siX.js → LpNotificationBell-CCwyJP5C.js} +26 -14
  44. package/dist/chunks/{LpNumberField-DWnQKktS.js → LpNumberField-B77O-z28.js} +1 -1
  45. package/dist/chunks/{LpPagination-DFngX7Xo.js → LpPagination-BcDlo3r_.js} +1 -1
  46. package/dist/chunks/{LpPasswordInput-CWVDuBJ5.js → LpPasswordInput-eKzQhbQP.js} +2 -2
  47. package/dist/chunks/{LpPhoneInput-CD-ZTeSd.js → LpPhoneInput-BCbrrhgE.js} +126 -23
  48. package/dist/chunks/{LpPie-BLco31Nx.js → LpPie-BEJ2SfI6.js} +9 -10
  49. package/dist/chunks/{LpPopover-p_e_shN3.js → LpPopover-DCKeqiVn.js} +1 -0
  50. package/dist/chunks/LpRangeCalendar-DZuaRV0W.js +331 -0
  51. package/dist/chunks/{LpRollingText-CM5gkSeF.js → LpRollingText-DB7upf-5.js} +1 -1
  52. package/dist/chunks/{LpScrollArea-D8xyKXcF.js → LpScrollArea-Bry1fdOM.js} +14 -2
  53. package/dist/chunks/{LpSection-aM6J_u51.js → LpSection-tKEH0jYf.js} +1 -1
  54. package/dist/chunks/{LpSegmented-Dejd7cIx.js → LpSegmented-C09EEam2.js} +1 -1
  55. package/dist/chunks/{LpSelect-DrRD9I7L.js → LpSelect-DNIL6MB9.js} +20 -23
  56. package/dist/chunks/{LpSidebar-BgwUNWpJ.js → LpSidebar-Bwws_X29.js} +3 -3
  57. package/dist/chunks/{LpSidebarNav-Bqxz8aWT.js → LpSidebarNav-kx-LdqNU.js} +3 -3
  58. package/dist/chunks/{LpStat-dXtyrdX9.js → LpStat-B-7udBRP.js} +1 -1
  59. package/dist/chunks/{LpStepper-Bk-XaQYU.js → LpStepper-C7XiVKZj.js} +34 -19
  60. package/dist/chunks/{LpSwitch-B1aLKulj.js → LpSwitch-OrcOJX9m.js} +1 -1
  61. package/dist/chunks/LpTableFilter-BV8PpLM9.js +158 -0
  62. package/dist/chunks/{LpTabs-_qMVaZJ6.js → LpTabs-29iW1XOx.js} +1 -1
  63. package/dist/chunks/LpTagsInput-D1SuqbhB.js +300 -0
  64. package/dist/chunks/{LpTextarea-yP8hGedR.js → LpTextarea-uuScWo6-.js} +1 -1
  65. package/dist/chunks/{LpThemeProvider-Wjm7Tuit.js → LpThemeProvider-Be4r2TQX.js} +1 -1
  66. package/dist/chunks/{LpThemeSwitcher-CKLc10KZ.js → LpThemeSwitcher-B4aVPbNC.js} +19 -22
  67. package/dist/chunks/{LpTimeField-C5HRgS5H.js → LpTimeField-Cqe7fXnh.js} +1 -1
  68. package/dist/chunks/{LpToaster--oT6lfhL.js → LpToaster-DTtWuKvq.js} +76 -9
  69. package/dist/chunks/{LpTooltip-CBdzeKNf.js → LpTooltip-CXVKcOXT.js} +3 -2
  70. package/dist/chunks/{LpTopologyCanvas-DocsLal3.js → LpTopologyCanvas-6ozNrQKh.js} +2 -1
  71. package/dist/chunks/{LpUptimeBar-DLtxOMRy.js → LpUptimeBar-ugcv25xj.js} +2 -2
  72. package/dist/chunks/icons-CkA0njzm.js +43 -0
  73. package/dist/chunks/{useTheme-C8JHUlPM.js → useTheme-DJm1JSsY.js} +47 -50
  74. package/dist/component-names.d.ts +1 -1
  75. package/dist/components/ContextMenuItems.vue.js +1 -1
  76. package/dist/components/LayoutCanvas.vue.js +1 -1
  77. package/dist/components/LayoutNode.vue.js +1 -1
  78. package/dist/components/LpActionBar.vue.js +1 -1
  79. package/dist/components/LpAddressInput.vue.js +1 -1
  80. package/dist/components/LpAlert.vue.js +1 -1
  81. package/dist/components/LpAppShell.vue.js +1 -1
  82. package/dist/components/LpAutocomplete.vue.js +1 -1
  83. package/dist/components/LpAvatar.vue.js +1 -1
  84. package/dist/components/LpBreadcrumbs.vue.js +1 -1
  85. package/dist/components/LpButton.vue.d.ts +2 -2
  86. package/dist/components/LpButton.vue.js +1 -1
  87. package/dist/components/LpCalendar.vue.js +1 -1
  88. package/dist/components/LpCard.vue.js +1 -1
  89. package/dist/components/LpChart.vue.d.ts +16 -1
  90. package/dist/components/LpChart.vue.js +63 -5
  91. package/dist/components/LpCheckbox.vue.js +1 -1
  92. package/dist/components/LpCodeBlock.vue.js +1 -1
  93. package/dist/components/LpColorPicker.vue.d.ts +2 -2
  94. package/dist/components/LpColorPicker.vue.js +1 -1
  95. package/dist/components/LpCommandPalette.vue.d.ts +6 -0
  96. package/dist/components/LpCommandPalette.vue.js +62 -11
  97. package/dist/components/LpConfirmDialog.vue.js +1 -1
  98. package/dist/components/LpConfirmHost.vue.js +1 -1
  99. package/dist/components/LpContextMenu.vue.js +1 -1
  100. package/dist/components/LpDatePicker.vue.js +1 -1
  101. package/dist/components/LpDateRangePicker.vue.d.ts +60 -0
  102. package/dist/components/LpDateRangePicker.vue.js +4 -0
  103. package/dist/components/LpDisclosure.vue.js +1 -1
  104. package/dist/components/LpDrawer.vue.js +1 -1
  105. package/dist/components/LpDropdownMenu.vue.js +1 -1
  106. package/dist/components/LpDropzone.vue.js +1 -1
  107. package/dist/components/LpEmptyState.vue.js +1 -1
  108. package/dist/components/LpFieldNotice.vue.d.ts +8 -0
  109. package/dist/components/LpFieldNotice.vue.js +4 -0
  110. package/dist/components/LpFileTree.vue.js +1 -1
  111. package/dist/components/LpFileTreeNode.vue.js +1 -1
  112. package/dist/components/LpFormField.vue.d.ts +4 -1
  113. package/dist/components/LpFormField.vue.js +1 -1
  114. package/dist/components/LpIcon.vue.d.ts +0 -1
  115. package/dist/components/LpIcon.vue.js +1 -1
  116. package/dist/components/LpImageEditor.vue.js +2 -2
  117. package/dist/components/LpInput.vue.d.ts +19 -0
  118. package/dist/components/LpInput.vue.js +1 -1
  119. package/dist/components/LpLightbox.vue.js +1 -1
  120. package/dist/components/LpLogViewer.vue.d.ts +52 -1
  121. package/dist/components/LpLogViewer.vue.js +1 -1
  122. package/dist/components/LpMapPicker.vue.js +1 -1
  123. package/dist/components/LpMediaGallery.vue.js +1 -1
  124. package/dist/components/LpModal.vue.js +1 -1
  125. package/dist/components/LpModalNav.vue.js +1 -1
  126. package/dist/components/LpNotificationBell.vue.js +1 -1
  127. package/dist/components/LpNumberField.vue.js +1 -1
  128. package/dist/components/LpPagination.vue.js +1 -1
  129. package/dist/components/LpPasswordInput.vue.js +1 -1
  130. package/dist/components/LpPhoneInput.vue.d.ts +13 -0
  131. package/dist/components/LpPhoneInput.vue.js +1 -1
  132. package/dist/components/LpPie.vue.js +1 -1
  133. package/dist/components/LpPopover.vue.js +1 -1
  134. package/dist/components/LpProgress.vue.d.ts +1 -1
  135. package/dist/components/LpRangeCalendar.vue.d.ts +51 -0
  136. package/dist/components/LpRangeCalendar.vue.js +4 -0
  137. package/dist/components/LpRollingText.vue.d.ts +1 -1
  138. package/dist/components/LpRollingText.vue.js +1 -1
  139. package/dist/components/LpScrollArea.vue.d.ts +2 -2
  140. package/dist/components/LpScrollArea.vue.js +1 -1
  141. package/dist/components/LpSection.vue.js +1 -1
  142. package/dist/components/LpSegmented.vue.js +1 -1
  143. package/dist/components/LpSelect.vue.js +1 -1
  144. package/dist/components/LpShortcutsDialog.vue.d.ts +6 -0
  145. package/dist/components/LpShortcutsDialog.vue.js +56 -14
  146. package/dist/components/LpSidebar.vue.js +1 -1
  147. package/dist/components/LpSidebarNav.vue.js +1 -1
  148. package/dist/components/LpStat.vue.js +1 -1
  149. package/dist/components/LpStepper.vue.js +1 -1
  150. package/dist/components/LpSwitch.vue.js +1 -1
  151. package/dist/components/LpTable.vue.d.ts +84 -2
  152. package/dist/components/LpTable.vue.js +481 -107
  153. package/dist/components/LpTableFilter.vue.d.ts +31 -0
  154. package/dist/components/LpTableFilter.vue.js +4 -0
  155. package/dist/components/LpTabs.vue.js +1 -1
  156. package/dist/components/LpTagsInput.vue.d.ts +77 -0
  157. package/dist/components/LpTagsInput.vue.js +4 -0
  158. package/dist/components/LpTextarea.vue.js +1 -1
  159. package/dist/components/LpThemeProvider.vue.js +1 -1
  160. package/dist/components/LpThemeSwitcher.vue.d.ts +2 -2
  161. package/dist/components/LpThemeSwitcher.vue.js +1 -1
  162. package/dist/components/LpTimeField.vue.js +1 -1
  163. package/dist/components/LpToaster.vue.d.ts +2 -0
  164. package/dist/components/LpToaster.vue.js +1 -1
  165. package/dist/components/LpTooltip.vue.js +1 -1
  166. package/dist/components/LpTopologyCanvas.vue.js +1 -1
  167. package/dist/components/LpUptimeBar.vue.js +1 -1
  168. package/dist/components/chart.js +3 -2
  169. package/dist/components/commandSearch.js +3 -0
  170. package/dist/components/dateRange.d.ts +43 -0
  171. package/dist/components/dateRange.js +76 -0
  172. package/dist/components/exportData.d.ts +58 -0
  173. package/dist/components/exportData.js +165 -0
  174. package/dist/components/logSearch.d.ts +18 -0
  175. package/dist/components/logSearch.js +36 -0
  176. package/dist/components/phone.d.ts +41 -0
  177. package/dist/components/phone.js +80 -0
  178. package/dist/components/tableFilter.d.ts +36 -0
  179. package/dist/components/tableFilter.js +84 -0
  180. package/dist/components/tags.d.ts +20 -0
  181. package/dist/components/tags.js +37 -0
  182. package/dist/composables/useField.d.ts +4 -0
  183. package/dist/composables/useFieldNotice.d.ts +17 -0
  184. package/dist/composables/useFieldNotice.js +28 -0
  185. package/dist/composables/useForm.d.ts +53 -0
  186. package/dist/composables/useForm.js +207 -0
  187. package/dist/composables/useHotkeys.d.ts +65 -5
  188. package/dist/composables/useHotkeys.js +170 -9
  189. package/dist/composables/useInputMask.d.ts +59 -0
  190. package/dist/composables/useInputMask.js +170 -0
  191. package/dist/composables/useLocale.d.ts +2 -0
  192. package/dist/composables/useLocale.js +9 -0
  193. package/dist/composables/usePaintSelect.d.ts +22 -0
  194. package/dist/composables/usePaintSelect.js +169 -0
  195. package/dist/composables/useShift.js +7 -2
  196. package/dist/icons-all.d.ts +1 -0
  197. package/dist/icons-all.js +3 -0
  198. package/dist/icons.d.ts +14 -1
  199. package/dist/index.d.ts +29 -3
  200. package/dist/index.js +195 -138
  201. package/dist/kit-icons.d.ts +2 -0
  202. package/dist/theme/backdrop.d.ts +12 -0
  203. package/dist/theme/presets.d.ts +0 -2
  204. package/package.json +13 -4
  205. package/src/component-names.ts +4 -0
  206. package/src/components/ContextMenuItems.vue +1 -1
  207. package/src/components/LayoutNode.vue +11 -2
  208. package/src/components/LpActionBar.vue +1 -1
  209. package/src/components/LpAutocomplete.vue +1 -0
  210. package/src/components/LpAvatar.vue +2 -2
  211. package/src/components/LpButton.vue +1 -1
  212. package/src/components/LpChart.vue +80 -1
  213. package/src/components/LpColorPicker.vue +34 -1
  214. package/src/components/LpCommandPalette.vue +82 -8
  215. package/src/components/LpContextMenu.vue +1 -1
  216. package/src/components/LpDatePicker.vue +11 -4
  217. package/src/components/LpDateRangePicker.vue +226 -0
  218. package/src/components/LpDrawer.vue +1 -1
  219. package/src/components/LpDropdownMenu.vue +1 -0
  220. package/src/components/LpFieldNotice.vue +65 -0
  221. package/src/components/LpFormField.vue +33 -4
  222. package/src/components/LpIcon.vue +22 -4
  223. package/src/components/LpInput.vue +46 -6
  224. package/src/components/LpLogViewer.vue +225 -22
  225. package/src/components/LpModal.vue +2 -2
  226. package/src/components/LpModalNav.vue +13 -2
  227. package/src/components/LpNotificationBell.vue +15 -7
  228. package/src/components/LpPhoneInput.vue +179 -20
  229. package/src/components/LpPie.vue +8 -5
  230. package/src/components/LpPopover.vue +1 -0
  231. package/src/components/LpRangeCalendar.vue +365 -0
  232. package/src/components/LpRollingText.vue +3 -0
  233. package/src/components/LpScrollArea.vue +22 -2
  234. package/src/components/LpSelect.vue +0 -0
  235. package/src/components/LpShortcutsDialog.vue +77 -8
  236. package/src/components/LpStepper.vue +23 -10
  237. package/src/components/LpSwitch.vue +1 -1
  238. package/src/components/LpTable.vue +584 -65
  239. package/src/components/LpTableFilter.vue +175 -0
  240. package/src/components/LpTagsInput.vue +364 -0
  241. package/src/components/LpThemeSwitcher.vue +19 -23
  242. package/src/components/LpToaster.vue +91 -5
  243. package/src/components/LpTooltip.vue +9 -2
  244. package/src/components/LpTopologyCanvas.vue +7 -1
  245. package/src/components/chart.ts +5 -3
  246. package/src/components/commandSearch.ts +6 -0
  247. package/src/components/dateRange.ts +134 -0
  248. package/src/components/exportData.ts +228 -0
  249. package/src/components/logSearch.ts +46 -0
  250. package/src/components/phone.ts +140 -0
  251. package/src/components/tableFilter.ts +122 -0
  252. package/src/components/tags.ts +62 -0
  253. package/src/composables/useField.ts +4 -0
  254. package/src/composables/useFieldNotice.ts +59 -0
  255. package/src/composables/useForm.ts +314 -0
  256. package/src/composables/useHotkeys.ts +269 -13
  257. package/src/composables/useInputMask.ts +254 -0
  258. package/src/composables/useLocale.ts +14 -0
  259. package/src/composables/usePaintSelect.ts +243 -0
  260. package/src/composables/useShift.ts +13 -2
  261. package/src/iconSubset.d.mts +10 -0
  262. package/src/iconSubset.mjs +51 -0
  263. package/src/icons-all.ts +10 -0
  264. package/src/icons.ts +59 -8
  265. package/src/index.ts +37 -3
  266. package/src/kit-icons.ts +5 -0
  267. package/src/nuxt.ts +30 -2
  268. package/src/runtime/theme.plugin.ts +2 -2
  269. package/src/theme/backdrop.ts +69 -0
  270. package/src/theme/presets.ts +6 -64
  271. package/src/tokens/tokens.css +53 -4
package/src/icons.ts CHANGED
@@ -1,11 +1,62 @@
1
- import { addCollection } from "@iconify/vue"
2
- import lucide from "@iconify-json/lucide/icons.json"
1
+ import { addCollection, addIcon, iconLoaded, type IconifyIcon, type IconifyJSON } from "@iconify/vue"
2
+ import { ref } from "vue"
3
+ import { KIT_ICONS } from "./kit-icons"
3
4
 
4
5
  /*
5
- * Register the lucide collection offline so <LpIcon name="lucide:*"> resolves
6
- * without hitting the iconify API (required for Tauri / air-gapped use).
7
- *
8
- * This pulls the whole lucide set. If bundle size matters in an app, replace
9
- * this with a curated subset via addIcon() — the LpIcon API is unchanged.
6
+ * Offline icons without the whole lucide set in every bundle. The kit registers
7
+ * only the icons its own components render (KIT_ICONS, generated at build). Any
8
+ * other "lucide:*" name an app renders loads the full collection as a separate
9
+ * chunk on first use, from the app's own bundle, never from the iconify API, so
10
+ * Tauri and air-gapped apps keep working. Apps that need every icon in the
11
+ * server render (or no late chunk at all) register them up front: the Nuxt
12
+ * module's `icons` option, `registerIcons`, or `import "@leavepulse/ui/icons-all"`.
10
13
  */
11
- addCollection(lucide as Parameters<typeof addCollection>[0])
14
+ addCollection(KIT_ICONS)
15
+
16
+ /** Bumped whenever icons are registered, so rendered icons re-resolve. */
17
+ export const iconsVersion = ref(0)
18
+
19
+ let lucide: Promise<IconifyJSON> | undefined
20
+
21
+ function loadLucide(): Promise<IconifyJSON> {
22
+ lucide ??= import("@iconify-json/lucide/icons.json").then((m) => (m.default ?? m) as IconifyJSON)
23
+ return lucide
24
+ }
25
+
26
+ /** Register a whole iconify collection (any prefix) for offline use. */
27
+ export function registerIconCollection(collection: IconifyJSON): void {
28
+ addCollection(collection)
29
+ iconsVersion.value++
30
+ }
31
+
32
+ /**
33
+ * Register lucide icons by name ("check" or "lucide:check") from the bundled
34
+ * collection. Resolves once they render offline.
35
+ */
36
+ export async function registerIcons(names: readonly string[]): Promise<void> {
37
+ const wanted = names.map((n) => n.replace(/^lucide:/, ""))
38
+ if (wanted.every((n) => iconLoaded(`lucide:${n}`))) return
39
+ const all = await loadLucide()
40
+ for (const name of wanted) {
41
+ const parent = all.aliases?.[name]?.parent
42
+ const body = all.icons[name] ?? (parent ? all.icons[parent] : undefined)
43
+ if (!body) continue
44
+ const icon: IconifyIcon = { width: all.width, height: all.height, ...body }
45
+ addIcon(`lucide:${name}`, icon)
46
+ }
47
+ iconsVersion.value++
48
+ }
49
+
50
+ /** Register the full lucide collection. */
51
+ export async function registerAllIcons(): Promise<void> {
52
+ registerIconCollection(await loadLucide())
53
+ }
54
+
55
+ const pending = new Set<string>()
56
+
57
+ /** A lucide name that isn't registered yet: load it from the bundled set. */
58
+ export function requestIcon(name: string): void {
59
+ if (pending.has(name) || typeof window === "undefined") return
60
+ pending.add(name)
61
+ void registerIcons([name]).finally(() => pending.delete(name))
62
+ }
package/src/index.ts CHANGED
@@ -37,6 +37,9 @@ export { default as LpCard } from "./components/LpCard.vue"
37
37
  export { default as LpChart } from "./components/LpChart.vue"
38
38
  export type { ChartPointEvent } from "./components/LpChart.vue"
39
39
  export type { ChartText } from "./components/LpChart.vue"
40
+ export type { ChartExportOptions } from "./components/LpChart.vue"
41
+ export { backgroundOf, csvField, downloadFile, fileStem, inlineSvg, resolveCssColor, svgToPng, toCsv } from "./components/exportData"
42
+ export type { CsvColumn, CsvOptions, RasterOptions } from "./components/exportData"
40
43
  export {
41
44
  CHART_PALETTE,
42
45
  axisTicks,
@@ -79,6 +82,12 @@ export type { ConfirmOptions } from "./components/confirm"
79
82
  export { default as LpContextMenu } from "./components/LpContextMenu.vue"
80
83
  export type { ContextMenuItemDef } from "./components/LpContextMenu.vue"
81
84
  export { default as LpDatePicker } from "./components/LpDatePicker.vue"
85
+ export { default as LpDateRangePicker } from "./components/LpDateRangePicker.vue"
86
+ export type { DateRangePickerLabels } from "./components/LpDateRangePicker.vue"
87
+ export { default as LpRangeCalendar } from "./components/LpRangeCalendar.vue"
88
+ export type { RangeCalendarLabels } from "./components/LpRangeCalendar.vue"
89
+ export { clampRange, defaultRangePresets, formatRange, normalizeRange, sameRange } from "./components/dateRange"
90
+ export type { DateRange, DateRangePreset, DateRangePresetLabels } from "./components/dateRange"
82
91
  export { default as LpDisclosure } from "./components/LpDisclosure.vue"
83
92
  export { default as LpDivider } from "./components/LpDivider.vue"
84
93
  export { default as LpDrawer } from "./components/LpDrawer.vue"
@@ -102,8 +111,10 @@ export {
102
111
  subtreeIds,
103
112
  subtreeSize,
104
113
  } from "./components/fileTree"
114
+ export { default as LpFieldNotice } from "./components/LpFieldNotice.vue"
105
115
  export { default as LpFormField } from "./components/LpFormField.vue"
106
116
  export { default as LpIcon } from "./components/LpIcon.vue"
117
+ export { iconsVersion, registerAllIcons, registerIconCollection, registerIcons } from "./icons"
107
118
  export { default as LpImageEditor } from "./components/LpImageEditor.vue"
108
119
  export { default as LpInfraNode } from "./components/LpInfraNode.vue"
109
120
  export type { InfraNodeData } from "./components/LpInfraNode.vue"
@@ -116,6 +127,7 @@ export { default as LpLink } from "./components/LpLink.vue"
116
127
  export { default as LpLogViewer } from "./components/LpLogViewer.vue"
117
128
  export type { LogLevel, LogLine } from "./components/LpLogViewer.vue"
118
129
  export type { LogViewerLabels } from "./components/LpLogViewer.vue"
130
+ export { countLevels, matchPositions, matchesTerm, ringWindow, stepMatch } from "./components/logSearch"
119
131
  export { default as LpMediaGallery } from "./components/LpMediaGallery.vue"
120
132
  export { default as LpModal } from "./components/LpModal.vue"
121
133
  export { default as LpModalNav } from "./components/LpModalNav.vue"
@@ -167,11 +179,16 @@ export { default as LpSwitch } from "./components/LpSwitch.vue"
167
179
  export { default as LpTable } from "./components/LpTable.vue"
168
180
  export type { SortState, TableColumn, TablePage, TableQuery } from "./components/LpTable.vue"
169
181
  export type { TableLabels } from "./components/LpTable.vue"
182
+ export type { TableExportOptions } from "./components/LpTable.vue"
170
183
  export { compareValues } from "./components/tableSort"
171
184
  export { default as LpTableOfContents } from "./components/LpTableOfContents.vue"
172
185
  export type { TocLink } from "./components/LpTableOfContents.vue"
173
186
  export { default as LpTabs } from "./components/LpTabs.vue"
174
187
  export type { TabItem } from "./components/LpTabs.vue"
188
+ export { default as LpTagsInput } from "./components/LpTagsInput.vue"
189
+ export type { TagsInputLabels } from "./components/LpTagsInput.vue"
190
+ export { addTags, splitTags } from "./components/tags"
191
+ export type { AddTagsOptions, TagDuplicates, TagRejection, TagValidator } from "./components/tags"
175
192
  export { default as LpTextarea } from "./components/LpTextarea.vue"
176
193
  export { default as LpThemeSwitcher } from "./components/LpThemeSwitcher.vue"
177
194
  export { default as LpTilt } from "./components/LpTilt.vue"
@@ -225,7 +242,7 @@ export {
225
242
  useTheme,
226
243
  } from "./theme/useTheme"
227
244
  export type { RevealOrigin } from "./theme/useTheme"
228
- export { detectBackdropFilter, isBrokenBackdropEngine, NO_BACKDROP_ATTR } from "./theme/backdrop"
245
+ export { detectBackdropFilter, GLASS_BACKDROP_ATTR, isBrokenBackdropEngine, NO_BACKDROP_ATTR, setGlassBackdrop } from "./theme/backdrop"
229
246
  export { DEFAULT_SURFACE } from "./theme/tokens"
230
247
  export { defineTheme } from "./theme/define"
231
248
  export type { ThemeOverrides } from "./theme/define"
@@ -237,7 +254,7 @@ export type {
237
254
  SurfaceTokens,
238
255
  TokenSet,
239
256
  } from "./theme/tokens"
240
- export { amber, dark, leavepulse, light, lime, nord, presets, rose, violet } from "./theme/presets"
257
+ export { amber, dark, light, lime, nord, presets, rose, violet } from "./theme/presets"
241
258
  export type { PresetName } from "./theme/presets"
242
259
  export { parseConfig, serializeConfig, UI_CONFIG_VERSION } from "./theme/config"
243
260
  export type { UiConfig } from "./theme/config"
@@ -252,7 +269,16 @@ export {
252
269
  mergeShortcutGroups,
253
270
  } from "./composables/useHotkeys"
254
271
  export type { HotkeyBinding, HotkeyHelp, ShortcutEntry, ShortcutGroup } from "./composables/useHotkeys"
255
- export { matchesHotkey, useAppleKeyboard } from "./composables/useHotkeys"
272
+ export {
273
+ findHotkeyConflicts,
274
+ hotkeyConflicts,
275
+ hotkeySteps,
276
+ matchesHotkey,
277
+ pendingHotkey,
278
+ sequenceProgress,
279
+ useAppleKeyboard,
280
+ } from "./composables/useHotkeys"
281
+ export type { HotkeyConflict, HotkeyStep } from "./composables/useHotkeys"
256
282
  export { anyModalOpen, topModalElement, useModalLayer } from "./components/modalDepth"
257
283
  export type { ModalLayer, ModalLayerOptions } from "./components/modalDepth"
258
284
  export { provideGlass, useGlass } from "./composables/useGlass"
@@ -260,7 +286,11 @@ export { LP_CONFIG, lpConfig, mergeConfig, provideLpConfig, useLabels, useLinkCo
260
286
  export type { LabelScope, LpConfig } from "./composables/useLpConfig"
261
287
  export { useMergedClass, useMergedAttrs, mergeClass } from "./composables/useMergedClass"
262
288
  export { anchorPattern, stripDisallowed, useInputFilter } from "./composables/useInputFilter"
289
+ export { usePaintSelect } from "./composables/usePaintSelect"
290
+ export type { UsePaintSelectOptions } from "./composables/usePaintSelect"
263
291
  export { LP_FIELD, fieldMessageId, provideField, useField, useFieldControl } from "./composables/useField"
292
+ export { FIELD_NOTICE_MS, useFieldNotice } from "./composables/useFieldNotice"
293
+ export type { FieldNotice, FieldNoticeOptions, FieldNoticeTone } from "./composables/useFieldNotice"
264
294
  export type { FieldContext, FieldControlState } from "./composables/useField"
265
295
  export type { UseInputFilterOptions } from "./composables/useInputFilter"
266
296
  export { easeOut, easeTravel, easingToken, prefersReducedMotion } from "./composables/easing"
@@ -271,6 +301,10 @@ export { useRovingFocus } from "./composables/useRovingFocus"
271
301
  export type { RovingItem, UseRovingFocusOptions } from "./composables/useRovingFocus"
272
302
  export { useFormDraft } from "./composables/useFormDraft"
273
303
  export type { UseFormDraft, UseFormDraftOptions } from "./composables/useFormDraft"
304
+ export { DEFAULT_MASK_TOKENS, applyMask, maskDelete, parseMask, useInputMask } from "./composables/useInputMask"
305
+ export type { MaskOptions, MaskResult, MaskSpec, MaskToken, MaskTokens, UseInputMaskOptions } from "./composables/useInputMask"
306
+ export { deepEqual, useForm } from "./composables/useForm"
307
+ export type { FieldBinding, FieldRule, FormErrorMessage, FormErrors, FormRules, UseForm, UseFormOptions } from "./composables/useForm"
274
308
 
275
309
  export { useSettled } from "./composables/useSettled"
276
310
  export type { UseSettledOptions } from "./composables/useSettled"
@@ -0,0 +1,5 @@
1
+ /* AUTO-GENERATED by scripts/gen-kit-icons.mjs — do not edit.
2
+ * The lucide icons kit components render, registered offline by icons.ts. */
3
+ import type { IconifyJSON } from "@iconify/vue"
4
+
5
+ export const KIT_ICONS: IconifyJSON = {"prefix":"lucide","icons":{"activity":{"body":"<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2\"/>"},"arrow-down":{"body":"<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M12 5v14m7-7l-7 7l-7-7\"/>"},"arrow-up":{"body":"<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"m5 12l7-7l7 7m-7 7V5\"/>"},"bell":{"body":"<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M10.268 21a2 2 0 0 0 3.464 0m-10.47-5.674A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326\"/>"},"bell-off":{"body":"<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M10.268 21a2 2 0 0 0 3.464 0M17 17H4a1 1 0 0 1-.74-1.673C4.59 13.956 6 12.499 6 8a6 6 0 0 1 .258-1.742M2 2l20 20M8.668 3.01A6 6 0 0 1 18 8c0 2.687.77 4.653 1.707 6.05\"/>"},"calendar":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><path d=\"M8 2v4m8-4v4\"/><rect width=\"18\" height=\"18\" x=\"3\" y=\"4\" rx=\"2\"/><path d=\"M3 10h18\"/></g>"},"calendar-range":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><rect width=\"18\" height=\"18\" x=\"3\" y=\"4\" rx=\"2\"/><path d=\"M16 2v4M3 10h18M8 2v4m9 8h-6m2 4H7m0-4h.01M17 18h.01\"/></g>"},"chart-no-axes-column":{"body":"<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M5 21v-6m7 6V3m7 18V9\"/>"},"chart-pie":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><path d=\"M21 12c.552 0 1.005-.449.95-.998a10 10 0 0 0-8.953-8.951c-.55-.055-.998.398-.998.95v8a1 1 0 0 0 1 1z\"/><path d=\"M21.21 15.89A10 10 0 1 1 8 2.83\"/></g>"},"check":{"body":"<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M20 6L9 17l-5-5\"/>"},"check-check":{"body":"<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M18 6L7 17l-5-5m20-2l-7.5 7.5L13 16\"/>"},"circle-check-big":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><path d=\"M21.801 10A10 10 0 1 1 17 3.335\"/><path d=\"m9 11l3 3L22 4\"/></g>"},"chevron-down":{"body":"<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"m6 9l6 6l6-6\"/>"},"chevron-left":{"body":"<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"m15 18l-6-6l6-6\"/>"},"chevron-right":{"body":"<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"m9 18l6-6l-6-6\"/>"},"chevron-up":{"body":"<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"m18 15l-6-6l-6 6\"/>"},"chevrons-up-down":{"body":"<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"m7 15l5 5l5-5M7 9l5-5l5 5\"/>"},"circle-alert":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"M12 8v4m0 4h.01\"/></g>"},"circle-check":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"m9 12l2 2l4-4\"/></g>"},"circle-x":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"m15 9l-6 6m0-6l6 6\"/></g>"},"clipboard":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><rect width=\"8\" height=\"4\" x=\"8\" y=\"2\" rx=\"1\" ry=\"1\"/><path d=\"M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2\"/></g>"},"clipboard-list":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><rect width=\"8\" height=\"4\" x=\"8\" y=\"2\" rx=\"1\" ry=\"1\"/><path d=\"M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2m4 7h4m-4 5h4m-8-5h.01M8 16h.01\"/></g>"},"clock":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"M12 6v6l4 2\"/></g>"},"code":{"body":"<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"m16 18l6-6l-6-6M8 6l-6 6l6 6\"/>"},"columns-3":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\"/><path d=\"M9 3v18m6-18v18\"/></g>"},"container":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><path d=\"M22 7.7c0-.6-.4-1.2-.8-1.5l-6.3-3.9a1.72 1.72 0 0 0-1.7 0l-10.3 6c-.5.2-.9.8-.9 1.4v6.6c0 .5.4 1.2.8 1.5l6.3 3.9a1.72 1.72 0 0 0 1.7 0l10.3-6c.5-.3.9-1 .9-1.5Z\"/><path d=\"M10 21.9V14L2.1 9.1M10 14l11.9-6.9M14 19.8v-8.1m4 5.8V9.4\"/></g>"},"copy":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></g>"},"crosshair":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"M22 12h-4M6 12H2m10-6V2m0 20v-4\"/></g>"},"database":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><ellipse cx=\"12\" cy=\"5\" rx=\"9\" ry=\"3\"/><path d=\"M3 5v14a9 3 0 0 0 18 0V5\"/><path d=\"M3 12a9 3 0 0 0 18 0\"/></g>"},"dot":{"body":"<circle cx=\"12.1\" cy=\"12.1\" r=\"1\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"/>"},"download":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><path d=\"M12 15V3m9 12v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\"/><path d=\"m7 10l5 5l5-5\"/></g>"},"external-link":{"body":"<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M15 3h6v6m-11 5L21 3m-3 10v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\"/>"},"eye":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><path d=\"M2.062 12.348a1 1 0 0 1 0-.696a10.75 10.75 0 0 1 19.876 0a1 1 0 0 1 0 .696a10.75 10.75 0 0 1-19.876 0\"/><circle cx=\"12\" cy=\"12\" r=\"3\"/></g>"},"eye-off":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><path d=\"M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575a1 1 0 0 1 0 .696a10.8 10.8 0 0 1-1.444 2.49m-6.41-.679a3 3 0 0 1-4.242-4.242\"/><path d=\"M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151a1 1 0 0 1 0-.696a10.75 10.75 0 0 1 4.446-5.143M2 2l20 20\"/></g>"},"file":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><path d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\"/><path d=\"M14 2v5a1 1 0 0 0 1 1h5\"/></g>"},"file-archive":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><path d=\"M13.659 22H18a2 2 0 0 0 2-2V8a2.4 2.4 0 0 0-.706-1.706l-3.588-3.588A2.4 2.4 0 0 0 14 2H6a2 2 0 0 0-2 2v11.5\"/><path d=\"M14 2v5a1 1 0 0 0 1 1h5M8 12v-1m0 7v-2m0-9V6\"/><circle cx=\"8\" cy=\"20\" r=\"2\"/></g>"},"file-code":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><path d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\"/><path d=\"M14 2v5a1 1 0 0 0 1 1h5m-10 4.5L8 15l2 2.5m4-5l2 2.5l-2 2.5\"/></g>"},"file-cog":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><path d=\"M15 8a1 1 0 0 1-1-1V2a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8zm5 0v12a2 2 0 0 1-2 2h-4.182M3.305 19.53l.923-.382M4 10.592V4a2 2 0 0 1 2-2h8M4.228 16.852l-.924-.383m2.548-1.241l-.383-.923m.383 6.467l-.383.924m2.679-6.468l.383-.923m-.001 7.391l-.382-.924m1.625-3.92l.922-.383m-.922 2.679l.922.383\"/><circle cx=\"7\" cy=\"18\" r=\"3\"/></g>"},"file-image":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><path d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\"/><path d=\"M14 2v5a1 1 0 0 0 1 1h5\"/><circle cx=\"10\" cy=\"12\" r=\"2\"/><path d=\"m20 17l-1.296-1.296a2.41 2.41 0 0 0-3.408 0L9 22\"/></g>"},"file-json":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><path d=\"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z\"/><path d=\"M14 2v4a2 2 0 0 0 2 2h4m-10 4a1 1 0 0 0-1 1v1a1 1 0 0 1-1 1a1 1 0 0 1 1 1v1a1 1 0 0 0 1 1m4 0a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1a1 1 0 0 1-1-1v-1a1 1 0 0 0-1-1\"/></g>","hidden":true},"file-key":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><path d=\"M14 2v5a1 1 0 0 0 1 1h5M4 12v6m0-4h2\"/><path d=\"M9.65 22H18a2 2 0 0 0 2-2V8a2.4 2.4 0 0 0-.706-1.706l-3.588-3.588A2.4 2.4 0 0 0 14 2H6a2 2 0 0 0-2 2v4\"/><circle cx=\"4\" cy=\"20\" r=\"2\"/></g>"},"file-lock":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><path d=\"M4 9.8V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.706.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2h-3\"/><path d=\"M14 2v5a1 1 0 0 0 1 1h5M9 17v-2a2 2 0 0 0-4 0v2\"/><rect width=\"8\" height=\"5\" x=\"3\" y=\"17\" rx=\"1\"/></g>"},"file-spreadsheet":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><path d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\"/><path d=\"M14 2v5a1 1 0 0 0 1 1h5M8 13h2m4 0h2m-8 4h2m4 0h2\"/></g>"},"file-terminal":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><path d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\"/><path d=\"M14 2v5a1 1 0 0 0 1 1h5M8 16l2-2l-2-2m4 6h4\"/></g>"},"file-text":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><path d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\"/><path d=\"M14 2v5a1 1 0 0 0 1 1h5M10 9H8m8 4H8m8 4H8\"/></g>"},"file-type":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><path d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\"/><path d=\"M14 2v5a1 1 0 0 0 1 1h5m-9 10h2m-1-6v6m-3-5v-.5a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 .5.5v.5\"/></g>"},"filter":{"body":"<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M22 3H2l8 9.46V19l4 2v-8.54z\"/>","hidden":true},"filter-x":{"body":"<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M13.013 3H2l8 9.46V19l4 2v-8.54l.9-1.055M22 3l-5 5m0-5l5 5\"/>","hidden":true},"folder":{"body":"<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z\"/>"},"folder-open":{"body":"<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"m6 14l1.5-2.9A2 2 0 0 1 9.24 10H20a2 2 0 0 1 1.94 2.5l-1.54 6a2 2 0 0 1-1.95 1.5H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H18a2 2 0 0 1 2 2v2\"/>"},"folder-search":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><path d=\"M10.7 20H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2v4.1M21 21l-1.9-1.9\"/><circle cx=\"17\" cy=\"17\" r=\"3\"/></g>"},"git-branch":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><path d=\"M15 6a9 9 0 0 0-9 9V3\"/><circle cx=\"18\" cy=\"6\" r=\"3\"/><circle cx=\"6\" cy=\"18\" r=\"3\"/></g>"},"image-off":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><path d=\"m2 2l20 20M10.41 10.41a2 2 0 1 1-2.83-2.83m5.92 5.92L6 21m12-9l3 3\"/><path d=\"M3.59 3.59A2 2 0 0 0 3 5v14a2 2 0 0 0 2 2h14c.55 0 1.052-.22 1.41-.59M21 15V5a2 2 0 0 0-2-2H9\"/></g>"},"inbox":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><path d=\"M22 12h-6l-2 3h-4l-2-3H2\"/><path d=\"M5.45 5.11L2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11\"/></g>"},"info":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"M12 16v-4m0-4h.01\"/></g>"},"link":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><path d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/><path d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/></g>"},"list":{"body":"<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M3 5h.01M3 12h.01M3 19h.01M8 5h13M8 12h13M8 19h13\"/>"},"loader-circle":{"body":"<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M21 12a9 9 0 1 1-6.219-8.56\"/>"},"locate-fixed":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><path d=\"M2 12h3m14 0h3M12 2v3m0 14v3\"/><circle cx=\"12\" cy=\"12\" r=\"7\"/><circle cx=\"12\" cy=\"12\" r=\"3\"/></g>"},"lock":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><rect width=\"18\" height=\"11\" x=\"3\" y=\"11\" rx=\"2\" ry=\"2\"/><path d=\"M7 11V7a5 5 0 0 1 10 0v4\"/></g>"},"lock-open":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><rect width=\"18\" height=\"11\" x=\"3\" y=\"11\" rx=\"2\" ry=\"2\"/><path d=\"M7 11V7a5 5 0 0 1 9.9-1\"/></g>"},"map":{"body":"<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M14.106 5.553a2 2 0 0 0 1.788 0l3.659-1.83A1 1 0 0 1 21 4.619v12.764a1 1 0 0 1-.553.894l-4.553 2.277a2 2 0 0 1-1.788 0l-4.212-2.106a2 2 0 0 0-1.788 0l-3.659 1.83A1 1 0 0 1 3 19.381V6.618a1 1 0 0 1 .553-.894l4.553-2.277a2 2 0 0 1 1.788 0zm.894.211v15M9 3.236v15\"/>"},"map-pin":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><path d=\"M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0\"/><circle cx=\"12\" cy=\"10\" r=\"3\"/></g>"},"maximize-2":{"body":"<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M15 3h6v6m0-6l-7 7M3 21l7-7m-1 7H3v-6\"/>"},"menu":{"body":"<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 5h16M4 12h16M4 19h16\"/>"},"minus":{"body":"<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M5 12h14\"/>"},"monitor":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><rect width=\"20\" height=\"14\" x=\"2\" y=\"3\" rx=\"2\"/><path d=\"M8 21h8m-4-4v4\"/></g>"},"moon":{"body":"<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401\"/>"},"octagon-alert":{"body":"<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M12 16h.01M12 8v4m3.312-10a2 2 0 0 1 1.414.586l4.688 4.688A2 2 0 0 1 22 8.688v6.624a2 2 0 0 1-.586 1.414l-4.688 4.688a2 2 0 0 1-1.414.586H8.688a2 2 0 0 1-1.414-.586l-4.688-4.688A2 2 0 0 1 2 15.312V8.688a2 2 0 0 1 .586-1.414l4.688-4.688A2 2 0 0 1 8.688 2z\"/>"},"package":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><path d=\"M11 21.73a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73zm1 .27V12\"/><path d=\"M3.29 7L12 12l8.71-5M7.5 4.27l9 5.15\"/></g>"},"palette":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><path d=\"M12 22a1 1 0 0 1 0-20a10 9 0 0 1 10 9a5 5 0 0 1-5 5h-2.25a1.75 1.75 0 0 0-1.4 2.8l.3.4a1.75 1.75 0 0 1-1.4 2.8z\"/><circle cx=\"13.5\" cy=\"6.5\" r=\".5\" fill=\"currentColor\"/><circle cx=\"17.5\" cy=\"10.5\" r=\".5\" fill=\"currentColor\"/><circle cx=\"6.5\" cy=\"12.5\" r=\".5\" fill=\"currentColor\"/><circle cx=\"8.5\" cy=\"7.5\" r=\".5\" fill=\"currentColor\"/></g>"},"plus":{"body":"<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M5 12h14m-7-7v14\"/>"},"rotate-ccw":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><path d=\"M3 12a9 9 0 1 0 9-9a9.75 9.75 0 0 0-6.74 2.74L3 8\"/><path d=\"M3 3v5h5\"/></g>"},"rotate-cw":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><path d=\"M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8\"/><path d=\"M21 3v5h-5\"/></g>"},"scroll-text":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><path d=\"M15 12h-5m5-4h-5m9 9V5a2 2 0 0 0-2-2H4\"/><path d=\"M8 21h12a2 2 0 0 0 2-2v-1a1 1 0 0 0-1-1H11a1 1 0 0 0-1 1v1a2 2 0 1 1-4 0V5a2 2 0 1 0-4 0v2a1 1 0 0 0 1 1h3\"/></g>"},"search":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><path d=\"m21 21l-4.34-4.34\"/><circle cx=\"11\" cy=\"11\" r=\"8\"/></g>"},"server":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><rect width=\"20\" height=\"8\" x=\"2\" y=\"2\" rx=\"2\" ry=\"2\"/><rect width=\"20\" height=\"8\" x=\"2\" y=\"14\" rx=\"2\" ry=\"2\"/><path d=\"M6 6h.01M6 18h.01\"/></g>"},"sun":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><circle cx=\"12\" cy=\"12\" r=\"4\"/><path d=\"M12 2v2m0 16v2M4.93 4.93l1.41 1.41m11.32 11.32l1.41 1.41M2 12h2m16 0h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41\"/></g>"},"trash-2":{"body":"<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M10 11v6m4-6v6m5-11v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6M3 6h18M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\"/>"},"trending-down":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><path d=\"M16 17h6v-6\"/><path d=\"m22 17l-8.5-8.5l-5 5L2 7\"/></g>"},"trending-up":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><path d=\"M16 7h6v6\"/><path d=\"m22 7l-8.5 8.5l-5-5L2 17\"/></g>"},"triangle-alert":{"body":"<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"m21.73 18l-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3M12 9v4m0 4h.01\"/>"},"undo-2":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><path d=\"M9 14L4 9l5-5\"/><path d=\"M4 9h10.5a5.5 5.5 0 0 1 5.5 5.5a5.5 5.5 0 0 1-5.5 5.5H11\"/></g>"},"upload":{"body":"<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M12 3v12m5-7l-5-5l-5 5m14 7v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\"/>"},"x":{"body":"<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M18 6L6 18M6 6l12 12\"/>"},"zoom-in":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><circle cx=\"11\" cy=\"11\" r=\"8\"/><path d=\"m21 21l-4.35-4.35M11 8v6m-3-3h6\"/></g>"},"zoom-out":{"body":"<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><circle cx=\"11\" cy=\"11\" r=\"8\"/><path d=\"m21 21l-4.35-4.35M8 11h6\"/></g>"}},"width":24,"height":24,"aliases":{"check-circle":{"parent":"circle-check-big"}}}
package/src/nuxt.ts CHANGED
@@ -18,9 +18,17 @@
18
18
  * link false to skip providing NuxtLink as the kit's link component
19
19
  * exclude component names not to auto-register (e.g. ["LayoutCanvas"]
20
20
  * when the app has its own component of that name)
21
+ * icons which lucide icons render in the server pass and ship in the
22
+ * main bundle: "scan" (default) finds "lucide:*" literals in the
23
+ * app's source, "all" registers the whole set, "kit" only the
24
+ * kit's own, or a list of names. Anything else still renders,
25
+ * from a lazily loaded chunk of the bundled collection.
21
26
  */
22
- import { addComponent, addPlugin, addTemplate, createResolver, defineNuxtModule } from "@nuxt/kit"
27
+ import { readFileSync } from "node:fs"
28
+ import { createRequire } from "node:module"
29
+ import { addComponent, addPlugin, addPluginTemplate, addTemplate, createResolver, defineNuxtModule } from "@nuxt/kit"
23
30
  import { COMPONENT_NAMES } from "./component-names"
31
+ import { namesInDirs, subset } from "./iconSubset.mjs"
24
32
 
25
33
  export interface LeavepulseUiOptions {
26
34
  /** Register the SSR theme plugin. Disable to wire theming yourself. */
@@ -33,17 +41,28 @@ export interface LeavepulseUiOptions {
33
41
  link?: boolean
34
42
  /** Component names to leave unregistered. */
35
43
  exclude?: string[]
44
+ /** Lucide icons registered up front (default "scan"). */
45
+ icons?: "scan" | "all" | "kit" | string[]
46
+ }
47
+
48
+ function iconsPlugin(mode: LeavepulseUiOptions["icons"], srcDir: string): string {
49
+ if (mode === "kit") return ""
50
+ if (mode === "all") return 'import "@leavepulse/ui/icons-all"\n'
51
+ const lucide = JSON.parse(readFileSync(createRequire(import.meta.url).resolve("@iconify-json/lucide/icons.json"), "utf8"))
52
+ const names = Array.isArray(mode) ? mode.map((n) => n.replace(/^lucide:/, "")) : namesInDirs([srcDir])
53
+ return `import { registerIconCollection } from "@leavepulse/ui"\nregisterIconCollection(${JSON.stringify(subset(lucide, names))})\n`
36
54
  }
37
55
 
38
56
  export default defineNuxtModule<LeavepulseUiOptions>({
39
57
  meta: { name: "@leavepulse/ui", configKey: "leavepulseUi" },
40
- defaults: { theme: true, link: true },
58
+ defaults: { theme: true, link: true, icons: "scan" },
41
59
  setup(
42
60
  options: LeavepulseUiOptions,
43
61
  nuxt: {
44
62
  options: {
45
63
  runtimeConfig: { public: Record<string, unknown> }
46
64
  alias: Record<string, string>
65
+ srcDir: string
47
66
  }
48
67
  hook: (
49
68
  name: "prepare:types",
@@ -64,6 +83,15 @@ export default defineNuxtModule<LeavepulseUiOptions>({
64
83
  })
65
84
  }
66
85
 
86
+ const icons = iconsPlugin(options.icons, nuxt.options.srcDir)
87
+ if (icons) {
88
+ addPluginTemplate({
89
+ filename: "leavepulse-ui-icons.mjs",
90
+ mode: "all",
91
+ getContents: () => `${icons}import { defineNuxtPlugin } from "#app"\nexport default defineNuxtPlugin(() => {})\n`,
92
+ })
93
+ }
94
+
67
95
  if (options.link !== false) {
68
96
  addPlugin({ src: resolver.resolve("./runtime/config.plugin"), mode: "all" })
69
97
  }
@@ -17,7 +17,7 @@
17
17
  // Through the barrel, not "../theme/…": this file is compiled by the consuming
18
18
  // app, where the barrel resolves to the same dist instance the components use.
19
19
  import {
20
- leavepulse,
20
+ dark,
21
21
  presets,
22
22
  THEME_COOKIE,
23
23
  themeFromCookie,
@@ -43,7 +43,7 @@ export default defineNuxtPlugin(() => {
43
43
  }
44
44
 
45
45
  const themes = [...(appThemes as TokenSet[]), ...(Object.values(presets) as TokenSet[])]
46
- const fallback = themes.find((theme) => theme.name === options.defaultTheme) ?? leavepulse
46
+ const fallback = themes.find((theme) => theme.name === options.defaultTheme) ?? dark
47
47
 
48
48
  // Raw value: themeFromCookie decodes safely itself, a throwing decode here
49
49
  // would turn a malformed cookie into a 500 on every request.
@@ -49,3 +49,72 @@ export function detectBackdropFilter(
49
49
  root.toggleAttribute(NO_BACKDROP_ATTR, !usable)
50
50
  return usable
51
51
  }
52
+
53
+ /*
54
+ * Glass without backdrop-filter. Where the engine cannot blur what lies under
55
+ * a panel (the flag above), it can still blur an ordinary element, so a panel
56
+ * can be frosted by painting a blurred copy of what is under it, as long as
57
+ * that is known. In an app that paints its own wallpaper (a launcher, a shell)
58
+ * it is: the consumer hands the wallpaper over as a CSS `background` value,
59
+ * and every `.lp-glass-overlay` draws it, blurred and aligned to the viewport,
60
+ * beneath its tint. Live content under the panel stays sharp; the wallpaper,
61
+ * which is most of what glass shows, reads as frosted.
62
+ *
63
+ * The copy is placed by the panel's position on screen, which overlays animate
64
+ * and drawers drag, so while any glass panel is mounted its offset is kept in
65
+ * CSS variables (`--lp-gx`, `--lp-gy`) once a frame. Nothing runs where the
66
+ * real blur works or no backdrop was given.
67
+ */
68
+ export const GLASS_BACKDROP_ATTR = "data-lp-glass-backdrop"
69
+
70
+ let tracking = 0
71
+ let observer: MutationObserver | undefined
72
+
73
+ function trackPanels() {
74
+ const panels = document.querySelectorAll<HTMLElement>(".lp-glass-overlay")
75
+ for (const panel of panels) {
76
+ const rect = panel.getBoundingClientRect()
77
+ const x = `${Math.round(rect.left)}px`
78
+ const y = `${Math.round(rect.top)}px`
79
+ if (panel.style.getPropertyValue("--lp-gx") !== x) panel.style.setProperty("--lp-gx", x)
80
+ if (panel.style.getPropertyValue("--lp-gy") !== y) panel.style.setProperty("--lp-gy", y)
81
+ }
82
+ tracking = panels.length ? requestAnimationFrame(trackPanels) : 0
83
+ }
84
+
85
+ function startTracking() {
86
+ if (!tracking && document.querySelector(".lp-glass-overlay")) tracking = requestAnimationFrame(trackPanels)
87
+ }
88
+
89
+ /**
90
+ * Give glass panels a wallpaper to frost where backdrop-filter does not work:
91
+ * `setGlassBackdrop("url(/bg.jpg) center / cover no-repeat, #0b0f14")`, the
92
+ * same value the app paints behind itself. `filter` replaces the default blur,
93
+ * e.g. `"none"` for a wallpaper that was blurred ahead of time, which is
94
+ * cheaper on an engine that blurs on the CPU. `null` turns it off.
95
+ */
96
+ export function setGlassBackdrop(
97
+ background: string | null,
98
+ options: { filter?: string; root?: HTMLElement } = {},
99
+ ): void {
100
+ if (typeof document === "undefined") return
101
+ const root = options.root ?? document.documentElement
102
+ if (!background) {
103
+ root.removeAttribute(GLASS_BACKDROP_ATTR)
104
+ root.style.removeProperty("--lp-glass-backdrop")
105
+ root.style.removeProperty("--lp-glass-backdrop-filter")
106
+ observer?.disconnect()
107
+ observer = undefined
108
+ return
109
+ }
110
+ root.setAttribute(GLASS_BACKDROP_ATTR, "")
111
+ root.style.setProperty("--lp-glass-backdrop", background)
112
+ if (options.filter) root.style.setProperty("--lp-glass-backdrop-filter", options.filter)
113
+ else root.style.removeProperty("--lp-glass-backdrop-filter")
114
+ if (!root.hasAttribute(NO_BACKDROP_ATTR) || typeof MutationObserver === "undefined") return
115
+ if (!observer) {
116
+ observer = new MutationObserver(startTracking)
117
+ observer.observe(document.body, { childList: true, subtree: true })
118
+ }
119
+ startTracking()
120
+ }
@@ -1,4 +1,4 @@
1
- import type { SurfaceTokens, TokenSet } from "./tokens"
1
+ import type { TokenSet } from "./tokens"
2
2
 
3
3
  /*
4
4
  * Built-in theme presets — plain TokenSet objects (JSON). These ARE the themes;
@@ -14,13 +14,12 @@ const interFont = {
14
14
  }
15
15
 
16
16
  /*
17
- * NOTE on naming: the exported CONST names are frozen for compatibility (apps
18
- * import `dark` / `leavepulse` directly), but the display `name` changed —
19
- * `leavepulse` is now the one called "Dark" (it is the product's dark theme),
20
- * and this near-black neutral became "Onyx" to free that label up.
17
+ * The kit's dark theme, a near-black neutral. It was displayed as "Onyx" while
18
+ * the LeavePulse site theme held the "Dark" label; with that theme gone the
19
+ * label is back here.
21
20
  */
22
21
  export const dark: TokenSet = {
23
- name: "Onyx",
22
+ name: "Dark",
24
23
  mode: "dark",
25
24
  colors: {
26
25
  surface: "#080b0d",
@@ -120,63 +119,6 @@ export const lime: TokenSet = {
120
119
  },
121
120
  }
122
121
 
123
- /*
124
- * Glass skin — frosted panels with backdrop blur, a faint top-down highlight
125
- * overlay, a layered drop shadow and an inset highlight line. Opt a theme into
126
- * it by setting its `surface` axis to this (the LeavePulse site uses it).
127
- */
128
- const glassSurface: SurfaceTokens = {
129
- borderWidth: "1px",
130
- panelBlur: "10px",
131
- panelSaturate: "120%",
132
- panelOverlay:
133
- "linear-gradient(180deg, rgba(255, 255, 255, 0.06), rgba(255, 255, 255, 0.01))",
134
- panelShadow: "0 20px 60px rgba(0, 0, 0, 0.35)",
135
- panelInset: "inset 0 1px 0 rgba(255, 255, 255, 0.08)",
136
- }
137
-
138
- /*
139
- * LeavePulse site theme — the colours the website shipped before the kit
140
- * migration (deep navy surfaces, cyan brand, teal accent), with the glass skin.
141
- * Distinct from `dark` (which is a near-black neutral) so the site keeps its
142
- * look when it switches its CSS-var dictionary over to the kit.
143
- */
144
- export const leavepulse: TokenSet = {
145
- name: "Dark",
146
- mode: "dark",
147
- colors: {
148
- surface: "#020618",
149
- surfaceRaised: "#0b1222",
150
- surfaceSoft: "rgba(11, 18, 34, 0.7)",
151
- ink: "#f3f6ff",
152
- inkInverse: "#0b1222",
153
- muted: "#94a3bf",
154
- mutedStrong: "#cad5e2",
155
- brand: "#00bcff",
156
- brandHover: "#19c3ff",
157
- brandSoft: "rgba(0, 188, 255, 0.2)",
158
- action: "#44c2ad",
159
- actionHover: "#56d3be",
160
- actionSoft: "rgba(68, 194, 173, 0.14)",
161
- accent: "#d36a2c",
162
- accentHover: "#da824e",
163
- accentSoft: "rgba(211, 106, 44, 0.14)",
164
- danger: "#f87171",
165
- dangerHover: "#fca5a5",
166
- dangerSoft: "rgba(248, 113, 113, 0.14)",
167
- line: "#1c2740",
168
- lineStrong: "rgba(255, 255, 255, 0.15)",
169
- ring: "rgba(0, 188, 255, 0.35)",
170
- },
171
- shape: { ...sharedShape, radiusControl: 12 },
172
- density: { ...sharedDensity },
173
- font: {
174
- sans: '"Inter", "IBM Plex Sans", "Segoe UI", sans-serif',
175
- mono: '"JetBrains Mono", "SF Mono", ui-monospace, monospace',
176
- },
177
- surface: glassSurface,
178
- }
179
-
180
122
  export const rose: TokenSet = {
181
123
  name: "Rose",
182
124
  mode: "dark",
@@ -305,5 +247,5 @@ export const nord: TokenSet = {
305
247
  font: { ...interFont },
306
248
  }
307
249
 
308
- export const presets = { dark, light, lime, leavepulse, rose, amber, violet, nord } as const
250
+ export const presets = { dark, light, lime, rose, amber, violet, nord } as const
309
251
  export type PresetName = keyof typeof presets
@@ -256,6 +256,19 @@
256
256
  transform: translateY(4px) scale(0.97);
257
257
  }
258
258
  }
259
+ /* A chip joining a row of chips (tags): grows out of its own centre. */
260
+ @keyframes chip-in {
261
+ from {
262
+ opacity: 0;
263
+ transform: scale(0.85);
264
+ }
265
+ }
266
+ @keyframes chip-out {
267
+ to {
268
+ opacity: 0;
269
+ transform: scale(0.85);
270
+ }
271
+ }
259
272
  /* Option cascade: items slide in top→down on open. */
260
273
  @keyframes option-in {
261
274
  from {
@@ -537,11 +550,14 @@
537
550
  backdrop-filter: blur(var(--glass-overlay-blur, 28px)) saturate(170%);
538
551
  }
539
552
 
553
+ /*
554
+ * A dialog opened over another is glass too: without its own blur the text of
555
+ * the dialog below read straight through the fill. Its scrim stays unblurred
556
+ * (.lp-scrim--nested), so the only blur is the panel's, and the fill is a
557
+ * little denser than the first layer's, since what it blurs is glass already.
558
+ */
540
559
  .lp-glass-overlay--nested {
541
- background-color: color-mix(in srgb, var(--color-surface-raised) 88%, transparent);
542
- background-image: none;
543
- -webkit-backdrop-filter: none;
544
- backdrop-filter: none;
560
+ --glass-overlay-fill: 62%;
545
561
  }
546
562
 
547
563
  :root[data-lp-no-backdrop] .lp-glass-overlay {
@@ -551,6 +567,39 @@
551
567
  backdrop-filter: none;
552
568
  }
553
569
 
570
+ /*
571
+ * The same glass where the blur does not composite but the app said what lies
572
+ * behind it (setGlassBackdrop): a blurred copy of that wallpaper, aligned to
573
+ * the viewport by the panel's offset, sits under a fill a little denser than
574
+ * the real glass, since only the wallpaper and not the page is softened.
575
+ */
576
+ :root[data-lp-no-backdrop][data-lp-glass-backdrop] .lp-glass-overlay {
577
+ background: none;
578
+ isolation: isolate;
579
+ overflow: clip;
580
+ }
581
+
582
+ :root[data-lp-no-backdrop][data-lp-glass-backdrop] .lp-glass-overlay::before {
583
+ content: "";
584
+ position: absolute;
585
+ z-index: -1;
586
+ left: calc(-1 * var(--lp-gx, 0px));
587
+ top: calc(-1 * var(--lp-gy, 0px));
588
+ width: 100vw;
589
+ height: 100vh;
590
+ /* The tint rides in the same layer: a negative z-index child paints over
591
+ its stacking context's own background, so a fill on the panel would sit
592
+ under the wallpaper and vanish. */
593
+ background:
594
+ linear-gradient(
595
+ color-mix(in srgb, var(--color-surface-raised) var(--glass-overlay-fallback-fill, 62%), transparent),
596
+ color-mix(in srgb, var(--color-surface-raised) var(--glass-overlay-fallback-fill, 62%), transparent)
597
+ ),
598
+ var(--lp-glass-backdrop);
599
+ filter: var(--lp-glass-backdrop-filter, blur(var(--glass-overlay-blur, 28px)) saturate(170%));
600
+ pointer-events: none;
601
+ }
602
+
554
603
  /* The overlay gradient rides above the base fill but under the content. */
555
604
  .lp-skin-panel::before {
556
605
  content: "";