@adia-ai/web-components 0.6.25 → 0.6.27

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 CHANGED
@@ -1,5 +1,23 @@
1
1
  # Changelog — @adia-ai/web-components
2
2
 
3
+ ## [0.6.27] — 2026-05-22
4
+
5
+ ### Added — `chart-ui[loading]` skeleton placeholder (§FB-12)
6
+
7
+ - **`<chart-ui loading>` shows a `<skeleton-ui>` placeholder** instead of the chart body while data is being fetched. Preserves the element's aspect-ratio dimensions so the skeleton occupies the same space the chart will fill once data arrives. Parity with `stat-ui[loading]` and `table-ui[loading]` (both shipped v0.6.18). Closes the remaining open item from FEEDBACK-12. File: `components/chart/class.js` + `components/chart/chart.yaml`.
8
+
9
+ ## [0.6.26] — 2026-05-22
10
+
11
+ ### Added — regression tests for FB-46 (select-ui) and FB-47 (table-ui)
12
+
13
+ - **`components/select/select.test.js`** (new, 4 tests) — locks the FB-46 `[multiple]` pre-init fix: `<option selected>` captures all values, `.value="a,b"` syncs `aria-selected` via Set, single-select backward compat preserved.
14
+ - **`components/table/table.test.js`** (2 new tests) — locks the FB-47 Enter-key fix: Enter on a focused body cell fires `cell-click` with correct row data; Enter on a header cell does NOT fire `cell-click` (sort path only).
15
+ - **`components/select/select.examples.html`** — multi-select pre-selected demo variants added (option-selected form and value= form).
16
+
17
+ ### Maintenance
18
+
19
+ - Lockstep version bump. Substantive v0.6.26 source fix: `editor-sidebar` `#syncCollapsed()` 0-width guard applied (FB-42/FB-48, `@adia-ai/web-modules`). See `packages/web-modules/CHANGELOG.md`.
20
+
3
21
  ## [0.6.25] — 2026-05-22
4
22
 
5
23
  ### Fixed — `table-ui` Enter key activates focused body cell (FB-47)
@@ -392,10 +410,6 @@ Scope: custom elements, core (`AdiaElement` + reactivity + templates),
392
410
  trait system, style tokens, patterns (composite elements). The A2UI
393
411
  runtime ships in the sibling `@adia-ai/a2ui-runtime` package
394
412
  (renamed from `@adia-ai/a2ui-utils` in v0.3.0) as of `0.0.4`.
395
- ## [Unreleased]
396
-
397
- _No pending changes._
398
-
399
413
  ## [0.6.4] - 2026-05-18
400
414
 
401
415
  ### v0.6.4 — Lockstep ride-along
@@ -102,6 +102,11 @@
102
102
  "type": "boolean",
103
103
  "default": false
104
104
  },
