decantr 0.9.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 (382) hide show
  1. package/AGENTS.md +868 -0
  2. package/CHANGELOG.md +255 -0
  3. package/CLAUDE.md +178 -0
  4. package/LICENSE +21 -0
  5. package/README.md +229 -0
  6. package/cli/art.js +127 -0
  7. package/cli/commands/a11y.js +61 -0
  8. package/cli/commands/audit.js +225 -0
  9. package/cli/commands/build.js +38 -0
  10. package/cli/commands/dev.js +18 -0
  11. package/cli/commands/doctor.js +197 -0
  12. package/cli/commands/figma-sync.js +48 -0
  13. package/cli/commands/figma-tokens.js +55 -0
  14. package/cli/commands/generate.js +26 -0
  15. package/cli/commands/init.js +116 -0
  16. package/cli/commands/lint.js +209 -0
  17. package/cli/commands/mcp.js +530 -0
  18. package/cli/commands/migrate.js +175 -0
  19. package/cli/commands/test.js +38 -0
  20. package/cli/commands/validate.js +354 -0
  21. package/cli/index.js +113 -0
  22. package/package.json +95 -0
  23. package/reference/atoms.md +517 -0
  24. package/reference/behaviors.md +384 -0
  25. package/reference/build-tooling.md +275 -0
  26. package/reference/color-guidelines.md +965 -0
  27. package/reference/component-lifecycle.md +137 -0
  28. package/reference/compound-spacing.md +95 -0
  29. package/reference/decantation-process.md +499 -0
  30. package/reference/dev-server-routes.md +93 -0
  31. package/reference/form-system.md +253 -0
  32. package/reference/i18n.md +336 -0
  33. package/reference/icons.md +576 -0
  34. package/reference/llm-primer.md +953 -0
  35. package/reference/plugins.md +252 -0
  36. package/reference/registry-consumption.md +76 -0
  37. package/reference/router.md +217 -0
  38. package/reference/shells.md +116 -0
  39. package/reference/spatial-guidelines.md +541 -0
  40. package/reference/ssr.md +234 -0
  41. package/reference/state-data.md +215 -0
  42. package/reference/state-patterns.md +166 -0
  43. package/reference/state.md +194 -0
  44. package/reference/style-system.md +110 -0
  45. package/reference/tokens.md +460 -0
  46. package/src/app.js +19 -0
  47. package/src/chart/_animate.js +266 -0
  48. package/src/chart/_base.js +109 -0
  49. package/src/chart/_data.js +209 -0
  50. package/src/chart/_format.js +106 -0
  51. package/src/chart/_interact.js +364 -0
  52. package/src/chart/_palette.js +105 -0
  53. package/src/chart/_renderer.js +52 -0
  54. package/src/chart/_scene.js +262 -0
  55. package/src/chart/_shared.js +371 -0
  56. package/src/chart/index.js +637 -0
  57. package/src/chart/layouts/_layout-base.js +328 -0
  58. package/src/chart/layouts/cartesian.js +148 -0
  59. package/src/chart/layouts/hierarchy.js +562 -0
  60. package/src/chart/layouts/polar.js +101 -0
  61. package/src/chart/renderers/canvas.js +179 -0
  62. package/src/chart/renderers/svg.js +256 -0
  63. package/src/chart/renderers/webgpu.js +715 -0
  64. package/src/chart/types/_type-base.js +26 -0
  65. package/src/chart/types/area.js +134 -0
  66. package/src/chart/types/bar.js +173 -0
  67. package/src/chart/types/box-plot.js +125 -0
  68. package/src/chart/types/bubble.js +63 -0
  69. package/src/chart/types/candlestick.js +115 -0
  70. package/src/chart/types/chord.js +85 -0
  71. package/src/chart/types/combination.js +108 -0
  72. package/src/chart/types/funnel.js +68 -0
  73. package/src/chart/types/gauge.js +163 -0
  74. package/src/chart/types/heatmap.js +98 -0
  75. package/src/chart/types/histogram.js +71 -0
  76. package/src/chart/types/line.js +111 -0
  77. package/src/chart/types/org-chart.js +93 -0
  78. package/src/chart/types/pie.js +81 -0
  79. package/src/chart/types/radar.js +96 -0
  80. package/src/chart/types/radial.js +68 -0
  81. package/src/chart/types/range-area.js +55 -0
  82. package/src/chart/types/range-bar.js +61 -0
  83. package/src/chart/types/sankey.js +73 -0
  84. package/src/chart/types/scatter.js +66 -0
  85. package/src/chart/types/sparkline.js +81 -0
  86. package/src/chart/types/sunburst.js +69 -0
  87. package/src/chart/types/swimlane.js +88 -0
  88. package/src/chart/types/treemap.js +62 -0
  89. package/src/chart/types/waterfall.js +100 -0
  90. package/src/components/_base.js +1658 -0
  91. package/src/components/_behaviors.js +1140 -0
  92. package/src/components/_primitives.js +534 -0
  93. package/src/components/_qr-encoder.js +539 -0
  94. package/src/components/accordion.js +207 -0
  95. package/src/components/affix.js +62 -0
  96. package/src/components/alert-dialog.js +75 -0
  97. package/src/components/alert.js +47 -0
  98. package/src/components/aspect-ratio.js +24 -0
  99. package/src/components/avatar-group.js +55 -0
  100. package/src/components/avatar.js +38 -0
  101. package/src/components/back-top.js +75 -0
  102. package/src/components/badge.js +74 -0
  103. package/src/components/banner.js +68 -0
  104. package/src/components/breadcrumb.js +162 -0
  105. package/src/components/button.js +115 -0
  106. package/src/components/calendar.js +131 -0
  107. package/src/components/card.js +192 -0
  108. package/src/components/carousel.js +98 -0
  109. package/src/components/cascader.js +261 -0
  110. package/src/components/checkbox.js +80 -0
  111. package/src/components/chip.js +81 -0
  112. package/src/components/code-block.js +82 -0
  113. package/src/components/collapsible.js +50 -0
  114. package/src/components/color-palette.js +438 -0
  115. package/src/components/color-picker.js +314 -0
  116. package/src/components/combobox.js +181 -0
  117. package/src/components/command.js +174 -0
  118. package/src/components/comment.js +206 -0
  119. package/src/components/context-menu.js +76 -0
  120. package/src/components/data-table.js +724 -0
  121. package/src/components/date-picker.js +217 -0
  122. package/src/components/date-range-picker.js +244 -0
  123. package/src/components/datetime-picker.js +271 -0
  124. package/src/components/descriptions.js +68 -0
  125. package/src/components/drawer.js +179 -0
  126. package/src/components/dropdown.js +88 -0
  127. package/src/components/empty.js +41 -0
  128. package/src/components/float-button.js +90 -0
  129. package/src/components/form.js +106 -0
  130. package/src/components/hover-card.js +49 -0
  131. package/src/components/icon.js +87 -0
  132. package/src/components/image.js +97 -0
  133. package/src/components/index.js +117 -0
  134. package/src/components/input-group.js +75 -0
  135. package/src/components/input-number.js +155 -0
  136. package/src/components/input-otp.js +178 -0
  137. package/src/components/input.js +91 -0
  138. package/src/components/kbd.js +36 -0
  139. package/src/components/label.js +25 -0
  140. package/src/components/list.js +118 -0
  141. package/src/components/masked-input.js +236 -0
  142. package/src/components/mentions.js +165 -0
  143. package/src/components/menu.js +259 -0
  144. package/src/components/message.js +80 -0
  145. package/src/components/modal.js +147 -0
  146. package/src/components/navigation-menu.js +166 -0
  147. package/src/components/notification.js +84 -0
  148. package/src/components/pagination.js +104 -0
  149. package/src/components/placeholder.js +132 -0
  150. package/src/components/popconfirm.js +70 -0
  151. package/src/components/popover.js +58 -0
  152. package/src/components/progress.js +61 -0
  153. package/src/components/qrcode.js +251 -0
  154. package/src/components/radiogroup.js +120 -0
  155. package/src/components/range-slider.js +176 -0
  156. package/src/components/rate.js +186 -0
  157. package/src/components/resizable.js +83 -0
  158. package/src/components/result.js +57 -0
  159. package/src/components/scroll-area.js +43 -0
  160. package/src/components/segmented.js +97 -0
  161. package/src/components/select.js +165 -0
  162. package/src/components/separator.js +31 -0
  163. package/src/components/shell.js +407 -0
  164. package/src/components/skeleton.js +39 -0
  165. package/src/components/slider.js +141 -0
  166. package/src/components/sortable-list.js +176 -0
  167. package/src/components/space.js +42 -0
  168. package/src/components/spinner.js +112 -0
  169. package/src/components/splitter.js +147 -0
  170. package/src/components/statistic.js +136 -0
  171. package/src/components/steps.js +99 -0
  172. package/src/components/switch.js +95 -0
  173. package/src/components/table.js +44 -0
  174. package/src/components/tabs.js +216 -0
  175. package/src/components/tag.js +115 -0
  176. package/src/components/textarea.js +82 -0
  177. package/src/components/time-picker.js +153 -0
  178. package/src/components/time-range-picker.js +170 -0
  179. package/src/components/timeline.js +226 -0
  180. package/src/components/toast.js +71 -0
  181. package/src/components/toggle.js +213 -0
  182. package/src/components/tooltip.js +57 -0
  183. package/src/components/tour.js +159 -0
  184. package/src/components/transfer.js +163 -0
  185. package/src/components/tree-select.js +274 -0
  186. package/src/components/tree.js +141 -0
  187. package/src/components/typography.js +136 -0
  188. package/src/components/upload.js +118 -0
  189. package/src/components/visually-hidden.js +20 -0
  190. package/src/components/watermark.js +124 -0
  191. package/src/core/index.js +539 -0
  192. package/src/core/lifecycle.js +69 -0
  193. package/src/css/atoms.js +651 -0
  194. package/src/css/components.js +940 -0
  195. package/src/css/derive.js +1296 -0
  196. package/src/css/index.js +265 -0
  197. package/src/css/runtime.js +268 -0
  198. package/src/css/styles/addons/bioluminescent.js +93 -0
  199. package/src/css/styles/addons/clay.js +70 -0
  200. package/src/css/styles/addons/clean.js +57 -0
  201. package/src/css/styles/addons/command-center.js +143 -0
  202. package/src/css/styles/addons/dopamine.js +83 -0
  203. package/src/css/styles/addons/editorial.js +80 -0
  204. package/src/css/styles/addons/glassmorphism.js +99 -0
  205. package/src/css/styles/addons/liquid-glass.js +105 -0
  206. package/src/css/styles/addons/prismatic.js +100 -0
  207. package/src/css/styles/addons/retro.js +63 -0
  208. package/src/css/styles/auradecantism.js +96 -0
  209. package/src/css/theme-registry.js +444 -0
  210. package/src/data/entity.js +281 -0
  211. package/src/data/index.js +13 -0
  212. package/src/data/persist.js +225 -0
  213. package/src/data/query.js +839 -0
  214. package/src/data/realtime.js +299 -0
  215. package/src/data/url.js +177 -0
  216. package/src/data/worker.js +134 -0
  217. package/src/explorer/archetypes.js +243 -0
  218. package/src/explorer/atoms.js +228 -0
  219. package/src/explorer/charts.js +497 -0
  220. package/src/explorer/components.js +129 -0
  221. package/src/explorer/foundations.js +949 -0
  222. package/src/explorer/icons.js +178 -0
  223. package/src/explorer/patterns.js +247 -0
  224. package/src/explorer/recipes.js +194 -0
  225. package/src/explorer/shared/pattern-examples.js +1337 -0
  226. package/src/explorer/shared/showcase-renderer.js +958 -0
  227. package/src/explorer/shared/spec-table.js +41 -0
  228. package/src/explorer/shared/usage-links.js +87 -0
  229. package/src/explorer/shell-config.js +10 -0
  230. package/src/explorer/shells.js +551 -0
  231. package/src/explorer/styles.js +161 -0
  232. package/src/explorer/tokens.js +262 -0
  233. package/src/explorer/tools.js +525 -0
  234. package/src/form/index.js +804 -0
  235. package/src/i18n/index.js +251 -0
  236. package/src/icons/essential.js +479 -0
  237. package/src/icons/index.js +53 -0
  238. package/src/plugins/index.js +282 -0
  239. package/src/registry/archetypes/content-site.json +71 -0
  240. package/src/registry/archetypes/docs-explorer.json +23 -0
  241. package/src/registry/archetypes/ecommerce.json +104 -0
  242. package/src/registry/archetypes/financial-dashboard.json +77 -0
  243. package/src/registry/archetypes/index.json +41 -0
  244. package/src/registry/archetypes/portfolio.json +82 -0
  245. package/src/registry/archetypes/recipe-community.json +159 -0
  246. package/src/registry/archetypes/saas-dashboard.json +86 -0
  247. package/src/registry/architect/cross-cutting.json +45 -0
  248. package/src/registry/architect/domains/ecommerce.json +294 -0
  249. package/src/registry/architect/domains/financial-services.json +302 -0
  250. package/src/registry/architect/index.json +26 -0
  251. package/src/registry/architect/traits.json +379 -0
  252. package/src/registry/atoms.json +16 -0
  253. package/src/registry/chart-showcase.json +160 -0
  254. package/src/registry/chart.json +136 -0
  255. package/src/registry/components.json +8616 -0
  256. package/src/registry/core.json +216 -0
  257. package/src/registry/css.json +319 -0
  258. package/src/registry/data.json +135 -0
  259. package/src/registry/foundations.json +11 -0
  260. package/src/registry/icons.json +463 -0
  261. package/src/registry/index.json +101 -0
  262. package/src/registry/patterns/activity-feed.json +37 -0
  263. package/src/registry/patterns/article-content.json +27 -0
  264. package/src/registry/patterns/auth-form.json +37 -0
  265. package/src/registry/patterns/author-card.json +20 -0
  266. package/src/registry/patterns/card-grid.json +127 -0
  267. package/src/registry/patterns/category-nav.json +26 -0
  268. package/src/registry/patterns/chart-grid.json +36 -0
  269. package/src/registry/patterns/chat-interface.json +37 -0
  270. package/src/registry/patterns/checklist-card.json +55 -0
  271. package/src/registry/patterns/comparison-panel.json +27 -0
  272. package/src/registry/patterns/component-showcase.json +24 -0
  273. package/src/registry/patterns/contact-form.json +31 -0
  274. package/src/registry/patterns/cta-section.json +20 -0
  275. package/src/registry/patterns/data-table.json +37 -0
  276. package/src/registry/patterns/detail-header.json +83 -0
  277. package/src/registry/patterns/detail-panel.json +27 -0
  278. package/src/registry/patterns/explorer-shell.json +22 -0
  279. package/src/registry/patterns/filter-bar.json +33 -0
  280. package/src/registry/patterns/filter-sidebar.json +27 -0
  281. package/src/registry/patterns/form-sections.json +110 -0
  282. package/src/registry/patterns/goal-tracker.json +27 -0
  283. package/src/registry/patterns/hero.json +107 -0
  284. package/src/registry/patterns/index.json +47 -0
  285. package/src/registry/patterns/kpi-grid.json +36 -0
  286. package/src/registry/patterns/media-gallery.json +20 -0
  287. package/src/registry/patterns/order-history.json +20 -0
  288. package/src/registry/patterns/pagination.json +19 -0
  289. package/src/registry/patterns/photo-to-recipe.json +36 -0
  290. package/src/registry/patterns/pipeline-tracker.json +28 -0
  291. package/src/registry/patterns/post-list.json +27 -0
  292. package/src/registry/patterns/pricing-table.json +32 -0
  293. package/src/registry/patterns/scorecard.json +28 -0
  294. package/src/registry/patterns/search-bar.json +20 -0
  295. package/src/registry/patterns/specimen-grid.json +19 -0
  296. package/src/registry/patterns/stat-card.json +55 -0
  297. package/src/registry/patterns/stats-bar.json +55 -0
  298. package/src/registry/patterns/steps-card.json +55 -0
  299. package/src/registry/patterns/table-of-contents.json +19 -0
  300. package/src/registry/patterns/testimonials.json +21 -0
  301. package/src/registry/patterns/timeline.json +27 -0
  302. package/src/registry/patterns/token-inspector.json +21 -0
  303. package/src/registry/patterns/wizard.json +27 -0
  304. package/src/registry/recipe-auradecantism.json +69 -0
  305. package/src/registry/recipe-clean.json +65 -0
  306. package/src/registry/recipe-command-center.json +78 -0
  307. package/src/registry/router.json +73 -0
  308. package/src/registry/schema/README.md +197 -0
  309. package/src/registry/skeletons.json +259 -0
  310. package/src/registry/state.json +137 -0
  311. package/src/registry/tokens.json +40 -0
  312. package/src/router/hash.js +17 -0
  313. package/src/router/history.js +18 -0
  314. package/src/router/index.js +598 -0
  315. package/src/ssr/index.js +922 -0
  316. package/src/state/arrays.js +181 -0
  317. package/src/state/devtools.js +647 -0
  318. package/src/state/index.js +498 -0
  319. package/src/state/middleware.js +288 -0
  320. package/src/state/scheduler.js +206 -0
  321. package/src/state/store.js +300 -0
  322. package/src/tags/index.js +19 -0
  323. package/src/tannins/auth.js +396 -0
  324. package/src/test/dom.js +352 -0
  325. package/src/test/index.js +62 -0
  326. package/src/test/state.js +306 -0
  327. package/tools/a11y-audit.js +487 -0
  328. package/tools/analyzer.js +315 -0
  329. package/tools/audit.js +706 -0
  330. package/tools/builder.js +1422 -0
  331. package/tools/css-extract.js +188 -0
  332. package/tools/dev-server.js +316 -0
  333. package/tools/dts-gen.js +1260 -0
  334. package/tools/figma-components.js +329 -0
  335. package/tools/figma-patterns.js +516 -0
  336. package/tools/figma-plugin/code.js +453 -0
  337. package/tools/figma-plugin/manifest.json +14 -0
  338. package/tools/figma-plugin/ui.html +268 -0
  339. package/tools/figma-render.js +293 -0
  340. package/tools/figma-tokens.js +712 -0
  341. package/tools/figma-upload.js +318 -0
  342. package/tools/generate.js +738 -0
  343. package/tools/icons.js +133 -0
  344. package/tools/init-templates.js +265 -0
  345. package/tools/install-hooks.sh +5 -0
  346. package/tools/migrations/0.5.0.js +53 -0
  347. package/tools/migrations/0.6.0.js +95 -0
  348. package/tools/minify.js +170 -0
  349. package/tools/pre-commit +4 -0
  350. package/tools/registry.js +662 -0
  351. package/tools/reset-playground.js +61 -0
  352. package/tools/starter-templates/content-site/app.js +49 -0
  353. package/tools/starter-templates/content-site/essence.js +19 -0
  354. package/tools/starter-templates/content-site/pages.js +31 -0
  355. package/tools/starter-templates/ecommerce/app.js +50 -0
  356. package/tools/starter-templates/ecommerce/essence.js +19 -0
  357. package/tools/starter-templates/ecommerce/pages.js +31 -0
  358. package/tools/starter-templates/landing-page/app.js +38 -0
  359. package/tools/starter-templates/landing-page/essence.js +18 -0
  360. package/tools/starter-templates/landing-page/pages.js +21 -0
  361. package/tools/starter-templates/portfolio/app.js +45 -0
  362. package/tools/starter-templates/portfolio/essence.js +19 -0
  363. package/tools/starter-templates/portfolio/pages.js +33 -0
  364. package/tools/starter-templates/saas-dashboard/app.js +70 -0
  365. package/tools/starter-templates/saas-dashboard/essence.js +19 -0
  366. package/tools/starter-templates/saas-dashboard/pages.js +31 -0
  367. package/tools/verify-pack.js +203 -0
  368. package/types/chart.d.ts +77 -0
  369. package/types/components.d.ts +587 -0
  370. package/types/core.d.ts +89 -0
  371. package/types/css.d.ts +149 -0
  372. package/types/data.d.ts +238 -0
  373. package/types/form.d.ts +164 -0
  374. package/types/i18n.d.ts +51 -0
  375. package/types/icons.d.ts +27 -0
  376. package/types/index.d.ts +13 -0
  377. package/types/router.d.ts +116 -0
  378. package/types/ssr.d.ts +102 -0
  379. package/types/state.d.ts +83 -0
  380. package/types/tags.d.ts +62 -0
  381. package/types/tannins.d.ts +63 -0
  382. package/types/test.d.ts +48 -0
