@adia-ai/web-components 0.7.27 → 0.7.28
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 +18 -0
- package/components/chart/chart.a2ui.json +1 -1
- package/components/chart/chart.yaml +2 -0
- package/components/kbd/kbd.a2ui.json +4 -0
- package/components/kbd/kbd.d.ts +2 -0
- package/components/kbd/kbd.yaml +5 -0
- package/components/table/cell-types.js +31 -2
- package/components/table/table.a2ui.json +1 -1
- package/components/table/table.test.js +37 -0
- package/components/table/table.yaml +2 -0
- package/core/markdown.js +1 -1
- package/dist/host.min.css +1 -1
- package/dist/host.sheet.js +1 -1
- package/dist/theme-provider.min.js +1 -1
- package/dist/web-components.min.css +1 -1
- package/dist/web-components.min.js +57 -57
- package/dist/web-components.sheet.js +1 -1
- package/package.json +1 -1
- package/styles/resets.css +15 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,22 @@
|
|
|
1
1
|
# Changelog — @adia-ai/web-components
|
|
2
|
+
## [0.7.28] — 2026-07-14
|
|
3
|
+
|
|
4
|
+
### Added
|
|
5
|
+
- **`table-ui` (`components/table/cell-types.js`) — `markdown` cell type: inline `` `code` ``/**bold**/*italic*/`[link](href)` rendered as real elements, not a plain string.** TKT-0008 (site-a2ui re-verification, direction 1): docs reference tables (props/API tables) mix prose with multiple inline `<code>` spans per cell — content the `{columns, data}` JSON contract previously couldn't carry, forcing a preserved-HTML fallback that dropped the table from the A2UI graph entirely. Renders via `core/markdown.js`'s `inline()` (now exported) — the exact encode/decode pairing the docs-transpiler's own `convertInline()` already produces elsewhere in the pipeline. `[title]` carries the tag-stripped plain text for the truncation tooltip. New unit suite in `table.test.js` (3 cases).
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
- **`core/markdown.js` — `inline()` is now exported.** Was module-private; reused by `cell-types.js`'s new `markdown` cell type as the client-side half of the docs-transpiler's `convertInline()` contract. No behavior change to existing callers.
|
|
9
|
+
|
|
10
|
+
### Fixed — TKT-0010, corpus admission-validation content gaps
|
|
11
|
+
- **`kbd.yaml` — declares a `textContent` prop.** Every other text-bearing leaf (`Text`, `Code`) already declares one; `Kbd` was missing it, so the transpiler's unconditional `textContent` extraction for leaf types produced a value the catalog schema rejected as an unevaluated property on every harvested `<kbd-ui>` chunk (12 instances). Purely a schema declaration gap — no behavior change (the transpiler already extracted the value correctly).
|
|
12
|
+
- **`chart.yaml`/`table.yaml` — `data` prop declares `items: {type: object}`.** Opts these two dynamic array props into `@adia-ai/a2ui-corpus`'s new `DynamicObjectList` schema (array-of-object) instead of the default `DynamicStringList` (array-of-string) — the wrong shape for chart/table row records. Paired with a transpiler fix in `@adia-ai/a2ui-compose` (the attribute value was never actually parsed); see that package's CHANGELOG.
|
|
13
|
+
|
|
14
|
+
### Fixed — GH #224, SVG zero-viewport silent non-render
|
|
15
|
+
- **`styles/resets.css` — `svg` gets its own reset rule, dropping `max-inline-size`/`block-size` instead of sharing `img`/`picture`/`video`/`canvas`'s `max-inline-size: 100%; block-size: auto` rule.** Per the SVG spec, a zero-size viewport — exactly what `max-inline-size: 100%` computes to inside a zero-intrinsic-size ancestor (the common `width:0; height:0; transform:scale(s)` pattern for a CSS-scaled canvas/scene) — makes the element **not render at all**, not "render at 0 visual size": silent, no console warning. `img`/`picture`/`video`/`canvas` don't share this failure mode. Components that embed SVG (`icon-ui`, etc.) already size it explicitly in their own scoped CSS and are unaffected either way (verified: no component CSS relies on the global rule's sizing behavior). Verified via the full web-modules test suite + a manual repro check against the reporting issue's own reproduction case (no dedicated new test — a global CSS reset rule).
|
|
16
|
+
|
|
17
|
+
### Maintenance
|
|
18
|
+
- **`dist/` CDN bundles rebuilt** (`host.min.css`, `host.sheet.js`, `theme-provider.min.js`, `web-components.min.{css,js}`, `web-components.sheet.js`) to inline the `resets.css` fix above.
|
|
19
|
+
|
|
2
20
|
## [0.7.27] — 2026-07-12
|
|
3
21
|
|
|
4
22
|
Fixes harvested from the /site → A2UI docs migration's live operator reports (TKT-0002…0006) — each was a real framework defect the migration surfaced, not a docs-only issue — plus the router race that three separate flake classes traced back to.
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
},
|
|
56
56
|
"data": {
|
|
57
57
|
"description": "JS property (set programmatically — `el.data = [...]`). An array of plain objects; each object's keys are named by the `x` and `y` attributes — e.g. `<chart-ui x=\"month\" y=\"revenue\">` consumes `[{month:'Jan', revenue:3200}, {month:'Feb', revenue:4100}]`. The Chart.js `{labels, datasets}` envelope is NOT chart-ui's API — passing it (or any non-array value) renders an empty chart. May also be supplied declaratively as a JSON-array `data=\"[…]\"` attribute, hydrated once at connect. Custom accessor on the element class, not a reflected attribute.",
|
|
58
|
-
"$ref": "common_types.json#/$defs/
|
|
58
|
+
"$ref": "common_types.json#/$defs/DynamicObjectList"
|
|
59
59
|
},
|
|
60
60
|
"format": {
|
|
61
61
|
"description": "Number-format mode applied to axis labels + value overlays + donut total + gauge value + treemap value + funnel value + internal tooltip. `abbr` is the legacy 1.2K / 3M format; `decimal` fixes 2 decimals; `currency` prefixes via `--chart-currency-prefix` token (default \"$\"); `percent` multiplies × 100 and adds a % suffix.",
|
|
@@ -122,6 +122,8 @@ props:
|
|
|
122
122
|
hydrated once at connect. Custom accessor on the element class, not a
|
|
123
123
|
reflected attribute.
|
|
124
124
|
type: array
|
|
125
|
+
items:
|
|
126
|
+
type: object
|
|
125
127
|
default: []
|
|
126
128
|
dynamic: true # JS-set collection prop with a custom setter — deliberately not in static properties
|
|
127
129
|
events:
|
|
@@ -25,6 +25,10 @@
|
|
|
25
25
|
"lg"
|
|
26
26
|
],
|
|
27
27
|
"default": ""
|
|
28
|
+
},
|
|
29
|
+
"textContent": {
|
|
30
|
+
"description": "Key label text, extracted from innerHTML (e.g. \"Ctrl+K\"). The main payload field for Kbd components extracted from HTML — mirrors Text/Code's textContent prop.",
|
|
31
|
+
"$ref": "common_types.json#/$defs/DynamicString"
|
|
28
32
|
}
|
|
29
33
|
},
|
|
30
34
|
"required": [
|
package/components/kbd/kbd.d.ts
CHANGED
|
@@ -15,4 +15,6 @@ import { UIElement } from '../../core/element.js';
|
|
|
15
15
|
export class UIKbd extends UIElement {
|
|
16
16
|
/** Sizing scale: sm, md (default), lg. */
|
|
17
17
|
size: 'sm' | 'md' | 'lg';
|
|
18
|
+
/** Key label text, extracted from innerHTML (e.g. "Ctrl+K"). The main payload field for Kbd components extracted from HTML — mirrors Text/Code's textContent prop. */
|
|
19
|
+
textContent: string;
|
|
18
20
|
}
|
package/components/kbd/kbd.yaml
CHANGED
|
@@ -19,6 +19,11 @@ props:
|
|
|
19
19
|
- md
|
|
20
20
|
- lg
|
|
21
21
|
reflect: true
|
|
22
|
+
textContent:
|
|
23
|
+
description: Key label text, extracted from innerHTML (e.g. "Ctrl+K"). The main payload field for Kbd components extracted from HTML — mirrors Text/Code's textContent prop.
|
|
24
|
+
type: string
|
|
25
|
+
default: ''
|
|
26
|
+
dynamic: true
|
|
22
27
|
events: {}
|
|
23
28
|
slots:
|
|
24
29
|
default:
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// cell-types.js - Built-in cell type registry for table-ui
|
|
2
2
|
|
|
3
|
+
import { inline } from '../../core/markdown.js';
|
|
4
|
+
|
|
3
5
|
const cellTypes = {};
|
|
4
6
|
|
|
5
7
|
function registerCellType(name, config) {
|
|
@@ -233,7 +235,34 @@ registerCellType('link', {
|
|
|
233
235
|
sortFn: 'alphanumeric',
|
|
234
236
|
});
|
|
235
237
|
|
|
236
|
-
// 11.
|
|
238
|
+
// 11. markdown — TKT-0008: cells with inline `code`/**bold**/*italic*/
|
|
239
|
+
// [link](href) content the docs-transpiler couldn't express as a plain
|
|
240
|
+
// string (table.yaml {columns,data} contract carries plain values; this
|
|
241
|
+
// is the one escape hatch for INLINE-safe rich text, reusing the same
|
|
242
|
+
// inline() converter core/markdown.js already round-trips against
|
|
243
|
+
// scripts/build/lib/docs-transpiler.mjs's convertInline() — the two are
|
|
244
|
+
// paired encode/decode halves of one contract, not independent parsers).
|
|
245
|
+
// Block-level content (nested tables, component tags, colspan/rowspan)
|
|
246
|
+
// stays out of scope; those still fall back to the preserved-HTML Code
|
|
247
|
+
// panel synthesizeTable already emits.
|
|
248
|
+
registerCellType('markdown', {
|
|
249
|
+
render(value, row, cell) {
|
|
250
|
+
let s = cell.firstElementChild;
|
|
251
|
+
if (!s || s.tagName !== 'SPAN') {
|
|
252
|
+
cell.replaceChildren();
|
|
253
|
+
s = cell.appendChild(document.createElement('span'));
|
|
254
|
+
}
|
|
255
|
+
s.innerHTML = inline(String(value ?? ''));
|
|
256
|
+
cell.title = s.textContent;
|
|
257
|
+
},
|
|
258
|
+
format(value) {
|
|
259
|
+
return String(value ?? '');
|
|
260
|
+
},
|
|
261
|
+
align: 'left',
|
|
262
|
+
sortFn: 'alphanumeric',
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
// 12. progress
|
|
237
266
|
registerCellType('progress', {
|
|
238
267
|
render(value, row, cell) {
|
|
239
268
|
let wrapper = cell.querySelector('row-ui');
|
|
@@ -262,7 +291,7 @@ registerCellType('progress', {
|
|
|
262
291
|
sortFn: 'numeric',
|
|
263
292
|
});
|
|
264
293
|
|
|
265
|
-
//
|
|
294
|
+
// 13. actions
|
|
266
295
|
registerCellType('actions', {
|
|
267
296
|
render(value, row, cell, meta) {
|
|
268
297
|
const actions = meta?.actions || [];
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
},
|
|
23
23
|
"data": {
|
|
24
24
|
"description": "Row records. Array of plain objects keyed to columns[].key.",
|
|
25
|
-
"$ref": "common_types.json#/$defs/
|
|
25
|
+
"$ref": "common_types.json#/$defs/DynamicObjectList"
|
|
26
26
|
},
|
|
27
27
|
"density": {
|
|
28
28
|
"description": "Controls cell padding and row height. 'compact' for dense data, 'standard' for default spacing, 'comfortable' for spacious rows.",
|
|
@@ -389,3 +389,40 @@ describe('table-ui — F6 per-row expand suppression (rowExpandable)', () => {
|
|
|
389
389
|
expect(el.expanded).toContain(1);
|
|
390
390
|
});
|
|
391
391
|
});
|
|
392
|
+
|
|
393
|
+
describe('table-ui — "markdown" cell type (TKT-0008)', () => {
|
|
394
|
+
it('renders inline `code`/**bold**/*italic*/[link](href) as real elements, not literal syntax', async () => {
|
|
395
|
+
const el = mount('<table-ui></table-ui>');
|
|
396
|
+
el.columns = [{ key: 'desc', label: 'Description', type: 'markdown' }];
|
|
397
|
+
el.data = [{ desc: 'Semantic status: `new` | `updated` | **beta** or *deprecated*, see [docs](/site/components/badge).' }];
|
|
398
|
+
await raf();
|
|
399
|
+
|
|
400
|
+
const cell = el.querySelector('[role="gridcell"][data-key="desc"]');
|
|
401
|
+
expect([...cell.querySelectorAll('code')].map((c) => c.textContent)).toEqual(['new', 'updated']);
|
|
402
|
+
expect(cell.querySelector('strong').textContent).toBe('beta');
|
|
403
|
+
expect(cell.querySelector('em').textContent).toBe('deprecated');
|
|
404
|
+
expect(cell.querySelector('a').getAttribute('href')).toBe('/site/components/badge');
|
|
405
|
+
expect(cell.textContent).not.toMatch(/`|\*\*|\[docs\]/); // no literal markdown syntax leaked through
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
it('sets [title] to the plain-text (tag-stripped) version, for the truncation tooltip', async () => {
|
|
409
|
+
const el = mount('<table-ui></table-ui>');
|
|
410
|
+
el.columns = [{ key: 'prop', label: 'Prop', type: 'markdown' }];
|
|
411
|
+
el.data = [{ prop: '`variant`' }];
|
|
412
|
+
await raf();
|
|
413
|
+
|
|
414
|
+
const cell = el.querySelector('[role="gridcell"][data-key="prop"]');
|
|
415
|
+
expect(cell.title).toBe('variant');
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
it('a plain value with no markdown syntax renders as ordinary text (no stray elements)', async () => {
|
|
419
|
+
const el = mount('<table-ui></table-ui>');
|
|
420
|
+
el.columns = [{ key: 'desc', label: 'Description', type: 'markdown' }];
|
|
421
|
+
el.data = [{ desc: 'Plain sentence, no special characters.' }];
|
|
422
|
+
await raf();
|
|
423
|
+
|
|
424
|
+
const cell = el.querySelector('[role="gridcell"][data-key="desc"]');
|
|
425
|
+
expect(cell.querySelector('code, strong, em, a')).toBeNull();
|
|
426
|
+
expect(cell.textContent).toBe('Plain sentence, no special characters.');
|
|
427
|
+
});
|
|
428
|
+
});
|
|
@@ -27,6 +27,8 @@ props:
|
|
|
27
27
|
data:
|
|
28
28
|
description: Row records. Array of plain objects keyed to columns[].key.
|
|
29
29
|
type: array
|
|
30
|
+
items:
|
|
31
|
+
type: object
|
|
30
32
|
default: []
|
|
31
33
|
dynamic: true # JS-set collection prop with a custom setter — deliberately not in static properties
|
|
32
34
|
density:
|
package/core/markdown.js
CHANGED
|
@@ -91,7 +91,7 @@ export function renderMarkdown(src) {
|
|
|
91
91
|
const CODE_PH = (n) => `\0CODE${n}\0`;
|
|
92
92
|
const CODE_PH_RE = /\0CODE(\d+)\0/g;
|
|
93
93
|
|
|
94
|
-
function inline(text) {
|
|
94
|
+
export function inline(text) {
|
|
95
95
|
const escaped = esc(text);
|
|
96
96
|
|
|
97
97
|
// 1. Extract inline-code spans FIRST and protect their (already-escaped,
|