@oscarpalmer/oui 0.21.0 → 0.22.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/popover.css +9 -9
- package/dist/css/tooltip.css +20 -20
- package/dist/js/index.d.mts +46 -3
- package/dist/js/index.mjs +2536 -6
- package/dist/js/internal/draggable.d.mts +1 -1
- package/dist/js/internal/draggable.mjs +3 -0
- package/dist/js/internal/floatable.d.mts +2 -2
- package/dist/js/internal/floatable.mjs +38 -135
- package/dist/js/movable.d.mts +1 -1
- package/dist/js/popover.mjs +1 -1
- package/dist/js/sortable.d.mts +1 -1
- package/dist/js/tooltip.d.mts +1 -1
- package/dist/js/tooltip.mjs +95 -97
- package/package.json +13 -5
- package/src/css/mixins.scss +8 -12
- package/src/css/popover.scss +1 -1
- package/src/css/tooltip.scss +22 -22
- package/src/js/internal/floatable.ts +53 -270
- package/src/js/popover.ts +1 -1
- package/src/js/tooltip.ts +129 -131
- /package/dist/js/{movable-BEo2LbUI.d.mts → movable-BKFgoaOl.d.mts} +0 -0
package/dist/js/index.mjs
CHANGED
|
@@ -1,7 +1,2537 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
//#region src/js/internal/attributable.ts
|
|
2
|
+
function attributable(attribute, add, remove) {
|
|
3
|
+
new MutationObserver((entries) => {
|
|
4
|
+
const { length } = entries;
|
|
5
|
+
for (let index = 0; index < length; index += 1) {
|
|
6
|
+
const entry = entries[index];
|
|
7
|
+
if (entry.type === "attributes" && entry.target instanceof HTMLElement) if (entry.target.hasAttribute(attribute)) handleAdded(attribute, [entry.target], add);
|
|
8
|
+
else handleRemoved([entry.target], remove);
|
|
9
|
+
else if (entry.type === "childList") {
|
|
10
|
+
handleAdded(attribute, entry.addedNodes, add);
|
|
11
|
+
handleRemoved(entry.removedNodes, remove);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}).observe(document, {
|
|
15
|
+
attributeFilter: [attribute],
|
|
16
|
+
attributes: true,
|
|
17
|
+
childList: true,
|
|
18
|
+
subtree: true
|
|
19
|
+
});
|
|
20
|
+
requestAnimationFrame(() => {
|
|
21
|
+
handleAdded(attribute, document.querySelectorAll(`[${attribute}]`), add);
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
function handleAdded(attribute, nodes, add) {
|
|
25
|
+
const elements = [...nodes].filter((node) => node instanceof HTMLElement);
|
|
26
|
+
const { length } = elements;
|
|
27
|
+
for (let index = 0; index < length; index += 1) {
|
|
28
|
+
const element = elements[index];
|
|
29
|
+
if (element.hasAttribute(attribute)) add(element);
|
|
30
|
+
if (element.hasChildNodes()) handleAdded(attribute, element.childNodes, add);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function handleRemoved(nodes, remove) {
|
|
34
|
+
const elements = [...nodes].filter((node) => node instanceof HTMLElement);
|
|
35
|
+
const { length } = elements;
|
|
36
|
+
for (let index = 0; index < length; index += 1) {
|
|
37
|
+
const element = elements[index];
|
|
38
|
+
remove(element);
|
|
39
|
+
if (element.hasChildNodes()) handleRemoved(element.childNodes, remove);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
//#endregion
|
|
43
|
+
//#region node_modules/@oscarpalmer/atoms/dist/internal/is.mjs
|
|
44
|
+
/**
|
|
45
|
+
* Is the value a number?
|
|
46
|
+
*
|
|
47
|
+
* @param value Value to check
|
|
48
|
+
* @returns `true` if the value is a `number`, otherwise `false`
|
|
49
|
+
*/
|
|
50
|
+
function isNumber(value) {
|
|
51
|
+
return typeof value === "number" && !Number.isNaN(value);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Is the value a plain object?
|
|
55
|
+
*
|
|
56
|
+
* @param value Value to check
|
|
57
|
+
* @returns `true` if the value is a plain object, otherwise `false`
|
|
58
|
+
*/
|
|
59
|
+
function isPlainObject(value) {
|
|
60
|
+
if (value === null || typeof value !== "object") return false;
|
|
61
|
+
if (Symbol.toStringTag in value || Symbol.iterator in value) return false;
|
|
62
|
+
const prototype = Object.getPrototypeOf(value);
|
|
63
|
+
return prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null;
|
|
64
|
+
}
|
|
65
|
+
//#endregion
|
|
66
|
+
//#region node_modules/@oscarpalmer/atoms/dist/internal/number.mjs
|
|
67
|
+
/**
|
|
68
|
+
* Clamp a number between a minimum and maximum value
|
|
69
|
+
*
|
|
70
|
+
* @param value Value to clamp
|
|
71
|
+
* @param minimum Minimum value
|
|
72
|
+
* @param maximum Maximum value
|
|
73
|
+
* @param loop If `true`, the value will loop around when smaller than the minimum or larger than the maximum _(defaults to `false`)_
|
|
74
|
+
* @returns Clamped value
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```typescript
|
|
78
|
+
* clamp(10, 0, 5); // => 5
|
|
79
|
+
* clamp(10, 0, 5, true); // => 0
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
function clamp(value, minimum, maximum, loop) {
|
|
83
|
+
if (![
|
|
84
|
+
value,
|
|
85
|
+
minimum,
|
|
86
|
+
maximum
|
|
87
|
+
].every(isNumber)) return NaN;
|
|
88
|
+
if (value < minimum) return loop === true ? maximum : minimum;
|
|
89
|
+
return value > maximum ? loop === true ? minimum : maximum : value;
|
|
90
|
+
}
|
|
91
|
+
//#endregion
|
|
92
|
+
//#region node_modules/@oscarpalmer/toretto/dist/internal/is.mjs
|
|
93
|
+
/**
|
|
94
|
+
* Is the value an event position?
|
|
95
|
+
*
|
|
96
|
+
* @param value Value to check
|
|
97
|
+
* @returns `true` if it's an event position, otherwise `false`
|
|
98
|
+
*/
|
|
99
|
+
function isEventPosition(value) {
|
|
100
|
+
return typeof value === "object" && value != null && typeof value.x === "number" && typeof value.y === "number";
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Is the value an event target?
|
|
104
|
+
*
|
|
105
|
+
* @param value Value to check
|
|
106
|
+
* @returns `true` if it's an event target, otherwise `false`
|
|
107
|
+
*/
|
|
108
|
+
function isEventTarget(value) {
|
|
109
|
+
return typeof value === "object" && value != null && typeof value.addEventListener === "function" && typeof value.removeEventListener === "function" && typeof value.dispatchEvent === "function";
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Is the value an HTML or SVG element?
|
|
113
|
+
*
|
|
114
|
+
* @param value Value to check
|
|
115
|
+
* @returns `true` if it's an HTML or SVG element, otherwise `false`
|
|
116
|
+
*/
|
|
117
|
+
function isHTMLOrSVGElement(value) {
|
|
118
|
+
return value instanceof HTMLElement || value instanceof SVGElement;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Is the value an input element? _(`<input>`, `<select>`, or `<textarea>`)_
|
|
122
|
+
*
|
|
123
|
+
* @param value Value to check
|
|
124
|
+
* @returns `true` if it's an input element, otherwise `false`
|
|
125
|
+
*/
|
|
126
|
+
function isInputElement(value) {
|
|
127
|
+
return value instanceof HTMLInputElement || value instanceof HTMLSelectElement || value instanceof HTMLTextAreaElement;
|
|
128
|
+
}
|
|
129
|
+
//#endregion
|
|
130
|
+
//#region node_modules/@oscarpalmer/atoms/dist/internal/string.mjs
|
|
131
|
+
/**
|
|
132
|
+
* Get the string value from any value
|
|
133
|
+
*
|
|
134
|
+
* @param value Original value
|
|
135
|
+
* @returns String representation of the value
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* ```typescript
|
|
139
|
+
* getString(null) // => ''
|
|
140
|
+
* getString('foo') // => 'foo'
|
|
141
|
+
* getString(123) // => '123'
|
|
142
|
+
* getString(true) // => 'true'
|
|
143
|
+
* getString([1, 2, 3]) // => '1,2,3'
|
|
144
|
+
* getString({a: 1}) // => '{"a":1}'
|
|
145
|
+
* getString(() => 123) // => '123'
|
|
146
|
+
* ```
|
|
147
|
+
*/
|
|
148
|
+
function getString(value) {
|
|
149
|
+
if (typeof value === "string") return value;
|
|
150
|
+
if (value == null) return "";
|
|
151
|
+
if (typeof value === "function") return getString(value());
|
|
152
|
+
if (typeof value !== "object") return String(value);
|
|
153
|
+
const asString = String(value.valueOf?.() ?? value);
|
|
154
|
+
return asString.startsWith("[object ") ? JSON.stringify(value) : asString;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Join an array of values into a string _(while ignoring empty values)_
|
|
158
|
+
*
|
|
159
|
+
* _(`null`, `undefined`, and any values that become whitespace-only strings are considered empty)_
|
|
160
|
+
*
|
|
161
|
+
* @param array Array of values
|
|
162
|
+
* @param delimiter Delimiter to use between values
|
|
163
|
+
* @returns Joined string
|
|
164
|
+
*/
|
|
165
|
+
function join(array, delimiter) {
|
|
166
|
+
if (!Array.isArray(array)) return "";
|
|
167
|
+
const { length } = array;
|
|
168
|
+
if (length === 0) return "";
|
|
169
|
+
const values = [];
|
|
170
|
+
for (let index = 0; index < length; index += 1) {
|
|
171
|
+
const item = getString(array[index]);
|
|
172
|
+
if (item.length > 0) values.push(item);
|
|
173
|
+
}
|
|
174
|
+
return values.join(typeof delimiter === "string" ? delimiter : "");
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Split a string into words _(and other readable parts)_
|
|
178
|
+
*
|
|
179
|
+
* @param value Original string
|
|
180
|
+
* @returns Array of words found in the string
|
|
181
|
+
*/
|
|
182
|
+
function words(value) {
|
|
183
|
+
return typeof value === "string" ? value.match(EXPRESSION_WORDS) ?? [] : [];
|
|
184
|
+
}
|
|
185
|
+
const EXPRESSION_WORDS = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;
|
|
186
|
+
//#endregion
|
|
187
|
+
//#region node_modules/@oscarpalmer/atoms/dist/internal/sized.mjs
|
|
188
|
+
function getSizedMaximum(first, second) {
|
|
189
|
+
let actual;
|
|
190
|
+
if (typeof first === "number") actual = first;
|
|
191
|
+
else actual = typeof second === "number" ? second : MAXIMUM_DEFAULT;
|
|
192
|
+
return clamp(actual, 1, MAXIMUM_ABSOLUTE);
|
|
193
|
+
}
|
|
194
|
+
const MAXIMUM_ABSOLUTE = 16777216;
|
|
195
|
+
const MAXIMUM_DEFAULT = 1048576;
|
|
196
|
+
//#endregion
|
|
197
|
+
//#region node_modules/@oscarpalmer/atoms/dist/sized/map.mjs
|
|
198
|
+
/**
|
|
199
|
+
* A _Map_ with a maximum size
|
|
200
|
+
*
|
|
201
|
+
* Behavior is similar to a _LRU_ cache, where the least recently used entries are removed
|
|
202
|
+
*/
|
|
203
|
+
var SizedMap = class extends Map {
|
|
204
|
+
/**
|
|
205
|
+
* The maximum size of the _Map_
|
|
206
|
+
*/
|
|
207
|
+
#maximumSize;
|
|
208
|
+
/**
|
|
209
|
+
* Is the _Map_ full?
|
|
210
|
+
*/
|
|
211
|
+
get full() {
|
|
212
|
+
return super.size >= this.#maximumSize;
|
|
213
|
+
}
|
|
214
|
+
get maximum() {
|
|
215
|
+
return this.#maximumSize;
|
|
216
|
+
}
|
|
217
|
+
constructor(first, second) {
|
|
218
|
+
const maximum = getSizedMaximum(first, second);
|
|
219
|
+
super();
|
|
220
|
+
this.#maximumSize = maximum;
|
|
221
|
+
if (Array.isArray(first)) {
|
|
222
|
+
const { length } = first;
|
|
223
|
+
if (length <= maximum) for (let index = 0; index < length; index += 1) this.set(...first[index]);
|
|
224
|
+
else for (let index = 0; index < maximum; index += 1) this.set(...first[length - maximum + index]);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* @inheritdoc
|
|
229
|
+
*/
|
|
230
|
+
get(key) {
|
|
231
|
+
if (super.has(key)) {
|
|
232
|
+
const value = super.get(key);
|
|
233
|
+
this.#setValue(key, value, true);
|
|
234
|
+
return value;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* @inheritdoc
|
|
239
|
+
*/
|
|
240
|
+
set(key, value) {
|
|
241
|
+
return this.#setValue(key, value, super.has(key));
|
|
242
|
+
}
|
|
243
|
+
#setValue(key, value, has) {
|
|
244
|
+
if (has) super.delete(key);
|
|
245
|
+
else if (super.size >= this.#maximumSize) super.delete(super.keys().next().value);
|
|
246
|
+
super.set(key, value);
|
|
247
|
+
return this;
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
//#endregion
|
|
251
|
+
//#region node_modules/@oscarpalmer/atoms/dist/function/memoize.mjs
|
|
252
|
+
/**
|
|
253
|
+
* A _Memoized_ function instance, caching and retrieving results based on the its parameters _(or a custom cache key)_
|
|
254
|
+
*/
|
|
255
|
+
var Memoized = class {
|
|
256
|
+
#state;
|
|
257
|
+
/**
|
|
258
|
+
* Maximum cache size
|
|
259
|
+
*
|
|
260
|
+
* @returns Maximum cache size _(or `Number.NaN` if the instance has been destroyed)_
|
|
261
|
+
*/
|
|
262
|
+
get maximum() {
|
|
263
|
+
return this.#state.cache?.maximum ?? NaN;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Current cache size
|
|
267
|
+
*
|
|
268
|
+
* @returns Current cache size _(or `Number.NaN` if the instance has been destroyed)_
|
|
269
|
+
*/
|
|
270
|
+
get size() {
|
|
271
|
+
return this.#state.cache?.size ?? NaN;
|
|
272
|
+
}
|
|
273
|
+
constructor(callback, options) {
|
|
274
|
+
const cache = new SizedMap(options.cacheSize);
|
|
275
|
+
const getter = (...parameters) => {
|
|
276
|
+
const key = options.cacheKey?.(...parameters) ?? (parameters.length === 1 ? parameters[0] : join(parameters.map(getString), SEPARATOR));
|
|
277
|
+
if (cache.has(key)) return cache.get(key);
|
|
278
|
+
const value = callback(...parameters);
|
|
279
|
+
cache.set(key, value);
|
|
280
|
+
return value;
|
|
281
|
+
};
|
|
282
|
+
this.#state = {
|
|
283
|
+
cache,
|
|
284
|
+
getter
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Clear the cache
|
|
289
|
+
*/
|
|
290
|
+
clear() {
|
|
291
|
+
this.#state.cache?.clear();
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Delete a result from the cache
|
|
295
|
+
*
|
|
296
|
+
* @param key Key to delete
|
|
297
|
+
* @returns `true` if the key existed and was removed, otherwise `false`
|
|
298
|
+
*/
|
|
299
|
+
delete(key) {
|
|
300
|
+
return this.#state.cache?.delete(key) ?? false;
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Destroy the instance
|
|
304
|
+
*
|
|
305
|
+
* _(When a Memoized instance is destroyed, its cache and callback are removed, and calls to `run` will throw an error)_
|
|
306
|
+
*/
|
|
307
|
+
destroy() {
|
|
308
|
+
this.#state.cache?.clear();
|
|
309
|
+
this.#state.cache = void 0;
|
|
310
|
+
this.#state.getter = void 0;
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Get a result from the cache
|
|
314
|
+
*
|
|
315
|
+
* @param key Key to get
|
|
316
|
+
* @returns Cached result or `undefined` if it does not exist
|
|
317
|
+
*/
|
|
318
|
+
get(key) {
|
|
319
|
+
return this.#state.cache?.get(key);
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Does the result exist?
|
|
323
|
+
*
|
|
324
|
+
* @param key Key to check
|
|
325
|
+
* @returns `true` if the result exists, otherwise `false`
|
|
326
|
+
*/
|
|
327
|
+
has(key) {
|
|
328
|
+
return this.#state.cache?.has(key) ?? false;
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Run the callback with the provided parameters
|
|
332
|
+
*
|
|
333
|
+
* @param parameters Parameters to pass to the callback
|
|
334
|
+
* @returns Cached or computed _(then cached)_ result
|
|
335
|
+
*/
|
|
336
|
+
run(...parameters) {
|
|
337
|
+
if (this.#state.cache == null || this.#state.getter == null) throw new Error(MEMOIZED_ERROR_DESTROYED);
|
|
338
|
+
return this.#state.getter(...parameters);
|
|
339
|
+
}
|
|
340
|
+
};
|
|
341
|
+
function getMemoizationOptions(input) {
|
|
342
|
+
const { cacheKey, cacheSize } = isPlainObject(input) ? input : {};
|
|
343
|
+
return {
|
|
344
|
+
cacheKey: typeof cacheKey === "function" ? cacheKey : void 0,
|
|
345
|
+
cacheSize: typeof cacheSize === "number" && cacheSize > 0 ? cacheSize : DEFAULT_CACHE_SIZE
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Memoize a function, caching and retrieving results based on the first parameter
|
|
350
|
+
*
|
|
351
|
+
* @param callback Callback to memoize
|
|
352
|
+
* @param options Memoization options
|
|
353
|
+
* @returns _Memoized_ instance
|
|
354
|
+
*/
|
|
355
|
+
function memoize(callback, options) {
|
|
356
|
+
if (typeof callback !== "function") throw new TypeError(MEMOIZED_ERROR_CALLBACK);
|
|
357
|
+
return new Memoized(callback, getMemoizationOptions(options));
|
|
358
|
+
}
|
|
359
|
+
const DEFAULT_CACHE_SIZE = 1024;
|
|
360
|
+
const MEMOIZED_ERROR_CALLBACK = "Memoized requires a callback function";
|
|
361
|
+
const MEMOIZED_ERROR_DESTROYED = "The Memoized instance has been destroyed";
|
|
362
|
+
const SEPARATOR = "_";
|
|
363
|
+
//#endregion
|
|
364
|
+
//#region node_modules/@oscarpalmer/atoms/dist/string/case.mjs
|
|
365
|
+
/**
|
|
366
|
+
* Convert a string to camel case _(thisIsCamelCase)_
|
|
367
|
+
*
|
|
368
|
+
* @param value String to convert
|
|
369
|
+
* @returns Camel-cased string
|
|
370
|
+
*/
|
|
371
|
+
function camelCase(value) {
|
|
372
|
+
return toCase(CASE_CAMEL, value, true, false);
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Capitalize the first letter of a string _(and lowercase the rest)_
|
|
376
|
+
*
|
|
377
|
+
* @param value String to capitalize
|
|
378
|
+
* @returns Capitalized string
|
|
379
|
+
*/
|
|
380
|
+
function capitalize(value) {
|
|
381
|
+
if (typeof value !== "string" || value.length === 0) return "";
|
|
382
|
+
memoizedCapitalize ??= memoize((v) => v.length === 1 ? v.toLocaleUpperCase() : `${v.charAt(0).toLocaleUpperCase()}${v.slice(1).toLocaleLowerCase()}`);
|
|
383
|
+
return memoizedCapitalize.run(value);
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Convert a string to kebab case _(this-is-kebab-case)_
|
|
387
|
+
*
|
|
388
|
+
* @param value String to convert
|
|
389
|
+
* @returns Kebab-cased string
|
|
390
|
+
*/
|
|
391
|
+
function kebabCase(value) {
|
|
392
|
+
return toCase(CASE_KEBAB, value, false, false);
|
|
393
|
+
}
|
|
394
|
+
function toCase(type, value, capitalizeAny, capitalizeFirst) {
|
|
395
|
+
caseMemoizers[type] ??= memoize(toCaseCallback.bind({
|
|
396
|
+
type,
|
|
397
|
+
capitalizeAny,
|
|
398
|
+
capitalizeFirst
|
|
399
|
+
}));
|
|
400
|
+
return caseMemoizers[type].run(value);
|
|
401
|
+
}
|
|
402
|
+
function toCaseCallback(value) {
|
|
403
|
+
if (typeof value !== "string") return "";
|
|
404
|
+
if (value.length < 1) return value;
|
|
405
|
+
const { capitalizeAny, capitalizeFirst, type } = this;
|
|
406
|
+
const parts = words(value);
|
|
407
|
+
const partsLength = parts.length;
|
|
408
|
+
const cased = [];
|
|
409
|
+
for (let partIndex = 0; partIndex < partsLength; partIndex += 1) {
|
|
410
|
+
const items = parts[partIndex].replace(EXPRESSION_ACRONYM, (full, one, two, three) => three === S ? full : `${one}-${two}${three}`).replace(EXPRESSION_CAMEL_CASE, REPLACEMENT_CAMEL_CASE).split("-");
|
|
411
|
+
const itemsLength = items.length;
|
|
412
|
+
const partResult = [];
|
|
413
|
+
let itemCount = 0;
|
|
414
|
+
for (let itemIndex = 0; itemIndex < itemsLength; itemIndex += 1) {
|
|
415
|
+
const item = items[itemIndex];
|
|
416
|
+
if (item.length === 0) continue;
|
|
417
|
+
if (!capitalizeAny || itemCount === 0 && partIndex === 0 && !capitalizeFirst) partResult.push(item.toLocaleLowerCase());
|
|
418
|
+
else partResult.push(capitalize(item));
|
|
419
|
+
itemCount += 1;
|
|
420
|
+
}
|
|
421
|
+
cased.push(join(partResult, delimiters[type]));
|
|
422
|
+
}
|
|
423
|
+
return join(cased, delimiters[type]);
|
|
424
|
+
}
|
|
425
|
+
const CASE_CAMEL = "camel";
|
|
426
|
+
const CASE_KEBAB = "kebab";
|
|
427
|
+
const CASE_PASCAL = "pascal";
|
|
428
|
+
const CASE_SNAKE = "snake";
|
|
429
|
+
const DELIMTER_EMPTY = "";
|
|
430
|
+
const DELIMITER_HYPHEN = "-";
|
|
431
|
+
const DELIMITER_UNDERSCORE = "_";
|
|
432
|
+
const EXPRESSION_CAMEL_CASE = /(\p{Ll})(\p{Lu})/gu;
|
|
433
|
+
const EXPRESSION_ACRONYM = /(\p{Lu}*)(\p{Lu})(\p{Ll}+)/gu;
|
|
434
|
+
const REPLACEMENT_CAMEL_CASE = "$1-$2";
|
|
435
|
+
const S = "s";
|
|
436
|
+
const caseMemoizers = {};
|
|
437
|
+
const delimiters = {
|
|
438
|
+
[CASE_CAMEL]: DELIMTER_EMPTY,
|
|
439
|
+
[CASE_KEBAB]: DELIMITER_HYPHEN,
|
|
440
|
+
[CASE_PASCAL]: DELIMTER_EMPTY,
|
|
441
|
+
[CASE_SNAKE]: DELIMITER_UNDERSCORE
|
|
442
|
+
};
|
|
443
|
+
let memoizedCapitalize;
|
|
444
|
+
//#endregion
|
|
445
|
+
//#region node_modules/@oscarpalmer/toretto/dist/internal/get-value.mjs
|
|
446
|
+
function getBoolean(value, defaultValue) {
|
|
447
|
+
return typeof value === "boolean" ? value : defaultValue ?? false;
|
|
448
|
+
}
|
|
449
|
+
function getStyleValue(element, property, computed) {
|
|
450
|
+
if (property.startsWith(CSS_VARIABLE_PREFIX$1)) return element.style.getPropertyValue(property);
|
|
451
|
+
const name = camelCase(property);
|
|
452
|
+
return computed ? getComputedStyle(element)[name] : element.style[name];
|
|
453
|
+
}
|
|
454
|
+
const CSS_VARIABLE_PREFIX$1 = "--";
|
|
455
|
+
//#endregion
|
|
456
|
+
//#region node_modules/@oscarpalmer/toretto/dist/event/delegation.mjs
|
|
457
|
+
function addDelegatedHandler(doc, type, name, passive) {
|
|
458
|
+
if (DELEGATED.has(name)) return;
|
|
459
|
+
DELEGATED.add(name);
|
|
460
|
+
doc.addEventListener(type, passive ? HANDLER_PASSIVE : HANDLER_ACTIVE, { passive });
|
|
461
|
+
}
|
|
462
|
+
function addDelegatedListener(target, type, name, listener, passive) {
|
|
463
|
+
target[name] ??= /* @__PURE__ */ new Set();
|
|
464
|
+
target[name].add(listener);
|
|
465
|
+
addDelegatedHandler(document, type, name, passive);
|
|
466
|
+
return () => {
|
|
467
|
+
removeDelegatedListener(target, name, listener);
|
|
468
|
+
};
|
|
469
|
+
}
|
|
470
|
+
function delegatedEventHandler(event) {
|
|
471
|
+
const key = `${EVENT_PREFIX}${event.type}${this ? EVENT_SUFFIX_PASSIVE : EVENT_SUFFIX_ACTIVE}`;
|
|
472
|
+
const items = event.composedPath();
|
|
473
|
+
const { length } = items;
|
|
474
|
+
let cancelled = false;
|
|
475
|
+
let target = items[0];
|
|
476
|
+
const originalStopPropagation = event.stopPropagation;
|
|
477
|
+
event.stopPropagation = function() {
|
|
478
|
+
cancelled = true;
|
|
479
|
+
originalStopPropagation.call(event);
|
|
480
|
+
};
|
|
481
|
+
event.stopImmediatePropagation = event.stopPropagation.bind(event);
|
|
482
|
+
Object.defineProperties(event, {
|
|
483
|
+
currentTarget: {
|
|
484
|
+
configurable: true,
|
|
485
|
+
get() {
|
|
486
|
+
return target;
|
|
487
|
+
}
|
|
488
|
+
},
|
|
489
|
+
target: {
|
|
490
|
+
configurable: true,
|
|
491
|
+
value: target
|
|
492
|
+
}
|
|
493
|
+
});
|
|
494
|
+
for (let index = 0; index < length; index += 1) {
|
|
495
|
+
const item = items[index];
|
|
496
|
+
const listeners = item[key];
|
|
497
|
+
if (item.disabled || listeners == null) continue;
|
|
498
|
+
target = item;
|
|
499
|
+
for (const listener of listeners) {
|
|
500
|
+
listener.call(item, event);
|
|
501
|
+
if (cancelled) return;
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
function getDelegatedName(target, type, options) {
|
|
506
|
+
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}`;
|
|
507
|
+
}
|
|
508
|
+
function removeDelegatedListener(target, name, listener) {
|
|
509
|
+
const handlers = target[name];
|
|
510
|
+
if (handlers == null || !handlers.has(listener)) return false;
|
|
511
|
+
handlers.delete(listener);
|
|
512
|
+
if (handlers.size === 0) target[name] = void 0;
|
|
513
|
+
return true;
|
|
514
|
+
}
|
|
515
|
+
const DELEGATED = /* @__PURE__ */ new Set();
|
|
516
|
+
const EVENT_PREFIX = "@";
|
|
517
|
+
const EVENT_SUFFIX_ACTIVE = ":active";
|
|
518
|
+
const EVENT_SUFFIX_PASSIVE = ":passive";
|
|
519
|
+
const EVENT_TYPES = new Set([
|
|
520
|
+
"beforeinput",
|
|
521
|
+
"click",
|
|
522
|
+
"dblclick",
|
|
523
|
+
"contextmenu",
|
|
524
|
+
"focusin",
|
|
525
|
+
"focusout",
|
|
526
|
+
"input",
|
|
527
|
+
"keydown",
|
|
528
|
+
"keyup",
|
|
529
|
+
"mousedown",
|
|
530
|
+
"mousemove",
|
|
531
|
+
"mouseout",
|
|
532
|
+
"mouseover",
|
|
533
|
+
"mouseup",
|
|
534
|
+
"pointerdown",
|
|
535
|
+
"pointermove",
|
|
536
|
+
"pointerout",
|
|
537
|
+
"pointerover",
|
|
538
|
+
"pointerup",
|
|
539
|
+
"touchend",
|
|
540
|
+
"touchmove",
|
|
541
|
+
"touchstart"
|
|
542
|
+
]);
|
|
543
|
+
const HANDLER_ACTIVE = delegatedEventHandler.bind(false);
|
|
544
|
+
const HANDLER_PASSIVE = delegatedEventHandler.bind(true);
|
|
545
|
+
//#endregion
|
|
546
|
+
//#region node_modules/@oscarpalmer/atoms/dist/is.mjs
|
|
547
|
+
/**
|
|
548
|
+
* Is the value `undefined`, `null`, or stringified as a whitespace-only string?
|
|
549
|
+
*
|
|
550
|
+
* @param value Value to check
|
|
551
|
+
* @returns `true` if the value is nullable or matches a whitespace-only string, otherwise `false`
|
|
552
|
+
*/
|
|
553
|
+
function isNullableOrWhitespace(value) {
|
|
554
|
+
return value == null || EXPRESSION_WHITESPACE$1.test(getString(value));
|
|
555
|
+
}
|
|
556
|
+
const EXPRESSION_WHITESPACE$1 = /^\s*$/;
|
|
557
|
+
//#endregion
|
|
558
|
+
//#region node_modules/@oscarpalmer/atoms/dist/internal/function/misc.mjs
|
|
559
|
+
/**
|
|
560
|
+
* A function that does nothing, which can be useful, I guess…
|
|
561
|
+
*/
|
|
562
|
+
function noop() {}
|
|
563
|
+
//#endregion
|
|
564
|
+
//#region node_modules/@oscarpalmer/toretto/dist/event/index.mjs
|
|
565
|
+
function createEventOptions(options) {
|
|
566
|
+
return {
|
|
567
|
+
capture: getBoolean(options?.capture),
|
|
568
|
+
once: getBoolean(options?.once),
|
|
569
|
+
passive: getBoolean(options?.passive, true),
|
|
570
|
+
signal: options?.signal instanceof AbortSignal ? options.signal : void 0
|
|
571
|
+
};
|
|
572
|
+
}
|
|
573
|
+
/**
|
|
574
|
+
* Get the X- and Y-coordinates from a pointer event
|
|
575
|
+
*
|
|
576
|
+
* @param event Pointer event
|
|
577
|
+
* @returns X- and Y-coordinates
|
|
578
|
+
*/
|
|
579
|
+
function getPosition(event) {
|
|
580
|
+
let x;
|
|
581
|
+
let y;
|
|
582
|
+
if (event instanceof MouseEvent) {
|
|
583
|
+
x = event.clientX;
|
|
584
|
+
y = event.clientY;
|
|
585
|
+
} else if (event instanceof TouchEvent) {
|
|
586
|
+
x = event.touches[0]?.clientX;
|
|
587
|
+
y = event.touches[0]?.clientY;
|
|
588
|
+
}
|
|
589
|
+
return typeof x === "number" && typeof y === "number" ? {
|
|
590
|
+
x,
|
|
591
|
+
y
|
|
592
|
+
} : void 0;
|
|
593
|
+
}
|
|
594
|
+
function on(target, type, listener, options) {
|
|
595
|
+
if (!isEventTarget(target) || typeof type !== "string" || typeof listener !== "function") return noop;
|
|
596
|
+
const extended = createEventOptions(options);
|
|
597
|
+
const delegated = getDelegatedName(target, type, extended);
|
|
598
|
+
if (delegated != null) return addDelegatedListener(target, type, delegated, listener, extended.passive);
|
|
599
|
+
target.addEventListener(type, listener, extended);
|
|
600
|
+
if (extended.once) return noop;
|
|
601
|
+
return () => {
|
|
602
|
+
target.removeEventListener(type, listener, extended);
|
|
603
|
+
};
|
|
604
|
+
}
|
|
605
|
+
//#endregion
|
|
606
|
+
//#region node_modules/@oscarpalmer/toretto/dist/find/relative.mjs
|
|
607
|
+
function findAncestor(origin, selector) {
|
|
608
|
+
const element = getElement(origin);
|
|
609
|
+
if (element == null || selector == null) return null;
|
|
610
|
+
if (typeof selector === "string") {
|
|
611
|
+
if (Element.prototype.matches.call(element, selector)) return element;
|
|
612
|
+
return Element.prototype.closest.call(element, selector);
|
|
613
|
+
}
|
|
614
|
+
if (typeof selector !== "function") return null;
|
|
615
|
+
if (selector(element)) return element;
|
|
616
|
+
let parent = element.parentElement;
|
|
617
|
+
while (parent != null && !selector(parent)) {
|
|
618
|
+
if (parent === document.body) return null;
|
|
619
|
+
parent = parent.parentElement;
|
|
620
|
+
}
|
|
621
|
+
return parent;
|
|
622
|
+
}
|
|
623
|
+
function getElement(origin) {
|
|
624
|
+
if (origin instanceof Element) return origin;
|
|
625
|
+
return origin instanceof Event && origin.target instanceof Element ? origin.target : void 0;
|
|
626
|
+
}
|
|
627
|
+
//#endregion
|
|
628
|
+
//#region node_modules/@oscarpalmer/toretto/dist/find/index.mjs
|
|
629
|
+
/**
|
|
630
|
+
* Get elements from an event position
|
|
631
|
+
*
|
|
632
|
+
* @param position Event position
|
|
633
|
+
* @returns Elements at the event position
|
|
634
|
+
*/
|
|
635
|
+
function getElementFromPosition(position) {
|
|
636
|
+
if (!isEventPosition(position) || typeof document.elementFromPoint !== "function") return [];
|
|
637
|
+
const { x, y } = position;
|
|
638
|
+
const elements = [];
|
|
639
|
+
const events = [];
|
|
640
|
+
let current;
|
|
641
|
+
while (true) {
|
|
642
|
+
current = document.elementFromPoint(x, y);
|
|
643
|
+
if (current == null || elements.indexOf(current) !== -1) break;
|
|
644
|
+
if (!(current instanceof HTMLElement)) continue;
|
|
645
|
+
elements.push(current);
|
|
646
|
+
events.push({
|
|
647
|
+
value: current.style.getPropertyValue(STYLE_POINTER_EVENTS),
|
|
648
|
+
priority: current.style.getPropertyPriority(STYLE_POINTER_EVENTS)
|
|
649
|
+
});
|
|
650
|
+
current.style.setProperty(STYLE_POINTER_EVENTS, STYLE_NONE$1, STYLE_IMPORTANT);
|
|
651
|
+
}
|
|
652
|
+
const { length } = elements;
|
|
653
|
+
for (let index = 0; index < length; index += 1) {
|
|
654
|
+
const element = elements[index];
|
|
655
|
+
const event = events[index];
|
|
656
|
+
if (element instanceof HTMLElement) element.style.setProperty(STYLE_POINTER_EVENTS, event.value ?? "", event.priority);
|
|
657
|
+
}
|
|
658
|
+
return elements;
|
|
659
|
+
}
|
|
660
|
+
const STYLE_IMPORTANT = "important";
|
|
661
|
+
const STYLE_NONE$1 = "none";
|
|
662
|
+
const STYLE_POINTER_EVENTS = "pointer-events";
|
|
663
|
+
//#endregion
|
|
664
|
+
//#region node_modules/@oscarpalmer/toretto/dist/focusable.mjs
|
|
665
|
+
/**
|
|
666
|
+
* Get a list of focusable elements within a parent element
|
|
667
|
+
*
|
|
668
|
+
* @param parent Parent element
|
|
669
|
+
* @returns Focusable elements
|
|
670
|
+
*/
|
|
671
|
+
function getFocusable(parent) {
|
|
672
|
+
return getValidElements(parent, FILTERS_FOCUSABLE, false);
|
|
673
|
+
}
|
|
674
|
+
function getItem(element, tabbable) {
|
|
675
|
+
return {
|
|
676
|
+
element,
|
|
677
|
+
tabIndex: tabbable ? getTabIndex(element) : TABINDEX_DEFAULT
|
|
678
|
+
};
|
|
679
|
+
}
|
|
680
|
+
function getTabIndex(element) {
|
|
681
|
+
const tabIndex = element?.tabIndex ?? TABINDEX_DEFAULT;
|
|
682
|
+
if (tabIndex < TABINDEX_BASE && (EXPRESSION_SPECIAL_TABINDEX.test(element.tagName) || isEditable(element)) && !hasTabIndex(element)) return TABINDEX_BASE;
|
|
683
|
+
return tabIndex;
|
|
684
|
+
}
|
|
685
|
+
function getValidElements(parent, filters, tabbable) {
|
|
686
|
+
if (!(parent instanceof Element)) return [];
|
|
687
|
+
const elements = [...parent.querySelectorAll(SELECTOR_FULL)];
|
|
688
|
+
const items = [];
|
|
689
|
+
let { length } = elements;
|
|
690
|
+
for (let index = 0; index < length; index += 1) {
|
|
691
|
+
const item = getItem(elements[index], tabbable);
|
|
692
|
+
if (!filters.some((filter) => filter(item))) items.push(item);
|
|
693
|
+
}
|
|
694
|
+
if (!tabbable) return items.map((item) => item.element);
|
|
695
|
+
const indiced = [];
|
|
696
|
+
const zeroed = [];
|
|
697
|
+
length = items.length;
|
|
698
|
+
for (let index = 0; index < length; index += 1) {
|
|
699
|
+
const item = items[index];
|
|
700
|
+
if (item.tabIndex === TABINDEX_BASE) zeroed.push(item.element);
|
|
701
|
+
else indiced[item.tabIndex] = [...indiced[item.tabIndex] ?? [], item.element];
|
|
702
|
+
}
|
|
703
|
+
return [...indiced.flat(), ...zeroed];
|
|
704
|
+
}
|
|
705
|
+
function hasTabIndex(element) {
|
|
706
|
+
return !Number.isNaN(Number.parseInt(element.getAttribute(ATTRIBUTE_TABINDEX), 10));
|
|
707
|
+
}
|
|
708
|
+
function isDisabled$1(item) {
|
|
709
|
+
if (EXPRESSION_DISABLEABLE.test(item.element.tagName) && isDisabledFromFieldset(item.element)) return true;
|
|
710
|
+
return item.element.disabled ?? false;
|
|
711
|
+
}
|
|
712
|
+
function isDisabledFromFieldset(element) {
|
|
713
|
+
let parent = element.parentElement;
|
|
714
|
+
while (parent != null) {
|
|
715
|
+
if (parent instanceof HTMLFieldSetElement && parent.disabled) {
|
|
716
|
+
const children = Array.from(parent.children);
|
|
717
|
+
const { length } = children;
|
|
718
|
+
for (let index = 0; index < length; index += 1) {
|
|
719
|
+
const child = children[index];
|
|
720
|
+
if (child instanceof HTMLLegendElement) return parent.matches(SELECTOR_FIELDSET_DISABLED) || !child.contains(element);
|
|
721
|
+
}
|
|
722
|
+
return true;
|
|
723
|
+
}
|
|
724
|
+
parent = parent.parentElement;
|
|
725
|
+
}
|
|
726
|
+
return false;
|
|
727
|
+
}
|
|
728
|
+
function isEditable(element) {
|
|
729
|
+
return EXPRESSION_TRUEISH.test(element.getAttribute(ATTRIBUTE_CONTENTEDITABLE));
|
|
730
|
+
}
|
|
731
|
+
function isHidden(item) {
|
|
732
|
+
if ((item.element.hidden ?? false) || item.element instanceof HTMLInputElement && item.element.type === STYLE_HIDDEN) return true;
|
|
733
|
+
if ((item.element.matches(SELECTOR_SUMMARY_FIRST) ? item.element.parentElement : item.element)?.matches(SELECTOR_DETAILS_CLOSED_CHILDREN) ?? false) return true;
|
|
734
|
+
const style = getComputedStyle(item.element);
|
|
735
|
+
if (style.display === STYLE_NONE || style.visibility === STYLE_HIDDEN) return true;
|
|
736
|
+
const { height, width } = item.element.getBoundingClientRect();
|
|
737
|
+
return height === 0 && width === 0;
|
|
738
|
+
}
|
|
739
|
+
function isInert(item) {
|
|
740
|
+
return (item.element.inert ?? false) || EXPRESSION_TRUEISH.test(item.element.getAttribute(ATTRIBUTE_INERT)) || item.element.parentElement != null && isInert({
|
|
741
|
+
element: item.element.parentElement,
|
|
742
|
+
tabIndex: TABINDEX_DEFAULT
|
|
743
|
+
});
|
|
744
|
+
}
|
|
745
|
+
function isSummarised(item) {
|
|
746
|
+
return item.element instanceof HTMLDetailsElement && [...item.element.children].some((child) => EXPRESSION_SUMMARY.test(child.tagName));
|
|
747
|
+
}
|
|
748
|
+
const ATTRIBUTE_CONTENTEDITABLE = "contenteditable";
|
|
749
|
+
const ATTRIBUTE_INERT = "inert";
|
|
750
|
+
const ATTRIBUTE_TABINDEX = "tabindex";
|
|
751
|
+
const EXPRESSION_DISABLEABLE = /^(button|input|select|textarea)$/i;
|
|
752
|
+
const EXPRESSION_SPECIAL_TABINDEX = /^(audio|details|video)$/i;
|
|
753
|
+
const EXPRESSION_SUMMARY = /^summary$/i;
|
|
754
|
+
const EXPRESSION_TRUEISH = /^(|true)$/i;
|
|
755
|
+
const FILTERS_FOCUSABLE = [
|
|
756
|
+
isDisabled$1,
|
|
757
|
+
isInert,
|
|
758
|
+
isHidden,
|
|
759
|
+
isSummarised
|
|
760
|
+
];
|
|
761
|
+
[...FILTERS_FOCUSABLE];
|
|
762
|
+
const SELECTOR_DETAILS_CLOSED_CHILDREN = "details:not([open]) *";
|
|
763
|
+
const SELECTOR_FIELDSET_DISABLED = "fieldset[disabled] *";
|
|
764
|
+
const SELECTOR_SUMMARY_FIRST = "details > summary:first-of-type";
|
|
765
|
+
const SELECTOR_FULL = [
|
|
766
|
+
"[contenteditable]:not([contenteditable=\"false\"])",
|
|
767
|
+
"[tabindex]:not(slot)",
|
|
768
|
+
"a[href]",
|
|
769
|
+
"audio[controls]",
|
|
770
|
+
"button",
|
|
771
|
+
"details",
|
|
772
|
+
SELECTOR_SUMMARY_FIRST,
|
|
773
|
+
"input",
|
|
774
|
+
"select",
|
|
775
|
+
"textarea",
|
|
776
|
+
"video[controls]"
|
|
777
|
+
].map((selector) => `${selector}:not([inert])`).join(",");
|
|
778
|
+
const STYLE_HIDDEN = "hidden";
|
|
779
|
+
const STYLE_NONE = "none";
|
|
780
|
+
const TABINDEX_BASE = 0;
|
|
781
|
+
const TABINDEX_DEFAULT = -1;
|
|
782
|
+
//#endregion
|
|
783
|
+
//#region src/js/focus-trap/embedded.ts
|
|
784
|
+
var FocusTrap = class {
|
|
785
|
+
disabled = false;
|
|
786
|
+
connected = true;
|
|
787
|
+
element;
|
|
788
|
+
embedded;
|
|
789
|
+
get contain() {
|
|
790
|
+
return this.element.hasAttribute(FOCUS_TRAP_CONTAIN);
|
|
791
|
+
}
|
|
792
|
+
get noescape() {
|
|
793
|
+
return this.element.hasAttribute(FOCUS_TRAP_NOESCAPE);
|
|
794
|
+
}
|
|
795
|
+
constructor(element, options) {
|
|
796
|
+
this.element = element;
|
|
797
|
+
this.embedded = options != null;
|
|
798
|
+
element.setAttribute("tabindex", "-1");
|
|
799
|
+
if (options != null) element.setAttribute(FOCUS_TRAP_SELECTOR, "");
|
|
800
|
+
if (options?.noescape) element.setAttribute(FOCUS_TRAP_NOESCAPE, "");
|
|
801
|
+
}
|
|
802
|
+
connect() {
|
|
803
|
+
setConnected(this, true);
|
|
804
|
+
}
|
|
805
|
+
destroy() {
|
|
806
|
+
this.element = void 0;
|
|
807
|
+
}
|
|
808
|
+
disable() {
|
|
809
|
+
if (!(this.disabled || this.noescape)) setDisabled(this, true);
|
|
810
|
+
}
|
|
811
|
+
disconnect() {
|
|
812
|
+
setConnected(this, false);
|
|
813
|
+
}
|
|
814
|
+
enable() {
|
|
815
|
+
if (this.disabled) setDisabled(this, false);
|
|
816
|
+
}
|
|
817
|
+
focus(last) {
|
|
818
|
+
tabToTrap(this, getFocusable(this.element), this.element, last ? -1 : 0);
|
|
819
|
+
}
|
|
820
|
+
};
|
|
821
|
+
function createFocusTrap(element, options) {
|
|
822
|
+
let focusTrap = FOCUSTRAPS_ALL.get(element);
|
|
823
|
+
if (focusTrap == null) {
|
|
824
|
+
focusTrap = new FocusTrap(element, options);
|
|
825
|
+
FOCUSTRAPS_ALL.set(element, focusTrap);
|
|
826
|
+
}
|
|
827
|
+
return focusTrap;
|
|
828
|
+
}
|
|
829
|
+
function onEscape(event) {
|
|
830
|
+
let element = findAncestor(event, ATTRIBUTE_SELECTOR);
|
|
831
|
+
let focusTrap = FOCUSTRAPS_ALL.get(element);
|
|
832
|
+
if (element == null || focusTrap == null) return;
|
|
833
|
+
while (focusTrap.disabled) {
|
|
834
|
+
element = findAncestor(focusTrap.element.parentElement, ATTRIBUTE_SELECTOR);
|
|
835
|
+
focusTrap = FOCUSTRAPS_ALL.get(element);
|
|
836
|
+
if (element == null || focusTrap == null) return;
|
|
837
|
+
if (!focusTrap.disabled) break;
|
|
838
|
+
}
|
|
839
|
+
focusTrap?.disable();
|
|
840
|
+
}
|
|
841
|
+
function onFocusIn(event) {
|
|
842
|
+
lastTarget = FOCUSTRAPS_ALL.get(findAncestor(event, ATTRIBUTE_SELECTOR)) == null ? void 0 : event.target;
|
|
843
|
+
}
|
|
844
|
+
function onKeydown$2(event) {
|
|
845
|
+
switch (event.key) {
|
|
846
|
+
case "Escape":
|
|
847
|
+
onEscape(event);
|
|
848
|
+
break;
|
|
849
|
+
case "Tab":
|
|
850
|
+
onTab(event);
|
|
851
|
+
break;
|
|
852
|
+
default: return;
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
function onPointerdown$2(event) {
|
|
856
|
+
const lastFocusTrap = findAncestor(lastTarget, ATTRIBUTE_SELECTOR);
|
|
857
|
+
const nextFocusTrap = findAncestor(event, ATTRIBUTE_SELECTOR);
|
|
858
|
+
if (lastFocusTrap != null && nextFocusTrap !== lastFocusTrap) {
|
|
859
|
+
if (FOCUSTRAPS_ALL.get(lastFocusTrap)?.contain ?? false) {
|
|
860
|
+
event.preventDefault();
|
|
861
|
+
lastTarget?.focus();
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
if (FOCUSTRAPS_DISABLED.size === 0) return;
|
|
865
|
+
for (const focusTrap of FOCUSTRAPS_DISABLED) if (focusTrap.element !== nextFocusTrap) focusTrap.enable();
|
|
866
|
+
}
|
|
867
|
+
function onTab(event) {
|
|
868
|
+
const element = findAncestor(event, ATTRIBUTE_SELECTOR);
|
|
869
|
+
const focusTrap = FOCUSTRAPS_ALL.get(element);
|
|
870
|
+
if (focusTrap == null) return;
|
|
871
|
+
if (!focusTrap.disabled) event.preventDefault();
|
|
872
|
+
const elements = getFocusable(element);
|
|
873
|
+
const index = elements.indexOf(event.target);
|
|
874
|
+
if (index === -1 || elements.length === 0) tabToTrap(focusTrap, elements, element);
|
|
875
|
+
else tabToElement(focusTrap, elements, index, event.shiftKey ? -1 : 1);
|
|
876
|
+
}
|
|
877
|
+
function setConnected(focusTrap, value) {
|
|
878
|
+
if (!focusTrap.embedded || focusTrap.connected === value) return;
|
|
879
|
+
focusTrap.connected = value;
|
|
880
|
+
}
|
|
881
|
+
function setDisabled(focusTrap, value) {
|
|
882
|
+
focusTrap.disabled = value;
|
|
883
|
+
if (value) FOCUSTRAPS_DISABLED.add(focusTrap);
|
|
884
|
+
else FOCUSTRAPS_DISABLED.delete(focusTrap);
|
|
885
|
+
}
|
|
886
|
+
function tabToElement(focusTrap, elements, index, modifier) {
|
|
887
|
+
const { length } = elements;
|
|
888
|
+
const next = clamp(index + modifier, 0, length - 1, true);
|
|
889
|
+
if (focusTrap.disabled) {
|
|
890
|
+
if (index === length - 1 && next === 0 || index === 0 && next === length - 1) {
|
|
891
|
+
lastTarget = void 0;
|
|
892
|
+
focusTrap.enable();
|
|
893
|
+
}
|
|
894
|
+
return;
|
|
895
|
+
}
|
|
896
|
+
const element = elements[next];
|
|
897
|
+
const elementFocusTrap = FOCUSTRAPS_ALL.get(element);
|
|
898
|
+
if (elementFocusTrap != null) elementFocusTrap.focus(modifier === -1);
|
|
899
|
+
else {
|
|
900
|
+
elements[next].focus();
|
|
901
|
+
lastTarget = elements[next];
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
function tabToTrap(focusTrap, elements, element, index) {
|
|
905
|
+
if (focusTrap.disabled) {
|
|
906
|
+
lastTarget = void 0;
|
|
907
|
+
focusTrap.enable();
|
|
908
|
+
} else {
|
|
909
|
+
const next = elements.length === 0 ? element : elements.at(index ?? 0);
|
|
910
|
+
next.focus();
|
|
911
|
+
lastTarget = next;
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
const FOCUS_TRAP_SELECTOR = "oui-focus-trap";
|
|
915
|
+
const ATTRIBUTE_SELECTOR = `[${FOCUS_TRAP_SELECTOR}]`;
|
|
916
|
+
const EVENT_OPTIONS = {
|
|
917
|
+
capture: true,
|
|
918
|
+
passive: false
|
|
919
|
+
};
|
|
920
|
+
const FOCUS_TRAP_CONTAIN = `${FOCUS_TRAP_SELECTOR}-contain`;
|
|
921
|
+
const FOCUS_TRAP_NOESCAPE = `${FOCUS_TRAP_SELECTOR}-noescape`;
|
|
922
|
+
const FOCUSTRAPS_ALL = /* @__PURE__ */ new WeakMap();
|
|
923
|
+
const FOCUSTRAPS_DISABLED = /* @__PURE__ */ new Set();
|
|
924
|
+
let lastTarget;
|
|
925
|
+
on(document, "focusin", onFocusIn, EVENT_OPTIONS);
|
|
926
|
+
on(document, "keydown", onKeydown$2, EVENT_OPTIONS);
|
|
927
|
+
on(document, "mousedown", onPointerdown$2, EVENT_OPTIONS);
|
|
928
|
+
on(document, "touchstart", onPointerdown$2, EVENT_OPTIONS);
|
|
929
|
+
//#endregion
|
|
930
|
+
//#region src/js/focus-trap/standalone.ts
|
|
931
|
+
function removeFocusTraps(element) {
|
|
932
|
+
FOCUSTRAPS_ALL.get(element)?.destroy();
|
|
933
|
+
FOCUSTRAPS_ALL.delete(element);
|
|
934
|
+
}
|
|
935
|
+
attributable(FOCUS_TRAP_SELECTOR, createFocusTrap, removeFocusTraps);
|
|
936
|
+
new Set([
|
|
937
|
+
Node.ELEMENT_NODE,
|
|
938
|
+
Node.TEXT_NODE,
|
|
939
|
+
Node.PROCESSING_INSTRUCTION_NODE,
|
|
940
|
+
Node.COMMENT_NODE,
|
|
941
|
+
Node.DOCUMENT_TYPE_NODE
|
|
942
|
+
]);
|
|
943
|
+
//#endregion
|
|
944
|
+
//#region node_modules/@oscarpalmer/toretto/dist/internal/property.mjs
|
|
945
|
+
function getPropertyValue(element, name, value) {
|
|
946
|
+
if (isInputElement(element) && name === "value") return getString(value);
|
|
947
|
+
return value;
|
|
948
|
+
}
|
|
949
|
+
function updateProperty(element, name, value, dispatch) {
|
|
950
|
+
let property = name;
|
|
951
|
+
if (!(property in element)) property = camelCase(name);
|
|
952
|
+
const next = getPropertyValue(element, name, value);
|
|
953
|
+
if (!(property in element) || Object.is(element[property], next)) return;
|
|
954
|
+
element[property] = next;
|
|
955
|
+
const event = dispatch && elementEvents[element.tagName]?.[property];
|
|
956
|
+
if (typeof event === "string") element.dispatchEvent(new Event(event, {
|
|
957
|
+
bubbles: true,
|
|
958
|
+
cancelable: true
|
|
959
|
+
}));
|
|
960
|
+
}
|
|
961
|
+
const elementEvents = {
|
|
962
|
+
DETAILS: { open: "toggle" },
|
|
963
|
+
INPUT: {
|
|
964
|
+
checked: "change",
|
|
965
|
+
value: "input"
|
|
966
|
+
},
|
|
967
|
+
SELECT: { value: "change" },
|
|
968
|
+
TEXTAREA: { value: "input" }
|
|
969
|
+
};
|
|
970
|
+
//#endregion
|
|
971
|
+
//#region node_modules/@oscarpalmer/toretto/dist/internal/attribute.mjs
|
|
972
|
+
function isAttribute(value) {
|
|
973
|
+
return value instanceof Attr || isPlainObject(value) && typeof value.name === "string" && "value" in value;
|
|
974
|
+
}
|
|
975
|
+
function updateAttribute(element, name, value, dispatch) {
|
|
976
|
+
const lowerCaseName = name.toLowerCase();
|
|
977
|
+
const isBoolean = booleanAttributesSet.has(lowerCaseName);
|
|
978
|
+
const next = isBoolean ? value === true || typeof value === "string" && (value === "" || value.toLowerCase() === lowerCaseName) : value == null ? "" : value;
|
|
979
|
+
if (isBoolean || dispatchedAttributes.has(name)) updateProperty(element, name, next, dispatch);
|
|
980
|
+
updateElementValue(element, name, isBoolean ? next ? "" : null : value, element.setAttribute, element.removeAttribute, isBoolean, false);
|
|
981
|
+
}
|
|
982
|
+
/**
|
|
983
|
+
* List of boolean attributes
|
|
984
|
+
*/
|
|
985
|
+
const booleanAttributes = Object.freeze([
|
|
986
|
+
"async",
|
|
987
|
+
"autofocus",
|
|
988
|
+
"autoplay",
|
|
989
|
+
"checked",
|
|
990
|
+
"controls",
|
|
991
|
+
"default",
|
|
992
|
+
"defer",
|
|
993
|
+
"disabled",
|
|
994
|
+
"formnovalidate",
|
|
995
|
+
"hidden",
|
|
996
|
+
"inert",
|
|
997
|
+
"ismap",
|
|
998
|
+
"itemscope",
|
|
999
|
+
"loop",
|
|
1000
|
+
"multiple",
|
|
1001
|
+
"muted",
|
|
1002
|
+
"nomodule",
|
|
1003
|
+
"novalidate",
|
|
1004
|
+
"open",
|
|
1005
|
+
"playsinline",
|
|
1006
|
+
"readonly",
|
|
1007
|
+
"required",
|
|
1008
|
+
"reversed",
|
|
1009
|
+
"selected"
|
|
1010
|
+
]);
|
|
1011
|
+
const booleanAttributesSet = new Set(booleanAttributes);
|
|
1012
|
+
const dispatchedAttributes = new Set([
|
|
1013
|
+
"checked",
|
|
1014
|
+
"open",
|
|
1015
|
+
"value"
|
|
1016
|
+
]);
|
|
1017
|
+
document.createElement("form");
|
|
1018
|
+
//#endregion
|
|
1019
|
+
//#region node_modules/@oscarpalmer/toretto/dist/internal/element-value.mjs
|
|
1020
|
+
function ignoreSetAttribute(element, name) {
|
|
1021
|
+
if (element instanceof HTMLTextAreaElement && name === "value") return true;
|
|
1022
|
+
return false;
|
|
1023
|
+
}
|
|
1024
|
+
function normalizeKey(key, style) {
|
|
1025
|
+
return style && key.startsWith(CSS_VARIABLE_PREFIX) ? key : kebabCase(key);
|
|
1026
|
+
}
|
|
1027
|
+
function setElementValue(element, first, second, third, callback, style) {
|
|
1028
|
+
if (!isHTMLOrSVGElement(element)) return;
|
|
1029
|
+
if (typeof first === "string") setElementValues(element, first, second, third, callback, style);
|
|
1030
|
+
else if (isAttribute(first)) setElementValues(element, first.name, first.value, third, callback, style);
|
|
1031
|
+
}
|
|
1032
|
+
function setElementValues(element, first, second, third, callback, style) {
|
|
1033
|
+
if (!isHTMLOrSVGElement(element)) return;
|
|
1034
|
+
const dispatch = third !== false;
|
|
1035
|
+
if (typeof first === "string") {
|
|
1036
|
+
callback(element, normalizeKey(first, style), second, dispatch);
|
|
1037
|
+
return;
|
|
1038
|
+
}
|
|
1039
|
+
const isArray = Array.isArray(first);
|
|
1040
|
+
if (!isArray && !(typeof first === "object" && first !== null)) return;
|
|
1041
|
+
const entries = isArray ? first : Object.entries(first).map(([name, value]) => ({
|
|
1042
|
+
name,
|
|
1043
|
+
value
|
|
1044
|
+
}));
|
|
1045
|
+
const { length } = entries;
|
|
1046
|
+
for (let index = 0; index < length; index += 1) {
|
|
1047
|
+
const entry = entries[index];
|
|
1048
|
+
if (typeof entry === "object" && typeof entry?.name === "string") callback(element, normalizeKey(entry.name, style), entry.value, dispatch);
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
function updateElementValue(element, key, value, set, remove, isBoolean, json) {
|
|
1052
|
+
if (isBoolean ? value == null : isNullableOrWhitespace(value)) remove.call(element, key);
|
|
1053
|
+
else if (!ignoreSetAttribute(element, key)) set.call(element, key, json ? JSON.stringify(value) : getString(value));
|
|
1054
|
+
}
|
|
1055
|
+
const CSS_VARIABLE_PREFIX = "--";
|
|
1056
|
+
//#endregion
|
|
1057
|
+
//#region node_modules/@oscarpalmer/toretto/dist/style.mjs
|
|
1058
|
+
/**
|
|
1059
|
+
* Get styles from an element
|
|
1060
|
+
*
|
|
1061
|
+
* @param element Element to get the styles from
|
|
1062
|
+
* @param properties Styles to get
|
|
1063
|
+
* @param computed Get the computed styles? _(defaults to `false`)_
|
|
1064
|
+
* @returns Style values
|
|
1065
|
+
*/
|
|
1066
|
+
function getStyles(element, properties, computed) {
|
|
1067
|
+
const styles = {};
|
|
1068
|
+
if (!(isHTMLOrSVGElement(element) && Array.isArray(properties))) return styles;
|
|
1069
|
+
const { length } = properties;
|
|
1070
|
+
for (let index = 0; index < length; index += 1) {
|
|
1071
|
+
const property = properties[index];
|
|
1072
|
+
if (typeof property === "string") styles[property] = getStyleValue(element, property, computed === true);
|
|
1073
|
+
}
|
|
1074
|
+
return styles;
|
|
1075
|
+
}
|
|
1076
|
+
/**
|
|
1077
|
+
* Set styles on an element
|
|
1078
|
+
*
|
|
1079
|
+
* @param element Element to set the styles on
|
|
1080
|
+
* @param styles Styles to set
|
|
1081
|
+
*/
|
|
1082
|
+
function setStyles(element, styles) {
|
|
1083
|
+
setElementValues(element, styles, null, null, updateStyleProperty, true);
|
|
1084
|
+
}
|
|
1085
|
+
/**
|
|
1086
|
+
* Toggle styles for an element
|
|
1087
|
+
*
|
|
1088
|
+
* @param element Element to style
|
|
1089
|
+
* @param styles Styles to be set or removed
|
|
1090
|
+
* @returns Style toggler
|
|
1091
|
+
*/
|
|
1092
|
+
function toggleStyles(element, styles) {
|
|
1093
|
+
function toggle(set) {
|
|
1094
|
+
hasSet = set;
|
|
1095
|
+
let next;
|
|
1096
|
+
if (set) {
|
|
1097
|
+
values = getStyles(element, keys);
|
|
1098
|
+
next = styles;
|
|
1099
|
+
} else {
|
|
1100
|
+
next = { ...values };
|
|
1101
|
+
values = {};
|
|
1102
|
+
for (let index = 0; index < length; index += 1) values[keys[index]] = void 0;
|
|
1103
|
+
}
|
|
1104
|
+
setStyles(element, next);
|
|
1105
|
+
}
|
|
1106
|
+
const keys = Object.keys(styles);
|
|
1107
|
+
const { length } = keys;
|
|
1108
|
+
let hasSet = false;
|
|
1109
|
+
let values = {};
|
|
1110
|
+
return {
|
|
1111
|
+
set() {
|
|
1112
|
+
if (!hasSet) toggle(true);
|
|
1113
|
+
},
|
|
1114
|
+
remove() {
|
|
1115
|
+
if (hasSet) toggle(false);
|
|
1116
|
+
}
|
|
1117
|
+
};
|
|
1118
|
+
}
|
|
1119
|
+
function updateStyleProperty(element, key, value) {
|
|
1120
|
+
updateElementValue(element, key, value, function(property, style) {
|
|
1121
|
+
if (property.startsWith(VARIABLE_PREFIX)) this.style.setProperty(property, getString(style));
|
|
1122
|
+
else this.style[property] = getString(style);
|
|
1123
|
+
}, function(property) {
|
|
1124
|
+
if (property.startsWith(VARIABLE_PREFIX)) this.style.removeProperty(property);
|
|
1125
|
+
else this.style[property] = "";
|
|
1126
|
+
if (this.getAttribute(ATTRIBUTE_STYLE) === "") this.removeAttribute(ATTRIBUTE_STYLE);
|
|
1127
|
+
}, false, false);
|
|
1128
|
+
}
|
|
1129
|
+
const ATTRIBUTE_STYLE = "style";
|
|
1130
|
+
const VARIABLE_PREFIX = "--";
|
|
1131
|
+
//#endregion
|
|
1132
|
+
//#region node_modules/@oscarpalmer/toretto/dist/touch.mjs
|
|
1133
|
+
function getSupport() {
|
|
1134
|
+
if (window == null || navigator == null) return false;
|
|
1135
|
+
if ("matchMedia" in window) {
|
|
1136
|
+
const media = matchMedia?.("(pointer: coarse)");
|
|
1137
|
+
if (typeof media?.matches === "boolean" && media.matches) return true;
|
|
1138
|
+
}
|
|
1139
|
+
if ("ontouchstart" in window) return true;
|
|
1140
|
+
if (typeof navigator.maxTouchPoints === "number" && navigator.maxTouchPoints > 0) return true;
|
|
1141
|
+
if (typeof navigator.msMaxTouchPoints === "number" && navigator.msMaxTouchPoints > 0) return true;
|
|
1142
|
+
return false;
|
|
1143
|
+
}
|
|
1144
|
+
/**
|
|
1145
|
+
* Does the device support touch events?
|
|
1146
|
+
*/
|
|
1147
|
+
const supportsTouch = (() => {
|
|
1148
|
+
let support = getSupport();
|
|
1149
|
+
const instance = Object.create({
|
|
1150
|
+
get() {
|
|
1151
|
+
return support;
|
|
1152
|
+
},
|
|
1153
|
+
update() {
|
|
1154
|
+
support = getSupport();
|
|
1155
|
+
return support;
|
|
1156
|
+
}
|
|
1157
|
+
});
|
|
1158
|
+
Object.defineProperty(instance, "value", { get() {
|
|
1159
|
+
return support;
|
|
1160
|
+
} });
|
|
1161
|
+
return instance;
|
|
1162
|
+
})();
|
|
1163
|
+
//#endregion
|
|
1164
|
+
//#region src/js/internal/draggable.ts
|
|
1165
|
+
var Draggable = class {
|
|
1166
|
+
prefix;
|
|
1167
|
+
element;
|
|
1168
|
+
options;
|
|
1169
|
+
container;
|
|
1170
|
+
hasHandles;
|
|
1171
|
+
horizontal = true;
|
|
1172
|
+
vertical = true;
|
|
1173
|
+
constructor(prefix, element, options) {
|
|
1174
|
+
this.prefix = prefix;
|
|
1175
|
+
this.element = element;
|
|
1176
|
+
this.options = options;
|
|
1177
|
+
setContainer(this, options);
|
|
1178
|
+
setDirection(this, options);
|
|
1179
|
+
}
|
|
1180
|
+
destroy() {
|
|
1181
|
+
unsetContainer(this, this.options);
|
|
1182
|
+
this.container = void 0;
|
|
1183
|
+
this.element = void 0;
|
|
1184
|
+
this.options = void 0;
|
|
1185
|
+
}
|
|
1186
|
+
};
|
|
1187
|
+
function addDraggable(element) {
|
|
1188
|
+
let instances = state.instances.get(element);
|
|
1189
|
+
if (instances == null) {
|
|
1190
|
+
instances = {};
|
|
1191
|
+
state.instances.set(element, instances);
|
|
1192
|
+
}
|
|
1193
|
+
instances[this.property] ??= new this.constructor(element);
|
|
1194
|
+
}
|
|
1195
|
+
function getHandle(event, isMovable) {
|
|
1196
|
+
return findAncestor(event, isMovable ? SELECTOR_MOVABLE_HANDLE : SELECTOR_SORTABLE_HANDLE);
|
|
1197
|
+
}
|
|
1198
|
+
function getNextPosition(draggable, position) {
|
|
1199
|
+
let x = state.original?.x ?? 0;
|
|
1200
|
+
let y = state.original?.y ?? 0;
|
|
1201
|
+
if (draggable.horizontal) {
|
|
1202
|
+
x = position.x - (state.offset?.x ?? 0);
|
|
1203
|
+
if (state.container != null && state.element != null) x = clamp(x, state.container.left, state.container.right - state.element.rectangle.width);
|
|
1204
|
+
}
|
|
1205
|
+
if (draggable.vertical) {
|
|
1206
|
+
y = position.y - (state.offset?.y ?? 0);
|
|
1207
|
+
if (state.container != null && state.element != null) y = clamp(y, state.container.top, state.container.bottom - state.element.rectangle.height);
|
|
1208
|
+
}
|
|
1209
|
+
return {
|
|
1210
|
+
x,
|
|
1211
|
+
y
|
|
1212
|
+
};
|
|
1213
|
+
}
|
|
1214
|
+
function onKeydown$1(event) {
|
|
1215
|
+
if (current == null || event.key !== KEY_ESCAPE) return;
|
|
1216
|
+
const { origin } = current;
|
|
1217
|
+
current.options.drag.onCancel?.(state, current);
|
|
1218
|
+
current.element.dispatchEvent(new CustomEvent(`${current.prefix}:cancel`, { detail: { element: origin } }));
|
|
1219
|
+
reset();
|
|
1220
|
+
}
|
|
1221
|
+
function onPointerdown$1(event) {
|
|
1222
|
+
if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey || (supportsTouch.value ? event.type === "mousedown" : event.type === "touchstart" || event.button !== 0)) return;
|
|
1223
|
+
const container = findAncestor(event, SELECTOR$4);
|
|
1224
|
+
const instances = state.instances.get(container);
|
|
1225
|
+
if (instances == null) return;
|
|
1226
|
+
const isMovable = container.hasAttribute(ATTRIBUTE_MOVABLE);
|
|
1227
|
+
const instance = isMovable ? instances.movable : instances.sortable;
|
|
1228
|
+
if (instance == null) return;
|
|
1229
|
+
if (supportsTouch.value) event.preventDefault();
|
|
1230
|
+
let element = container;
|
|
1231
|
+
if (!isMovable) {
|
|
1232
|
+
element = findAncestor(event, SELECTOR_SORTABLE_ITEM);
|
|
1233
|
+
if (element == null || element.parentElement !== container) return;
|
|
1234
|
+
}
|
|
1235
|
+
let handle = element;
|
|
1236
|
+
instance.hasHandles ??= element.querySelector(SELECTOR_SORTABLE_HANDLE) != null;
|
|
1237
|
+
if (instance.hasHandles) handle = getHandle(event, isMovable);
|
|
1238
|
+
if (handle == null) return;
|
|
1239
|
+
const { dragged } = instance;
|
|
1240
|
+
const rectangle = dragged.getBoundingClientRect();
|
|
1241
|
+
const position = getPosition(event) ?? {
|
|
1242
|
+
x: 0,
|
|
1243
|
+
y: 0
|
|
1244
|
+
};
|
|
1245
|
+
current = instance;
|
|
1246
|
+
state.container = instance.container?.getBoundingClientRect();
|
|
1247
|
+
state.element = {
|
|
1248
|
+
rectangle,
|
|
1249
|
+
node: dragged
|
|
1250
|
+
};
|
|
1251
|
+
state.offset = instance.options.position.getOffset(state, instance, element, position);
|
|
1252
|
+
state.original = instance.options.position.getOriginal(state, instance, position);
|
|
1253
|
+
const begin = new CustomEvent(`${instance.prefix}:begin`, {
|
|
1254
|
+
detail: {
|
|
1255
|
+
element,
|
|
1256
|
+
position: { ...state.original }
|
|
1257
|
+
},
|
|
1258
|
+
cancelable: true
|
|
1259
|
+
});
|
|
1260
|
+
instance.element.dispatchEvent(begin);
|
|
1261
|
+
setTimeout(() => {
|
|
1262
|
+
if (begin.defaultPrevented) {
|
|
1263
|
+
current?.options.drag.onCancel(state, instance);
|
|
1264
|
+
reset();
|
|
1265
|
+
return;
|
|
1266
|
+
}
|
|
1267
|
+
const next = getNextPosition(instance, position);
|
|
1268
|
+
dragged.style.position = "fixed";
|
|
1269
|
+
dragged.style.inset = `${next.y}px auto auto ${next.x}px`;
|
|
1270
|
+
instance.options.drag.onBegin(event, state, instance, element, handle, next);
|
|
1271
|
+
styleToggler.set();
|
|
1272
|
+
});
|
|
1273
|
+
}
|
|
1274
|
+
function onPointermove$1(event) {
|
|
1275
|
+
if (current == null) return;
|
|
1276
|
+
const position = getPosition(event);
|
|
1277
|
+
if (position == null) return;
|
|
1278
|
+
const next = getNextPosition(current, position);
|
|
1279
|
+
if (state.element != null) state.element.node.style.inset = `${next.y}px auto auto ${next.x}px`;
|
|
1280
|
+
const detail = current.options.drag.onMove(event, state, current, {
|
|
1281
|
+
calculated: next,
|
|
1282
|
+
original: position
|
|
1283
|
+
});
|
|
1284
|
+
current.element.dispatchEvent(new CustomEvent(`${current.prefix}:move`, { detail }));
|
|
1285
|
+
}
|
|
1286
|
+
function onPointerup$1(event) {
|
|
1287
|
+
current?.options.drag.onEnd?.(event, state, current, reset);
|
|
1288
|
+
}
|
|
1289
|
+
function removeDraggable(element) {
|
|
1290
|
+
const { property } = this;
|
|
1291
|
+
const instances = state.instances.get(element);
|
|
1292
|
+
if (instances == null || instances[property] == null) return;
|
|
1293
|
+
instances[property]?.destroy();
|
|
1294
|
+
instances[property] = void 0;
|
|
1295
|
+
if (instances[properties[property]] == null) state.instances.delete(element);
|
|
1296
|
+
}
|
|
1297
|
+
function reset() {
|
|
1298
|
+
current = void 0;
|
|
1299
|
+
state.container = void 0;
|
|
1300
|
+
state.element = void 0;
|
|
1301
|
+
state.offset = void 0;
|
|
1302
|
+
state.original = void 0;
|
|
1303
|
+
styleToggler.remove();
|
|
1304
|
+
}
|
|
1305
|
+
function setContainer(draggable, options) {
|
|
1306
|
+
const selector = draggable.element.getAttribute(options.container.attribute);
|
|
1307
|
+
if (typeof selector !== "string") return;
|
|
1308
|
+
draggable.container = globals.has(selector) ? draggable.element.ownerDocument.body : document.querySelector(selector) ?? void 0;
|
|
1309
|
+
if (draggable.container == null) return;
|
|
1310
|
+
const set = options.container.map.get(draggable.container);
|
|
1311
|
+
if (set == null) options.container.map.set(draggable.container, new Set([draggable]));
|
|
1312
|
+
else set.add(draggable);
|
|
1313
|
+
options.container.onInitialize?.(draggable);
|
|
1314
|
+
}
|
|
1315
|
+
function setDirection(draggable, options) {
|
|
1316
|
+
const direction = draggable.element.getAttribute(options.direction.attribute);
|
|
1317
|
+
if (horizontals.has(direction)) draggable.vertical = false;
|
|
1318
|
+
else if (verticals.has(direction)) draggable.horizontal = false;
|
|
1319
|
+
options.direction.onAfter?.(draggable);
|
|
1320
|
+
}
|
|
1321
|
+
function unsetContainer(draggable, options) {
|
|
1322
|
+
const { container } = draggable;
|
|
1323
|
+
if (container == null) return;
|
|
1324
|
+
const set = options.container.map.get(container);
|
|
1325
|
+
let empty = false;
|
|
1326
|
+
if (set != null) {
|
|
1327
|
+
set.delete(draggable);
|
|
1328
|
+
if (set.size === 0) {
|
|
1329
|
+
empty = true;
|
|
1330
|
+
options.container.map.delete(container);
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
options.container.onDestroy?.(draggable, container, empty);
|
|
1334
|
+
}
|
|
1335
|
+
const ATTRIBUTE_MOVABLE = "oui-movable";
|
|
1336
|
+
const ATTRIBUTE_SORTABLE = "oui-sortable";
|
|
1337
|
+
const KEY_ESCAPE = "Escape";
|
|
1338
|
+
const SELECTOR$4 = `[${ATTRIBUTE_MOVABLE}], [${ATTRIBUTE_SORTABLE}]`;
|
|
1339
|
+
const SELECTOR_MOVABLE_HANDLE = `[${ATTRIBUTE_MOVABLE}-handle]`;
|
|
1340
|
+
const SELECTOR_SORTABLE_HANDLE = `[${ATTRIBUTE_SORTABLE}-handle]`;
|
|
1341
|
+
const SELECTOR_SORTABLE_ITEM = `[${ATTRIBUTE_SORTABLE}] > *`;
|
|
1342
|
+
const globals = new Set([
|
|
1343
|
+
"body",
|
|
1344
|
+
"document",
|
|
1345
|
+
"window"
|
|
1346
|
+
]);
|
|
1347
|
+
const horizontals = new Set(["horizontal", "x"]);
|
|
1348
|
+
const properties = {
|
|
1349
|
+
movable: "sortable",
|
|
1350
|
+
sortable: "movable"
|
|
1351
|
+
};
|
|
1352
|
+
const state = {
|
|
1353
|
+
container: void 0,
|
|
1354
|
+
element: void 0,
|
|
1355
|
+
instances: /* @__PURE__ */ new WeakMap(),
|
|
1356
|
+
offset: void 0,
|
|
1357
|
+
original: void 0
|
|
1358
|
+
};
|
|
1359
|
+
const styleToggler = toggleStyles(document.body, {
|
|
1360
|
+
touchAction: "none",
|
|
1361
|
+
userSelect: "none",
|
|
1362
|
+
webkitUserSelect: "none"
|
|
1363
|
+
});
|
|
1364
|
+
const verticals = new Set(["vertical", "y"]);
|
|
1365
|
+
let current;
|
|
1366
|
+
on(document, "keydown", onKeydown$1);
|
|
1367
|
+
on(document, "mousedown", onPointerdown$1);
|
|
1368
|
+
on(document, "pointermove", onPointermove$1);
|
|
1369
|
+
on(document, "pointerup", onPointerup$1);
|
|
1370
|
+
on(document, "touchcancel", onPointerup$1, { passive: false });
|
|
1371
|
+
on(document, "touchstart", onPointerdown$1, { passive: false });
|
|
1372
|
+
//#endregion
|
|
1373
|
+
//#region src/js/movable.ts
|
|
1374
|
+
var Movable = class extends Draggable {
|
|
1375
|
+
inset;
|
|
1376
|
+
moved = false;
|
|
1377
|
+
offset;
|
|
1378
|
+
position;
|
|
1379
|
+
get dragged() {
|
|
1380
|
+
return this.element;
|
|
1381
|
+
}
|
|
1382
|
+
get origin() {
|
|
1383
|
+
return this.element;
|
|
1384
|
+
}
|
|
1385
|
+
constructor(element) {
|
|
1386
|
+
super("move", element, {
|
|
1387
|
+
container: {
|
|
1388
|
+
attribute: ATTRIBUTE_CONTAINER$1,
|
|
1389
|
+
map: CONTAINERS$1,
|
|
1390
|
+
onDestroy: destroyContainer,
|
|
1391
|
+
onInitialize: initializeContainer
|
|
1392
|
+
},
|
|
1393
|
+
direction: {
|
|
1394
|
+
attribute: ATTRIBUTE_DIRECTION$1,
|
|
1395
|
+
onAfter: afterDirection
|
|
1396
|
+
},
|
|
1397
|
+
drag: {
|
|
1398
|
+
onBegin: onBegin$1,
|
|
1399
|
+
onCancel: onCancel$1,
|
|
1400
|
+
onEnd: onEnd$2,
|
|
1401
|
+
onMove: onMove$1
|
|
1402
|
+
},
|
|
1403
|
+
position: {
|
|
1404
|
+
getOffset: getOffsetPosition$1,
|
|
1405
|
+
getOriginal: getOriginalPosition$1
|
|
1406
|
+
}
|
|
1407
|
+
});
|
|
1408
|
+
this.hasHandles = element.querySelector(SELECTOR_HANDLE$1) != null;
|
|
1409
|
+
this.inset = element.style.inset;
|
|
1410
|
+
this.position = element.style.position;
|
|
1411
|
+
}
|
|
1412
|
+
destroy() {
|
|
1413
|
+
super.destroy();
|
|
1414
|
+
MOVED.delete(this);
|
|
1415
|
+
this.element.style.inset = this.inset;
|
|
1416
|
+
this.element.style.position = this.position;
|
|
1417
|
+
}
|
|
1418
|
+
};
|
|
1419
|
+
function afterDirection(draggable) {
|
|
1420
|
+
const container = draggable.container?.getBoundingClientRect();
|
|
1421
|
+
if (container != null) setOffset(draggable, container);
|
|
1422
|
+
}
|
|
1423
|
+
function destroyContainer(_, container, empty) {
|
|
1424
|
+
if (empty) resizer.unobserve(container);
|
|
1425
|
+
}
|
|
1426
|
+
function getOffsetPosition$1(state, _, __, position) {
|
|
1427
|
+
return {
|
|
1428
|
+
x: position.x - (state.element?.rectangle.left ?? 0),
|
|
1429
|
+
y: position.y - (state.element?.rectangle.top ?? 0)
|
|
1430
|
+
};
|
|
1431
|
+
}
|
|
1432
|
+
function getOriginalPosition$1(state) {
|
|
1433
|
+
return {
|
|
1434
|
+
x: state.element?.rectangle.left ?? 0,
|
|
1435
|
+
y: state.element?.rectangle.top ?? 0
|
|
1436
|
+
};
|
|
1437
|
+
}
|
|
1438
|
+
function initializeContainer(draggable) {
|
|
1439
|
+
resizer.observe(draggable.container);
|
|
1440
|
+
}
|
|
1441
|
+
function onBegin$1() {}
|
|
1442
|
+
function onCancel$1(state, draggable) {
|
|
1443
|
+
const { element, inset, moved, position } = draggable;
|
|
1444
|
+
const { x, y } = state.original ?? {
|
|
1445
|
+
x: 0,
|
|
1446
|
+
y: 0
|
|
1447
|
+
};
|
|
1448
|
+
if (moved) element.style.inset = `${y}px auto auto ${x}px`;
|
|
1449
|
+
else {
|
|
1450
|
+
element.style.position = position;
|
|
1451
|
+
element.style.inset = inset;
|
|
1452
|
+
}
|
|
1453
|
+
}
|
|
1454
|
+
function onEnd$2(event, state, draggable, reset) {
|
|
1455
|
+
const movable = draggable;
|
|
1456
|
+
if (!movable.moved) {
|
|
1457
|
+
movable.moved = true;
|
|
1458
|
+
if (movable.container != null) MOVED.add(movable);
|
|
1459
|
+
}
|
|
1460
|
+
const container = movable.container?.getBoundingClientRect();
|
|
1461
|
+
if (container != null) setOffset(movable, container);
|
|
1462
|
+
const end = new CustomEvent(EVENT_END$1, {
|
|
1463
|
+
detail: {
|
|
1464
|
+
from: { ...state.original },
|
|
1465
|
+
to: getPosition(event)
|
|
1466
|
+
},
|
|
1467
|
+
cancelable: true
|
|
1468
|
+
});
|
|
1469
|
+
movable.element.dispatchEvent(end);
|
|
1470
|
+
setTimeout(() => {
|
|
1471
|
+
if (end.defaultPrevented) onCancel$1(state, draggable);
|
|
1472
|
+
reset();
|
|
1473
|
+
});
|
|
1474
|
+
}
|
|
1475
|
+
function onMove$1(_, state, __, position) {
|
|
1476
|
+
return {
|
|
1477
|
+
from: { ...state.original },
|
|
1478
|
+
to: { ...position.calculated }
|
|
1479
|
+
};
|
|
1480
|
+
}
|
|
1481
|
+
function onResize(entries) {
|
|
1482
|
+
const { length } = entries;
|
|
1483
|
+
for (let index = 0; index < length; index += 1) {
|
|
1484
|
+
const entry = entries[index];
|
|
1485
|
+
const set = CONTAINERS$1.get(entry.target);
|
|
1486
|
+
if (set == null) continue;
|
|
1487
|
+
for (const movable of set) reposition(movable);
|
|
1488
|
+
}
|
|
1489
|
+
}
|
|
1490
|
+
function onScroll() {
|
|
1491
|
+
for (const moved of MOVED) reposition(moved);
|
|
1492
|
+
}
|
|
1493
|
+
function reposition(movable) {
|
|
1494
|
+
if (!movable.moved || movable.container == null) return;
|
|
1495
|
+
const container = movable.container.getBoundingClientRect();
|
|
1496
|
+
const x = container.left + (movable.offset?.x ?? 0);
|
|
1497
|
+
const y = container.top + (movable.offset?.y ?? 0);
|
|
1498
|
+
movable.element.style.inset = `${y}px auto auto ${x}px`;
|
|
1499
|
+
}
|
|
1500
|
+
function setOffset(movable, container) {
|
|
1501
|
+
movable.offset = {};
|
|
1502
|
+
const element = movable.element.getBoundingClientRect();
|
|
1503
|
+
movable.offset.y = element.top - container.top;
|
|
1504
|
+
movable.offset.x = element.left - container.left;
|
|
1505
|
+
}
|
|
1506
|
+
const ATTRIBUTE$2 = "oui-movable";
|
|
1507
|
+
const ATTRIBUTE_CONTAINER$1 = `${ATTRIBUTE$2}-container`;
|
|
1508
|
+
const ATTRIBUTE_DIRECTION$1 = `${ATTRIBUTE$2}-direction`;
|
|
1509
|
+
const CONTAINERS$1 = /* @__PURE__ */ new Map();
|
|
1510
|
+
const EVENT_END$1 = "move:end";
|
|
1511
|
+
const MOVED = /* @__PURE__ */ new Set();
|
|
1512
|
+
const SELECTOR_HANDLE$1 = `[${ATTRIBUTE$2}-handle]`;
|
|
1513
|
+
const bound$1 = {
|
|
1514
|
+
constructor: Movable,
|
|
1515
|
+
property: "movable"
|
|
1516
|
+
};
|
|
1517
|
+
const resizer = new ResizeObserver(onResize);
|
|
1518
|
+
attributable(ATTRIBUTE$2, addDraggable.bind(bound$1), removeDraggable.bind(bound$1));
|
|
1519
|
+
on(document, "scroll", onScroll);
|
|
1520
|
+
//#endregion
|
|
1521
|
+
//#region src/js/internal/floatable.ts
|
|
1522
|
+
var Floatable = class {
|
|
1523
|
+
options;
|
|
1524
|
+
active = false;
|
|
1525
|
+
disabled = false;
|
|
1526
|
+
frame;
|
|
1527
|
+
ignoreFocus = false;
|
|
1528
|
+
constructor(options) {
|
|
1529
|
+
this.options = options;
|
|
1530
|
+
initialize(this);
|
|
1531
|
+
}
|
|
1532
|
+
destroy() {
|
|
1533
|
+
stop(this);
|
|
1534
|
+
const state = getState();
|
|
1535
|
+
state?.active.delete(this);
|
|
1536
|
+
state?.mapped.delete(this.options.anchor);
|
|
1537
|
+
state?.mapped.delete(this.options.content);
|
|
1538
|
+
this.options.anchor = void 0;
|
|
1539
|
+
this.options.content = void 0;
|
|
1540
|
+
}
|
|
1541
|
+
disable() {
|
|
1542
|
+
if (this.disabled) return;
|
|
1543
|
+
this.disabled = true;
|
|
1544
|
+
stop(this);
|
|
1545
|
+
getState()?.active.delete(this);
|
|
1546
|
+
}
|
|
1547
|
+
enable() {
|
|
1548
|
+
if (!this.disabled) return;
|
|
1549
|
+
this.disabled = false;
|
|
1550
|
+
initialize(this);
|
|
1551
|
+
}
|
|
1552
|
+
toggle(active, ignoreFocus) {
|
|
1553
|
+
if (this.disabled || this.active === active) return;
|
|
1554
|
+
const state = getState();
|
|
1555
|
+
if (state == null) return;
|
|
1556
|
+
this.ignoreFocus = !active && (ignoreFocus ?? false);
|
|
1557
|
+
stop(this);
|
|
1558
|
+
if (active) state.active.add(this);
|
|
1559
|
+
else state.active.delete(this);
|
|
1560
|
+
if (this.options.interactive) if (active) state.order.push(this);
|
|
1561
|
+
else {
|
|
1562
|
+
const index = state.order.indexOf(this);
|
|
1563
|
+
if (index > -1) state.order.splice(index, 1);
|
|
1564
|
+
}
|
|
1565
|
+
if (active) activate(this);
|
|
1566
|
+
else deactivate(this);
|
|
1567
|
+
}
|
|
1568
|
+
};
|
|
1569
|
+
function activate(floatable) {
|
|
1570
|
+
floatable.active = true;
|
|
1571
|
+
document.body.append(floatable.options.content);
|
|
1572
|
+
floatable.options.content.hidden = false;
|
|
1573
|
+
setPosition(floatable);
|
|
1574
|
+
}
|
|
1575
|
+
function closeAbove(element) {
|
|
1576
|
+
const state = getState();
|
|
1577
|
+
if (state == null) return;
|
|
1578
|
+
const index = state.order.findIndex((floatable) => floatable.options.anchor === element || floatable.options.content === element);
|
|
1579
|
+
if (index === -1 || index === state.order.length - 1) return;
|
|
1580
|
+
while (index < state.order.length - 1) state.order.pop()?.toggle(false, true);
|
|
1581
|
+
}
|
|
1582
|
+
function closeAll() {
|
|
1583
|
+
const state = getState();
|
|
1584
|
+
const floatables = [...state?.active ?? []];
|
|
1585
|
+
state?.active.clear();
|
|
1586
|
+
for (const floatable of floatables) floatable.toggle(false, true);
|
|
1587
|
+
}
|
|
1588
|
+
function closeNonInteractive(state) {
|
|
1589
|
+
for (const floatable of state.active) if (!floatable.options.interactive) floatable.toggle(false);
|
|
1590
|
+
}
|
|
1591
|
+
function deactivate(floatable) {
|
|
1592
|
+
floatable.active = false;
|
|
1593
|
+
if (!floatable.options.reusable) {
|
|
1594
|
+
floatable.options.content.hidden = true;
|
|
1595
|
+
floatable.options.anchor.insertAdjacentElement(INSERT_AFTEREND, floatable.options.content);
|
|
1596
|
+
}
|
|
1597
|
+
floatable.options.onAfter?.(false);
|
|
1598
|
+
}
|
|
1599
|
+
function getAnchorName() {
|
|
1600
|
+
index$2 += 1;
|
|
1601
|
+
return `--oui-floatable-anchor-${index$2}`;
|
|
1602
|
+
}
|
|
1603
|
+
function getState() {
|
|
1604
|
+
return window._oscarpalmer_oui_floatable;
|
|
1605
|
+
}
|
|
1606
|
+
function initialize(floatable) {
|
|
1607
|
+
const { anchor, content, interactive } = floatable.options;
|
|
1608
|
+
if (interactive) {
|
|
1609
|
+
anchor.setAttribute(ATTRIBUTE_ANCHOR, "");
|
|
1610
|
+
content.setAttribute(ATTRIBUTE_CONTENT$1, "");
|
|
1611
|
+
}
|
|
1612
|
+
const anchorName = getAnchorName();
|
|
1613
|
+
anchor.style.anchorName = anchorName;
|
|
1614
|
+
content.style.position = "absolute";
|
|
1615
|
+
content.style.positionAnchor = anchorName;
|
|
1616
|
+
content.style.positionTry = "normal flip-start";
|
|
1617
|
+
const state = getState();
|
|
1618
|
+
state?.mapped.set(anchor, floatable);
|
|
1619
|
+
state?.mapped.set(content, floatable);
|
|
1620
|
+
}
|
|
1621
|
+
function isDisabled(element) {
|
|
1622
|
+
return element.disabled || element.readOnly || element.getAttribute("aria-disabled") === "true";
|
|
1623
|
+
}
|
|
1624
|
+
function onClick$1(event) {
|
|
1625
|
+
const related = findAncestor(event, SELECTOR_ALL);
|
|
1626
|
+
if (!(related instanceof HTMLElement)) closeAll();
|
|
1627
|
+
else if (related.hasAttribute(ATTRIBUTE_CONTENT$1)) closeAbove(related);
|
|
1628
|
+
else if (!isDisabled(related)) toggle$1(related);
|
|
1629
|
+
}
|
|
1630
|
+
function onKeyDown(event) {
|
|
1631
|
+
if (event.key !== "Escape") return;
|
|
1632
|
+
const state = getState();
|
|
1633
|
+
if (state == null || state.active.size === 0) return;
|
|
1634
|
+
closeNonInteractive(state);
|
|
1635
|
+
const related = findAncestor(event, SELECTOR_CONTENT$2);
|
|
1636
|
+
if (!(related instanceof HTMLElement)) return;
|
|
1637
|
+
closeAbove(related);
|
|
1638
|
+
const floatable = state.mapped.get(related);
|
|
1639
|
+
if (floatable != null) floatable.toggle(false);
|
|
1640
|
+
}
|
|
1641
|
+
function setPosition(floatable) {
|
|
1642
|
+
let position = floatable.options.anchor.getAttribute(floatable.options.positionAttribute) ?? floatable.options.defaultPosition;
|
|
1643
|
+
if (AREAS[position] == null) position = floatable.options.defaultPosition;
|
|
1644
|
+
const area = AREAS[position];
|
|
1645
|
+
floatable.options.content.style.positionArea = area;
|
|
1646
|
+
floatable.options.content.setAttribute(ATTRIBUTE_POSITION$1, POSITIONS[area]);
|
|
1647
|
+
floatable.options.onAfter?.(true);
|
|
1648
|
+
}
|
|
1649
|
+
function stop(floatable) {
|
|
1650
|
+
if (floatable.frame != null) cancelAnimationFrame(floatable.frame);
|
|
1651
|
+
floatable.frame = void 0;
|
|
1652
|
+
}
|
|
1653
|
+
function toggle$1(anchor) {
|
|
1654
|
+
const floatable = getState()?.mapped.get(anchor);
|
|
1655
|
+
if (floatable == null) {
|
|
1656
|
+
closeAll();
|
|
1657
|
+
return;
|
|
1658
|
+
}
|
|
1659
|
+
const active = Boolean(floatable.active);
|
|
1660
|
+
const content = findAncestor(floatable.options.anchor, SELECTOR_CONTENT$2);
|
|
1661
|
+
if (content == null) closeAll();
|
|
1662
|
+
else closeAbove(content);
|
|
1663
|
+
floatable.toggle(!active);
|
|
1664
|
+
}
|
|
1665
|
+
const AREAS = {
|
|
1666
|
+
above: "block-start",
|
|
1667
|
+
"above-end": "start span-start",
|
|
1668
|
+
"above-start": "start span-end",
|
|
1669
|
+
below: "block-end",
|
|
1670
|
+
"below-end": "end span-start",
|
|
1671
|
+
"below-start": "end span-end",
|
|
1672
|
+
end: "center end",
|
|
1673
|
+
"end-bottom": "span-start end",
|
|
1674
|
+
"end-top": "span-end end",
|
|
1675
|
+
start: "center start",
|
|
1676
|
+
"start-bottom": "span-start start",
|
|
1677
|
+
"start-top": "span-end start"
|
|
1678
|
+
};
|
|
1679
|
+
const ATTRIBUTE_ANCHOR = "oui-floatable-anchor";
|
|
1680
|
+
const ATTRIBUTE_CONTENT$1 = "oui-floatable-content";
|
|
1681
|
+
const ATTRIBUTE_POSITION$1 = "oui-position";
|
|
1682
|
+
const INSERT_AFTEREND = "afterend";
|
|
1683
|
+
const POSITIONS = Object.fromEntries(Object.entries(AREAS).map(([position, area]) => [area, position]));
|
|
1684
|
+
const SELECTOR_ALL = `[${ATTRIBUTE_ANCHOR}], [${ATTRIBUTE_CONTENT$1}]`;
|
|
1685
|
+
const SELECTOR_CONTENT$2 = `[${ATTRIBUTE_CONTENT$1}]`;
|
|
1686
|
+
let index$2 = 0;
|
|
1687
|
+
if (window._oscarpalmer_oui_floatable == null) {
|
|
1688
|
+
Object.defineProperty(window, "_oscarpalmer_oui_floatable", {
|
|
1689
|
+
enumerable: false,
|
|
1690
|
+
value: {
|
|
1691
|
+
active: /* @__PURE__ */ new Set(),
|
|
1692
|
+
mapped: /* @__PURE__ */ new Map(),
|
|
1693
|
+
order: []
|
|
1694
|
+
},
|
|
1695
|
+
writable: false
|
|
1696
|
+
});
|
|
1697
|
+
on(document, "keydown", (event) => {
|
|
1698
|
+
onKeyDown(event);
|
|
1699
|
+
});
|
|
1700
|
+
on(document, "click", (event) => {
|
|
1701
|
+
onClick$1(event);
|
|
1702
|
+
});
|
|
1703
|
+
}
|
|
1704
|
+
//#endregion
|
|
1705
|
+
//#region src/js/popover.ts
|
|
1706
|
+
let index$1 = 0;
|
|
1707
|
+
var OuiPopoverElement = class extends HTMLElement {
|
|
1708
|
+
#floatable;
|
|
1709
|
+
#focusTrap;
|
|
1710
|
+
constructor() {
|
|
1711
|
+
super();
|
|
1712
|
+
const content = this.querySelector(SELECTOR_CONTENT$1);
|
|
1713
|
+
const toggle = this.querySelector(SELECTOR_TOGGLE);
|
|
1714
|
+
if (!(content instanceof HTMLElement)) throw new Error("A oui-popover must have a direct child element with the [oui-popover-content]-attribute");
|
|
1715
|
+
if (!(toggle instanceof HTMLButtonElement)) throw new Error("A oui-popover must have a direct child element with the [oui-popover-toggle]-attribute and be a button");
|
|
1716
|
+
content.hidden = true;
|
|
1717
|
+
content.setAttribute("role", "dialog");
|
|
1718
|
+
content.setAttribute("aria-modal", "true");
|
|
1719
|
+
if (isNullableOrWhitespace(content.id)) content.setAttribute("id", `${ATTRIBUTE_ID_PREFIX}_${++index$1}`);
|
|
1720
|
+
toggle.setAttribute("aria-controls", content.id);
|
|
1721
|
+
toggle.setAttribute("aria-haspopup", "dialog");
|
|
1722
|
+
this.#floatable = new Floatable({
|
|
1723
|
+
content,
|
|
1724
|
+
anchor: toggle,
|
|
1725
|
+
defaultPosition: "below-start",
|
|
1726
|
+
interactive: true,
|
|
1727
|
+
positionAttribute: "position",
|
|
1728
|
+
reusable: false,
|
|
1729
|
+
onAfter: (active) => {
|
|
1730
|
+
if (active) focus(content);
|
|
1731
|
+
else if (!this.#floatable.ignoreFocus) toggle.focus();
|
|
1732
|
+
}
|
|
1733
|
+
});
|
|
1734
|
+
this.#focusTrap = createFocusTrap(content, { noescape: true });
|
|
1735
|
+
POPOVERS.set(toggle, this.#floatable);
|
|
1736
|
+
POPOVERS.set(content, this.#floatable);
|
|
1737
|
+
}
|
|
1738
|
+
close() {
|
|
1739
|
+
this.hidePopover();
|
|
1740
|
+
}
|
|
1741
|
+
connectedCallback() {
|
|
1742
|
+
this.#floatable.enable();
|
|
1743
|
+
this.#focusTrap.connect();
|
|
1744
|
+
}
|
|
1745
|
+
disconnectedCallback() {
|
|
1746
|
+
this.#floatable.disable();
|
|
1747
|
+
this.#focusTrap.disconnect();
|
|
1748
|
+
}
|
|
1749
|
+
hidePopover() {
|
|
1750
|
+
if (this.#floatable.active && this.isConnected) this.#floatable.toggle(false);
|
|
1751
|
+
}
|
|
1752
|
+
open() {
|
|
1753
|
+
this.showPopover();
|
|
1754
|
+
}
|
|
1755
|
+
showPopover() {
|
|
1756
|
+
if (!this.#floatable.active && this.isConnected) this.#floatable.toggle(true);
|
|
1757
|
+
}
|
|
1758
|
+
toggle() {
|
|
1759
|
+
this.togglePopover();
|
|
1760
|
+
}
|
|
1761
|
+
togglePopover(options) {
|
|
1762
|
+
if (typeof options === "boolean") {
|
|
1763
|
+
if (options === true) this.showPopover();
|
|
1764
|
+
else this.hidePopover();
|
|
1765
|
+
return options;
|
|
1766
|
+
}
|
|
1767
|
+
if (this.#floatable.active) {
|
|
1768
|
+
this.hidePopover();
|
|
1769
|
+
return false;
|
|
1770
|
+
}
|
|
1771
|
+
this.showPopover();
|
|
1772
|
+
return true;
|
|
1773
|
+
}
|
|
1774
|
+
};
|
|
1775
|
+
function focus(content) {
|
|
1776
|
+
let target = getFocusable(content)[0];
|
|
1777
|
+
if (!(target instanceof HTMLElement)) target = content;
|
|
1778
|
+
requestAnimationFrame(() => {
|
|
1779
|
+
target.focus();
|
|
1780
|
+
});
|
|
1781
|
+
}
|
|
1782
|
+
const ATTRIBUTE_ID_PREFIX = "oui_popover_content_";
|
|
1783
|
+
const POPOVERS = /* @__PURE__ */ new Map();
|
|
1784
|
+
const SELECTOR$3 = "oui-popover";
|
|
1785
|
+
const SELECTOR_CONTENT$1 = `:scope > [${SELECTOR$3}-content]`;
|
|
1786
|
+
const SELECTOR_TOGGLE = `:scope > [${SELECTOR$3}-toggle]`;
|
|
1787
|
+
customElements.define(SELECTOR$3, OuiPopoverElement);
|
|
1788
|
+
//#endregion
|
|
1789
|
+
//#region node_modules/@oscarpalmer/toretto/dist/attribute/set.attribute.mjs
|
|
1790
|
+
function setAttribute(element, first, second, third) {
|
|
1791
|
+
setElementValue(element, first, second, third, updateAttribute);
|
|
1792
|
+
}
|
|
1793
|
+
function setAttributes(element, attributes, dispatch) {
|
|
1794
|
+
setElementValues(element, attributes, null, dispatch, updateAttribute);
|
|
1795
|
+
}
|
|
1796
|
+
//#endregion
|
|
1797
|
+
//#region node_modules/@oscarpalmer/toretto/dist/property/set.property.mjs
|
|
1798
|
+
/**
|
|
1799
|
+
* Set the values of one or more properties on an element
|
|
1800
|
+
*
|
|
1801
|
+
* Also updates attributes for boolean/dispatchable properties, and if `dispatch` is `true`, will dispatch events for dispatchable properties
|
|
1802
|
+
*
|
|
1803
|
+
* @param target Target element
|
|
1804
|
+
* @param properties Properties to set
|
|
1805
|
+
* @param dispatch Dispatch events for properties? _(defaults to `true`)_
|
|
1806
|
+
*/
|
|
1807
|
+
function setProperties(target, properties, dispatch) {
|
|
1808
|
+
if (!isHTMLOrSVGElement(target) || !isPlainObject(properties)) return;
|
|
1809
|
+
const shouldDispatch = dispatch !== false;
|
|
1810
|
+
const keys = Object.keys(properties);
|
|
1811
|
+
const { length } = keys;
|
|
1812
|
+
for (let index = 0; index < length; index += 1) setPropertyValue(target, keys[index], properties[keys[index]], shouldDispatch);
|
|
1813
|
+
}
|
|
1814
|
+
function setPropertyValue(element, property, value, dispatch) {
|
|
1815
|
+
if (booleanAttributesSet.has(property.toLowerCase()) || dispatchedAttributes.has(property)) setAttribute(element, property, value, dispatch);
|
|
1816
|
+
else updateProperty(element, property, value, dispatch);
|
|
1817
|
+
}
|
|
1818
|
+
//#endregion
|
|
1819
|
+
//#region node_modules/@oscarpalmer/toretto/dist/create.mjs
|
|
1820
|
+
function createElement(tag, properties, attributes, styles) {
|
|
1821
|
+
if (typeof tag !== "string") throw new TypeError(MESSAGE);
|
|
1822
|
+
const element = document.createElement(tag);
|
|
1823
|
+
if (properties != null) setProperties(element, properties);
|
|
1824
|
+
if (attributes != null) setAttributes(element, attributes);
|
|
1825
|
+
if (styles != null) setStyles(element, styles);
|
|
1826
|
+
return element;
|
|
1827
|
+
}
|
|
1828
|
+
const MESSAGE = "Tag name must be a string";
|
|
1829
|
+
//#endregion
|
|
1830
|
+
//#region src/js/sortable.ts
|
|
1831
|
+
var Sortable = class extends Draggable {
|
|
1832
|
+
connections;
|
|
1833
|
+
origin;
|
|
1834
|
+
get dragged() {
|
|
1835
|
+
return getDragPlaceholder();
|
|
1836
|
+
}
|
|
1837
|
+
constructor(element) {
|
|
1838
|
+
super("sort", element, {
|
|
1839
|
+
container: {
|
|
1840
|
+
attribute: ATTRIBUTE_CONTAINER,
|
|
1841
|
+
map: CONTAINERS
|
|
1842
|
+
},
|
|
1843
|
+
direction: { attribute: ATTRIBUTE_DIRECTION },
|
|
1844
|
+
drag: {
|
|
1845
|
+
onBegin,
|
|
1846
|
+
onCancel,
|
|
1847
|
+
onEnd: onEnd$1,
|
|
1848
|
+
onMove
|
|
1849
|
+
},
|
|
1850
|
+
position: {
|
|
1851
|
+
getOffset: getOffsetPosition,
|
|
1852
|
+
getOriginal: getOriginalPosition
|
|
1853
|
+
}
|
|
1854
|
+
});
|
|
1855
|
+
this.connections = this.element.getAttribute(ATTRIBUTE_CONNECTIONS);
|
|
1856
|
+
}
|
|
1857
|
+
};
|
|
1858
|
+
function afterEnd(insert, from, events, elements, position, valid) {
|
|
1859
|
+
elements.origin?.removeAttribute(ATTRIBUTE_ORIGIN);
|
|
1860
|
+
from.origin = void 0;
|
|
1861
|
+
resetPlaceholders();
|
|
1862
|
+
if (!valid || events.some((event) => event.defaultPrevented)) return;
|
|
1863
|
+
if (insert !== "insert") {
|
|
1864
|
+
elements.target.append(elements.origin);
|
|
1865
|
+
return;
|
|
1866
|
+
}
|
|
1867
|
+
if (position == null) return;
|
|
1868
|
+
const { height, top } = elements.target.getBoundingClientRect();
|
|
1869
|
+
let insertion;
|
|
1870
|
+
if (position.y < top + height / 2) insertion = INSERT_BEFORE;
|
|
1871
|
+
else insertion = INSERT_AFTER;
|
|
1872
|
+
elements.target?.insertAdjacentElement(insertion, elements.origin);
|
|
1873
|
+
document.body.removeAttribute(ATTRIBUTE_ACTIVE$1);
|
|
1874
|
+
}
|
|
1875
|
+
function getDragPlaceholder() {
|
|
1876
|
+
placeholder.drag.default ??= createElement("div");
|
|
1877
|
+
return placeholder.drag.custom ?? placeholder.drag.default;
|
|
1878
|
+
}
|
|
1879
|
+
function getOffsetPosition(_, draggable, element, position) {
|
|
1880
|
+
const rectangle = element.getBoundingClientRect();
|
|
1881
|
+
return {
|
|
1882
|
+
x: draggable.horizontal ? 0 : position.x - rectangle.left,
|
|
1883
|
+
y: draggable.vertical ? 0 : position.y - rectangle.top
|
|
1884
|
+
};
|
|
1885
|
+
}
|
|
1886
|
+
function getOriginalPosition(_, __, position) {
|
|
1887
|
+
return position;
|
|
1888
|
+
}
|
|
1889
|
+
function getPositionPlaceholder(sortable) {
|
|
1890
|
+
placeholder.position ??= createElement("div");
|
|
1891
|
+
placeholder.position.setAttribute(ATTRIBUTE_PLACEHOLDER_POSITION, "");
|
|
1892
|
+
if (sortable.origin != null) placeholder.position.style.setProperty("--placeholder-height", `${sortable.origin.getBoundingClientRect().height}px`);
|
|
1893
|
+
return placeholder.position;
|
|
1894
|
+
}
|
|
1895
|
+
function onBegin(_, state, draggable, element) {
|
|
1896
|
+
const sortable = draggable;
|
|
1897
|
+
sortable.origin = element;
|
|
1898
|
+
setPlaceholder(state, sortable, element);
|
|
1899
|
+
element.setAttribute(ATTRIBUTE_ORIGIN, "");
|
|
1900
|
+
document.body.setAttribute(ATTRIBUTE_ACTIVE$1, "");
|
|
1901
|
+
}
|
|
1902
|
+
function onCancel(_, draggable) {
|
|
1903
|
+
const sortable = draggable;
|
|
1904
|
+
const { origin } = sortable;
|
|
1905
|
+
origin?.removeAttribute(ATTRIBUTE_ORIGIN);
|
|
1906
|
+
document.body.removeAttribute(ATTRIBUTE_ACTIVE$1);
|
|
1907
|
+
resetPlaceholders();
|
|
1908
|
+
sortable.origin = void 0;
|
|
1909
|
+
}
|
|
1910
|
+
function onEnd$1(event, state, draggable, reset) {
|
|
1911
|
+
const from = draggable;
|
|
1912
|
+
const { origin } = from;
|
|
1913
|
+
const position = getPosition(event) ?? {
|
|
1914
|
+
x: 0,
|
|
1915
|
+
y: 0
|
|
1916
|
+
};
|
|
1917
|
+
const target = getElementFromPosition(position)[0];
|
|
1918
|
+
let element = findAncestor(target, SELECTOR_ITEM);
|
|
1919
|
+
if (element?.hasAttribute(ATTRIBUTE_PLACEHOLDER_POSITION)) if (element.getAttribute(ATTRIBUTE_PLACEHOLDER_POSITION) === "after") element = element.previousElementSibling;
|
|
1920
|
+
else element = element.nextElementSibling;
|
|
1921
|
+
let insert = "insert";
|
|
1922
|
+
let to;
|
|
1923
|
+
if (element == null) {
|
|
1924
|
+
element = findAncestor(target, SELECTOR$2);
|
|
1925
|
+
to = state.instances.get(element)?.sortable;
|
|
1926
|
+
insert = element == null ? void 0 : element.children.length === 0 ? "append" : "prepend";
|
|
1927
|
+
} else to = state.instances.get(element.parentElement)?.sortable;
|
|
1928
|
+
const valid = insert != null && validatePosition(state, from, to, position);
|
|
1929
|
+
const options = {
|
|
1930
|
+
detail: valid ? {
|
|
1931
|
+
from: {
|
|
1932
|
+
element: origin,
|
|
1933
|
+
position: { ...state.original }
|
|
1934
|
+
},
|
|
1935
|
+
to: {
|
|
1936
|
+
element,
|
|
1937
|
+
position: { ...position }
|
|
1938
|
+
}
|
|
1939
|
+
} : void 0,
|
|
1940
|
+
bubbles: false,
|
|
1941
|
+
cancelable: true
|
|
1942
|
+
};
|
|
1943
|
+
const fromEvent = new CustomEvent(EVENT_END, options);
|
|
1944
|
+
const toEvent = new CustomEvent(EVENT_END, options);
|
|
1945
|
+
from.element.dispatchEvent(fromEvent);
|
|
1946
|
+
if (from !== to) to?.element.dispatchEvent(toEvent);
|
|
1947
|
+
setTimeout(() => {
|
|
1948
|
+
afterEnd(insert, from, [fromEvent, toEvent], {
|
|
1949
|
+
origin,
|
|
1950
|
+
target: element
|
|
1951
|
+
}, position, valid);
|
|
1952
|
+
reset();
|
|
1953
|
+
});
|
|
1954
|
+
}
|
|
1955
|
+
function onMove(event, state, draggable, position) {
|
|
1956
|
+
const from = draggable;
|
|
1957
|
+
const fromElement = from.origin;
|
|
1958
|
+
const toElement = findAncestor(event, SELECTOR_ITEM);
|
|
1959
|
+
let to;
|
|
1960
|
+
if (toElement == null) to = state.instances.get(findAncestor(event, SELECTOR$2))?.sortable;
|
|
1961
|
+
else to = state.instances.get(toElement.parentElement)?.sortable;
|
|
1962
|
+
if (!validatePosition(state, from, to, position.original)) return;
|
|
1963
|
+
const placeholder = getPositionPlaceholder(from);
|
|
1964
|
+
if (toElement != null && toElement !== fromElement) {
|
|
1965
|
+
const { height, top } = toElement.getBoundingClientRect();
|
|
1966
|
+
let place;
|
|
1967
|
+
if (position.calculated.y < top + height / 2) {
|
|
1968
|
+
place = "before";
|
|
1969
|
+
toElement.insertAdjacentElement(INSERT_BEFORE, placeholder);
|
|
1970
|
+
} else {
|
|
1971
|
+
place = "after";
|
|
1972
|
+
toElement.insertAdjacentElement(INSERT_AFTER, placeholder);
|
|
1973
|
+
}
|
|
1974
|
+
placeholder.setAttribute(ATTRIBUTE_PLACEHOLDER_POSITION, place);
|
|
1975
|
+
} else placeholder.remove();
|
|
1976
|
+
return {
|
|
1977
|
+
from: {
|
|
1978
|
+
element: fromElement,
|
|
1979
|
+
position: { ...state.original }
|
|
1980
|
+
},
|
|
1981
|
+
to: {
|
|
1982
|
+
element: toElement,
|
|
1983
|
+
position: { ...position.calculated }
|
|
1984
|
+
}
|
|
1985
|
+
};
|
|
1986
|
+
}
|
|
1987
|
+
function resetPlaceholders() {
|
|
1988
|
+
placeholder.drag.custom?.remove();
|
|
1989
|
+
placeholder.drag.default?.remove();
|
|
1990
|
+
placeholder.position?.remove();
|
|
1991
|
+
placeholder.drag.custom = void 0;
|
|
1992
|
+
}
|
|
1993
|
+
function setPlaceholder(state, sortable, origin) {
|
|
1994
|
+
const element = getDragPlaceholder();
|
|
1995
|
+
placeholder.drag.default.innerHTML = "";
|
|
1996
|
+
updatePlaceholder(sortable, element);
|
|
1997
|
+
const event = new CustomEvent(EVENT_PLACEHOLDER, {
|
|
1998
|
+
cancelable: true,
|
|
1999
|
+
detail: {
|
|
2000
|
+
origin,
|
|
2001
|
+
parent: sortable.element,
|
|
2002
|
+
placeholder: element,
|
|
2003
|
+
create: (value) => {
|
|
2004
|
+
if (!(value instanceof HTMLElement)) return;
|
|
2005
|
+
placeholder.drag.custom = value;
|
|
2006
|
+
updatePlaceholder(sortable, value);
|
|
2007
|
+
state.element = {
|
|
2008
|
+
rectangle: value.getBoundingClientRect(),
|
|
2009
|
+
node: value
|
|
2010
|
+
};
|
|
2011
|
+
}
|
|
2012
|
+
}
|
|
2013
|
+
});
|
|
2014
|
+
sortable.element.dispatchEvent(event);
|
|
2015
|
+
setTimeout(() => {
|
|
2016
|
+
if (!event.defaultPrevented && placeholder.drag.custom == null) placeholder.drag.default?.append(element.cloneNode(true));
|
|
2017
|
+
document.body.append(placeholder.drag.custom ?? placeholder.drag.default ?? "");
|
|
2018
|
+
});
|
|
2019
|
+
}
|
|
2020
|
+
function updatePlaceholder(sortable, element) {
|
|
2021
|
+
element.style.position = "fixed";
|
|
2022
|
+
element.setAttribute(ATTRIBUTE_PLACEHOLDER_DRAG, "");
|
|
2023
|
+
if (sortable.horizontal) element.setAttribute(ATTRIBUTE_HORIZONTAL$1, "");
|
|
2024
|
+
else element.removeAttribute(ATTRIBUTE_HORIZONTAL$1);
|
|
2025
|
+
if (sortable.vertical) element.setAttribute(ATTRIBUTE_VERTICAL, "");
|
|
2026
|
+
else element.removeAttribute(ATTRIBUTE_VERTICAL);
|
|
2027
|
+
}
|
|
2028
|
+
function validatePosition(_, from, to, position) {
|
|
2029
|
+
let valid = true;
|
|
2030
|
+
const rectangle = from.origin?.getBoundingClientRect();
|
|
2031
|
+
if (rectangle != null && !from.horizontal) valid = position.x >= rectangle.left && position.x <= rectangle.right;
|
|
2032
|
+
if (valid && rectangle != null && !from.vertical) valid = position.y >= rectangle.top && position.y <= rectangle.bottom;
|
|
2033
|
+
if (valid && from.connections != null) valid = to?.element.matches(from.connections) ?? true;
|
|
2034
|
+
if (valid && to?.connections != null) valid = from.element.matches(to.connections);
|
|
2035
|
+
return valid;
|
|
2036
|
+
}
|
|
2037
|
+
const ATTRIBUTE$1 = "oui-sortable";
|
|
2038
|
+
const ATTRIBUTE_ACTIVE$1 = `${ATTRIBUTE$1}-active`;
|
|
2039
|
+
const ATTRIBUTE_CONNECTIONS = `${ATTRIBUTE$1}-connections`;
|
|
2040
|
+
const ATTRIBUTE_CONTAINER = `${ATTRIBUTE$1}-container`;
|
|
2041
|
+
const ATTRIBUTE_DIRECTION = `${ATTRIBUTE$1}-direction`;
|
|
2042
|
+
const ATTRIBUTE_HORIZONTAL$1 = `${ATTRIBUTE$1}-horizontal`;
|
|
2043
|
+
const ATTRIBUTE_ORIGIN = `${ATTRIBUTE$1}-origin`;
|
|
2044
|
+
const ATTRIBUTE_PLACEHOLDER_DRAG = `${ATTRIBUTE$1}-placeholder-drag`;
|
|
2045
|
+
const ATTRIBUTE_PLACEHOLDER_POSITION = `${ATTRIBUTE$1}-placeholder-position`;
|
|
2046
|
+
const ATTRIBUTE_VERTICAL = `${ATTRIBUTE$1}-vertical`;
|
|
2047
|
+
const CONTAINERS = /* @__PURE__ */ new Map();
|
|
2048
|
+
const EVENT_END = "sort:end";
|
|
2049
|
+
const EVENT_PLACEHOLDER = "sort:placeholder";
|
|
2050
|
+
const INSERT_AFTER = "afterend";
|
|
2051
|
+
const INSERT_BEFORE = "beforebegin";
|
|
2052
|
+
const SELECTOR$2 = `[${ATTRIBUTE$1}]`;
|
|
2053
|
+
const SELECTOR_ITEM = `[${ATTRIBUTE$1}] > *`;
|
|
2054
|
+
const bound = {
|
|
2055
|
+
constructor: Sortable,
|
|
2056
|
+
property: "sortable"
|
|
2057
|
+
};
|
|
2058
|
+
const placeholder = {
|
|
2059
|
+
drag: {
|
|
2060
|
+
custom: void 0,
|
|
2061
|
+
default: void 0
|
|
2062
|
+
},
|
|
2063
|
+
position: void 0
|
|
2064
|
+
};
|
|
2065
|
+
attributable(ATTRIBUTE$1, addDraggable.bind(bound), removeDraggable.bind(bound));
|
|
2066
|
+
//#endregion
|
|
2067
|
+
//#region node_modules/@oscarpalmer/atoms/dist/math.mjs
|
|
2068
|
+
/**
|
|
2069
|
+
* Round a number
|
|
2070
|
+
*
|
|
2071
|
+
* @param value Number to round
|
|
2072
|
+
* @param decimals Number of decimal places to round to _(defaults to `0`)_
|
|
2073
|
+
* @returns Rounded number, or `Number.NaN` if the value if unable to be rounded
|
|
2074
|
+
*/
|
|
2075
|
+
function round(value, decimals) {
|
|
2076
|
+
return roundNumber(Math.round, value, decimals);
|
|
2077
|
+
}
|
|
2078
|
+
function roundNumber(callback, value, decimals) {
|
|
2079
|
+
if (typeof value !== "number") return NaN;
|
|
2080
|
+
if (typeof decimals !== "number" || decimals < 1) return callback(value);
|
|
2081
|
+
const mod = 10 ** decimals;
|
|
2082
|
+
return callback((value + Number.EPSILON) * mod) / mod;
|
|
2083
|
+
}
|
|
2084
|
+
//#endregion
|
|
2085
|
+
//#region src/js/splitter.ts
|
|
2086
|
+
var OuiSplitterElement = class extends HTMLElement {
|
|
2087
|
+
static observedAttributes = [
|
|
2088
|
+
"max",
|
|
2089
|
+
"min",
|
|
2090
|
+
"size",
|
|
2091
|
+
"type"
|
|
2092
|
+
];
|
|
2093
|
+
#splitter;
|
|
2094
|
+
get max() {
|
|
2095
|
+
return this.#splitter.values.max;
|
|
2096
|
+
}
|
|
2097
|
+
set max(value) {
|
|
2098
|
+
this.setAttribute("max", String(value));
|
|
2099
|
+
}
|
|
2100
|
+
get min() {
|
|
2101
|
+
return this.#splitter.values.min;
|
|
2102
|
+
}
|
|
2103
|
+
set min(value) {
|
|
2104
|
+
this.setAttribute("min", String(value));
|
|
2105
|
+
}
|
|
2106
|
+
get size() {
|
|
2107
|
+
return this.#splitter.values.now.current;
|
|
2108
|
+
}
|
|
2109
|
+
set size(value) {
|
|
2110
|
+
this.setAttribute("size", String(value));
|
|
2111
|
+
}
|
|
2112
|
+
get type() {
|
|
2113
|
+
return this.getAttribute("type") ?? "vertical";
|
|
2114
|
+
}
|
|
2115
|
+
set type(value) {
|
|
2116
|
+
this.setAttribute("type", value);
|
|
2117
|
+
}
|
|
2118
|
+
constructor() {
|
|
2119
|
+
super();
|
|
2120
|
+
const panels = [...this.children].filter((child) => child instanceof HTMLElement);
|
|
2121
|
+
if (panels.length !== 2) throw new Error(`${SELECTOR$1} must have exactly two panels.`);
|
|
2122
|
+
this.#splitter = new Splitter(this, panels);
|
|
2123
|
+
}
|
|
2124
|
+
connectedCallback() {
|
|
2125
|
+
this.#splitter.updateConnections(1);
|
|
2126
|
+
}
|
|
2127
|
+
disconnectedCallback() {
|
|
2128
|
+
this.#splitter.updateConnections(0);
|
|
2129
|
+
}
|
|
2130
|
+
attributeChangedCallback(name) {
|
|
2131
|
+
switch (name) {
|
|
2132
|
+
case "max":
|
|
2133
|
+
case "min":
|
|
2134
|
+
case "size":
|
|
2135
|
+
this.#splitter.updateValues();
|
|
2136
|
+
break;
|
|
2137
|
+
case "type":
|
|
2138
|
+
this.#splitter.updateOrientation();
|
|
2139
|
+
break;
|
|
2140
|
+
default: break;
|
|
2141
|
+
}
|
|
2142
|
+
}
|
|
2143
|
+
};
|
|
2144
|
+
let index = 0;
|
|
2145
|
+
var Splitter = class {
|
|
2146
|
+
element;
|
|
2147
|
+
handle;
|
|
2148
|
+
panels;
|
|
2149
|
+
rectangle;
|
|
2150
|
+
separator;
|
|
2151
|
+
types;
|
|
2152
|
+
values;
|
|
2153
|
+
constructor(element, panels) {
|
|
2154
|
+
this.element = element;
|
|
2155
|
+
this.panels = panels;
|
|
2156
|
+
if (isNullableOrWhitespace(element.id)) element.id = `oui_splitter_${++index}`;
|
|
2157
|
+
this.values = getValues(element);
|
|
2158
|
+
this.handle = createHandle();
|
|
2159
|
+
this.rectangle = element.getBoundingClientRect();
|
|
2160
|
+
this.separator = createSeparator(this);
|
|
2161
|
+
this.separator.append(this.handle);
|
|
2162
|
+
panels[0].insertAdjacentElement("afterend", this.separator);
|
|
2163
|
+
this.updateOrientation();
|
|
2164
|
+
this.updateValues();
|
|
2165
|
+
}
|
|
2166
|
+
updateConnections(add) {
|
|
2167
|
+
const method = METHODS_CONNECT[add];
|
|
2168
|
+
MAPPED_ELEMENTS[method](this.element, this);
|
|
2169
|
+
MAPPED_ELEMENTS[method](this.handle, this);
|
|
2170
|
+
MAPPED_ELEMENTS[method](this.separator, this);
|
|
2171
|
+
if (this.types.auto) RESIZE_OBSERVER[METHODS_OBSERVE[add]](this.element);
|
|
2172
|
+
}
|
|
2173
|
+
updateOrientation() {
|
|
2174
|
+
this.types = getTypes(this);
|
|
2175
|
+
if (this.types.auto) RESIZE_OBSERVER.observe(this.element);
|
|
2176
|
+
else RESIZE_OBSERVER.unobserve(this.element);
|
|
2177
|
+
if (this.types.horizontal) this.element.setAttribute(ATTRIBUTE_HORIZONTAL, "");
|
|
2178
|
+
else this.element.removeAttribute(ATTRIBUTE_HORIZONTAL);
|
|
2179
|
+
setAriaOrientation(this);
|
|
2180
|
+
}
|
|
2181
|
+
updateValues() {
|
|
2182
|
+
this.values = getValues(this.element);
|
|
2183
|
+
requestAnimationFrame(() => {
|
|
2184
|
+
setSize(this, this.values.now.current);
|
|
2185
|
+
setAriaValue(this);
|
|
2186
|
+
});
|
|
2187
|
+
}
|
|
2188
|
+
};
|
|
2189
|
+
function createHandle() {
|
|
2190
|
+
const handle = document.createElement("span");
|
|
2191
|
+
handle.setAttribute("aria-hidden", "true");
|
|
2192
|
+
handle.setAttribute(ATTRIBUTE_HANDLE, "");
|
|
2193
|
+
return handle;
|
|
2194
|
+
}
|
|
2195
|
+
function createSeparator(splitter) {
|
|
2196
|
+
const separator = document.createElement("div");
|
|
2197
|
+
separator.role = "separator";
|
|
2198
|
+
separator.tabIndex = 0;
|
|
2199
|
+
separator.setAttribute("aria-controls", splitter.element.id);
|
|
2200
|
+
separator.setAttribute("aria-label", "Resize panels");
|
|
2201
|
+
separator.setAttribute(ATTRIBUTE_SEPARATOR, "");
|
|
2202
|
+
return separator;
|
|
2203
|
+
}
|
|
2204
|
+
function getContained(min, value, max) {
|
|
2205
|
+
return round(clamp(value, min, max), VALUE_DECIMALS);
|
|
2206
|
+
}
|
|
2207
|
+
function getSize(splitter, value) {
|
|
2208
|
+
const { height, left, top, width } = splitter.rectangle;
|
|
2209
|
+
const fraction = (value - (splitter.types.horizontal ? top : left)) / (splitter.types.horizontal ? height : width);
|
|
2210
|
+
return getContained(splitter.values.min, fraction, splitter.values.max);
|
|
2211
|
+
}
|
|
2212
|
+
function getTypes(splitter, width, height) {
|
|
2213
|
+
const type = splitter.element.getAttribute("type")?.trim() ?? "";
|
|
2214
|
+
if (type === "horizontal") return {
|
|
2215
|
+
auto: false,
|
|
2216
|
+
horizontal: true
|
|
2217
|
+
};
|
|
2218
|
+
if (type === "auto") return {
|
|
2219
|
+
auto: true,
|
|
2220
|
+
horizontal: (height ?? splitter.rectangle.height) > (width ?? splitter.rectangle.width)
|
|
2221
|
+
};
|
|
2222
|
+
return {
|
|
2223
|
+
auto: false,
|
|
2224
|
+
horizontal: false
|
|
2225
|
+
};
|
|
2226
|
+
}
|
|
2227
|
+
function getValue(element, name, defaultValue) {
|
|
2228
|
+
const value = element.getAttribute(name);
|
|
2229
|
+
if (isNullableOrWhitespace(value)) return defaultValue;
|
|
2230
|
+
const parsed = Number.parseFloat(value);
|
|
2231
|
+
if (Number.isNaN(parsed)) return defaultValue;
|
|
2232
|
+
if (parsed < 0) return defaultValue;
|
|
2233
|
+
return parsed > 1 ? parsed / NAVIGATION_MAXIMUM_TOTAL : parsed;
|
|
2234
|
+
}
|
|
2235
|
+
function getValues(element) {
|
|
2236
|
+
const values = {
|
|
2237
|
+
max: getValue(element, "max", NAVIGATION_MAXIMUM_PERCENTAGE),
|
|
2238
|
+
min: getValue(element, "min", NAVIGATION_MINIMUM_PERCENTAGE),
|
|
2239
|
+
now: {
|
|
2240
|
+
current: .5,
|
|
2241
|
+
previous: .5
|
|
2242
|
+
}
|
|
2243
|
+
};
|
|
2244
|
+
const value = getContained(values.min, getValue(element, "size", values.now.current), values.max);
|
|
2245
|
+
values.now.current = value;
|
|
2246
|
+
values.now.previous = value;
|
|
2247
|
+
return values;
|
|
2248
|
+
}
|
|
2249
|
+
function onEnd(reset) {
|
|
2250
|
+
if (splitter == null) return;
|
|
2251
|
+
splitter.handle.removeAttribute(ATTRIBUTE_ACTIVE);
|
|
2252
|
+
splitter.separator.removeAttribute(ATTRIBUTE_ACTIVE);
|
|
2253
|
+
if (reset) setSize(splitter, splitter.values.now.previous);
|
|
2254
|
+
else splitter.values.now.previous = splitter.values.now.current;
|
|
2255
|
+
splitter = void 0;
|
|
2256
|
+
STYLING_TOGGLER.remove();
|
|
2257
|
+
}
|
|
2258
|
+
function onKeydown(event) {
|
|
2259
|
+
switch (true) {
|
|
2260
|
+
case KEYS_ALL.has(event.key):
|
|
2261
|
+
onNavigate(event);
|
|
2262
|
+
break;
|
|
2263
|
+
case event.key === "Escape":
|
|
2264
|
+
onEnd(true);
|
|
2265
|
+
break;
|
|
2266
|
+
default: break;
|
|
2267
|
+
}
|
|
2268
|
+
}
|
|
2269
|
+
function onNavigate(event) {
|
|
2270
|
+
const splitter = MAPPED_ELEMENTS.get(findAncestor(event, "[oui-splitter-separator]"));
|
|
2271
|
+
if (splitter == null) return;
|
|
2272
|
+
const { types, values } = splitter;
|
|
2273
|
+
if (KEYS_ABSOLUTE.has(event.key)) {
|
|
2274
|
+
setSize(splitter, event.key === "End" ? values.max : values.min, true);
|
|
2275
|
+
return;
|
|
2276
|
+
}
|
|
2277
|
+
if (types.horizontal && !KEYS_HORIZONTAL.has(event.key) || !(types.horizontal || KEYS_VERTICAL.has(event.key))) return;
|
|
2278
|
+
const offset = KEYS_NEGATIVE.has(event.key) ? -1 : 1;
|
|
2279
|
+
setSize(splitter, getContained(values.min, values.now.current + offset * NAVIGATION_MODIFIER, values.max), true);
|
|
2280
|
+
}
|
|
2281
|
+
function onObservation(entries) {
|
|
2282
|
+
if (frame != null) cancelAnimationFrame(frame);
|
|
2283
|
+
frame = requestAnimationFrame(() => {
|
|
2284
|
+
for (const entry of entries) {
|
|
2285
|
+
const splitter = MAPPED_ELEMENTS.get(entry.target);
|
|
2286
|
+
if (splitter == null) return;
|
|
2287
|
+
splitter.types = getTypes(splitter, entry.contentRect.width, entry.contentRect.height);
|
|
2288
|
+
if (splitter.types.horizontal) splitter.element.setAttribute(ATTRIBUTE_HORIZONTAL, "");
|
|
2289
|
+
else splitter.element.removeAttribute(ATTRIBUTE_HORIZONTAL);
|
|
2290
|
+
setAriaOrientation(splitter);
|
|
2291
|
+
}
|
|
2292
|
+
frame = void 0;
|
|
2293
|
+
});
|
|
2294
|
+
}
|
|
2295
|
+
function onPointerdown(event) {
|
|
2296
|
+
if (supportsTouch.value ? event.type === "mousedown" : event.type === "touchstart") return;
|
|
2297
|
+
splitter = MAPPED_ELEMENTS.get(findAncestor(event, SELECTOR_HANDLE));
|
|
2298
|
+
if (splitter == null) return;
|
|
2299
|
+
if (supportsTouch.value) event.preventDefault();
|
|
2300
|
+
splitter.handle.setAttribute(ATTRIBUTE_ACTIVE, "");
|
|
2301
|
+
splitter.separator.setAttribute(ATTRIBUTE_ACTIVE, "");
|
|
2302
|
+
splitter.rectangle = splitter.element.getBoundingClientRect();
|
|
2303
|
+
STYLING_TOGGLER.set();
|
|
2304
|
+
}
|
|
2305
|
+
function onPointermove(event) {
|
|
2306
|
+
if (splitter == null) return;
|
|
2307
|
+
const position = getPosition(event);
|
|
2308
|
+
if (position != null) {
|
|
2309
|
+
splitter.values.now.current = getSize(splitter, splitter.types.horizontal ? position.y : position.x);
|
|
2310
|
+
setSize(splitter, splitter.values.now.current);
|
|
2311
|
+
}
|
|
2312
|
+
}
|
|
2313
|
+
function onPointerup() {
|
|
2314
|
+
if (splitter != null) onEnd(false);
|
|
2315
|
+
}
|
|
2316
|
+
function setAriaOrientation(splitter) {
|
|
2317
|
+
splitter.separator.setAttribute("aria-orientation", splitter.types.horizontal ? "horizontal" : "vertical");
|
|
2318
|
+
}
|
|
2319
|
+
function setAriaValue(splitter) {
|
|
2320
|
+
splitter.separator.setAttribute("aria-valuemax", String(splitter.values.max));
|
|
2321
|
+
splitter.separator.setAttribute("aria-valuemin", String(splitter.values.min));
|
|
2322
|
+
splitter.separator.setAttribute("aria-valuenow", String(splitter.values.now.current));
|
|
2323
|
+
}
|
|
2324
|
+
function setSize(splitter, size, previous) {
|
|
2325
|
+
splitter.values.now.current = size;
|
|
2326
|
+
if (previous) splitter.values.now.previous = size;
|
|
2327
|
+
splitter.element.style.setProperty("--oui-splitter-size", `${size}`);
|
|
2328
|
+
setAriaValue(splitter);
|
|
2329
|
+
}
|
|
2330
|
+
const SELECTOR$1 = "oui-splitter";
|
|
2331
|
+
const ATTRIBUTE_ACTIVE = `${SELECTOR$1}-active`;
|
|
2332
|
+
const ATTRIBUTE_HANDLE = `${SELECTOR$1}-handle`;
|
|
2333
|
+
const ATTRIBUTE_HORIZONTAL = `${SELECTOR$1}-horizontal`;
|
|
2334
|
+
const ATTRIBUTE_SEPARATOR = `${SELECTOR$1}-separator`;
|
|
2335
|
+
const KEYS_ABSOLUTE = new Set(["End", "Home"]);
|
|
2336
|
+
const KEYS_HORIZONTAL = new Set(["ArrowDown", "ArrowUp"]);
|
|
2337
|
+
const KEYS_NEGATIVE = new Set(["ArrowLeft", "ArrowUp"]);
|
|
2338
|
+
const KEYS_VERTICAL = new Set(["ArrowLeft", "ArrowRight"]);
|
|
2339
|
+
const KEYS_ALL = new Set([
|
|
2340
|
+
...KEYS_ABSOLUTE,
|
|
2341
|
+
...KEYS_HORIZONTAL,
|
|
2342
|
+
...KEYS_VERTICAL
|
|
2343
|
+
]);
|
|
2344
|
+
const MAPPED_ELEMENTS = /* @__PURE__ */ new WeakMap();
|
|
2345
|
+
const METHODS_CONNECT = ["delete", "set"];
|
|
2346
|
+
const METHODS_OBSERVE = ["unobserve", "observe"];
|
|
2347
|
+
const NAVIGATION_MAXIMUM_PERCENTAGE = .9;
|
|
2348
|
+
const NAVIGATION_MAXIMUM_TOTAL = 100;
|
|
2349
|
+
const NAVIGATION_MINIMUM_PERCENTAGE = .1;
|
|
2350
|
+
const NAVIGATION_MODIFIER = .05;
|
|
2351
|
+
const RESIZE_OBSERVER = new ResizeObserver(onObservation);
|
|
2352
|
+
const SELECTOR_HANDLE = `[${ATTRIBUTE_HANDLE}]`;
|
|
2353
|
+
const STYLING_TOGGLER = toggleStyles(document.body, {
|
|
2354
|
+
touchAction: "none",
|
|
2355
|
+
userSelect: "none",
|
|
2356
|
+
webkitUserSelect: "none"
|
|
2357
|
+
});
|
|
2358
|
+
const VALUE_DECIMALS = 6;
|
|
2359
|
+
let frame;
|
|
2360
|
+
let splitter;
|
|
2361
|
+
customElements.define(SELECTOR$1, OuiSplitterElement);
|
|
2362
|
+
on(document, "keydown", onKeydown);
|
|
2363
|
+
on(document, "mousedown", onPointerdown);
|
|
2364
|
+
on(document, "pointermove", onPointermove);
|
|
2365
|
+
on(document, "pointerup", onPointerup);
|
|
2366
|
+
on(document, "touchcancel", onPointerup, { passive: false });
|
|
2367
|
+
on(document, "touchstart", onPointerdown, { passive: false });
|
|
2368
|
+
//#endregion
|
|
2369
|
+
//#region src/js/tooltip.ts
|
|
2370
|
+
var Tooltip = class {
|
|
2371
|
+
elements;
|
|
2372
|
+
floatable;
|
|
2373
|
+
constructor(anchor, elements) {
|
|
2374
|
+
const content = getContent();
|
|
2375
|
+
this.elements = elements;
|
|
2376
|
+
this.floatable = new Floatable({
|
|
2377
|
+
anchor,
|
|
2378
|
+
content,
|
|
2379
|
+
defaultPosition: "above",
|
|
2380
|
+
interactive: false,
|
|
2381
|
+
positionAttribute: ATTRIBUTE_POSITION,
|
|
2382
|
+
reusable: true,
|
|
2383
|
+
onAfter: (active) => {
|
|
2384
|
+
if (active) {
|
|
2385
|
+
content.innerHTML = "";
|
|
2386
|
+
content.append(...this.elements);
|
|
2387
|
+
}
|
|
2388
|
+
if (active || TOOLTIPS_ACTIVE.size > 0) return;
|
|
2389
|
+
content.removeAttribute(ATTRIBUTE_CONTENT_ACTIVE);
|
|
2390
|
+
contentTimer = setTimeout(() => {
|
|
2391
|
+
content.innerHTML = "";
|
|
2392
|
+
content.remove();
|
|
2393
|
+
}, delayClose);
|
|
2394
|
+
}
|
|
2395
|
+
});
|
|
2396
|
+
}
|
|
2397
|
+
destroy() {
|
|
2398
|
+
const { floatable } = this;
|
|
2399
|
+
TOOLTIPS_ACTIVE.delete(this);
|
|
2400
|
+
TOOLTIPS_PENDING.delete(this);
|
|
2401
|
+
TOOLTIPS_ALL.delete(floatable.options.anchor);
|
|
2402
|
+
TOOLTIPS_ALL.delete(floatable.options.content);
|
|
2403
|
+
floatable.destroy();
|
|
2404
|
+
this.elements = [];
|
|
2405
|
+
this.floatable = void 0;
|
|
2406
|
+
}
|
|
2407
|
+
};
|
|
2408
|
+
function addTooltip(anchor) {
|
|
2409
|
+
if (TOOLTIPS_ALL.has(anchor)) return;
|
|
2410
|
+
const elements = getElements(anchor);
|
|
2411
|
+
if (elements != null) TOOLTIPS_ALL.set(anchor, new Tooltip(anchor, elements));
|
|
2412
|
+
}
|
|
2413
|
+
function closeTooltips(current) {
|
|
2414
|
+
const pending = [...TOOLTIPS_PENDING];
|
|
2415
|
+
for (const item of pending) {
|
|
2416
|
+
if (item === current) continue;
|
|
2417
|
+
TOOLTIPS_PENDING.delete(item);
|
|
2418
|
+
}
|
|
2419
|
+
const active = [...TOOLTIPS_ACTIVE];
|
|
2420
|
+
for (const item of active) {
|
|
2421
|
+
if (item === current) continue;
|
|
2422
|
+
TOOLTIPS_ACTIVE.delete(item);
|
|
2423
|
+
item.floatable.toggle(false);
|
|
2424
|
+
}
|
|
2425
|
+
}
|
|
2426
|
+
function getElements(anchor) {
|
|
2427
|
+
let elements = findElements(anchor.getAttribute(ARIA_LABELLEDBY));
|
|
2428
|
+
if (elements.length > 0) return elements.map((element) => element.cloneNode(true));
|
|
2429
|
+
elements = findElements(anchor.getAttribute(ARIA_DESCRIBEDBY));
|
|
2430
|
+
if (elements.length > 0) return elements.map((element) => element.cloneNode(true));
|
|
2431
|
+
let content = anchor.getAttribute(ARIA_LABEL);
|
|
2432
|
+
if (isNullableOrWhitespace(content)) content = anchor.getAttribute(ARIA_DESCRIPTION);
|
|
2433
|
+
if (isNullableOrWhitespace(content)) return;
|
|
2434
|
+
const paragraph = document.createElement("p");
|
|
2435
|
+
paragraph.textContent = content;
|
|
2436
|
+
return [paragraph];
|
|
2437
|
+
}
|
|
2438
|
+
function findElements(attribute) {
|
|
2439
|
+
const ids = attribute?.split(EXPRESSION_WHITESPACE) ?? [];
|
|
2440
|
+
const elements = [];
|
|
2441
|
+
for (const id of ids) {
|
|
2442
|
+
if (isNullableOrWhitespace(id)) continue;
|
|
2443
|
+
const element = document.querySelector(`#${id}`);
|
|
2444
|
+
if (element instanceof HTMLElement) {
|
|
2445
|
+
const cloned = element.cloneNode(true);
|
|
2446
|
+
cloned.hidden = false;
|
|
2447
|
+
elements.push(cloned);
|
|
2448
|
+
}
|
|
2449
|
+
}
|
|
2450
|
+
return elements;
|
|
2451
|
+
}
|
|
2452
|
+
function getContent() {
|
|
2453
|
+
if (contentElement != null) return contentElement;
|
|
2454
|
+
contentElement = document.createElement("div");
|
|
2455
|
+
contentElement.setAttribute(ATTRIBUTE_CONTENT, "");
|
|
2456
|
+
contentElement.role = "tooltip";
|
|
2457
|
+
contentElement.tabIndex = -1;
|
|
2458
|
+
return contentElement;
|
|
2459
|
+
}
|
|
2460
|
+
function onActivate(event) {
|
|
2461
|
+
onToggle(event, true);
|
|
2462
|
+
}
|
|
2463
|
+
function onChange() {
|
|
2464
|
+
if (TOOLTIPS_ACTIVE.size === 0) return;
|
|
2465
|
+
}
|
|
2466
|
+
function onClick(event) {
|
|
2467
|
+
if (findAncestor(event, SELECTOR_CONTENT) != null) event.stopPropagation();
|
|
2468
|
+
}
|
|
2469
|
+
function onDeactivate(event) {
|
|
2470
|
+
onToggle(event, false);
|
|
2471
|
+
}
|
|
2472
|
+
function onToggle(event, activate) {
|
|
2473
|
+
if (toggle != null) cancelAnimationFrame(toggle);
|
|
2474
|
+
if (findAncestor(event, SELECTOR_CONTENT) != null) {
|
|
2475
|
+
if (contentTimer != null) clearTimeout(contentTimer);
|
|
2476
|
+
return;
|
|
2477
|
+
}
|
|
2478
|
+
toggle = requestAnimationFrame(() => {
|
|
2479
|
+
toggle = void 0;
|
|
2480
|
+
const element = findAncestor(event, SELECTOR);
|
|
2481
|
+
const tooltip = TOOLTIPS_ALL.get(element);
|
|
2482
|
+
if (TOOLTIPS_ACTIVE.size > 0 || TOOLTIPS_PENDING.size > 0) closeTooltips(tooltip);
|
|
2483
|
+
if (tooltip == null || tooltip.floatable.active === activate) return;
|
|
2484
|
+
if (activate) {
|
|
2485
|
+
clearTimeout(contentTimer);
|
|
2486
|
+
TOOLTIPS_PENDING.add(tooltip);
|
|
2487
|
+
contentTimer = setTimeout(() => {
|
|
2488
|
+
TOOLTIPS_ACTIVE.add(tooltip);
|
|
2489
|
+
TOOLTIPS_PENDING.delete(tooltip);
|
|
2490
|
+
tooltip.floatable.options.content.style.positionAnchor = tooltip.floatable.options.anchor.style.anchorName;
|
|
2491
|
+
tooltip.floatable.toggle(true);
|
|
2492
|
+
setTimeout(() => {
|
|
2493
|
+
tooltip.floatable.options.content.setAttribute(ATTRIBUTE_CONTENT_ACTIVE, "");
|
|
2494
|
+
});
|
|
2495
|
+
}, delayOpen);
|
|
2496
|
+
return;
|
|
2497
|
+
}
|
|
2498
|
+
TOOLTIPS_ACTIVE.delete(tooltip);
|
|
2499
|
+
tooltip.floatable.toggle(false);
|
|
2500
|
+
});
|
|
2501
|
+
}
|
|
2502
|
+
function removeTooltip(element) {
|
|
2503
|
+
if (!element.hasAttribute(ATTRIBUTE_CONTENT)) TOOLTIPS_ALL.get(element)?.destroy();
|
|
2504
|
+
}
|
|
2505
|
+
function setTooltipDelay(open, close) {
|
|
2506
|
+
delayClose = typeof close === "number" && close >= 0 ? close : delayClose;
|
|
2507
|
+
delayOpen = typeof open === "number" && open >= 0 ? open : delayOpen;
|
|
2508
|
+
}
|
|
2509
|
+
const ARIA_DESCRIBEDBY = "aria-describedby";
|
|
2510
|
+
const ARIA_DESCRIPTION = "aria-description";
|
|
2511
|
+
const ARIA_LABEL = "aria-label";
|
|
2512
|
+
const ARIA_LABELLEDBY = "aria-labelledby";
|
|
2513
|
+
const ATTRIBUTE = "oui-tooltip";
|
|
2514
|
+
const ATTRIBUTE_CONTENT = `${ATTRIBUTE}-content`;
|
|
2515
|
+
const ATTRIBUTE_CONTENT_ACTIVE = `${ATTRIBUTE_CONTENT}-active`;
|
|
2516
|
+
const ATTRIBUTE_POSITION = `${ATTRIBUTE}-position`;
|
|
2517
|
+
const SELECTOR = `[${ATTRIBUTE}]`;
|
|
2518
|
+
const SELECTOR_CONTENT = `[${ATTRIBUTE_CONTENT}]`;
|
|
2519
|
+
const EXPRESSION_WHITESPACE = /\s+/;
|
|
2520
|
+
const TOOLTIPS_ACTIVE = /* @__PURE__ */ new Set();
|
|
2521
|
+
const TOOLTIPS_ALL = /* @__PURE__ */ new WeakMap();
|
|
2522
|
+
const TOOLTIPS_PENDING = /* @__PURE__ */ new Set();
|
|
2523
|
+
let contentElement;
|
|
2524
|
+
let contentTimer;
|
|
2525
|
+
let delayClose = 250;
|
|
2526
|
+
let delayOpen = 500;
|
|
2527
|
+
let toggle;
|
|
2528
|
+
attributable(ATTRIBUTE, addTooltip, removeTooltip);
|
|
2529
|
+
on(document, "click", onClick, { capture: true });
|
|
2530
|
+
on(document, "focusin", onActivate);
|
|
2531
|
+
on(document, "focusout", onDeactivate);
|
|
2532
|
+
on(document, "mousemove", onActivate);
|
|
2533
|
+
on(window, "resize", onChange);
|
|
2534
|
+
on(document, "scroll", onChange);
|
|
2535
|
+
on(document, "touchstart", onActivate);
|
|
2536
|
+
//#endregion
|
|
7
2537
|
export { OuiPopoverElement, OuiSplitterElement, setTooltipDelay };
|