@@ -0,0 +1,576 @@
1
+ # Icon System Reference
2
+
3
+ Decantr's icon system renders 375 essential stroke-based SVG icons as CSS-masked `<span>` elements. Icons inherit `currentColor`, inject CSS once per name, and tree-shake unused paths at build time.
4
+
5
+ ## Rendering Pipeline
6
+
7
+ ```
8
+ essential.js → getIconPath(name) → icon(name, opts)
9
+
10
+ buildDataUri(inner, weight, filled)
11
+
12
+ injectIconCSS(name, inner, weight, filled)
13
+
14
+ <span class="d-i d-i-{variantKey}">
15
+ ```
16
+
17
+ All icons use a 24×24 viewBox, `stroke-linecap="round"`, `stroke-linejoin="round"`. Default: `stroke-width="2"`, `fill="none"`. Weight and fill options parameterize the SVG wrapper. The `<span>` uses `mask-image` with a data URI — color comes from `currentColor` via the parent's `color` property. Each icon variant is injected into a shared `<style data-decantr-icons>` element exactly once (keyed by name + weight + filled).
18
+
19
+ ---
20
+
21
+ ## Core API
22
+
23
+ ### `icon(name, opts?)` — `decantr/components`
24
+
25
+ Render an icon as a `<span>` element.
26
+
27
+ | Param | Type | Default | Description |
28
+ |-------|------|---------|-------------|
29
+ | `name` | `string` | — | Icon name in kebab-case (e.g. `'check'`, `'chevron-down'`) |
30
+ | `opts.size` | `string\|number` | `'1.25em'` | CSS width and height |
31
+ | `opts.weight` | `string\|number` | `'regular'` | Stroke weight (see Weight table below) |
32
+ | `opts.filled` | `boolean` | `false` | Fill closed shapes |
33
+ | `opts.class` | `string` | — | Additional CSS classes |
34
+ | `...rest` | — | — | Spread to the `<span>` element |
35
+
36
+ **Returns:** `HTMLElement` with `class="d-i d-i-{name}"`, `role="img"`, `aria-hidden="true"`
37
+
38
+ ```javascript
39
+ import { icon } from 'decantr/components';
40
+
41
+ icon('check'); // default 1.25em, regular weight
42
+ icon('star', { size: '1em' }); // inline with text
43
+ icon('home', { size: '2rem' }); // large feature icon
44
+ icon('edit', { class: css('_fgprimary') }); // colored
45
+ icon('heart', { filled: true }); // solid heart
46
+ icon('star', { weight: 'bold', filled: true }); // bold + filled
47
+ icon('chevron-down', { weight: 'thin' }); // thin stroke
48
+ icon('circle', { weight: 1.5 }); // numeric weight
49
+ ```
50
+
51
+ #### Weight
52
+
53
+ Named or numeric, controls `stroke-width`. Numeric values clamped to `[0.5, 4]`.
54
+
55
+ | Name | stroke-width |
56
+ |------|-------------|
57
+ | `thin` | 1 |
58
+ | `light` | 1.5 |
59
+ | `regular` | 2 (default) |
60
+ | `medium` | 2.5 |
61
+ | `bold` | 3 |
62
+
63
+ Fill-based icons (auto-detected via `fill=` attribute) ignore weight.
64
+
65
+ #### Filled
66
+
67
+ Boolean, default `false`. Adds `fill='black'` alongside stroke attributes in the SVG wrapper. Closed shapes (paths, polygons, circles, rects) fill in; open elements (lines, polylines) remain unchanged. Fill-based icons ignore this option (already filled).
68
+
69
+ #### CSS Class Naming
70
+
71
+ Variants produce CSS class suffixes on `d-i-{name}`:
72
+
73
+ | Variant | CSS class example |
74
+ |---------|------------------|
75
+ | Default (regular, no fill) | `d-i-heart` |
76
+ | Weight only | `d-i-heart--w1` (thin), `d-i-heart--w1p5` (light) |
77
+ | Fill only | `d-i-heart--filled` |
78
+ | Weight + fill | `d-i-heart--w3-filled` (bold + filled) |
79
+
80
+ Decimals use `p` in class names: `1.5` → `w1p5`, `2.5` → `w2p5`.
81
+
82
+ ### Registry Functions — `decantr/icons`
83
+
84
+ | Function | Signature | Description |
85
+ |----------|-----------|-------------|
86
+ | `getIconPath` | `(name) → string\|null` | Get SVG inner content for an icon |
87
+ | `registerIcon` | `(name, svgInner)` | Register or override a single icon |
88
+ | `registerIcons` | `(map)` | Bulk-register from `{ name: svgInner }` object |
89
+ | `hasIcon` | `(name) → boolean` | Check if icon is available |
90
+ | `getIconNames` | `() → string[]` | List all available icon names |
91
+
92
+ ### `caret(direction?, opts?)` — `decantr/components` (via `_behaviors.js`)
93
+
94
+ Convenience wrapper for chevron icons used as dropdown/expand indicators.
95
+
96
+ | Param | Type | Default | Description |
97
+ |-------|------|---------|-------------|
98
+ | `direction` | `'down'\|'up'\|'left'\|'right'` | `'down'` | Chevron direction |
99
+ | `opts` | `object` | `{}` | Passed to `icon()` |
100
+
101
+ **Returns:** `icon('chevron-{direction}', { size: '1em', class: 'd-caret', ...opts })`
102
+
103
+ CSS classes `.d-caret` (transition on transform) and `.d-caret-open` (`rotate(180deg)`) handle open/close animation.
104
+
105
+ **Used by:** Accordion, Cascader, Combobox, DataTable, Menu, NavigationMenu, Select, TreeSelect
106
+
107
+ ---
108
+
109
+ ## Size Tiers
110
+
111
+ | Tier | Size | When to use |
112
+ |------|------|-------------|
113
+ | **inline** | `1em` | Inside text-bearing components — Button, Chip, Menu items, Steps, Pickers, carets. Scales with font size. |
114
+ | **default** | `1.25em` | Standalone icons, general purpose. The `icon()` default. |
115
+ | **feature** | `1.5em`–`24px` | Feature cards, settings panels, navigation highlights. |
116
+ | **hero** | `2.5rem`–`3rem` | Empty states, Result status icons, large visual anchors. |
117
+
118
+ **Rule:** Use `1em` when the icon sits beside text (it scales with the text). Use `1.25em`+ when the icon stands alone.
119
+
120
+ From `spatial-guidelines.md` §7:
121
+
122
+ | Context | Icon Size | Text Size | Icon-Text Gap |
123
+ |---------|-----------|-----------|---------------|
124
+ | Small (compact) | 16px | 12-14px | 4px (`_gap1`) |
125
+ | Default | 20-24px | 14-16px | 8px (`_gap2`) |
126
+ | Large | 24-32px | 16-20px | 8-12px (`_gap2`–`_gap3`) |
127
+
128
+ ---
129
+
130
+ ## Component Integration Map
131
+
132
+ Components that accept or render icons. Sizes listed are what the component renders internally.
133
+
134
+ | Component | Prop / Mechanism | Type | Rendered Size | Notes |
135
+ |-----------|-----------------|------|---------------|-------|
136
+ | **Button** | `iconLeft`, `iconRight` | `string\|Node` | `1em` | String auto-wrapped via `icon(name, {size:'1em'})` |
137
+ | **Chip** | child icon node | `Node` | `1em` | `.d-chip-icon` class applied |
138
+ | **Alert** | `icon` | `string\|Node` | component default | Severity icon auto-assigned if omitted |
139
+ | **Input** | `prefix`, `suffix` | `string\|Node` | parent font | Wrapped in `.d-input-prefix`/`.d-input-suffix` |
140
+ | **InputNumber** | `prefix`, `suffix` | `string\|Node` | parent font | Same as Input |
141
+ | **Select** | caret auto-rendered | — | `1em` | `caret('down')` for dropdown arrow |
142
+ | **Combobox** | caret auto-rendered | — | `1em` | `caret('down')` for dropdown arrow |
143
+ | **DatePicker** | calendar icon auto | — | `1em` | `icon('calendar', {size:'1em'})` |
144
+ | **TimePicker** | clock icon auto | — | `1em` | `icon('clock', {size:'1em'})` |
145
+ | **Accordion** | caret auto-rendered | — | `1em` | `caret('down')`, rotates on open |
146
+ | **Menu** | caret on submenus | — | `1em` | `caret('right')` for nested items |
147
+ | **NavigationMenu** | caret auto-rendered | — | `1em` | `caret('down')` for dropdown triggers |
148
+ | **Dropdown** | item `icon` | `string\|Node` | `1em` | `.d-dropdown-item-icon` class |
149
+ | **ContextMenu** | item `icon` | `string\|Node` | `1em` | Same as Dropdown |
150
+ | **DataTable** | sort/expand carets | — | `1em` | Auto-rendered sort indicators and row expand |
151
+ | **Cascader** | caret auto-rendered | — | `1em` | `caret('right')` for navigation |
152
+ | **TreeSelect** | expand caret | — | `0.875em` | Smaller for nested tree items |
153
+ | **Segmented** | item `icon` | `string\|Node` | `1em` | Optional icon per segment |
154
+ | **Steps** | status icons auto | — | component default | Auto check/x for completed/error steps |
155
+ | **Timeline** | `dot` content | `Node` | varies | Custom icon in timeline dot |
156
+ | **BackTop** | arrow-up auto | — | `1.25em` | `icon('arrow-up')` default |
157
+ | **Statistic** | `prefix`, `suffix` | `string\|Node` | parent font | Visual prefix/suffix for numeric value |
158
+ | **Spinner** | loader icon | — | varies | Integrated icon animation |
159
+ | **Badge** | `icon` | `string\|Node` | component default | Optional icon in badge |
160
+
161
+ ---
162
+
163
+ ## Essential Icon Catalog
164
+
165
+ 375 icons organized by semantic category. Canonical machine-readable source: `src/registry/icons.json`.
166
+
167
+ ### Navigation (15)
168
+ `check`, `x`, `plus`, `minus`, `chevron-down`, `chevron-up`, `chevron-left`, `chevron-right`, `chevrons-left`, `chevrons-right`, `arrow-left`, `arrow-right`, `arrow-up`, `arrow-down`, `navigation`
169
+
170
+ Directional control, confirmation/dismissal, expand/collapse. The backbone of interactive UI.
171
+
172
+ ### Common UI (22)
173
+ `search`, `menu`, `more-horizontal`, `more-vertical`, `external-link`, `home`, `bell`, `settings`, `star`, `edit`, `trash`, `copy`, `eye`, `eye-off`, `filter`, `download`, `upload`, `refresh`, `loader`, `log-out`, `log-in`, `user`
174
+
175
+ General-purpose actions and indicators used across all domain archetypes.
176
+
177
+ ### Feedback (9)
178
+ `info`, `alert-triangle`, `alert-circle`, `check-circle`, `x-circle`, `circle-dot`, `flag`, `ban`, `alarm`
179
+
180
+ Status communication. Map directly to Alert/Notification severity variants: `info` → info, `alert-triangle` → warning, `alert-circle` → error, `check-circle` → success, `x-circle` → error/destructive.
181
+
182
+ ### Time & Scheduling (11)
183
+ `clock`, `timer`, `hourglass`, `alarm-clock`, `watch`, `watch-smart`, `history`, `calendar`, `calendar-check`, `calendar-plus`, `calendar-x`
184
+
185
+ All scheduling, reminders, deadlines, and time-tracking contexts.
186
+
187
+ ### Layout / Data (9)
188
+ `layout-dashboard`, `mail`, `image`, `file`, `folder`, `grip-vertical`, `move`, `blocks`
189
+
190
+ Content type indicators and drag handles. Dashboard and file management contexts.
191
+
192
+ ### People & Security (19)
193
+ `user`, `users`, `user-plus`, `user-minus`, `user-check`, `user-x`, `users-round`, `shield`, `shield-check`, `shield-x`, `shield-alert`, `lock`, `lock-keyhole`, `unlock`, `key`, `fingerprint`, `eye-scan`, `id-card`, `passport`
194
+
195
+ Authentication, authorization, team management, and identity verification.
196
+
197
+ ### Documents & Data (29)
198
+ `file-text`, `file-plus`, `file-minus`, `file-check`, `file-x`, `file-search`, `file-code`, `file-spreadsheet`, `file-image`, `file-audio`, `file-video`, `files`, `folder-open`, `folder-plus`, `folder-check`, `save`, `printer`, `bookmark`, `bookmark-plus`, `archive`, `clipboard`, `paperclip`, `link`, `unlink`, `hash`, `tag`, `notebook`, `contract`, `invoice`
199
+
200
+ Document actions, file types, and metadata. Content management and file operations.
201
+
202
+ ### Communication (29)
203
+ `phone`, `video`, `send`, `at-sign`, `at`, `message-square`, `message-circle`, `reply`, `rss`, `podcast`, `microphone`, `microphone-off`, `headphones`, `megaphone`, `newspaper`, `radio`, `tv`, `cast`, `heart`, `heart-crack`, `thumbs-up`, `thumbs-down`, `smile`, `frown`, `meh`, `laugh`, `angry`, `award`
204
+
205
+ Messaging, social engagement, media, and broadcasting.
206
+
207
+ ### Charts & Analytics (6)
208
+ `bar-chart`, `pie-chart`, `trending-up`, `trending-down`, `activity`, `percent`
209
+
210
+ Data visualization indicators. Use `trending-up`/`trending-down` for KPI trend arrows.
211
+
212
+ ### Organization (8)
213
+ `list`, `list-ordered`, `grid-3x3`, `inbox`, `layers`, `kanban`, `columns`, `rows`
214
+
215
+ View modes, sorting, and organizational structures.
216
+
217
+ ### Navigation & Layout (7)
218
+ `sidebar`, `panel-left`, `panel-right`, `maximize`, `minimize`, `expand`, `shrink`
219
+
220
+ Window and panel management. Dashboard and editor layouts.
221
+
222
+ ### Dev & Infrastructure (13)
223
+ `code`, `terminal`, `server`, `database`, `moon`, `sun`, `cloud`, `cloud-upload`, `cloud-download`, `cloud-cog`, `wifi`, `wifi-off`, `bug`
224
+
225
+ Developer tools, infrastructure status, and mode toggles. `moon`/`sun` are the canonical dark/light mode toggle icons.
226
+
227
+ ### Business & Finance (14)
228
+ `calculator`, `bank`, `coins`, `piggy-bank`, `invoice`, `contract`, `signature`, `stamp`, `briefcase`, `handshake`, `scale`, `target`, `crown`, `lighthouse`
229
+
230
+ Banking, contracts, professional tools, and financial contexts.
231
+
232
+ ### Commerce (22)
233
+ `credit-card`, `shopping-cart`, `shopping-bag`, `store`, `wallet`, `dollar-sign`, `receipt`, `gift`, `coupon`, `barcode`, `qr-code`, `price-tag`, `percent-circle`, `shipping`, `returns`, `truck`, `package`, `box`, `boxes`, `container`, `pallet`, `forklift`
234
+
235
+ Shopping, payments, and logistics.
236
+
237
+ ### Media & Creative (16)
238
+ `camera`, `camera-off`, `film`, `palette`, `brush`, `pen-tool`, `eyedropper`, `crop`, `type`, `align-left`, `align-center`, `align-right`, `align-justify`, `sparkles`, `wand`, `eraser`
239
+
240
+ Photography, design tools, and text formatting.
241
+
242
+ ### Devices & Technology (13)
243
+ `smartphone`, `tablet`, `laptop`, `monitor`, `bluetooth`, `usb`, `battery`, `battery-charging`, `battery-low`, `signal`, `satellite`, `robot`, `chip`
244
+
245
+ Hardware, connectivity, and device types.
246
+
247
+ ### Workflow & Development (12)
248
+ `git-branch`, `git-merge`, `git-pull-request`, `git-commit`, `milestone`, `workflow`, `variable`, `regex`, `binary`, `webhook`, `api`, `container-ship`
249
+
250
+ Version control, CI/CD, and project management tools.
251
+
252
+ ### Healthcare & Wellness (12)
253
+ `stethoscope`, `pill`, `syringe`, `heart-pulse`, `bandage`, `thermometer`, `brain`, `dna`, `accessibility`, `baby`, `apple`, `dumbbell`
254
+
255
+ Medical, wellness, fitness, and accessibility contexts.
256
+
257
+ ### Education & Learning (10)
258
+ `book`, `book-open`, `graduation-cap`, `notebook`, `presentation`, `trophy`, `medal`, `school`, `lightbulb`, `puzzle`
259
+
260
+ Learning, achievements, and educational institutions.
261
+
262
+ ### Transportation & Travel (11)
263
+ `car`, `bus`, `train`, `bicycle`, `ship`, `rocket`, `helicopter`, `taxi`, `parking`, `fuel`, `map-compass`
264
+
265
+ Vehicles, travel, and logistics.
266
+
267
+ ### Food & Hospitality (8)
268
+ `utensils`, `coffee`, `wine`, `pizza`, `cake`, `chef-hat`, `grape`, `wheat`
269
+
270
+ Dining, beverages, and culinary contexts.
271
+
272
+ ### Home & Real Estate (10)
273
+ `house`, `apartment`, `sofa`, `lamp`, `bed`, `bath`, `garden`, `door-closed`, `window`, `air-conditioning`
274
+
275
+ Furniture, property, and living spaces.
276
+
277
+ ### Weather & Environment (9)
278
+ `umbrella`, `wind`, `droplet`, `snowflake`, `sunrise`, `sunset`, `leaf`, `tree`, `mountain`
279
+
280
+ Climate, nature, and environmental contexts.
281
+
282
+ ### Actions (11)
283
+ `undo`, `redo`, `share`, `share-2`, `rotate-cw`, `rotate-ccw`, `scissors`, `zap`, `scan`, `pencil`, `pen`
284
+
285
+ Editing operations and quick actions.
286
+
287
+ ### Maps & Location (2)
288
+ `globe`, `map-pin`
289
+
290
+ Geographic and internationalization contexts.
291
+
292
+ ### Places (17)
293
+ `building`, `building-2`, `hospital`, `factory`, `warehouse`, `landmark`, `door-open`, `garage`, `fence`, `construction`, `anchor`, `plane`, `map`, `compass`, `route`, `cctv`
294
+
295
+ Physical locations and facility management.
296
+
297
+ ### Tools & Config (14)
298
+ `wrench`, `tool`, `hammer`, `screwdriver`, `nut`, `plug`, `cog`, `sliders-horizontal`, `gauge`, `toggle-left`, `toggle-right`, `power`, `cpu`, `hard-drive`
299
+
300
+ Settings, configuration, and system administration.
301
+
302
+ ### Tables & Data Grids (15)
303
+ `table`, `table-rows`, `table-columns`, `table-cells`, `layout-grid`, `sort-asc`, `sort-desc`, `arrow-up-down`, `filter-x`, `group`, `ungroup`, `spreadsheet`, `pivot-table`
304
+
305
+ DataTable controls and view configuration. Sort/filter/group affordances.
306
+
307
+ ### Shapes & Symbols (9)
308
+ `circle`, `square`, `triangle`, `diamond`, `hexagon`, `infinity`, `asterisk`, `hash-tag`, `parentheses`
309
+
310
+ Geometric shapes and common symbols for UI decoration, status, and categorization.
311
+
312
+ ---
313
+
314
+ ## Content Strategy: When to Use Icons
315
+
316
+ ### The Five Functions of Icons
317
+
318
+ | Function | What it communicates | Where it appears |
319
+ |----------|---------------------|-----------------|
320
+ | **Recognition** | Quick identification of action or object | Buttons, nav items, menus |
321
+ | **Scannability** | Visual anchors that break text monotony | KPI cards, feature lists, settings panels |
322
+ | **Affordance** | Signals interactivity or expandability | Dropdown carets, sort indicators, expandable sections |
323
+ | **Status** | Conveys state or feedback type | Alerts, results, step completion, trend indicators |
324
+ | **Density** | Communicates meaning in less space than text | Icon-only buttons, compact toolbars, data table controls |
325
+
326
+ ### Mandatory Icon Placement
327
+
328
+ Icons MUST appear in these contexts:
329
+
330
+ 1. **Navigation items** (sidebar, menu) — leading icon for scannability
331
+ 2. **Empty states** (Result, Empty) — visual focal point required
332
+ 3. **Feedback components** (Alert, Banner, Notification, toast) — severity before reading text
333
+ 4. **Form triggers** (DatePicker, TimePicker, search inputs) — affordance signal
334
+ 5. **Data table controls** (sort, filter, expand, pin) — primary affordance
335
+ 6. **Step indicators** — auto check/x plus domain-specific custom icons
336
+ 7. **KPI / Statistics** — trend arrows (`trending-up`/`trending-down`), category icons for dashboard anchoring
337
+
338
+ ### Recommended Icon Placement
339
+
340
+ Optional but improves visual integrity:
341
+
342
+ - **Button `iconLeft`** for primary CTAs — adds visual weight and recognition
343
+ - **Chip icons** for category disambiguation in tag clouds or filter bars
344
+ - **Menu/Dropdown item icons** for faster scanning in long lists
345
+ - **Card headers** with topic icons for visual grouping
346
+ - **Hero sections** with feature icon alongside headline
347
+
348
+ ### When NOT to Use Icons
349
+
350
+ - **Pure text content** — articles, documentation body, prose paragraphs
351
+ - **Purely decorative** — icon with no semantic value adds noise
352
+ - **Already icon-dense areas** — too many icons defeat scannability
353
+ - **Typography components** (Title, Text, Paragraph) — they carry their own visual weight
354
+
355
+ ---
356
+
357
+ ## Accessibility
358
+
359
+ - Icons render `role="img"` and `aria-hidden="true"` — decorative by default
360
+ - **Icon-only buttons:** place `aria-label` on the `<button>`, NOT the icon
361
+ ```javascript
362
+ Button({ 'aria-label': 'Delete', size: 'icon' }, icon('trash'))
363
+ ```
364
+ - Never use an icon as the sole conveyor of critical information without adjacent text
365
+ - Color alone is not sufficient — icons help distinguish Alert variants beyond color (e.g., `alert-triangle` for warning vs `info` for info)
366
+ - Icons are static; animated states use CSS transitions on containers (e.g., `.d-caret` → `.d-caret-open`)
367
+
368
+ ---
369
+
370
+ ## Custom Icons
371
+
372
+ ### Import workflow via `tools/icons.js`
373
+
374
+ ```bash
375
+ node tools/icons.js <svg-dir> [output.js]
376
+ ```
377
+
378
+ **SVG requirements:** 24×24 viewBox, stroke-based preferred (`fill="none"`, `stroke-width="2"`, `stroke-linecap="round"`, `stroke-linejoin="round"`).
379
+
380
+ | Command | Output |
381
+ |---------|--------|
382
+ | `node tools/icons.js ./my-icons` | `src/icons/custom.js` |
383
+ | `node tools/icons.js ./brand-icons brand.js` | `src/icons/brand.js` |
384
+ | `node tools/icons.js` (no args) | Regenerates `src/registry/icons.json` only |
385
+
386
+ **Generated module:**
387
+ ```javascript
388
+ // Generated by tools/icons.js — do not edit
389
+ export const ICONS = {
390
+ 'icon-name': '<path d="..."/>',
391
+ };
392
+ ```
393
+
394
+ **Registration in app code:**
395
+ ```javascript
396
+ import { ICONS } from './icons/custom.js';
397
+ import { registerIcons } from 'decantr/icons';
398
+ registerIcons(ICONS);
399
+ ```
400
+
401
+ ### Runtime registration
402
+
403
+ For icons loaded dynamically (e.g., from an API):
404
+
405
+ ```javascript
406
+ import { registerIcon, hasIcon } from 'decantr/icons';
407
+
408
+ if (!hasIcon('my-dynamic-icon')) {
409
+ registerIcon('my-dynamic-icon', '<path d="M12 2L22 22H2z"/>');
410
+ }
411
+ ```
412
+
413
+ Register custom icons before first render to avoid a flash of missing icons.
414
+
415
+ ---
416
+
417
+ ## Third-Party Icon Libraries
418
+
419
+ Decantr's `icon()` renders SVGs via CSS `mask-image`. Third-party libraries fall into two categories: SVG-based (compatible with `icon()`) and font/class-based (bypass `icon()` entirely). The LLM generating code already knows every library's conventions — Decantr provides the hooks, not the adapters.
420
+
421
+ ### Config Signal
422
+
423
+ Declare the project's icon library in `decantr.config.json`:
424
+
425
+ ```jsonc
426
+ {
427
+ "icons": {
428
+ "library": "material" // informational — tells LLM what conventions to use
429
+ }
430
+ }
431
+ ```
432
+
433
+ Decantr does not act on this value. It signals to the LLM which icon library's conventions to follow when generating code. Validated by `decantr validate` (warns on unrecognized libraries).
434
+
435
+ ### SVG Libraries (Lucide, Heroicons, Phosphor, Feather, Tabler)
436
+
437
+ These ship SVG data and work directly with `registerIcons()`.
438
+
439
+ **Stroke-based (Lucide, Feather, Heroicons Outline):**
440
+
441
+ ```javascript
442
+ import { registerIcons } from 'decantr/icons';
443
+ import lucideIcons from './icons/lucide-data.js'; // generated via tools/icons.js
444
+ registerIcons(lucideIcons);
445
+
446
+ // Then use normally
447
+ icon('search'); // renders Lucide's search icon
448
+ ```
449
+
450
+ **Fill-based (Heroicons Solid, Material SVGs, Phosphor Fill):**
451
+
452
+ `buildDataUri()` auto-detects fill-based SVGs. If the inner content contains a `fill=` attribute with a non-`none` value, it uses fill rendering (`fill='black' stroke='none'`). Otherwise it uses stroke rendering (default).
453
+
454
+ ```javascript
455
+ // Fill-based SVGs — auto-detected
456
+ registerIcon('home-solid', '<path fill="currentColor" d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"/>');
457
+
458
+ // SVGs with bare <path> (no fill attr) — add fill="currentColor" when registering
459
+ registerIcon('expand-more', '<path fill="currentColor" d="M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z"/>');
460
+ ```
461
+
462
+ **Import workflow:**
463
+
464
+ ```bash
465
+ node tools/icons.js ./lucide-svgs lucide.js # → src/icons/lucide.js
466
+ node tools/icons.js ./heroicons-solid solid.js # → src/icons/solid.js
467
+ ```
468
+
469
+ ### Font-Based Libraries (Google Material Icons, Font Awesome)
470
+
471
+ Font/class-based icon systems use a fundamentally different rendering model (`font-family` + ligatures or `::before` pseudo-elements). They bypass `icon()` entirely — the LLM generates native HTML.
472
+
473
+ **Google Material Icons:**
474
+
475
+ ```html
476
+ <!-- Load in index.html -->
477
+ <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
478
+ ```
479
+
480
+ ```javascript
481
+ // LLM generates native Material Icons markup
482
+ h('span', { class: 'material-icons', 'aria-hidden': 'true' }, 'home')
483
+ h('span', { class: 'material-icons', 'aria-hidden': 'true' }, 'search')
484
+ ```
485
+
486
+ **Font Awesome:**
487
+
488
+ ```html
489
+ <!-- Load in index.html -->
490
+ <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css" rel="stylesheet">
491
+ ```
492
+
493
+ ```javascript
494
+ // LLM generates native Font Awesome markup
495
+ h('i', { class: 'fa-solid fa-house', 'aria-hidden': 'true' })
496
+ h('i', { class: 'fa-solid fa-magnifying-glass', 'aria-hidden': 'true' })
497
+ ```
498
+
499
+ ### Structural Icon Overrides
500
+
501
+ Framework components (Select, Accordion, DataTable, Alert, etc.) use ~15 structural icons internally via `icon()`. These always work with the built-in essential set, regardless of what third-party library the project uses.
502
+
503
+ For visual consistency with an external SVG library, override the structural icons at app startup:
504
+
505
+ ```javascript
506
+ import { registerIcon } from 'decantr/icons';
507
+
508
+ // Override structural icons with Material Design SVGs
509
+ registerIcon('chevron-down', '<path fill="currentColor" d="M7 10l5 5 5-5z"/>');
510
+ registerIcon('chevron-up', '<path fill="currentColor" d="M7 14l5-5 5 5z"/>');
511
+ registerIcon('chevron-left', '<path fill="currentColor" d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"/>');
512
+ registerIcon('chevron-right', '<path fill="currentColor" d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/>');
513
+ registerIcon('check', '<path fill="currentColor" d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/>');
514
+ registerIcon('x', '<path fill="currentColor" d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/>');
515
+ registerIcon('calendar', '<path fill="currentColor" d="M19 3h-1V1h-2v2H8V1H6v2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11z"/>');
516
+ registerIcon('clock', '<path fill="currentColor" d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm.5-13H11v6l5.25 3.15.75-1.23-4.5-2.67z"/>');
517
+ registerIcon('search', '<path fill="currentColor" d="M15.5 14h-.79l-.28-.27A6.47 6.47 0 0016 9.5 6.5 6.5 0 109.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5z"/>');
518
+ // ... remaining structural icons as needed
519
+ ```
520
+
521
+ **Structural icon names (15 total):**
522
+
523
+ `chevron-down`, `chevron-up`, `chevron-left`, `chevron-right`, `check`, `x`, `calendar`, `clock`, `search`, `arrow-up`, `grip-vertical`, `info`, `check-circle`, `alert-triangle`, `x-circle`
524
+
525
+ Most SVG icon libraries ship downloadable SVGs alongside any font files — the LLM extracts the appropriate `<path>` data for these overrides.
526
+
527
+ ### Summary by Library Type
528
+
529
+ | Library Type | Examples | Integration | `icon()` used? |
530
+ |---|---|---|---|
531
+ | SVG stroke | Lucide, Feather, Heroicons Outline | `registerIcons()` | Yes |
532
+ | SVG fill | Heroicons Solid, Material SVGs, Phosphor Fill | `registerIcons()` (auto-detected) | Yes |
533
+ | Font ligature | Google Material Icons | Load font, native HTML | No — LLM generates `<span class="material-icons">` |
534
+ | CSS class | Font Awesome, Bootstrap Icons | Load CSS, native HTML | No — LLM generates `<i class="fa-solid fa-*">` |
535
+ | Custom SVGs | Company icon sets | `tools/icons.js` → `registerIcons()` | Yes |
536
+
537
+ ---
538
+
539
+ ## Build Optimization
540
+
541
+ Tree shaking scans bundled JS for `icon('name')` call patterns and prunes unused SVG path data from the output. Only referenced icons ship in the production bundle.
542
+
543
+ - Essential icons that are never referenced are stripped
544
+ - Custom icons registered via `registerIcons()` are included if the module is imported
545
+ - `hasIcon()` guard calls do not count as icon usage for tree shaking
546
+
547
+ ---
548
+
549
+ ## Icon-Text Spacing
550
+
551
+ Components handle icon-text gaps internally — do not add manual spacing gaps around icons rendered by components.
552
+
553
+ | Context | Gap Token | Value | Example |
554
+ |---------|-----------|-------|---------|
555
+ | Micro icon-text (label-adjacent) | `--d-sp-1` | 4px | Helper text icon, badge icon |
556
+ | Button icon-label | `--d-sp-2` | 8px | `Button({ iconLeft: 'plus' }, 'Add')` |
557
+ | Alert/Notification icon-body | `--d-sp-3` | 12px | Severity icon to message text |
558
+
559
+ For standalone icon-text pairs outside components, use `_gap1` (4px intimate) or `_gap2` (8px default). See `reference/spatial-guidelines.md` §3 Gestalt Proximity Rules.
560
+
561
+ ---
562
+
563
+ ## Quick Reference
564
+
565
+ | Scenario | Icon required? | Size | Code |
566
+ |----------|---------------|------|------|
567
+ | Button with label | Recommended for CTAs | `1em` (auto) | `Button({ iconLeft: 'plus' }, 'Add Item')` |
568
+ | Icon-only button | Yes (only content) | `1em` (auto) | `Button({ 'aria-label': 'Delete', size: 'icon' }, icon('trash'))` |
569
+ | Nav/menu item | Yes (scannability) | `1em` (auto) | `{ label: 'Dashboard', icon: 'layout-dashboard' }` |
570
+ | Alert | Yes (auto-assigned) | component default | `Alert({ variant: 'warning' }, 'Check your input')` |
571
+ | Empty state | Yes (focal point) | `2.5rem`–`3rem` | `icon('inbox', { size: '3rem' })` |
572
+ | Result status | Yes (focal point) | hero tier | `Result({ status: 'success' })` |
573
+ | KPI card | Recommended | `1.5em` | `icon('trending-up', { size: '1.5em' })` |
574
+ | Feature card | Recommended | `1.5em`–`24px` | `icon('shield', { size: '24px' })` |
575
+ | Data table sort | Yes (affordance) | `1em` (auto) | Auto-rendered by DataTable |
576
+ | Standalone decorative | No | — | Use text or visual hierarchy instead |