@adia-ai/web-components 0.6.13 → 0.6.15
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.
- package/CHANGELOG.md +22 -0
- package/core/icons-phosphor.js +41 -2
- package/core/icons.js +64 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# Changelog — @adia-ai/web-components
|
|
2
2
|
|
|
3
|
+
## [0.6.15] — 2026-05-21
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
- **`installIconLoaders` / `installIconLoadersForRegistered` no longer silently accept a malformed shape (FB-07).** The previous behavior was `weightModules = { ...EMPTY_WEIGHTS, ...modules }` which spread any top-level keys verbatim. A flat path→svg glob (the documented quick-start shape; see FB-09) had its `/path/foo.svg` keys spread at the top level of `weightModules`, leaving every per-weight slot empty. Every `<icon-ui>` then rendered the icon NAME as visible text in its slot — confusing to debug because the per-icon `warnMissingIcon` console message points at name-resolution issues (Phosphor alias, `registerIcon`, etc.), not at loader-shape issues. The fix shape-detects three cases: (1) per-weight map keyed by `regular`/`thin`/`light`/`bold`/`fill`/`duotone` installs verbatim; (2) flat path→svg map auto-promotes to `{ regular: <flat> }` with a one-time `console.warn` so the caller knows to wrap explicitly (and so bold/fill/etc. aren't silently lost); (3) anything else logs `console.error` with the received key sample and aborts the install (registry stays unchanged). Net: the documented flat shape from `docs/guides/02-quick-start.md` continues to work but emits one diagnostic warn per install; consumers on prior versions writing the flat shape needed to wrap manually to get icons at all. Files: `packages/web-components/core/icons.js` (+59 LOC: `WEIGHT_KEYS` const, `isFlatGlobShape()`, `warnedShapes` WeakSet, three-branch dispatch inside `installIconLoaders`).
|
|
7
|
+
- **`core/icons-phosphor.js` no longer silently swallows `import.meta.glob` failures (FB-08).** Two silent-fail paths fixed. (a) **Empty-glob path** — `import.meta.glob('/node_modules/@phosphor-icons/core/assets/<weight>/*.svg', …)` returns `{}` (not an error) when zero files match. This happens when the consumer's Vite root sits below `node_modules`, or with pnpm/yarn-berry virtual paths, or when this module is loaded from a published package directory (the absolute-style glob is resolved against the Vite root, not this file's directory). Previously `hasViteGlob` was set true and `installIconLoaders({ regular: {}, … })` ran anyway, leaving the registry empty with no diagnostic. The fix sums per-weight entry counts after the `try` block; if all six weights have zero entries, emits a `console.warn` with the canonical manual-install snippet. (b) **Caught-error path** — the bare `catch {}` was scoped to handle "no Vite at all" (`ReferenceError` because `import.meta.glob` doesn't exist in static serving), but it also swallowed every OTHER error type (plugin order issues, Vite-config misconfigs, etc.). The catch now logs non-`ReferenceError` failures via `console.warn` before falling back to the manifest fetch. Files: `packages/web-components/core/icons-phosphor.js` (+38 LOC, -2 LOC).
|
|
8
|
+
|
|
9
|
+
### Docs
|
|
10
|
+
- **Quick-start + migration guide examples corrected (FB-09).** `docs/guides/02-quick-start.md` lines ~76-81 (boot sequence) and ~126-131 (the dedicated `installIconLoadersForRegistered` section) both showed the flat-glob form passed directly to `installIconLoadersForRegistered`. Both now wrap the glob in `{ regular: … }` to match the canonical contract. New `### Pitfall: flat glob silently auto-promoted (v0.6.15+)` section explains the FB-07 auto-promote behavior and when the per-weight form is strictly required (bold/fill/etc.). `docs/MIGRATION GUIDE.md` lines ~279-282 (the v0.5.3 §154 recommended upgrade example) had the same flat-glob bug — corrected. The skill `adia-ui-kit` v2.9.0 ships the same scaffold-template correction.
|
|
11
|
+
|
|
12
|
+
### Verification
|
|
13
|
+
- `verify:traits` 56/56 clean.
|
|
14
|
+
- `components.mjs --verify` clean (142 files up-to-date).
|
|
15
|
+
- `smoke:engines` green; `smoke:register-engine` 11/11.
|
|
16
|
+
- `npm run check` omnibus PASSES (LightningCSS minify, link check, primitive composes coverage, demo shell imports, phosphor wiring, MCP server smoke 3/3, register-engine 11/11, traits 56/56).
|
|
17
|
+
- `eval:diff --engine zettel` cov=49% / avg=90 (baseline-identical).
|
|
18
|
+
- Browser-verified four cases against `installIconLoaders`: flat glob → 1 warn + install; garbage shape → 1 error + abort; null → 1 error + abort; per-weight map → silent. Live `/site/examples/admin-dashboard` shows 406/412 icon-ui elements with rendered SVGs — same baseline as pre-fix; substrate change non-regressing.
|
|
19
|
+
|
|
20
|
+
## [0.6.14] — 2026-05-21
|
|
21
|
+
|
|
22
|
+
### Maintenance
|
|
23
|
+
- **Lockstep version bump only.** No source changes in this package; bumped to maintain the 9-package version coherence enforced by `scripts/release/check-lockstep.mjs`. Substantive v0.6.14 work shipped in `@adia-ai/web-modules` — `<admin-page-header>` now uses `var(--page-content-header-bg)` (= `--a-canvas-2`) + `var(--a-shadow-sm)` so the page-header band reads as elevated chrome over the body canvas. See `packages/web-modules/CHANGELOG.md#0614--2026-05-21` for details.
|
|
24
|
+
|
|
3
25
|
## [0.6.13] — 2026-05-20
|
|
4
26
|
|
|
5
27
|
### Maintenance
|
package/core/icons-phosphor.js
CHANGED
|
@@ -65,11 +65,50 @@ try {
|
|
|
65
65
|
duotone: import.meta.glob('/node_modules/@phosphor-icons/core/assets/duotone/*.svg', { query: '?raw', import: 'default' }),
|
|
66
66
|
};
|
|
67
67
|
hasViteGlob = true;
|
|
68
|
-
} catch {
|
|
69
|
-
|
|
68
|
+
} catch (err) {
|
|
69
|
+
// FB-08: distinguish "no Vite at all" (expected, ReferenceError) from
|
|
70
|
+
// every other error (unexpected, worth logging). ReferenceError is the
|
|
71
|
+
// signal that `import.meta.glob` doesn't exist — i.e. non-Vite static
|
|
72
|
+
// serving, which is what the manifest-fetch fallback below was designed
|
|
73
|
+
// for. Anything else got swallowed silently by the previous bare catch.
|
|
74
|
+
if (err && !(err instanceof ReferenceError)) {
|
|
75
|
+
console.warn(
|
|
76
|
+
`[icons-phosphor] import.meta.glob threw an unexpected error ` +
|
|
77
|
+
`(not a vanilla ReferenceError): ${err.message}. ` +
|
|
78
|
+
`Falling back to manifest fetch. If you're using Vite, this likely ` +
|
|
79
|
+
`means a misconfigured plugin order or glob root.`
|
|
80
|
+
);
|
|
81
|
+
}
|
|
70
82
|
}
|
|
71
83
|
|
|
72
84
|
if (hasViteGlob) {
|
|
85
|
+
// FB-08: detect the silent-empty-glob case — `import.meta.glob` returns
|
|
86
|
+
// `{}` when zero files match (it does NOT throw). The previous behavior
|
|
87
|
+
// installed empty per-weight maps and the consumer saw an empty icon
|
|
88
|
+
// registry with no diagnostic. This happens when the consumer's Vite
|
|
89
|
+
// root sits below `node_modules`, or with pnpm/yarn-berry virtual paths,
|
|
90
|
+
// or when this file runs from inside a published package directory
|
|
91
|
+
// (its absolute-style glob is resolved relative to the Vite root, not
|
|
92
|
+
// this file's directory).
|
|
93
|
+
const totalIcons = Object.values(weightModules).reduce(
|
|
94
|
+
(sum, weight) => sum + Object.keys(weight).length, 0
|
|
95
|
+
);
|
|
96
|
+
if (totalIcons === 0) {
|
|
97
|
+
console.warn(
|
|
98
|
+
`[icons-phosphor] No Phosphor icons matched the auto-install glob ` +
|
|
99
|
+
`\`/node_modules/@phosphor-icons/core/assets/<weight>/*.svg\`. ` +
|
|
100
|
+
`This usually means your Vite root sits below node_modules, you use ` +
|
|
101
|
+
`pnpm/yarn-berry virtual paths, or this module is loaded from a ` +
|
|
102
|
+
`published package directory. Install loaders manually from your app entry:\n` +
|
|
103
|
+
` import { installIconLoaders } from '@adia-ai/web-components/core/icons';\n` +
|
|
104
|
+
` installIconLoaders({\n` +
|
|
105
|
+
` regular: import.meta.glob(\n` +
|
|
106
|
+
` '../node_modules/@phosphor-icons/core/assets/regular/*.svg',\n` +
|
|
107
|
+
` { query: '?raw', import: 'default', eager: true }\n` +
|
|
108
|
+
` ),\n` +
|
|
109
|
+
` });`
|
|
110
|
+
);
|
|
111
|
+
}
|
|
73
112
|
installIconLoaders(weightModules);
|
|
74
113
|
} else {
|
|
75
114
|
// Non-Vite static serving: fetch the build-time manifest in the
|
package/core/icons.js
CHANGED
|
@@ -103,8 +103,27 @@ export function listIcons() {
|
|
|
103
103
|
// `installIconLoaders` (called by `icons-phosphor.js` in the zero-config path).
|
|
104
104
|
|
|
105
105
|
const EMPTY_WEIGHTS = { regular: {}, thin: {}, light: {}, bold: {}, fill: {}, duotone: {} };
|
|
106
|
+
const WEIGHT_KEYS = new Set(['regular', 'thin', 'light', 'bold', 'fill', 'duotone']);
|
|
106
107
|
let weightModules = EMPTY_WEIGHTS;
|
|
107
108
|
|
|
109
|
+
/* Shape-detect a flat `import.meta.glob` result: zero recognized weight
|
|
110
|
+
keys (`regular`/`thin`/`light`/`bold`/`fill`/`duotone`) AND at least one
|
|
111
|
+
key that looks like an SVG path (`.svg` suffix). Used to auto-promote
|
|
112
|
+
the documented flat-glob form (FB-09) to `{ regular: <flat> }` so the
|
|
113
|
+
substrate stops silently failing on the most common malformed shape
|
|
114
|
+
(FB-07). */
|
|
115
|
+
function isFlatGlobShape(modules) {
|
|
116
|
+
const keys = Object.keys(modules);
|
|
117
|
+
if (keys.length === 0) return false;
|
|
118
|
+
for (const k of keys) if (WEIGHT_KEYS.has(k)) return false;
|
|
119
|
+
for (const k of keys) if (k.endsWith('.svg')) return true;
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/* Warn-once cache so the FB-07 auto-promote message doesn't spam in HMR
|
|
124
|
+
environments where `installIconLoaders` re-runs on every hot reload. */
|
|
125
|
+
const warnedShapes = new WeakSet();
|
|
126
|
+
|
|
108
127
|
/* `whenIconRegistryReady` lets a component defer icon-name decisions until
|
|
109
128
|
the registry is sync-checkable. <icon-ui> doesn't need it — it owns the
|
|
110
129
|
<name → svg> render and re-stamps elements when the loader map arrives.
|
|
@@ -128,7 +147,51 @@ export const whenIconRegistryReady = new Promise((r) => { resolveRegistryReady =
|
|
|
128
147
|
* before loaders arrived. Idempotent — calling it twice replaces the map.
|
|
129
148
|
*/
|
|
130
149
|
export function installIconLoaders(modules) {
|
|
131
|
-
|
|
150
|
+
// FB-07: validate shape before installing. The previous behavior was
|
|
151
|
+
// `weightModules = { ...EMPTY_WEIGHTS, ...modules }` which silently
|
|
152
|
+
// accepted any object — including the documented-but-broken flat
|
|
153
|
+
// path→svg glob (FB-09), which spread path keys at the top level
|
|
154
|
+
// and left every weight slot empty. Three shapes are now recognized:
|
|
155
|
+
//
|
|
156
|
+
// 1. Per-weight map { regular: { path: svg }, bold: { ... }, ... }
|
|
157
|
+
// — canonical, installs verbatim.
|
|
158
|
+
// 2. Flat glob { '/path/foo.svg': '<svg>', ... } — auto-promoted to
|
|
159
|
+
// { regular: <flat> } with a one-time warn so the caller knows
|
|
160
|
+
// to wrap explicitly (and so bold/fill/etc. aren't silently lost).
|
|
161
|
+
// 3. Anything else — logged via console.error, install aborted.
|
|
162
|
+
if (!modules || typeof modules !== 'object') {
|
|
163
|
+
console.error(
|
|
164
|
+
`[icons] installIconLoaders: expected per-weight map { regular: { ... }, bold: { ... }, ... }, ` +
|
|
165
|
+
`got ${modules === null ? 'null' : typeof modules}. Install aborted; registry unchanged.`
|
|
166
|
+
);
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
let installable = modules;
|
|
170
|
+
if (isFlatGlobShape(modules)) {
|
|
171
|
+
if (!warnedShapes.has(modules)) {
|
|
172
|
+
warnedShapes.add(modules);
|
|
173
|
+
console.warn(
|
|
174
|
+
`[icons] installIconLoaders received a flat path→svg map. ` +
|
|
175
|
+
`Auto-promoting to { regular: <flat> }. Wrap explicitly to silence ` +
|
|
176
|
+
`this warning and to load bold/fill/etc. weights:\n` +
|
|
177
|
+
` installIconLoaders({ regular: import.meta.glob('.../regular/*.svg', { ... }) });`
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
installable = { regular: modules };
|
|
181
|
+
} else {
|
|
182
|
+
const hasAnyWeight = Object.keys(modules).some(k => WEIGHT_KEYS.has(k));
|
|
183
|
+
if (!hasAnyWeight) {
|
|
184
|
+
const sampleKeys = Object.keys(modules).slice(0, 5).join(', ');
|
|
185
|
+
console.error(
|
|
186
|
+
`[icons] installIconLoaders: shape unrecognized. ` +
|
|
187
|
+
`Expected per-weight map keyed by regular/thin/light/bold/fill/duotone, ` +
|
|
188
|
+
`or a flat path→svg map. Received keys: ${sampleKeys || '(empty)'}. ` +
|
|
189
|
+
`Install aborted; registry unchanged.`
|
|
190
|
+
);
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
weightModules = { ...EMPTY_WEIGHTS, ...installable };
|
|
132
195
|
registryReady = true;
|
|
133
196
|
if (typeof document !== 'undefined') {
|
|
134
197
|
for (const el of document.querySelectorAll('icon-ui[name]')) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adia-ai/web-components",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.15",
|
|
4
4
|
"description": "AdiaUI web components \u2014 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",
|