@oscarpalmer/oui 0.22.0 → 0.22.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/js/index.mjs CHANGED
@@ -1,2537 +1,7 @@
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
1
+ import "./focus-trap/standalone.mjs";
2
+ import "./movable.mjs";
3
+ import { OuiPopoverElement } from "./popover.mjs";
4
+ import "./sortable.mjs";
5
+ import { OuiSplitterElement } from "./splitter.mjs";
6
+ import { setTooltipDelay } from "./tooltip.mjs";
2537
7
  export { OuiPopoverElement, OuiSplitterElement, setTooltipDelay };