@adia-ai/web-components 0.4.7 → 0.4.8

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 (211) hide show
  1. package/README.md +39 -0
  2. package/components/accordion/accordion.a2ui.json +3 -0
  3. package/components/accordion/accordion.d.ts +12 -2
  4. package/components/accordion/accordion.yaml +4 -0
  5. package/components/action-list/action-list.a2ui.json +3 -0
  6. package/components/action-list/action-list.d.ts +12 -2
  7. package/components/action-list/action-list.yaml +4 -0
  8. package/components/agent-artifact/agent-artifact.a2ui.json +4 -0
  9. package/components/agent-artifact/agent-artifact.d.ts +12 -2
  10. package/components/agent-artifact/agent-artifact.yaml +5 -0
  11. package/components/agent-feedback-bar/agent-feedback-bar.a2ui.json +3 -0
  12. package/components/agent-feedback-bar/agent-feedback-bar.d.ts +14 -2
  13. package/components/agent-feedback-bar/agent-feedback-bar.yaml +4 -0
  14. package/components/agent-questions/agent-questions.a2ui.json +3 -0
  15. package/components/agent-questions/agent-questions.d.ts +12 -2
  16. package/components/agent-questions/agent-questions.yaml +4 -0
  17. package/components/agent-reasoning/agent-reasoning.a2ui.json +4 -0
  18. package/components/agent-reasoning/agent-reasoning.d.ts +16 -2
  19. package/components/agent-reasoning/agent-reasoning.yaml +5 -0
  20. package/components/agent-suggestions/agent-suggestions.a2ui.json +3 -0
  21. package/components/agent-suggestions/agent-suggestions.d.ts +12 -2
  22. package/components/agent-suggestions/agent-suggestions.yaml +4 -0
  23. package/components/agent-trace/agent-trace.a2ui.json +1 -0
  24. package/components/agent-trace/agent-trace.d.ts +12 -2
  25. package/components/alert/alert.a2ui.json +1 -0
  26. package/components/alert/alert.d.ts +12 -2
  27. package/components/aside/aside.a2ui.json +1 -0
  28. package/components/avatar/avatar.a2ui.json +3 -0
  29. package/components/avatar/avatar.d.ts +3 -2
  30. package/components/avatar/avatar.yaml +4 -0
  31. package/components/badge/badge.a2ui.json +3 -0
  32. package/components/badge/badge.d.ts +3 -2
  33. package/components/badge/badge.yaml +4 -0
  34. package/components/block/block.a2ui.json +1 -0
  35. package/components/block/block.d.ts +3 -2
  36. package/components/breadcrumb/breadcrumb.a2ui.json +5 -0
  37. package/components/breadcrumb/breadcrumb.d.ts +3 -2
  38. package/components/breadcrumb/breadcrumb.yaml +6 -0
  39. package/components/button/button.a2ui.json +3 -0
  40. package/components/button/button.d.ts +12 -2
  41. package/components/button/button.yaml +5 -0
  42. package/components/calendar-picker/calendar-picker.a2ui.json +1 -0
  43. package/components/canvas/canvas.a2ui.json +1 -0
  44. package/components/canvas/canvas.d.ts +18 -2
  45. package/components/canvas/canvas.yaml +10 -0
  46. package/components/card/card.a2ui.json +1 -0
  47. package/components/card/card.d.ts +12 -2
  48. package/components/chart/chart.a2ui.json +1 -0
  49. package/components/chart/chart.d.ts +16 -2
  50. package/components/chart-legend/chart-legend.a2ui.json +4 -0
  51. package/components/chart-legend/chart-legend.d.ts +12 -2
  52. package/components/chart-legend/chart-legend.yaml +5 -0
  53. package/components/chat-thread/chat-thread.a2ui.json +1 -0
  54. package/components/chat-thread/chat-thread.d.ts +12 -2
  55. package/components/check/check.a2ui.json +1 -0
  56. package/components/code/code.a2ui.json +1 -0
  57. package/components/col/col.a2ui.json +1 -0
  58. package/components/col/col.d.ts +3 -2
  59. package/components/color-picker/color-picker.a2ui.json +3 -0
  60. package/components/color-picker/color-picker.yaml +4 -0
  61. package/components/command/command.a2ui.json +1 -0
  62. package/components/command/command.d.ts +14 -2
  63. package/components/demo-toggle/demo-toggle.a2ui.json +1 -0
  64. package/components/demo-toggle/demo-toggle.d.ts +12 -2
  65. package/components/description-list/description-list.a2ui.json +1 -0
  66. package/components/description-list/description-list.d.ts +3 -2
  67. package/components/divider/divider.a2ui.json +1 -0
  68. package/components/divider/divider.d.ts +3 -2
  69. package/components/drawer/drawer.a2ui.json +1 -0
  70. package/components/drawer/drawer.d.ts +12 -2
  71. package/components/embed/embed.a2ui.json +1 -0
  72. package/components/embed/embed.d.ts +3 -2
  73. package/components/empty-state/empty-state.a2ui.json +3 -0
  74. package/components/empty-state/empty-state.d.ts +3 -2
  75. package/components/empty-state/empty-state.yaml +4 -0
  76. package/components/feed/feed.a2ui.json +9 -1
  77. package/components/feed/feed.d.ts +12 -2
  78. package/components/feed/feed.yaml +8 -1
  79. package/components/field/field.a2ui.json +1 -0
  80. package/components/field/field.d.ts +3 -2
  81. package/components/fields/fields.a2ui.json +1 -0
  82. package/components/fields/fields.d.ts +3 -2
  83. package/components/footer/footer.a2ui.json +1 -0
  84. package/components/grid/grid.a2ui.json +1 -0
  85. package/components/grid/grid.d.ts +3 -2
  86. package/components/header/header.a2ui.json +1 -0
  87. package/components/heatmap/heatmap.a2ui.json +1 -0
  88. package/components/heatmap/heatmap.d.ts +14 -2
  89. package/components/icon/icon.a2ui.json +1 -0
  90. package/components/icon/icon.d.ts +3 -2
  91. package/components/image/image.a2ui.json +3 -0
  92. package/components/image/image.d.ts +3 -2
  93. package/components/image/image.yaml +4 -0
  94. package/components/index.js +8 -0
  95. package/components/input/input.a2ui.json +4 -0
  96. package/components/input/input.yaml +6 -0
  97. package/components/inspector/inspector.a2ui.json +5 -0
  98. package/components/inspector/inspector.d.ts +3 -2
  99. package/components/inspector/inspector.yaml +6 -0
  100. package/components/kbd/kbd.a2ui.json +1 -0
  101. package/components/kbd/kbd.d.ts +3 -2
  102. package/components/link/link.a2ui.json +1 -0
  103. package/components/link/link.d.ts +12 -2
  104. package/components/list/list.a2ui.json +3 -0
  105. package/components/list/list.d.ts +12 -2
  106. package/components/list/list.yaml +4 -0
  107. package/components/menu/menu.a2ui.json +3 -0
  108. package/components/menu/menu.d.ts +12 -2
  109. package/components/menu/menu.yaml +4 -0
  110. package/components/modal/modal.a2ui.json +1 -0
  111. package/components/modal/modal.d.ts +12 -2
  112. package/components/nav/nav.a2ui.json +1 -0
  113. package/components/nav/nav.d.ts +12 -2
  114. package/components/nav-group/nav-group.a2ui.json +1 -0
  115. package/components/nav-group/nav-group.d.ts +12 -2
  116. package/components/nav-item/nav-item.a2ui.json +1 -0
  117. package/components/nav-item/nav-item.d.ts +12 -2
  118. package/components/noodles/noodles.a2ui.json +1 -0
  119. package/components/noodles/noodles.d.ts +16 -2
  120. package/components/option-card/option-card.a2ui.json +3 -0
  121. package/components/option-card/option-card.yaml +4 -0
  122. package/components/otp-input/otp-input.a2ui.json +1 -0
  123. package/components/page/page.a2ui.json +1 -0
  124. package/components/page/page.d.ts +3 -2
  125. package/components/pagination/pagination.a2ui.json +1 -0
  126. package/components/pagination/pagination.d.ts +12 -2
  127. package/components/pane/pane.a2ui.json +8 -1
  128. package/components/pane/pane.d.ts +12 -2
  129. package/components/pane/pane.yaml +7 -1
  130. package/components/pipeline-status/pipeline-status.a2ui.json +1 -0
  131. package/components/pipeline-status/pipeline-status.d.ts +3 -2
  132. package/components/popover/popover.a2ui.json +1 -0
  133. package/components/popover/popover.d.ts +3 -2
  134. package/components/progress/progress.a2ui.json +1 -0
  135. package/components/progress/progress.d.ts +3 -2
  136. package/components/progress-row/progress-row.a2ui.json +3 -0
  137. package/components/progress-row/progress-row.d.ts +3 -2
  138. package/components/progress-row/progress-row.yaml +4 -0
  139. package/components/radio/radio.a2ui.json +1 -0
  140. package/components/range/range.a2ui.json +1 -0
  141. package/components/rating/rating.a2ui.json +1 -0
  142. package/components/richtext/richtext.a2ui.json +1 -0
  143. package/components/richtext/richtext.d.ts +3 -2
  144. package/components/row/row.a2ui.json +1 -0
  145. package/components/row/row.d.ts +12 -2
  146. package/components/search/search.a2ui.json +1 -0
  147. package/components/section/section.a2ui.json +1 -0
  148. package/components/segment/segment.a2ui.json +3 -0
  149. package/components/segment/segment.d.ts +3 -2
  150. package/components/segment/segment.yaml +4 -0
  151. package/components/segmented/segmented.a2ui.json +1 -0
  152. package/components/select/select.a2ui.json +3 -0
  153. package/components/select/select.yaml +4 -0
  154. package/components/skeleton/skeleton.a2ui.json +1 -0
  155. package/components/skeleton/skeleton.d.ts +3 -2
  156. package/components/slider/slider.a2ui.json +1 -0
  157. package/components/stack/stack.a2ui.json +1 -0
  158. package/components/stack/stack.d.ts +3 -2
  159. package/components/stat/stat.a2ui.json +1 -0
  160. package/components/step-progress/step-progress.a2ui.json +1 -0
  161. package/components/step-progress/step-progress.d.ts +3 -2
  162. package/components/stepper/stepper.a2ui.json +3 -0
  163. package/components/stepper/stepper.d.ts +3 -2
  164. package/components/stepper/stepper.yaml +4 -0
  165. package/components/stream/stream.a2ui.json +1 -0
  166. package/components/stream/stream.d.ts +16 -2
  167. package/components/swatch/swatch.a2ui.json +1 -0
  168. package/components/swatch/swatch.d.ts +3 -2
  169. package/components/swiper/swiper.a2ui.json +3 -0
  170. package/components/swiper/swiper.d.ts +16 -2
  171. package/components/swiper/swiper.yaml +4 -0
  172. package/components/switch/switch.a2ui.json +1 -0
  173. package/components/table/table.a2ui.json +7 -0
  174. package/components/table/table.d.ts +20 -2
  175. package/components/table/table.yaml +8 -0
  176. package/components/table-toolbar/table-toolbar.a2ui.json +12 -0
  177. package/components/table-toolbar/table-toolbar.d.ts +18 -2
  178. package/components/table-toolbar/table-toolbar.yaml +13 -0
  179. package/components/tabs/tabs.a2ui.json +3 -0
  180. package/components/tabs/tabs.d.ts +12 -2
  181. package/components/tabs/tabs.yaml +4 -0
  182. package/components/tag/tag.a2ui.json +1 -0
  183. package/components/tag/tag.d.ts +12 -2
  184. package/components/text/text.a2ui.json +1 -0
  185. package/components/text/text.d.ts +3 -2
  186. package/components/textarea/textarea.a2ui.json +1 -0
  187. package/components/timeline/timeline.a2ui.json +18 -1
  188. package/components/timeline/timeline.d.ts +19 -2
  189. package/components/timeline/timeline.yaml +14 -1
  190. package/components/toast/toast.a2ui.json +1 -0
  191. package/components/toast/toast.d.ts +12 -2
  192. package/components/toggle-group/toggle-group.a2ui.json +1 -0
  193. package/components/toggle-group/toggle-group.d.ts +12 -2
  194. package/components/toggle-scheme/toggle-scheme.a2ui.json +3 -0
  195. package/components/toggle-scheme/toggle-scheme.d.ts +12 -2
  196. package/components/toggle-scheme/toggle-scheme.yaml +4 -0
  197. package/components/toolbar/toolbar.a2ui.json +3 -0
  198. package/components/toolbar/toolbar.d.ts +3 -2
  199. package/components/toolbar/toolbar.yaml +4 -0
  200. package/components/tooltip/tooltip.a2ui.json +1 -0
  201. package/components/tooltip/tooltip.d.ts +3 -2
  202. package/components/tree/tree.a2ui.json +3 -0
  203. package/components/tree/tree.d.ts +12 -2
  204. package/components/tree/tree.yaml +4 -0
  205. package/components/upload/upload.a2ui.json +1 -0
  206. package/core/icons-phosphor.js +93 -0
  207. package/core/icons.js +92 -90
  208. package/core/index.js +5 -0
  209. package/index.d.ts +78 -77
  210. package/index.js +7 -0
  211. package/package.json +3 -2