105
+ "loading": {
106
+ "description": "Show a skeleton placeholder instead of the chart body. Set to true while data is being fetched; clear once data arrives. Preserves the element's aspect-ratio dimensions so the skeleton occupies the same space the chart will fill. Parity with stat-ui[loading] and table-ui[loading] (§FB-12, v0.6.27).",
107
+ "type": "boolean",
108
+ "default": false
109
+ },
105
110
  "radius": {
106
111
  "description": "Bar corner radius (null = let CSS tokens decide)",
107
112
  "type": "number",
@@ -36,6 +36,8 @@ export class UIChart extends UIElement {
36
36
  hideGrid: boolean;
37
37
  /** Hide value labels */
38
38
  hideValues: boolean;
39
+ /** Show a skeleton placeholder instead of the chart body. Set to true while data is being fetched; clear once data arrives. Preserves the element's aspect-ratio dimensions so the skeleton occupies the same space the chart will fill. Parity with stat-ui[loading] and table-ui[loading] (§FB-12, v0.6.27). */
40
+ loading: boolean;
39
41
  /** Bar corner radius (null = let CSS tokens decide) */
40
42
  radius: number;
41
43
  /** Chart size */
@@ -103,6 +103,16 @@ props:
103
103
  description: Line smoothing factor
104
104
  type: number
105
105
  default: 0.4
106
+ loading:
107
+ description: >-
108
+ Show a skeleton placeholder instead of the chart body. Set to true
109
+ while data is being fetched; clear once data arrives. Preserves the
110
+ element's aspect-ratio dimensions so the skeleton occupies the same
111
+ space the chart will fill. Parity with stat-ui[loading] and
112
+ table-ui[loading] (§FB-12, v0.6.27).
113
+ type: boolean
114
+ default: false
115
+ reflect: true
106
116
  heading:
107
117
  description: >-
108
118
  DEPRECATED (OD-CHART-02). Place chart titles in an enclosing
@@ -226,6 +226,7 @@ export class UIChart extends UIElement {
226
226
  aspect: { type: String, default: 'std', reflect: true },
227
227
  size: { type: String, default: '', reflect: true },
228
228
  format: { type: String, default: 'abbr', reflect: true },
229
+ loading: { type: Boolean, default: false, reflect: true },
229
230
  };
230
231
 
231
232
  static template = () => null;
@@ -366,6 +367,23 @@ export class UIChart extends UIElement {
366
367
  }
367
368
 
368
369
  render() {
370
+ // §FB-12: loading state — replace chart body with a skeleton placeholder.
371
+ // Preserves the element's dimensions (aspect ratio CSS stays in effect)
372
+ // so the skeleton occupies the same space the chart will fill.
373
+ if (this.loading) {
374
+ let sk = this.querySelector('skeleton-ui[data-chart-skel]');
375
+ if (!sk) {
376
+ sk = document.createElement('skeleton-ui');
377
+ sk.setAttribute('data-chart-skel', '');
378
+ sk.style.cssText = 'display:block;width:100%;height:100%;min-height:4rem;border-radius:var(--a-radius-md)';
379
+ }
380
+ this.innerHTML = '';
381
+ this.appendChild(sk);
382
+ return;
383
+ }
384
+ // Remove skeleton if loading was cleared
385
+ const sk = this.querySelector('skeleton-ui[data-chart-skel]');
386
+ if (sk) sk.remove();
369
387
  this.#renderChart();
370
388
  }
371
389
 
@@ -236,3 +236,50 @@ describe('table-ui — wrap default + opt-in', () => {
236
236
  }
237
237
  });
238
238
  });
239
+
240
+ describe('table-ui — FB-47 keyboard: Enter activates focused body cell', () => {
241
+ beforeEach(() => { document.body.innerHTML = ''; });
242
+
243
+ it('Enter on a focused body cell fires cell-click with the row data', async () => {
244
+ const el = mount('<table-ui></table-ui>');
245
+ el.columns = COLS;
246
+ el.data = ROWS;
247
+ await raf();
248
+
249
+ // ArrowDown from null initialises #focusedCell to {row:0,col:0} then
250
+ // increments to {row:1,col:0} and calls #updateFocus → [data-focused] on
251
+ // the second body row cell.
252
+ el.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown', bubbles: true }));
253
+ await tick();
254
+
255
+ let fired = null;
256
+ el.addEventListener('cell-click', (e) => { fired = e.detail; });
257
+
258
+ el.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', bubbles: true }));
259
+ await tick();
260
+
261
+ expect(fired).not.toBeNull();
262
+ expect(fired.row).toMatchObject({ id: 2, name: 'Bob' }); // index 1 = second row
263
+ });
264
+
265
+ it('Enter on a focused header cell does NOT fire cell-click (sort path only)', async () => {
266
+ const el = mount('<table-ui></table-ui>');
267
+ el.columns = COLS;
268
+ el.data = ROWS;
269
+ await raf();
270
+
271
+ // ArrowUp from null initialises to {row:0,col:0} then decrements to
272
+ // {row:-1,col:0} → header row.
273
+ el.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowUp', bubbles: true }));
274
+ await tick();
275
+
276
+ let cellClickFired = false;
277
+ el.addEventListener('cell-click', () => { cellClickFired = true; });
278
+
279
+ el.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', bubbles: true }));
280
+ await tick();
281
+
282
+ // Header Enter triggers sort (or no-op if not sortable), never cell-click.
283
+ expect(cellClickFired).toBe(false);
284
+ });
285
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adia-ai/web-components",
3
- "version": "0.6.25",
3
+ "version": "0.6.27",
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",