@zeyos/zx 4.2.0 → 4.3.0
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 +37 -0
- package/README.md +5 -0
- package/dist/types/components/calendar/calendar.d.ts +19 -2
- package/dist/types/components/dialog/dialog.d.ts +6 -1
- package/dist/types/components/dropdown/dropdown.d.ts +5 -0
- package/dist/types/components/launcher/launcher.d.ts +5 -0
- package/dist/types/components/message/message.d.ts +9 -1
- package/dist/types/components/modal/modal.d.ts +44 -7
- package/dist/types/components/sheet/sheet.d.ts +22 -12
- package/dist/types/core/overlay-host.d.ts +12 -0
- package/dist/zx-zeyos.esm.js +138 -32
- package/dist/zx-zeyos.esm.min.js +1 -1
- package/dist/zx.css +259 -132
- package/dist/zx.esm.js +277 -82
- package/dist/zx.esm.min.js +3 -3
- package/dist/zx.global.js +277 -82
- package/dist/zx.global.min.js +3 -3
- package/dist/zx.min.css +1 -1
- package/docs/api.json +36 -0
- package/docs/llms.md +37 -18
- package/docs/llms.txt +1 -1
- package/package.json +1 -1
- package/src/components/account-menu/account-menu.css +1 -1
- package/src/components/app-rail/app-rail.css +1 -1
- package/src/components/calendar/calendar.css +66 -24
- package/src/components/calendar/calendar.js +114 -19
- package/src/components/context-menu/context-menu.css +2 -2
- package/src/components/context-menu/context-menu.js +5 -1
- package/src/components/date-picker/date-picker.css +18 -11
- package/src/components/datebox/date-range-box.css +4 -2
- package/src/components/datebox/datebox.css +4 -2
- package/src/components/dialog/dialog.css +4 -3
- package/src/components/dialog/dialog.js +2 -1
- package/src/components/dropdown/dropdown.css +4 -2
- package/src/components/dropdown/dropdown.js +7 -2
- package/src/components/launcher/launcher.css +10 -8
- package/src/components/launcher/launcher.js +9 -2
- package/src/components/menu-button/menu-button.css +2 -2
- package/src/components/message/message.css +7 -16
- package/src/components/message/message.js +17 -11
- package/src/components/modal/modal.css +6 -4
- package/src/components/modal/modal.js +99 -25
- package/src/components/select/select.css +9 -7
- package/src/components/sheet/sheet.css +25 -7
- package/src/components/sheet/sheet.js +43 -23
- package/src/components/table/table.css +5 -3
- package/src/components/tag-picker/tag-picker.css +5 -3
- package/src/components/tooltip/tooltip.css +4 -2
- package/src/components/tooltip/tooltip.js +4 -1
- package/src/core/overlay-host.js +23 -0
- package/styles/tokens/dark.css +4 -0
- package/styles/tokens/semantic.css +83 -8
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
|
|
30
30
|
.zx-context-menu__item:hover,
|
|
31
31
|
.zx-context-menu__item:focus-visible {
|
|
32
|
-
background: var(--zx-color-
|
|
32
|
+
background: var(--zx-color-overlay-hover);
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
.zx-context-menu__item[data-danger="true"] {
|
|
@@ -50,5 +50,5 @@
|
|
|
50
50
|
.zx-context-menu__separator {
|
|
51
51
|
block-size: 1px;
|
|
52
52
|
margin: var(--zx-space-1) var(--zx-space-2);
|
|
53
|
-
background: var(--zx-color-
|
|
53
|
+
background: var(--zx-color-overlay-divider);
|
|
54
54
|
}
|
|
@@ -82,7 +82,11 @@ export class ContextMenu extends Component {
|
|
|
82
82
|
this.#target = resolved;
|
|
83
83
|
document.body.append(this.el);
|
|
84
84
|
|
|
85
|
-
this.#dropdown = new Dropdown(this.el, {
|
|
85
|
+
this.#dropdown = new Dropdown(this.el, {
|
|
86
|
+
openOn: 'manual',
|
|
87
|
+
placement: 'bottom-start',
|
|
88
|
+
scope: resolved
|
|
89
|
+
});
|
|
86
90
|
this.#panel = this.#dropdown.getPanel();
|
|
87
91
|
this.#panel.classList.add('zx-context-menu');
|
|
88
92
|
this.#panel.setAttribute('role', 'menu');
|
|
@@ -31,14 +31,14 @@
|
|
|
31
31
|
place-items: center;
|
|
32
32
|
min-inline-size: var(--zx-control-height);
|
|
33
33
|
padding: 0;
|
|
34
|
-
border-color:
|
|
35
|
-
background:
|
|
34
|
+
border-color: transparent;
|
|
35
|
+
background: transparent;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
.zx-date-picker__heading {
|
|
39
39
|
overflow: hidden;
|
|
40
|
-
border-color:
|
|
41
|
-
background:
|
|
40
|
+
border-color: transparent;
|
|
41
|
+
background: transparent;
|
|
42
42
|
font-weight: 650;
|
|
43
43
|
text-overflow: ellipsis;
|
|
44
44
|
text-wrap: nowrap;
|
|
@@ -76,9 +76,9 @@
|
|
|
76
76
|
min-inline-size: 0;
|
|
77
77
|
min-block-size: var(--zx-control-height);
|
|
78
78
|
padding: 0;
|
|
79
|
-
border-color:
|
|
79
|
+
border-color: transparent;
|
|
80
80
|
border-radius: var(--zx-radius-md);
|
|
81
|
-
background:
|
|
81
|
+
background: transparent;
|
|
82
82
|
font-variant-numeric: tabular-nums;
|
|
83
83
|
}
|
|
84
84
|
|
|
@@ -125,10 +125,12 @@
|
|
|
125
125
|
inset: var(--zx-space-3);
|
|
126
126
|
border: 1px solid var(--zx-color-overlay-border);
|
|
127
127
|
border-radius: var(--zx-radius-md);
|
|
128
|
-
background: var(--zx-color-overlay-surface);
|
|
128
|
+
background-color: var(--zx-color-overlay-surface);
|
|
129
|
+
background-image: var(--zx-overlay-surface-image);
|
|
130
|
+
background-clip: padding-box;
|
|
129
131
|
-webkit-backdrop-filter: var(--zx-glass-filter-overlay);
|
|
130
132
|
backdrop-filter: var(--zx-glass-filter-overlay);
|
|
131
|
-
box-shadow: var(--zx-glass-
|
|
133
|
+
box-shadow: var(--zx-glass-overlay-shadow);
|
|
132
134
|
padding: var(--zx-space-3);
|
|
133
135
|
}
|
|
134
136
|
|
|
@@ -157,11 +159,16 @@
|
|
|
157
159
|
.zx-month-picker__month {
|
|
158
160
|
min-inline-size: 0;
|
|
159
161
|
padding-inline: var(--zx-space-1);
|
|
160
|
-
border-color:
|
|
161
|
-
background:
|
|
162
|
+
border-color: transparent;
|
|
163
|
+
background: transparent;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.zx-date-picker__quick-month[aria-selected="true"] {
|
|
167
|
+
background: var(--zx-color-overlay-selected);
|
|
168
|
+
color: var(--zx-color-accent);
|
|
169
|
+
font-weight: 700;
|
|
162
170
|
}
|
|
163
171
|
|
|
164
|
-
.zx-date-picker__quick-month[aria-selected="true"],
|
|
165
172
|
.zx-month-picker__month[aria-selected="true"] {
|
|
166
173
|
background: var(--zx-color-bg-selected);
|
|
167
174
|
color: var(--zx-color-accent);
|
|
@@ -124,10 +124,12 @@
|
|
|
124
124
|
.zx-date-range-box__popover .zx-date-range-picker__surface {
|
|
125
125
|
max-inline-size: none;
|
|
126
126
|
border-color: var(--zx-color-overlay-border);
|
|
127
|
-
background: var(--zx-color-overlay-surface);
|
|
127
|
+
background-color: var(--zx-color-overlay-surface);
|
|
128
|
+
background-image: var(--zx-overlay-surface-image);
|
|
129
|
+
background-clip: padding-box;
|
|
128
130
|
-webkit-backdrop-filter: var(--zx-glass-filter-overlay);
|
|
129
131
|
backdrop-filter: var(--zx-glass-filter-overlay);
|
|
130
|
-
box-shadow: var(--zx-glass-
|
|
132
|
+
box-shadow: var(--zx-glass-overlay-shadow);
|
|
131
133
|
}
|
|
132
134
|
|
|
133
135
|
@media (prefers-reduced-transparency: reduce) {
|
|
@@ -104,10 +104,12 @@
|
|
|
104
104
|
|
|
105
105
|
.zx-datebox__popover .zx-date-picker__surface {
|
|
106
106
|
border-color: var(--zx-color-overlay-border);
|
|
107
|
-
background: var(--zx-color-overlay-surface);
|
|
107
|
+
background-color: var(--zx-color-overlay-surface);
|
|
108
|
+
background-image: var(--zx-overlay-surface-image);
|
|
109
|
+
background-clip: padding-box;
|
|
108
110
|
-webkit-backdrop-filter: var(--zx-glass-filter-overlay);
|
|
109
111
|
backdrop-filter: var(--zx-glass-filter-overlay);
|
|
110
|
-
box-shadow: var(--zx-glass-
|
|
112
|
+
box-shadow: var(--zx-glass-overlay-shadow);
|
|
111
113
|
}
|
|
112
114
|
|
|
113
115
|
@media (prefers-reduced-transparency: reduce) {
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
padding: 0;
|
|
4
4
|
}
|
|
5
5
|
|
|
6
|
-
.zx-dialog[open]
|
|
6
|
+
.zx-dialog[open],
|
|
7
|
+
.zx-dialog:popover-open {
|
|
7
8
|
display: grid;
|
|
8
9
|
}
|
|
9
10
|
|
|
@@ -17,7 +18,7 @@
|
|
|
17
18
|
|
|
18
19
|
.zx-dialog__header {
|
|
19
20
|
justify-content: space-between;
|
|
20
|
-
border-block-end: 1px solid var(--zx-color-
|
|
21
|
+
border-block-end: 1px solid var(--zx-color-overlay-divider);
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
.zx-dialog__title {
|
|
@@ -40,7 +41,7 @@
|
|
|
40
41
|
|
|
41
42
|
.zx-dialog__footer {
|
|
42
43
|
justify-content: flex-end;
|
|
43
|
-
border-block-start: 1px solid var(--zx-color-
|
|
44
|
+
border-block-start: 1px solid var(--zx-color-overlay-divider);
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
.zx-dialog__footer[hidden] {
|
|
@@ -22,6 +22,7 @@ const FOCUSABLE_SELECTOR = [
|
|
|
22
22
|
* @property {DialogButton[]} [buttons=[]] Footer buttons.
|
|
23
23
|
* @property {boolean} [closable=true] Whether Escape and the header button may close the dialog.
|
|
24
24
|
* @property {Node|string|number|{toElement: () => Node|null}|null} [content=null] Body content.
|
|
25
|
+
* @property {Element|string|null} [scope=null] Element whose nearest Zx theme scope owns the overlay; defaults to the opener.
|
|
25
26
|
* @property {(event: CustomEvent<Record<string, never>>) => void} [onopen] Open event listener.
|
|
26
27
|
* @property {(event: CustomEvent<{result: unknown}>) => void} [onclose] Close event listener.
|
|
27
28
|
* @property {(event: CustomEvent<Record<string, never>>) => void} [oncancel] Cancel event listener.
|
|
@@ -89,7 +90,7 @@ export class Dialog extends Modal {
|
|
|
89
90
|
#opener = null;
|
|
90
91
|
|
|
91
92
|
/**
|
|
92
|
-
* Creates a structured dialog
|
|
93
|
+
* Creates a structured dialog in the configured theme scope, or at document level when unscoped.
|
|
93
94
|
* @param {Element|string|null} [_target=null] Ignored; Dialog always owns its root.
|
|
94
95
|
* @param {DialogOptions} [options={}] Dialog options.
|
|
95
96
|
*/
|
|
@@ -4,10 +4,12 @@
|
|
|
4
4
|
overflow: auto;
|
|
5
5
|
border: 1px solid var(--zx-color-overlay-border);
|
|
6
6
|
border-radius: var(--zx-radius-md);
|
|
7
|
-
background: var(--zx-color-overlay-surface);
|
|
7
|
+
background-color: var(--zx-color-overlay-surface);
|
|
8
|
+
background-image: var(--zx-overlay-surface-image);
|
|
9
|
+
background-clip: padding-box;
|
|
8
10
|
-webkit-backdrop-filter: var(--zx-glass-filter-overlay);
|
|
9
11
|
backdrop-filter: var(--zx-glass-filter-overlay);
|
|
10
|
-
box-shadow: var(--zx-glass-
|
|
12
|
+
box-shadow: var(--zx-glass-overlay-shadow);
|
|
11
13
|
color: var(--zx-color-text);
|
|
12
14
|
padding: var(--zx-space-3);
|
|
13
15
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Component } from '../../core/component.js';
|
|
2
2
|
import { h, resolveElement } from '../../core/dom.js';
|
|
3
|
+
import { overlayHost } from '../../core/overlay-host.js';
|
|
3
4
|
import { position } from '../../core/position.js';
|
|
4
5
|
import { uid } from '../../core/util.js';
|
|
5
6
|
|
|
@@ -14,6 +15,7 @@ const HANDLE_ESCAPE_DISMISS = Symbol('zxDropdownEscapeDismiss');
|
|
|
14
15
|
* @property {boolean} [matchWidth=false] Whether the panel matches the anchor width.
|
|
15
16
|
* @property {'click'|'manual'} [openOn='click'] Trigger behavior.
|
|
16
17
|
* @property {boolean} [closeOnSelect=false] Whether a click within the panel closes it.
|
|
18
|
+
* @property {Element|string|null} [scope=null] Element whose nearest Zx theme scope owns the panel; defaults to the anchor.
|
|
17
19
|
* @property {(event: CustomEvent<Record<string, never>>) => void} [onopen] Open event listener.
|
|
18
20
|
* @property {(event: CustomEvent<Record<string, never>>) => void} [onclose] Close event listener.
|
|
19
21
|
*/
|
|
@@ -34,7 +36,8 @@ export class Dropdown extends Component {
|
|
|
34
36
|
offset: 4,
|
|
35
37
|
matchWidth: false,
|
|
36
38
|
openOn: 'click',
|
|
37
|
-
closeOnSelect: false
|
|
39
|
+
closeOnSelect: false,
|
|
40
|
+
scope: null
|
|
38
41
|
};
|
|
39
42
|
|
|
40
43
|
/** @type {Element} */
|
|
@@ -55,6 +58,7 @@ export class Dropdown extends Component {
|
|
|
55
58
|
if (!resolved) throw new TypeError('Dropdown anchor could not be resolved');
|
|
56
59
|
super(null, options);
|
|
57
60
|
this.#anchor = resolved;
|
|
61
|
+
overlayHost(this.options.scope ?? resolved).append(this.el);
|
|
58
62
|
this.#rememberAnchorAttribute('aria-expanded');
|
|
59
63
|
this.#rememberAnchorAttribute('aria-controls');
|
|
60
64
|
this.#anchor.setAttribute('aria-expanded', 'false');
|
|
@@ -79,7 +83,6 @@ export class Dropdown extends Component {
|
|
|
79
83
|
popover: 'manual'
|
|
80
84
|
});
|
|
81
85
|
panel.dataset.state = 'closed';
|
|
82
|
-
document.body.append(panel);
|
|
83
86
|
return panel;
|
|
84
87
|
}
|
|
85
88
|
|
|
@@ -90,6 +93,8 @@ export class Dropdown extends Component {
|
|
|
90
93
|
*/
|
|
91
94
|
open() {
|
|
92
95
|
if (this.isOpen() || this.#destroyed) return this;
|
|
96
|
+
const host = overlayHost(this.options.scope ?? this.#anchor);
|
|
97
|
+
if (this.el.parentElement !== host) host.append(this.el);
|
|
93
98
|
this.#position = position(this.#anchor, this.el, {
|
|
94
99
|
placement: this.options.placement,
|
|
95
100
|
offset: Number(this.options.offset),
|
|
@@ -3,10 +3,12 @@
|
|
|
3
3
|
max-block-size: min(720px, calc(100vh - (2 * var(--zx-space-6))));
|
|
4
4
|
border: 1px solid var(--zx-color-overlay-border);
|
|
5
5
|
border-radius: var(--zx-radius-xl);
|
|
6
|
-
background: var(--zx-color-overlay-panel);
|
|
6
|
+
background-color: var(--zx-color-overlay-panel);
|
|
7
|
+
background-image: var(--zx-overlay-panel-image);
|
|
8
|
+
background-clip: padding-box;
|
|
7
9
|
-webkit-backdrop-filter: var(--zx-glass-filter-panel);
|
|
8
10
|
backdrop-filter: var(--zx-glass-filter-panel);
|
|
9
|
-
box-shadow: var(--zx-glass-
|
|
11
|
+
box-shadow: var(--zx-glass-panel-shadow);
|
|
10
12
|
color: var(--zx-color-text);
|
|
11
13
|
padding: 0;
|
|
12
14
|
}
|
|
@@ -22,7 +24,7 @@
|
|
|
22
24
|
}
|
|
23
25
|
|
|
24
26
|
.zx-launcher::backdrop {
|
|
25
|
-
background: var(--zx-color-
|
|
27
|
+
background: var(--zx-color-overlay-backdrop);
|
|
26
28
|
}
|
|
27
29
|
|
|
28
30
|
.zx-launcher__surface {
|
|
@@ -36,7 +38,7 @@
|
|
|
36
38
|
grid-template-columns: auto minmax(0, 1fr) auto auto;
|
|
37
39
|
align-items: center;
|
|
38
40
|
gap: var(--zx-space-3);
|
|
39
|
-
border-block-end: 1px solid var(--zx-color-
|
|
41
|
+
border-block-end: 1px solid var(--zx-color-overlay-divider);
|
|
40
42
|
padding: var(--zx-space-3) var(--zx-space-4);
|
|
41
43
|
}
|
|
42
44
|
|
|
@@ -129,11 +131,11 @@
|
|
|
129
131
|
|
|
130
132
|
.zx-launcher__option[aria-selected="true"],
|
|
131
133
|
.zx-launcher__option:hover {
|
|
132
|
-
background: var(--zx-color-
|
|
134
|
+
background: var(--zx-color-overlay-hover);
|
|
133
135
|
}
|
|
134
136
|
|
|
135
137
|
.zx-launcher__option[aria-current="page"] {
|
|
136
|
-
background: var(--zx-color-
|
|
138
|
+
background: var(--zx-color-overlay-selected);
|
|
137
139
|
color: var(--zx-color-accent);
|
|
138
140
|
}
|
|
139
141
|
|
|
@@ -148,7 +150,7 @@
|
|
|
148
150
|
}
|
|
149
151
|
|
|
150
152
|
.zx-launcher__option[data-kind="application"][aria-current="page"] {
|
|
151
|
-
background: var(--zx-color-
|
|
153
|
+
background: var(--zx-color-overlay-selected);
|
|
152
154
|
}
|
|
153
155
|
|
|
154
156
|
.zx-launcher__option[data-kind="application"] .zx-launcher__icon {
|
|
@@ -187,7 +189,7 @@
|
|
|
187
189
|
justify-content: end;
|
|
188
190
|
gap: var(--zx-space-4);
|
|
189
191
|
padding: var(--zx-space-2) var(--zx-space-4);
|
|
190
|
-
border-block-start: 1px solid var(--zx-color-
|
|
192
|
+
border-block-start: 1px solid var(--zx-color-overlay-divider);
|
|
191
193
|
color: var(--zx-color-text-muted);
|
|
192
194
|
font-size: var(--zx-text-xs);
|
|
193
195
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Component } from '../../core/component.js';
|
|
2
2
|
import { h, safeHref } from '../../core/dom.js';
|
|
3
3
|
import { icon } from '../../core/icons.js';
|
|
4
|
+
import { overlayHost } from '../../core/overlay-host.js';
|
|
4
5
|
import { uid } from '../../core/util.js';
|
|
5
6
|
|
|
6
7
|
/**
|
|
@@ -49,6 +50,7 @@ import { uid } from '../../core/util.js';
|
|
|
49
50
|
* @property {string} [loadingText='Searching…'] Loading-state text.
|
|
50
51
|
* @property {'mod+k'|false} [shortcut='mod+k'] Optional global keyboard shortcut.
|
|
51
52
|
* @property {false|{move?: string, open?: string, close?: string}} [hints] Visible keyboard hints, or false.
|
|
53
|
+
* @property {Element|string|null} [scope=null] Element whose nearest Zx theme scope owns an internally created launcher; defaults to the opener.
|
|
52
54
|
* @property {(event: CustomEvent<LauncherSelectDetail>) => void} [onselect] Preventable selection listener.
|
|
53
55
|
* @property {(event: CustomEvent<{query: string}>) => void} [onquery] Query-change listener.
|
|
54
56
|
* @property {(event: CustomEvent<Record<string, never>>) => void} [onopen] Open listener.
|
|
@@ -85,7 +87,8 @@ export class Launcher extends Component {
|
|
|
85
87
|
emptyText: 'No results',
|
|
86
88
|
loadingText: 'Searching…',
|
|
87
89
|
shortcut: 'mod+k',
|
|
88
|
-
hints: { move: 'Move', open: 'Open', close: 'Close' }
|
|
90
|
+
hints: { move: 'Move', open: 'Open', close: 'Close' },
|
|
91
|
+
scope: null
|
|
89
92
|
};
|
|
90
93
|
|
|
91
94
|
/**
|
|
@@ -172,7 +175,7 @@ export class Launcher extends Component {
|
|
|
172
175
|
results,
|
|
173
176
|
footer));
|
|
174
177
|
dialog.dataset.state = 'closed';
|
|
175
|
-
if (this._createdRoot)
|
|
178
|
+
if (this._createdRoot) overlayHost(this.options.scope).append(dialog);
|
|
176
179
|
|
|
177
180
|
this.listen(input, 'input', () => {
|
|
178
181
|
this._query = /** @type {HTMLInputElement} */ (input).value;
|
|
@@ -212,6 +215,10 @@ export class Launcher extends Component {
|
|
|
212
215
|
/** Opens the launcher and focuses/selects its query. @returns {this} @fires Launcher#open */
|
|
213
216
|
open() {
|
|
214
217
|
if (this.isOpen() || this._destroyed) return this;
|
|
218
|
+
if (this._createdRoot) {
|
|
219
|
+
const host = overlayHost(this.options.scope);
|
|
220
|
+
if (this.el.parentElement !== host) host.append(this.el);
|
|
221
|
+
}
|
|
215
222
|
this.el.showModal();
|
|
216
223
|
this.el.dataset.state = 'open';
|
|
217
224
|
this.refs.input.setAttribute('aria-expanded', 'true');
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
|
|
25
25
|
.zx-menu-button__item:hover,
|
|
26
26
|
.zx-menu-button__item:focus-visible {
|
|
27
|
-
background: var(--zx-color-
|
|
27
|
+
background: var(--zx-color-overlay-hover);
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
.zx-menu-button__item[data-danger="true"] {
|
|
@@ -45,5 +45,5 @@
|
|
|
45
45
|
.zx-menu-button__separator {
|
|
46
46
|
block-size: 1px;
|
|
47
47
|
margin: var(--zx-space-1) var(--zx-space-2);
|
|
48
|
-
background: var(--zx-color-
|
|
48
|
+
background: var(--zx-color-overlay-divider);
|
|
49
49
|
}
|
|
@@ -55,24 +55,15 @@
|
|
|
55
55
|
background: var(--zx-color-danger-bg);
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
@supports (backdrop-filter: blur(1px)) {
|
|
58
|
+
@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
|
|
59
59
|
.zx-message__toast {
|
|
60
|
-
|
|
60
|
+
border-color: color-mix(in srgb, var(--zx-message-kind) 28%, var(--zx-color-overlay-border));
|
|
61
|
+
background-color: var(--zx-color-overlay-surface);
|
|
62
|
+
background-image: var(--zx-overlay-toast-image);
|
|
63
|
+
background-clip: padding-box;
|
|
61
64
|
-webkit-backdrop-filter: var(--zx-glass-filter-overlay);
|
|
62
65
|
backdrop-filter: var(--zx-glass-filter-overlay);
|
|
63
|
-
box-shadow:
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
.zx-message__toast[data-kind="success"] {
|
|
67
|
-
background: color-mix(in srgb, var(--zx-color-success-bg) 34%, var(--zx-color-overlay-surface));
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
.zx-message__toast[data-kind="warning"] {
|
|
71
|
-
background: color-mix(in srgb, var(--zx-color-warning-bg) 34%, var(--zx-color-overlay-surface));
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
.zx-message__toast[data-kind="error"] {
|
|
75
|
-
background: color-mix(in srgb, var(--zx-color-danger-bg) 34%, var(--zx-color-overlay-surface));
|
|
66
|
+
box-shadow: var(--zx-glass-overlay-shadow);
|
|
76
67
|
}
|
|
77
68
|
}
|
|
78
69
|
|
|
@@ -111,7 +102,7 @@
|
|
|
111
102
|
block-size: 4px;
|
|
112
103
|
margin-block-start: var(--zx-space-2);
|
|
113
104
|
border-radius: var(--zx-radius-full);
|
|
114
|
-
background: var(--zx-color-
|
|
105
|
+
background: var(--zx-color-overlay-divider);
|
|
115
106
|
}
|
|
116
107
|
|
|
117
108
|
.zx-message__progress-fill {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Component } from '../../core/component.js';
|
|
2
2
|
import { h } from '../../core/dom.js';
|
|
3
3
|
import { icon } from '../../core/icons.js';
|
|
4
|
+
import { overlayHost } from '../../core/overlay-host.js';
|
|
4
5
|
|
|
5
6
|
/** @typedef {'info'|'success'|'warning'|'error'} MessageKind */
|
|
6
7
|
|
|
@@ -9,6 +10,7 @@ import { icon } from '../../core/icons.js';
|
|
|
9
10
|
* @property {MessageKind|'danger'} [kind='info'] Message intent (`danger` aliases `error`).
|
|
10
11
|
* @property {number} [timeout=4000] Auto-dismiss delay in milliseconds; zero persists.
|
|
11
12
|
* @property {boolean} [closable=true] Whether to render a close button.
|
|
13
|
+
* @property {Element|string|null} [scope=null] Element whose nearest Zx theme scope owns a floating toast.
|
|
12
14
|
*/
|
|
13
15
|
|
|
14
16
|
/**
|
|
@@ -133,8 +135,8 @@ export class Message extends Component {
|
|
|
133
135
|
maxVisible: 5
|
|
134
136
|
};
|
|
135
137
|
|
|
136
|
-
/** @type {Message
|
|
137
|
-
static #floating =
|
|
138
|
+
/** @type {WeakMap<Element, Message>} */
|
|
139
|
+
static #floating = new WeakMap();
|
|
138
140
|
|
|
139
141
|
/** @returns {HTMLElement} */
|
|
140
142
|
render() {
|
|
@@ -217,16 +219,17 @@ export class Message extends Component {
|
|
|
217
219
|
* @returns {MessageHandle}
|
|
218
220
|
*/
|
|
219
221
|
static show(msg, options = {}) {
|
|
220
|
-
return this.#floatingRegion().show(msg, options);
|
|
222
|
+
return this.#floatingRegion(options.scope).show(msg, options);
|
|
221
223
|
}
|
|
222
224
|
|
|
223
225
|
/**
|
|
224
226
|
* Shows a floating progress status.
|
|
225
227
|
* @param {string} text Initial status text.
|
|
228
|
+
* @param {{scope?: Element|string|null}} [options={}] Floating-region scope.
|
|
226
229
|
* @returns {ProgressHandle}
|
|
227
230
|
*/
|
|
228
|
-
static progress(text) {
|
|
229
|
-
return this.#floatingRegion()._progress(text);
|
|
231
|
+
static progress(text, options = {}) {
|
|
232
|
+
return this.#floatingRegion(options.scope)._progress(text);
|
|
230
233
|
}
|
|
231
234
|
|
|
232
235
|
/** @returns {void} */
|
|
@@ -414,19 +417,22 @@ export class Message extends Component {
|
|
|
414
417
|
this._queue.remove(entry);
|
|
415
418
|
}
|
|
416
419
|
|
|
417
|
-
/** @returns {Message} */
|
|
418
|
-
static #floatingRegion() {
|
|
419
|
-
|
|
420
|
+
/** @param {Element|string|null|undefined} scope @returns {Message} */
|
|
421
|
+
static #floatingRegion(scope) {
|
|
422
|
+
const host = overlayHost(scope ?? null);
|
|
423
|
+
const existing = this.#floating.get(host);
|
|
424
|
+
if (existing) return existing;
|
|
420
425
|
const region = h('div', {
|
|
421
426
|
class: 'zx-message-region',
|
|
422
427
|
popover: 'manual',
|
|
423
428
|
role: 'status',
|
|
424
429
|
ariaLive: 'polite'
|
|
425
430
|
});
|
|
426
|
-
|
|
427
|
-
|
|
431
|
+
host.append(region);
|
|
432
|
+
const floating = new Message(region);
|
|
433
|
+
this.#floating.set(host, floating);
|
|
428
434
|
if (typeof region.showPopover === 'function') region.showPopover();
|
|
429
|
-
return
|
|
435
|
+
return floating;
|
|
430
436
|
}
|
|
431
437
|
}
|
|
432
438
|
|
|
@@ -4,10 +4,12 @@
|
|
|
4
4
|
overflow: auto;
|
|
5
5
|
border: 1px solid var(--zx-color-overlay-border);
|
|
6
6
|
border-radius: var(--zx-radius-lg);
|
|
7
|
-
background: var(--zx-color-overlay-panel);
|
|
7
|
+
background-color: var(--zx-color-overlay-panel);
|
|
8
|
+
background-image: var(--zx-overlay-panel-image);
|
|
9
|
+
background-clip: padding-box;
|
|
8
10
|
-webkit-backdrop-filter: var(--zx-glass-filter-panel);
|
|
9
11
|
backdrop-filter: var(--zx-glass-filter-panel);
|
|
10
|
-
box-shadow: var(--zx-glass-
|
|
12
|
+
box-shadow: var(--zx-glass-panel-shadow);
|
|
11
13
|
color: var(--zx-color-text);
|
|
12
14
|
padding: 0;
|
|
13
15
|
}
|
|
@@ -23,7 +25,7 @@
|
|
|
23
25
|
}
|
|
24
26
|
|
|
25
27
|
.zx-modal::backdrop {
|
|
26
|
-
background: var(--zx-color-
|
|
28
|
+
background: var(--zx-color-overlay-backdrop);
|
|
27
29
|
}
|
|
28
30
|
|
|
29
31
|
.zx-modal__content {
|
|
@@ -34,7 +36,7 @@
|
|
|
34
36
|
* `:modal` rather than `[open]`: only a dialog opened with `showModal()` blocks the page, and a
|
|
35
37
|
* non-modal one (Sheet's `modal: false`) must leave the page scrollable behind it.
|
|
36
38
|
*/
|
|
37
|
-
body:has(
|
|
39
|
+
body:has(.zx-modal:modal) {
|
|
38
40
|
overflow: hidden;
|
|
39
41
|
overscroll-behavior: none;
|
|
40
42
|
}
|