@@ -24,6 +24,9 @@
24
24
  "x-adiaui": {
25
25
  "anti_patterns": [],
26
26
  "category": "data",
27
+ "composes": [
28
+ "icon-ui"
29
+ ],
27
30
  "events": {
28
31
  "tree-select": {
29
32
  "description": "Fired when an item is selected. detail: { item, text, value }"
@@ -5,11 +5,21 @@
5
5
  *
6
6
  * Type declarations generated by scripts/build/dts-codegen.mjs from
7
7
  * the component's `.a2ui.json` sidecar. Edit the source `.yaml`,
8
- * run `npm run components`, then `npm run codegen:dts` to regenerate;
9
- * or hand-author this file fully if rich event types are needed.
8
+ * run `npm run build:components`, then `npm run codegen:dts` to
9
+ * regenerate; or hand-author this file fully if rich event types are
10
+ * needed beyond what the yaml `events:` block can express.
10
11
  */
11
12
 
12
13
  import { UIElement } from '../../core/element.js';
13
14
 
15
+ export type TreeSelectEvent = CustomEvent<unknown>;
16
+
14
17
  export class UITree extends UIElement {
18
+
19
+ addEventListener<K extends keyof HTMLElementEventMap>(
20
+ type: K,
21
+ listener: (this: UITree, ev: HTMLElementEventMap[K]) => unknown,
22
+ options?: boolean | AddEventListenerOptions,
23
+ ): void;
24
+ addEventListener(type: 'tree-select', listener: (ev: TreeSelectEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
15
25
  }
@@ -8,6 +8,10 @@ category: data
8
8
  version: 1
9
9
  description: Collapsible tree container with keyboard navigation (arrow keys, Enter/Space). Manages
10
10
  selection across nested tree-item-ns.
11
+ # Per ADR-0027 — primitives that programmatically create other primitives
12
+ # do NOT auto-import them. Consumer (or demo shell) must explicitly import.
13
+ composes:
14
+ - icon-ui
11
15
  props: {}
12
16
  events:
13
17
  tree-select:
@@ -64,6 +64,7 @@
64
64
  "x-adiaui": {
65
65
  "anti_patterns": [],
66
66
  "category": "input",
67
+ "composes": [],
67
68
  "events": {
68
69
  "change": {
69
70
  "description": "Fired when files are selected via click or drag-and-drop"
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Phosphor icon glob — side-effect module that wires the full
3
+ * @phosphor-icons/core asset tree (~9000 SVGs × 6 weights) into the
4
+ * registry exposed by `./icons.js`.
5
+ *
6
+ * ## When to import this
7
+ *
8
+ * import '@adia-ai/web-components/core/icons-phosphor';
9
+ *
10
+ * Use this only when you want any Phosphor name to resolve without
11
+ * pre-registering it. The main barrel (`import '@adia-ai/web-components'`)
12
+ * and the core barrel (`import '@adia-ai/web-components/core'`) already
13
+ * side-effect-import this file for zero-config users.
14
+ *
15
+ * ## What this costs
16
+ *
17
+ * `import.meta.glob` with the default lazy mode tells Vite to emit one
18
+ * code-split chunk per matched file. The full Phosphor set is ~9000 SVGs
19
+ * (~1500 names × 6 weights), so `vite build` emits ~9000 chunks even if
20
+ * your app only renders 2 icons. The chunks are HTTP-cacheable, but:
21
+ *
22
+ * - `vite build` graph cost scales with the Phosphor set, not your usage
23
+ * - `.vite/deps` cache grows >100 MB during dev
24
+ * - Static deploys without incremental upload push tens of thousands of
25
+ * tiny files on every deploy
26
+ * - Rollup warns "(!) Some chunks are larger than 500 KB"
27
+ *
28
+ * For production bundles with size SLOs, skip this side-effect import and
29
+ * register only the icons you use:
30
+ *
31
+ * import { installIconLoaders } from '@adia-ai/web-components/core/icons';
32
+ * installIconLoaders({
33
+ * regular: import.meta.glob(
34
+ * '/node_modules/@phosphor-icons/core/assets/regular/{caret-right,moon,sun,x}.svg',
35
+ * { query: '?raw', import: 'default', eager: true }
36
+ * ),
37
+ * });
38
+ *
39
+ * Brace-list globs are statically analyzed; only the named files are
40
+ * emitted as chunks (or inlined when `eager: true`).
41
+ *
42
+ * ## Vite glob detection
43
+ *
44
+ * `import.meta.glob` is a build-time macro — Vite's AST transform replaces
45
+ * each call with a literal `{ path: loader }` object before the module
46
+ * reaches the browser. At runtime `import.meta.glob` is undefined, so a
47
+ * direct call throws. We wrap the assignment in try/catch to handle both:
48
+ *
49
+ * - Vite dev/build → rewritten to literals → try block succeeds
50
+ * - Static serving → actual runtime call throws → catch falls through
51
+ * to the manifest fetch below
52
+ */
53
+
54
+ import { installIconLoaders } from './icons.js';
55
+
56
+ let weightModules;
57
+ let hasViteGlob = false;
58
+ try {
59
+ weightModules = {
60
+ regular: import.meta.glob('/node_modules/@phosphor-icons/core/assets/regular/*.svg', { query: '?raw', import: 'default' }),
61
+ thin: import.meta.glob('/node_modules/@phosphor-icons/core/assets/thin/*.svg', { query: '?raw', import: 'default' }),
62
+ light: import.meta.glob('/node_modules/@phosphor-icons/core/assets/light/*.svg', { query: '?raw', import: 'default' }),
63
+ bold: import.meta.glob('/node_modules/@phosphor-icons/core/assets/bold/*.svg', { query: '?raw', import: 'default' }),
64
+ fill: import.meta.glob('/node_modules/@phosphor-icons/core/assets/fill/*.svg', { query: '?raw', import: 'default' }),
65
+ duotone: import.meta.glob('/node_modules/@phosphor-icons/core/assets/duotone/*.svg', { query: '?raw', import: 'default' }),
66
+ };
67
+ hasViteGlob = true;
68
+ } catch {
69
+ /* non-Vite static serving — manifest fetch below handles it */
70
+ }
71
+
72
+ if (hasViteGlob) {
73
+ installIconLoaders(weightModules);
74
+ } else {
75
+ // Non-Vite static serving: fetch the build-time manifest in the
76
+ // background. No top-level await — module finishes loading immediately;
77
+ // icons appear once the one-shot manifest fetch resolves.
78
+ // The specifier is hidden behind a variable so Vite's static analysis
79
+ // never tries to pre-resolve it in dev (where the file doesn't exist).
80
+ const manifestSpec = './icons-manifest.js';
81
+ import(/* @vite-ignore */ manifestSpec).then(({ default: manifest }) => {
82
+ const modules = Object.fromEntries(Object.entries(manifest).map(([weight, names]) => {
83
+ const prefix = `/node_modules/@phosphor-icons/core/assets/${weight}/`;
84
+ const entries = names.map(name => {
85
+ const path = prefix + name;
86
+ const loader = () => fetch(path).then(r => r.ok ? r.text() : Promise.reject(new Error(`icon fetch failed: ${path}`)));
87
+ return [path, loader];
88
+ });
89
+ return [weight, Object.fromEntries(entries)];
90
+ }));
91
+ installIconLoaders(modules);
92
+ }).catch(() => { /* manifest missing — registry stays empty; consumers can registerIcon() themselves */ });
93
+ }
package/core/icons.js CHANGED
@@ -1,11 +1,56 @@
1
1
  /**
2
- * Icon Registry — loads SVGs from @phosphor-icons/core.
3
- * All icons are loaded on-demand; each weight variant is cached separately.
2
+ * Icon Registry — pluggable icon lookup map.
4
3
  *
5
4
  * Usage:
6
5
  * <icon-ui name="paper-plane-right"></icon-ui>
7
6
  * <icon-ui name="star" weight="fill"></icon-ui>
8
7
  * <icon-ui name="heart" weight="bold"></icon-ui>
8
+ *
9
+ * ## Why this module is small
10
+ *
11
+ * This file holds the registry surface only. The Phosphor auto-glob
12
+ * (`@phosphor-icons/core/assets/{weight}/*.svg` × 6 weights, ~9000 SVGs)
13
+ * lives in the sibling side-effect module `./icons-phosphor.js`. Splitting
14
+ * keeps `core/icons.js` cheap to import — primitives that consume the
15
+ * registry API (button, input, icon) pull in the API surface without
16
+ * triggering Vite's per-icon code-split chunks.
17
+ *
18
+ * ## Loading icons
19
+ *
20
+ * Three paths, pick whichever matches your bundle-size budget:
21
+ *
22
+ * 1. **Zero-config (recommended for prototypes + small apps).** Import
23
+ * the main barrel — it side-effect-imports `icons-phosphor.js` for
24
+ * you and every Phosphor name resolves on demand:
25
+ *
26
+ * import '@adia-ai/web-components';
27
+ *
28
+ * 2. **Opt-in full Phosphor with piecemeal component imports.** If you
29
+ * import components one at a time but want every Phosphor name to
30
+ * work, side-effect-import the phosphor module yourself:
31
+ *
32
+ * import '@adia-ai/web-components/components/button';
33
+ * import '@adia-ai/web-components/core/icons-phosphor';
34
+ *
35
+ * 3. **Scoped registration (recommended for production bundle-size
36
+ * SLOs).** Skip `icons-phosphor.js` entirely and register only the
37
+ * icons you actually use. `import.meta.glob` with a brace-list emits
38
+ * one chunk per matched file — for a 4-icon app, that's ~4 chunks
39
+ * instead of the ~9000 the full set would produce:
40
+ *
41
+ * import { installIconLoaders } from '@adia-ai/web-components/core/icons';
42
+ * installIconLoaders({
43
+ * regular: import.meta.glob(
44
+ * '/node_modules/@phosphor-icons/core/assets/regular/{caret-right,caret-up-down,moon,sun}.svg',
45
+ * { query: '?raw', import: 'default', eager: true }
46
+ * ),
47
+ * });
48
+ *
49
+ * Or register single SVGs directly:
50
+ *
51
+ * import { registerIcon } from '@adia-ai/web-components/core/icons';
52
+ * import caretRightSvg from './assets/caret-right.svg?raw';
53
+ * registerIcon('caret-right', caretRightSvg);
9
54
  */
10
55
 
11
56
  export const ICON_WEIGHTS = ['regular', 'thin', 'light', 'bold', 'fill', 'duotone'];
@@ -49,94 +94,50 @@ export function listIcons() {
49
94
  return [...registry.keys()];
50
95
  }
51
96
 
52
- // ── Async loader ──
53
-
54
- // Vite dev: `import.meta.glob(...)` is a build-time macro — Vite's AST
55
- // transform replaces each call with a literal `{ path: loader }` object
56
- // before the module reaches the browser. `import.meta.glob` itself is NOT
57
- // exposed as a runtime property, so `typeof import.meta.glob` is always
58
- // `'undefined'` at run time — don't try to feature-detect with it.
97
+ // ── Loader-map plumbing ──
59
98
  //
60
- // Production static serving (no Vite): the glob calls remain in the
61
- // source and `import.meta.glob` is undefined, so calling it throws a
62
- // TypeError. We wrap the assignment in try/catch to handle both worlds:
63
- // - Vite dev Vite rewrote the calls to literals → try block succeeds.
64
- // - Static → actual runtime call throws catch block falls back to
65
- // EMPTY_WEIGHTS; the manifest branch below fills it in.
66
- const EMPTY_WEIGHTS = { regular: {}, thin: {}, light: {}, bold: {}, fill: {}, duotone: {} };
99
+ // `weightModules` maps weight ({ path → loader }). A loader is either an
100
+ // SVG string (eager) or a `() => Promise<string>` (lazy). The default empty
101
+ // map means lookups all miss; callers either register icons directly via
102
+ // `registerIcon`/`registerIcons` or install a loader map via
103
+ // `installIconLoaders` (called by `icons-phosphor.js` in the zero-config path).
67
104
 
68
- // `let` so the background manifest load (non-Vite branch) can swap in a
69
- // real map once `icons-manifest.js` resolves. `resolveLoader` reads
70
- // through this each call, so new icons become visible after manifest load.
71
- let weightModules;
72
- let hasViteGlob = false;
73
- try {
74
- weightModules = {
75
- regular: import.meta.glob('/node_modules/@phosphor-icons/core/assets/regular/*.svg', { query: '?raw', import: 'default' }),
76
- thin: import.meta.glob('/node_modules/@phosphor-icons/core/assets/thin/*.svg', { query: '?raw', import: 'default' }),
77
- light: import.meta.glob('/node_modules/@phosphor-icons/core/assets/light/*.svg', { query: '?raw', import: 'default' }),
78
- bold: import.meta.glob('/node_modules/@phosphor-icons/core/assets/bold/*.svg', { query: '?raw', import: 'default' }),
79
- fill: import.meta.glob('/node_modules/@phosphor-icons/core/assets/fill/*.svg', { query: '?raw', import: 'default' }),
80
- duotone: import.meta.glob('/node_modules/@phosphor-icons/core/assets/duotone/*.svg', { query: '?raw', import: 'default' }),
81
- };
82
- hasViteGlob = true;
83
- } catch {
84
- weightModules = EMPTY_WEIGHTS;
85
- }
86
-
87
- /* Flag guarding the missing-icon warn below. In Vite dev, `weightModules`
88
- is populated synchronously by the glob rewrite, so the registry is ready
89
- before any icon-ui element connects. In non-Vite static deploys, the
90
- manifest load is async and arrives some time after first paint — warning
91
- during that window would false-positive for every icon on the page.
92
- Flipped to `true` in the manifest `.then()` handler below. */
93
- let registryReady = hasViteGlob;
105
+ const EMPTY_WEIGHTS = { regular: {}, thin: {}, light: {}, bold: {}, fill: {}, duotone: {} };
106
+ let weightModules = EMPTY_WEIGHTS;
94
107
 
95
108
  /* `whenIconRegistryReady` lets a component defer icon-name decisions until
96
109
  the registry is sync-checkable. <icon-ui> doesn't need it — it owns the
97
- <name → svg> render and the manifest .then() handler below re-runs
98
- loadIcon for every element. But components that branch on whether a
99
- string IS an icon (e.g. <input-ui>'s prefix/suffix, which accept both
100
- icon names and text labels like "@" or "$") need to re-evaluate after
101
- manifest load, otherwise a kebab-case name baked into the DOM as text
102
- never recovers. */
110
+ <name → svg> render and re-stamps elements when the loader map arrives.
111
+ But components that branch on whether a string IS an icon (e.g.
112
+ <input-ui>'s prefix/suffix, which accept both icon names and text labels
113
+ like "@" or "$") need to re-evaluate once loaders arrive, otherwise a
114
+ kebab-case name baked into the DOM as text never recovers. */
115
+ let registryReady = false;
103
116
  let resolveRegistryReady;
104
117
  export const whenIconRegistryReady = new Promise((r) => { resolveRegistryReady = r; });
105
- if (hasViteGlob) resolveRegistryReady();
106
118
 
107
- // Non-Vite environments (plain static serving): fetch the build-time
108
- // manifest in the background and rebuild `weightModules` with lazy
109
- // fetch-based loaders. No top-level await the module finishes loading
110
- // immediately; icons appear once the one-shot manifest fetch resolves.
111
- if (!hasViteGlob) {
112
- // Specifier is hidden behind a variable so Vite's static analysis
113
- // never tries to pre-resolve it in dev (where the file doesn't exist).
114
- const manifestSpec = './icons-manifest.js';
115
- import(/* @vite-ignore */ manifestSpec).then(({ default: manifest }) => {
116
- weightModules = Object.fromEntries(Object.entries(manifest).map(([weight, names]) => {
117
- const prefix = `/node_modules/@phosphor-icons/core/assets/${weight}/`;
118
- const entries = names.map(name => {
119
- const path = prefix + name;
120
- const loader = () => fetch(path).then(r => r.ok ? r.text() : Promise.reject(new Error(`icon fetch failed: ${path}`)));
121
- return [path, loader];
122
- });
123
- return [weight, Object.fromEntries(entries)];
124
- }));
125
- registryReady = true;
126
- // icon-ui elements that asked for an icon before the manifest loaded
127
- // gave up silently (resolveLoader returned null on EMPTY_WEIGHTS).
128
- // Re-request every <icon-ui name> now that a real loader map is in
129
- // place. Idempotent — already-loaded icons short-circuit on
130
- // registry.has() inside loadIcon.
131
- if (typeof document !== 'undefined') {
132
- for (const el of document.querySelectorAll('icon-ui[name]')) {
133
- const name = el.getAttribute('name');
134
- const weight = el.getAttribute('weight') || DEFAULT_WEIGHT;
135
- if (name) loadIcon(name, weight);
136
- }
119
+ /**
120
+ * Install a per-weight loader map and mark the registry ready. The map
121
+ * shape matches `import.meta.glob` output: `{ '/path/to/star.svg': loader }`.
122
+ *
123
+ * Either a lazy glob (Vite emits a chunk per icon) or `{ eager: true }`
124
+ * (Vite inlines the strings) works the loader can be the SVG string
125
+ * directly or a thunk returning `Promise<string>`.
126
+ *
127
+ * Calling this re-stamps any `<icon-ui>` elements that asked for an icon
128
+ * before loaders arrived. Idempotent calling it twice replaces the map.
129
+ */
130
+ export function installIconLoaders(modules) {
131
+ weightModules = { ...EMPTY_WEIGHTS, ...modules };
132
+ registryReady = true;
133
+ if (typeof document !== 'undefined') {
134
+ for (const el of document.querySelectorAll('icon-ui[name]')) {
135
+ const name = el.getAttribute('name');
136
+ const weight = el.getAttribute('weight') || DEFAULT_WEIGHT;
137
+ if (name) loadIcon(name, weight);
137
138
  }
138
- resolveRegistryReady();
139
- }).catch(() => { /* keep EMPTY_WEIGHTS — registryReady stays false */ });
139
+ }
140
+ resolveRegistryReady();
140
141
  }
141
142
 
142
143
  /* Track which (name, weight) pairs we've already warned about so the
@@ -184,9 +185,9 @@ function resolveLoader(name, weight = DEFAULT_WEIGHT) {
184
185
 
185
186
  /**
186
187
  * Sync check: is `name` a loadable icon at the given weight? True if the
187
- * asset exists in the build-time glob OR has an alias that does. Does NOT
188
- * trigger loading. Used by components that accept either an icon name or a
189
- * text label (e.g. input-ui's prefix/suffix) to disambiguate.
188
+ * asset exists in the installed loader map OR has an alias that does. Does
189
+ * NOT trigger loading. Used by components that accept either an icon name
190
+ * or a text label (e.g. input-ui's prefix/suffix) to disambiguate.
190
191
  */
191
192
  export function isIconName(name, weight = DEFAULT_WEIGHT) {
192
193
  if (!name || typeof name !== 'string') return false;
@@ -267,16 +268,17 @@ async function loadIcon(name, weight = DEFAULT_WEIGHT) {
267
268
  if (!loader) {
268
269
  pending.delete(key);
269
270
  // Warn once per (name, weight) — but only if the registry is
270
- // known-complete. In non-Vite pre-manifest mode, `weightModules` is
271
- // empty and every lookup fails legitimately until the manifest
272
- // resolves; warning there would be noise. The manifest `.then()`
273
- // handler above re-triggers loadIcon for every element, so misses
274
- // that survive the re-query are the ones worth warning about.
271
+ // known-complete. Pre-loader-install the map is empty + every lookup
272
+ // fails legitimately; warning there would be noise. `installIconLoaders`
273
+ // re-stamps every <icon-ui> element after install, so misses that
274
+ // survive the re-query are the ones worth warning about.
275
275
  if (registryReady) warnMissingIcon(name, weight);
276
276
  return;
277
277
  }
278
278
 
279
- const svg = await loader();
279
+ // Loader may be a string (eager glob) or a thunk returning string /
280
+ // Promise<string> (lazy glob or fetch).
281
+ const svg = typeof loader === 'function' ? await loader() : loader;
280
282
  registry.set(key, svg);
281
283
 
282
284
  // Re-render any icon-ui elements showing this name+weight. Regular has
package/core/index.js CHANGED
@@ -21,6 +21,11 @@ export * from './controller.js';
21
21
  export * from './provider.js';
22
22
  export * from './anchor.js';
23
23
  export * from './icons.js';
24
+ // Side-effect-import phosphor so the core barrel preserves zero-config
25
+ // icon resolution. Apps that want a scoped icon set should import
26
+ // `core/icons` directly and call `installIconLoaders()` — see
27
+ // `core/icons.js` JSDoc.
28
+ import './icons-phosphor.js';
24
29
  export * from './markdown.js';
25
30
  export * from './transport.js';
26
31
  export * from './polyfills.js';
package/index.d.ts CHANGED
@@ -129,83 +129,84 @@ export type {
129
129
  UploadChangeEventDetail,
130
130
  } from './components/upload/upload.js';
131
131
 
132
- // ── Non-form primitives (typed; §74 v0.4.7) ─────────────────────────
133
- // Property types are codegen'd from each component's `.a2ui.json`
134
- // sidecar by `scripts/build/dts-codegen.mjs`. Event types stay on the
135
- // 17 form-bearing primitives (above) where they carry semantic payload.
136
- export type { UIAccordion } from './components/accordion/accordion.js';
137
- export type { UIActionList } from './components/action-list/action-list.js';
138
- export type { UIAgentArtifact } from './components/agent-artifact/agent-artifact.js';
139
- export type { UIAgentFeedbackBar } from './components/agent-feedback-bar/agent-feedback-bar.js';
140
- export type { UIAgentQuestions } from './components/agent-questions/agent-questions.js';
141
- export type { UIAgentReasoning } from './components/agent-reasoning/agent-reasoning.js';
142
- export type { UIAgentSuggestions } from './components/agent-suggestions/agent-suggestions.js';
143
- export type { UIAgentTrace } from './components/agent-trace/agent-trace.js';
144
- export type { UIAlert } from './components/alert/alert.js';
145
- export type { UIAvatar } from './components/avatar/avatar.js';
146
- export type { UIBadge } from './components/badge/badge.js';
147
- export type { UIBlock } from './components/block/block.js';
148
- export type { UIBreadcrumb } from './components/breadcrumb/breadcrumb.js';
149
- export type { UIButton } from './components/button/button.js';
150
- export type { UICanvas } from './components/canvas/canvas.js';
151
- export type { UICard } from './components/card/card.js';
152
- export type { UIChart } from './components/chart/chart.js';
153
- export type { UIChartLegend } from './components/chart-legend/chart-legend.js';
154
- export type { UIChatThread } from './components/chat-thread/chat-thread.js';
155
- export type { UIColumn } from './components/col/col.js';
156
- export type { UICommand } from './components/command/command.js';
157
- export type { UIDemoToggle } from './components/demo-toggle/demo-toggle.js';
158
- export type { UIDescriptionList } from './components/description-list/description-list.js';
159
- export type { UIDivider } from './components/divider/divider.js';
160
- export type { UIDrawer } from './components/drawer/drawer.js';
161
- export type { UIEmbed } from './components/embed/embed.js';
162
- export type { UIEmptyState } from './components/empty-state/empty-state.js';
163
- export type { UIFeed } from './components/feed/feed.js';
164
- export type { UIField } from './components/field/field.js';
165
- export type { UIFields } from './components/fields/fields.js';
166
- export type { UIGrid } from './components/grid/grid.js';
167
- export type { UIHeatmap } from './components/heatmap/heatmap.js';
168
- export type { UIIcon } from './components/icon/icon.js';
169
- export type { UIImage } from './components/image/image.js';
170
- export type { UIInspector } from './components/inspector/inspector.js';
171
- export type { UIKbd } from './components/kbd/kbd.js';
172
- export type { UILink } from './components/link/link.js';
173
- export type { UIList } from './components/list/list.js';
174
- export type { UIMenu } from './components/menu/menu.js';
175
- export type { UIModal } from './components/modal/modal.js';
176
- export type { UINav } from './components/nav/nav.js';
177
- export type { UINavGroup } from './components/nav-group/nav-group.js';
178
- export type { UINavItem } from './components/nav-item/nav-item.js';
179
- export type { UINoodles } from './components/noodles/noodles.js';
180
- export type { UIPage } from './components/page/page.js';
181
- export type { UIPagination } from './components/pagination/pagination.js';
182
- export type { UIPane } from './components/pane/pane.js';
183
- export type { UIPipelineStatus } from './components/pipeline-status/pipeline-status.js';
184
- export type { UIPopover } from './components/popover/popover.js';
185
- export type { UIProgress } from './components/progress/progress.js';
186
- export type { UIProgressRow } from './components/progress-row/progress-row.js';
187
- export type { UIRichtext } from './components/richtext/richtext.js';
188
- export type { UIRow } from './components/row/row.js';
189
- export type { UISegment } from './components/segment/segment.js';
190
- export type { UISkeleton } from './components/skeleton/skeleton.js';
191
- export type { UIStack } from './components/stack/stack.js';
192
- export type { UIStepProgress } from './components/step-progress/step-progress.js';
193
- export type { UIStepper } from './components/stepper/stepper.js';
194
- export type { UIStream } from './components/stream/stream.js';
195
- export type { UISwatch } from './components/swatch/swatch.js';
196
- export type { UISwiper } from './components/swiper/swiper.js';
197
- export type { UITable } from './components/table/table.js';
198
- export type { UITableToolbar } from './components/table-toolbar/table-toolbar.js';
199
- export type { UITabs } from './components/tabs/tabs.js';
200
- export type { UITag } from './components/tag/tag.js';
201
- export type { UIText } from './components/text/text.js';
202
- export type { UITimeline } from './components/timeline/timeline.js';
203
- export type { UIToast } from './components/toast/toast.js';
204
- export type { UIToggleGroup } from './components/toggle-group/toggle-group.js';
205
- export type { UIToggleScheme } from './components/toggle-scheme/toggle-scheme.js';
206
- export type { UIToolbar } from './components/toolbar/toolbar.js';
207
- export type { UITooltip } from './components/tooltip/tooltip.js';
208
- export type { UITree } from './components/tree/tree.js';
132
+ // ── Non-form primitives (typed; §74 v0.4.7 + §80 v0.4.8) ────────────
133
+ // Property types + event types codegen'd from each component's
134
+ // `.a2ui.json` sidecar by `scripts/build/dts-codegen.mjs`. Event-bearing
135
+ // types use `export *` so consumers can import event type names
136
+ // (e.g. `ModalCloseEvent`, `TimelineToggleEventDetail`) directly.
137
+ export * from './components/accordion/accordion.js';
138
+ export * from './components/action-list/action-list.js';
139
+ export * from './components/agent-artifact/agent-artifact.js';
140
+ export * from './components/agent-feedback-bar/agent-feedback-bar.js';
141
+ export * from './components/agent-questions/agent-questions.js';
142
+ export * from './components/agent-reasoning/agent-reasoning.js';
143
+ export * from './components/agent-suggestions/agent-suggestions.js';
144
+ export * from './components/agent-trace/agent-trace.js';
145
+ export * from './components/alert/alert.js';
146
+ export * from './components/avatar/avatar.js';
147
+ export * from './components/badge/badge.js';
148
+ export * from './components/block/block.js';
149
+ export * from './components/breadcrumb/breadcrumb.js';
150
+ export * from './components/button/button.js';
151
+ export * from './components/canvas/canvas.js';
152
+ export * from './components/card/card.js';
153
+ export * from './components/chart/chart.js';
154
+ export * from './components/chart-legend/chart-legend.js';
155
+ export * from './components/chat-thread/chat-thread.js';
156
+ export * from './components/col/col.js';
157
+ export * from './components/command/command.js';
158
+ export * from './components/demo-toggle/demo-toggle.js';
159
+ export * from './components/description-list/description-list.js';
160
+ export * from './components/divider/divider.js';
161
+ export * from './components/drawer/drawer.js';
162
+ export * from './components/embed/embed.js';
163
+ export * from './components/empty-state/empty-state.js';
164
+ export * from './components/feed/feed.js';
165
+ export * from './components/field/field.js';
166
+ export * from './components/fields/fields.js';
167
+ export * from './components/grid/grid.js';
168
+ export * from './components/heatmap/heatmap.js';
169
+ export * from './components/icon/icon.js';
170
+ export * from './components/image/image.js';
171
+ export * from './components/inspector/inspector.js';
172
+ export * from './components/kbd/kbd.js';
173
+ export * from './components/link/link.js';
174
+ export * from './components/list/list.js';
175
+ export * from './components/menu/menu.js';
176
+ export * from './components/modal/modal.js';
177
+ export * from './components/nav/nav.js';
178
+ export * from './components/nav-group/nav-group.js';
179
+ export * from './components/nav-item/nav-item.js';
180
+ export * from './components/noodles/noodles.js';
181
+ export * from './components/page/page.js';
182
+ export * from './components/pagination/pagination.js';
183
+ export * from './components/pane/pane.js';
184
+ export * from './components/pipeline-status/pipeline-status.js';
185
+ export * from './components/popover/popover.js';
186
+ export * from './components/progress/progress.js';
187
+ export * from './components/progress-row/progress-row.js';
188
+ export * from './components/richtext/richtext.js';
189
+ export * from './components/row/row.js';
190
+ export * from './components/segment/segment.js';
191
+ export * from './components/skeleton/skeleton.js';
192
+ export * from './components/stack/stack.js';
193
+ export * from './components/step-progress/step-progress.js';
194
+ export * from './components/stepper/stepper.js';
195
+ export * from './components/stream/stream.js';
196
+ export * from './components/swatch/swatch.js';
197
+ export * from './components/swiper/swiper.js';
198
+ export * from './components/table/table.js';
199
+ export * from './components/table-toolbar/table-toolbar.js';
200
+ export * from './components/tabs/tabs.js';
201
+ export * from './components/tag/tag.js';
202
+ export * from './components/text/text.js';
203
+ export * from './components/timeline/timeline.js';
204
+ export * from './components/toast/toast.js';
205
+ export * from './components/toggle-group/toggle-group.js';
206
+ export * from './components/toggle-scheme/toggle-scheme.js';
207
+ export * from './components/toolbar/toolbar.js';
208
+ export * from './components/tooltip/tooltip.js';
209
+ export * from './components/tree/tree.js';
209
210
 
210
211
  // ── Global HTMLElementTagNameMap augmentation ───────────────────────
211
212
  //
package/index.js CHANGED
@@ -23,6 +23,13 @@
23
23
  * import '@adia-ai/web-modules/chat'; // chat-shell
24
24
  * import '@adia-ai/web-modules/editor'; // editor-shell
25
25
  * import '@adia-ai/web-modules/runtime'; // gen-root, a2ui-root
26
+ *
27
+ * Icon registry: the main barrel side-effect-imports
28
+ * `core/icons-phosphor.js` so every Phosphor name resolves without
29
+ * pre-registration. Apps with bundle-size SLOs should skip this barrel,
30
+ * import primitives piecemeal, and call `installIconLoaders()` with a
31
+ * scoped glob — see `core/icons.js` JSDoc.
26
32
  */
27
33
 
34
+ import './core/icons-phosphor.js';
28
35
  export * from './components/index.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adia-ai/web-components",
3
- "version": "0.4.7",
3
+ "version": "0.4.8",
4
4
  "description": "AdiaUI web components — vanilla custom elements. A2UI runtime (renderer, registry, streams, wiring) lives in @adia-ai/a2ui-runtime.",
5
5
  "type": "module",
6
6
  "types": "./index.d.ts",
@@ -54,7 +54,8 @@
54
54
  "*.css",
55
55
  "./index.js",
56
56
  "./components/**/*.js",
57
- "./core/provider.js"
57
+ "./core/provider.js",
58
+ "./core/icons-phosphor.js"
58
59
  ],
59
60
  "dependencies": {
60
61
  "@adia-ai/a2ui-runtime": "^0.4.0"