tyrell-components 1.0.0-TC52 → 1.0.0-TC53
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/css/tyrell-theme.css +25 -2
- package/css/tyrell.css +4 -0
- package/dist/tyrell-colors-static.css +1 -316
- package/dist/tyrell-theme.css +1 -1443
- package/dist/tyrell.css +1 -1390
- package/dist/tyrell.js +1 -1
- package/lib/base/ty-component.js +196 -196
- package/lib/components/button.d.ts +1 -1
- package/lib/components/button.js +260 -259
- package/lib/components/calendar-month.d.ts +2 -2
- package/lib/components/calendar-month.js +426 -416
- package/lib/components/calendar-navigation.js +238 -238
- package/lib/components/calendar.js +605 -602
- package/lib/components/checkbox.d.ts +1 -1
- package/lib/components/checkbox.js +273 -272
- package/lib/components/copy.d.ts +1 -1
- package/lib/components/copy.js +279 -278
- package/lib/components/date-picker.d.ts +1 -1
- package/lib/components/date-picker.js +1103 -1108
- package/lib/components/file-upload.js +404 -404
- package/lib/components/icon.js +141 -141
- package/lib/components/input.d.ts +1 -1
- package/lib/components/input.js +593 -596
- package/lib/components/modal.js +319 -319
- package/lib/components/option.js +167 -167
- package/lib/components/popup.js +233 -233
- package/lib/components/radio.d.ts +2 -2
- package/lib/components/radio.js +407 -406
- package/lib/components/resize-observer.js +67 -67
- package/lib/components/scroll-container.js +294 -294
- package/lib/components/select.d.ts +1 -1
- package/lib/components/select.js +1524 -1532
- package/lib/components/selected-tags.js +184 -184
- package/lib/components/step.js +62 -62
- package/lib/components/switch.d.ts +1 -1
- package/lib/components/switch.js +214 -213
- package/lib/components/tab.js +62 -62
- package/lib/components/tabs.js +507 -507
- package/lib/components/tag.d.ts +1 -1
- package/lib/components/tag.js +236 -235
- package/lib/components/textarea.d.ts +1 -1
- package/lib/components/textarea.js +457 -456
- package/lib/components/tooltip.js +283 -283
- package/lib/components/wizard.js +384 -384
- package/lib/icons/heroicons/micro.js +392 -392
- package/lib/icons/heroicons/mini.js +382 -382
- package/lib/icons/heroicons/outline.js +337 -337
- package/lib/icons/heroicons/solid.js +407 -407
- package/lib/icons/lucide.js +22843 -22843
- package/lib/icons/material/filled.js +9653 -9653
- package/lib/icons/material/outlined.js +10271 -10271
- package/lib/icons/material/round.js +10495 -10495
- package/lib/icons/material/sharp.js +9905 -9905
- package/lib/icons/material/two-tone.js +12792 -12792
- package/lib/index.js +21 -21
- package/lib/styles/button.js +176 -288
- package/lib/styles/calendar-month.js +123 -183
- package/lib/styles/calendar-navigation.js +60 -79
- package/lib/styles/calendar.js +8 -9
- package/lib/styles/checkbox.js +45 -72
- package/lib/styles/copy.js +67 -91
- package/lib/styles/custom-scrollbar.js +80 -100
- package/lib/styles/date-picker.js +261 -331
- package/lib/styles/field-size.d.ts +6 -0
- package/lib/styles/field-size.js +91 -0
- package/lib/styles/file-upload.js +139 -169
- package/lib/styles/icon.js +92 -156
- package/lib/styles/input.js +125 -241
- package/lib/styles/modal.js +67 -102
- package/lib/styles/option.d.ts +1 -1
- package/lib/styles/option.js +47 -67
- package/lib/styles/popup.js +34 -65
- package/lib/styles/radio.js +69 -96
- package/lib/styles/resize-observer.js +2 -5
- package/lib/styles/scroll-container.js +100 -130
- package/lib/styles/select-base.js +525 -778
- package/lib/styles/select.js +140 -228
- package/lib/styles/step.js +22 -29
- package/lib/styles/switch.js +34 -55
- package/lib/styles/tab.js +22 -29
- package/lib/styles/tabs.js +171 -252
- package/lib/styles/tag.js +135 -188
- package/lib/styles/textarea.d.ts +1 -1
- package/lib/styles/textarea.js +205 -271
- package/lib/styles/tooltip.js +3 -3
- package/lib/styles/wizard.js +170 -226
- package/lib/types/common.d.ts +2 -0
- package/lib/types/common.js +6 -5
- package/lib/utils/calendar-utils.js +100 -100
- package/lib/utils/custom-scrollbar.js +272 -272
- package/lib/utils/flavor-sheet.js +14 -14
- package/lib/utils/icon-registry.js +127 -127
- package/lib/utils/loader-registry.js +3 -3
- package/lib/utils/locale.js +34 -34
- package/lib/utils/mobile.js +1 -1
- package/lib/utils/number-format.js +54 -54
- package/lib/utils/positioning.js +212 -212
- package/lib/utils/property-capture.js +36 -36
- package/lib/utils/property-manager.js +125 -125
- package/lib/utils/resize-observer.js +23 -23
- package/lib/utils/scroll-lock.js +57 -57
- package/lib/utils/styles.js +17 -17
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/package.json +4 -4
package/lib/components/modal.js
CHANGED
|
@@ -10,369 +10,369 @@ const modalIds = new WeakMap();
|
|
|
10
10
|
const pendingCloseReasons = new WeakMap();
|
|
11
11
|
const CLOSE_ICON = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-x-icon lucide-x"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>`;
|
|
12
12
|
function parseBoolAttr(el, name) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
13
|
+
if (!el.hasAttribute(name)) {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
const value = el.getAttribute(name);
|
|
17
|
+
if (value !== null && value.toLowerCase() === 'false') {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
return true;
|
|
21
21
|
}
|
|
22
22
|
function getModalAttributes(el) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
23
|
+
return {
|
|
24
|
+
open: parseBoolAttr(el, 'open'),
|
|
25
|
+
backdrop: el.hasAttribute('backdrop') ? parseBoolAttr(el, 'backdrop') : true,
|
|
26
|
+
closeOnOutsideClick: parseBoolAttr(el, 'prevent-outside-click')
|
|
27
|
+
? false
|
|
28
|
+
: el.hasAttribute('close-on-outside-click')
|
|
29
|
+
? parseBoolAttr(el, 'close-on-outside-click')
|
|
30
|
+
: true,
|
|
31
|
+
closeOnEscape: parseBoolAttr(el, 'prevent-escape')
|
|
32
|
+
? false
|
|
33
|
+
: el.hasAttribute('close-on-escape')
|
|
34
|
+
? parseBoolAttr(el, 'close-on-escape')
|
|
35
|
+
: true,
|
|
36
|
+
};
|
|
37
37
|
}
|
|
38
38
|
function getModalDialog(shadowRoot) {
|
|
39
|
-
|
|
39
|
+
return shadowRoot.querySelector('.ty-modal-dialog');
|
|
40
40
|
}
|
|
41
41
|
function getModalId(el) {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
42
|
+
let id = modalIds.get(el);
|
|
43
|
+
if (!id) {
|
|
44
|
+
id = `modal-${el.id || Math.random().toString(36).slice(2, 11)}`;
|
|
45
|
+
modalIds.set(el, id);
|
|
46
|
+
}
|
|
47
|
+
return id;
|
|
48
48
|
}
|
|
49
49
|
function isMobile() {
|
|
50
|
-
|
|
50
|
+
return window.innerWidth < 768 || navigator.maxTouchPoints > 0;
|
|
51
51
|
}
|
|
52
52
|
function dispatchModalEvent(el, eventType, detail) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
53
|
+
const event = new CustomEvent(eventType, {
|
|
54
|
+
detail,
|
|
55
|
+
cancelable: true,
|
|
56
|
+
});
|
|
57
|
+
el.dispatchEvent(event);
|
|
58
58
|
}
|
|
59
59
|
function ensureInternalDialog(shadowRoot) {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
60
|
+
let dialog = getModalDialog(shadowRoot);
|
|
61
|
+
if (!dialog) {
|
|
62
|
+
dialog = document.createElement('dialog');
|
|
63
|
+
const closeButton = document.createElement('button');
|
|
64
|
+
const contentDiv = document.createElement('div');
|
|
65
|
+
const slot = document.createElement('slot');
|
|
66
|
+
dialog.className = 'ty-modal-dialog';
|
|
67
|
+
closeButton.className = 'close-button';
|
|
68
|
+
closeButton.type = 'button';
|
|
69
|
+
closeButton.setAttribute('aria-label', 'Close modal');
|
|
70
|
+
closeButton.innerHTML = CLOSE_ICON;
|
|
71
|
+
contentDiv.className = 'modal-content';
|
|
72
|
+
contentDiv.appendChild(slot);
|
|
73
|
+
dialog.appendChild(closeButton);
|
|
74
|
+
dialog.appendChild(contentDiv);
|
|
75
|
+
shadowRoot.appendChild(dialog);
|
|
76
|
+
}
|
|
77
|
+
return dialog;
|
|
78
78
|
}
|
|
79
79
|
function closeModal(el, reason = 'programmatic', opts) {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
80
|
+
const shadowRoot = el.shadowRoot;
|
|
81
|
+
const dialog = shadowRoot ? getModalDialog(shadowRoot) : null;
|
|
82
|
+
if (!dialog || !dialog.open)
|
|
83
|
+
return;
|
|
84
|
+
if (!opts?.force) {
|
|
85
|
+
const beforeClose = new CustomEvent('beforeclose', {
|
|
86
|
+
detail: { reason },
|
|
87
|
+
cancelable: true,
|
|
88
|
+
});
|
|
89
|
+
el.dispatchEvent(beforeClose);
|
|
90
|
+
if (beforeClose.defaultPrevented)
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
pendingCloseReasons.set(el, reason);
|
|
94
|
+
el.removeAttribute('open');
|
|
95
95
|
}
|
|
96
96
|
function openModal(el) {
|
|
97
|
-
|
|
97
|
+
el.setAttribute('open', 'true');
|
|
98
98
|
}
|
|
99
99
|
function handleBackdropClick(el, event) {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
100
|
+
event.stopPropagation();
|
|
101
|
+
const shadowRoot = el.shadowRoot;
|
|
102
|
+
const dialog = shadowRoot ? getModalDialog(shadowRoot) : null;
|
|
103
|
+
if (dialog && event.target === dialog) {
|
|
104
|
+
event.preventDefault();
|
|
105
|
+
closeModal(el, 'backdrop');
|
|
106
|
+
}
|
|
107
107
|
}
|
|
108
108
|
function handleEscapeKey(el, event) {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
109
|
+
event.stopPropagation();
|
|
110
|
+
if (event.key === 'Escape') {
|
|
111
|
+
event.preventDefault();
|
|
112
|
+
closeModal(el, 'escape');
|
|
113
|
+
}
|
|
114
114
|
}
|
|
115
115
|
function handleCloseButtonClick(el, event) {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
116
|
+
event.preventDefault();
|
|
117
|
+
event.stopPropagation();
|
|
118
|
+
closeModal(el, 'close-button');
|
|
119
119
|
}
|
|
120
120
|
function handleHoverEnter(_el, event) {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
121
|
+
const content = event.currentTarget;
|
|
122
|
+
const dialog = content.closest('.ty-modal-dialog');
|
|
123
|
+
if (dialog) {
|
|
124
|
+
const closeButton = dialog.querySelector('.close-button');
|
|
125
|
+
if (closeButton) {
|
|
126
|
+
closeButton.classList.add('hide');
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
129
|
}
|
|
130
130
|
function handleHoverLeave(_el, event) {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
131
|
+
const content = event.currentTarget;
|
|
132
|
+
const dialog = content.closest('.ty-modal-dialog');
|
|
133
|
+
if (dialog) {
|
|
134
|
+
const closeButton = dialog.querySelector('.close-button');
|
|
135
|
+
if (closeButton) {
|
|
136
|
+
closeButton.classList.remove('hide');
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
139
|
}
|
|
140
140
|
function setupBackdropClick(el, dialog, enabled) {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
141
|
+
const existingHandler = backdropClickHandlers.get(el);
|
|
142
|
+
if (existingHandler) {
|
|
143
|
+
dialog.removeEventListener('click', existingHandler);
|
|
144
|
+
backdropClickHandlers.delete(el);
|
|
145
|
+
}
|
|
146
|
+
if (enabled) {
|
|
147
|
+
const handler = (e) => handleBackdropClick(el, e);
|
|
148
|
+
backdropClickHandlers.set(el, handler);
|
|
149
|
+
dialog.addEventListener('click', handler);
|
|
150
|
+
}
|
|
151
151
|
}
|
|
152
152
|
function setupEscapeKey(el, dialog, enabled) {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
153
|
+
const existingHandler = escapeKeyHandlers.get(el);
|
|
154
|
+
if (existingHandler) {
|
|
155
|
+
dialog.removeEventListener('keydown', existingHandler);
|
|
156
|
+
escapeKeyHandlers.delete(el);
|
|
157
|
+
}
|
|
158
|
+
if (enabled) {
|
|
159
|
+
const handler = (e) => handleEscapeKey(el, e);
|
|
160
|
+
escapeKeyHandlers.set(el, handler);
|
|
161
|
+
dialog.addEventListener('keydown', handler);
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
const handler = (e) => {
|
|
165
|
+
if (e.key === 'Escape')
|
|
166
|
+
e.preventDefault();
|
|
167
|
+
};
|
|
168
|
+
escapeKeyHandlers.set(el, handler);
|
|
169
|
+
dialog.addEventListener('keydown', handler);
|
|
170
|
+
}
|
|
171
171
|
}
|
|
172
172
|
function setupCloseButton(el, dialog, showButton) {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
173
|
+
const closeButton = dialog.querySelector('.close-button');
|
|
174
|
+
if (!closeButton)
|
|
175
|
+
return;
|
|
176
|
+
if (showButton) {
|
|
177
|
+
closeButton.style.display = '';
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
closeButton.style.display = 'none';
|
|
181
|
+
}
|
|
182
|
+
const existingHandler = closeButtonHandlers.get(el);
|
|
183
|
+
if (existingHandler) {
|
|
184
|
+
closeButton.removeEventListener('click', existingHandler);
|
|
185
|
+
closeButtonHandlers.delete(el);
|
|
186
|
+
}
|
|
187
|
+
if (showButton) {
|
|
188
|
+
const handler = (e) => handleCloseButtonClick(el, e);
|
|
189
|
+
closeButtonHandlers.set(el, handler);
|
|
190
|
+
closeButton.addEventListener('click', handler);
|
|
191
|
+
}
|
|
192
192
|
}
|
|
193
193
|
function setupCloseButtonHover(el, dialog) {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
194
|
+
const modalContent = dialog.querySelector('.modal-content');
|
|
195
|
+
if (!modalContent)
|
|
196
|
+
return;
|
|
197
|
+
const existingEnterHandler = hoverEnterHandlers.get(el);
|
|
198
|
+
const existingLeaveHandler = hoverLeaveHandlers.get(el);
|
|
199
|
+
if (existingEnterHandler) {
|
|
200
|
+
modalContent.removeEventListener('mouseenter', existingEnterHandler);
|
|
201
|
+
hoverEnterHandlers.delete(el);
|
|
202
|
+
}
|
|
203
|
+
if (existingLeaveHandler) {
|
|
204
|
+
modalContent.removeEventListener('mouseleave', existingLeaveHandler);
|
|
205
|
+
hoverLeaveHandlers.delete(el);
|
|
206
|
+
}
|
|
207
|
+
if (!isMobile()) {
|
|
208
|
+
const enterHandler = (e) => handleHoverEnter(el, e);
|
|
209
|
+
const leaveHandler = (e) => handleHoverLeave(el, e);
|
|
210
|
+
hoverEnterHandlers.set(el, enterHandler);
|
|
211
|
+
hoverLeaveHandlers.set(el, leaveHandler);
|
|
212
|
+
modalContent.addEventListener('mouseenter', enterHandler);
|
|
213
|
+
modalContent.addEventListener('mouseleave', leaveHandler);
|
|
214
|
+
}
|
|
215
215
|
}
|
|
216
216
|
function render(el) {
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
217
|
+
const shadowRoot = el.shadowRoot;
|
|
218
|
+
if (!shadowRoot)
|
|
219
|
+
return;
|
|
220
|
+
const attributes = getModalAttributes(el);
|
|
221
|
+
const dialog = ensureInternalDialog(shadowRoot);
|
|
222
|
+
const modalId = getModalId(el);
|
|
223
|
+
ensureStyles(shadowRoot, { css: modalStyles, id: 'ty-modal' });
|
|
224
|
+
dialog.className = 'ty-modal-dialog';
|
|
225
|
+
if (attributes.backdrop) {
|
|
226
|
+
dialog.setAttribute('data-backdrop', 'true');
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
dialog.removeAttribute('data-backdrop');
|
|
230
|
+
}
|
|
231
|
+
const label = el.getAttribute('label');
|
|
232
|
+
if (label) {
|
|
233
|
+
dialog.setAttribute('aria-label', label);
|
|
234
|
+
}
|
|
235
|
+
else {
|
|
236
|
+
dialog.removeAttribute('aria-label');
|
|
237
|
+
}
|
|
238
|
+
setupBackdropClick(el, dialog, attributes.closeOnOutsideClick);
|
|
239
|
+
setupEscapeKey(el, dialog, attributes.closeOnEscape);
|
|
240
|
+
dialog.oncancel = (event) => {
|
|
241
|
+
event.preventDefault();
|
|
242
|
+
if (getModalAttributes(el).closeOnEscape)
|
|
243
|
+
closeModal(el, 'escape');
|
|
244
|
+
};
|
|
245
|
+
setupCloseButton(el, dialog, attributes.closeOnOutsideClick);
|
|
246
|
+
setupCloseButtonHover(el, dialog);
|
|
247
|
+
if (attributes.open) {
|
|
248
|
+
if (!dialog.open) {
|
|
249
|
+
lockScroll(modalId);
|
|
250
|
+
if (attributes.backdrop) {
|
|
251
|
+
dialog.showModal();
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
dialog.show();
|
|
255
|
+
}
|
|
256
|
+
syncBackdropZoom();
|
|
257
|
+
dispatchModalEvent(el, 'open', {});
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
else {
|
|
261
|
+
if (dialog.open) {
|
|
262
|
+
unlockScroll(modalId);
|
|
263
|
+
dialog.close();
|
|
264
|
+
syncBackdropZoom();
|
|
265
|
+
const reason = pendingCloseReasons.get(el) ?? 'programmatic';
|
|
266
|
+
pendingCloseReasons.delete(el);
|
|
267
|
+
dispatchModalEvent(el, 'close', { reason });
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
dialog.onclose = (event) => {
|
|
271
|
+
if (event.target !== dialog)
|
|
272
|
+
return;
|
|
273
|
+
unlockScroll(modalId);
|
|
274
|
+
if (el.hasAttribute('open')) {
|
|
275
|
+
el.removeAttribute('open');
|
|
276
|
+
dispatchModalEvent(el, 'close', {
|
|
277
|
+
reason: 'native',
|
|
278
|
+
returnValue: dialog.returnValue || undefined
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
syncBackdropZoom();
|
|
282
|
+
};
|
|
283
283
|
}
|
|
284
284
|
function syncBackdropZoom() {
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
285
|
+
const anyOpen = Array.from(document.querySelectorAll('ty-modal[open][backdrop-zoom], ty-dialog[open][backdrop-zoom]')).some((m) => {
|
|
286
|
+
const v = m.getAttribute('backdrop-zoom').toLowerCase().trim();
|
|
287
|
+
return v !== 'false' && v !== '0';
|
|
288
|
+
});
|
|
289
|
+
document.documentElement.classList.toggle('ty-modal-zoom', anyOpen);
|
|
290
290
|
}
|
|
291
291
|
function cleanup(el) {
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
292
|
+
const modalId = modalIds.get(el);
|
|
293
|
+
const shadowRoot = el.shadowRoot;
|
|
294
|
+
const dialog = shadowRoot ? getModalDialog(shadowRoot) : null;
|
|
295
|
+
if (modalId) {
|
|
296
|
+
unlockScroll(modalId);
|
|
297
|
+
modalIds.delete(el);
|
|
298
|
+
}
|
|
299
|
+
syncBackdropZoom();
|
|
300
|
+
if (!dialog)
|
|
301
|
+
return;
|
|
302
|
+
const backdropHandler = backdropClickHandlers.get(el);
|
|
303
|
+
if (backdropHandler) {
|
|
304
|
+
dialog.removeEventListener('click', backdropHandler);
|
|
305
|
+
backdropClickHandlers.delete(el);
|
|
306
|
+
}
|
|
307
|
+
const escapeHandler = escapeKeyHandlers.get(el);
|
|
308
|
+
if (escapeHandler) {
|
|
309
|
+
dialog.removeEventListener('keydown', escapeHandler);
|
|
310
|
+
escapeKeyHandlers.delete(el);
|
|
311
|
+
}
|
|
312
|
+
const closeButton = dialog.querySelector('.close-button');
|
|
313
|
+
if (closeButton) {
|
|
314
|
+
const closeHandler = closeButtonHandlers.get(el);
|
|
315
|
+
if (closeHandler) {
|
|
316
|
+
closeButton.removeEventListener('click', closeHandler);
|
|
317
|
+
closeButtonHandlers.delete(el);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
const modalContent = dialog.querySelector('.modal-content');
|
|
321
|
+
if (modalContent) {
|
|
322
|
+
const enterHandler = hoverEnterHandlers.get(el);
|
|
323
|
+
const leaveHandler = hoverLeaveHandlers.get(el);
|
|
324
|
+
if (enterHandler) {
|
|
325
|
+
modalContent.removeEventListener('mouseenter', enterHandler);
|
|
326
|
+
hoverEnterHandlers.delete(el);
|
|
327
|
+
}
|
|
328
|
+
if (leaveHandler) {
|
|
329
|
+
modalContent.removeEventListener('mouseleave', leaveHandler);
|
|
330
|
+
hoverLeaveHandlers.delete(el);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
333
|
}
|
|
334
334
|
export class TyModal extends HTMLElement {
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
335
|
+
static get observedAttributes() {
|
|
336
|
+
return ['open', 'backdrop', 'close-on-outside-click', 'close-on-escape', 'prevent-outside-click', 'prevent-escape', 'label'];
|
|
337
|
+
}
|
|
338
|
+
get open() { return parseBoolAttr(this, 'open'); }
|
|
339
|
+
set open(v) { v ? this.setAttribute('open', 'true') : this.removeAttribute('open'); }
|
|
340
|
+
get backdrop() { return getModalAttributes(this).backdrop; }
|
|
341
|
+
set backdrop(v) { this.setAttribute('backdrop', String(!!v)); }
|
|
342
|
+
get closeOnOutsideClick() { return getModalAttributes(this).closeOnOutsideClick; }
|
|
343
|
+
set closeOnOutsideClick(v) { this.setAttribute('close-on-outside-click', String(!!v)); }
|
|
344
|
+
get closeOnEscape() { return getModalAttributes(this).closeOnEscape; }
|
|
345
|
+
set closeOnEscape(v) { this.setAttribute('close-on-escape', String(!!v)); }
|
|
346
|
+
get preventOutsideClick() { return parseBoolAttr(this, 'prevent-outside-click'); }
|
|
347
|
+
set preventOutsideClick(v) {
|
|
348
|
+
v ? this.setAttribute('prevent-outside-click', '') : this.removeAttribute('prevent-outside-click');
|
|
349
|
+
}
|
|
350
|
+
get preventEscape() { return parseBoolAttr(this, 'prevent-escape'); }
|
|
351
|
+
set preventEscape(v) {
|
|
352
|
+
v ? this.setAttribute('prevent-escape', '') : this.removeAttribute('prevent-escape');
|
|
353
|
+
}
|
|
354
|
+
constructor() {
|
|
355
|
+
super();
|
|
356
|
+
this.attachShadow({ mode: 'open' });
|
|
357
|
+
}
|
|
358
|
+
connectedCallback() {
|
|
359
|
+
render(this);
|
|
360
|
+
this.show = () => openModal(this);
|
|
361
|
+
this.hide = (opts) => closeModal(this, 'programmatic', opts);
|
|
362
|
+
}
|
|
363
|
+
disconnectedCallback() {
|
|
364
|
+
cleanup(this);
|
|
365
|
+
}
|
|
366
|
+
attributeChangedCallback(_name, _oldValue, _newValue) {
|
|
367
|
+
if (!this.isConnected)
|
|
368
|
+
return;
|
|
369
|
+
render(this);
|
|
370
|
+
}
|
|
371
371
|
}
|
|
372
372
|
if (!customElements.get('ty-modal')) {
|
|
373
|
-
|
|
373
|
+
customElements.define('ty-modal', TyModal);
|
|
374
374
|
}
|
|
375
375
|
if (!customElements.get('ty-dialog')) {
|
|
376
|
-
|
|
377
|
-
|
|
376
|
+
customElements.define('ty-dialog', class TyDialog extends TyModal {
|
|
377
|
+
});
|
|
378
378
|
}
|