@adia-ai/web-components 0.5.8 → 0.5.10
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/USAGE.md +253 -0
- package/components/accordion/accordion.d.ts +22 -1
- package/components/action-list/action-list.d.ts +14 -1
- package/components/agent-artifact/agent-artifact.d.ts +1 -1
- package/components/agent-feedback-bar/agent-feedback-bar.d.ts +1 -1
- package/components/agent-questions/agent-questions.d.ts +1 -1
- package/components/agent-reasoning/agent-reasoning.d.ts +1 -1
- package/components/agent-suggestions/agent-suggestions.d.ts +1 -1
- package/components/agent-trace/agent-trace.d.ts +1 -1
- package/components/alert/alert.d.ts +1 -1
- package/components/avatar/avatar.d.ts +8 -1
- package/components/badge/badge.d.ts +1 -1
- package/components/block/block.d.ts +1 -1
- package/components/breadcrumb/breadcrumb.d.ts +1 -1
- package/components/button/button.d.ts +1 -1
- package/components/canvas/canvas.d.ts +1 -1
- package/components/card/card.d.ts +1 -1
- package/components/chart/chart.d.ts +1 -1
- package/components/chart-legend/chart-legend.d.ts +1 -1
- package/components/chat-thread/chat-thread.d.ts +40 -1
- package/components/code/code.css +1 -1
- package/components/col/col.a2ui.json +4 -4
- package/components/col/col.d.ts +2 -2
- package/components/col/col.yaml +2 -2
- package/components/command/command.d.ts +1 -1
- package/components/demo-toggle/demo-toggle.d.ts +1 -1
- package/components/description-list/description-list.d.ts +1 -1
- package/components/divider/divider.d.ts +1 -1
- package/components/drawer/drawer.d.ts +1 -1
- package/components/embed/embed.d.ts +1 -1
- package/components/empty-state/class.js +10 -4
- package/components/empty-state/empty-state.a2ui.json +5 -0
- package/components/empty-state/empty-state.css +36 -0
- package/components/empty-state/empty-state.d.ts +6 -1
- package/components/empty-state/empty-state.test.js +77 -0
- package/components/empty-state/empty-state.yaml +9 -0
- package/components/feed/feed.css +1 -1
- package/components/feed/feed.d.ts +106 -13
- package/components/field/field.d.ts +1 -1
- package/components/fields/fields.d.ts +1 -1
- package/components/grid/grid.d.ts +1 -1
- package/components/heatmap/heatmap.d.ts +1 -1
- package/components/icon/icon.d.ts +1 -1
- package/components/image/image.d.ts +1 -1
- package/components/input/class.js +2 -1
- package/components/input/input.a2ui.json +5 -0
- package/components/input/input.d.ts +14 -0
- package/components/input/input.test.js +99 -0
- package/components/input/input.yaml +14 -0
- package/components/inspector/inspector.d.ts +1 -1
- package/components/kbd/kbd.d.ts +1 -1
- package/components/link/link.d.ts +1 -1
- package/components/list/list.d.ts +10 -1
- package/components/menu/menu-divider.a2ui.json +41 -0
- package/components/menu/menu-divider.yaml +15 -0
- package/components/menu/menu-item.a2ui.json +77 -0
- package/components/menu/menu-item.yaml +45 -0
- package/components/menu/menu.d.ts +17 -1
- package/components/modal/modal.d.ts +1 -1
- package/components/nav/nav.css +1 -1
- package/components/nav/nav.d.ts +1 -1
- package/components/nav-group/nav-group.d.ts +1 -1
- package/components/nav-item/nav-item.d.ts +1 -1
- package/components/noodles/noodles.d.ts +1 -1
- package/components/page/page.d.ts +1 -1
- package/components/pagination/pagination.d.ts +1 -1
- package/components/pane/pane.d.ts +1 -1
- package/components/pipeline-status/pipeline-status.d.ts +1 -1
- package/components/popover/popover.d.ts +1 -1
- package/components/progress/progress.d.ts +1 -1
- package/components/progress-row/progress-row.d.ts +1 -1
- package/components/range/range.css +1 -1
- package/components/rating/rating.d.ts +8 -0
- package/components/richtext/richtext.a2ui.json +4 -4
- package/components/richtext/richtext.d.ts +2 -2
- package/components/richtext/richtext.yaml +2 -2
- package/components/row/row.d.ts +1 -1
- package/components/segment/segment.d.ts +1 -1
- package/components/select/class.js +28 -0
- package/components/select/select.css +1 -1
- package/components/select/select.d.ts +14 -0
- package/components/select/select.yaml +28 -0
- package/components/skeleton/skeleton.d.ts +1 -1
- package/components/slider/class.js +20 -50
- package/components/slider/slider.css +1 -1
- package/components/stack/stack.d.ts +1 -1
- package/components/step-progress/step-progress.d.ts +1 -1
- package/components/stepper/stepper-item.a2ui.json +74 -0
- package/components/stepper/stepper-item.yaml +45 -0
- package/components/stepper/stepper.d.ts +13 -1
- package/components/stream/stream.d.ts +1 -1
- package/components/swatch/swatch.css +1 -1
- package/components/swatch/swatch.d.ts +1 -1
- package/components/swiper/swiper.d.ts +1 -1
- package/components/switch/switch.css +1 -1
- package/components/table/table.d.ts +1 -1
- package/components/table-toolbar/table-toolbar.d.ts +1 -1
- package/components/tabs/tabs.d.ts +12 -1
- package/components/tag/tag.d.ts +1 -1
- package/components/text/text.d.ts +64 -13
- package/components/text/text.test.js +8 -2
- package/components/textarea/class.js +7 -1
- package/components/textarea/textarea.a2ui.json +5 -0
- package/components/textarea/textarea.yaml +14 -0
- package/components/timeline/timeline.d.ts +20 -1
- package/components/toast/class.js +9 -0
- package/components/toast/toast.d.ts +9 -5
- package/components/toast/toast.yaml +16 -0
- package/components/toggle-group/toggle-group.d.ts +12 -1
- package/components/toggle-group/toggle-option.a2ui.json +61 -0
- package/components/toggle-group/toggle-option.yaml +33 -0
- package/components/toggle-scheme/toggle-scheme.d.ts +1 -1
- package/components/toolbar/toolbar-group.a2ui.json +41 -0
- package/components/toolbar/toolbar-group.yaml +16 -0
- package/components/toolbar/toolbar.d.ts +4 -1
- package/components/tooltip/tooltip.css +2 -2
- package/components/tooltip/tooltip.d.ts +1 -1
- package/components/tree/tree.css +1 -1
- package/components/tree/tree.d.ts +18 -1
- package/core/form.d.ts +35 -0
- package/core/form.js +93 -0
- package/core/signals.d.ts +28 -0
- package/index.d.ts +2 -2
- package/package.json +1 -1
- package/styles/colors/semantics.css +6 -0
- package/styles/tokens.css +3 -0
- package/styles/typography.css +2 -0
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @see https://ui-kit.exe.xyz/site/components/description-list
|
|
5
5
|
*
|
|
6
6
|
* Type declarations generated by scripts/build/dts-codegen.mjs from
|
|
7
|
-
* the component's `.a2ui.json` sidecar. Edit the source `.yaml`,
|
|
7
|
+
* the component's `.a2ui.json` sidecar(s). Edit the source `.yaml`,
|
|
8
8
|
* run `npm run build:components`, then `npm run codegen:dts` to
|
|
9
9
|
* regenerate; or hand-author this file fully if rich event types are
|
|
10
10
|
* needed beyond what the yaml `events:` block can express.
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @see https://ui-kit.exe.xyz/site/components/divider
|
|
5
5
|
*
|
|
6
6
|
* Type declarations generated by scripts/build/dts-codegen.mjs from
|
|
7
|
-
* the component's `.a2ui.json` sidecar. Edit the source `.yaml`,
|
|
7
|
+
* the component's `.a2ui.json` sidecar(s). Edit the source `.yaml`,
|
|
8
8
|
* run `npm run build:components`, then `npm run codegen:dts` to
|
|
9
9
|
* regenerate; or hand-author this file fully if rich event types are
|
|
10
10
|
* needed beyond what the yaml `events:` block can express.
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @see https://ui-kit.exe.xyz/site/components/drawer
|
|
5
5
|
*
|
|
6
6
|
* Type declarations generated by scripts/build/dts-codegen.mjs from
|
|
7
|
-
* the component's `.a2ui.json` sidecar. Edit the source `.yaml`,
|
|
7
|
+
* the component's `.a2ui.json` sidecar(s). Edit the source `.yaml`,
|
|
8
8
|
* run `npm run build:components`, then `npm run codegen:dts` to
|
|
9
9
|
* regenerate; or hand-author this file fully if rich event types are
|
|
10
10
|
* needed beyond what the yaml `events:` block can express.
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @see https://ui-kit.exe.xyz/site/components/embed
|
|
5
5
|
*
|
|
6
6
|
* Type declarations generated by scripts/build/dts-codegen.mjs from
|
|
7
|
-
* the component's `.a2ui.json` sidecar. Edit the source `.yaml`,
|
|
7
|
+
* the component's `.a2ui.json` sidecar(s). Edit the source `.yaml`,
|
|
8
8
|
* run `npm run build:components`, then `npm run codegen:dts` to
|
|
9
9
|
* regenerate; or hand-author this file fully if rich event types are
|
|
10
10
|
* needed beyond what the yaml `events:` block can express.
|
|
@@ -26,9 +26,13 @@ import { UIElement } from '../../core/element.js';
|
|
|
26
26
|
|
|
27
27
|
export class UIEmptyState extends UIElement {
|
|
28
28
|
static properties = {
|
|
29
|
-
icon: { type: String,
|
|
30
|
-
heading: { type: String,
|
|
31
|
-
description: { type: String,
|
|
29
|
+
icon: { type: String, default: '', reflect: true },
|
|
30
|
+
heading: { type: String, default: '', reflect: true },
|
|
31
|
+
description: { type: String, default: '', reflect: true },
|
|
32
|
+
// §223 (v0.5.9): minimal layout — single-line muted (no centered column,
|
|
33
|
+
// no padding bump, no icon-size lg). Use for inline empty-table-row /
|
|
34
|
+
// inline placeholder cells where the canvas placeholder is too loud.
|
|
35
|
+
minimal: { type: Boolean, default: false, reflect: true },
|
|
32
36
|
};
|
|
33
37
|
|
|
34
38
|
static template = () => null;
|
|
@@ -47,7 +51,9 @@ export class UIEmptyState extends UIElement {
|
|
|
47
51
|
if (!this.#iconEl) {
|
|
48
52
|
this.#iconEl = this.#stampMark(document.createElement('icon-ui'));
|
|
49
53
|
this.#iconEl.setAttribute('slot', 'icon');
|
|
50
|
-
|
|
54
|
+
// §223 (v0.5.9): minimal layout sizes the icon inline; non-minimal
|
|
55
|
+
// keeps the canonical lg badge.
|
|
56
|
+
if (!this.minimal) this.#iconEl.setAttribute('size', 'lg');
|
|
51
57
|
this.insertBefore(this.#iconEl, this.firstChild);
|
|
52
58
|
}
|
|
53
59
|
|
|
@@ -30,6 +30,11 @@
|
|
|
30
30
|
"description": "Icon name displayed above the heading",
|
|
31
31
|
"type": "string",
|
|
32
32
|
"default": ""
|
|
33
|
+
},
|
|
34
|
+
"minimal": {
|
|
35
|
+
"description": "§223 (v0.5.9). Single-line muted layout — drops centered-column chrome\n(no vertical padding, no row-stack, no icon-size bump). Useful for\ninline empty-table-row / inline empty-list / placeholder cells where\nthe full-canvas placeholder is too prominent.",
|
|
36
|
+
"type": "boolean",
|
|
37
|
+
"default": false
|
|
33
38
|
}
|
|
34
39
|
},
|
|
35
40
|
"required": [
|
|
@@ -55,4 +55,40 @@
|
|
|
55
55
|
[slot="action"] {
|
|
56
56
|
margin-top: var(--empty-state-action-mt);
|
|
57
57
|
}
|
|
58
|
+
|
|
59
|
+
/* ── §223 (v0.5.9): [minimal] — single-line muted layout ──
|
|
60
|
+
Drops centered-column chrome (no canvas-style padding, no flex-column
|
|
61
|
+
stack). Renders as `[icon] heading [description]` inline in muted-fg.
|
|
62
|
+
Useful for inline placeholder rows / cells where the full placeholder
|
|
63
|
+
would be too loud. */
|
|
64
|
+
:scope[minimal] {
|
|
65
|
+
flex-direction: row;
|
|
66
|
+
align-items: baseline;
|
|
67
|
+
text-align: start;
|
|
68
|
+
padding: var(--a-space-2) var(--a-space-3);
|
|
69
|
+
gap: var(--a-space-2);
|
|
70
|
+
color: var(--a-fg-muted);
|
|
71
|
+
font-size: var(--a-ui-size);
|
|
72
|
+
}
|
|
73
|
+
:scope[minimal] [slot="icon"] {
|
|
74
|
+
font-size: 1em;
|
|
75
|
+
color: inherit;
|
|
76
|
+
flex-shrink: 0;
|
|
77
|
+
}
|
|
78
|
+
:scope[minimal] [slot="heading"] {
|
|
79
|
+
font-size: inherit;
|
|
80
|
+
font-weight: var(--a-weight-normal);
|
|
81
|
+
color: inherit;
|
|
82
|
+
line-height: inherit;
|
|
83
|
+
}
|
|
84
|
+
:scope[minimal] [slot="description"] {
|
|
85
|
+
font-size: inherit;
|
|
86
|
+
color: inherit;
|
|
87
|
+
line-height: inherit;
|
|
88
|
+
max-width: none;
|
|
89
|
+
}
|
|
90
|
+
:scope[minimal] [slot="action"] {
|
|
91
|
+
margin-top: 0;
|
|
92
|
+
margin-inline-start: auto;
|
|
93
|
+
}
|
|
58
94
|
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @see https://ui-kit.exe.xyz/site/components/empty-state
|
|
5
5
|
*
|
|
6
6
|
* Type declarations generated by scripts/build/dts-codegen.mjs from
|
|
7
|
-
* the component's `.a2ui.json` sidecar. Edit the source `.yaml`,
|
|
7
|
+
* the component's `.a2ui.json` sidecar(s). Edit the source `.yaml`,
|
|
8
8
|
* run `npm run build:components`, then `npm run codegen:dts` to
|
|
9
9
|
* regenerate; or hand-author this file fully if rich event types are
|
|
10
10
|
* needed beyond what the yaml `events:` block can express.
|
|
@@ -19,4 +19,9 @@ export class UIEmptyState extends UIElement {
|
|
|
19
19
|
heading: string;
|
|
20
20
|
/** Icon name displayed above the heading */
|
|
21
21
|
icon: string;
|
|
22
|
+
/** §223 (v0.5.9). Single-line muted layout — drops centered-column chrome
|
|
23
|
+
(no vertical padding, no row-stack, no icon-size bump). Useful for
|
|
24
|
+
inline empty-table-row / inline empty-list / placeholder cells where
|
|
25
|
+
the full-canvas placeholder is too prominent. */
|
|
26
|
+
minimal: boolean;
|
|
22
27
|
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* empty-state-ui — focused unit tests for the §223 (v0.5.9) `minimal`
|
|
3
|
+
* boolean prop.
|
|
4
|
+
*
|
|
5
|
+
* Pre-§223 only the centered-column canvas layout existed. §223 adds
|
|
6
|
+
* an inline single-row muted layout for placeholder cells / table rows
|
|
7
|
+
* where the full-canvas placeholder is too prominent (R13 §4).
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { describe, it, expect, beforeEach } from 'vitest';
|
|
11
|
+
import '../../core/element.js';
|
|
12
|
+
import './empty-state.js';
|
|
13
|
+
|
|
14
|
+
const tick = () => new Promise((r) => queueMicrotask(r));
|
|
15
|
+
|
|
16
|
+
function mount(html) {
|
|
17
|
+
const wrap = document.createElement('div');
|
|
18
|
+
wrap.innerHTML = html;
|
|
19
|
+
document.body.appendChild(wrap);
|
|
20
|
+
return wrap.firstElementChild;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
describe('empty-state-ui — §223 (v0.5.9) minimal mode', () => {
|
|
24
|
+
beforeEach(() => { document.body.innerHTML = ''; });
|
|
25
|
+
|
|
26
|
+
it('defaults to non-minimal (canvas-style placeholder)', () => {
|
|
27
|
+
const el = mount('<empty-state-ui heading="No results"></empty-state-ui>');
|
|
28
|
+
expect(el.minimal).toBe(false);
|
|
29
|
+
expect(el.hasAttribute('minimal')).toBe(false);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('reflects [minimal] attribute to the property', () => {
|
|
33
|
+
const el = mount('<empty-state-ui minimal heading="No matches"></empty-state-ui>');
|
|
34
|
+
expect(el.minimal).toBe(true);
|
|
35
|
+
expect(el.hasAttribute('minimal')).toBe(true);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('stamps icon WITHOUT size="lg" when minimal', async () => {
|
|
39
|
+
const el = mount('<empty-state-ui minimal icon="search" heading="No matches"></empty-state-ui>');
|
|
40
|
+
await tick();
|
|
41
|
+
const icon = el.querySelector(':scope > [slot="icon"]');
|
|
42
|
+
expect(icon).not.toBeNull();
|
|
43
|
+
// Minimal layout uses 1em inherited font-size; non-minimal stamps lg.
|
|
44
|
+
expect(icon.hasAttribute('size')).toBe(false);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('stamps icon WITH size="lg" when not minimal (no regression)', async () => {
|
|
48
|
+
const el = mount('<empty-state-ui icon="search" heading="No matches"></empty-state-ui>');
|
|
49
|
+
await tick();
|
|
50
|
+
const icon = el.querySelector(':scope > [slot="icon"]');
|
|
51
|
+
expect(icon).not.toBeNull();
|
|
52
|
+
expect(icon.getAttribute('size')).toBe('lg');
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('stamps heading + description slots in both modes', async () => {
|
|
56
|
+
const minimal = mount('<empty-state-ui minimal heading="Empty" description="No rows"></empty-state-ui>');
|
|
57
|
+
const canvas = mount('<empty-state-ui heading="Empty" description="No rows"></empty-state-ui>');
|
|
58
|
+
await tick();
|
|
59
|
+
|
|
60
|
+
for (const el of [minimal, canvas]) {
|
|
61
|
+
const h = el.querySelector(':scope > [slot="heading"]');
|
|
62
|
+
const d = el.querySelector(':scope > [slot="description"]');
|
|
63
|
+
expect(h?.textContent).toBe('Empty');
|
|
64
|
+
expect(d?.textContent).toBe('No rows');
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('honors a consumer-provided [slot="action"] child in either mode', () => {
|
|
69
|
+
const el = mount(`
|
|
70
|
+
<empty-state-ui minimal heading="Empty">
|
|
71
|
+
<button slot="action" data-test="reset">Reset</button>
|
|
72
|
+
</empty-state-ui>
|
|
73
|
+
`);
|
|
74
|
+
const action = el.querySelector(':scope > [slot="action"][data-test="reset"]');
|
|
75
|
+
expect(action).not.toBeNull();
|
|
76
|
+
});
|
|
77
|
+
});
|
|
@@ -24,6 +24,15 @@ props:
|
|
|
24
24
|
description: Icon name displayed above the heading
|
|
25
25
|
type: string
|
|
26
26
|
default: ""
|
|
27
|
+
minimal:
|
|
28
|
+
description: |-
|
|
29
|
+
§223 (v0.5.9). Single-line muted layout — drops centered-column chrome
|
|
30
|
+
(no vertical padding, no row-stack, no icon-size bump). Useful for
|
|
31
|
+
inline empty-table-row / inline empty-list / placeholder cells where
|
|
32
|
+
the full-canvas placeholder is too prominent.
|
|
33
|
+
type: boolean
|
|
34
|
+
default: false
|
|
35
|
+
reflect: true
|
|
27
36
|
events: {}
|
|
28
37
|
slots:
|
|
29
38
|
action:
|
package/components/feed/feed.css
CHANGED
|
@@ -102,7 +102,7 @@ feed-item-ui[data-closing] {
|
|
|
102
102
|
--feed-item-duration: var(--a-duration);
|
|
103
103
|
--feed-item-easing: var(--a-easing-out);
|
|
104
104
|
--feed-item-gap: var(--a-space-3);
|
|
105
|
-
--feed-item-max-width:
|
|
105
|
+
--feed-item-max-width: 22rem; /* §230-bundle (v0.5.9): component-local. Was orphaned --a-feed-max-width — hoisted per RESPONSE-21 guidance. */
|
|
106
106
|
}
|
|
107
107
|
:scope[variant="info"] { --feed-item-fg: var(--a-info-fg); --feed-item-bg: var(--a-info-muted); }
|
|
108
108
|
:scope[variant="success"] { --feed-item-fg: var(--a-success-fg); --feed-item-bg: var(--a-success-muted); }
|
|
@@ -1,29 +1,122 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `<feed-ui>` — Shared top-layer feed channel. Per docs/specs/feed-channel.md
|
|
2
|
+
* `<feed-ui>` — Shared top-layer feed channel. Per docs/specs/feed-channel.md
|
|
3
|
+
* (SPEC-FEED-CHANNEL-001). Per-position singletons mounted lazily into
|
|
4
|
+
* document.body via Popover API; consumers post via the static API
|
|
5
|
+
* (`UIFeed.post()`) or the global 'feed' CustomEvent.
|
|
3
6
|
*
|
|
4
7
|
* @see https://ui-kit.exe.xyz/site/components/feed
|
|
5
8
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
9
|
+
* HAND-AUTHORED (not codegen'd) per §247 (v0.5.10, FB-24) — the
|
|
10
|
+
* sibling-yaml codegen walk (v0.5.9 §228) catches the two element classes
|
|
11
|
+
* (`UIFeedContainer` + `UIFeedItem`) but misses the ambient `UIFeed`
|
|
12
|
+
* static-API class because it has no tag-registered yaml. Hand-authored
|
|
13
|
+
* .d.ts adds the static-API + supporting types. `dts-codegen.mjs` keeps
|
|
14
|
+
* this file in its `HAND_AUTHORED_DTS` skip list.
|
|
11
15
|
*/
|
|
12
16
|
|
|
13
17
|
import { UIElement } from '../../core/element.js';
|
|
14
18
|
|
|
15
|
-
|
|
19
|
+
/** Lane positions where `<feed-ui>` containers mount. */
|
|
20
|
+
export type FeedPosition =
|
|
21
|
+
| 'top-left' | 'top-center' | 'top-right'
|
|
22
|
+
| 'bottom-left' | 'bottom-center' | 'bottom-right'
|
|
23
|
+
| 'inline';
|
|
16
24
|
|
|
17
|
-
|
|
18
|
-
|
|
25
|
+
/**
|
|
26
|
+
* Options for `UIFeed.post()` — the imperative one-shot path. Mirrors
|
|
27
|
+
* `UIFeedItem`'s reflected props plus `position` (which container lane).
|
|
28
|
+
*/
|
|
29
|
+
export interface UIFeedPostOptions {
|
|
30
|
+
/** Body copy for the feed item. */
|
|
31
|
+
text: string;
|
|
32
|
+
/** Optional emphasis line above text. */
|
|
33
|
+
heading?: string;
|
|
34
|
+
/** Optional leading icon name (Phosphor). */
|
|
35
|
+
icon?: string;
|
|
36
|
+
/** Semantic variant. */
|
|
37
|
+
variant?: 'default' | 'info' | 'success' | 'warning' | 'danger';
|
|
38
|
+
/** Auto-fade timer in ms; `null` / `0` = sticky (requires user input). */
|
|
39
|
+
duration?: number;
|
|
40
|
+
/** Render an `x` close button (default `true` for sticky, `false` for auto-fade). */
|
|
41
|
+
dismissible?: boolean;
|
|
42
|
+
/** Lane to render into. Defaults to `'bottom-right'`. */
|
|
43
|
+
position?: FeedPosition;
|
|
44
|
+
/**
|
|
45
|
+
* Phase 2 action-required policy: when set, the item carries an action
|
|
46
|
+
* button. Per `feed-channel.md` §2.3, sets `role="alertdialog"` + focus
|
|
47
|
+
* is trapped until the action fires (or the item dismisses).
|
|
48
|
+
*/
|
|
49
|
+
action?: string;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Imperative handle returned by `UIFeed.post()` — dismiss / update. */
|
|
53
|
+
export interface FeedHandle {
|
|
54
|
+
/** Stable id assigned by `<feed-ui>`. `null` if the post failed. */
|
|
55
|
+
id: string | null;
|
|
56
|
+
/** Dismiss the item programmatically (triggers exit animation). */
|
|
57
|
+
dismiss(): void;
|
|
58
|
+
/** Mutate the item's content in-place (e.g. promote loading→done). */
|
|
59
|
+
update(patch: Partial<UIFeedPostOptions>): void;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export type FeedContainerCloseEvent = CustomEvent<unknown>;
|
|
63
|
+
|
|
64
|
+
export class UIFeedContainer extends UIElement {
|
|
65
|
+
/** Cap on simultaneously visible items per lane. */
|
|
19
66
|
max: number;
|
|
20
|
-
/** Lane the feed renders into */
|
|
21
|
-
position:
|
|
67
|
+
/** Lane the feed renders into. */
|
|
68
|
+
position: FeedPosition;
|
|
69
|
+
|
|
70
|
+
addEventListener<K extends keyof HTMLElementEventMap>(
|
|
71
|
+
type: K,
|
|
72
|
+
listener: (this: UIFeedContainer, ev: HTMLElementEventMap[K]) => unknown,
|
|
73
|
+
options?: boolean | AddEventListenerOptions,
|
|
74
|
+
): void;
|
|
75
|
+
addEventListener(type: 'close', listener: (ev: FeedContainerCloseEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export type FeedItemCloseEvent = CustomEvent<unknown>;
|
|
79
|
+
|
|
80
|
+
export class UIFeedItem extends UIElement {
|
|
81
|
+
/** Render an `x` close button (default `true` for sticky, `false` for auto-fade). */
|
|
82
|
+
dismissible: boolean;
|
|
83
|
+
/** Auto-fade timer in ms; `null` / `0` = sticky (requires user input). */
|
|
84
|
+
duration: number;
|
|
85
|
+
/** Optional emphasis line above text. */
|
|
86
|
+
heading: string;
|
|
87
|
+
/** Optional leading icon name. */
|
|
88
|
+
icon: string;
|
|
89
|
+
/** Body copy. */
|
|
90
|
+
text: string;
|
|
91
|
+
/** Semantic variant. */
|
|
92
|
+
variant: 'default' | 'info' | 'success' | 'warning' | 'danger';
|
|
22
93
|
|
|
23
94
|
addEventListener<K extends keyof HTMLElementEventMap>(
|
|
24
95
|
type: K,
|
|
25
|
-
listener: (this:
|
|
96
|
+
listener: (this: UIFeedItem, ev: HTMLElementEventMap[K]) => unknown,
|
|
26
97
|
options?: boolean | AddEventListenerOptions,
|
|
27
98
|
): void;
|
|
28
|
-
addEventListener(type: 'close', listener: (ev:
|
|
99
|
+
addEventListener(type: 'close', listener: (ev: FeedItemCloseEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Static API for posting `<feed-item-ui>` rows without instantiating
|
|
104
|
+
* `<feed-ui>` declaratively. Per-position lanes auto-mount into
|
|
105
|
+
* `document.body` on first call. Use this in place of declarative
|
|
106
|
+
* `<feed-ui>` for one-shot programmatic messages (toast-style API).
|
|
107
|
+
*
|
|
108
|
+
* The class is NOT a custom element — it's a singleton namespace. Don't
|
|
109
|
+
* try to `new UIFeed()` or extend it; use the static methods only.
|
|
110
|
+
*/
|
|
111
|
+
export class UIFeed {
|
|
112
|
+
/** Get (or lazily create + mount) the per-position lane container. */
|
|
113
|
+
static get(position?: FeedPosition): UIFeedContainer;
|
|
114
|
+
/** Post a feed item. Returns a handle for programmatic dismiss / update. */
|
|
115
|
+
static post(opts: UIFeedPostOptions): FeedHandle;
|
|
116
|
+
/** Clear all items in the lane at the given position. */
|
|
117
|
+
static clear(position?: FeedPosition): void;
|
|
118
|
+
/** Purge all lanes; tear down DOM containers. */
|
|
119
|
+
static purge(): void;
|
|
120
|
+
/** Internal: drop empty container after the last item dismisses. */
|
|
121
|
+
static releaseContainerIfEmpty(container: UIFeedContainer): void;
|
|
29
122
|
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @see https://ui-kit.exe.xyz/site/components/field
|
|
5
5
|
*
|
|
6
6
|
* Type declarations generated by scripts/build/dts-codegen.mjs from
|
|
7
|
-
* the component's `.a2ui.json` sidecar. Edit the source `.yaml`,
|
|
7
|
+
* the component's `.a2ui.json` sidecar(s). Edit the source `.yaml`,
|
|
8
8
|
* run `npm run build:components`, then `npm run codegen:dts` to
|
|
9
9
|
* regenerate; or hand-author this file fully if rich event types are
|
|
10
10
|
* needed beyond what the yaml `events:` block can express.
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @see https://ui-kit.exe.xyz/site/components/fields
|
|
5
5
|
*
|
|
6
6
|
* Type declarations generated by scripts/build/dts-codegen.mjs from
|
|
7
|
-
* the component's `.a2ui.json` sidecar. Edit the source `.yaml`,
|
|
7
|
+
* the component's `.a2ui.json` sidecar(s). Edit the source `.yaml`,
|
|
8
8
|
* run `npm run build:components`, then `npm run codegen:dts` to
|
|
9
9
|
* regenerate; or hand-author this file fully if rich event types are
|
|
10
10
|
* needed beyond what the yaml `events:` block can express.
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @see https://ui-kit.exe.xyz/site/components/grid
|
|
5
5
|
*
|
|
6
6
|
* Type declarations generated by scripts/build/dts-codegen.mjs from
|
|
7
|
-
* the component's `.a2ui.json` sidecar. Edit the source `.yaml`,
|
|
7
|
+
* the component's `.a2ui.json` sidecar(s). Edit the source `.yaml`,
|
|
8
8
|
* run `npm run build:components`, then `npm run codegen:dts` to
|
|
9
9
|
* regenerate; or hand-author this file fully if rich event types are
|
|
10
10
|
* needed beyond what the yaml `events:` block can express.
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @see https://ui-kit.exe.xyz/site/components/heatmap
|
|
5
5
|
*
|
|
6
6
|
* Type declarations generated by scripts/build/dts-codegen.mjs from
|
|
7
|
-
* the component's `.a2ui.json` sidecar. Edit the source `.yaml`,
|
|
7
|
+
* the component's `.a2ui.json` sidecar(s). Edit the source `.yaml`,
|
|
8
8
|
* run `npm run build:components`, then `npm run codegen:dts` to
|
|
9
9
|
* regenerate; or hand-author this file fully if rich event types are
|
|
10
10
|
* needed beyond what the yaml `events:` block can express.
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @see https://ui-kit.exe.xyz/site/components/icon
|
|
5
5
|
*
|
|
6
6
|
* Type declarations generated by scripts/build/dts-codegen.mjs from
|
|
7
|
-
* the component's `.a2ui.json` sidecar. Edit the source `.yaml`,
|
|
7
|
+
* the component's `.a2ui.json` sidecar(s). Edit the source `.yaml`,
|
|
8
8
|
* run `npm run build:components`, then `npm run codegen:dts` to
|
|
9
9
|
* regenerate; or hand-author this file fully if rich event types are
|
|
10
10
|
* needed beyond what the yaml `events:` block can express.
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @see https://ui-kit.exe.xyz/site/components/image
|
|
5
5
|
*
|
|
6
6
|
* Type declarations generated by scripts/build/dts-codegen.mjs from
|
|
7
|
-
* the component's `.a2ui.json` sidecar. Edit the source `.yaml`,
|
|
7
|
+
* the component's `.a2ui.json` sidecar(s). Edit the source `.yaml`,
|
|
8
8
|
* run `npm run build:components`, then `npm run codegen:dts` to
|
|
9
9
|
* regenerate; or hand-author this file fully if rich event types are
|
|
10
10
|
* needed beyond what the yaml `events:` block can express.
|
|
@@ -601,7 +601,8 @@ export class UIInput extends UIFormElement {
|
|
|
601
601
|
this.value = text;
|
|
602
602
|
if (!this.#isNativePassword) this.#textEl.toggleAttribute('data-empty', !text);
|
|
603
603
|
this.syncValue(text);
|
|
604
|
-
|
|
604
|
+
// §220 (v0.5.9, FEEDBACK-14 §3): trailing-debounce when `throttle > 0`.
|
|
605
|
+
this.scheduleThrottledInput();
|
|
605
606
|
};
|
|
606
607
|
|
|
607
608
|
#onBeforeInput = (e) => {
|
|
@@ -146,6 +146,11 @@
|
|
|
146
146
|
"type": "string",
|
|
147
147
|
"default": ""
|
|
148
148
|
},
|
|
149
|
+
"throttle": {
|
|
150
|
+
"description": "§220 (v0.5.9, FEEDBACK-14 §3). Trailing-debounce on the `input`\nevent in milliseconds. When > 0, value mutates immediately + the UI\nstays responsive, but `input` dispatch is collapsed so only the\nfinal value in the throttle window emits. Useful for expensive\n`input`-driven computation (palette regen, large list filter,\nserver-side autocomplete). `change` fires unthrottled on blur /\nEnter / stepper commit; any pending `input` flushes before `change`\nso consumers see input→input→…→input→change ordering. Default 0\npreserves synchronous emission.",
|
|
151
|
+
"type": "number",
|
|
152
|
+
"default": 0
|
|
153
|
+
},
|
|
149
154
|
"value": {
|
|
150
155
|
"description": "Current input value, synced with contenteditable text surface. For `type=\"number\"`, this is the formatted numeric string; read `el.valueAsNumber` for the parsed Number.",
|
|
151
156
|
"type": "string",
|
|
@@ -30,6 +30,20 @@ export class UIInput extends UIFormElement {
|
|
|
30
30
|
suffix: string;
|
|
31
31
|
/** Raw mode — drops chrome (border, padding) for inline composition. */
|
|
32
32
|
raw: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* §247 (v0.5.10, FB-26 §1): mobile keyboard hint per HTML `inputmode`
|
|
35
|
+
* spec — `numeric` / `decimal` / `email` / `tel` / `url` / `search` /
|
|
36
|
+
* `none`. Forwards to the underlying contenteditable surface. Empty
|
|
37
|
+
* string = no hint (browser default).
|
|
38
|
+
*/
|
|
39
|
+
inputmode: string;
|
|
40
|
+
/**
|
|
41
|
+
* §247 (v0.5.10, FB-26 §1): HTML `autocomplete` attribute (`off` /
|
|
42
|
+
* `name` / `email` / `current-password` / `new-password` etc).
|
|
43
|
+
* Forwards to the underlying contenteditable surface for browser
|
|
44
|
+
* autofill behavior.
|
|
45
|
+
*/
|
|
46
|
+
autocomplete: string;
|
|
33
47
|
|
|
34
48
|
// ── Number-mode properties (active when type="number") ──
|
|
35
49
|
/** Minimum value. `null` to disable. */
|
|
@@ -121,3 +121,102 @@ describe('input-ui — §199 leading/trailing affordance slots', () => {
|
|
|
121
121
|
expect(text.textContent).toBe('Theme 1');
|
|
122
122
|
});
|
|
123
123
|
});
|
|
124
|
+
|
|
125
|
+
describe('input-ui — §220 (v0.5.9) throttle parity', () => {
|
|
126
|
+
beforeEach(() => { document.body.innerHTML = ''; });
|
|
127
|
+
|
|
128
|
+
it('inherits `throttle` property default 0 from UIFormElement', () => {
|
|
129
|
+
const el = mount('<input-ui></input-ui>');
|
|
130
|
+
expect(el.throttle).toBe(0);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it('reflects [throttle] attribute to the property', () => {
|
|
134
|
+
const el = mount('<input-ui throttle="150"></input-ui>');
|
|
135
|
+
expect(el.throttle).toBe(150);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it('dispatches `input` synchronously when throttle=0 (default)', async () => {
|
|
139
|
+
const el = mount('<input-ui></input-ui>');
|
|
140
|
+
await tick();
|
|
141
|
+
let count = 0;
|
|
142
|
+
// Filter for host-emitted CustomEvents (have detail.value); surface
|
|
143
|
+
// InputEvents bubble up too but have no detail property.
|
|
144
|
+
el.addEventListener('input', (e) => {
|
|
145
|
+
if (e.detail?.value !== undefined) count++;
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
// Simulate user typing — set value + dispatch DOM input on the
|
|
149
|
+
// contenteditable surface so the host's #onInput handler fires.
|
|
150
|
+
const surface = el.querySelector('[slot="text"]');
|
|
151
|
+
surface.textContent = 'a';
|
|
152
|
+
surface.dispatchEvent(new InputEvent('input', { bubbles: true }));
|
|
153
|
+
surface.textContent = 'ab';
|
|
154
|
+
surface.dispatchEvent(new InputEvent('input', { bubbles: true }));
|
|
155
|
+
surface.textContent = 'abc';
|
|
156
|
+
surface.dispatchEvent(new InputEvent('input', { bubbles: true }));
|
|
157
|
+
|
|
158
|
+
expect(count).toBe(3);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it('collapses burst dispatches to one trailing `input` when throttle>0', async () => {
|
|
162
|
+
const el = mount('<input-ui throttle="20"></input-ui>');
|
|
163
|
+
await tick();
|
|
164
|
+
const events = [];
|
|
165
|
+
// Filter for host-emitted CustomEvents (have detail.value); surface
|
|
166
|
+
// InputEvents bubble up too but have no detail property.
|
|
167
|
+
el.addEventListener('input', (e) => {
|
|
168
|
+
if (e.detail?.value !== undefined) events.push(e.detail.value);
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
const surface = el.querySelector('[slot="text"]');
|
|
172
|
+
surface.textContent = 'a';
|
|
173
|
+
surface.dispatchEvent(new InputEvent('input', { bubbles: true }));
|
|
174
|
+
surface.textContent = 'ab';
|
|
175
|
+
surface.dispatchEvent(new InputEvent('input', { bubbles: true }));
|
|
176
|
+
surface.textContent = 'abc';
|
|
177
|
+
surface.dispatchEvent(new InputEvent('input', { bubbles: true }));
|
|
178
|
+
|
|
179
|
+
expect(events).toEqual([]);
|
|
180
|
+
|
|
181
|
+
await new Promise((r) => setTimeout(r, 35));
|
|
182
|
+
expect(events).toEqual(['abc']);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
it('flushPendingInput() fires the pending dispatch synchronously', async () => {
|
|
186
|
+
const el = mount('<input-ui throttle="50"></input-ui>');
|
|
187
|
+
await tick();
|
|
188
|
+
const events = [];
|
|
189
|
+
// Filter for host-emitted CustomEvents (have detail.value); surface
|
|
190
|
+
// InputEvents bubble up too but have no detail property.
|
|
191
|
+
el.addEventListener('input', (e) => {
|
|
192
|
+
if (e.detail?.value !== undefined) events.push(e.detail.value);
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
const surface = el.querySelector('[slot="text"]');
|
|
196
|
+
surface.textContent = 'pending';
|
|
197
|
+
surface.dispatchEvent(new InputEvent('input', { bubbles: true }));
|
|
198
|
+
|
|
199
|
+
expect(events).toEqual([]);
|
|
200
|
+
el.flushPendingInput();
|
|
201
|
+
expect(events).toEqual(['pending']);
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
it('dropPendingInput() prevents the dispatch (used by disconnected)', async () => {
|
|
205
|
+
const el = mount('<input-ui throttle="20"></input-ui>');
|
|
206
|
+
await tick();
|
|
207
|
+
const events = [];
|
|
208
|
+
// Filter for host-emitted CustomEvents (have detail.value); surface
|
|
209
|
+
// InputEvents bubble up too but have no detail property.
|
|
210
|
+
el.addEventListener('input', (e) => {
|
|
211
|
+
if (e.detail?.value !== undefined) events.push(e.detail.value);
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
const surface = el.querySelector('[slot="text"]');
|
|
215
|
+
surface.textContent = 'gone';
|
|
216
|
+
surface.dispatchEvent(new InputEvent('input', { bubbles: true }));
|
|
217
|
+
|
|
218
|
+
el.dropPendingInput();
|
|
219
|
+
await new Promise((r) => setTimeout(r, 30));
|
|
220
|
+
expect(events).toEqual([]);
|
|
221
|
+
});
|
|
222
|
+
});
|
|
@@ -139,6 +139,20 @@ props:
|
|
|
139
139
|
description: Suffix text rendered after the text surface (e.g., unit like 'kg')
|
|
140
140
|
type: string
|
|
141
141
|
default: ''
|
|
142
|
+
throttle:
|
|
143
|
+
description: |-
|
|
144
|
+
§220 (v0.5.9, FEEDBACK-14 §3). Trailing-debounce on the `input`
|
|
145
|
+
event in milliseconds. When > 0, value mutates immediately + the UI
|
|
146
|
+
stays responsive, but `input` dispatch is collapsed so only the
|
|
147
|
+
final value in the throttle window emits. Useful for expensive
|
|
148
|
+
`input`-driven computation (palette regen, large list filter,
|
|
149
|
+
server-side autocomplete). `change` fires unthrottled on blur /
|
|
150
|
+
Enter / stepper commit; any pending `input` flushes before `change`
|
|
151
|
+
so consumers see input→input→…→input→change ordering. Default 0
|
|
152
|
+
preserves synchronous emission.
|
|
153
|
+
type: number
|
|
154
|
+
default: 0
|
|
155
|
+
reflect: true
|
|
142
156
|
value:
|
|
143
157
|
description: Current input value, synced with contenteditable text surface. For `type="number"`, this is the formatted
|
|
144
158
|
numeric string; read `el.valueAsNumber` for the parsed Number.
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @see https://ui-kit.exe.xyz/site/components/inspector
|
|
5
5
|
*
|
|
6
6
|
* Type declarations generated by scripts/build/dts-codegen.mjs from
|
|
7
|
-
* the component's `.a2ui.json` sidecar. Edit the source `.yaml`,
|
|
7
|
+
* the component's `.a2ui.json` sidecar(s). Edit the source `.yaml`,
|
|
8
8
|
* run `npm run build:components`, then `npm run codegen:dts` to
|
|
9
9
|
* regenerate; or hand-author this file fully if rich event types are
|
|
10
10
|
* needed beyond what the yaml `events:` block can express.
|
package/components/kbd/kbd.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @see https://ui-kit.exe.xyz/site/components/kbd
|
|
5
5
|
*
|
|
6
6
|
* Type declarations generated by scripts/build/dts-codegen.mjs from
|
|
7
|
-
* the component's `.a2ui.json` sidecar. Edit the source `.yaml`,
|
|
7
|
+
* the component's `.a2ui.json` sidecar(s). Edit the source `.yaml`,
|
|
8
8
|
* run `npm run build:components`, then `npm run codegen:dts` to
|
|
9
9
|
* regenerate; or hand-author this file fully if rich event types are
|
|
10
10
|
* needed beyond what the yaml `events:` block can express.
|
|
@@ -28,7 +28,7 @@ wiring. ARIA role is "link" (set automatically by `<a>` element).
|
|
|
28
28
|
* @see https://ui-kit.exe.xyz/site/components/link
|
|
29
29
|
*
|
|
30
30
|
* Type declarations generated by scripts/build/dts-codegen.mjs from
|
|
31
|
-
* the component's `.a2ui.json` sidecar. Edit the source `.yaml`,
|
|
31
|
+
* the component's `.a2ui.json` sidecar(s). Edit the source `.yaml`,
|
|
32
32
|
* run `npm run build:components`, then `npm run codegen:dts` to
|
|
33
33
|
* regenerate; or hand-author this file fully if rich event types are
|
|
34
34
|
* needed beyond what the yaml `events:` block can express.
|