@adia-ai/web-components 0.6.36 → 0.6.38
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 +48 -1
- package/components/accordion/accordion-item.a2ui.json +3 -0
- package/components/accordion/accordion-item.yaml +5 -0
- package/components/action-list/action-item.a2ui.json +5 -1
- package/components/action-list/action-item.yaml +7 -0
- 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/card/card.a2ui.json +17 -1
- package/components/card/card.yaml +24 -1
- 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.a2ui.json +9 -0
- package/components/empty-state/empty-state.class.js +2 -0
- package/components/empty-state/empty-state.yaml +15 -0
- package/components/feed/feed-item.a2ui.json +5 -0
- package/components/feed/feed-item.yaml +10 -0
- package/components/feed/feed.class.js +13 -5
- package/components/feed/feed.css +14 -0
- package/components/field/field.a2ui.json +6 -0
- package/components/field/field.yaml +10 -0
- package/components/index.js +11 -0
- package/components/inline-edit/inline-edit.a2ui.json +159 -0
- package/components/inline-edit/inline-edit.class.js +184 -0
- package/components/inline-edit/inline-edit.css +62 -0
- package/components/inline-edit/inline-edit.d.ts +52 -0
- package/components/inline-edit/inline-edit.js +12 -0
- package/components/inline-edit/inline-edit.yaml +125 -0
- package/components/integration-card/integration-card.class.js +9 -0
- package/components/integration-card/integration-card.test.js +4 -3
- package/components/list/list-item.a2ui.json +8 -1
- package/components/list/list-item.yaml +12 -0
- package/components/list/list.css +36 -6
- package/components/mark/mark.a2ui.json +109 -0
- package/components/mark/mark.class.js +22 -0
- package/components/mark/mark.css +39 -0
- package/components/mark/mark.d.ts +27 -0
- package/components/mark/mark.js +12 -0
- package/components/mark/mark.yaml +87 -0
- package/components/modal/modal.a2ui.json +9 -0
- package/components/modal/modal.yaml +14 -0
- package/components/nav-group/nav-group.a2ui.json +3 -0
- package/components/nav-group/nav-group.css +7 -1
- package/components/nav-group/nav-group.yaml +5 -0
- package/components/nav-item/nav-item.a2ui.json +3 -0
- package/components/nav-item/nav-item.yaml +5 -0
- 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 +15 -3
- package/components/select/select.a2ui.json +3 -0
- package/components/select/select.class.js +4 -0
- package/components/select/select.yaml +5 -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 +22 -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 +38 -6
- package/components/stat/stat.css +18 -14
- package/components/stepper/stepper-item.a2ui.json +3 -0
- package/components/stepper/stepper-item.yaml +5 -0
- 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/timeline/timeline-item.a2ui.json +8 -1
- package/components/timeline/timeline-item.yaml +12 -0
- 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/tree/tree-item.a2ui.json +5 -1
- package/components/tree/tree-item.yaml +7 -0
- package/components/tree/tree.a2ui.json +3 -0
- package/components/tree/tree.yaml +5 -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 +11 -0
- package/styles/resets.css +10 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/* Host styles (scoped — host IS a context-menu-ui descendant of itself). */
|
|
2
|
+
@scope (context-menu-ui) {
|
|
3
|
+
:scope {
|
|
4
|
+
/* Element itself does not render — it's just a behavioral wrapper.
|
|
5
|
+
Targets (wrapped child / [for] match) render in flow normally. */
|
|
6
|
+
display: contents;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/* Authored items live in light DOM as the source of truth, but render
|
|
10
|
+
ONLY when the surface opens (the surface clones them into the popover).
|
|
11
|
+
Hide them in flow so they don't appear next to the target. */
|
|
12
|
+
:scope > menu-item-ui,
|
|
13
|
+
:scope > menu-divider-ui {
|
|
14
|
+
display: none;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/* Surface styles are NOT scoped to context-menu-ui — the surface is
|
|
19
|
+
appended to document.body (escapes the host's `display: contents` so
|
|
20
|
+
fixed-position + top-layer work), so any @scope rule pinned to
|
|
21
|
+
context-menu-ui as the scope root would miss.
|
|
22
|
+
|
|
23
|
+
Chrome MUST visually match menu-ui's surface — same vocabulary, same
|
|
24
|
+
tokens, same animation. menu-ui is the canonical menu surface; this
|
|
25
|
+
is just the right-click trigger surface for the same menu shape. */
|
|
26
|
+
[data-context-menu-surface] {
|
|
27
|
+
margin: 0;
|
|
28
|
+
padding: var(--a-space-1);
|
|
29
|
+
border: 1px solid var(--a-border-subtle);
|
|
30
|
+
border-radius: var(--a-radius-lg);
|
|
31
|
+
background: var(--a-bg-subtle);
|
|
32
|
+
box-shadow: var(--a-shadow-lg);
|
|
33
|
+
min-width: 10rem;
|
|
34
|
+
font-family: inherit;
|
|
35
|
+
font-size: var(--a-ui-size);
|
|
36
|
+
color: var(--a-fg);
|
|
37
|
+
opacity: 1;
|
|
38
|
+
translate: 0 0;
|
|
39
|
+
transition: opacity var(--a-duration-fast) var(--a-easing-out),
|
|
40
|
+
translate var(--a-duration-fast) var(--a-easing-out);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
[data-context-menu-surface]:popover-open {
|
|
44
|
+
@starting-style {
|
|
45
|
+
opacity: 0;
|
|
46
|
+
translate: 0 -4px;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
[data-context-menu-surface]:not(:popover-open) {
|
|
51
|
+
display: none !important;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
@media (prefers-reduced-motion: reduce) {
|
|
55
|
+
[data-context-menu-surface] { transition: none; }
|
|
56
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `<context-menu-ui>` — Right-click activated menu — the OS-native context-menu pattern as a
|
|
3
|
+
web component. Distinct from `menu-ui` (which is button-triggered):
|
|
4
|
+
same item shape (`menu-item-ui` children), different trigger surface
|
|
5
|
+
(`contextmenu` event), and pointer-anchored positioning instead of
|
|
6
|
+
element-anchored. Pattern: WAI-APG Menu.
|
|
7
|
+
|
|
8
|
+
Two binding modes:
|
|
9
|
+
**A. Wrap.** Default-slot child becomes the target:
|
|
10
|
+
`<context-menu-ui><my-table>...</my-table>...items</context-menu-ui>`.
|
|
11
|
+
**B. Selector.** Point at one or more existing elements via [for]:
|
|
12
|
+
`<context-menu-ui for="#my-table">...items</context-menu-ui>`.
|
|
13
|
+
|
|
14
|
+
On `contextmenu` event on a target: `preventDefault()`, position the
|
|
15
|
+
menu at the pointer coords, show via Popover API. Touch long-press
|
|
16
|
+
(configurable via [long-press-ms]) does the same. Shift+F10 / Menu
|
|
17
|
+
key opens at the focused target's center for keyboard users.
|
|
18
|
+
|
|
19
|
+
*
|
|
20
|
+
* @see https://ui-kit.exe.xyz/site/components/context-menu
|
|
21
|
+
*
|
|
22
|
+
* Type declarations generated by scripts/build/dts-codegen.mjs from
|
|
23
|
+
* the component's `.a2ui.json` sidecar(s). Edit the source `.yaml`,
|
|
24
|
+
* run `npm run build:components`, then `npm run codegen:dts` to
|
|
25
|
+
* regenerate; or hand-author this file fully if rich event types are
|
|
26
|
+
* needed beyond what the yaml `events:` block can express.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
import { UIElement } from '../../core/element.js';
|
|
30
|
+
|
|
31
|
+
export interface ContextMenuCloseEventDetail {
|
|
32
|
+
/** "select" | "outside" | "escape" */
|
|
33
|
+
reason: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export type ContextMenuCloseEvent = CustomEvent<ContextMenuCloseEventDetail>;
|
|
37
|
+
export interface ContextMenuOpenEventDetail {
|
|
38
|
+
/** The target element the menu was opened on. */
|
|
39
|
+
target: string;
|
|
40
|
+
/** Pointer x coord (viewport-relative); null for keyboard activation. */
|
|
41
|
+
x: number;
|
|
42
|
+
/** Pointer y coord; null for keyboard activation. */
|
|
43
|
+
y: number;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export type ContextMenuOpenEvent = CustomEvent<ContextMenuOpenEventDetail>;
|
|
47
|
+
export interface ContextMenuSelectEventDetail {
|
|
48
|
+
/** Selected item's text. */
|
|
49
|
+
text: string;
|
|
50
|
+
/** Selected item's value. */
|
|
51
|
+
value: string;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export type ContextMenuSelectEvent = CustomEvent<ContextMenuSelectEventDetail>;
|
|
55
|
+
|
|
56
|
+
export class UIContextMenu extends UIElement {
|
|
57
|
+
/** CSS selector(s) for target element(s). Empty = use default-slot child. */
|
|
58
|
+
for: string;
|
|
59
|
+
/** Programmatic open state. Set true to open at target center. */
|
|
60
|
+
open: boolean;
|
|
61
|
+
|
|
62
|
+
addEventListener<K extends keyof HTMLElementEventMap>(
|
|
63
|
+
type: K,
|
|
64
|
+
listener: (this: UIContextMenu, ev: HTMLElementEventMap[K]) => unknown,
|
|
65
|
+
options?: boolean | AddEventListenerOptions,
|
|
66
|
+
): void;
|
|
67
|
+
addEventListener(type: 'context-menu-close', listener: (ev: ContextMenuCloseEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
68
|
+
addEventListener(type: 'context-menu-open', listener: (ev: ContextMenuOpenEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
69
|
+
addEventListener(type: 'context-menu-select', listener: (ev: ContextMenuSelectEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
70
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `<context-menu-ui>` — auto-registers the tag on import.
|
|
3
|
+
*
|
|
4
|
+
* For non-side-effect class import (test isolation, tag override), use
|
|
5
|
+
* the `class` subpath:
|
|
6
|
+
*
|
|
7
|
+
* import { UIContextMenu } from '@adia-ai/web-components/components/context-menu/class';
|
|
8
|
+
*
|
|
9
|
+
* @see ../../USAGE.md#registration--auto-vs-explicit
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { defineIfFree } from '../../core/register.js';
|
|
13
|
+
import { UIContextMenu } from './context-menu.class.js';
|
|
14
|
+
|
|
15
|
+
defineIfFree('context-menu-ui', UIContextMenu);
|
|
16
|
+
|
|
17
|
+
export { UIContextMenu };
|
|
@@ -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).
|
|
@@ -85,8 +85,17 @@
|
|
|
85
85
|
"select"
|
|
86
86
|
],
|
|
87
87
|
"slots": {
|
|
88
|
+
"description": {
|
|
89
|
+
"description": "Override slot for the description text. Use for multi-paragraph or richly-marked-up explanatory copy."
|
|
90
|
+
},
|
|
88
91
|
"action": {
|
|
89
92
|
"description": "User-provided action element (e.g. button) displayed below the description"
|
|
93
|
+
},
|
|
94
|
+
"heading": {
|
|
95
|
+
"description": "Override slot for the heading text. Use when richer markup than the plain [heading] attribute is needed (line breaks, inline links, bold emphasis)."
|
|
96
|
+
},
|
|
97
|
+
"icon": {
|
|
98
|
+
"description": "Override slot for the [icon] glyph. Use when the attribute-driven Phosphor icon isn't enough (e.g., custom SVG, illustration, or a styled icon-ui with non-default weight). Mutually exclusive with [icon]."
|
|
90
99
|
}
|
|
91
100
|
},
|
|
92
101
|
"states": [
|
|
@@ -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.
|
|
@@ -53,6 +53,21 @@ props:
|
|
|
53
53
|
reflect: true
|
|
54
54
|
events: {}
|
|
55
55
|
slots:
|
|
56
|
+
icon:
|
|
57
|
+
description: >-
|
|
58
|
+
Override slot for the [icon] glyph. Use when the attribute-driven
|
|
59
|
+
Phosphor icon isn't enough (e.g., custom SVG, illustration, or
|
|
60
|
+
a styled icon-ui with non-default weight). Mutually exclusive
|
|
61
|
+
with [icon].
|
|
62
|
+
heading:
|
|
63
|
+
description: >-
|
|
64
|
+
Override slot for the heading text. Use when richer markup than
|
|
65
|
+
the plain [heading] attribute is needed (line breaks, inline
|
|
66
|
+
links, bold emphasis).
|
|
67
|
+
description:
|
|
68
|
+
description: >-
|
|
69
|
+
Override slot for the description text. Use for multi-paragraph
|
|
70
|
+
or richly-marked-up explanatory copy.
|
|
56
71
|
action:
|
|
57
72
|
description: User-provided action element (e.g. button) displayed below the description
|
|
58
73
|
states:
|
|
@@ -13,6 +13,11 @@
|
|
|
13
13
|
}
|
|
14
14
|
],
|
|
15
15
|
"properties": {
|
|
16
|
+
"action": {
|
|
17
|
+
"description": "Label of an inline action button (the \"deep-link\" / \"undo\" pattern).\nPair with `onAction` callback in `UIFeed.post()` — click invokes the\ncallback then auto-dismisses. Empty string renders no action button.\n",
|
|
18
|
+
"type": "string",
|
|
19
|
+
"default": ""
|
|
20
|
+
},
|
|
16
21
|
"component": {
|
|
17
22
|
"const": "FeedItem"
|
|
18
23
|
},
|
|
@@ -42,6 +42,14 @@ props:
|
|
|
42
42
|
description: Render an x close button (default true for sticky, false for auto-fade)
|
|
43
43
|
type: boolean
|
|
44
44
|
default: false
|
|
45
|
+
action:
|
|
46
|
+
description: |
|
|
47
|
+
Label of an inline action button (the "deep-link" / "undo" pattern).
|
|
48
|
+
Pair with `onAction` callback in `UIFeed.post()` — click invokes the
|
|
49
|
+
callback then auto-dismisses. Empty string renders no action button.
|
|
50
|
+
type: string
|
|
51
|
+
default: ""
|
|
52
|
+
reflect: true
|
|
45
53
|
events:
|
|
46
54
|
close:
|
|
47
55
|
description: Fired after the item finishes its exit animation
|
|
@@ -74,3 +82,5 @@ a2ui:
|
|
|
74
82
|
reason: 'Imperative ownership.'
|
|
75
83
|
- rule: 'Different from <alert-ui> (inline persistent) and <toast-ui> (standalone ephemeral); feed-item is feed-scoped.'
|
|
76
84
|
reason: 'Surface boundary.'
|
|
85
|
+
- rule: 'For "notification deep-link" pattern: post with action + onAction. Click navigates and auto-dismisses (router.push() / location.href / api.markRead()).'
|
|
86
|
+
reason: 'Deep-link pattern lives in the onAction callback, not in markup.'
|
|
@@ -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);
|
|
@@ -103,6 +103,12 @@
|
|
|
103
103
|
"action": {
|
|
104
104
|
"description": "Button adjacent to the control for inline actions (clear, reset, help popover)."
|
|
105
105
|
},
|
|
106
|
+
"error": {
|
|
107
|
+
"description": "Override slot for error markup richer than the plain [error] attribute string. Rendered below the control with danger-text styling. Mutually exclusive with [error]."
|
|
108
|
+
},
|
|
109
|
+
"hint": {
|
|
110
|
+
"description": "Override slot for hint markup richer than the plain [hint] attribute string (inline links, code spans, abbreviations). Rendered below the control at body-subtle typography. Mutually exclusive with [hint]."
|
|
111
|
+
},
|
|
106
112
|
"trailing": {
|
|
107
113
|
"description": "Secondary text or badge aligned with the label in the stacked layout (right-aligned) or between label and control in the inline layout."
|
|
108
114
|
}
|
|
@@ -89,6 +89,16 @@ slots:
|
|
|
89
89
|
description: >-
|
|
90
90
|
Button adjacent to the control for inline actions (clear,
|
|
91
91
|
reset, help popover).
|
|
92
|
+
hint:
|
|
93
|
+
description: >-
|
|
94
|
+
Override slot for hint markup richer than the plain [hint] attribute
|
|
95
|
+
string (inline links, code spans, abbreviations). Rendered below
|
|
96
|
+
the control at body-subtle typography. Mutually exclusive with [hint].
|
|
97
|
+
error:
|
|
98
|
+
description: >-
|
|
99
|
+
Override slot for error markup richer than the plain [error] attribute
|
|
100
|
+
string. Rendered below the control with danger-text styling. Mutually
|
|
101
|
+
exclusive with [error].
|
|
92
102
|
states:
|
|
93
103
|
- name: idle
|
|
94
104
|
description: Default, ready for interaction.
|
package/components/index.js
CHANGED
|
@@ -79,11 +79,22 @@ 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';
|
|
96
|
+
export { UIMark } from './mark/mark.js';
|
|
97
|
+
export { UIInlineEdit } from './inline-edit/inline-edit.js';
|
|
87
98
|
export { UIToolbar, UIToolbarGroup } from './toolbar/toolbar.js';
|
|
88
99
|
export { UINav } from './nav/nav.js';
|
|
89
100
|
export { UINavGroup } from './nav-group/nav-group.js';
|