@oscarpalmer/oui 0.18.0 → 0.19.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/dist/css/badge.css +10 -10
- package/dist/css/button.css +9 -9
- package/dist/css/color.css +99 -99
- package/dist/css/content.css +1 -1
- package/dist/css/flex.css +39 -39
- package/dist/css/form.css +29 -56
- package/dist/css/message.css +6 -6
- package/dist/css/reset.css +3 -2
- package/dist/css/table.css +4 -4
- package/dist/css/tooltip.css +18 -1
- package/dist/js/attributable.full.js +29 -41
- package/dist/js/floatable.full.js +322 -337
- package/dist/js/focus-trap/embedded.full.js +252 -195
- package/dist/js/focus-trap/standalone.full.js +283 -238
- package/dist/js/index.js +3 -3
- package/dist/js/oui.full.js +1170 -1193
- package/dist/js/popover.full.js +568 -630
- package/dist/js/popover.js +1 -1
- package/dist/js/splitter.full.js +533 -369
- package/dist/js/splitter.js +2 -2
- package/dist/js/tooltip.full.js +488 -554
- package/dist/js/tooltip.js +1 -1
- package/package.json +19 -19
- package/src/css/a11y.scss +1 -1
- package/src/css/badge.scss +23 -19
- package/src/css/button.scss +9 -9
- package/src/css/color.scss +99 -99
- package/src/css/content.scss +6 -8
- package/src/css/flex.scss +21 -20
- package/src/css/form.scss +37 -60
- package/src/css/message.scss +8 -12
- package/src/css/mixins.scss +11 -12
- package/src/css/popover.scss +2 -2
- package/src/css/reset.scss +14 -14
- package/src/css/splitter.scss +15 -13
- package/src/css/table.scss +11 -11
- package/src/css/tooltip.scss +25 -4
- package/src/js/attributable.ts +3 -10
- package/src/js/floatable.ts +7 -25
- package/src/js/focus-trap/embedded.ts +6 -24
- package/src/js/popover.ts +3 -3
- package/src/js/splitter.ts +9 -39
- package/src/js/tooltip.ts +5 -17
- package/dist/css/value.css +0 -1
|
@@ -1,72 +1,51 @@
|
|
|
1
1
|
function attributable(attribute, add, remove) {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
attributes: true,
|
|
23
|
-
childList: true,
|
|
24
|
-
subtree: true,
|
|
25
|
-
});
|
|
26
|
-
requestAnimationFrame(() => {
|
|
27
|
-
handleAdded(attribute, document.querySelectorAll(`[${attribute}]`), add);
|
|
28
|
-
});
|
|
2
|
+
new MutationObserver((entries) => {
|
|
3
|
+
const { length } = entries;
|
|
4
|
+
for (let index = 0; index < length; index += 1) {
|
|
5
|
+
const entry = entries[index];
|
|
6
|
+
if (entry.type === "attributes" && entry.target instanceof HTMLElement) if (entry.target.hasAttribute(attribute)) handleAdded(attribute, [entry.target], add);
|
|
7
|
+
else handleRemoved([entry.target], remove);
|
|
8
|
+
else if (entry.type === "childList") {
|
|
9
|
+
handleAdded(attribute, entry.addedNodes, add);
|
|
10
|
+
handleRemoved(entry.removedNodes, remove);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}).observe(document, {
|
|
14
|
+
attributeFilter: [attribute],
|
|
15
|
+
attributes: true,
|
|
16
|
+
childList: true,
|
|
17
|
+
subtree: true
|
|
18
|
+
});
|
|
19
|
+
requestAnimationFrame(() => {
|
|
20
|
+
handleAdded(attribute, document.querySelectorAll(`[${attribute}]`), add);
|
|
21
|
+
});
|
|
29
22
|
}
|
|
30
23
|
function handleAdded(attribute, nodes, add) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
38
|
-
}
|
|
24
|
+
const elements = [...nodes].filter((node) => node instanceof HTMLElement);
|
|
25
|
+
const { length } = elements;
|
|
26
|
+
for (let index = 0; index < length; index += 1) {
|
|
27
|
+
const element = elements[index];
|
|
28
|
+
if (element.hasAttribute(attribute)) add(element);
|
|
29
|
+
}
|
|
39
30
|
}
|
|
40
31
|
function handleRemoved(nodes, remove) {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
remove(elements[index]);
|
|
45
|
-
}
|
|
32
|
+
const elements = [...nodes].filter((node) => node instanceof HTMLElement);
|
|
33
|
+
const { length } = elements;
|
|
34
|
+
for (let index = 0; index < length; index += 1) remove(elements[index]);
|
|
46
35
|
}
|
|
47
|
-
|
|
48
36
|
function isNumber(value) {
|
|
49
37
|
return typeof value === "number" && !Number.isNaN(value);
|
|
50
38
|
}
|
|
51
|
-
|
|
52
39
|
function clamp(value, minimum, maximum, loop) {
|
|
53
40
|
if (![
|
|
54
41
|
value,
|
|
55
42
|
minimum,
|
|
56
43
|
maximum
|
|
57
44
|
].every(isNumber)) return NaN;
|
|
58
|
-
if (value < minimum) return maximum ;
|
|
59
|
-
return value > maximum ? minimum
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
function isEventTarget(value) {
|
|
63
|
-
return typeof value === "object" && value != null && typeof value.addEventListener === "function" && typeof value.removeEventListener === "function" && typeof value.dispatchEvent === "function";
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
function getBoolean(value, defaultValue) {
|
|
67
|
-
return typeof value === "boolean" ? value : defaultValue ?? false;
|
|
45
|
+
if (value < minimum) return loop === true ? maximum : minimum;
|
|
46
|
+
return value > maximum ? loop === true ? minimum : maximum : value;
|
|
68
47
|
}
|
|
69
|
-
|
|
48
|
+
function noop() {}
|
|
70
49
|
function calculate() {
|
|
71
50
|
return new Promise((resolve) => {
|
|
72
51
|
const values = [];
|
|
@@ -74,37 +53,122 @@ function calculate() {
|
|
|
74
53
|
function step(now) {
|
|
75
54
|
if (last != null) values.push(now - last);
|
|
76
55
|
last = now;
|
|
77
|
-
if (values.length >=
|
|
78
|
-
|
|
79
|
-
resolve(median);
|
|
80
|
-
} else requestAnimationFrame(step);
|
|
56
|
+
if (values.length >= TOTAL) resolve(values.sort().slice(TRIM_PART, -TRIM_PART).reduce((first, second) => first + second, 0) / (values.length - TRIM_TOTAL));
|
|
57
|
+
else requestAnimationFrame(step);
|
|
81
58
|
}
|
|
82
59
|
requestAnimationFrame(step);
|
|
83
60
|
});
|
|
84
61
|
}
|
|
85
|
-
|
|
86
|
-
var
|
|
87
|
-
var
|
|
88
|
-
calculate()
|
|
89
|
-
|
|
90
|
-
|
|
62
|
+
var TOTAL = 10;
|
|
63
|
+
var TRIM_PART = 2;
|
|
64
|
+
var TRIM_TOTAL = 4;
|
|
65
|
+
await calculate();
|
|
66
|
+
function getBoolean(value, defaultValue) {
|
|
67
|
+
return typeof value === "boolean" ? value : defaultValue ?? false;
|
|
68
|
+
}
|
|
69
|
+
function isEventTarget(value) {
|
|
70
|
+
return typeof value === "object" && value != null && typeof value.addEventListener === "function" && typeof value.removeEventListener === "function" && typeof value.dispatchEvent === "function";
|
|
71
|
+
}
|
|
72
|
+
function addDelegatedHandler(doc, type, name, passive) {
|
|
73
|
+
if (DELEGATED.has(name)) return;
|
|
74
|
+
DELEGATED.add(name);
|
|
75
|
+
doc.addEventListener(type, passive ? HANDLER_PASSIVE : HANDLER_ACTIVE, { passive });
|
|
76
|
+
}
|
|
77
|
+
function addDelegatedListener(target, type, name, listener, passive) {
|
|
78
|
+
target[name] ??= /* @__PURE__ */ new Set();
|
|
79
|
+
target[name].add(listener);
|
|
80
|
+
addDelegatedHandler(document, type, name, passive);
|
|
81
|
+
return () => {
|
|
82
|
+
removeDelegatedListener(target, name, listener);
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
function delegatedEventHandler(event) {
|
|
86
|
+
const key = `${EVENT_PREFIX}${event.type}${this ? EVENT_SUFFIX_PASSIVE : EVENT_SUFFIX_ACTIVE}`;
|
|
87
|
+
const items = event.composedPath();
|
|
88
|
+
const { length } = items;
|
|
89
|
+
let target = items[0];
|
|
90
|
+
Object.defineProperties(event, {
|
|
91
|
+
currentTarget: {
|
|
92
|
+
configurable: true,
|
|
93
|
+
get() {
|
|
94
|
+
return target;
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
target: {
|
|
98
|
+
configurable: true,
|
|
99
|
+
value: target
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
for (let index = 0; index < length; index += 1) {
|
|
103
|
+
const item = items[index];
|
|
104
|
+
const listeners = item[key];
|
|
105
|
+
if (item.disabled || listeners == null) continue;
|
|
106
|
+
target = item;
|
|
107
|
+
for (const listener of listeners) {
|
|
108
|
+
listener.call(item, event);
|
|
109
|
+
if (event.cancelBubble) return;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
function getDelegatedName(target, type, options) {
|
|
114
|
+
if (isEventTarget(target) && EVENT_TYPES.has(type) && !options.capture && !options.once && options.signal == null) return `${EVENT_PREFIX}${type}${options.passive ? EVENT_SUFFIX_PASSIVE : EVENT_SUFFIX_ACTIVE}`;
|
|
115
|
+
}
|
|
116
|
+
function removeDelegatedListener(target, name, listener) {
|
|
117
|
+
const handlers = target[name];
|
|
118
|
+
if (handlers == null || !handlers.has(listener)) return false;
|
|
119
|
+
handlers.delete(listener);
|
|
120
|
+
if (handlers.size === 0) target[name] = void 0;
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
var DELEGATED = /* @__PURE__ */ new Set();
|
|
124
|
+
var EVENT_PREFIX = "@";
|
|
125
|
+
var EVENT_SUFFIX_ACTIVE = ":active";
|
|
126
|
+
var EVENT_SUFFIX_PASSIVE = ":passive";
|
|
127
|
+
var EVENT_TYPES = new Set([
|
|
128
|
+
"beforeinput",
|
|
129
|
+
"click",
|
|
130
|
+
"dblclick",
|
|
131
|
+
"contextmenu",
|
|
132
|
+
"focusin",
|
|
133
|
+
"focusout",
|
|
134
|
+
"input",
|
|
135
|
+
"keydown",
|
|
136
|
+
"keyup",
|
|
137
|
+
"mousedown",
|
|
138
|
+
"mousemove",
|
|
139
|
+
"mouseout",
|
|
140
|
+
"mouseover",
|
|
141
|
+
"mouseup",
|
|
142
|
+
"pointerdown",
|
|
143
|
+
"pointermove",
|
|
144
|
+
"pointerout",
|
|
145
|
+
"pointerover",
|
|
146
|
+
"pointerup",
|
|
147
|
+
"touchend",
|
|
148
|
+
"touchmove",
|
|
149
|
+
"touchstart"
|
|
150
|
+
]);
|
|
151
|
+
var HANDLER_ACTIVE = delegatedEventHandler.bind(false);
|
|
152
|
+
var HANDLER_PASSIVE = delegatedEventHandler.bind(true);
|
|
91
153
|
function createEventOptions(options) {
|
|
92
154
|
return {
|
|
93
155
|
capture: getBoolean(options?.capture),
|
|
94
156
|
once: getBoolean(options?.once),
|
|
95
157
|
passive: getBoolean(options?.passive, true),
|
|
96
|
-
signal: options?.signal
|
|
158
|
+
signal: options?.signal instanceof AbortSignal ? options.signal : void 0
|
|
97
159
|
};
|
|
98
160
|
}
|
|
99
161
|
function on(target, type, listener, options) {
|
|
100
162
|
if (!isEventTarget(target) || typeof type !== "string" || typeof listener !== "function") return noop;
|
|
101
163
|
const extended = createEventOptions(options);
|
|
164
|
+
const delegated = getDelegatedName(target, type, extended);
|
|
165
|
+
if (delegated != null) return addDelegatedListener(target, type, delegated, listener, extended.passive);
|
|
102
166
|
target.addEventListener(type, listener, extended);
|
|
167
|
+
if (extended.once) return noop;
|
|
103
168
|
return () => {
|
|
104
169
|
target.removeEventListener(type, listener, extended);
|
|
105
170
|
};
|
|
106
171
|
}
|
|
107
|
-
|
|
108
172
|
function findAncestor(origin, selector) {
|
|
109
173
|
if (!(origin instanceof Element) || selector == null) return null;
|
|
110
174
|
if (typeof selector === "string") {
|
|
@@ -120,26 +184,42 @@ function findAncestor(origin, selector) {
|
|
|
120
184
|
}
|
|
121
185
|
return parent;
|
|
122
186
|
}
|
|
123
|
-
|
|
124
187
|
function getFocusable(parent) {
|
|
125
|
-
return getValidElements(parent, FILTERS_FOCUSABLE);
|
|
188
|
+
return getValidElements(parent, FILTERS_FOCUSABLE, false);
|
|
126
189
|
}
|
|
127
190
|
function getItem(element, tabbable) {
|
|
128
191
|
return {
|
|
129
192
|
element,
|
|
130
|
-
tabIndex: TABINDEX_DEFAULT
|
|
193
|
+
tabIndex: tabbable ? getTabIndex(element) : TABINDEX_DEFAULT
|
|
131
194
|
};
|
|
132
195
|
}
|
|
196
|
+
function getTabIndex(element) {
|
|
197
|
+
const tabIndex = element?.tabIndex ?? TABINDEX_DEFAULT;
|
|
198
|
+
if (tabIndex < TABINDEX_BASE && (EXPRESSION_SPECIAL_TABINDEX.test(element.tagName) || isEditable(element)) && !hasTabIndex(element)) return TABINDEX_BASE;
|
|
199
|
+
return tabIndex;
|
|
200
|
+
}
|
|
133
201
|
function getValidElements(parent, filters, tabbable) {
|
|
134
202
|
if (!(parent instanceof Element)) return [];
|
|
135
203
|
const elements = [...parent.querySelectorAll(SELECTOR_FULL)];
|
|
136
204
|
const items = [];
|
|
137
205
|
let { length } = elements;
|
|
138
206
|
for (let index = 0; index < length; index += 1) {
|
|
139
|
-
const item = getItem(elements[index]);
|
|
207
|
+
const item = getItem(elements[index], tabbable);
|
|
140
208
|
if (!filters.some((filter) => filter(item))) items.push(item);
|
|
141
209
|
}
|
|
142
|
-
return items.map((item) => item.element);
|
|
210
|
+
if (!tabbable) return items.map((item) => item.element);
|
|
211
|
+
const indiced = [];
|
|
212
|
+
const zeroed = [];
|
|
213
|
+
length = items.length;
|
|
214
|
+
for (let index = 0; index < length; index += 1) {
|
|
215
|
+
const item = items[index];
|
|
216
|
+
if (item.tabIndex === TABINDEX_BASE) zeroed.push(item.element);
|
|
217
|
+
else indiced[item.tabIndex] = [...indiced[item.tabIndex] ?? [], item.element];
|
|
218
|
+
}
|
|
219
|
+
return [...indiced.flat(), ...zeroed];
|
|
220
|
+
}
|
|
221
|
+
function hasTabIndex(element) {
|
|
222
|
+
return !Number.isNaN(Number.parseInt(element.getAttribute(ATTRIBUTE_TABINDEX), 10));
|
|
143
223
|
}
|
|
144
224
|
function isDisabled(item) {
|
|
145
225
|
if (EXPRESSION_DISABLEABLE.test(item.element.tagName) && isDisabledFromFieldset(item.element)) return true;
|
|
@@ -161,6 +241,9 @@ function isDisabledFromFieldset(element) {
|
|
|
161
241
|
}
|
|
162
242
|
return false;
|
|
163
243
|
}
|
|
244
|
+
function isEditable(element) {
|
|
245
|
+
return EXPRESSION_TRUEISH.test(element.getAttribute(ATTRIBUTE_CONTENTEDITABLE));
|
|
246
|
+
}
|
|
164
247
|
function isHidden(item) {
|
|
165
248
|
if ((item.element.hidden ?? false) || item.element instanceof HTMLInputElement && item.element.type === STYLE_HIDDEN) return true;
|
|
166
249
|
if ((item.element.matches(SELECTOR_SUMMARY_FIRST) ? item.element.parentElement : item.element)?.matches(SELECTOR_DETAILS_CLOSED_CHILDREN) ?? false) return true;
|
|
@@ -171,13 +254,18 @@ function isHidden(item) {
|
|
|
171
254
|
}
|
|
172
255
|
function isInert(item) {
|
|
173
256
|
return (item.element.inert ?? false) || EXPRESSION_TRUEISH.test(item.element.getAttribute(ATTRIBUTE_INERT)) || item.element.parentElement != null && isInert({
|
|
174
|
-
element: item.element.parentElement
|
|
257
|
+
element: item.element.parentElement,
|
|
258
|
+
tabIndex: TABINDEX_DEFAULT
|
|
259
|
+
});
|
|
175
260
|
}
|
|
176
261
|
function isSummarised(item) {
|
|
177
262
|
return item.element instanceof HTMLDetailsElement && [...item.element.children].some((child) => EXPRESSION_SUMMARY.test(child.tagName));
|
|
178
263
|
}
|
|
264
|
+
var ATTRIBUTE_CONTENTEDITABLE = "contenteditable";
|
|
179
265
|
var ATTRIBUTE_INERT = "inert";
|
|
266
|
+
var ATTRIBUTE_TABINDEX = "tabindex";
|
|
180
267
|
var EXPRESSION_DISABLEABLE = /^(button|input|select|textarea)$/i;
|
|
268
|
+
var EXPRESSION_SPECIAL_TABINDEX = /^(audio|details|video)$/i;
|
|
181
269
|
var EXPRESSION_SUMMARY = /^summary$/i;
|
|
182
270
|
var EXPRESSION_TRUEISH = /^(|true)$/i;
|
|
183
271
|
var FILTERS_FOCUSABLE = [
|
|
@@ -186,6 +274,7 @@ var FILTERS_FOCUSABLE = [
|
|
|
186
274
|
isHidden,
|
|
187
275
|
isSummarised
|
|
188
276
|
];
|
|
277
|
+
[...FILTERS_FOCUSABLE];
|
|
189
278
|
var SELECTOR_DETAILS_CLOSED_CHILDREN = "details:not([open]) *";
|
|
190
279
|
var SELECTOR_FIELDSET_DISABLED = "fieldset[disabled] *";
|
|
191
280
|
var SELECTOR_SUMMARY_FIRST = "details > summary:first-of-type";
|
|
@@ -204,199 +293,155 @@ var SELECTOR_FULL = [
|
|
|
204
293
|
].map((selector) => `${selector}:not([inert])`).join(",");
|
|
205
294
|
var STYLE_HIDDEN = "hidden";
|
|
206
295
|
var STYLE_NONE = "none";
|
|
296
|
+
var TABINDEX_BASE = 0;
|
|
207
297
|
var TABINDEX_DEFAULT = -1;
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
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
|
-
enable() {
|
|
246
|
-
if (this.disabled) {
|
|
247
|
-
setDisabled(this, false);
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
focus(last) {
|
|
251
|
-
tabToTrap(this, getFocusable(this.element), this.element, last ? -1 : 0);
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
//
|
|
298
|
+
var FocusTrap = class {
|
|
299
|
+
disabled = false;
|
|
300
|
+
connected = true;
|
|
301
|
+
element;
|
|
302
|
+
embedded;
|
|
303
|
+
get contain() {
|
|
304
|
+
return this.element.hasAttribute(FOCUS_TRAP_CONTAIN);
|
|
305
|
+
}
|
|
306
|
+
get noescape() {
|
|
307
|
+
return this.element.hasAttribute(FOCUS_TRAP_NOESCAPE);
|
|
308
|
+
}
|
|
309
|
+
constructor(element, options) {
|
|
310
|
+
this.element = element;
|
|
311
|
+
this.embedded = options != null;
|
|
312
|
+
element.setAttribute("tabindex", "-1");
|
|
313
|
+
if (options != null) element.setAttribute(FOCUS_TRAP_SELECTOR, "");
|
|
314
|
+
if (options?.noescape) element.setAttribute(FOCUS_TRAP_NOESCAPE, "");
|
|
315
|
+
}
|
|
316
|
+
connect() {
|
|
317
|
+
setConnected(this, true);
|
|
318
|
+
}
|
|
319
|
+
destroy() {
|
|
320
|
+
this.element = void 0;
|
|
321
|
+
}
|
|
322
|
+
disable() {
|
|
323
|
+
if (!(this.disabled || this.noescape)) setDisabled(this, true);
|
|
324
|
+
}
|
|
325
|
+
disconnect() {
|
|
326
|
+
setConnected(this, false);
|
|
327
|
+
}
|
|
328
|
+
enable() {
|
|
329
|
+
if (this.disabled) setDisabled(this, false);
|
|
330
|
+
}
|
|
331
|
+
focus(last) {
|
|
332
|
+
tabToTrap(this, getFocusable(this.element), this.element, last ? -1 : 0);
|
|
333
|
+
}
|
|
334
|
+
};
|
|
255
335
|
function createFocusTrap(element, options) {
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
336
|
+
let focusTrap = FOCUSTRAPS_ALL.get(element);
|
|
337
|
+
if (focusTrap == null) {
|
|
338
|
+
focusTrap = new FocusTrap(element, options);
|
|
339
|
+
FOCUSTRAPS_ALL.set(element, focusTrap);
|
|
340
|
+
}
|
|
341
|
+
return focusTrap;
|
|
262
342
|
}
|
|
263
343
|
function onEscape(event) {
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
}
|
|
275
|
-
if (!focusTrap.disabled) {
|
|
276
|
-
break;
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
focusTrap?.disable();
|
|
344
|
+
let element = findAncestor(event.target, ATTRIBUTE_SELECTOR);
|
|
345
|
+
let focusTrap = FOCUSTRAPS_ALL.get(element);
|
|
346
|
+
if (element == null || focusTrap == null) return;
|
|
347
|
+
while (focusTrap.disabled) {
|
|
348
|
+
element = findAncestor(focusTrap.element.parentElement, ATTRIBUTE_SELECTOR);
|
|
349
|
+
focusTrap = FOCUSTRAPS_ALL.get(element);
|
|
350
|
+
if (element == null || focusTrap == null) return;
|
|
351
|
+
if (!focusTrap.disabled) break;
|
|
352
|
+
}
|
|
353
|
+
focusTrap?.disable();
|
|
280
354
|
}
|
|
281
355
|
function onFocusIn(event) {
|
|
282
|
-
|
|
283
|
-
lastTarget = focusTrap == null ? undefined : event.target;
|
|
356
|
+
lastTarget = FOCUSTRAPS_ALL.get(findAncestor(event.target, ATTRIBUTE_SELECTOR)) == null ? void 0 : event.target;
|
|
284
357
|
}
|
|
285
358
|
function onKeydown(event) {
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
}
|
|
359
|
+
switch (event.key) {
|
|
360
|
+
case "Escape":
|
|
361
|
+
onEscape(event);
|
|
362
|
+
break;
|
|
363
|
+
case "Tab":
|
|
364
|
+
onTab(event);
|
|
365
|
+
break;
|
|
366
|
+
default: return;
|
|
367
|
+
}
|
|
296
368
|
}
|
|
297
369
|
function onPointerdown(event) {
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
}
|
|
309
|
-
for (const focusTrap of FOCUSTRAPS_DISABLED) {
|
|
310
|
-
if (focusTrap.element !== nextFocusTrap) {
|
|
311
|
-
focusTrap.enable();
|
|
312
|
-
}
|
|
313
|
-
}
|
|
370
|
+
const lastFocusTrap = findAncestor(lastTarget, ATTRIBUTE_SELECTOR);
|
|
371
|
+
const nextFocusTrap = findAncestor(event.target, ATTRIBUTE_SELECTOR);
|
|
372
|
+
if (lastFocusTrap != null && nextFocusTrap !== lastFocusTrap) {
|
|
373
|
+
if (FOCUSTRAPS_ALL.get(lastFocusTrap)?.contain ?? false) {
|
|
374
|
+
event.preventDefault();
|
|
375
|
+
lastTarget?.focus();
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
if (FOCUSTRAPS_DISABLED.size === 0) return;
|
|
379
|
+
for (const focusTrap of FOCUSTRAPS_DISABLED) if (focusTrap.element !== nextFocusTrap) focusTrap.enable();
|
|
314
380
|
}
|
|
315
381
|
function onTab(event) {
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
const elements = getFocusable(element);
|
|
325
|
-
const index = elements.indexOf(event.target);
|
|
326
|
-
if (index === -1 || elements.length === 0) {
|
|
327
|
-
tabToTrap(focusTrap, elements, element);
|
|
328
|
-
}
|
|
329
|
-
else {
|
|
330
|
-
tabToElement(focusTrap, elements, index, event.shiftKey ? -1 : 1);
|
|
331
|
-
}
|
|
382
|
+
const element = findAncestor(event.target, ATTRIBUTE_SELECTOR);
|
|
383
|
+
const focusTrap = FOCUSTRAPS_ALL.get(element);
|
|
384
|
+
if (focusTrap == null) return;
|
|
385
|
+
if (!focusTrap.disabled) event.preventDefault();
|
|
386
|
+
const elements = getFocusable(element);
|
|
387
|
+
const index = elements.indexOf(event.target);
|
|
388
|
+
if (index === -1 || elements.length === 0) tabToTrap(focusTrap, elements, element);
|
|
389
|
+
else tabToElement(focusTrap, elements, index, event.shiftKey ? -1 : 1);
|
|
332
390
|
}
|
|
333
391
|
function setConnected(focusTrap, value) {
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
}
|
|
337
|
-
focusTrap.connected = value;
|
|
392
|
+
if (!focusTrap.embedded || focusTrap.connected === value) return;
|
|
393
|
+
focusTrap.connected = value;
|
|
338
394
|
}
|
|
339
395
|
function setDisabled(focusTrap, value) {
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
}
|
|
344
|
-
else {
|
|
345
|
-
FOCUSTRAPS_DISABLED.delete(focusTrap);
|
|
346
|
-
}
|
|
396
|
+
focusTrap.disabled = value;
|
|
397
|
+
if (value) FOCUSTRAPS_DISABLED.add(focusTrap);
|
|
398
|
+
else FOCUSTRAPS_DISABLED.delete(focusTrap);
|
|
347
399
|
}
|
|
348
400
|
function tabToElement(focusTrap, elements, index, modifier) {
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
elements[next].focus();
|
|
366
|
-
lastTarget = elements[next];
|
|
367
|
-
}
|
|
401
|
+
const { length } = elements;
|
|
402
|
+
const next = clamp(index + modifier, 0, length - 1, true);
|
|
403
|
+
if (focusTrap.disabled) {
|
|
404
|
+
if (index === length - 1 && next === 0 || index === 0 && next === length - 1) {
|
|
405
|
+
lastTarget = void 0;
|
|
406
|
+
focusTrap.enable();
|
|
407
|
+
}
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
const element = elements[next];
|
|
411
|
+
const elementFocusTrap = FOCUSTRAPS_ALL.get(element);
|
|
412
|
+
if (elementFocusTrap != null) elementFocusTrap.focus(modifier === -1);
|
|
413
|
+
else {
|
|
414
|
+
elements[next].focus();
|
|
415
|
+
lastTarget = elements[next];
|
|
416
|
+
}
|
|
368
417
|
}
|
|
369
418
|
function tabToTrap(focusTrap, elements, element, index) {
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
//
|
|
381
|
-
const FOCUS_TRAP_SELECTOR = 'oui-focus-trap';
|
|
419
|
+
if (focusTrap.disabled) {
|
|
420
|
+
lastTarget = void 0;
|
|
421
|
+
focusTrap.enable();
|
|
422
|
+
} else {
|
|
423
|
+
const next = elements.length === 0 ? element : elements.at(index ?? 0);
|
|
424
|
+
next.focus();
|
|
425
|
+
lastTarget = next;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
const FOCUS_TRAP_SELECTOR = "oui-focus-trap";
|
|
382
429
|
const ATTRIBUTE_SELECTOR = `[${FOCUS_TRAP_SELECTOR}]`;
|
|
383
430
|
const EVENT_OPTIONS = {
|
|
384
|
-
|
|
385
|
-
|
|
431
|
+
capture: true,
|
|
432
|
+
passive: false
|
|
386
433
|
};
|
|
387
434
|
const FOCUS_TRAP_CONTAIN = `${FOCUS_TRAP_SELECTOR}-contain`;
|
|
388
435
|
const FOCUS_TRAP_NOESCAPE = `${FOCUS_TRAP_SELECTOR}-noescape`;
|
|
389
|
-
const FOCUSTRAPS_ALL = new WeakMap();
|
|
390
|
-
const FOCUSTRAPS_DISABLED = new Set();
|
|
436
|
+
const FOCUSTRAPS_ALL = /* @__PURE__ */ new WeakMap();
|
|
437
|
+
const FOCUSTRAPS_DISABLED = /* @__PURE__ */ new Set();
|
|
391
438
|
let lastTarget;
|
|
392
|
-
|
|
393
|
-
on(document,
|
|
394
|
-
on(document,
|
|
395
|
-
on(document,
|
|
396
|
-
on(document, 'touchstart', onPointerdown, EVENT_OPTIONS);
|
|
397
|
-
|
|
439
|
+
on(document, "focusin", onFocusIn, EVENT_OPTIONS);
|
|
440
|
+
on(document, "keydown", onKeydown, EVENT_OPTIONS);
|
|
441
|
+
on(document, "mousedown", onPointerdown, EVENT_OPTIONS);
|
|
442
|
+
on(document, "touchstart", onPointerdown, EVENT_OPTIONS);
|
|
398
443
|
function removeFocusTraps(element) {
|
|
399
|
-
|
|
400
|
-
|
|
444
|
+
FOCUSTRAPS_ALL.get(element)?.destroy();
|
|
445
|
+
FOCUSTRAPS_ALL.delete(element);
|
|
401
446
|
}
|
|
402
447
|
attributable(FOCUS_TRAP_SELECTOR, createFocusTrap, removeFocusTraps);
|
package/dist/js/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { setDelay } from "./tooltip.js";
|
|
2
|
-
import { OuiSplitterElement } from "./splitter.js";
|
|
3
|
-
import { OuiPopoverElement } from "./popover.js";
|
|
4
1
|
import "./focus-trap/standalone.js";
|
|
2
|
+
import { OuiPopoverElement } from "./popover.js";
|
|
3
|
+
import { OuiSplitterElement } from "./splitter.js";
|
|
4
|
+
import { setDelay } from "./tooltip.js";
|
|
5
5
|
export { OuiPopoverElement, OuiSplitterElement, setDelay };
|