@crowdstrike/glide-core 0.29.2 → 0.30.1
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/accordion.js +240 -1
- package/dist/accordion.styles.js +13 -7
- package/dist/button-group.button.js +143 -1
- package/dist/button-group.button.styles.js +43 -15
- package/dist/button-group.js +249 -1
- package/dist/button-group.styles.js +10 -5
- package/dist/button.js +206 -1
- package/dist/button.styles.js +12 -7
- package/dist/checkbox-group.js +479 -14
- package/dist/checkbox-group.styles.js +5 -2
- package/dist/checkbox.js +519 -32
- package/dist/checkbox.styles.js +10 -5
- package/dist/drawer.js +168 -1
- package/dist/drawer.styles.js +5 -2
- package/dist/dropdown.js +2423 -123
- package/dist/dropdown.option.js +536 -1
- package/dist/dropdown.option.styles.js +5 -2
- package/dist/dropdown.styles.js +15 -8
- package/dist/form-controls-layout.js +102 -1
- package/dist/form-controls-layout.styles.js +5 -2
- package/dist/icon-button.js +139 -1
- package/dist/icon-button.styles.js +19 -7
- package/dist/icons/checked.js +28 -1
- package/dist/icons/chevron.js +21 -1
- package/dist/icons/magnifying-glass.js +23 -1
- package/dist/icons/pencil.js +21 -1
- package/dist/icons/severity-critical.js +20 -1
- package/dist/icons/severity-informational.js +20 -1
- package/dist/icons/severity-medium.js +20 -1
- package/dist/icons/x.js +21 -1
- package/dist/inline-alert.js +118 -1
- package/dist/inline-alert.styles.js +5 -2
- package/dist/input.d.ts +8 -2
- package/dist/input.js +505 -41
- package/dist/input.styles.js +25 -4
- package/dist/label.js +303 -1
- package/dist/label.styles.js +11 -5
- package/dist/library/assert-slot.js +136 -1
- package/dist/library/expect-unhandled-rejection.js +14 -1
- package/dist/library/expect-window-error.js +26 -1
- package/dist/library/final.js +18 -1
- package/dist/library/form-control.js +1 -1
- package/dist/library/localize.js +10 -1
- package/dist/library/mouse.js +35 -1
- package/dist/library/on-resize.js +24 -1
- package/dist/library/required.js +35 -1
- package/dist/library/shadow-root-mode.js +4 -1
- package/dist/library/unique-id.js +3 -1
- package/dist/link.js +92 -1
- package/dist/link.styles.js +10 -5
- package/dist/menu.d.ts +3 -2
- package/dist/menu.js +1259 -1
- package/dist/menu.styles.js +35 -19
- package/dist/modal.d.ts +4 -0
- package/dist/modal.icon-button.js +60 -1
- package/dist/modal.icon-button.styles.js +5 -2
- package/dist/modal.js +473 -1
- package/dist/modal.styles.js +71 -22
- package/dist/option.d.ts +74 -0
- package/dist/option.js +498 -0
- package/dist/option.styles.js +140 -0
- package/dist/{menu.options.d.ts → options.d.ts} +5 -6
- package/dist/options.js +130 -0
- package/dist/options.styles.js +21 -0
- package/dist/popover.js +620 -1
- package/dist/popover.styles.js +11 -5
- package/dist/radio-group.js +624 -17
- package/dist/radio-group.radio.js +211 -1
- package/dist/radio-group.radio.styles.js +9 -4
- package/dist/radio-group.styles.js +5 -2
- package/dist/slider.js +1040 -61
- package/dist/slider.styles.js +9 -4
- package/dist/spinner.js +60 -1
- package/dist/spinner.styles.js +5 -2
- package/dist/split-button.js +116 -1
- package/dist/split-button.primary-button.js +100 -1
- package/dist/split-button.primary-button.styles.js +13 -6
- package/dist/split-button.primary-link.js +102 -1
- package/dist/split-button.secondary-button.d.ts +2 -3
- package/dist/split-button.secondary-button.js +121 -1
- package/dist/split-button.secondary-button.styles.js +12 -7
- package/dist/split-button.styles.js +9 -4
- package/dist/styles/focus-outline.js +9 -3
- package/dist/styles/fonts.css +6 -1
- package/dist/styles/opacity-and-scale-animation.js +6 -3
- package/dist/styles/skeleton.js +6 -3
- package/dist/styles/variables.css +410 -1
- package/dist/styles/visually-hidden.js +6 -3
- package/dist/tab.group.js +386 -1
- package/dist/tab.group.styles.js +5 -2
- package/dist/tab.js +133 -1
- package/dist/tab.panel.js +93 -1
- package/dist/tab.panel.styles.js +11 -5
- package/dist/tab.styles.js +9 -4
- package/dist/tag.js +207 -1
- package/dist/tag.styles.js +10 -5
- package/dist/textarea.js +353 -19
- package/dist/textarea.styles.js +23 -4
- package/dist/toast.js +130 -1
- package/dist/toast.toasts.js +248 -25
- package/dist/toast.toasts.styles.js +9 -4
- package/dist/toggle.js +178 -1
- package/dist/toggle.styles.js +25 -5
- package/dist/tooltip.container.js +130 -1
- package/dist/tooltip.container.styles.js +5 -2
- package/dist/tooltip.js +484 -1
- package/dist/tooltip.styles.js +21 -5
- package/dist/translations/en.js +36 -1
- package/dist/translations/fr.js +37 -1
- package/dist/translations/ja.js +37 -1
- package/package.json +8 -12
- package/dist/menu.button.d.ts +0 -42
- package/dist/menu.button.js +0 -1
- package/dist/menu.button.styles.js +0 -32
- package/dist/menu.link.d.ts +0 -44
- package/dist/menu.link.js +0 -1
- package/dist/menu.link.styles.js +0 -35
- package/dist/menu.options.js +0 -1
- package/dist/menu.options.styles.d.ts +0 -2
- package/dist/menu.options.styles.js +0 -20
- /package/dist/{menu.button.styles.d.ts → option.styles.d.ts} +0 -0
- /package/dist/{menu.link.styles.d.ts → options.styles.d.ts} +0 -0
package/dist/menu.styles.js
CHANGED
@@ -1,35 +1,51 @@
|
|
1
|
-
import{css}from
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
.component {
|
10
|
-
color: var(--glide-core-color-static-text-default);
|
11
|
-
display: flex;
|
12
|
-
}
|
13
|
-
|
1
|
+
import { css } from 'lit';
|
2
|
+
import opacityAndScaleAnimation from './styles/opacity-and-scale-animation.js';
|
3
|
+
export default [
|
4
|
+
css `
|
5
|
+
${opacityAndScaleAnimation('.default-slot:popover-open')}
|
6
|
+
`,
|
7
|
+
css `
|
14
8
|
.target-slot {
|
15
|
-
|
16
|
-
|
9
|
+
&::slotted(:is([disabled], [aria-disabled='true'])) {
|
10
|
+
color: var(--glide-core-color-interactive-icon-default--disabled);
|
11
|
+
cursor: default;
|
12
|
+
}
|
17
13
|
}
|
18
14
|
|
19
15
|
.default-slot {
|
20
16
|
background-color: var(
|
21
17
|
--glide-core-private-color-dialog-and-modal-surface-container
|
22
18
|
);
|
23
|
-
border: 1px solid
|
24
|
-
var(--glide-core-color-static-surface-container-secondary);
|
19
|
+
border: 1px solid var(--glide-core-color-static-stroke-secondary);
|
25
20
|
border-radius: var(--glide-core-rounding-base-radius-sm);
|
26
21
|
box-shadow: var(--glide-core-effect-floating);
|
27
22
|
box-sizing: border-box;
|
23
|
+
color: var(--glide-core-color-static-text-default);
|
24
|
+
|
25
|
+
/*
|
26
|
+
For submenus, which will inherit "cursor: pointer" from their Option(s).
|
27
|
+
"cursor: default" tells the user that clicking the padding around the
|
28
|
+
default slot won't select an Option.
|
29
|
+
*/
|
30
|
+
cursor: default;
|
28
31
|
inline-size: max-content;
|
29
32
|
inset: unset;
|
30
33
|
margin-block: 0;
|
31
34
|
min-inline-size: 9.375rem;
|
32
|
-
padding:
|
35
|
+
padding-block-end: 0;
|
36
|
+
padding-block-start: var(--glide-core-spacing-base-xxxs);
|
37
|
+
padding-inline: var(--glide-core-spacing-base-xxxs);
|
33
38
|
position: absolute;
|
39
|
+
|
40
|
+
/*
|
41
|
+
This little hack replaces "padding-block-end", which the last option overlaps
|
42
|
+
when the Option(s) overflow and scroll.
|
43
|
+
*/
|
44
|
+
&::slotted(glide-core-options)::after {
|
45
|
+
block-size: var(--glide-core-spacing-base-xxxs);
|
46
|
+
content: '';
|
47
|
+
display: block;
|
48
|
+
}
|
34
49
|
}
|
35
|
-
|
50
|
+
`,
|
51
|
+
];
|
package/dist/modal.d.ts
CHANGED
@@ -7,6 +7,7 @@ declare global {
|
|
7
7
|
/**
|
8
8
|
* @attr {string} label
|
9
9
|
* @attr {boolean} [back-button=false]
|
10
|
+
* @attr {string} [description]
|
10
11
|
* @attr {boolean} [open=false]
|
11
12
|
* @attr {'critical'|'informational'|'medium'} [severity]
|
12
13
|
* @attr {'small'|'medium'|'large'|'xlarge'} [size='medium']
|
@@ -28,6 +29,7 @@ export default class Modal extends LitElement {
|
|
28
29
|
static styles: import("lit").CSSResult[];
|
29
30
|
label?: string;
|
30
31
|
backButton: boolean;
|
32
|
+
description?: string;
|
31
33
|
/**
|
32
34
|
* @default false
|
33
35
|
*/
|
@@ -43,4 +45,6 @@ export default class Modal extends LitElement {
|
|
43
45
|
private hasPrimarySlotContent;
|
44
46
|
private hasSecondarySlotContent;
|
45
47
|
private hasTertiarySlotContent;
|
48
|
+
private isScrolledFromBottom;
|
49
|
+
private isScrolledFromTop;
|
46
50
|
}
|
@@ -1 +1,60 @@
|
|
1
|
-
var __decorate=this&&this.__decorate
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
6
|
+
};
|
7
|
+
import './icon-button.js';
|
8
|
+
import { html, LitElement } from 'lit';
|
9
|
+
import { customElement, property } from 'lit/decorators.js';
|
10
|
+
import { ifDefined } from 'lit/directives/if-defined.js';
|
11
|
+
import packageJson from '../package.json' with { type: 'json' };
|
12
|
+
import styles from './modal.icon-button.styles.js';
|
13
|
+
import assertSlot from './library/assert-slot.js';
|
14
|
+
import shadowRootMode from './library/shadow-root-mode.js';
|
15
|
+
import final from './library/final.js';
|
16
|
+
import required from './library/required.js';
|
17
|
+
/**
|
18
|
+
* @attr {string} label
|
19
|
+
*
|
20
|
+
* @readonly
|
21
|
+
* @attr {string} [version]
|
22
|
+
*
|
23
|
+
* @slot {Element} - An icon
|
24
|
+
*/
|
25
|
+
let ModalIconButton = class ModalIconButton extends LitElement {
|
26
|
+
constructor() {
|
27
|
+
super(...arguments);
|
28
|
+
this.version = packageJson.version;
|
29
|
+
}
|
30
|
+
static { this.shadowRootOptions = {
|
31
|
+
...LitElement.shadowRootOptions,
|
32
|
+
mode: shadowRootMode,
|
33
|
+
}; }
|
34
|
+
static { this.styles = styles; }
|
35
|
+
render() {
|
36
|
+
return html `
|
37
|
+
<glide-core-icon-button label=${ifDefined(this.label)} variant="tertiary">
|
38
|
+
<slot ${assertSlot()}>
|
39
|
+
<!--
|
40
|
+
An icon
|
41
|
+
@required
|
42
|
+
@type {Element}
|
43
|
+
-->
|
44
|
+
</slot>
|
45
|
+
</glide-core-icon-button>
|
46
|
+
`;
|
47
|
+
}
|
48
|
+
};
|
49
|
+
__decorate([
|
50
|
+
property({ reflect: true }),
|
51
|
+
required
|
52
|
+
], ModalIconButton.prototype, "label", void 0);
|
53
|
+
__decorate([
|
54
|
+
property({ reflect: true })
|
55
|
+
], ModalIconButton.prototype, "version", void 0);
|
56
|
+
ModalIconButton = __decorate([
|
57
|
+
customElement('glide-core-modal-icon-button'),
|
58
|
+
final
|
59
|
+
], ModalIconButton);
|
60
|
+
export default ModalIconButton;
|
package/dist/modal.js
CHANGED
@@ -1 +1,473 @@
|
|
1
|
-
var __decorate
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
6
|
+
};
|
7
|
+
import { html, LitElement } from 'lit';
|
8
|
+
import { classMap } from 'lit/directives/class-map.js';
|
9
|
+
import { createRef, ref } from 'lit/directives/ref.js';
|
10
|
+
import { customElement, property, state } from 'lit/decorators.js';
|
11
|
+
import { styleMap } from 'lit/directives/style-map.js';
|
12
|
+
import { when } from 'lit/directives/when.js';
|
13
|
+
import packageJson from '../package.json' with { type: 'json' };
|
14
|
+
import { LocalizeController } from './library/localize.js';
|
15
|
+
import ModalIconButton from './modal.icon-button.js';
|
16
|
+
import Button from './button.js';
|
17
|
+
import Tooltip from './tooltip.js';
|
18
|
+
import styles from './modal.styles.js';
|
19
|
+
import xIcon from './icons/x.js';
|
20
|
+
import assertSlot from './library/assert-slot.js';
|
21
|
+
import shadowRootMode from './library/shadow-root-mode.js';
|
22
|
+
import severityInformationalIcon from './icons/severity-informational.js';
|
23
|
+
import severityMediumIcon from './icons/severity-medium.js';
|
24
|
+
import severityCriticalIcon from './icons/severity-critical.js';
|
25
|
+
import final from './library/final.js';
|
26
|
+
import required from './library/required.js';
|
27
|
+
import onResize from './library/on-resize.js';
|
28
|
+
const globalStylesheet = new CSSStyleSheet();
|
29
|
+
globalStylesheet.insertRule(`
|
30
|
+
.private-glide-core-modal-lock-scroll {
|
31
|
+
scrollbar-gutter: stable !important;
|
32
|
+
overflow: hidden !important;
|
33
|
+
}
|
34
|
+
`);
|
35
|
+
/**
|
36
|
+
* @attr {string} label
|
37
|
+
* @attr {boolean} [back-button=false]
|
38
|
+
* @attr {string} [description]
|
39
|
+
* @attr {boolean} [open=false]
|
40
|
+
* @attr {'critical'|'informational'|'medium'} [severity]
|
41
|
+
* @attr {'small'|'medium'|'large'|'xlarge'} [size='medium']
|
42
|
+
*
|
43
|
+
* @readonly
|
44
|
+
* @attr {string} [version]
|
45
|
+
*
|
46
|
+
* @slot {Element | string}
|
47
|
+
* @slot {ModalIconButton} [header-actions]
|
48
|
+
* @slot {Button} [primary]
|
49
|
+
* @slot {Button} [secondary]
|
50
|
+
* @slot {Button | Tooltip} [tertiary]
|
51
|
+
*
|
52
|
+
* @fires {Event} toggle
|
53
|
+
*/
|
54
|
+
let Modal = class Modal extends LitElement {
|
55
|
+
constructor() {
|
56
|
+
super(...arguments);
|
57
|
+
this.backButton = false;
|
58
|
+
this.size = 'medium';
|
59
|
+
this.version = packageJson.version;
|
60
|
+
this.hasPrimarySlotContent = false;
|
61
|
+
this.hasSecondarySlotContent = false;
|
62
|
+
this.hasTertiarySlotContent = false;
|
63
|
+
this.isScrolledFromBottom = false;
|
64
|
+
this.isScrolledFromTop = false;
|
65
|
+
this.#backButtonElementRef = createRef();
|
66
|
+
this.#bodyElementRef = createRef();
|
67
|
+
this.#closeButtonElementRef = createRef();
|
68
|
+
this.#componentElementRef = createRef();
|
69
|
+
this.#containerElementRef = createRef();
|
70
|
+
this.#headerActionsSlotElementRef = createRef();
|
71
|
+
this.#isContainerClick = false;
|
72
|
+
this.#isOpen = false;
|
73
|
+
this.#localize = new LocalizeController(this);
|
74
|
+
this.#primarySlotElementRef = createRef();
|
75
|
+
this.#secondarySlotElementRef = createRef();
|
76
|
+
this.#tertiarySlotElementRef = createRef();
|
77
|
+
// An arrow function field instead of a method so `this` is closed over and
|
78
|
+
// set to the component instead of `document`.
|
79
|
+
this.#onContainerClick = () => {
|
80
|
+
this.#isContainerClick = true;
|
81
|
+
};
|
82
|
+
// An arrow function field instead of a method so `this` is closed over and
|
83
|
+
// set to the component instead of `document`.
|
84
|
+
this.#onDocumentClick = () => {
|
85
|
+
const isOpen = this.open;
|
86
|
+
// There's a comment in `firstUpdated()` explaining the timeout.
|
87
|
+
setTimeout(() => {
|
88
|
+
if (this.#isContainerClick) {
|
89
|
+
// This handler will be called twice for a single click if the element clicked was
|
90
|
+
// a `<label>`. Because clicking a `<label>` produces two "click" events.
|
91
|
+
//
|
92
|
+
// If we immediately set `#isContainerClick` to `false`, Modal will close when this
|
93
|
+
// handler is called the second time. So we wait a tick to ensure both "click"
|
94
|
+
// events have been dispatched.
|
95
|
+
setTimeout(() => {
|
96
|
+
this.#isContainerClick = false;
|
97
|
+
});
|
98
|
+
// The click may be a result of the user clicking a button to open Modal.
|
99
|
+
// If so then `this.open` will have been set to `true` in the frame between
|
100
|
+
// when this handler was called and this timeout. And we don't want to
|
101
|
+
// immediately close Modal after the user has opened it. So we only close
|
102
|
+
// Modal if the state of `this.open` hasn't changed.
|
103
|
+
}
|
104
|
+
else if (isOpen === this.open) {
|
105
|
+
this.open = false;
|
106
|
+
}
|
107
|
+
});
|
108
|
+
};
|
109
|
+
}
|
110
|
+
static { this.shadowRootOptions = {
|
111
|
+
...LitElement.shadowRootOptions,
|
112
|
+
mode: shadowRootMode,
|
113
|
+
}; }
|
114
|
+
static { this.styles = styles; }
|
115
|
+
/**
|
116
|
+
* @default false
|
117
|
+
*/
|
118
|
+
get open() {
|
119
|
+
return this.#isOpen;
|
120
|
+
}
|
121
|
+
set open(isOpen) {
|
122
|
+
const hasChanged = isOpen !== this.#isOpen;
|
123
|
+
this.#isOpen = isOpen;
|
124
|
+
if (isOpen && hasChanged) {
|
125
|
+
this.#show();
|
126
|
+
this.dispatchEvent(new Event('toggle', { bubbles: true, composed: true }));
|
127
|
+
}
|
128
|
+
else if (hasChanged) {
|
129
|
+
this.#hide();
|
130
|
+
this.dispatchEvent(new Event('toggle', { bubbles: true, composed: true }));
|
131
|
+
}
|
132
|
+
}
|
133
|
+
connectedCallback() {
|
134
|
+
super.connectedCallback();
|
135
|
+
const isAdopted = document.adoptedStyleSheets.includes(globalStylesheet);
|
136
|
+
if (!isAdopted) {
|
137
|
+
document.adoptedStyleSheets.push(globalStylesheet);
|
138
|
+
}
|
139
|
+
// 1. The consumer has a click handler on a button.
|
140
|
+
// 2. The user clicks the button.
|
141
|
+
// 3. The button's click handler is called and sets `this.open` to `true`.
|
142
|
+
// 4. The "click" event bubbles up and is handled by `#onDocumentClick`.
|
143
|
+
// 5. That handler sets `open` to `false` because the click came from outside
|
144
|
+
// Modal.
|
145
|
+
// 6. Modal is opened then closed in the same frame and so never opens.
|
146
|
+
//
|
147
|
+
// `capture` ensures `#onDocumentClick` is called before #3, so the button click
|
148
|
+
// handler setting `open` to `true` isn't overwritten by this handler setting
|
149
|
+
// `open` to `false`.
|
150
|
+
document.addEventListener('click', this.#onDocumentClick, {
|
151
|
+
capture: true,
|
152
|
+
});
|
153
|
+
}
|
154
|
+
disconnectedCallback() {
|
155
|
+
super.disconnectedCallback();
|
156
|
+
document.documentElement.classList.remove('private-glide-core-modal-lock-scroll');
|
157
|
+
document.adoptedStyleSheets = document.adoptedStyleSheets.filter((stylesheet) => {
|
158
|
+
return stylesheet !== globalStylesheet;
|
159
|
+
});
|
160
|
+
document.removeEventListener('click', this.#onDocumentClick, {
|
161
|
+
capture: true,
|
162
|
+
});
|
163
|
+
}
|
164
|
+
firstUpdated() {
|
165
|
+
if (this.open) {
|
166
|
+
this.#show();
|
167
|
+
}
|
168
|
+
// Modals's "click" handler on `document` listens for clicks in the capture
|
169
|
+
// phase. There's a comment explaining why. `#isContainerClick` must be set
|
170
|
+
// by this handler before that handler is called. That handler will be called
|
171
|
+
// first because events travel down instead of up the `document` during their
|
172
|
+
// capture phase. But this "click" handler, because it listens in the capture
|
173
|
+
// phase, will be called in the same frame. So the `document` handler checks
|
174
|
+
// `#isContainerClick` after a timeout to give this handler a chance to be called.
|
175
|
+
//
|
176
|
+
// In short, we have to listen in the capture phase here because the `document`
|
177
|
+
// listener listens in the capture phase.
|
178
|
+
this.#containerElementRef.value?.addEventListener('click', this.#onContainerClick, { capture: true });
|
179
|
+
}
|
180
|
+
// The contents `<dialog>` are wrapped in a `<div>` so we can separate backdrop
|
181
|
+
// clicks from non-backdrop ones. We add "click" listeners to the `<div>` and the
|
182
|
+
// `document`. The former listener sets a boolean that the latter has a condition
|
183
|
+
// for. If the boolean is `false`, then we know the click came from the backdrop.
|
184
|
+
// That's also why the padding is on the `<div>`, so padding clicks come from
|
185
|
+
// inside it and Modal remains open.
|
186
|
+
render() {
|
187
|
+
return html `<dialog
|
188
|
+
class=${classMap({
|
189
|
+
component: true,
|
190
|
+
small: this.size === 'small',
|
191
|
+
medium: this.size === 'medium',
|
192
|
+
large: this.size === 'large',
|
193
|
+
xlarge: this.size === 'xlarge',
|
194
|
+
})}
|
195
|
+
data-test="component"
|
196
|
+
@keydown=${this.#onComponentKeyDown}
|
197
|
+
${ref(this.#componentElementRef)}
|
198
|
+
${onResize(this.#onScrollAndResize.bind(this))})}
|
199
|
+
>
|
200
|
+
<div
|
201
|
+
class="container"
|
202
|
+
@mouseup=${this.#onContainerMouseup}
|
203
|
+
${ref(this.#containerElementRef)}
|
204
|
+
>
|
205
|
+
<header
|
206
|
+
class=${classMap({ header: true, shadow: this.isScrolledFromTop })}
|
207
|
+
>
|
208
|
+
<div class="label-and-actions">
|
209
|
+
<h2 class="label" data-test="heading" id="heading">
|
210
|
+
${when(this.severity, () => html `<span
|
211
|
+
aria-label="${this.#localize.term(this.severity === 'informational'
|
212
|
+
? 'severityInformational'
|
213
|
+
: this.severity === 'critical'
|
214
|
+
? 'severityCritical'
|
215
|
+
: 'severityMedium')} - "
|
216
|
+
class=${classMap({
|
217
|
+
severity: true,
|
218
|
+
critical: this.severity === 'critical',
|
219
|
+
informational: this.severity === 'informational',
|
220
|
+
medium: this.severity === 'medium',
|
221
|
+
})}
|
222
|
+
data-test="severity"
|
223
|
+
>
|
224
|
+
${this.severity && icons[this.severity]}
|
225
|
+
</span>`)}
|
226
|
+
${when(this.backButton && !this.severity, () => html `<glide-core-modal-icon-button
|
227
|
+
class="back-button"
|
228
|
+
data-test="back-button"
|
229
|
+
label=${this.#localize.term('close')}
|
230
|
+
@click=${this.#onCloseButtonClick}
|
231
|
+
${ref(this.#backButtonElementRef)}
|
232
|
+
>
|
233
|
+
${icons.back}
|
234
|
+
</glide-core-modal-icon-button>`)}
|
235
|
+
${this.label}
|
236
|
+
</h2>
|
237
|
+
|
238
|
+
<div class="header-actions" role="toolbar">
|
239
|
+
<slot
|
240
|
+
name="header-actions"
|
241
|
+
${assertSlot([ModalIconButton], true)}
|
242
|
+
${ref(this.#headerActionsSlotElementRef)}
|
243
|
+
>
|
244
|
+
<!-- @type {ModalIconButton} -->
|
245
|
+
</slot>
|
246
|
+
|
247
|
+
<glide-core-modal-icon-button
|
248
|
+
class="close-button"
|
249
|
+
data-test="close-button"
|
250
|
+
label=${this.#localize.term('close')}
|
251
|
+
@click=${this.#onCloseButtonClick}
|
252
|
+
${ref(this.#closeButtonElementRef)}
|
253
|
+
>
|
254
|
+
${xIcon}
|
255
|
+
</glide-core-modal-icon-button>
|
256
|
+
</div>
|
257
|
+
</div>
|
258
|
+
|
259
|
+
${when(this.description, () => html `<h3
|
260
|
+
class="description"
|
261
|
+
data-test="description"
|
262
|
+
id="description"
|
263
|
+
>
|
264
|
+
${this.description}
|
265
|
+
</h3>`)}
|
266
|
+
</header>
|
267
|
+
|
268
|
+
<div
|
269
|
+
aria-labelledby=${this.description
|
270
|
+
? 'heading description'
|
271
|
+
: 'heading'}
|
272
|
+
class="body"
|
273
|
+
role="region"
|
274
|
+
@scroll=${this.#onScrollAndResize}
|
275
|
+
${ref(this.#bodyElementRef)}
|
276
|
+
>
|
277
|
+
<slot ${assertSlot()}>
|
278
|
+
<!-- @type {Element | string} -->
|
279
|
+
</slot>
|
280
|
+
</div>
|
281
|
+
|
282
|
+
<footer
|
283
|
+
class=${classMap({
|
284
|
+
footer: true,
|
285
|
+
shadow: this.isScrolledFromBottom,
|
286
|
+
})}
|
287
|
+
>
|
288
|
+
<menu
|
289
|
+
aria-hidden=${!this.hasTertiarySlotContent &&
|
290
|
+
!this.hasSecondarySlotContent &&
|
291
|
+
!this.hasPrimarySlotContent}
|
292
|
+
class="actions"
|
293
|
+
>
|
294
|
+
<li aria-hidden=${!this.hasTertiarySlotContent} class="action">
|
295
|
+
<slot
|
296
|
+
class="tertiary-slot"
|
297
|
+
name="tertiary"
|
298
|
+
@slotchange=${this.#onTertiarySlotChange}
|
299
|
+
${assertSlot([Button, Tooltip], true)}
|
300
|
+
${ref(this.#tertiarySlotElementRef)}
|
301
|
+
>
|
302
|
+
<!-- @type {Button | Tooltip} -->
|
303
|
+
</slot>
|
304
|
+
</li>
|
305
|
+
|
306
|
+
<li aria-hidden=${!this.hasSecondarySlotContent} class="action">
|
307
|
+
<slot
|
308
|
+
name="secondary"
|
309
|
+
@slotchange=${this.#onSecondarySlotChange}
|
310
|
+
${assertSlot([Button], true)}
|
311
|
+
${ref(this.#secondarySlotElementRef)}
|
312
|
+
>
|
313
|
+
<!-- @type {Button} -->
|
314
|
+
</slot>
|
315
|
+
</li>
|
316
|
+
|
317
|
+
<li aria-hidden=${!this.hasPrimarySlotContent} class="action">
|
318
|
+
<slot
|
319
|
+
name="primary"
|
320
|
+
@slotchange=${this.#onPrimarySlotChange}
|
321
|
+
${assertSlot([Button], true)}
|
322
|
+
${ref(this.#primarySlotElementRef)}
|
323
|
+
>
|
324
|
+
<!-- @type {Button} -->
|
325
|
+
</slot>
|
326
|
+
</li>
|
327
|
+
</menu>
|
328
|
+
</footer>
|
329
|
+
</div>
|
330
|
+
</dialog>`;
|
331
|
+
}
|
332
|
+
#backButtonElementRef;
|
333
|
+
#bodyElementRef;
|
334
|
+
#closeButtonElementRef;
|
335
|
+
#componentElementRef;
|
336
|
+
#containerElementRef;
|
337
|
+
#headerActionsSlotElementRef;
|
338
|
+
#isContainerClick;
|
339
|
+
#isOpen;
|
340
|
+
#localize;
|
341
|
+
#primarySlotElementRef;
|
342
|
+
#secondarySlotElementRef;
|
343
|
+
#tertiarySlotElementRef;
|
344
|
+
// An arrow function field instead of a method so `this` is closed over and
|
345
|
+
// set to the component instead of `document`.
|
346
|
+
#onContainerClick;
|
347
|
+
// An arrow function field instead of a method so `this` is closed over and
|
348
|
+
// set to the component instead of `document`.
|
349
|
+
#onDocumentClick;
|
350
|
+
#hide() {
|
351
|
+
document.documentElement.classList.remove('private-glide-core-modal-lock-scroll');
|
352
|
+
this.#componentElementRef.value?.close();
|
353
|
+
}
|
354
|
+
#onCloseButtonClick() {
|
355
|
+
this.open = false;
|
356
|
+
}
|
357
|
+
#onComponentKeyDown(event) {
|
358
|
+
if (event.key === 'Escape') {
|
359
|
+
this.open = false;
|
360
|
+
// Prevent Safari from leaving full screen.
|
361
|
+
event.preventDefault();
|
362
|
+
}
|
363
|
+
}
|
364
|
+
// For the case where the user accidentally mouses down on the Modal's backdrop,
|
365
|
+
// then moves the mouse inside Modal before mousing up. Without this handler, Modal
|
366
|
+
// would close instead of remaining open. The reason it's needed in addition to
|
367
|
+
// the "click" handler is because programmatic clicks don't generate "mousedown"
|
368
|
+
// events. And we ran into a case where a consumer was calling `click()` on an
|
369
|
+
// element inside Modal, inadvertently closing it. Otherwise, this event handler
|
370
|
+
// would suffice.
|
371
|
+
#onContainerMouseup() {
|
372
|
+
this.#isContainerClick = true;
|
373
|
+
}
|
374
|
+
#onPrimarySlotChange() {
|
375
|
+
this.hasPrimarySlotContent = Boolean(this.#primarySlotElementRef.value?.assignedElements().length);
|
376
|
+
}
|
377
|
+
#onScrollAndResize() {
|
378
|
+
if (this.open && this.#bodyElementRef.value) {
|
379
|
+
if (this.#bodyElementRef.value.scrollHeight >
|
380
|
+
this.#bodyElementRef.value.clientHeight) {
|
381
|
+
this.isScrolledFromTop = this.#bodyElementRef.value.scrollTop > 0;
|
382
|
+
this.isScrolledFromBottom =
|
383
|
+
this.#bodyElementRef.value.scrollHeight -
|
384
|
+
this.#bodyElementRef.value.scrollTop -
|
385
|
+
this.#bodyElementRef.value.clientHeight >
|
386
|
+
0;
|
387
|
+
}
|
388
|
+
else {
|
389
|
+
this.isScrolledFromTop = false;
|
390
|
+
this.isScrolledFromBottom = false;
|
391
|
+
}
|
392
|
+
}
|
393
|
+
}
|
394
|
+
#onSecondarySlotChange() {
|
395
|
+
this.hasSecondarySlotContent = Boolean(this.#secondarySlotElementRef.value?.assignedElements().length);
|
396
|
+
}
|
397
|
+
#onTertiarySlotChange() {
|
398
|
+
this.hasTertiarySlotContent = Boolean(this.#tertiarySlotElementRef.value?.assignedElements().length);
|
399
|
+
}
|
400
|
+
#show() {
|
401
|
+
document.documentElement.classList.add('private-glide-core-modal-lock-scroll');
|
402
|
+
this.#componentElementRef.value?.showModal();
|
403
|
+
}
|
404
|
+
};
|
405
|
+
__decorate([
|
406
|
+
property({ reflect: true }),
|
407
|
+
required
|
408
|
+
], Modal.prototype, "label", void 0);
|
409
|
+
__decorate([
|
410
|
+
property({ attribute: 'back-button', type: Boolean, reflect: true })
|
411
|
+
], Modal.prototype, "backButton", void 0);
|
412
|
+
__decorate([
|
413
|
+
property({ reflect: true })
|
414
|
+
], Modal.prototype, "description", void 0);
|
415
|
+
__decorate([
|
416
|
+
property({ reflect: true, type: Boolean })
|
417
|
+
], Modal.prototype, "open", null);
|
418
|
+
__decorate([
|
419
|
+
property({ reflect: true })
|
420
|
+
], Modal.prototype, "severity", void 0);
|
421
|
+
__decorate([
|
422
|
+
property({ reflect: true, useDefault: true })
|
423
|
+
], Modal.prototype, "size", void 0);
|
424
|
+
__decorate([
|
425
|
+
property({ reflect: true })
|
426
|
+
], Modal.prototype, "version", void 0);
|
427
|
+
__decorate([
|
428
|
+
state()
|
429
|
+
], Modal.prototype, "hasPrimarySlotContent", void 0);
|
430
|
+
__decorate([
|
431
|
+
state()
|
432
|
+
], Modal.prototype, "hasSecondarySlotContent", void 0);
|
433
|
+
__decorate([
|
434
|
+
state()
|
435
|
+
], Modal.prototype, "hasTertiarySlotContent", void 0);
|
436
|
+
__decorate([
|
437
|
+
state()
|
438
|
+
], Modal.prototype, "isScrolledFromBottom", void 0);
|
439
|
+
__decorate([
|
440
|
+
state()
|
441
|
+
], Modal.prototype, "isScrolledFromTop", void 0);
|
442
|
+
Modal = __decorate([
|
443
|
+
customElement('glide-core-modal'),
|
444
|
+
final
|
445
|
+
], Modal);
|
446
|
+
export default Modal;
|
447
|
+
const icons = {
|
448
|
+
back: html `
|
449
|
+
<svg
|
450
|
+
style=${styleMap({
|
451
|
+
height: '1.25rem',
|
452
|
+
width: '1.25rem',
|
453
|
+
})}
|
454
|
+
viewBox="0 0 24 24"
|
455
|
+
fill="none"
|
456
|
+
>
|
457
|
+
<path
|
458
|
+
d="M12 18C11.4477 18 11 18.4477 11 19C11 19.5523 11.4477 20 12 20V18ZM20 14.5C20 16.433 18.433 18 16.5 18V20C19.5376 20 22 17.5376 22 14.5H20ZM16.5 11C18.433 11 20 12.567 20 14.5H22C22 11.4624 19.5376 9 16.5 9V11ZM16.5 18H12V20H16.5V18ZM16.5 9H3V11H16.5V9Z"
|
459
|
+
fill="currentColor"
|
460
|
+
/>
|
461
|
+
<path
|
462
|
+
d="M7 6L3 10L7 14"
|
463
|
+
stroke="currentColor"
|
464
|
+
stroke-width="2"
|
465
|
+
stroke-linecap="round"
|
466
|
+
stroke-linejoin="round"
|
467
|
+
/>
|
468
|
+
</svg>
|
469
|
+
`,
|
470
|
+
critical: severityCriticalIcon,
|
471
|
+
informational: severityInformationalIcon,
|
472
|
+
medium: severityMediumIcon,
|
473
|
+
};
|