@momentum-design/components 0.129.46 → 0.129.47
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/dist/browser/index.js +264 -264
- package/dist/browser/index.js.map +4 -4
- package/dist/components/combobox/combobox.component.d.ts +1 -1
- package/dist/components/combobox/combobox.component.js +2 -5
- package/dist/components/dialog/dialog.component.d.ts +19 -7
- package/dist/components/dialog/dialog.component.js +40 -14
- package/dist/components/menubar/menubar.component.d.ts +6 -0
- package/dist/components/menubar/menubar.component.js +30 -26
- package/dist/components/menupopover/menupopover.component.d.ts +1 -1
- package/dist/components/menupopover/menupopover.component.js +19 -24
- package/dist/components/popover/popover.component.d.ts +14 -25
- package/dist/components/popover/popover.component.js +23 -32
- package/dist/components/searchpopover/searchpopover.component.d.ts +1 -1
- package/dist/components/searchpopover/searchpopover.component.js +2 -2
- package/dist/components/select/select.component.d.ts +1 -1
- package/dist/components/select/select.component.js +5 -3
- package/dist/components/tooltip/tooltip.component.d.ts +1 -0
- package/dist/components/tooltip/tooltip.component.js +17 -0
- package/dist/custom-elements.json +42 -59
- package/dist/utils/controllers/DepthManager.d.ts +202 -0
- package/dist/utils/controllers/DepthManager.js +259 -0
- package/dist/utils/mixins/BackdropMixin.js +19 -2
- package/dist/utils/mixins/FocusTrapMixin.d.ts +0 -0
- package/dist/utils/mixins/FocusTrapMixin.js +1 -0
- package/package.json +1 -1
- package/dist/components/popover/popover.stack.d.ts +0 -53
- package/dist/components/popover/popover.stack.js +0 -66
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Global stack of elements managed by DepthManager
|
|
3
|
+
* @internal
|
|
4
|
+
*/
|
|
5
|
+
const elementStack = [];
|
|
6
|
+
/**
|
|
7
|
+
* Initial z-index for the first element in the stack
|
|
8
|
+
*/
|
|
9
|
+
const BASE_Z_INDEX = 1000;
|
|
10
|
+
/**
|
|
11
|
+
* Number of z-index levels per element in the stack
|
|
12
|
+
* @internal
|
|
13
|
+
* - level -2: level of backdrop (if any)
|
|
14
|
+
* - level -1: level of trigger component (if any)
|
|
15
|
+
* - level 0: z-index of the overlay element (e.g. popover, dialog, etc.)
|
|
16
|
+
*/
|
|
17
|
+
const NUMBER_OF_Z_INDEX_LEVELS_PER_ELEMENT = 3;
|
|
18
|
+
export const OVERLAY_BACKDROP_Z_INDEX_OFFSET = -2;
|
|
19
|
+
export const OVERLAY_TRIGGER_Z_INDEX_OFFSET = -1;
|
|
20
|
+
/**
|
|
21
|
+
* DepthManager is a controller that manages a stack of elements to control their depth (z-index).
|
|
22
|
+
*
|
|
23
|
+
* It uses a global stack to keep track of the order of elements, allowing for proper layering of overlays.
|
|
24
|
+
*
|
|
25
|
+
* ## Use Case
|
|
26
|
+
*
|
|
27
|
+
* ### Pop single overlay
|
|
28
|
+
*
|
|
29
|
+
* The easiest one, usually the host removes itself from the stack when it is closed, with the `popHost` method.
|
|
30
|
+
*
|
|
31
|
+
* ### Pop until specific overlay
|
|
32
|
+
*
|
|
33
|
+
* When the chain of nested popover (e.g.: submenus) opened and the user closes other than the last one,
|
|
34
|
+
* we have to close all overlays stacked above the specific one. In this case, the `popItem` or directly the `pupUntil` method is used.
|
|
35
|
+
*
|
|
36
|
+
* ### Closing "sibling" overlays
|
|
37
|
+
*
|
|
38
|
+
* In some cases, multiple overlays can be opened from the same trigger (e.g.: tooltip, context menu, etc.), we can not close
|
|
39
|
+
* all overlays above the specific one, because they independently opened.
|
|
40
|
+
*
|
|
41
|
+
* `popUntil` method can handle this case by skipping the overlays which share the same trigger ID as the specified one.
|
|
42
|
+
*
|
|
43
|
+
* ### Manually removing overlays
|
|
44
|
+
*
|
|
45
|
+
* When the user switch from one sub-menu to another, we need to close all sub-menus from common parent menu.
|
|
46
|
+
* DepthManager does not have built-in solution for this case. The host component need to make sure the submenu
|
|
47
|
+
* hide before the new one is shown.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```ts
|
|
51
|
+
* // Add and remove item based on the disabled state
|
|
52
|
+
* class Container extends Component {
|
|
53
|
+
* private this.depthManager = new DepthManager<>(this);
|
|
54
|
+
*
|
|
55
|
+
* constructor() {
|
|
56
|
+
* super();
|
|
57
|
+
* this.addEventListener('modified', this.handleModifiedEvent);
|
|
58
|
+
* }
|
|
59
|
+
*
|
|
60
|
+
* openOverlay() {
|
|
61
|
+
* this.depthManager.pushHost()
|
|
62
|
+
* }
|
|
63
|
+
*
|
|
64
|
+
* closeOverlay() {
|
|
65
|
+
* this.depthManager.popHost()
|
|
66
|
+
* }
|
|
67
|
+
*
|
|
68
|
+
* onComponentStackChanged (change: StackChange) {
|
|
69
|
+
* switch (change) {
|
|
70
|
+
* case 'added':
|
|
71
|
+
* return;
|
|
72
|
+
* case 'removed':
|
|
73
|
+
* return this.closeOverlay()
|
|
74
|
+
* case 'moved':
|
|
75
|
+
* return this.requestUpdate('zIndex');
|
|
76
|
+
* }
|
|
77
|
+
* }
|
|
78
|
+
* }
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
export class DepthManager {
|
|
82
|
+
/**
|
|
83
|
+
* Creates an instance of DepthManager.
|
|
84
|
+
*/
|
|
85
|
+
constructor(host) {
|
|
86
|
+
this.host = host;
|
|
87
|
+
host.addController(this);
|
|
88
|
+
}
|
|
89
|
+
hostConnected() { }
|
|
90
|
+
hostDisconnected() {
|
|
91
|
+
// Remove this instance from the global stack on disconnect
|
|
92
|
+
this.remove([this.host]);
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Gets the total number of elements in the stack
|
|
96
|
+
*/
|
|
97
|
+
get length() {
|
|
98
|
+
return elementStack.length;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Adds host element to the stack
|
|
102
|
+
*
|
|
103
|
+
* @returns push was successful (true) or not (false)
|
|
104
|
+
*/
|
|
105
|
+
pushHost() {
|
|
106
|
+
var _a, _b;
|
|
107
|
+
if (!this.has(this.host)) {
|
|
108
|
+
elementStack.push(this.host);
|
|
109
|
+
(_b = (_a = this.host).onComponentStackChanged) === null || _b === void 0 ? void 0 : _b.call(_a, 'added');
|
|
110
|
+
return true;
|
|
111
|
+
}
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Pops all the items above the host and then pops the host itself
|
|
116
|
+
*
|
|
117
|
+
* @returns The host if it was in the stack, undefined otherwise
|
|
118
|
+
*/
|
|
119
|
+
popHost() {
|
|
120
|
+
return this.popItem(this.host);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Pops all the items above the specified item and then pops the item itself
|
|
124
|
+
*
|
|
125
|
+
* @param item - The item to pop
|
|
126
|
+
* @returns The item if it was in the stack, undefined otherwise
|
|
127
|
+
*/
|
|
128
|
+
popItem(item) {
|
|
129
|
+
if (this.has(item)) {
|
|
130
|
+
const untilItemIdx = elementStack.indexOf(item) - 1;
|
|
131
|
+
this.popUntil((it, idx) => {
|
|
132
|
+
// This can handle the case when multiple overlays share the same trigger (id), e.g.: tooltip, etc.
|
|
133
|
+
if (it !== item && it.triggerID === item.triggerID)
|
|
134
|
+
return 'skip';
|
|
135
|
+
return idx !== untilItemIdx;
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
return undefined;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Removes the last element from the stack
|
|
142
|
+
*
|
|
143
|
+
* @returns The last element in the stack
|
|
144
|
+
*/
|
|
145
|
+
pop() {
|
|
146
|
+
var _a;
|
|
147
|
+
const popped = elementStack.pop();
|
|
148
|
+
(_a = popped === null || popped === void 0 ? void 0 : popped.onComponentStackChanged) === null || _a === void 0 ? void 0 : _a.call(popped, 'removed');
|
|
149
|
+
return popped;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Removes elements from the stack until the predicate function returns false
|
|
153
|
+
*
|
|
154
|
+
* Note: it will remove the
|
|
155
|
+
*
|
|
156
|
+
* @param predicateFn - The predicate function to test each element
|
|
157
|
+
* @returns The removed elements
|
|
158
|
+
*/
|
|
159
|
+
popUntil(predicateFn) {
|
|
160
|
+
const poppedElements = [];
|
|
161
|
+
for (let i = elementStack.length - 1; i >= 0; i -= 1) {
|
|
162
|
+
const item = elementStack[i];
|
|
163
|
+
const result = predicateFn(item, i);
|
|
164
|
+
if (result === false)
|
|
165
|
+
break;
|
|
166
|
+
if (result !== 'skip')
|
|
167
|
+
poppedElements.push(item);
|
|
168
|
+
}
|
|
169
|
+
return this.remove(poppedElements);
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Returns the last element in the stack
|
|
173
|
+
* without removing it
|
|
174
|
+
*
|
|
175
|
+
* @returns The last element in the stack
|
|
176
|
+
*/
|
|
177
|
+
peek() {
|
|
178
|
+
return elementStack.at(-1);
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Removes one or more elements from the stack without popping others.
|
|
182
|
+
*
|
|
183
|
+
* It notifies the elements on the stack which were removed and those which changed position.
|
|
184
|
+
* Items removed in bach, notify moved items only once.
|
|
185
|
+
*
|
|
186
|
+
* @param elements - Popover instance
|
|
187
|
+
* @returns undefined when the element was not found, the removed element otherwise
|
|
188
|
+
*/
|
|
189
|
+
remove(elements) {
|
|
190
|
+
var _a, _b;
|
|
191
|
+
const removedElements = elements.filter(el => elementStack.includes(el));
|
|
192
|
+
const updateStackFrom = removedElements.reduce((idx, el) => Math.min(idx, elementStack.indexOf(el)), Infinity);
|
|
193
|
+
// Remove elements from the stack
|
|
194
|
+
removedElements.forEach(el => {
|
|
195
|
+
var _a;
|
|
196
|
+
elementStack.splice(elementStack.indexOf(el), 1);
|
|
197
|
+
(_a = el === null || el === void 0 ? void 0 : el.onComponentStackChanged) === null || _a === void 0 ? void 0 : _a.call(el, 'removed');
|
|
198
|
+
});
|
|
199
|
+
// Notify elements about the move
|
|
200
|
+
for (let i = updateStackFrom; i < elementStack.length; i += 1) {
|
|
201
|
+
(_b = (_a = elementStack[i]).onComponentStackChanged) === null || _b === void 0 ? void 0 : _b.call(_a, 'moved');
|
|
202
|
+
}
|
|
203
|
+
return removedElements;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Checks if the stack has a specific element
|
|
207
|
+
*
|
|
208
|
+
* @param element - Popover instance
|
|
209
|
+
* @returns True if the stack has the element, false otherwise
|
|
210
|
+
*/
|
|
211
|
+
has(element) {
|
|
212
|
+
return elementStack.includes(element);
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Gets the depth of the host element in the stack
|
|
216
|
+
*/
|
|
217
|
+
getHostDepth() {
|
|
218
|
+
return this.getElementDepth(this.host);
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Gets the depth of the element in the stack
|
|
222
|
+
* @param element - The element to get the depth of
|
|
223
|
+
*/
|
|
224
|
+
getElementDepth(element) {
|
|
225
|
+
return elementStack.indexOf(element);
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Gets the z-index of the host element in the stack
|
|
229
|
+
*/
|
|
230
|
+
getHostZIndex() {
|
|
231
|
+
return this.getItemZIndex(this.host);
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Gets the z-index of the element in the stack
|
|
235
|
+
* @param element - The element to get the z-index of
|
|
236
|
+
*
|
|
237
|
+
* @returns The z-index of the element if found, otherwise returns -1
|
|
238
|
+
*/
|
|
239
|
+
getItemZIndex(element) {
|
|
240
|
+
const depth = this.getElementDepth(element);
|
|
241
|
+
return depth >= 0 ? BASE_Z_INDEX + depth * NUMBER_OF_Z_INDEX_LEVELS_PER_ELEMENT : -1;
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Checks if host is at the top of the stack
|
|
245
|
+
*
|
|
246
|
+
* @returns True if host is on top, false otherwise
|
|
247
|
+
*/
|
|
248
|
+
isHostOnTop() {
|
|
249
|
+
return this.peek() === this.host;
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Clears the stack
|
|
253
|
+
*
|
|
254
|
+
* Pops all elements from the stack one-by-one.
|
|
255
|
+
*/
|
|
256
|
+
clear() {
|
|
257
|
+
this.popUntil(() => true);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { OVERLAY_BACKDROP_Z_INDEX_OFFSET, OVERLAY_TRIGGER_Z_INDEX_OFFSET } from '../controllers/DepthManager';
|
|
1
2
|
export const BackdropMixin = (superClass) => {
|
|
2
3
|
class Backdrop extends superClass {
|
|
3
4
|
constructor() {
|
|
@@ -11,6 +12,20 @@ export const BackdropMixin = (superClass) => {
|
|
|
11
12
|
this.isBackdropInvisible = false;
|
|
12
13
|
/** @internal */
|
|
13
14
|
this.backdropElement = null;
|
|
15
|
+
/** @internal */
|
|
16
|
+
this.triggerElementCache = null;
|
|
17
|
+
}
|
|
18
|
+
update(changedProperties) {
|
|
19
|
+
var _a;
|
|
20
|
+
super.update(changedProperties);
|
|
21
|
+
if (changedProperties.has('zIndex') && this.backdropElement) {
|
|
22
|
+
// Update the backdrop z-index if the zIndex property changes
|
|
23
|
+
this.backdropElement.style.zIndex = `${this.zIndex + OVERLAY_BACKDROP_Z_INDEX_OFFSET}`;
|
|
24
|
+
const triggerEl = (_a = this.triggerElementCache) === null || _a === void 0 ? void 0 : _a.deref();
|
|
25
|
+
if (triggerEl) {
|
|
26
|
+
triggerEl.style.zIndex = `${this.zIndex + OVERLAY_TRIGGER_Z_INDEX_OFFSET}`;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
14
29
|
}
|
|
15
30
|
/**
|
|
16
31
|
* Creates a backdrop element with the specified class name prefix.
|
|
@@ -30,7 +45,7 @@ export const BackdropMixin = (superClass) => {
|
|
|
30
45
|
width: 100%;
|
|
31
46
|
height: 100%;
|
|
32
47
|
background: ${this.isBackdropInvisible ? `transparent` : `var(--mds-color-theme-common-overlays-secondary-normal)`};
|
|
33
|
-
z-index: ${this.zIndex
|
|
48
|
+
z-index: ${this.zIndex + OVERLAY_BACKDROP_Z_INDEX_OFFSET};
|
|
34
49
|
}
|
|
35
50
|
`;
|
|
36
51
|
backdrop.appendChild(styleElement);
|
|
@@ -63,13 +78,14 @@ export const BackdropMixin = (superClass) => {
|
|
|
63
78
|
if (!element) {
|
|
64
79
|
return;
|
|
65
80
|
}
|
|
81
|
+
this.triggerElementCache = new WeakRef(element);
|
|
66
82
|
// Store the original z-index and position of the element
|
|
67
83
|
this.elementOriginalStyle = {
|
|
68
84
|
zIndex: element.style.zIndex,
|
|
69
85
|
position: element.style.position,
|
|
70
86
|
};
|
|
71
87
|
// Set the z-index and position to ensure the element is above the backdrop
|
|
72
|
-
element.style.zIndex = `${this.zIndex
|
|
88
|
+
element.style.zIndex = `${this.zIndex + OVERLAY_TRIGGER_Z_INDEX_OFFSET}`;
|
|
73
89
|
// Only set the position to relative if it is not already set to fixed or absolute
|
|
74
90
|
if (!['fixed', 'absolute'].includes(window.getComputedStyle(element).position)) {
|
|
75
91
|
element.style.position = 'relative';
|
|
@@ -93,6 +109,7 @@ export const BackdropMixin = (superClass) => {
|
|
|
93
109
|
element.style.position = this.elementOriginalStyle.position;
|
|
94
110
|
// Clear the stored original style
|
|
95
111
|
this.elementOriginalStyle = undefined;
|
|
112
|
+
this.triggerElementCache = null;
|
|
96
113
|
}
|
|
97
114
|
}
|
|
98
115
|
return Backdrop;
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
package/package.json
CHANGED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import type Popover from './popover.component';
|
|
2
|
-
/**
|
|
3
|
-
* Manages a stack of popovers to control their order and lifecycle.
|
|
4
|
-
* This class allows adding, removing, and retrieving popovers
|
|
5
|
-
* while maintaining their stacking behavior.
|
|
6
|
-
*
|
|
7
|
-
*/
|
|
8
|
-
declare class PopoverStack {
|
|
9
|
-
/**
|
|
10
|
-
* Stack to maintain the order of popovers
|
|
11
|
-
* @internal
|
|
12
|
-
*/
|
|
13
|
-
private stack;
|
|
14
|
-
/**
|
|
15
|
-
* Adds a popover to the stack
|
|
16
|
-
*
|
|
17
|
-
* @param popover - Popover instance
|
|
18
|
-
* @returns The new depth of the stack
|
|
19
|
-
*/
|
|
20
|
-
push(popover: Popover): number;
|
|
21
|
-
/**
|
|
22
|
-
* Removes the last popover from the stack
|
|
23
|
-
*
|
|
24
|
-
* @returns The last popover in the stack
|
|
25
|
-
*/
|
|
26
|
-
pop(): Popover | undefined;
|
|
27
|
-
/**
|
|
28
|
-
* Returns the last popover in the stack
|
|
29
|
-
* without removing it
|
|
30
|
-
*
|
|
31
|
-
* @returns The last popover in the stack
|
|
32
|
-
*/
|
|
33
|
-
peek(): Popover | undefined;
|
|
34
|
-
/**
|
|
35
|
-
* Removes a popover from the stack
|
|
36
|
-
*
|
|
37
|
-
* @param popover - Popover instance
|
|
38
|
-
*/
|
|
39
|
-
remove(popover: Popover): void;
|
|
40
|
-
/**
|
|
41
|
-
* Checks if the stack has a specific popover
|
|
42
|
-
*
|
|
43
|
-
* @param popover - Popover instance
|
|
44
|
-
* @returns True if the stack has the popover, false otherwise
|
|
45
|
-
*/
|
|
46
|
-
has(popover: Popover): boolean;
|
|
47
|
-
/**
|
|
48
|
-
* Clears the stack
|
|
49
|
-
*/
|
|
50
|
-
clear(): void;
|
|
51
|
-
}
|
|
52
|
-
export declare const popoverStack: PopoverStack;
|
|
53
|
-
export {};
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Manages a stack of popovers to control their order and lifecycle.
|
|
3
|
-
* This class allows adding, removing, and retrieving popovers
|
|
4
|
-
* while maintaining their stacking behavior.
|
|
5
|
-
*
|
|
6
|
-
*/
|
|
7
|
-
class PopoverStack {
|
|
8
|
-
constructor() {
|
|
9
|
-
/**
|
|
10
|
-
* Stack to maintain the order of popovers
|
|
11
|
-
* @internal
|
|
12
|
-
*/
|
|
13
|
-
this.stack = [];
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* Adds a popover to the stack
|
|
17
|
-
*
|
|
18
|
-
* @param popover - Popover instance
|
|
19
|
-
* @returns The new depth of the stack
|
|
20
|
-
*/
|
|
21
|
-
push(popover) {
|
|
22
|
-
this.stack.push(popover);
|
|
23
|
-
return this.stack.length;
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Removes the last popover from the stack
|
|
27
|
-
*
|
|
28
|
-
* @returns The last popover in the stack
|
|
29
|
-
*/
|
|
30
|
-
pop() {
|
|
31
|
-
return this.stack.pop();
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Returns the last popover in the stack
|
|
35
|
-
* without removing it
|
|
36
|
-
*
|
|
37
|
-
* @returns The last popover in the stack
|
|
38
|
-
*/
|
|
39
|
-
peek() {
|
|
40
|
-
return this.stack[this.stack.length - 1];
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Removes a popover from the stack
|
|
44
|
-
*
|
|
45
|
-
* @param popover - Popover instance
|
|
46
|
-
*/
|
|
47
|
-
remove(popover) {
|
|
48
|
-
this.stack = this.stack.filter(item => item !== popover);
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Checks if the stack has a specific popover
|
|
52
|
-
*
|
|
53
|
-
* @param popover - Popover instance
|
|
54
|
-
* @returns True if the stack has the popover, false otherwise
|
|
55
|
-
*/
|
|
56
|
-
has(popover) {
|
|
57
|
-
return this.stack.includes(popover);
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Clears the stack
|
|
61
|
-
*/
|
|
62
|
-
clear() {
|
|
63
|
-
this.stack = [];
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
export const popoverStack = new PopoverStack();
|