@adia-ai/web-components 0.6.36 → 0.6.37
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 +28 -1
- package/components/badge/badge.a2ui.json +10 -0
- package/components/badge/badge.css +70 -0
- package/components/badge/badge.yaml +20 -0
- package/components/blockquote/blockquote.a2ui.json +121 -0
- package/components/blockquote/blockquote.class.js +68 -0
- package/components/blockquote/blockquote.css +46 -0
- package/components/blockquote/blockquote.d.ts +31 -0
- package/components/blockquote/blockquote.js +17 -0
- package/components/blockquote/blockquote.yaml +124 -0
- package/components/button/button.css +11 -3
- package/components/calendar-picker/calendar-picker.a2ui.json +15 -0
- package/components/calendar-picker/calendar-picker.class.js +7 -1
- package/components/calendar-picker/calendar-picker.yaml +14 -0
- package/components/color-input/color-input.a2ui.json +2 -2
- package/components/color-input/color-input.class.js +9 -2
- package/components/color-input/color-input.yaml +2 -2
- package/components/combobox/combobox.class.js +4 -0
- package/components/context-menu/context-menu.a2ui.json +159 -0
- package/components/context-menu/context-menu.class.js +275 -0
- package/components/context-menu/context-menu.css +56 -0
- package/components/context-menu/context-menu.d.ts +70 -0
- package/components/context-menu/context-menu.js +17 -0
- package/components/context-menu/context-menu.yaml +136 -0
- package/components/date-range-picker/date-range-picker.a2ui.json +15 -0
- package/components/date-range-picker/date-range-picker.class.js +2 -0
- package/components/date-range-picker/date-range-picker.yaml +14 -0
- package/components/datetime-picker/datetime-picker.a2ui.json +15 -0
- package/components/datetime-picker/datetime-picker.class.js +3 -1
- package/components/datetime-picker/datetime-picker.d.ts +2 -0
- package/components/datetime-picker/datetime-picker.yaml +14 -0
- package/components/empty-state/empty-state.class.js +2 -0
- package/components/feed/feed.class.js +13 -5
- package/components/feed/feed.css +14 -0
- package/components/index.js +9 -0
- package/components/integration-card/integration-card.class.js +9 -0
- package/components/integration-card/integration-card.test.js +4 -3
- package/components/nav-group/nav-group.css +7 -1
- package/components/number-format/number-format.a2ui.json +180 -0
- package/components/number-format/number-format.class.js +96 -0
- package/components/number-format/number-format.css +18 -0
- package/components/number-format/number-format.d.ts +68 -0
- package/components/number-format/number-format.js +17 -0
- package/components/number-format/number-format.yaml +204 -0
- package/components/pagination/pagination.a2ui.json +19 -2
- package/components/pagination/pagination.class.js +90 -37
- package/components/pagination/pagination.css +32 -127
- package/components/pagination/pagination.d.ts +8 -2
- package/components/pagination/pagination.test.js +195 -0
- package/components/pagination/pagination.yaml +22 -1
- package/components/password-strength/password-strength.a2ui.json +152 -0
- package/components/password-strength/password-strength.class.js +157 -0
- package/components/password-strength/password-strength.css +80 -0
- package/components/password-strength/password-strength.d.ts +59 -0
- package/components/password-strength/password-strength.js +17 -0
- package/components/password-strength/password-strength.yaml +153 -0
- package/components/popover/popover.css +43 -23
- package/components/popover/popover.yaml +8 -4
- package/components/qr-code/QR-TEST.svg +4 -0
- package/components/qr-code/qr-code.a2ui.json +154 -0
- package/components/qr-code/qr-code.class.js +129 -0
- package/components/qr-code/qr-code.css +41 -0
- package/components/qr-code/qr-code.d.ts +83 -0
- package/components/qr-code/qr-code.js +17 -0
- package/components/qr-code/qr-code.yaml +203 -0
- package/components/qr-code/qr-encoder.js +633 -0
- package/components/relative-time/relative-time.a2ui.json +120 -0
- package/components/relative-time/relative-time.class.js +136 -0
- package/components/relative-time/relative-time.css +22 -0
- package/components/relative-time/relative-time.d.ts +51 -0
- package/components/relative-time/relative-time.js +17 -0
- package/components/relative-time/relative-time.yaml +133 -0
- package/components/segmented/segmented.class.js +5 -1
- package/components/select/select.class.js +4 -0
- package/components/skip-nav/skip-nav.a2ui.json +92 -0
- package/components/skip-nav/skip-nav.class.js +45 -0
- package/components/skip-nav/skip-nav.css +54 -0
- package/components/skip-nav/skip-nav.d.ts +27 -0
- package/components/skip-nav/skip-nav.js +12 -0
- package/components/skip-nav/skip-nav.yaml +68 -0
- package/components/slider/slider.a2ui.json +16 -1
- package/components/slider/slider.class.js +264 -122
- package/components/slider/slider.css +82 -2
- package/components/slider/slider.d.ts +19 -3
- package/components/slider/slider.test.js +55 -0
- package/components/slider/slider.yaml +28 -6
- package/components/table/table.class.js +29 -6
- package/components/table/table.css +31 -4
- package/components/table-toolbar/table-toolbar.class.js +3 -1
- package/components/tag/tag.a2ui.json +3 -2
- package/components/tag/tag.css +35 -11
- package/components/tag/tag.d.ts +14 -0
- package/components/tag/tag.test.js +35 -11
- package/components/tag/tag.yaml +13 -7
- package/components/toast/toast.class.js +12 -4
- package/components/toc/toc.a2ui.json +159 -0
- package/components/toc/toc.class.js +222 -0
- package/components/toc/toc.css +92 -0
- package/components/toc/toc.d.ts +61 -0
- package/components/toc/toc.js +17 -0
- package/components/toc/toc.yaml +180 -0
- package/components/toolbar/toolbar.class.js +3 -0
- package/components/visually-hidden/visually-hidden.a2ui.json +71 -0
- package/components/visually-hidden/visually-hidden.class.js +14 -0
- package/components/visually-hidden/visually-hidden.css +25 -0
- package/components/visually-hidden/visually-hidden.d.ts +26 -0
- package/components/visually-hidden/visually-hidden.js +12 -0
- package/components/visually-hidden/visually-hidden.yaml +54 -0
- package/core/anchor.js +19 -3
- package/dist/web-components.min.css +1 -1
- package/dist/web-components.min.js +100 -89
- package/package.json +1 -1
- package/styles/colors/semantics.css +11 -2
- package/styles/components.css +9 -0
- package/styles/resets.css +10 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
$schema: ../../../../scripts/schemas/component.yaml.schema.json
|
|
2
|
+
name: UIContextMenu
|
|
3
|
+
tag: context-menu-ui
|
|
4
|
+
status: stable
|
|
5
|
+
component: ContextMenu
|
|
6
|
+
category: container
|
|
7
|
+
version: 1
|
|
8
|
+
description: |
|
|
9
|
+
Right-click activated menu — the OS-native context-menu pattern as a
|
|
10
|
+
web component. Distinct from `menu-ui` (which is button-triggered):
|
|
11
|
+
same item shape (`menu-item-ui` children), different trigger surface
|
|
12
|
+
(`contextmenu` event), and pointer-anchored positioning instead of
|
|
13
|
+
element-anchored. Pattern: WAI-APG Menu.
|
|
14
|
+
|
|
15
|
+
Two binding modes:
|
|
16
|
+
**A. Wrap.** Default-slot child becomes the target:
|
|
17
|
+
`<context-menu-ui><my-table>...</my-table>...items</context-menu-ui>`.
|
|
18
|
+
**B. Selector.** Point at one or more existing elements via [for]:
|
|
19
|
+
`<context-menu-ui for="#my-table">...items</context-menu-ui>`.
|
|
20
|
+
|
|
21
|
+
On `contextmenu` event on a target: `preventDefault()`, position the
|
|
22
|
+
menu at the pointer coords, show via Popover API. Touch long-press
|
|
23
|
+
(configurable via [long-press-ms]) does the same. Shift+F10 / Menu
|
|
24
|
+
key opens at the focused target's center for keyboard users.
|
|
25
|
+
composes:
|
|
26
|
+
- menu-item-ui
|
|
27
|
+
props:
|
|
28
|
+
for:
|
|
29
|
+
description: CSS selector(s) for target element(s). Empty = use default-slot child.
|
|
30
|
+
type: string
|
|
31
|
+
default: ""
|
|
32
|
+
reflect: true
|
|
33
|
+
open:
|
|
34
|
+
description: Programmatic open state. Set true to open at target center.
|
|
35
|
+
type: boolean
|
|
36
|
+
default: false
|
|
37
|
+
reflect: true
|
|
38
|
+
long-press-ms:
|
|
39
|
+
description: Long-press duration (ms) on touch devices to open the menu.
|
|
40
|
+
type: number
|
|
41
|
+
default: 500
|
|
42
|
+
reflect: false
|
|
43
|
+
attribute: long-press-ms
|
|
44
|
+
events:
|
|
45
|
+
context-menu-open:
|
|
46
|
+
description: Fired when the menu opens (right-click / long-press / keyboard).
|
|
47
|
+
detail:
|
|
48
|
+
target:
|
|
49
|
+
type: Element
|
|
50
|
+
description: The target element the menu was opened on.
|
|
51
|
+
x:
|
|
52
|
+
type: number
|
|
53
|
+
description: Pointer x coord (viewport-relative); null for keyboard activation.
|
|
54
|
+
y:
|
|
55
|
+
type: number
|
|
56
|
+
description: Pointer y coord; null for keyboard activation.
|
|
57
|
+
context-menu-close:
|
|
58
|
+
description: Fired when the menu closes (item-select / outside-click / Escape).
|
|
59
|
+
detail:
|
|
60
|
+
reason:
|
|
61
|
+
type: string
|
|
62
|
+
description: '"select" | "outside" | "escape"'
|
|
63
|
+
context-menu-select:
|
|
64
|
+
description: Fired when an item is activated. Same shape as menu-ui's `action` event.
|
|
65
|
+
detail:
|
|
66
|
+
value:
|
|
67
|
+
type: string
|
|
68
|
+
description: Selected item's value.
|
|
69
|
+
text:
|
|
70
|
+
type: string
|
|
71
|
+
description: Selected item's text.
|
|
72
|
+
slots:
|
|
73
|
+
default:
|
|
74
|
+
description: |
|
|
75
|
+
Two-purpose slot: the wrapped target element (mode A — first
|
|
76
|
+
non-menu-item-ui child) AND the menu-item-ui items. Items are
|
|
77
|
+
promoted to the popover surface on open.
|
|
78
|
+
states:
|
|
79
|
+
- name: idle
|
|
80
|
+
description: Default. Menu closed; trigger listeners attached.
|
|
81
|
+
- name: open
|
|
82
|
+
description: Menu visible at pointer position; focus inside.
|
|
83
|
+
attribute: open
|
|
84
|
+
traits: []
|
|
85
|
+
tokens:
|
|
86
|
+
--context-menu-bg:
|
|
87
|
+
description: Menu surface background color.
|
|
88
|
+
default: var(--a-bg-subtle)
|
|
89
|
+
--context-menu-border:
|
|
90
|
+
description: Menu surface border color.
|
|
91
|
+
default: var(--a-border-subtle)
|
|
92
|
+
--context-menu-radius:
|
|
93
|
+
description: Menu surface border radius.
|
|
94
|
+
default: var(--a-radius-md)
|
|
95
|
+
--context-menu-shadow:
|
|
96
|
+
description: Menu surface shadow.
|
|
97
|
+
default: var(--a-shadow-lg)
|
|
98
|
+
a2ui:
|
|
99
|
+
rules:
|
|
100
|
+
- rule: 'Use <context-menu-ui> for right-click menus on a target (table row, file item, canvas object). For button-triggered menus use <menu-ui>; for popover content that is not a menu use <popover-ui> directly.'
|
|
101
|
+
reason: 'Trigger surface boundary.'
|
|
102
|
+
- rule: 'Items are <menu-item-ui> children inside the default slot — same shape as <menu-ui> items.'
|
|
103
|
+
reason: 'Single menu vocabulary.'
|
|
104
|
+
- rule: 'Bind target via wrap (default-slot first non-menu-item-ui child) OR [for] selector. The selector form is useful for whole-table or whole-canvas menus where wrapping isn''t practical.'
|
|
105
|
+
reason: 'Two binding shapes.'
|
|
106
|
+
anti_patterns:
|
|
107
|
+
- wrong: '<context-menu-ui>...just items...</context-menu-ui>'
|
|
108
|
+
why: 'No target binding — the menu never opens.'
|
|
109
|
+
fix: 'Wrap a target: `<context-menu-ui><my-target></my-target>...items</context-menu-ui>` OR point at one: `<context-menu-ui for="#my-target">...items</context-menu-ui>`.'
|
|
110
|
+
examples:
|
|
111
|
+
- name: file-actions
|
|
112
|
+
description: Right-click a file row for Open / Rename / Delete.
|
|
113
|
+
a2ui: |
|
|
114
|
+
[
|
|
115
|
+
{ "id": "root", "component": "ContextMenu", "children": ["target", "item-open", "item-rename", "div", "item-delete"] },
|
|
116
|
+
{ "id": "target", "component": "Text", "textContent": "Right-click me" },
|
|
117
|
+
{ "id": "item-open", "component": "MenuItem", "value": "open", "text": "Open" },
|
|
118
|
+
{ "id": "item-rename", "component": "MenuItem", "value": "rename", "text": "Rename" },
|
|
119
|
+
{ "id": "div", "component": "MenuDivider" },
|
|
120
|
+
{ "id": "item-delete", "component": "MenuItem", "value": "delete", "text": "Delete", "variant": "danger" }
|
|
121
|
+
]
|
|
122
|
+
keywords:
|
|
123
|
+
- context-menu
|
|
124
|
+
- right-click
|
|
125
|
+
- menu
|
|
126
|
+
- popup-menu
|
|
127
|
+
synonyms:
|
|
128
|
+
right-click:
|
|
129
|
+
- context-menu
|
|
130
|
+
popup-menu:
|
|
131
|
+
- menu
|
|
132
|
+
- context-menu
|
|
133
|
+
related:
|
|
134
|
+
- menu
|
|
135
|
+
- menu-item
|
|
136
|
+
- popover
|
|
@@ -75,6 +75,21 @@
|
|
|
75
75
|
"type": "string",
|
|
76
76
|
"default": "Select range"
|
|
77
77
|
},
|
|
78
|
+
"placement": {
|
|
79
|
+
"description": "Popover placement relative to the trigger. Default `bottom` centers the two-calendar panel under the trigger (ADR-0034 Rule 2 — ~800px panel >> trigger).",
|
|
80
|
+
"type": "string",
|
|
81
|
+
"enum": [
|
|
82
|
+
"top",
|
|
83
|
+
"bottom",
|
|
84
|
+
"left",
|
|
85
|
+
"right",
|
|
86
|
+
"top-start",
|
|
87
|
+
"top-end",
|
|
88
|
+
"bottom-start",
|
|
89
|
+
"bottom-end"
|
|
90
|
+
],
|
|
91
|
+
"default": "bottom"
|
|
92
|
+
},
|
|
78
93
|
"readonly": {
|
|
79
94
|
"description": "Block edits; allow keyboard navigation for screen-reader inspection.",
|
|
80
95
|
"type": "boolean",
|
|
@@ -144,6 +144,8 @@ export class UIDateRangePicker extends UIFormElement {
|
|
|
144
144
|
placeholder: { type: String, default: 'Select range', reflect: true },
|
|
145
145
|
format: { type: String, default: 'short', reflect: true },
|
|
146
146
|
noPresets: { type: Boolean, default: false, attribute: 'no-presets', reflect: true },
|
|
147
|
+
// Popover placement — yaml documented reflect:true since v1.
|
|
148
|
+
placement: { type: String, default: 'bottom', reflect: true },
|
|
147
149
|
};
|
|
148
150
|
}
|
|
149
151
|
|
|
@@ -91,6 +91,20 @@ props:
|
|
|
91
91
|
default: false
|
|
92
92
|
attribute: no-presets
|
|
93
93
|
reflect: true
|
|
94
|
+
placement:
|
|
95
|
+
description: Popover placement relative to the trigger. Default `bottom` centers the two-calendar panel under the trigger (ADR-0034 Rule 2 — ~800px panel >> trigger).
|
|
96
|
+
type: string
|
|
97
|
+
default: bottom
|
|
98
|
+
reflect: true
|
|
99
|
+
enum:
|
|
100
|
+
- top
|
|
101
|
+
- bottom
|
|
102
|
+
- left
|
|
103
|
+
- right
|
|
104
|
+
- top-start
|
|
105
|
+
- top-end
|
|
106
|
+
- bottom-start
|
|
107
|
+
- bottom-end
|
|
94
108
|
events:
|
|
95
109
|
change:
|
|
96
110
|
description: Fired when the range commits (both `from` AND `to` selected, OR a preset clicked).
|
|
@@ -76,6 +76,21 @@
|
|
|
76
76
|
"type": "string",
|
|
77
77
|
"default": "Select date and time"
|
|
78
78
|
},
|
|
79
|
+
"placement": {
|
|
80
|
+
"description": "Popover placement relative to the trigger. Default `bottom` centers the calendar+time panel under the trigger (ADR-0034 Rule 2 — ~600px panel >> trigger).",
|
|
81
|
+
"type": "string",
|
|
82
|
+
"enum": [
|
|
83
|
+
"top",
|
|
84
|
+
"bottom",
|
|
85
|
+
"left",
|
|
86
|
+
"right",
|
|
87
|
+
"top-start",
|
|
88
|
+
"top-end",
|
|
89
|
+
"bottom-start",
|
|
90
|
+
"bottom-end"
|
|
91
|
+
],
|
|
92
|
+
"default": "bottom"
|
|
93
|
+
},
|
|
79
94
|
"precision": {
|
|
80
95
|
"description": "Time-pane precision. `minute` (default) emits `HH:mm`; `second` exposes the seconds segment and emits `HH:mm:ss`.",
|
|
81
96
|
"type": "string",
|
|
@@ -136,6 +136,8 @@ export class UIDatetimePicker extends UIFormElement {
|
|
|
136
136
|
placeholder: { type: String, default: 'Select date and time', reflect: false },
|
|
137
137
|
format: { type: String, default: 'short', reflect: true },
|
|
138
138
|
locale: { type: String, default: '', reflect: false },
|
|
139
|
+
// Popover placement — yaml documented reflect:true since v1.
|
|
140
|
+
placement: { type: String, default: 'bottom', reflect: true },
|
|
139
141
|
};
|
|
140
142
|
}
|
|
141
143
|
|
|
@@ -439,7 +441,7 @@ export class UIDatetimePicker extends UIFormElement {
|
|
|
439
441
|
// helper. Without this, the popover renders at viewport (0,0).
|
|
440
442
|
this.#anchorCleanup?.();
|
|
441
443
|
this.#anchorCleanup = anchorPopover(this.#triggerRef, this.#popoverRef, {
|
|
442
|
-
placement: this.getAttribute('placement') || 'bottom
|
|
444
|
+
placement: this.getAttribute('placement') || 'bottom', // ADR-0034 Rule 2: panel >> trigger
|
|
443
445
|
gap: 4,
|
|
444
446
|
});
|
|
445
447
|
document.addEventListener('pointerdown', this.#onOutside);
|
|
@@ -64,6 +64,8 @@ document locale. `h12` forces a 12-hour cycle with an AM/PM
|
|
|
64
64
|
open: boolean;
|
|
65
65
|
/** Text shown in the trigger when the value is empty. */
|
|
66
66
|
placeholder: string;
|
|
67
|
+
/** Popover placement relative to the trigger. Default `bottom` centers the calendar+time panel under the trigger (ADR-0034 Rule 2 — ~600px panel >> trigger). */
|
|
68
|
+
placement: 'top' | 'bottom' | 'left' | 'right' | 'top-start' | 'top-end' | 'bottom-start' | 'bottom-end';
|
|
67
69
|
/** Time-pane precision. `minute` (default) emits `HH:mm`; `second` exposes the seconds segment and emits `HH:mm:ss`. */
|
|
68
70
|
precision: 'minute' | 'second';
|
|
69
71
|
/** Block edits; allow keyboard navigation for screen-reader inspection. */
|
|
@@ -104,6 +104,20 @@ props:
|
|
|
104
104
|
description: BCP-47 locale tag used to derive hour-cycle when `hour-cycle` is empty. Falls back to `<html lang>` then to browser default.
|
|
105
105
|
type: string
|
|
106
106
|
default: ''
|
|
107
|
+
placement:
|
|
108
|
+
description: Popover placement relative to the trigger. Default `bottom` centers the calendar+time panel under the trigger (ADR-0034 Rule 2 — ~600px panel >> trigger).
|
|
109
|
+
type: string
|
|
110
|
+
default: bottom
|
|
111
|
+
reflect: true
|
|
112
|
+
enum:
|
|
113
|
+
- top
|
|
114
|
+
- bottom
|
|
115
|
+
- left
|
|
116
|
+
- right
|
|
117
|
+
- top-start
|
|
118
|
+
- top-end
|
|
119
|
+
- bottom-start
|
|
120
|
+
- bottom-end
|
|
107
121
|
events:
|
|
108
122
|
change:
|
|
109
123
|
description: Fired when the value commits (date picked + time edited, OR Apply clicked in explicit-commit mode).
|
|
@@ -29,6 +29,8 @@ export class UIEmptyState extends UIElement {
|
|
|
29
29
|
icon: { type: String, default: '', reflect: true },
|
|
30
30
|
heading: { type: String, default: '', reflect: true },
|
|
31
31
|
description: { type: String, default: '', reflect: true },
|
|
32
|
+
// Semantic variant — yaml documented reflect:true since v1.
|
|
33
|
+
variant: { type: String, default: '', reflect: true },
|
|
32
34
|
// §223 (v0.5.9): minimal layout — single-line muted (no centered column,
|
|
33
35
|
// no padding bump, no icon-size lg). Use for inline empty-table-row /
|
|
34
36
|
// inline placeholder cells where the canvas placeholder is too loud.
|
|
@@ -296,9 +296,14 @@ export class UIFeed {
|
|
|
296
296
|
* @param {string} [opts.position='bottom-right']
|
|
297
297
|
* @param {boolean} [opts.dismissible] override default (true for sticky, false for auto)
|
|
298
298
|
* @param {string} [opts.id]
|
|
299
|
-
* @param {string} [opts.action] Phase 2 — action button label. When set
|
|
300
|
-
*
|
|
301
|
-
*
|
|
299
|
+
* @param {string} [opts.action] Phase 2 — action button label. When set
|
|
300
|
+
* without an explicit duration, the item is
|
|
301
|
+
* sticky (role=alertdialog + focus trap).
|
|
302
|
+
* Pass an explicit numeric `duration` to
|
|
303
|
+
* build the "undo" pattern: the action
|
|
304
|
+
* button shows, but the item auto-dismisses
|
|
305
|
+
* after the timeout. Negative-action UX
|
|
306
|
+
* (delete/archive) typically uses 6000-8000.
|
|
302
307
|
* @param {function} [opts.onAction] Phase 2 — callback invoked when the
|
|
303
308
|
* action button is pressed. Item dismisses
|
|
304
309
|
* after the callback returns.
|
|
@@ -330,8 +335,11 @@ export class UIFeed {
|
|
|
330
335
|
item.heading = heading;
|
|
331
336
|
item.icon = icon;
|
|
332
337
|
item.variant = v;
|
|
333
|
-
// Action-required
|
|
334
|
-
|
|
338
|
+
// Action-required default is sticky; explicit duration honored so callers
|
|
339
|
+
// can build the "undo" pattern (action + timed auto-dismiss). Default
|
|
340
|
+
// (duration unspecified) preserves the original alertdialog sticky behavior.
|
|
341
|
+
const explicitDuration = 'duration' in opts;
|
|
342
|
+
item.duration = action && !explicitDuration ? 0 : duration;
|
|
335
343
|
if (dismissible != null) item.dismissible = !!dismissible;
|
|
336
344
|
if (action) item.action = action;
|
|
337
345
|
if (visibleCount >= max) item.setAttribute('data-queued', '');
|
package/components/feed/feed.css
CHANGED
|
@@ -40,6 +40,10 @@ feed-item-ui[data-closing] {
|
|
|
40
40
|
pointer-events: none; /* Items re-enable pointer-events. */
|
|
41
41
|
width: max-content;
|
|
42
42
|
max-width: var(--feed-max-width, var(--feed-max-width-default));
|
|
43
|
+
/* Items size to their own content (see feed-item-ui width: max-content);
|
|
44
|
+
align them to the lane's anchored edge so short items hug the side
|
|
45
|
+
rather than left-aligning inside a wider container. */
|
|
46
|
+
align-items: flex-end;
|
|
43
47
|
}
|
|
44
48
|
/* Reset native popover defaults. UA stylesheet sets `margin: auto;
|
|
45
49
|
inset: 0; border: solid; padding: 0.25em` which would center the
|
|
@@ -61,11 +65,13 @@ feed-item-ui[data-closing] {
|
|
|
61
65
|
}
|
|
62
66
|
:scope[position="bottom-left"] {
|
|
63
67
|
bottom: var(--feed-offset, var(--feed-offset-default)); left: var(--feed-offset, var(--feed-offset-default)); right: auto;
|
|
68
|
+
align-items: flex-start;
|
|
64
69
|
}
|
|
65
70
|
:scope[position="bottom-center"] {
|
|
66
71
|
bottom: var(--feed-offset, var(--feed-offset-default));
|
|
67
72
|
left: 50%; right: auto;
|
|
68
73
|
transform: translateX(-50%);
|
|
74
|
+
align-items: center;
|
|
69
75
|
}
|
|
70
76
|
:scope[position="top-right"] {
|
|
71
77
|
top: var(--feed-offset, var(--feed-offset-default)); right: var(--feed-offset, var(--feed-offset-default)); bottom: auto;
|
|
@@ -74,12 +80,14 @@ feed-item-ui[data-closing] {
|
|
|
74
80
|
:scope[position="top-left"] {
|
|
75
81
|
top: var(--feed-offset, var(--feed-offset-default)); left: var(--feed-offset, var(--feed-offset-default)); right: auto; bottom: auto;
|
|
76
82
|
flex-direction: column-reverse;
|
|
83
|
+
align-items: flex-start;
|
|
77
84
|
}
|
|
78
85
|
:scope[position="top-center"] {
|
|
79
86
|
top: var(--feed-offset, var(--feed-offset-default)); bottom: auto;
|
|
80
87
|
left: 50%; right: auto;
|
|
81
88
|
transform: translateX(-50%);
|
|
82
89
|
flex-direction: column-reverse;
|
|
90
|
+
align-items: center;
|
|
83
91
|
}
|
|
84
92
|
:scope[position="inline"] {
|
|
85
93
|
position: relative;
|
|
@@ -119,6 +127,12 @@ feed-item-ui[data-closing] {
|
|
|
119
127
|
display: flex;
|
|
120
128
|
align-items: center;
|
|
121
129
|
gap: var(--feed-item-gap);
|
|
130
|
+
/* Size to own content (a one-line "OK" stays narrow), capped at
|
|
131
|
+
max-width (long messages wrap at the bound). The lane container's
|
|
132
|
+
align-items (per [position]) re-aligns short items to the anchored
|
|
133
|
+
edge so they hug the corner instead of left-aligning under a
|
|
134
|
+
wider sibling. */
|
|
135
|
+
width: max-content;
|
|
122
136
|
max-width: var(--feed-item-max-width);
|
|
123
137
|
padding: var(--feed-item-py) var(--feed-item-px);
|
|
124
138
|
background: var(--feed-item-bg);
|
package/components/index.js
CHANGED
|
@@ -79,11 +79,20 @@ export { UIChartLegend } from './chart-legend/chart-legend.js';
|
|
|
79
79
|
export { UIPopover } from './popover/popover.js';
|
|
80
80
|
export { UIAccordion, UIAccordionItem } from './accordion/accordion.js';
|
|
81
81
|
export { UIDivider } from './divider/divider.js';
|
|
82
|
+
export { UIBlockquote } from './blockquote/blockquote.js';
|
|
83
|
+
export { UIRelativeTime } from './relative-time/relative-time.js';
|
|
84
|
+
export { UINumberFormat } from './number-format/number-format.js';
|
|
85
|
+
export { UIPasswordStrength } from './password-strength/password-strength.js';
|
|
86
|
+
export { UITableOfContents } from './toc/toc.js';
|
|
87
|
+
export { UIQRCode } from './qr-code/qr-code.js';
|
|
82
88
|
export { UIPagination } from './pagination/pagination.js';
|
|
83
89
|
export { UICode } from './code/code.js';
|
|
84
90
|
export { UIList, UIListItem } from './list/list.js';
|
|
85
91
|
export { UIListWindow } from './list-window/list-window.js';
|
|
86
92
|
export { UIMenu, UIMenuItem, UIMenuDivider } from './menu/menu.js';
|
|
93
|
+
export { UIContextMenu } from './context-menu/context-menu.js';
|
|
94
|
+
export { UIVisuallyHidden } from './visually-hidden/visually-hidden.js';
|
|
95
|
+
export { UISkipNav } from './skip-nav/skip-nav.js';
|
|
87
96
|
export { UIToolbar, UIToolbarGroup } from './toolbar/toolbar.js';
|
|
88
97
|
export { UINav } from './nav/nav.js';
|
|
89
98
|
export { UINavGroup } from './nav-group/nav-group.js';
|
|
@@ -229,6 +229,15 @@ export class UIIntegrationCard extends UIElement {
|
|
|
229
229
|
if (!this.#logoEl) return;
|
|
230
230
|
const logo = (this.logo || '').trim();
|
|
231
231
|
|
|
232
|
+
// Guard against unresolved AdiaUI template binding descriptors
|
|
233
|
+
// ({{p:N}} placeholders). The integration-card's connected() + render()
|
|
234
|
+
// fires synchronously when the parent template stamps the element, BEFORE
|
|
235
|
+
// the parent's reconciliation pass replaces {{p:N}} with the real value.
|
|
236
|
+
// Skipping here lets the second render (triggered by the reconciliation's
|
|
237
|
+
// property set) render the real logo. Without this guard, icon-ui fires
|
|
238
|
+
// a "not found" warn for every {{p:4}} it receives on first connect.
|
|
239
|
+
if (logo.startsWith('{{p:')) return;
|
|
240
|
+
|
|
232
241
|
// No logo → strip any prior content and hide.
|
|
233
242
|
if (!logo) {
|
|
234
243
|
this.#logoEl.replaceChildren();
|
|
@@ -275,9 +275,10 @@ describe('integration-card-ui — CSS contract (source-grep)', () => {
|
|
|
275
275
|
|
|
276
276
|
expect(CSS).toMatch(/@scope\s*\(\s*integration-card-ui\s*\)/);
|
|
277
277
|
expect(CSS).toMatch(/:where\(:scope\)\s*\{/);
|
|
278
|
-
|
|
279
|
-
expect(CSS).toMatch(/--integration-card-
|
|
280
|
-
expect(CSS).toMatch(/--integration-card-
|
|
278
|
+
// OD-5 sweep: token declarations use -default suffix per component-token-contract.md
|
|
279
|
+
expect(CSS).toMatch(/--integration-card-bg-default:/);
|
|
280
|
+
expect(CSS).toMatch(/--integration-card-border-default:/);
|
|
281
|
+
expect(CSS).toMatch(/--integration-card-radius-default:/);
|
|
281
282
|
});
|
|
282
283
|
|
|
283
284
|
it('keeps status-driven border tint (status="connected") inside @scope', async () => {
|
|
@@ -26,7 +26,13 @@
|
|
|
26
26
|
box-sizing: border-box;
|
|
27
27
|
display: flex;
|
|
28
28
|
flex-direction: column;
|
|
29
|
-
gap
|
|
29
|
+
/* Fallback to --nav-gap-default (cascaded from the ancestor nav-ui
|
|
30
|
+
where it's defined) so child nav-items get the spec spacing even
|
|
31
|
+
when the override token --nav-gap isn't explicitly set. Without
|
|
32
|
+
the fallback `var(--nav-gap)` resolved to empty → invalid gap →
|
|
33
|
+
items packed at 0 px stride. Reported 2026-05-25; latent since
|
|
34
|
+
Apr-20 snapshot. */
|
|
35
|
+
gap: var(--nav-gap, var(--nav-gap-default, var(--a-space-1)));
|
|
30
36
|
position: relative;
|
|
31
37
|
font-weight: var(--nav-group-text-weight);
|
|
32
38
|
}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://adiaui.dev/a2ui/v0_9/components/NumberFormat.json",
|
|
4
|
+
"title": "NumberFormat",
|
|
5
|
+
"description": "Display a numeric value with locale-aware formatting — currency,\npercentage, compact (1.2K / 3.4M), unit, or plain decimal. Wraps\n`Intl.NumberFormat`. Distinct from `<input-ui type=\"number\">`\n(an INPUT primitive); this is a DISPLAY primitive — read-only, no\nform participation, no keyboard handling. Pair with `<stat-ui>` for\nKPI surfaces or use standalone inline within prose.\n",
|
|
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
|
+
"compactDisplay": {
|
|
17
|
+
"description": "When [notation=\"compact\"], controls the compact-form length.\n`short` = \"1.2M\" (default); `long` = \"1.2 million\".\n",
|
|
18
|
+
"type": "string",
|
|
19
|
+
"enum": [
|
|
20
|
+
"short",
|
|
21
|
+
"long"
|
|
22
|
+
],
|
|
23
|
+
"default": "short"
|
|
24
|
+
},
|
|
25
|
+
"component": {
|
|
26
|
+
"const": "NumberFormat"
|
|
27
|
+
},
|
|
28
|
+
"currency": {
|
|
29
|
+
"description": "ISO 4217 currency code (e.g. \"USD\", \"EUR\", \"JPY\"). Required when\n[number-style=\"currency\"]; ignored otherwise.\n",
|
|
30
|
+
"type": "string",
|
|
31
|
+
"default": ""
|
|
32
|
+
},
|
|
33
|
+
"locale": {
|
|
34
|
+
"description": "BCP-47 locale tag for the formatter. Empty defaults to the\ndocument locale (`<html lang>`) then to browser default.\n",
|
|
35
|
+
"type": "string",
|
|
36
|
+
"default": ""
|
|
37
|
+
},
|
|
38
|
+
"maximumFractionDigits": {
|
|
39
|
+
"description": "Maximum fractional digits (0–20). Default `2` for decimal/\ncurrency/percent, `1` for compact notation.\n",
|
|
40
|
+
"type": "number",
|
|
41
|
+
"default": 2
|
|
42
|
+
},
|
|
43
|
+
"minimumFractionDigits": {
|
|
44
|
+
"description": "Minimum fractional digits (0–20). Padded with trailing zeros.\nUseful for currency display to force \".00\" suffix.\n",
|
|
45
|
+
"type": "number",
|
|
46
|
+
"default": 0
|
|
47
|
+
},
|
|
48
|
+
"notation": {
|
|
49
|
+
"description": "`Intl.NumberFormat` `notation` option. `standard` is the\nthousands-grouped form (1,234,567); `compact` is the abbreviated\nform (1.2M); `scientific` and `engineering` are the exponent\nforms. Defaults to `standard`.\n",
|
|
50
|
+
"type": "string",
|
|
51
|
+
"enum": [
|
|
52
|
+
"standard",
|
|
53
|
+
"compact",
|
|
54
|
+
"scientific",
|
|
55
|
+
"engineering"
|
|
56
|
+
],
|
|
57
|
+
"default": "standard"
|
|
58
|
+
},
|
|
59
|
+
"numberStyle": {
|
|
60
|
+
"description": "`Intl.NumberFormat` `style` option. `decimal` (default) renders a\nplain number with locale-aware grouping. `currency` requires\n[currency] to be set. `percent` formats 0–1 as 0%–100%. `unit`\nrequires [unit] to be set (e.g. \"kilobyte\", \"celsius\").\n",
|
|
61
|
+
"type": "string",
|
|
62
|
+
"enum": [
|
|
63
|
+
"decimal",
|
|
64
|
+
"currency",
|
|
65
|
+
"percent",
|
|
66
|
+
"unit"
|
|
67
|
+
],
|
|
68
|
+
"default": "decimal"
|
|
69
|
+
},
|
|
70
|
+
"signDisplay": {
|
|
71
|
+
"description": "`Intl.NumberFormat` `signDisplay` option. `auto` (default) shows\n\"−\" for negatives only; `always` shows \"+\" / \"−\"; `exceptZero`\nshows sign for non-zero only; `never` hides signs.\n",
|
|
72
|
+
"type": "string",
|
|
73
|
+
"enum": [
|
|
74
|
+
"auto",
|
|
75
|
+
"always",
|
|
76
|
+
"exceptZero",
|
|
77
|
+
"never"
|
|
78
|
+
],
|
|
79
|
+
"default": "auto"
|
|
80
|
+
},
|
|
81
|
+
"unit": {
|
|
82
|
+
"description": "`Intl.NumberFormat` unit identifier (e.g. \"kilometer-per-hour\",\n\"celsius\", \"byte\"). Required when [number-style=\"unit\"]; ignored\notherwise. See MDN's NumberFormat docs for the valid set.\n",
|
|
83
|
+
"type": "string",
|
|
84
|
+
"default": ""
|
|
85
|
+
},
|
|
86
|
+
"value": {
|
|
87
|
+
"description": "The numeric value to format. Empty string or non-numeric value\nrenders nothing.\n",
|
|
88
|
+
"type": "number",
|
|
89
|
+
"default": 0
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
"required": [
|
|
93
|
+
"component"
|
|
94
|
+
],
|
|
95
|
+
"unevaluatedProperties": false,
|
|
96
|
+
"x-adiaui": {
|
|
97
|
+
"anti_patterns": [
|
|
98
|
+
{
|
|
99
|
+
"fix": "<number-format-ui value=\"0.5\" number-style=\"percent\"></number-format-ui>\n",
|
|
100
|
+
"why": "Renders \"5,000%\" — Intl.NumberFormat percent style multiplies the\ninput by 100. value=50 means \"5000%\".\n",
|
|
101
|
+
"wrong": "<number-format-ui value=\"50\" number-style=\"percent\"></number-format-ui>\n"
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"fix": "<number-format-ui value=\"9.99\" number-style=\"currency\" currency=\"USD\"></number-format-ui>\n",
|
|
105
|
+
"why": "Missing [currency] code. Renders nothing rather than producing\nmalformed currency output.\n",
|
|
106
|
+
"wrong": "<number-format-ui value=\"9.99\" number-style=\"currency\"></number-format-ui>\n"
|
|
107
|
+
}
|
|
108
|
+
],
|
|
109
|
+
"category": "display",
|
|
110
|
+
"composes": [],
|
|
111
|
+
"events": {},
|
|
112
|
+
"examples": [
|
|
113
|
+
{
|
|
114
|
+
"description": "Plain locale-grouped number — default style.",
|
|
115
|
+
"a2ui": "[\n {\n \"id\": \"n\",\n \"component\": \"NumberFormat\",\n \"value\": 1234567.89\n }\n]\n",
|
|
116
|
+
"name": "decimal"
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
"description": "USD currency display.",
|
|
120
|
+
"a2ui": "[\n {\n \"id\": \"n\",\n \"component\": \"NumberFormat\",\n \"value\": 1299.99,\n \"numberStyle\": \"currency\",\n \"currency\": \"USD\"\n }\n]\n",
|
|
121
|
+
"name": "currency"
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"description": "Fraction → percent (0.876 → 87.6%).",
|
|
125
|
+
"a2ui": "[\n {\n \"id\": \"n\",\n \"component\": \"NumberFormat\",\n \"value\": 0.876,\n \"numberStyle\": \"percent\",\n \"maximumFractionDigits\": 1\n }\n]\n",
|
|
126
|
+
"name": "percent"
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"description": "Compact-form (1.2M, 3.4K).",
|
|
130
|
+
"a2ui": "[\n {\n \"id\": \"n\",\n \"component\": \"NumberFormat\",\n \"value\": 1234567,\n \"notation\": \"compact\"\n }\n]\n",
|
|
131
|
+
"name": "compact"
|
|
132
|
+
}
|
|
133
|
+
],
|
|
134
|
+
"keywords": [
|
|
135
|
+
"number-format",
|
|
136
|
+
"format",
|
|
137
|
+
"currency",
|
|
138
|
+
"percent",
|
|
139
|
+
"percentage",
|
|
140
|
+
"compact",
|
|
141
|
+
"number",
|
|
142
|
+
"locale",
|
|
143
|
+
"intl"
|
|
144
|
+
],
|
|
145
|
+
"name": "UINumberFormat",
|
|
146
|
+
"related": [
|
|
147
|
+
"stat",
|
|
148
|
+
"text",
|
|
149
|
+
"badge",
|
|
150
|
+
"input"
|
|
151
|
+
],
|
|
152
|
+
"slots": {},
|
|
153
|
+
"states": [
|
|
154
|
+
{
|
|
155
|
+
"description": "Default, displaying the formatted value.",
|
|
156
|
+
"name": "idle"
|
|
157
|
+
}
|
|
158
|
+
],
|
|
159
|
+
"status": "stable",
|
|
160
|
+
"synonyms": {
|
|
161
|
+
"currency": [
|
|
162
|
+
"number-format",
|
|
163
|
+
"money",
|
|
164
|
+
"price"
|
|
165
|
+
],
|
|
166
|
+
"number": [
|
|
167
|
+
"number-format",
|
|
168
|
+
"format"
|
|
169
|
+
],
|
|
170
|
+
"percent": [
|
|
171
|
+
"number-format",
|
|
172
|
+
"percentage"
|
|
173
|
+
]
|
|
174
|
+
},
|
|
175
|
+
"tag": "number-format-ui",
|
|
176
|
+
"tokens": {},
|
|
177
|
+
"traits": [],
|
|
178
|
+
"version": 1
|
|
179
|
+
}
|
|
180
|
+
}
|