@momentum-design/components 0.83.2 → 0.83.4
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 +179 -179
- package/dist/browser/index.js.map +4 -4
- package/dist/components/dialog/dialog.component.d.ts +22 -12
- package/dist/components/dialog/dialog.component.js +47 -25
- package/dist/components/dialog/dialog.events.d.ts +9 -1
- package/dist/components/dialog/dialog.events.js +12 -2
- package/dist/components/dialog/dialog.types.d.ts +1 -0
- package/dist/components/popover/popover.component.d.ts +6 -7
- package/dist/components/popover/popover.component.js +45 -23
- package/dist/components/tooltip/tooltip.component.js +1 -1
- package/dist/custom-elements.json +1958 -1818
- package/dist/react/dialog/index.d.ts +8 -0
- package/dist/react/dialog/index.js +8 -0
- package/dist/react/index.d.ts +5 -5
- package/dist/react/index.js +5 -5
- package/dist/utils/mixins/FocusTrapMixin.d.ts +2 -2
- package/dist/utils/mixins/FocusTrapMixin.js +70 -35
- package/dist/utils/mixins/PreventScrollMixin.d.ts +9 -0
- package/dist/utils/mixins/PreventScrollMixin.js +32 -0
- package/package.json +1 -1
@@ -10,6 +10,11 @@ import Component from '../../components/dialog';
|
|
10
10
|
* If a `triggerId` is provided, the dialog will manage focus with that element, otherwise it will
|
11
11
|
* remember the previously focused element before the dialog was opened.
|
12
12
|
*
|
13
|
+
* The dialog is a controlled component, meaning it does not have its own state management for visibility.
|
14
|
+
* Use the `visible` property to control the visibility of the dialog.
|
15
|
+
* Use the `onClose` event to handle the close action of the dialog (fired when Close button is clicked
|
16
|
+
* or Escape is pressed).
|
17
|
+
*
|
13
18
|
* Dialog component have 2 variants: default and promotional.
|
14
19
|
*
|
15
20
|
* **Accessibility notes for consuming (have to be explicitly set when you consume the component)**
|
@@ -30,6 +35,8 @@ import Component from '../../components/dialog';
|
|
30
35
|
* @event hidden - (React: onHidden) Dispatched when the dialog is hidden
|
31
36
|
* @event created - (React: onCreated) Dispatched when the dialog is created (added to the DOM)
|
32
37
|
* @event destroyed - (React: onDestroyed) Dispatched when the dialog is destroyed (removed from the DOM)
|
38
|
+
* @event close - (React: onClose) Dispatched when the Close Button is clicked or Escape key is pressed
|
39
|
+
* (this does not hide the dialog)
|
33
40
|
*
|
34
41
|
* @cssproperty --mdc-dialog-primary-background-color - primary background color of the dialog
|
35
42
|
* @cssproperty --mdc-dialog-border-color - border color of the dialog
|
@@ -53,5 +60,6 @@ declare const reactWrapper: import("@lit/react").ReactWebComponent<Component, {
|
|
53
60
|
onHidden: EventName<Event>;
|
54
61
|
onCreated: EventName<Event>;
|
55
62
|
onDestroyed: EventName<Event>;
|
63
|
+
onClose: EventName<Event>;
|
56
64
|
}>;
|
57
65
|
export default reactWrapper;
|
@@ -12,6 +12,11 @@ import { TAG_NAME } from '../../components/dialog/dialog.constants';
|
|
12
12
|
* If a `triggerId` is provided, the dialog will manage focus with that element, otherwise it will
|
13
13
|
* remember the previously focused element before the dialog was opened.
|
14
14
|
*
|
15
|
+
* The dialog is a controlled component, meaning it does not have its own state management for visibility.
|
16
|
+
* Use the `visible` property to control the visibility of the dialog.
|
17
|
+
* Use the `onClose` event to handle the close action of the dialog (fired when Close button is clicked
|
18
|
+
* or Escape is pressed).
|
19
|
+
*
|
15
20
|
* Dialog component have 2 variants: default and promotional.
|
16
21
|
*
|
17
22
|
* **Accessibility notes for consuming (have to be explicitly set when you consume the component)**
|
@@ -32,6 +37,8 @@ import { TAG_NAME } from '../../components/dialog/dialog.constants';
|
|
32
37
|
* @event hidden - (React: onHidden) Dispatched when the dialog is hidden
|
33
38
|
* @event created - (React: onCreated) Dispatched when the dialog is created (added to the DOM)
|
34
39
|
* @event destroyed - (React: onDestroyed) Dispatched when the dialog is destroyed (removed from the DOM)
|
40
|
+
* @event close - (React: onClose) Dispatched when the Close Button is clicked or Escape key is pressed
|
41
|
+
* (this does not hide the dialog)
|
35
42
|
*
|
36
43
|
* @cssproperty --mdc-dialog-primary-background-color - primary background color of the dialog
|
37
44
|
* @cssproperty --mdc-dialog-border-color - border color of the dialog
|
@@ -59,6 +66,7 @@ const reactWrapper = createComponent({
|
|
59
66
|
onHidden: 'hidden',
|
60
67
|
onCreated: 'created',
|
61
68
|
onDestroyed: 'destroyed',
|
69
|
+
onClose: 'close',
|
62
70
|
},
|
63
71
|
displayName: 'Dialog',
|
64
72
|
});
|
package/dist/react/index.d.ts
CHANGED
@@ -1,20 +1,20 @@
|
|
1
|
-
export { default as AlertChip } from './alertchip';
|
2
1
|
export { default as Animation } from './animation';
|
3
2
|
export { default as Appheader } from './appheader';
|
3
|
+
export { default as AlertChip } from './alertchip';
|
4
4
|
export { default as Avatar } from './avatar';
|
5
5
|
export { default as AvatarButton } from './avatarbutton';
|
6
6
|
export { default as Badge } from './badge';
|
7
|
+
export { default as Brandvisual } from './brandvisual';
|
7
8
|
export { default as Bullet } from './bullet';
|
8
9
|
export { default as Button } from './button';
|
9
|
-
export { default as Brandvisual } from './brandvisual';
|
10
|
-
export { default as ButtonLink } from './buttonlink';
|
11
10
|
export { default as ButtonGroup } from './buttongroup';
|
11
|
+
export { default as ButtonLink } from './buttonlink';
|
12
12
|
export { default as Buttonsimple } from './buttonsimple';
|
13
13
|
export { default as Card } from './card';
|
14
14
|
export { default as CardButton } from './cardbutton';
|
15
15
|
export { default as CardCheckbox } from './cardcheckbox';
|
16
|
-
export { default as Checkbox } from './checkbox';
|
17
16
|
export { default as CardRadio } from './cardradio';
|
17
|
+
export { default as Checkbox } from './checkbox';
|
18
18
|
export { default as Chip } from './chip';
|
19
19
|
export { default as Coachmark } from './coachmark';
|
20
20
|
export { default as Dialog } from './dialog';
|
@@ -32,8 +32,8 @@ export { default as List } from './list';
|
|
32
32
|
export { default as ListItem } from './listitem';
|
33
33
|
export { default as Marker } from './marker';
|
34
34
|
export { default as MenuBar } from './menubar';
|
35
|
-
export { default as MenuItemCheckbox } from './menuitemcheckbox';
|
36
35
|
export { default as MenuItem } from './menuitem';
|
36
|
+
export { default as MenuItemCheckbox } from './menuitemcheckbox';
|
37
37
|
export { default as MenuItemRadio } from './menuitemradio';
|
38
38
|
export { default as MenuPopover } from './menupopover';
|
39
39
|
export { default as MenuSection } from './menusection';
|
package/dist/react/index.js
CHANGED
@@ -1,20 +1,20 @@
|
|
1
|
-
export { default as AlertChip } from './alertchip';
|
2
1
|
export { default as Animation } from './animation';
|
3
2
|
export { default as Appheader } from './appheader';
|
3
|
+
export { default as AlertChip } from './alertchip';
|
4
4
|
export { default as Avatar } from './avatar';
|
5
5
|
export { default as AvatarButton } from './avatarbutton';
|
6
6
|
export { default as Badge } from './badge';
|
7
|
+
export { default as Brandvisual } from './brandvisual';
|
7
8
|
export { default as Bullet } from './bullet';
|
8
9
|
export { default as Button } from './button';
|
9
|
-
export { default as Brandvisual } from './brandvisual';
|
10
|
-
export { default as ButtonLink } from './buttonlink';
|
11
10
|
export { default as ButtonGroup } from './buttongroup';
|
11
|
+
export { default as ButtonLink } from './buttonlink';
|
12
12
|
export { default as Buttonsimple } from './buttonsimple';
|
13
13
|
export { default as Card } from './card';
|
14
14
|
export { default as CardButton } from './cardbutton';
|
15
15
|
export { default as CardCheckbox } from './cardcheckbox';
|
16
|
-
export { default as Checkbox } from './checkbox';
|
17
16
|
export { default as CardRadio } from './cardradio';
|
17
|
+
export { default as Checkbox } from './checkbox';
|
18
18
|
export { default as Chip } from './chip';
|
19
19
|
export { default as Coachmark } from './coachmark';
|
20
20
|
export { default as Dialog } from './dialog';
|
@@ -32,8 +32,8 @@ export { default as List } from './list';
|
|
32
32
|
export { default as ListItem } from './listitem';
|
33
33
|
export { default as Marker } from './marker';
|
34
34
|
export { default as MenuBar } from './menubar';
|
35
|
-
export { default as MenuItemCheckbox } from './menuitemcheckbox';
|
36
35
|
export { default as MenuItem } from './menuitem';
|
36
|
+
export { default as MenuItemCheckbox } from './menuitemcheckbox';
|
37
37
|
export { default as MenuItemRadio } from './menuitemradio';
|
38
38
|
export { default as MenuPopover } from './menupopover';
|
39
39
|
export { default as MenuSection } from './menusection';
|
@@ -2,9 +2,9 @@ import type { Component } from '../../models';
|
|
2
2
|
import type { Constructor } from './index.types';
|
3
3
|
export declare abstract class FocusTrapClassInterface {
|
4
4
|
protected abstract focusTrap: boolean;
|
5
|
-
enabledPreventScroll: boolean;
|
6
5
|
setInitialFocus(elementIndexToReceiveFocus?: number): void;
|
7
6
|
activateFocusTrap(): void;
|
8
7
|
deactivateFocusTrap(): void;
|
8
|
+
private setIsFocusTrapActivated;
|
9
9
|
}
|
10
|
-
export declare const FocusTrapMixin: <T extends Constructor<Component>>(superClass: T) => Constructor<
|
10
|
+
export declare const FocusTrapMixin: <T extends Constructor<Component>>(superClass: T) => Constructor<Component & FocusTrapClassInterface> & T;
|
@@ -7,8 +7,69 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
7
7
|
var __metadata = (this && this.__metadata) || function (k, v) {
|
8
8
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
9
9
|
};
|
10
|
+
/* eslint-disable no-use-before-define */
|
10
11
|
/* eslint-disable max-classes-per-file */
|
11
12
|
import { property } from 'lit/decorators.js';
|
13
|
+
/**
|
14
|
+
* FocusTrapStack manages a stack of active focus traps,
|
15
|
+
* ensuring only one focus trap is active at a time.
|
16
|
+
*
|
17
|
+
* This also makes sure there is only one keydown listener active at a time,
|
18
|
+
* which is necessary to handle focus trapping correctly.
|
19
|
+
*/
|
20
|
+
class FocusTrapStack {
|
21
|
+
static get stackArray() {
|
22
|
+
return Array.from(this.stack);
|
23
|
+
}
|
24
|
+
static addKeydownListener(keydownListener) {
|
25
|
+
this.currentKeydownListener = keydownListener;
|
26
|
+
document.addEventListener('keydown', keydownListener);
|
27
|
+
}
|
28
|
+
static removeKeydownListener() {
|
29
|
+
if (this.currentKeydownListener) {
|
30
|
+
document.removeEventListener('keydown', this.currentKeydownListener);
|
31
|
+
}
|
32
|
+
}
|
33
|
+
/**
|
34
|
+
* Activates a focus trap by adding it to the stack.
|
35
|
+
* It deactivates all other traps in the stack to ensure only one trap is active
|
36
|
+
*
|
37
|
+
* @param trap - The focus trap to activate.
|
38
|
+
*/
|
39
|
+
static activate(trap) {
|
40
|
+
// Deactivate all other traps
|
41
|
+
this.stackArray.forEach((activeTrap) => {
|
42
|
+
if (activeTrap !== trap) {
|
43
|
+
activeTrap.setIsFocusTrapActivated(false);
|
44
|
+
}
|
45
|
+
});
|
46
|
+
this.stack.add(trap);
|
47
|
+
// remove the current keydown listener if it exists
|
48
|
+
// and add a new one for the current trap
|
49
|
+
this.removeKeydownListener();
|
50
|
+
this.addKeydownListener(trap.handleTabKeydown.bind(trap));
|
51
|
+
}
|
52
|
+
/**
|
53
|
+
* Deactivates a focus trap by removing it from the stack.
|
54
|
+
* Activates the previous trap in the stack if any.
|
55
|
+
*
|
56
|
+
* @param trap - The focus trap to deactivate.
|
57
|
+
*/
|
58
|
+
static deactivate(trap) {
|
59
|
+
this.stack.delete(trap);
|
60
|
+
this.removeKeydownListener();
|
61
|
+
// activate the previous trap in the stack if any
|
62
|
+
if (this.stack.size > 0) {
|
63
|
+
const lastTrap = this.stackArray.pop();
|
64
|
+
if (lastTrap) {
|
65
|
+
lastTrap.setIsFocusTrapActivated(true);
|
66
|
+
this.addKeydownListener(lastTrap.handleTabKeydown.bind(lastTrap));
|
67
|
+
}
|
68
|
+
}
|
69
|
+
}
|
70
|
+
}
|
71
|
+
FocusTrapStack.stack = new Set();
|
72
|
+
FocusTrapStack.currentKeydownListener = null;
|
12
73
|
export const FocusTrapMixin = (superClass) => {
|
13
74
|
class FocusTrap extends superClass {
|
14
75
|
constructor() {
|
@@ -21,11 +82,6 @@ export const FocusTrapMixin = (superClass) => {
|
|
21
82
|
* @default true
|
22
83
|
*/
|
23
84
|
this.shouldFocusTrapWrap = true;
|
24
|
-
/**
|
25
|
-
* Prevent outside scrolling when element is shown.
|
26
|
-
* @default false
|
27
|
-
*/
|
28
|
-
this.enabledPreventScroll = false;
|
29
85
|
/** @internal */
|
30
86
|
this.focusTrapIndex = -1;
|
31
87
|
/** @internal */
|
@@ -33,38 +89,23 @@ export const FocusTrapMixin = (superClass) => {
|
|
33
89
|
/** @internal */
|
34
90
|
this.isFocusTrapActivated = false;
|
35
91
|
}
|
36
|
-
|
37
|
-
|
38
|
-
document.addEventListener('keydown', this.handleTabKeydown.bind(this));
|
39
|
-
}
|
40
|
-
disconnectedCallback() {
|
41
|
-
super.disconnectedCallback();
|
42
|
-
document.removeEventListener('keydown', this.handleTabKeydown.bind(this));
|
43
|
-
}
|
44
|
-
async updated(changedProperties) {
|
45
|
-
super.updated(changedProperties);
|
46
|
-
if (changedProperties.has('focusTrap')) {
|
47
|
-
if (!this.focusTrap) {
|
48
|
-
this.deactivateFocusTrap();
|
49
|
-
}
|
50
|
-
}
|
92
|
+
setIsFocusTrapActivated(isActivated) {
|
93
|
+
this.isFocusTrapActivated = isActivated;
|
51
94
|
}
|
52
95
|
/**
|
53
96
|
* Activate the focus trap
|
54
|
-
* This calculates the focusable elements within the component's shadow root
|
55
97
|
*/
|
56
98
|
activateFocusTrap() {
|
57
|
-
this.
|
99
|
+
this.setIsFocusTrapActivated(true);
|
100
|
+
FocusTrapStack.activate(this);
|
58
101
|
}
|
59
102
|
/**
|
60
103
|
* Deactivate the focus trap.
|
61
104
|
*/
|
62
105
|
deactivateFocusTrap() {
|
63
|
-
this.
|
106
|
+
this.setIsFocusTrapActivated(false);
|
107
|
+
FocusTrapStack.deactivate(this);
|
64
108
|
this.focusTrapIndex = -1;
|
65
|
-
this.enabledPreventScroll = false;
|
66
|
-
// todo: this should not override the body overflow style, but reset it instead
|
67
|
-
document.body.style.overflow = '';
|
68
109
|
}
|
69
110
|
/**
|
70
111
|
* Checks if the element has no client rectangles (not visible in the viewport).
|
@@ -233,12 +274,9 @@ export const FocusTrapMixin = (superClass) => {
|
|
233
274
|
if (this.focusableElements.length === 0 || !this.focusTrap) {
|
234
275
|
return;
|
235
276
|
}
|
236
|
-
if (this.enabledPreventScroll) {
|
237
|
-
document.body.style.overflow = 'hidden';
|
238
|
-
}
|
239
277
|
if (this.focusableElements[elementIndexToReceiveFocus]) {
|
240
278
|
this.focusTrapIndex = elementIndexToReceiveFocus;
|
241
|
-
this.focusableElements[elementIndexToReceiveFocus].focus();
|
279
|
+
this.focusableElements[elementIndexToReceiveFocus].focus({ preventScroll: true });
|
242
280
|
}
|
243
281
|
}
|
244
282
|
/**
|
@@ -325,7 +363,7 @@ export const FocusTrapMixin = (superClass) => {
|
|
325
363
|
}
|
326
364
|
const nextElement = this.focusableElements[this.focusTrapIndex];
|
327
365
|
if (nextElement) {
|
328
|
-
nextElement.focus();
|
366
|
+
nextElement.focus({ preventScroll: true });
|
329
367
|
}
|
330
368
|
}
|
331
369
|
/**
|
@@ -333,6 +371,7 @@ export const FocusTrapMixin = (superClass) => {
|
|
333
371
|
*
|
334
372
|
* @param event - The keyboard event.
|
335
373
|
*/
|
374
|
+
// @ts-ignore - this is a method which will be called in the stack
|
336
375
|
handleTabKeydown(event) {
|
337
376
|
if (!this.isFocusTrapActivated) {
|
338
377
|
return;
|
@@ -347,9 +386,5 @@ export const FocusTrapMixin = (superClass) => {
|
|
347
386
|
property({ type: Boolean, reflect: true, attribute: 'should-focus-trap-wrap' }),
|
348
387
|
__metadata("design:type", Boolean)
|
349
388
|
], FocusTrap.prototype, "shouldFocusTrapWrap", void 0);
|
350
|
-
__decorate([
|
351
|
-
property({ type: Boolean }),
|
352
|
-
__metadata("design:type", Boolean)
|
353
|
-
], FocusTrap.prototype, "enabledPreventScroll", void 0);
|
354
389
|
return FocusTrap;
|
355
390
|
};
|
@@ -0,0 +1,9 @@
|
|
1
|
+
import { LitElement } from 'lit';
|
2
|
+
import type { Constructor } from './index.types';
|
3
|
+
import type { Component } from '../../models';
|
4
|
+
export declare abstract class PreventScrollMixinInterface {
|
5
|
+
protected abstract preventScroll?: boolean;
|
6
|
+
protected activatePreventScroll(): void;
|
7
|
+
protected deactivatePreventScroll(): void;
|
8
|
+
}
|
9
|
+
export declare const PreventScrollMixin: <T extends Constructor<LitElement>>(superClass: T) => Constructor<Component & PreventScrollMixinInterface> & T;
|
@@ -0,0 +1,32 @@
|
|
1
|
+
export const PreventScrollMixin = (superClass) => {
|
2
|
+
class PreventScroll extends superClass {
|
3
|
+
constructor() {
|
4
|
+
super(...arguments);
|
5
|
+
/**
|
6
|
+
* @internal
|
7
|
+
*/
|
8
|
+
this.isPreventScrollActive = false;
|
9
|
+
/**
|
10
|
+
* @internal
|
11
|
+
*/
|
12
|
+
this.previousDocumentBodyStyleOverflow = '';
|
13
|
+
}
|
14
|
+
activatePreventScroll() {
|
15
|
+
if (this.preventScroll && !this.isPreventScrollActive) {
|
16
|
+
this.isPreventScrollActive = true;
|
17
|
+
// Store the previous body overflow style
|
18
|
+
this.previousDocumentBodyStyleOverflow = document.body.style.overflow;
|
19
|
+
// Set body overflow to hidden to prevent scrolling
|
20
|
+
document.body.style.overflow = 'hidden';
|
21
|
+
}
|
22
|
+
}
|
23
|
+
deactivatePreventScroll() {
|
24
|
+
if (this.isPreventScrollActive) {
|
25
|
+
this.isPreventScrollActive = false;
|
26
|
+
// Restore the previous body overflow style
|
27
|
+
document.body.style.overflow = this.previousDocumentBodyStyleOverflow;
|
28
|
+
}
|
29
|
+
}
|
30
|
+
}
|
31
|
+
return PreventScroll;
|
32
|
+
};
|
package/package.json
CHANGED