@adia-ai/web-components 0.5.4 → 0.5.5
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/components/accordion/accordion-item.a2ui.json +50 -0
- package/components/accordion/accordion-item.yaml +27 -0
- package/components/action-list/action-item.a2ui.json +63 -0
- package/components/action-list/action-item.yaml +37 -0
- package/components/avatar/avatar-group.a2ui.json +50 -0
- package/components/avatar/avatar-group.yaml +26 -0
- package/components/avatar/avatar.a2ui.json +4 -1
- package/components/avatar/avatar.yaml +7 -0
- package/components/button/class.js +39 -0
- package/components/chart/chart.a2ui.json +4 -2
- package/components/list/list-item.a2ui.json +53 -0
- package/components/list/list-item.yaml +29 -0
- package/components/select/class.js +14 -0
- package/components/select/select.a2ui.json +5 -0
- package/components/select/select.css +10 -0
- package/components/select/select.yaml +5 -0
- package/components/slider/class.js +58 -0
- package/components/slider/slider.a2ui.json +10 -0
- package/components/slider/slider.css +13 -0
- package/components/slider/slider.yaml +10 -0
- package/components/switch/class.js +18 -4
- package/components/switch/switch.css +10 -0
- package/components/tabs/tab.a2ui.json +58 -0
- package/components/tabs/tab.yaml +33 -0
- package/components/timeline/timeline-item.a2ui.json +76 -0
- package/components/timeline/timeline-item.yaml +47 -0
- package/components/tree/class.js +91 -0
- package/components/tree/tree-item.a2ui.json +65 -0
- package/components/tree/tree-item.yaml +41 -0
- package/components/tree/tree.a2ui.json +15 -0
- package/components/tree/tree.css +18 -0
- package/components/tree/tree.yaml +10 -0
- package/core/template.js +21 -3
- package/package.json +2 -2
|
@@ -134,4 +134,17 @@
|
|
|
134
134
|
:scope[disabled] [slot="fill"] { background: var(--slider-fill-bg-disabled); }
|
|
135
135
|
:scope[disabled] [slot="thumb"] { cursor: not-allowed; background: var(--slider-thumb-bg-disabled); }
|
|
136
136
|
:scope[disabled] [slot="thumb"]:hover { box-shadow: none; }
|
|
137
|
+
|
|
138
|
+
/* ── Hint (§184, v0.5.5, FEEDBACK-08 §7) ──
|
|
139
|
+
Small caption rendered beneath the track. aria-describedby is
|
|
140
|
+
wired on the host in class.js so screen readers announce this
|
|
141
|
+
as a description (distinct from aria-label, which comes from
|
|
142
|
+
[label]). Uses the same muted typography as field-ui's hint. */
|
|
143
|
+
[slot="hint"] {
|
|
144
|
+
display: block;
|
|
145
|
+
margin-top: var(--slider-hint-mt, var(--a-space-1));
|
|
146
|
+
font-size: var(--slider-hint-size, var(--a-fine-size));
|
|
147
|
+
color: var(--slider-hint-fg, var(--a-fg-muted));
|
|
148
|
+
line-height: var(--slider-hint-lh, 1.4);
|
|
149
|
+
}
|
|
137
150
|
}
|
|
@@ -51,6 +51,16 @@ props:
|
|
|
51
51
|
description: Current slider value
|
|
52
52
|
type: number
|
|
53
53
|
default: 50
|
|
54
|
+
throttle:
|
|
55
|
+
description: |-
|
|
56
|
+
§184 (v0.5.5, FEEDBACK-08 §4): when > 0, debounce the `input` event by this many milliseconds. Value updates + visual feedback remain immediate; only event dispatch accumulates. Pending input flushes BEFORE `change` so consumers always see input→…→input→change ordering. throttle="0" (default) preserves the pre-§184 every-pointer-move-fires-input behavior. Common values: 50-100ms for palette regen / shader compile / large list reflow.
|
|
57
|
+
type: number
|
|
58
|
+
default: 0
|
|
59
|
+
hint:
|
|
60
|
+
description: |-
|
|
61
|
+
§184 (v0.5.5, FEEDBACK-08 §7): small caption rendered beneath the slider track. Sets `aria-describedby` on the host so screen readers announce it as a description (distinct from `aria-label`, which comes from `label`). Does not conflict with the in-component `label`. Use for semantic clarifications a `<field-ui>` wrapper would be overkill for.
|
|
62
|
+
type: string
|
|
63
|
+
default: ""
|
|
54
64
|
events:
|
|
55
65
|
change:
|
|
56
66
|
description: "Fired when the value changes (on blur for inputs, on selection for pickers)."
|
|
@@ -26,12 +26,26 @@ export class UISwitch extends UIFormElement {
|
|
|
26
26
|
checked: { type: Boolean, default: false, reflect: true },
|
|
27
27
|
label: { type: String, default: '', reflect: true },
|
|
28
28
|
size: { type: String, default: '', reflect: true },
|
|
29
|
+
// §184 (v0.5.5, FEEDBACK-08 §7): caption beneath the toggle.
|
|
30
|
+
// switch.yaml has declared `hint` since §170 but the template
|
|
31
|
+
// never rendered it — this arc closes the spec-vs-impl gap +
|
|
32
|
+
// wires aria-describedby on the host for screen readers.
|
|
33
|
+
hint: { type: String, default: '', reflect: true },
|
|
29
34
|
};
|
|
30
35
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
36
|
+
// §184: per-instance hint id counter for aria-describedby wiring.
|
|
37
|
+
static #hintSeq = 0;
|
|
38
|
+
|
|
39
|
+
static template = (el) => {
|
|
40
|
+
const hintId = el.hint ? `switch-hint-${++UISwitch.#hintSeq}` : '';
|
|
41
|
+
if (hintId) el.setAttribute('aria-describedby', hintId);
|
|
42
|
+
else el.removeAttribute('aria-describedby');
|
|
43
|
+
return html`
|
|
44
|
+
<span slot="track"><span slot="thumb"></span></span>
|
|
45
|
+
${el.label ? html`<span slot="label">${el.label}</span>` : null}
|
|
46
|
+
${el.hint ? html`<span slot="hint" id=${hintId}>${el.hint}</span>` : null}
|
|
47
|
+
`;
|
|
48
|
+
};
|
|
35
49
|
|
|
36
50
|
connected() {
|
|
37
51
|
super.connected();
|
|
@@ -105,6 +105,16 @@ switch-ui[checked] [slot="thumb"] {
|
|
|
105
105
|
|
|
106
106
|
[slot="label"] { font-size: var(--switch-font-size); }
|
|
107
107
|
|
|
108
|
+
/* ── Hint (§184, v0.5.5, FEEDBACK-08 §7) ──
|
|
109
|
+
Caption beneath the toggle row; wired to aria-describedby on host. */
|
|
110
|
+
[slot="hint"] {
|
|
111
|
+
display: block;
|
|
112
|
+
margin-top: var(--switch-hint-mt, var(--a-space-1));
|
|
113
|
+
font-size: var(--switch-hint-size, var(--a-fine-size));
|
|
114
|
+
color: var(--switch-hint-fg, var(--a-fg-muted));
|
|
115
|
+
line-height: var(--switch-hint-lh, 1.4);
|
|
116
|
+
}
|
|
117
|
+
|
|
108
118
|
:scope:focus-visible { outline: none; }
|
|
109
119
|
:scope:focus-visible [slot="track"] { box-shadow: var(--switch-focus-ring); }
|
|
110
120
|
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://adiaui.dev/a2ui/v0_9/components/Tab.json",
|
|
4
|
+
"title": "Tab",
|
|
5
|
+
"description": "Child of <tabs-ui>. One tab panel — the tab BUTTON is rendered by the parent from this child's text/icon. Wraps panel content as light DOM.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"allOf": [
|
|
8
|
+
{
|
|
9
|
+
"$ref": "common_types.json#/$defs/ComponentCommon"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"$ref": "common_types.json#/$defs/CatalogComponentCommon"
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"properties": {
|
|
16
|
+
"component": {
|
|
17
|
+
"const": "Tab"
|
|
18
|
+
},
|
|
19
|
+
"disabled": {
|
|
20
|
+
"description": "Whether the tab is selectable.",
|
|
21
|
+
"type": "boolean",
|
|
22
|
+
"default": false
|
|
23
|
+
},
|
|
24
|
+
"icon": {
|
|
25
|
+
"description": "Optional leading icon name (Phosphor) for the tab button.",
|
|
26
|
+
"type": "string"
|
|
27
|
+
},
|
|
28
|
+
"text": {
|
|
29
|
+
"description": "Tab button label (rendered by parent <tabs-ui>).",
|
|
30
|
+
"type": "string"
|
|
31
|
+
},
|
|
32
|
+
"value": {
|
|
33
|
+
"description": "Stable id for the tab. Parent uses this to coordinate active state.",
|
|
34
|
+
"type": "string"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"required": [
|
|
38
|
+
"component"
|
|
39
|
+
],
|
|
40
|
+
"unevaluatedProperties": false,
|
|
41
|
+
"x-adiaui": {
|
|
42
|
+
"anti_patterns": [],
|
|
43
|
+
"category": "navigation",
|
|
44
|
+
"composes": [],
|
|
45
|
+
"events": {},
|
|
46
|
+
"examples": [],
|
|
47
|
+
"keywords": [],
|
|
48
|
+
"name": "UITab",
|
|
49
|
+
"related": [],
|
|
50
|
+
"slots": {},
|
|
51
|
+
"states": [],
|
|
52
|
+
"synonyms": {},
|
|
53
|
+
"tag": "tab-ui",
|
|
54
|
+
"tokens": {},
|
|
55
|
+
"traits": [],
|
|
56
|
+
"version": 1
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Edit this file; run `npm run build:components` to regenerate a2ui.json.
|
|
2
|
+
#
|
|
3
|
+
# §176 (v0.5.5): authored to close the §175 baseline-orphan class. The
|
|
4
|
+
# component already existed as a sibling class in the parent's class.js
|
|
5
|
+
# + was registered alongside the parent (e.g. UIList + UIListItem both
|
|
6
|
+
# from list/class.js). The catalog just lacked its own entry. With the
|
|
7
|
+
# §172 sibling-yaml scanner, this file gets picked up next to the parent
|
|
8
|
+
# yaml.
|
|
9
|
+
|
|
10
|
+
# Child component of <tabs-ui>. Surface only inside that parent.
|
|
11
|
+
$schema: ../../../../scripts/schemas/component.yaml.schema.json
|
|
12
|
+
name: UITab
|
|
13
|
+
tag: tab-ui
|
|
14
|
+
component: Tab
|
|
15
|
+
category: navigation
|
|
16
|
+
version: 1
|
|
17
|
+
description: |-
|
|
18
|
+
Child of <tabs-ui>. One tab panel — the tab BUTTON is rendered by the parent from this child's text/icon. Wraps panel content as light DOM.
|
|
19
|
+
|
|
20
|
+
props:
|
|
21
|
+
text:
|
|
22
|
+
description: Tab button label (rendered by parent <tabs-ui>).
|
|
23
|
+
type: string
|
|
24
|
+
value:
|
|
25
|
+
description: Stable id for the tab. Parent uses this to coordinate active state.
|
|
26
|
+
type: string
|
|
27
|
+
icon:
|
|
28
|
+
description: Optional leading icon name (Phosphor) for the tab button.
|
|
29
|
+
type: string
|
|
30
|
+
disabled:
|
|
31
|
+
description: Whether the tab is selectable.
|
|
32
|
+
type: boolean
|
|
33
|
+
default: false
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://adiaui.dev/a2ui/v0_9/components/TimelineItem.json",
|
|
4
|
+
"title": "TimelineItem",
|
|
5
|
+
"description": "Child of <timeline-ui>. One step in a sequenced reasoning/process timeline. Used heavily by <agent-reasoning-ui> + <agent-trace-ui>.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"allOf": [
|
|
8
|
+
{
|
|
9
|
+
"$ref": "common_types.json#/$defs/ComponentCommon"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"$ref": "common_types.json#/$defs/CatalogComponentCommon"
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"properties": {
|
|
16
|
+
"description": {
|
|
17
|
+
"description": "Subtitle below the label.",
|
|
18
|
+
"type": "string"
|
|
19
|
+
},
|
|
20
|
+
"component": {
|
|
21
|
+
"const": "TimelineItem"
|
|
22
|
+
},
|
|
23
|
+
"duration": {
|
|
24
|
+
"description": "Elapsed time (e.g. \"1.2s\", \"340ms\").",
|
|
25
|
+
"type": "string"
|
|
26
|
+
},
|
|
27
|
+
"icon": {
|
|
28
|
+
"description": "Optional leading icon name (Phosphor).",
|
|
29
|
+
"type": "string"
|
|
30
|
+
},
|
|
31
|
+
"spinner": {
|
|
32
|
+
"description": "Show a spinner instead of the icon while status=pending.",
|
|
33
|
+
"type": "boolean",
|
|
34
|
+
"default": false
|
|
35
|
+
},
|
|
36
|
+
"status": {
|
|
37
|
+
"description": "Lifecycle state (idle | pending | done | failed).",
|
|
38
|
+
"type": "string",
|
|
39
|
+
"default": "idle"
|
|
40
|
+
},
|
|
41
|
+
"text": {
|
|
42
|
+
"description": "Primary step label.",
|
|
43
|
+
"type": "string"
|
|
44
|
+
},
|
|
45
|
+
"time": {
|
|
46
|
+
"description": "Absolute timestamp (HH:MM or ISO).",
|
|
47
|
+
"type": "string"
|
|
48
|
+
},
|
|
49
|
+
"variant": {
|
|
50
|
+
"description": "Visual variant (default | accent | success | warning | danger).",
|
|
51
|
+
"type": "string",
|
|
52
|
+
"default": "default"
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
"required": [
|
|
56
|
+
"component"
|
|
57
|
+
],
|
|
58
|
+
"unevaluatedProperties": false,
|
|
59
|
+
"x-adiaui": {
|
|
60
|
+
"anti_patterns": [],
|
|
61
|
+
"category": "feedback",
|
|
62
|
+
"composes": [],
|
|
63
|
+
"events": {},
|
|
64
|
+
"examples": [],
|
|
65
|
+
"keywords": [],
|
|
66
|
+
"name": "UITimelineItem",
|
|
67
|
+
"related": [],
|
|
68
|
+
"slots": {},
|
|
69
|
+
"states": [],
|
|
70
|
+
"synonyms": {},
|
|
71
|
+
"tag": "timeline-item-ui",
|
|
72
|
+
"tokens": {},
|
|
73
|
+
"traits": [],
|
|
74
|
+
"version": 1
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Edit this file; run `npm run build:components` to regenerate a2ui.json.
|
|
2
|
+
#
|
|
3
|
+
# §176 (v0.5.5): authored to close the §175 baseline-orphan class. The
|
|
4
|
+
# component already existed as a sibling class in the parent's class.js
|
|
5
|
+
# + was registered alongside the parent (e.g. UIList + UIListItem both
|
|
6
|
+
# from list/class.js). The catalog just lacked its own entry. With the
|
|
7
|
+
# §172 sibling-yaml scanner, this file gets picked up next to the parent
|
|
8
|
+
# yaml.
|
|
9
|
+
|
|
10
|
+
# Child component of <timeline-ui>. Surface only inside that parent.
|
|
11
|
+
$schema: ../../../../scripts/schemas/component.yaml.schema.json
|
|
12
|
+
name: UITimelineItem
|
|
13
|
+
tag: timeline-item-ui
|
|
14
|
+
component: TimelineItem
|
|
15
|
+
category: feedback
|
|
16
|
+
version: 1
|
|
17
|
+
description: |-
|
|
18
|
+
Child of <timeline-ui>. One step in a sequenced reasoning/process timeline. Used heavily by <agent-reasoning-ui> + <agent-trace-ui>.
|
|
19
|
+
|
|
20
|
+
props:
|
|
21
|
+
text:
|
|
22
|
+
description: Primary step label.
|
|
23
|
+
type: string
|
|
24
|
+
description:
|
|
25
|
+
description: Subtitle below the label.
|
|
26
|
+
type: string
|
|
27
|
+
time:
|
|
28
|
+
description: Absolute timestamp (HH:MM or ISO).
|
|
29
|
+
type: string
|
|
30
|
+
duration:
|
|
31
|
+
description: Elapsed time (e.g. "1.2s", "340ms").
|
|
32
|
+
type: string
|
|
33
|
+
icon:
|
|
34
|
+
description: Optional leading icon name (Phosphor).
|
|
35
|
+
type: string
|
|
36
|
+
variant:
|
|
37
|
+
description: Visual variant (default | accent | success | warning | danger).
|
|
38
|
+
type: string
|
|
39
|
+
default: 'default'
|
|
40
|
+
status:
|
|
41
|
+
description: Lifecycle state (idle | pending | done | failed).
|
|
42
|
+
type: string
|
|
43
|
+
default: 'idle'
|
|
44
|
+
spinner:
|
|
45
|
+
description: Show a spinner instead of the icon while status=pending.
|
|
46
|
+
type: boolean
|
|
47
|
+
default: false
|
package/components/tree/class.js
CHANGED
|
@@ -63,6 +63,82 @@ export class UITree extends UIElement {
|
|
|
63
63
|
}));
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
+
// ──────────────────────────────────────────────────────────────────
|
|
67
|
+
// §184 (v0.5.5, FEEDBACK-08 §2): programmatic expand/collapse API.
|
|
68
|
+
// Pre-§184 consumers had to maintain local `_expanded[]` state +
|
|
69
|
+
// manually sync `tree-item.open` on every `tree-select` event. These
|
|
70
|
+
// five methods + the `auto-expand-selected` reflection let consumers
|
|
71
|
+
// declare the open state directly. All methods accept either a
|
|
72
|
+
// tree-item-ui element OR a value string (matched against [value]
|
|
73
|
+
// first, then [text] for ergonomics).
|
|
74
|
+
// ──────────────────────────────────────────────────────────────────
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Resolve an `item` argument to a tree-item-ui element, or `null` if
|
|
78
|
+
* no match. Accepts: HTMLElement (used as-is when it matches `tree-item-ui`)
|
|
79
|
+
* OR a string (matched against [value] first, then [text]).
|
|
80
|
+
*/
|
|
81
|
+
#resolveItem(arg) {
|
|
82
|
+
if (!arg) return null;
|
|
83
|
+
if (arg instanceof Element) {
|
|
84
|
+
return arg.matches?.('tree-item-ui') ? arg : null;
|
|
85
|
+
}
|
|
86
|
+
if (typeof arg === 'string') {
|
|
87
|
+
const escaped = arg.replace(/"/g, '\\"');
|
|
88
|
+
return (
|
|
89
|
+
this.querySelector(`tree-item-ui[value="${escaped}"]`) ||
|
|
90
|
+
this.querySelector(`tree-item-ui[text="${escaped}"]`) ||
|
|
91
|
+
null
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** Expand the given item (no-op when already open or it has no children). */
|
|
98
|
+
expand(itemOrValue) {
|
|
99
|
+
const item = this.#resolveItem(itemOrValue);
|
|
100
|
+
if (item && item.hasChildren && !item.open) item.open = true;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** Collapse the given item (no-op when already collapsed). */
|
|
104
|
+
collapse(itemOrValue) {
|
|
105
|
+
const item = this.#resolveItem(itemOrValue);
|
|
106
|
+
if (item && item.open) item.open = false;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** Expand every item with children. */
|
|
110
|
+
expandAll() {
|
|
111
|
+
for (const it of this.querySelectorAll('tree-item-ui')) {
|
|
112
|
+
if (it.hasChildren && !it.open) it.open = true;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/** Collapse every item. */
|
|
117
|
+
collapseAll() {
|
|
118
|
+
for (const it of this.querySelectorAll('tree-item-ui')) {
|
|
119
|
+
if (it.open) it.open = false;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Expand every ancestor of the given item so it becomes visible, then
|
|
125
|
+
* scroll it into view. Useful for revealing a programmatically-selected
|
|
126
|
+
* item nested inside collapsed parents.
|
|
127
|
+
*/
|
|
128
|
+
expandTo(itemOrValue) {
|
|
129
|
+
const item = this.#resolveItem(itemOrValue);
|
|
130
|
+
if (!item) return;
|
|
131
|
+
let parent = item.parentElement?.closest('tree-item-ui');
|
|
132
|
+
while (parent) {
|
|
133
|
+
if (parent.hasChildren && !parent.open) parent.open = true;
|
|
134
|
+
parent = parent.parentElement?.closest('tree-item-ui');
|
|
135
|
+
}
|
|
136
|
+
item.querySelector(':scope > [slot="row"]')?.scrollIntoView?.({
|
|
137
|
+
block: 'nearest',
|
|
138
|
+
inline: 'nearest',
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
|
|
66
142
|
#onClick = (e) => {
|
|
67
143
|
const item = e.target.closest('tree-item-ui');
|
|
68
144
|
if (!item || !this.contains(item)) return;
|
|
@@ -171,6 +247,10 @@ export class UITreeItem extends UIElement {
|
|
|
171
247
|
value: { type: String, default: '', reflect: true },
|
|
172
248
|
open: { type: Boolean, default: false, reflect: true },
|
|
173
249
|
selected: { type: Boolean, default: false, reflect: true },
|
|
250
|
+
// §184 (v0.5.5, FEEDBACK-08 §1): optional trailing badge for counts
|
|
251
|
+
// / labels (e.g. "Colors (7)" → text="Colors" badge="7"). Mirrors
|
|
252
|
+
// nav-item-ui badge API; styled muted-and-small via tree.css.
|
|
253
|
+
badge: { type: String, default: '', reflect: true },
|
|
174
254
|
};
|
|
175
255
|
|
|
176
256
|
static template = () => null;
|
|
@@ -222,6 +302,13 @@ export class UITreeItem extends UIElement {
|
|
|
222
302
|
textEl.textContent = this.text;
|
|
223
303
|
row.appendChild(textEl);
|
|
224
304
|
|
|
305
|
+
// §184: trailing badge (when [badge] is set). Stamped even when
|
|
306
|
+
// empty so render() can populate without re-stamping the DOM.
|
|
307
|
+
const badgeEl = document.createElement('span');
|
|
308
|
+
badgeEl.setAttribute('slot', 'badge');
|
|
309
|
+
if (this.badge) badgeEl.textContent = this.badge;
|
|
310
|
+
row.appendChild(badgeEl);
|
|
311
|
+
|
|
225
312
|
// Actions slot placeholder
|
|
226
313
|
const actions = document.createElement('span');
|
|
227
314
|
actions.setAttribute('slot', 'actions');
|
|
@@ -247,5 +334,9 @@ export class UITreeItem extends UIElement {
|
|
|
247
334
|
// Update text
|
|
248
335
|
const textEl = row.querySelector('[slot="text"]');
|
|
249
336
|
if (textEl && this.text) textEl.textContent = this.text;
|
|
337
|
+
|
|
338
|
+
// §184: keep badge slot synced with the [badge] attribute.
|
|
339
|
+
const badgeEl = row.querySelector('[slot="badge"]');
|
|
340
|
+
if (badgeEl) badgeEl.textContent = this.badge || '';
|
|
250
341
|
}
|
|
251
342
|
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://adiaui.dev/a2ui/v0_9/components/TreeItem.json",
|
|
4
|
+
"title": "TreeItem",
|
|
5
|
+
"description": "Child of <tree-ui>. One tree row with optional icon + text + trailing badge, plus nested tree-item-ui children for the collapsible hierarchy. Use inside <tree-ui> only.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"allOf": [
|
|
8
|
+
{
|
|
9
|
+
"$ref": "common_types.json#/$defs/ComponentCommon"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"$ref": "common_types.json#/$defs/CatalogComponentCommon"
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"properties": {
|
|
16
|
+
"badge": {
|
|
17
|
+
"description": "Optional trailing badge text (count, label, etc.). Renders muted + small + right-aligned alongside the row, mirroring the nav-item-ui badge API. When empty, the badge slot stays empty.\n\nAdded in §184 (v0.5.5, FEEDBACK-08 §1).",
|
|
18
|
+
"type": "string"
|
|
19
|
+
},
|
|
20
|
+
"component": {
|
|
21
|
+
"const": "TreeItem"
|
|
22
|
+
},
|
|
23
|
+
"icon": {
|
|
24
|
+
"description": "Optional leading icon name (Phosphor).",
|
|
25
|
+
"type": "string"
|
|
26
|
+
},
|
|
27
|
+
"open": {
|
|
28
|
+
"description": "When true, the item's children render expanded. Single-instance state; the parent `<tree-ui>` toggles this on click + Enter/Space + ArrowRight/ArrowLeft per tree-view APG.",
|
|
29
|
+
"type": "boolean"
|
|
30
|
+
},
|
|
31
|
+
"selected": {
|
|
32
|
+
"description": "Reflects the currently-selected item. Exactly one tree-item is selected per `<tree-ui>` parent (managed by the parent).",
|
|
33
|
+
"type": "boolean"
|
|
34
|
+
},
|
|
35
|
+
"text": {
|
|
36
|
+
"description": "Primary text rendered in the row.",
|
|
37
|
+
"type": "string"
|
|
38
|
+
},
|
|
39
|
+
"value": {
|
|
40
|
+
"description": "Stable value emitted in `tree-select` event detail.",
|
|
41
|
+
"type": "string"
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"required": [
|
|
45
|
+
"component"
|
|
46
|
+
],
|
|
47
|
+
"unevaluatedProperties": false,
|
|
48
|
+
"x-adiaui": {
|
|
49
|
+
"anti_patterns": [],
|
|
50
|
+
"category": "data",
|
|
51
|
+
"composes": [],
|
|
52
|
+
"events": {},
|
|
53
|
+
"examples": [],
|
|
54
|
+
"keywords": [],
|
|
55
|
+
"name": "UITreeItem",
|
|
56
|
+
"related": [],
|
|
57
|
+
"slots": {},
|
|
58
|
+
"states": [],
|
|
59
|
+
"synonyms": {},
|
|
60
|
+
"tag": "tree-item-ui",
|
|
61
|
+
"tokens": {},
|
|
62
|
+
"traits": [],
|
|
63
|
+
"version": 1
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Edit this file; run `npm run build:components` to regenerate a2ui.json.
|
|
2
|
+
#
|
|
3
|
+
# §184 (v0.5.5): authored to close FEEDBACK-08 §1 — tree-item-ui badge
|
|
4
|
+
# attribute + general orphan-class catalog gap. tree-item-ui has shipped
|
|
5
|
+
# since v0.0.x co-located in tree/class.js (UITreeItem) but never had its
|
|
6
|
+
# own catalog entry. With §172 sibling-yaml scanner, this file is picked
|
|
7
|
+
# up next to the parent yaml. Mirrors the v0.5.5 §176 sibling-yaml
|
|
8
|
+
# baseline-orphan closure pattern.
|
|
9
|
+
|
|
10
|
+
# Child component of <tree-ui>. Surface only inside that parent.
|
|
11
|
+
$schema: ../../../../scripts/schemas/component.yaml.schema.json
|
|
12
|
+
name: UITreeItem
|
|
13
|
+
tag: tree-item-ui
|
|
14
|
+
component: TreeItem
|
|
15
|
+
category: data
|
|
16
|
+
version: 1
|
|
17
|
+
description: |-
|
|
18
|
+
Child of <tree-ui>. One tree row with optional icon + text + trailing badge, plus nested tree-item-ui children for the collapsible hierarchy. Use inside <tree-ui> only.
|
|
19
|
+
|
|
20
|
+
props:
|
|
21
|
+
text:
|
|
22
|
+
description: Primary text rendered in the row.
|
|
23
|
+
type: string
|
|
24
|
+
icon:
|
|
25
|
+
description: Optional leading icon name (Phosphor).
|
|
26
|
+
type: string
|
|
27
|
+
value:
|
|
28
|
+
description: Stable value emitted in `tree-select` event detail.
|
|
29
|
+
type: string
|
|
30
|
+
open:
|
|
31
|
+
description: When true, the item's children render expanded. Single-instance state; the parent `<tree-ui>` toggles this on click + Enter/Space + ArrowRight/ArrowLeft per tree-view APG.
|
|
32
|
+
type: boolean
|
|
33
|
+
selected:
|
|
34
|
+
description: Reflects the currently-selected item. Exactly one tree-item is selected per `<tree-ui>` parent (managed by the parent).
|
|
35
|
+
type: boolean
|
|
36
|
+
badge:
|
|
37
|
+
description: |-
|
|
38
|
+
Optional trailing badge text (count, label, etc.). Renders muted + small + right-aligned alongside the row, mirroring the nav-item-ui badge API. When empty, the badge slot stays empty.
|
|
39
|
+
|
|
40
|
+
Added in §184 (v0.5.5, FEEDBACK-08 §1).
|
|
41
|
+
type: string
|
|
@@ -84,6 +84,21 @@
|
|
|
84
84
|
"--tree-actions-gap": {
|
|
85
85
|
"description": "Gap between action icons"
|
|
86
86
|
},
|
|
87
|
+
"--tree-badge-bg": {
|
|
88
|
+
"description": "Background color for the trailing badge (§184)."
|
|
89
|
+
},
|
|
90
|
+
"--tree-badge-fg": {
|
|
91
|
+
"description": "Foreground color for the trailing badge (§184)."
|
|
92
|
+
},
|
|
93
|
+
"--tree-badge-px": {
|
|
94
|
+
"description": "Inline padding for the trailing badge (§184)."
|
|
95
|
+
},
|
|
96
|
+
"--tree-badge-radius": {
|
|
97
|
+
"description": "Border radius for the trailing badge (§184)."
|
|
98
|
+
},
|
|
99
|
+
"--tree-badge-size": {
|
|
100
|
+
"description": "Font size for the trailing badge (§184)."
|
|
101
|
+
},
|
|
87
102
|
"--tree-bg-hover": {
|
|
88
103
|
"description": "Background color on hover"
|
|
89
104
|
},
|
package/components/tree/tree.css
CHANGED
|
@@ -127,6 +127,24 @@
|
|
|
127
127
|
text-overflow: ellipsis;
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
+
/* ── Badge (§184, v0.5.5, FEEDBACK-08 §1) ──
|
|
131
|
+
Optional trailing badge for counts/labels (e.g. "Colors (7)" →
|
|
132
|
+
text="Colors" badge="7"). Empty span renders nothing (no padding,
|
|
133
|
+
no chrome). Sits before the [slot="actions"] hover-revealed slot. */
|
|
134
|
+
[slot="badge"] {
|
|
135
|
+
flex-shrink: 0;
|
|
136
|
+
font-size: var(--tree-badge-size, var(--a-fine-size));
|
|
137
|
+
color: var(--tree-badge-fg, var(--tree-fg-muted));
|
|
138
|
+
background: var(--tree-badge-bg, transparent);
|
|
139
|
+
padding: 0 var(--tree-badge-px, var(--a-space-1));
|
|
140
|
+
border-radius: var(--tree-badge-radius, var(--a-radius-sm));
|
|
141
|
+
line-height: 1;
|
|
142
|
+
font-variant-numeric: tabular-nums;
|
|
143
|
+
}
|
|
144
|
+
[slot="badge"]:empty {
|
|
145
|
+
display: none;
|
|
146
|
+
}
|
|
147
|
+
|
|
130
148
|
/* ── Actions (right side) ── */
|
|
131
149
|
[slot="actions"] {
|
|
132
150
|
display: flex;
|
|
@@ -66,6 +66,16 @@ tokens:
|
|
|
66
66
|
description: Inline-end padding of each row
|
|
67
67
|
--tree-row-radius:
|
|
68
68
|
description: Border radius of each row
|
|
69
|
+
--tree-badge-bg:
|
|
70
|
+
description: Background color for the trailing badge (§184).
|
|
71
|
+
--tree-badge-fg:
|
|
72
|
+
description: Foreground color for the trailing badge (§184).
|
|
73
|
+
--tree-badge-px:
|
|
74
|
+
description: Inline padding for the trailing badge (§184).
|
|
75
|
+
--tree-badge-radius:
|
|
76
|
+
description: Border radius for the trailing badge (§184).
|
|
77
|
+
--tree-badge-size:
|
|
78
|
+
description: Font size for the trailing badge (§184).
|
|
69
79
|
requiredIcons:
|
|
70
80
|
- caret-right
|
|
71
81
|
a2ui:
|
package/core/template.js
CHANGED
|
@@ -137,14 +137,32 @@ function scan(fragment, count) {
|
|
|
137
137
|
// bug. Hot template paths fire many times, so warn (not throw):
|
|
138
138
|
// a thrown error would crash render; warn surfaces the bug class.
|
|
139
139
|
if (attr.value.includes('{{p:')) {
|
|
140
|
+
// §184 (v0.5.5, FEEDBACK-08 §5): `class` is special-cased
|
|
141
|
+
// in the hint because `.class=${expr}` sets a JS expando
|
|
142
|
+
// property (`element.class = "foo"`) — NOT the `class`
|
|
143
|
+
// attribute / className. Consumers following the original
|
|
144
|
+
// §152 generic hint silently lost CSS classes. For class,
|
|
145
|
+
// suggest `.className=${expr}`; for style suggest the
|
|
146
|
+
// canonical style-object path; for everything else keep
|
|
147
|
+
// the generic property-assignment recipe.
|
|
148
|
+
const a = attr.name;
|
|
149
|
+
const specific =
|
|
150
|
+
a === 'class'
|
|
151
|
+
? ` .className=\${expression} ← write to the className property (NOT .class, which is an expando)\n` +
|
|
152
|
+
` class="\${expression}" ← full replacement (whole class string is the expression)\n` +
|
|
153
|
+
` .classList=\${{foo: true, bar: false}} ← if/when implemented; verify in USAGE.md\n`
|
|
154
|
+
: a === 'style'
|
|
155
|
+
? ` .style.cssText=\${expression} ← write CSS text to .style.cssText\n` +
|
|
156
|
+
` style="\${expression}" ← full replacement of the style string\n`
|
|
157
|
+
: ` ${a}="\${expression}" ← full replacement (whole attr is the placeholder)\n` +
|
|
158
|
+
` .${a}=\${expression} ← property assignment (preferred for objects/functions)\n`;
|
|
140
159
|
// eslint-disable-next-line no-console
|
|
141
160
|
console.warn(
|
|
142
161
|
`[template] Partial attribute interpolation is not supported.\n` +
|
|
143
162
|
` Element: <${n.tagName.toLowerCase()}>\n` +
|
|
144
|
-
` Attribute: ${
|
|
163
|
+
` Attribute: ${a}="${attr.value.slice(0, 80)}${attr.value.length > 80 ? '…' : ''}"\n` +
|
|
145
164
|
` Use one of:\n` +
|
|
146
|
-
|
|
147
|
-
` .${attr.name}=\${expression} ← property assignment (preferred for objects/functions)\n` +
|
|
165
|
+
specific +
|
|
148
166
|
` Compute the full attr value as a single expression and interpolate the whole.`
|
|
149
167
|
);
|
|
150
168
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adia-ai/web-components",
|
|
3
|
-
"version": "0.5.
|
|
4
|
-
"description": "AdiaUI web components
|
|
3
|
+
"version": "0.5.5",
|
|
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",
|
|
7
7
|
"exports": {
|