@lmvz-ds/components 0.25.0 → 0.27.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 +24 -0
- package/cjs/{reactive-controller-host-DrtMkMd7.js → aria-validation-controller-BMV2tv9-.js} +0 -41
- package/cjs/{ds.constants-DSnxZ3ia.js → ds.constants-8fh6ItAF.js} +1 -1
- package/cjs/index.cjs.js +196 -2
- package/cjs/list-keyboard-controller-CzZdPBeH.js +173 -0
- package/cjs/lmvz-button-group.cjs.entry.js +183 -0
- package/cjs/lmvz-button_2.cjs.entry.js +199 -0
- package/cjs/lmvz-card.cjs.entry.js +1 -1
- package/cjs/lmvz-checkbox.cjs.entry.js +8 -4
- package/cjs/lmvz-chip.cjs.entry.js +5 -4
- package/cjs/lmvz-components.cjs.js +1 -1
- package/cjs/lmvz-header_2.cjs.entry.js +7 -51
- package/cjs/lmvz-input.cjs.entry.js +3 -2
- package/cjs/lmvz-menuitem.cjs.entry.js +4 -3
- package/cjs/lmvz-modal.cjs.entry.js +4 -3
- package/cjs/lmvz-radio.cjs.entry.js +4 -3
- package/cjs/lmvz-select.cjs.entry.js +3 -2
- package/cjs/lmvz-snackbar.cjs.entry.js +83 -0
- package/cjs/lmvz-tab.cjs.entry.js +31 -0
- package/cjs/lmvz-tabs.cjs.entry.js +256 -0
- package/cjs/lmvz-toggle.cjs.entry.js +5 -4
- package/cjs/loader.cjs.js +1 -1
- package/cjs/reactive-controller-host-B_lZtcA6.js +43 -0
- package/collection/api/ds.constants.js +4 -1
- package/collection/collection-manifest.json +3 -0
- package/collection/components/lmvz-button/lmvz-button.css +6 -6
- package/collection/components/lmvz-button-group/lmvz-button-group.css +2 -2
- package/collection/components/lmvz-card/lmvz-card.css +9 -9
- package/collection/components/lmvz-checkbox/lmvz-checkbox.css +14 -12
- package/collection/components/lmvz-checkbox/lmvz-checkbox.js +4 -1
- package/collection/components/lmvz-chip/lmvz-chip.css +2 -2
- package/collection/components/lmvz-header/lmvz-header.js +3 -3
- package/collection/components/lmvz-icon/lmvz-icon.js +1 -1
- package/collection/components/lmvz-menuitem/lmvz-menuitem.css +1 -1
- package/collection/components/lmvz-modal/lmvz-modal.css +4 -16
- package/collection/components/lmvz-radio/lmvz-radio.css +4 -4
- package/collection/components/lmvz-snackbar/lmvz-snackbar.css +101 -0
- package/collection/components/lmvz-snackbar/lmvz-snackbar.js +266 -0
- package/collection/components/lmvz-snackbar/public.js +1 -0
- package/collection/components/lmvz-snackbar/snackbar-controller.js +194 -0
- package/collection/components/lmvz-tab/lmvz-tab.css +148 -0
- package/collection/components/lmvz-tab/lmvz-tab.js +125 -0
- package/collection/components/lmvz-tabs/lmvz-tabs.css +58 -0
- package/collection/components/lmvz-tabs/lmvz-tabs.js +399 -0
- package/collection/components/lmvz-toggle/lmvz-toggle.css +2 -2
- package/collection/components/lmvz-toggle/lmvz-toggle.js +1 -1
- package/collection/index.js +1 -0
- package/collection/integration/header-integration/header-integration.js +1 -1
- package/collection/utils/aria/list-keyboard-controller.js +151 -28
- package/components/index.d.ts +6 -0
- package/components/index.d.ts.bak +6 -0
- package/components/index.js +1 -1
- package/components/lmvz-action.js +1 -1
- package/components/lmvz-button-group.js +1 -1
- package/components/lmvz-button.js +1 -1
- package/components/lmvz-card.js +1 -1
- package/components/lmvz-checkbox.js +1 -1
- package/components/lmvz-chip.js +1 -1
- package/components/lmvz-header.js +1 -1
- package/components/lmvz-icon.js +1 -1
- package/components/lmvz-input.js +1 -1
- package/components/lmvz-menuitem.js +1 -1
- package/components/lmvz-modal.js +1 -1
- package/components/lmvz-radio.js +1 -1
- package/components/lmvz-select.js +1 -1
- package/components/lmvz-snackbar.d.ts +11 -0
- package/components/lmvz-snackbar.d.ts.bak +11 -0
- package/components/lmvz-snackbar.js +1 -0
- package/components/lmvz-tab.d.ts +11 -0
- package/components/lmvz-tab.d.ts.bak +11 -0
- package/components/lmvz-tab.js +1 -0
- package/components/lmvz-tabs.d.ts +11 -0
- package/components/lmvz-tabs.d.ts.bak +11 -0
- package/components/lmvz-tabs.js +1 -0
- package/components/lmvz-toggle.js +1 -1
- package/components/p-0P2Wb3pE.js +1 -0
- package/components/p-2VdcUIrr.js +1 -0
- package/components/p-BJEQw1Sz.js +1 -0
- package/components/{p-Bb-kEOmU.js → p-Cs7RCOHZ.js} +1 -1
- package/components/p-CtaMrBNE.js +1 -0
- package/components/p-DjvbwRyl.js +1 -0
- package/components/{p-DYr7Jc0V.js → p-c7OzBK8f.js} +1 -1
- package/esm/{reactive-controller-host-ZrGf1F2-.js → aria-validation-controller-D-KO0Asb.js} +1 -41
- package/esm/{ds.constants-Bmi89ll1.js → ds.constants-BOOwq5dE.js} +1 -1
- package/esm/index.js +198 -1
- package/esm/list-keyboard-controller-Coi8XfUH.js +171 -0
- package/esm/lmvz-button-group.entry.js +181 -0
- package/esm/lmvz-button_2.entry.js +196 -0
- package/esm/lmvz-card.entry.js +1 -1
- package/esm/lmvz-checkbox.entry.js +7 -3
- package/esm/lmvz-chip.entry.js +4 -3
- package/esm/lmvz-components.js +1 -1
- package/esm/lmvz-header_2.entry.js +6 -50
- package/esm/lmvz-input.entry.js +2 -1
- package/esm/lmvz-menuitem.entry.js +3 -2
- package/esm/lmvz-modal.entry.js +3 -2
- package/esm/lmvz-radio.entry.js +3 -2
- package/esm/lmvz-select.entry.js +2 -1
- package/esm/lmvz-snackbar.entry.js +81 -0
- package/esm/lmvz-tab.entry.js +29 -0
- package/esm/lmvz-tabs.entry.js +254 -0
- package/esm/lmvz-toggle.entry.js +4 -3
- package/esm/loader.js +1 -1
- package/esm/reactive-controller-host-FBuCCcFC.js +41 -0
- package/hydrate/index.js +565 -40
- package/hydrate/index.mjs +565 -40
- package/lmvz-components/index.esm.js +1 -1
- package/lmvz-components/lmvz-components.esm.js +1 -1
- package/lmvz-components/p-0a37e0f2.entry.js +1 -0
- package/lmvz-components/p-25f045b2.entry.js +1 -0
- package/lmvz-components/p-43b463bf.entry.js +1 -0
- package/lmvz-components/p-4bd71a3c.entry.js +1 -0
- package/lmvz-components/p-6484fbc6.entry.js +1 -0
- package/lmvz-components/p-6988c3ea.entry.js +1 -0
- package/lmvz-components/p-6de9981f.entry.js +1 -0
- package/lmvz-components/p-758dbb82.entry.js +1 -0
- package/lmvz-components/p-7b15cdce.entry.js +1 -0
- package/lmvz-components/p-8874ff19.entry.js +1 -0
- package/lmvz-components/p-BOOwq5dE.js +1 -0
- package/lmvz-components/p-CtaMrBNE.js +1 -0
- package/lmvz-components/p-FBuCCcFC.js +1 -0
- package/lmvz-components/p-a5c921dc.entry.js +1 -0
- package/lmvz-components/p-bb46a884.entry.js +1 -0
- package/lmvz-components/p-bd23eab3.entry.js +1 -0
- package/lmvz-components/p-c6228cee.entry.js +1 -0
- package/lmvz-components/p-da16ff58.entry.js +1 -0
- package/lmvz-components/p-hRb38wX6.js +1 -0
- package/manifest.json +858 -186
- package/package.json +13 -1
- package/types/api/ds.constants.d.ts +9 -1
- package/types/components/lmvz-checkbox/lmvz-checkbox.d.ts +1 -0
- package/types/components/lmvz-header/lmvz-header.d.ts +2 -2
- package/types/components/lmvz-snackbar/lmvz-snackbar.d.ts +21 -0
- package/types/components/lmvz-snackbar/public.d.ts +2 -0
- package/types/components/lmvz-snackbar/snackbar-controller.d.ts +32 -0
- package/types/components/lmvz-tab/lmvz-tab.d.ts +11 -0
- package/types/components/lmvz-tabs/lmvz-tabs.d.ts +43 -0
- package/types/components.d.ts +212 -1
- package/types/index.d.ts +1 -0
- package/types/utils/aria/list-keyboard-controller.d.ts +28 -5
- package/cjs/lmvz-button_3.cjs.entry.js +0 -375
- package/components/p-CCcoDnH-.js +0 -1
- package/components/p-CNmHnJ1D.js +0 -1
- package/components/p-vUYpZZoR.js +0 -1
- package/esm/lmvz-button_3.entry.js +0 -371
- package/lmvz-components/p-01aeca60.entry.js +0 -1
- package/lmvz-components/p-0dced359.entry.js +0 -1
- package/lmvz-components/p-2044a9ac.entry.js +0 -1
- package/lmvz-components/p-3c2adbb4.entry.js +0 -1
- package/lmvz-components/p-3df070b0.entry.js +0 -1
- package/lmvz-components/p-758078db.entry.js +0 -1
- package/lmvz-components/p-90f5a19d.entry.js +0 -1
- package/lmvz-components/p-Bmi89ll1.js +0 -1
- package/lmvz-components/p-CwX1wKkM.js +0 -1
- package/lmvz-components/p-acfeae08.entry.js +0 -1
- package/lmvz-components/p-c01a6c70.entry.js +0 -1
- package/lmvz-components/p-e1eaa7a2.entry.js +0 -1
- package/lmvz-components/p-e23d0054.entry.js +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# @lmvz-ds/components
|
|
2
2
|
|
|
3
|
+
## 0.27.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 81f8e3e: Tabs und Tab Komponenten hinzugefügt
|
|
8
|
+
- 7073812: Generierte ValueAccessors für Angular wurden durch Custom-Implementierung ersetzt
|
|
9
|
+
|
|
10
|
+
### Patch Changes
|
|
11
|
+
|
|
12
|
+
- 7127ead: Design Tokens aktualisiert
|
|
13
|
+
- c891440: Design Tokens aktualisiert
|
|
14
|
+
- c6f1f38: Checkbox a11y und Figma-Alignment verbessert
|
|
15
|
+
|
|
16
|
+
## 0.26.0
|
|
17
|
+
|
|
18
|
+
### Minor Changes
|
|
19
|
+
|
|
20
|
+
- 80f5b7d: Snackbar Komponente und Controller hinzugefügt.
|
|
21
|
+
|
|
22
|
+
### Patch Changes
|
|
23
|
+
|
|
24
|
+
- 1c0f1e5: Design Tokens aktualisiert
|
|
25
|
+
- 72c4ec5: Design Tokens aktualisiert
|
|
26
|
+
|
|
3
27
|
## 0.25.0
|
|
4
28
|
|
|
5
29
|
### Minor Changes
|
|
@@ -149,45 +149,4 @@ class AriaValidationController {
|
|
|
149
149
|
}
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
-
class ReactiveControllerHost {
|
|
153
|
-
controllers = new Set();
|
|
154
|
-
addController(controller) {
|
|
155
|
-
this.controllers.add(controller);
|
|
156
|
-
}
|
|
157
|
-
removeController(controller) {
|
|
158
|
-
this.controllers.delete(controller);
|
|
159
|
-
}
|
|
160
|
-
get activeControllers() {
|
|
161
|
-
return Array.from(this.controllers).filter((controller) => !controller.disabled);
|
|
162
|
-
}
|
|
163
|
-
connectedCallback() {
|
|
164
|
-
if (!this.controllers.size) {
|
|
165
|
-
console.warn('ReactiveControllerHost connected with no controllers registered.', this);
|
|
166
|
-
}
|
|
167
|
-
this.activeControllers.forEach((controller) => controller.hostConnected?.());
|
|
168
|
-
}
|
|
169
|
-
disconnectedCallback() {
|
|
170
|
-
this.activeControllers.forEach((controller) => controller.hostDisconnected?.());
|
|
171
|
-
}
|
|
172
|
-
componentWillLoad() {
|
|
173
|
-
this.activeControllers.forEach((controller) => controller.hostWillLoad?.());
|
|
174
|
-
}
|
|
175
|
-
componentDidLoad() {
|
|
176
|
-
this.activeControllers.forEach((controller) => controller.hostDidLoad?.());
|
|
177
|
-
}
|
|
178
|
-
componentWillRender() {
|
|
179
|
-
this.activeControllers.forEach((controller) => controller.hostWillRender?.());
|
|
180
|
-
}
|
|
181
|
-
componentDidRender() {
|
|
182
|
-
this.activeControllers.forEach((controller) => controller.hostDidRender?.());
|
|
183
|
-
}
|
|
184
|
-
componentWillUpdate() {
|
|
185
|
-
this.activeControllers.forEach((controller) => controller.hostWillUpdate?.());
|
|
186
|
-
}
|
|
187
|
-
componentDidUpdate() {
|
|
188
|
-
this.activeControllers.forEach((controller) => controller.hostDidUpdate?.());
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
152
|
exports.AriaValidationController = AriaValidationController;
|
|
193
|
-
exports.ReactiveControllerHost = ReactiveControllerHost;
|
|
@@ -4,7 +4,7 @@ const sizes = ['xs', 'sm', 'md', 'lg'];
|
|
|
4
4
|
const textSizes = [...sizes, 'xl'];
|
|
5
5
|
const inputTypes = ['text', 'email', 'password', 'tel', 'url', 'search', 'number'];
|
|
6
6
|
const iconSizes = [...sizes, 'inherit'];
|
|
7
|
-
const iconWeights = ['thin', 'medium', 'bold'
|
|
7
|
+
const iconWeights = ['thin', 'medium', 'bold'];
|
|
8
8
|
const chipTypes = ['active', 'warning', 'success', 'error', 'neutral'];
|
|
9
9
|
const chipSizes = ['default', 'small'];
|
|
10
10
|
|
package/cjs/index.cjs.js
CHANGED
|
@@ -1,12 +1,205 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var ariaLoader = require('./aria-loader-BRo2FTGh.js');
|
|
4
|
-
var ds_constants = require('./ds.constants-
|
|
4
|
+
var ds_constants = require('./ds.constants-8fh6ItAF.js');
|
|
5
5
|
var icons = require('./icons-BQASWgk-.js');
|
|
6
6
|
require('./svg-BMBduILB.js');
|
|
7
7
|
require('./logger-DsM6xg6V.js');
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
const PRIORITY_MAP = {
|
|
10
|
+
low: 0,
|
|
11
|
+
normal: 1,
|
|
12
|
+
high: 2,
|
|
13
|
+
};
|
|
14
|
+
const STATUS_DURATION = {
|
|
15
|
+
success: 5000,
|
|
16
|
+
warning: 5000,
|
|
17
|
+
error: 8000,
|
|
18
|
+
};
|
|
19
|
+
let idCounter = 0;
|
|
20
|
+
function nextId() {
|
|
21
|
+
idCounter += 1;
|
|
22
|
+
return `snackbar-${idCounter}`;
|
|
23
|
+
}
|
|
24
|
+
function resolveHostElement() {
|
|
25
|
+
if (typeof document === 'undefined') {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
const existing = document.querySelector('[data-snackbar-host]');
|
|
29
|
+
if (existing) {
|
|
30
|
+
return existing;
|
|
31
|
+
}
|
|
32
|
+
const el = document.createElement('lmvz-snackbar');
|
|
33
|
+
el.setAttribute('data-snackbar-host', '');
|
|
34
|
+
document.body.appendChild(el);
|
|
35
|
+
return el;
|
|
36
|
+
}
|
|
37
|
+
class SnackbarController {
|
|
38
|
+
hostEl = undefined;
|
|
39
|
+
active = undefined;
|
|
40
|
+
getHost() {
|
|
41
|
+
if (this.hostEl !== undefined && !this.hostEl.isConnected) {
|
|
42
|
+
this.hostEl = undefined;
|
|
43
|
+
}
|
|
44
|
+
if (this.hostEl === undefined) {
|
|
45
|
+
this.hostEl = resolveHostElement();
|
|
46
|
+
}
|
|
47
|
+
return this.hostEl;
|
|
48
|
+
}
|
|
49
|
+
clearTimer(entry) {
|
|
50
|
+
if (entry.timerId !== undefined) {
|
|
51
|
+
clearTimeout(entry.timerId);
|
|
52
|
+
entry.timerId = undefined;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
scheduleTimer(entry, delayMs) {
|
|
56
|
+
if (delayMs <= 0) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
entry.timerStartedAt = Date.now();
|
|
60
|
+
entry.timerId = setTimeout(() => {
|
|
61
|
+
if (this.active !== undefined && this.active.id === entry.id) {
|
|
62
|
+
this.dismissActive(entry, 'timeout');
|
|
63
|
+
}
|
|
64
|
+
}, delayMs);
|
|
65
|
+
}
|
|
66
|
+
dismissActive(entry, reason) {
|
|
67
|
+
this.clearTimer(entry);
|
|
68
|
+
const host = entry.hostEl;
|
|
69
|
+
host.removeEventListener('pointerenter', entry.onPointerEnter);
|
|
70
|
+
host.removeEventListener('pointerleave', entry.onPointerLeave);
|
|
71
|
+
host.removeEventListener('focusin', entry.onFocusIn);
|
|
72
|
+
host.removeEventListener('focusout', entry.onFocusOut);
|
|
73
|
+
if (entry.onActionListener) {
|
|
74
|
+
host.removeEventListener('lmvzAction', entry.onActionListener);
|
|
75
|
+
}
|
|
76
|
+
host.hide?.();
|
|
77
|
+
if (this.active?.id === entry.id) {
|
|
78
|
+
this.active = undefined;
|
|
79
|
+
}
|
|
80
|
+
if (reason !== 'action') {
|
|
81
|
+
host.dispatchEvent(new CustomEvent('lmvzClose', { detail: { reason }, bubbles: true, composed: true }));
|
|
82
|
+
}
|
|
83
|
+
entry.resolve({ reason });
|
|
84
|
+
}
|
|
85
|
+
pauseTimer(entry) {
|
|
86
|
+
entry.pauseCount += 1;
|
|
87
|
+
if (entry.pauseCount > 1 || entry.timerId === undefined) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const elapsed = entry.timerStartedAt !== undefined ? Date.now() - entry.timerStartedAt : 0;
|
|
91
|
+
entry.remaining = Math.max(0, entry.remaining - elapsed);
|
|
92
|
+
entry.timerStartedAt = undefined;
|
|
93
|
+
this.clearTimer(entry);
|
|
94
|
+
}
|
|
95
|
+
resumeTimer(entry) {
|
|
96
|
+
if (entry.pauseCount > 0) {
|
|
97
|
+
entry.pauseCount -= 1;
|
|
98
|
+
}
|
|
99
|
+
if (entry.pauseCount > 0) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
if (entry.remaining > 0) {
|
|
103
|
+
this.scheduleTimer(entry, entry.remaining);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
applyToHost(host, options) {
|
|
107
|
+
host.setAttribute('status', options.status ?? 'success');
|
|
108
|
+
if (options.actionLabel !== undefined) {
|
|
109
|
+
host.setAttribute('action-label', options.actionLabel);
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
host.removeAttribute('action-label');
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
open(options) {
|
|
116
|
+
const incomingPriority = PRIORITY_MAP[options.priority ?? 'normal'];
|
|
117
|
+
if (this.active !== undefined && incomingPriority < this.active.priority) {
|
|
118
|
+
let swallowResolve;
|
|
119
|
+
const closed = new Promise((resolve) => {
|
|
120
|
+
swallowResolve = resolve;
|
|
121
|
+
});
|
|
122
|
+
swallowResolve({ reason: 'swallowed' });
|
|
123
|
+
const id = nextId();
|
|
124
|
+
return {
|
|
125
|
+
id,
|
|
126
|
+
closed,
|
|
127
|
+
dismiss() {
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
if (this.active !== undefined) {
|
|
132
|
+
this.dismissActive(this.active, 'overridden');
|
|
133
|
+
}
|
|
134
|
+
const host = this.getHost();
|
|
135
|
+
if (host === undefined) {
|
|
136
|
+
const id = nextId();
|
|
137
|
+
let ssrResolve;
|
|
138
|
+
const closed = new Promise((resolve) => {
|
|
139
|
+
ssrResolve = resolve;
|
|
140
|
+
});
|
|
141
|
+
ssrResolve({ reason: 'swallowed' });
|
|
142
|
+
return { id, closed, dismiss() { } };
|
|
143
|
+
}
|
|
144
|
+
const id = nextId();
|
|
145
|
+
const status = options.status ?? 'success';
|
|
146
|
+
const durationMs = options.duration === 0 ? 0 : (options.duration ?? STATUS_DURATION[status]);
|
|
147
|
+
let entryResolve;
|
|
148
|
+
const closed = new Promise((resolve) => {
|
|
149
|
+
entryResolve = resolve;
|
|
150
|
+
});
|
|
151
|
+
const entry = {
|
|
152
|
+
id,
|
|
153
|
+
priority: incomingPriority,
|
|
154
|
+
resolve: entryResolve,
|
|
155
|
+
timerId: undefined,
|
|
156
|
+
remaining: durationMs,
|
|
157
|
+
timerStartedAt: undefined,
|
|
158
|
+
pauseCount: 0,
|
|
159
|
+
hostEl: host,
|
|
160
|
+
onPointerEnter: () => this.pauseTimer(entry),
|
|
161
|
+
onPointerLeave: () => this.resumeTimer(entry),
|
|
162
|
+
onFocusIn: () => this.pauseTimer(entry),
|
|
163
|
+
onFocusOut: () => this.resumeTimer(entry),
|
|
164
|
+
};
|
|
165
|
+
this.active = entry;
|
|
166
|
+
host.addEventListener('pointerenter', entry.onPointerEnter);
|
|
167
|
+
host.addEventListener('pointerleave', entry.onPointerLeave);
|
|
168
|
+
host.addEventListener('focusin', entry.onFocusIn);
|
|
169
|
+
host.addEventListener('focusout', entry.onFocusOut);
|
|
170
|
+
this.applyToHost(host, options);
|
|
171
|
+
const onAction = () => {
|
|
172
|
+
if (this.active !== undefined && this.active.id === id) {
|
|
173
|
+
options.onAction?.();
|
|
174
|
+
this.dismissActive(entry, 'action');
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
entry.onActionListener = onAction;
|
|
178
|
+
host.addEventListener('lmvzAction', onAction, { once: true });
|
|
179
|
+
host.show?.();
|
|
180
|
+
queueMicrotask(() => host.setAttribute('message', options.message));
|
|
181
|
+
if (durationMs > 0) {
|
|
182
|
+
this.scheduleTimer(entry, durationMs);
|
|
183
|
+
}
|
|
184
|
+
return {
|
|
185
|
+
id,
|
|
186
|
+
closed,
|
|
187
|
+
dismiss: () => {
|
|
188
|
+
if (this.active?.id === id) {
|
|
189
|
+
this.dismissActive(entry, 'manual');
|
|
190
|
+
}
|
|
191
|
+
},
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
dismiss(id) {
|
|
195
|
+
if (!this.active) {
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
if (!id || this.active.id === id) {
|
|
199
|
+
this.dismissActive(this.active, 'manual');
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
10
203
|
|
|
11
204
|
exports.ARIA_VALIDATION_RUNTIME_CHANGED_EVENT = ariaLoader.ARIA_VALIDATION_RUNTIME_CHANGED_EVENT;
|
|
12
205
|
exports.disableAriaValidation = ariaLoader.disableAriaValidation;
|
|
@@ -23,3 +216,4 @@ exports.textSizes = ds_constants.textSizes;
|
|
|
23
216
|
exports.getRegisteredIconProvider = icons.getRegisteredIconProvider;
|
|
24
217
|
exports.registerIconProvider = icons.registerIconProvider;
|
|
25
218
|
exports.typedIconFromSet = icons.typedIconFromSet;
|
|
219
|
+
exports.SnackbarController = SnackbarController;
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var component = require('./component-C7cavwmZ.js');
|
|
4
|
+
|
|
5
|
+
const defaultConfig = {
|
|
6
|
+
orientation: 'both',
|
|
7
|
+
enableHomeAndEnd: false,
|
|
8
|
+
manageTabIndex: false,
|
|
9
|
+
};
|
|
10
|
+
class DirectionalFocusController {
|
|
11
|
+
host;
|
|
12
|
+
elements = [];
|
|
13
|
+
currentElement;
|
|
14
|
+
config;
|
|
15
|
+
constructor(host, config = {}) {
|
|
16
|
+
this.host = host;
|
|
17
|
+
this.config = {
|
|
18
|
+
...defaultConfig,
|
|
19
|
+
...config,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
hostConnected() {
|
|
23
|
+
this.host.el.addEventListener('keydown', this.handleKeydown);
|
|
24
|
+
this.syncManagedFocusTarget();
|
|
25
|
+
}
|
|
26
|
+
hostDisconnected() {
|
|
27
|
+
this.host.el.removeEventListener('keydown', this.handleKeydown);
|
|
28
|
+
}
|
|
29
|
+
updateElements(elements) {
|
|
30
|
+
const previousElement = this.currentElement ?? this.getManagedActiveElement() ?? undefined;
|
|
31
|
+
this.elements = elements.filter((element) => 'focus' in element && element.nodeType === 1);
|
|
32
|
+
this.syncManagedFocusTarget(previousElement);
|
|
33
|
+
}
|
|
34
|
+
setCurrentElement(element) {
|
|
35
|
+
const previousElement = this.currentElement;
|
|
36
|
+
this.currentElement = element !== null && element !== undefined && 'focus' in element && element.nodeType === 1 ? element : undefined;
|
|
37
|
+
this.syncManagedFocusTarget(previousElement);
|
|
38
|
+
}
|
|
39
|
+
handleKeydown = (event) => {
|
|
40
|
+
const intent = this.getFocusIntent(event.key);
|
|
41
|
+
if (!intent)
|
|
42
|
+
return;
|
|
43
|
+
const activeElement = this.getManagedActiveElement();
|
|
44
|
+
const nextElement = this.getTargetElement(activeElement, intent);
|
|
45
|
+
if (!nextElement)
|
|
46
|
+
return;
|
|
47
|
+
event.preventDefault();
|
|
48
|
+
this.applyFocusTarget(nextElement, true);
|
|
49
|
+
};
|
|
50
|
+
getFocusIntent(key) {
|
|
51
|
+
if (this.config.enableHomeAndEnd && key === 'Home')
|
|
52
|
+
return 'first';
|
|
53
|
+
if (this.config.enableHomeAndEnd && key === 'End')
|
|
54
|
+
return 'last';
|
|
55
|
+
if (this.config.orientation === 'horizontal') {
|
|
56
|
+
if (key === 'ArrowRight')
|
|
57
|
+
return 'next';
|
|
58
|
+
if (key === 'ArrowLeft')
|
|
59
|
+
return 'previous';
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
if (this.config.orientation === 'vertical') {
|
|
63
|
+
if (key === 'ArrowDown')
|
|
64
|
+
return 'next';
|
|
65
|
+
if (key === 'ArrowUp')
|
|
66
|
+
return 'previous';
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
if (key === 'ArrowDown' || key === 'ArrowRight')
|
|
70
|
+
return 'next';
|
|
71
|
+
if (key === 'ArrowUp' || key === 'ArrowLeft')
|
|
72
|
+
return 'previous';
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
getManagedActiveElement() {
|
|
76
|
+
const activeElement = component.getDeepActiveElement(this.host.el.ownerDocument ?? document);
|
|
77
|
+
if (activeElement instanceof HTMLElement && this.elements.includes(activeElement) && this.canMoveFocusTo(activeElement)) {
|
|
78
|
+
return activeElement;
|
|
79
|
+
}
|
|
80
|
+
if (this.currentElement && this.elements.includes(this.currentElement) && this.canMoveFocusTo(this.currentElement)) {
|
|
81
|
+
return this.currentElement;
|
|
82
|
+
}
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
getTargetElement(current, intent) {
|
|
86
|
+
if (!this.elements.length)
|
|
87
|
+
return undefined;
|
|
88
|
+
if (intent === 'first')
|
|
89
|
+
return this.findFocusableFromIndex(-1, 'next');
|
|
90
|
+
if (intent === 'last')
|
|
91
|
+
return this.findFocusableFromIndex(this.elements.length, 'previous');
|
|
92
|
+
const currentIndex = current ? this.elements.indexOf(current) : -1;
|
|
93
|
+
if (currentIndex === -1) {
|
|
94
|
+
return intent === 'next' ? this.findFocusableFromIndex(-1, 'next') : this.findFocusableFromIndex(this.elements.length, 'previous');
|
|
95
|
+
}
|
|
96
|
+
return this.findFocusableFromIndex(currentIndex, intent);
|
|
97
|
+
}
|
|
98
|
+
findFocusableFromIndex(startIndex, intent) {
|
|
99
|
+
if (!this.elements.length)
|
|
100
|
+
return undefined;
|
|
101
|
+
const step = intent === 'next' ? 1 : -1;
|
|
102
|
+
for (let offset = 1; offset <= this.elements.length; offset++) {
|
|
103
|
+
const index = (startIndex + step * offset + this.elements.length) % this.elements.length;
|
|
104
|
+
const candidate = this.elements[index];
|
|
105
|
+
if (this.canMoveFocusTo(candidate))
|
|
106
|
+
return candidate;
|
|
107
|
+
}
|
|
108
|
+
return undefined;
|
|
109
|
+
}
|
|
110
|
+
syncManagedFocusTarget(previousElement) {
|
|
111
|
+
const nextElement = this.selectManagedElement(previousElement);
|
|
112
|
+
const didChange = nextElement !== this.currentElement;
|
|
113
|
+
this.currentElement = nextElement;
|
|
114
|
+
if (this.config.manageTabIndex) {
|
|
115
|
+
this.updateTabIndexes(nextElement);
|
|
116
|
+
}
|
|
117
|
+
if (didChange && nextElement) {
|
|
118
|
+
this.config.onFocusTargetChange?.(nextElement);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
selectManagedElement(previousElement) {
|
|
122
|
+
const activeElement = this.getManagedActiveElement();
|
|
123
|
+
if (activeElement)
|
|
124
|
+
return activeElement;
|
|
125
|
+
if (this.currentElement && this.elements.includes(this.currentElement) && this.canMoveFocusTo(this.currentElement)) {
|
|
126
|
+
return this.currentElement;
|
|
127
|
+
}
|
|
128
|
+
if (previousElement && this.elements.includes(previousElement)) {
|
|
129
|
+
return this.findFocusableFromIndex(this.elements.indexOf(previousElement), 'next') ?? this.findFocusableFromIndex(-1, 'next');
|
|
130
|
+
}
|
|
131
|
+
const currentRovingTarget = this.elements.find((element) => element.tabIndex === 0 && this.canMoveFocusTo(element));
|
|
132
|
+
if (currentRovingTarget)
|
|
133
|
+
return currentRovingTarget;
|
|
134
|
+
return this.findFocusableFromIndex(-1, 'next');
|
|
135
|
+
}
|
|
136
|
+
updateTabIndexes(activeElement) {
|
|
137
|
+
this.elements.forEach((element) => {
|
|
138
|
+
element.tabIndex = activeElement && element === activeElement ? 0 : -1;
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
applyFocusTarget(element, shouldFocus) {
|
|
142
|
+
const didChange = element !== this.currentElement;
|
|
143
|
+
this.currentElement = element;
|
|
144
|
+
if (this.config.manageTabIndex) {
|
|
145
|
+
this.updateTabIndexes(element);
|
|
146
|
+
}
|
|
147
|
+
if (shouldFocus) {
|
|
148
|
+
element.focus();
|
|
149
|
+
}
|
|
150
|
+
if (didChange) {
|
|
151
|
+
this.config.onFocusTargetChange?.(element);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
canMoveFocusTo(element) {
|
|
155
|
+
if (!element)
|
|
156
|
+
return false;
|
|
157
|
+
if (element.hasAttribute('disabled'))
|
|
158
|
+
return false;
|
|
159
|
+
if ('disabled' in element && Boolean(element.disabled))
|
|
160
|
+
return false;
|
|
161
|
+
if (element.getAttribute('aria-disabled') === 'true')
|
|
162
|
+
return false;
|
|
163
|
+
if (this.config.isFocusableElement)
|
|
164
|
+
return this.config.isFocusableElement(element);
|
|
165
|
+
const isTabOrderable = this.config.manageTabIndex || element.tabIndex >= 0;
|
|
166
|
+
return (isTabOrderable &&
|
|
167
|
+
element.getAttribute('aria-hidden') !== 'true' &&
|
|
168
|
+
(element.checkVisibility?.() ?? true) &&
|
|
169
|
+
element.offsetParent !== null);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
exports.DirectionalFocusController = DirectionalFocusController;
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var index = require('./index-BCFBLj0e.js');
|
|
4
|
+
var ariaLoader = require('./aria-loader-BRo2FTGh.js');
|
|
5
|
+
var component = require('./component-C7cavwmZ.js');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Returns a function that delegates to the given predicate/filter and negates its result.
|
|
9
|
+
* The returned function preserves the input function's types, arguments and timing.
|
|
10
|
+
*
|
|
11
|
+
* @param delegate - The predicate/filter function to negate.
|
|
12
|
+
* @returns A function that returns the negated result.
|
|
13
|
+
*/
|
|
14
|
+
function negate(delegate) {
|
|
15
|
+
return (...args) => {
|
|
16
|
+
const result = delegate(...args);
|
|
17
|
+
return ariaLoader.isPromise(result) ? result.then((res) => !res) : !result;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const lmvzButtonGroupCss = () => `:host{display:flex;justify-content:flex-end;gap:var(--lmvz-component-input-gap-md, clamp(0.5rem, 0.44rem + 0.26vw, 0.75rem));font:var(--lmvz-typography-body-md, 400 clamp(0.88rem, 0.84rem + 0.13vw, 1rem) / 1.5 Router);flex-wrap:wrap}::slotted([hidden]){display:none !important}`;
|
|
22
|
+
|
|
23
|
+
const LmvzButtonGroup = class {
|
|
24
|
+
constructor(hostRef) {
|
|
25
|
+
index.registerInstance(this, hostRef);
|
|
26
|
+
}
|
|
27
|
+
actionsSlot;
|
|
28
|
+
validationMessageCache = [];
|
|
29
|
+
actionsStateObserver;
|
|
30
|
+
get primaryEnabledAction() {
|
|
31
|
+
return this.enabledButtons.find(isPrimaryAction) ?? this.enabledButtons[0];
|
|
32
|
+
}
|
|
33
|
+
get hasActions() {
|
|
34
|
+
return this.assignedButtons.some((element) => isVisible(element) && isActionButton(element) && !isDisabledButton(element));
|
|
35
|
+
}
|
|
36
|
+
componentDidLoad() {
|
|
37
|
+
this.handleActionsSlotChange();
|
|
38
|
+
}
|
|
39
|
+
disconnectedCallback() {
|
|
40
|
+
this.actionsStateObserver?.disconnect();
|
|
41
|
+
}
|
|
42
|
+
get assignedElements() {
|
|
43
|
+
return this.actionsSlot?.assignedElements({ flatten: true }) ?? [];
|
|
44
|
+
}
|
|
45
|
+
get assignedButtons() {
|
|
46
|
+
return this.assignedElements.filter(isActionButton);
|
|
47
|
+
}
|
|
48
|
+
get visibleButtons() {
|
|
49
|
+
return this.assignedButtons.filter(isVisible);
|
|
50
|
+
}
|
|
51
|
+
get enabledButtons() {
|
|
52
|
+
return this.visibleButtons.filter(negate(isDisabledButton));
|
|
53
|
+
}
|
|
54
|
+
getActionValidationResult() {
|
|
55
|
+
if (!this.visibleButtons.length) {
|
|
56
|
+
return [];
|
|
57
|
+
}
|
|
58
|
+
const primaryActions = this.visibleButtons.filter(isPrimaryAction);
|
|
59
|
+
const secondaryActions = this.visibleButtons.filter(isSecondaryAction);
|
|
60
|
+
const issues = [];
|
|
61
|
+
const order = this.visibleButtons.toReversed();
|
|
62
|
+
if (primaryActions.length !== 1)
|
|
63
|
+
issues.push('LmvzModal actions slot must contain exactly one primary action.');
|
|
64
|
+
if (secondaryActions.length > 1)
|
|
65
|
+
issues.push(`LmvzModal actions slot must contain at most one secondary action (received ${secondaryActions.length})`);
|
|
66
|
+
if (primaryActions.length) {
|
|
67
|
+
const primaryAction = primaryActions[0];
|
|
68
|
+
const secondaryAction = secondaryActions[0];
|
|
69
|
+
if (order.indexOf(primaryAction) !== 0)
|
|
70
|
+
issues.push('Primary action must be the last focusable element in the actions slot (i.e. rightmost button).');
|
|
71
|
+
if (secondaryAction && order.indexOf(secondaryAction) !== 1)
|
|
72
|
+
issues.push('Secondary action must be the second-to-last focusable element in the actions slot (i.e. left of primary button).');
|
|
73
|
+
}
|
|
74
|
+
else if (secondaryActions.length) {
|
|
75
|
+
const secondaryAction = secondaryActions[0];
|
|
76
|
+
if (order.indexOf(secondaryAction) !== 0)
|
|
77
|
+
issues.push('Secondary action must be the last focusable element in the actions slot when no primary action is present (i.e. rightmost button).');
|
|
78
|
+
}
|
|
79
|
+
return issues;
|
|
80
|
+
}
|
|
81
|
+
handleActionsSlotChange = () => {
|
|
82
|
+
this.observeActionState();
|
|
83
|
+
this.syncActionsState();
|
|
84
|
+
};
|
|
85
|
+
observeActionState() {
|
|
86
|
+
if (typeof MutationObserver === 'undefined')
|
|
87
|
+
return;
|
|
88
|
+
this.actionsStateObserver?.disconnect();
|
|
89
|
+
if (!this.assignedButtons.length)
|
|
90
|
+
return;
|
|
91
|
+
this.actionsStateObserver = new MutationObserver(() => {
|
|
92
|
+
this.syncActionsState();
|
|
93
|
+
});
|
|
94
|
+
this.assignedButtons.forEach((element) => {
|
|
95
|
+
this.actionsStateObserver?.observe(element, {
|
|
96
|
+
attributes: true,
|
|
97
|
+
attributeFilter: ['disabled', 'hidden', 'variant'],
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
syncActionsState() {
|
|
102
|
+
const assignedElements = this.assignedElements;
|
|
103
|
+
assignedElements.forEach((element) => {
|
|
104
|
+
const isAllowedAction = ['LMVZ-BUTTON', 'BUTTON'].includes(element.tagName.toUpperCase());
|
|
105
|
+
if (isAllowedAction)
|
|
106
|
+
return;
|
|
107
|
+
if (!element.hasAttribute('hidden')) {
|
|
108
|
+
element.setAttribute('hidden', '');
|
|
109
|
+
}
|
|
110
|
+
if (element.getAttribute('aria-hidden') !== 'true') {
|
|
111
|
+
element.setAttribute('aria-hidden', 'true');
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
this.checkActions();
|
|
115
|
+
const length = this.visibleButtons.length;
|
|
116
|
+
for (let i = 0; i < length; i++) {
|
|
117
|
+
const variant = i === length - 1 ? 'primary' : i === length - 2 ? 'secondary' : 'tertiary';
|
|
118
|
+
const element = this.visibleButtons.at(i);
|
|
119
|
+
if (!element)
|
|
120
|
+
continue;
|
|
121
|
+
if (isLmvzButton(element)) {
|
|
122
|
+
if (!element.getAttribute('variant'))
|
|
123
|
+
element.setAttribute('variant', variant);
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
element.classList.add(variant);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
this.focusPrimaryAction();
|
|
130
|
+
}
|
|
131
|
+
focusPrimaryAction() {
|
|
132
|
+
const focusTarget = this.primaryEnabledAction;
|
|
133
|
+
if (!focusTarget || typeof window === 'undefined')
|
|
134
|
+
return;
|
|
135
|
+
window.requestAnimationFrame(() => {
|
|
136
|
+
if (component.canReceiveFocus(focusTarget)) {
|
|
137
|
+
focusTarget.focus();
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
checkActions() {
|
|
142
|
+
if (!ariaLoader.isAriaValidationEnabled())
|
|
143
|
+
return;
|
|
144
|
+
const issues = this.getActionValidationResult();
|
|
145
|
+
if (!issues.length) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
issues.forEach((issue) => {
|
|
149
|
+
if (this.validationMessageCache.includes(issue))
|
|
150
|
+
return;
|
|
151
|
+
console.warn(issue);
|
|
152
|
+
this.validationMessageCache.push(issue);
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
render() {
|
|
156
|
+
return (index.h(index.Host, { key: '56b60821ecaa2301d13e78d621e873aa74cd170e' }, index.h("slot", { key: 'e6a1422950fa5b0026356b7788a607a690116186', ref: (element) => (this.actionsSlot = element), onSlotchange: this.handleActionsSlotChange })));
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
function isActionButton(element) {
|
|
160
|
+
return ['LMVZ-BUTTON', 'BUTTON'].includes(element.tagName.toUpperCase());
|
|
161
|
+
}
|
|
162
|
+
function isLmvzButton(element) {
|
|
163
|
+
return element?.tagName.toUpperCase() === 'LMVZ-BUTTON';
|
|
164
|
+
}
|
|
165
|
+
function isDisabledButton(element) {
|
|
166
|
+
return element.hasAttribute('disabled') || element.disabled === true;
|
|
167
|
+
}
|
|
168
|
+
function isVisible(element) {
|
|
169
|
+
return !element.hasAttribute('hidden');
|
|
170
|
+
}
|
|
171
|
+
function getActionVariant(element) {
|
|
172
|
+
const variant = element.getAttribute('variant') ?? element.variant;
|
|
173
|
+
return variant === 'primary' || variant === 'secondary' || variant === 'tertiary' ? variant : 'secondary';
|
|
174
|
+
}
|
|
175
|
+
function isPrimaryAction(element) {
|
|
176
|
+
return getActionVariant(element) === 'primary';
|
|
177
|
+
}
|
|
178
|
+
function isSecondaryAction(element) {
|
|
179
|
+
return getActionVariant(element) === 'secondary';
|
|
180
|
+
}
|
|
181
|
+
LmvzButtonGroup.style = lmvzButtonGroupCss();
|
|
182
|
+
|
|
183
|
+
exports.lmvz_button_group = LmvzButtonGroup;
|