@oscarpalmer/oui 0.18.0 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/dist/css/badge.css +10 -10
  2. package/dist/css/button.css +9 -9
  3. package/dist/css/color.css +99 -99
  4. package/dist/css/content.css +1 -1
  5. package/dist/css/flex.css +39 -39
  6. package/dist/css/form.css +29 -56
  7. package/dist/css/message.css +6 -6
  8. package/dist/css/reset.css +3 -2
  9. package/dist/css/table.css +4 -4
  10. package/dist/css/tooltip.css +18 -1
  11. package/dist/js/attributable.full.js +29 -41
  12. package/dist/js/floatable.full.js +322 -337
  13. package/dist/js/focus-trap/embedded.full.js +252 -195
  14. package/dist/js/focus-trap/standalone.full.js +283 -238
  15. package/dist/js/index.js +3 -3
  16. package/dist/js/oui.full.js +1170 -1193
  17. package/dist/js/popover.full.js +568 -630
  18. package/dist/js/popover.js +1 -1
  19. package/dist/js/splitter.full.js +533 -369
  20. package/dist/js/splitter.js +2 -2
  21. package/dist/js/tooltip.full.js +488 -554
  22. package/dist/js/tooltip.js +1 -1
  23. package/package.json +19 -19
  24. package/src/css/a11y.scss +1 -1
  25. package/src/css/badge.scss +23 -19
  26. package/src/css/button.scss +9 -9
  27. package/src/css/color.scss +99 -99
  28. package/src/css/content.scss +6 -8
  29. package/src/css/flex.scss +21 -20
  30. package/src/css/form.scss +37 -60
  31. package/src/css/message.scss +8 -12
  32. package/src/css/mixins.scss +11 -12
  33. package/src/css/popover.scss +2 -2
  34. package/src/css/reset.scss +14 -14
  35. package/src/css/splitter.scss +15 -13
  36. package/src/css/table.scss +11 -11
  37. package/src/css/tooltip.scss +25 -4
  38. package/src/js/attributable.ts +3 -10
  39. package/src/js/floatable.ts +7 -25
  40. package/src/js/focus-trap/embedded.ts +6 -24
  41. package/src/js/popover.ts +3 -3
  42. package/src/js/splitter.ts +9 -39
  43. package/src/js/tooltip.ts +5 -17
  44. package/dist/css/value.css +0 -1
@@ -7,44 +7,42 @@ function isPlainObject(value) {
7
7
  const prototype = Object.getPrototypeOf(value);
8
8
  return prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null;
9
9
  }
10
-
11
10
  function compact(array, strict) {
12
11
  if (!Array.isArray(array)) return [];
12
+ if (strict === true) return array.filter(Boolean);
13
13
  const { length } = array;
14
14
  const compacted = [];
15
- for (let index = 0; index < length; index += 1) {
16
- const item = array[index];
15
+ for (let index$1 = 0; index$1 < length; index$1 += 1) {
16
+ const item = array[index$1];
17
17
  if (item != null) compacted.push(item);
18
18
  }
19
19
  return compacted;
20
20
  }
21
-
22
21
  function getString(value) {
23
22
  if (typeof value === "string") return value;
24
23
  if (value == null) return "";
24
+ if (typeof value === "function") return getString(value());
25
25
  if (typeof value !== "object") return String(value);
26
26
  const asString = String(value.valueOf?.() ?? value);
27
27
  return asString.startsWith("[object ") ? JSON.stringify(value) : asString;
28
28
  }
29
29
  function join(value, delimiter) {
30
- return compact(value).map(getString).join(delimiter );
30
+ return compact(value).map(getString).join(typeof delimiter === "string" ? delimiter : "");
31
31
  }
32
32
  function words(value) {
33
33
  return typeof value === "string" ? value.match(EXPRESSION_WORDS) ?? [] : [];
34
34
  }
35
35
  var EXPRESSION_WORDS = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;
36
-
37
36
  function isNullableOrWhitespace(value) {
38
37
  return value == null || EXPRESSION_WHITESPACE.test(getString(value));
39
38
  }
40
39
  var EXPRESSION_WHITESPACE = /^\s*$/;
41
-
42
40
  function round(value, decimals) {
43
41
  if (typeof value !== "number") return NaN;
42
+ if (typeof decimals !== "number" || decimals < 1) return Math.round(value);
44
43
  const mod = 10 ** decimals;
45
44
  return Math.round((value + Number.EPSILON) * mod) / mod;
46
45
  }
47
-
48
46
  function clamp(value, minimum, maximum, loop) {
49
47
  if (![
50
48
  value,
@@ -54,46 +52,166 @@ function clamp(value, minimum, maximum, loop) {
54
52
  if (value < minimum) return loop === true ? maximum : minimum;
55
53
  return value > maximum ? loop === true ? minimum : maximum : value;
56
54
  }
57
-
58
- function isEventTarget(value) {
59
- return typeof value === "object" && value != null && typeof value.addEventListener === "function" && typeof value.removeEventListener === "function" && typeof value.dispatchEvent === "function";
55
+ function noop() {}
56
+ function calculate() {
57
+ return new Promise((resolve) => {
58
+ const values = [];
59
+ let last;
60
+ function step(now) {
61
+ if (last != null) values.push(now - last);
62
+ last = now;
63
+ if (values.length >= TOTAL) resolve(values.sort().slice(TRIM_PART, -TRIM_PART).reduce((first, second) => first + second, 0) / (values.length - TRIM_TOTAL));
64
+ else requestAnimationFrame(step);
65
+ }
66
+ requestAnimationFrame(step);
67
+ });
60
68
  }
61
- function isHTMLOrSVGElement(value) {
62
- return value instanceof HTMLElement || value instanceof SVGElement;
69
+ var TOTAL = 10;
70
+ var TRIM_PART = 2;
71
+ var TRIM_TOTAL = 4;
72
+ await calculate();
73
+ var SizedMap = class extends Map {
74
+ #maximumSize;
75
+ get full() {
76
+ return this.size >= this.#maximumSize;
77
+ }
78
+ get maximum() {
79
+ return this.#maximumSize;
80
+ }
81
+ constructor(first, second) {
82
+ const maximum = getMaximum(first, second);
83
+ super();
84
+ this.#maximumSize = maximum;
85
+ if (Array.isArray(first)) {
86
+ const { length } = first;
87
+ if (length <= maximum) for (let index$1 = 0; index$1 < length; index$1 += 1) this.set(...first[index$1]);
88
+ else for (let index$1 = 0; index$1 < maximum; index$1 += 1) this.set(...first[length - maximum + index$1]);
89
+ }
90
+ }
91
+ get(key) {
92
+ const value = super.get(key);
93
+ if (value !== void 0 || this.has(key)) this.set(key, value);
94
+ return value;
95
+ }
96
+ set(key, value) {
97
+ if (this.has(key)) this.delete(key);
98
+ else if (this.size >= this.#maximumSize) this.delete(this.keys().next().value);
99
+ return super.set(key, value);
100
+ }
101
+ };
102
+ function getMaximum(first, second) {
103
+ let actual;
104
+ if (typeof first === "number") actual = first;
105
+ else actual = typeof second === "number" ? second : MAXIMUM_DEFAULT;
106
+ return clamp(actual, 1, MAXIMUM_ABSOLUTE);
107
+ }
108
+ var MAXIMUM_ABSOLUTE = 16777216;
109
+ var MAXIMUM_DEFAULT = 1048576;
110
+ var Memoized = class {
111
+ #state;
112
+ get maximum() {
113
+ return this.#state.cache?.maximum ?? NaN;
114
+ }
115
+ get size() {
116
+ return this.#state.cache?.size ?? NaN;
117
+ }
118
+ constructor(callback, options) {
119
+ const cache = new SizedMap(options.cacheSize);
120
+ const getter = (...parameters) => {
121
+ const key = options.cacheKey?.(...parameters) ?? (parameters.length === 1 ? parameters[0] : join(parameters.map(getString), "_"));
122
+ if (cache.has(key)) return cache.get(key);
123
+ const value = callback(...parameters);
124
+ cache.set(key, value);
125
+ return value;
126
+ };
127
+ this.#state = {
128
+ cache,
129
+ getter
130
+ };
131
+ }
132
+ clear() {
133
+ this.#state.cache?.clear();
134
+ }
135
+ delete(key) {
136
+ return this.#state.cache?.delete(key) ?? false;
137
+ }
138
+ destroy() {
139
+ this.#state.cache?.clear();
140
+ this.#state.cache = void 0;
141
+ this.#state.getter = void 0;
142
+ }
143
+ get(key) {
144
+ return this.#state.cache?.get(key);
145
+ }
146
+ has(key) {
147
+ return this.#state.cache?.has(key) ?? false;
148
+ }
149
+ run(...parameters) {
150
+ if (this.#state.cache == null || this.#state.getter == null) throw new Error("The Memoized instance has been destroyed");
151
+ return this.#state.getter(...parameters);
152
+ }
153
+ };
154
+ function getMemoizationOptions(input) {
155
+ const { cacheKey, cacheSize } = isPlainObject(input) ? input : {};
156
+ return {
157
+ cacheKey: typeof cacheKey === "function" ? cacheKey : void 0,
158
+ cacheSize: typeof cacheSize === "number" && cacheSize > 0 ? cacheSize : DEFAULT_CACHE_SIZE
159
+ };
160
+ }
161
+ function memoize(callback, options) {
162
+ return new Memoized(callback, getMemoizationOptions(options));
63
163
  }
64
-
164
+ var DEFAULT_CACHE_SIZE = 1024;
65
165
  function camelCase(value) {
66
- return toCase(value, "");
166
+ return toCase("camel", value, true, false);
67
167
  }
68
168
  function capitalize(value) {
69
169
  if (typeof value !== "string" || value.length === 0) return "";
70
- return value.length === 1 ? value.toLocaleUpperCase() : `${value.charAt(0).toLocaleUpperCase()}${value.slice(1).toLocaleLowerCase()}`;
71
- }
72
- function toCase(value, delimiter, capitalizeAny, capitalizeFirst) {
170
+ memoizedCapitalize ??= memoize((v) => v.length === 1 ? v.toLocaleUpperCase() : `${v.charAt(0).toLocaleUpperCase()}${v.slice(1).toLocaleLowerCase()}`);
171
+ return memoizedCapitalize.run(value);
172
+ }
173
+ function toCase(type, value, capitalizeAny, capitalizeFirst) {
174
+ memoizers[type] ??= memoize(toCaseCallback.bind({
175
+ type,
176
+ capitalizeAny,
177
+ capitalizeFirst
178
+ }));
179
+ return memoizers[type].run(value);
180
+ }
181
+ function toCaseCallback(value) {
73
182
  if (typeof value !== "string") return "";
74
183
  if (value.length < 1) return value;
184
+ const { capitalizeAny, capitalizeFirst, type } = this;
75
185
  const parts = words(value);
76
186
  const partsLength = parts.length;
77
187
  const result = [];
78
188
  for (let partIndex = 0; partIndex < partsLength; partIndex += 1) {
79
- const items = parts[partIndex].replace(EXPRESSION_ACRONYM, (full, one, two, three) => three === "s" ? full : `${one}-${two}${three}`).replace(EXPRESSION_CAMEL_CASE, "$1-$2").split("-");
189
+ 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("-");
80
190
  const itemsLength = items.length;
81
191
  const partResult = [];
82
192
  let itemCount = 0;
83
193
  for (let itemIndex = 0; itemIndex < itemsLength; itemIndex += 1) {
84
194
  const item = items[itemIndex];
85
195
  if (item.length === 0) continue;
86
- if (itemCount === 0 && partIndex === 0 && true) partResult.push(item.toLocaleLowerCase());
196
+ if (!capitalizeAny || itemCount === 0 && partIndex === 0 && !capitalizeFirst) partResult.push(item.toLocaleLowerCase());
87
197
  else partResult.push(capitalize(item));
88
198
  itemCount += 1;
89
199
  }
90
- result.push(join(partResult, delimiter));
200
+ result.push(join(partResult, delimiters[type]));
91
201
  }
92
- return join(result, delimiter);
202
+ return join(result, delimiters[type]);
93
203
  }
94
204
  var EXPRESSION_CAMEL_CASE = /(\p{Ll})(\p{Lu})/gu;
95
205
  var EXPRESSION_ACRONYM = /(\p{Lu}*)(\p{Lu})(\p{Ll}+)/gu;
96
-
206
+ var REPLACEMENT_CAMEL_CASE = "$1-$2";
207
+ var delimiters = {
208
+ camel: "",
209
+ kebab: "-",
210
+ pascal: "",
211
+ snake: "_"
212
+ };
213
+ var memoizers = {};
214
+ var memoizedCapitalize;
97
215
  function getBoolean(value, defaultValue) {
98
216
  return typeof value === "boolean" ? value : defaultValue ?? false;
99
217
  }
@@ -101,34 +219,99 @@ function getStyleValue(element, property, computed) {
101
219
  const name = camelCase(property);
102
220
  return computed ? getComputedStyle(element)[name] : element.style[name];
103
221
  }
104
-
105
- function calculate() {
106
- return new Promise((resolve) => {
107
- const values = [];
108
- let last;
109
- function step(now) {
110
- if (last != null) values.push(now - last);
111
- last = now;
112
- if (values.length >= CALCULATION_TOTAL) {
113
- const median = values.sort().slice(2, -2).reduce((first, second) => first + second, 0) / (values.length - CALCULATION_TRIM);
114
- resolve(median);
115
- } else requestAnimationFrame(step);
222
+ function isEventTarget(value) {
223
+ return typeof value === "object" && value != null && typeof value.addEventListener === "function" && typeof value.removeEventListener === "function" && typeof value.dispatchEvent === "function";
224
+ }
225
+ function isHTMLOrSVGElement(value) {
226
+ return value instanceof HTMLElement || value instanceof SVGElement;
227
+ }
228
+ function addDelegatedHandler(doc, type, name, passive) {
229
+ if (DELEGATED.has(name)) return;
230
+ DELEGATED.add(name);
231
+ doc.addEventListener(type, passive ? HANDLER_PASSIVE : HANDLER_ACTIVE, { passive });
232
+ }
233
+ function addDelegatedListener(target, type, name, listener, passive) {
234
+ target[name] ??= /* @__PURE__ */ new Set();
235
+ target[name].add(listener);
236
+ addDelegatedHandler(document, type, name, passive);
237
+ return () => {
238
+ removeDelegatedListener(target, name, listener);
239
+ };
240
+ }
241
+ function delegatedEventHandler(event) {
242
+ const key = `${EVENT_PREFIX}${event.type}${this ? EVENT_SUFFIX_PASSIVE : EVENT_SUFFIX_ACTIVE}`;
243
+ const items = event.composedPath();
244
+ const { length } = items;
245
+ let target = items[0];
246
+ Object.defineProperties(event, {
247
+ currentTarget: {
248
+ configurable: true,
249
+ get() {
250
+ return target;
251
+ }
252
+ },
253
+ target: {
254
+ configurable: true,
255
+ value: target
116
256
  }
117
- requestAnimationFrame(step);
118
257
  });
258
+ for (let index$1 = 0; index$1 < length; index$1 += 1) {
259
+ const item = items[index$1];
260
+ const listeners = item[key];
261
+ if (item.disabled || listeners == null) continue;
262
+ target = item;
263
+ for (const listener of listeners) {
264
+ listener.call(item, event);
265
+ if (event.cancelBubble) return;
266
+ }
267
+ }
119
268
  }
120
- function noop() {}
121
- var CALCULATION_TOTAL = 10;
122
- var CALCULATION_TRIM = 4;
123
- calculate().then((value) => {
124
- });
125
-
269
+ function getDelegatedName(target, type, options) {
270
+ 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}`;
271
+ }
272
+ function removeDelegatedListener(target, name, listener) {
273
+ const handlers = target[name];
274
+ if (handlers == null || !handlers.has(listener)) return false;
275
+ handlers.delete(listener);
276
+ if (handlers.size === 0) target[name] = void 0;
277
+ return true;
278
+ }
279
+ var DELEGATED = /* @__PURE__ */ new Set();
280
+ var EVENT_PREFIX = "@";
281
+ var EVENT_SUFFIX_ACTIVE = ":active";
282
+ var EVENT_SUFFIX_PASSIVE = ":passive";
283
+ var EVENT_TYPES = new Set([
284
+ "beforeinput",
285
+ "click",
286
+ "dblclick",
287
+ "contextmenu",
288
+ "focusin",
289
+ "focusout",
290
+ "input",
291
+ "keydown",
292
+ "keyup",
293
+ "mousedown",
294
+ "mousemove",
295
+ "mouseout",
296
+ "mouseover",
297
+ "mouseup",
298
+ "pointerdown",
299
+ "pointermove",
300
+ "pointerout",
301
+ "pointerover",
302
+ "pointerup",
303
+ "touchend",
304
+ "touchmove",
305
+ "touchstart"
306
+ ]);
307
+ var HANDLER_ACTIVE = delegatedEventHandler.bind(false);
308
+ var HANDLER_PASSIVE = delegatedEventHandler.bind(true);
126
309
  function createEventOptions(options) {
127
310
  return {
128
311
  capture: getBoolean(options?.capture),
129
312
  once: getBoolean(options?.once),
130
313
  passive: getBoolean(options?.passive, true),
131
- signal: options?.signal
314
+ signal: options?.signal instanceof AbortSignal ? options.signal : void 0
132
315
  };
133
316
  }
134
317
  function getPosition(event) {
@@ -149,12 +332,14 @@ function getPosition(event) {
149
332
  function on(target, type, listener, options) {
150
333
  if (!isEventTarget(target) || typeof type !== "string" || typeof listener !== "function") return noop;
151
334
  const extended = createEventOptions(options);
335
+ const delegated = getDelegatedName(target, type, extended);
336
+ if (delegated != null) return addDelegatedListener(target, type, delegated, listener, extended.passive);
152
337
  target.addEventListener(type, listener, extended);
338
+ if (extended.once) return noop;
153
339
  return () => {
154
340
  target.removeEventListener(type, listener, extended);
155
341
  };
156
342
  }
157
-
158
343
  function findAncestor(origin, selector) {
159
344
  if (!(origin instanceof Element) || selector == null) return null;
160
345
  if (typeof selector === "string") {
@@ -170,35 +355,74 @@ function findAncestor(origin, selector) {
170
355
  }
171
356
  return parent;
172
357
  }
173
-
174
- function setElementValues(element, first, second, callback) {
358
+ new Set([
359
+ Node.ELEMENT_NODE,
360
+ Node.TEXT_NODE,
361
+ Node.PROCESSING_INSTRUCTION_NODE,
362
+ Node.COMMENT_NODE,
363
+ Node.DOCUMENT_TYPE_NODE
364
+ ]);
365
+ Object.freeze([
366
+ "async",
367
+ "autofocus",
368
+ "autoplay",
369
+ "checked",
370
+ "controls",
371
+ "default",
372
+ "defer",
373
+ "disabled",
374
+ "formnovalidate",
375
+ "hidden",
376
+ "inert",
377
+ "ismap",
378
+ "itemscope",
379
+ "loop",
380
+ "multiple",
381
+ "muted",
382
+ "nomodule",
383
+ "novalidate",
384
+ "open",
385
+ "playsinline",
386
+ "readonly",
387
+ "required",
388
+ "reversed",
389
+ "selected"
390
+ ]);
391
+ document.createElement("form");
392
+ function setElementValues(element, first, second, third, callback) {
175
393
  if (!isHTMLOrSVGElement(element)) return;
176
- if (isPlainObject(first)) {
177
- const entries = Object.entries(first);
178
- const { length } = entries;
179
- for (let index = 0; index < length; index += 1) {
180
- const [key, value] = entries[index];
181
- callback(element, key, value);
182
- }
183
- } else if (typeof first === "string") callback(element, first, second);
394
+ if (typeof first === "string") {
395
+ callback(element, first, second, third);
396
+ return;
397
+ }
398
+ const isArray = Array.isArray(first);
399
+ if (!isArray && !(typeof first === "object" && first !== null)) return;
400
+ const entries = isArray ? first : Object.entries(first).map(([name, value]) => ({
401
+ name,
402
+ value
403
+ }));
404
+ const { length } = entries;
405
+ for (let index$1 = 0; index$1 < length; index$1 += 1) {
406
+ const entry = entries[index$1];
407
+ if (typeof entry === "object" && typeof entry?.name === "string") callback(element, entry.name, entry.value, third);
408
+ }
184
409
  }
185
- function updateElementValue(element, key, value, set, remove, json) {
186
- if (isNullableOrWhitespace(value)) remove.call(element, key);
187
- else set.call(element, key, String(value));
410
+ function updateElementValue(element, key, value, set, remove, isBoolean, json) {
411
+ if (isBoolean ? value == null : isNullableOrWhitespace(value)) remove.call(element, key);
412
+ else set.call(element, key, json ? JSON.stringify(value) : String(value));
188
413
  }
189
-
190
414
  function getStyles(element, properties, computed) {
191
415
  const styles = {};
192
416
  if (!(isHTMLOrSVGElement(element) && Array.isArray(properties))) return styles;
193
417
  const { length } = properties;
194
- for (let index = 0; index < length; index += 1) {
195
- const property = properties[index];
418
+ for (let index$1 = 0; index$1 < length; index$1 += 1) {
419
+ const property = properties[index$1];
196
420
  if (typeof property === "string") styles[property] = getStyleValue(element, property, computed === true);
197
421
  }
198
422
  return styles;
199
423
  }
200
424
  function setStyles(element, styles) {
201
- setElementValues(element, styles, null, updateStyleProperty);
425
+ setElementValues(element, styles, null, null, updateStyleProperty);
202
426
  }
203
427
  function toggleStyles(element, styles) {
204
428
  function toggle(set) {
@@ -227,13 +451,12 @@ function toggleStyles(element, styles) {
227
451
  };
228
452
  }
229
453
  function updateStyleProperty(element, key, value) {
230
- updateElementValue(element, key, value, function(property, value$1) {
231
- this.style[property] = value$1;
454
+ updateElementValue(element, key, value, function(property, style) {
455
+ this.style[property] = style;
232
456
  }, function(property) {
233
457
  this.style[property] = "";
234
- });
458
+ }, false, false);
235
459
  }
236
-
237
460
  function getSupport() {
238
461
  if (window == null || navigator == null) return false;
239
462
  if ("matchMedia" in window) {
@@ -261,345 +484,286 @@ var touch_default = (() => {
261
484
  } });
262
485
  return instance;
263
486
  })();
264
-
265
- class OuiSplitterElement extends HTMLElement {
266
- static observedAttributes = ['max', 'min', 'size', 'type'];
267
- #splitter;
268
- // Getters and setters
269
- get max() {
270
- return this.#splitter.values.max;
271
- }
272
- set max(value) {
273
- this.setAttribute('max', String(value));
274
- }
275
- get min() {
276
- return this.#splitter.values.min;
277
- }
278
- set min(value) {
279
- this.setAttribute('min', String(value));
280
- }
281
- get size() {
282
- return this.#splitter.values.now.current;
283
- }
284
- set size(value) {
285
- this.setAttribute('size', String(value));
286
- }
287
- get type() {
288
- return this.getAttribute('type') ?? 'vertical';
289
- }
290
- set type(value) {
291
- this.setAttribute('type', value);
292
- }
293
- // Constructor
294
- constructor() {
295
- super();
296
- const panels = [...this.children].filter(child => child instanceof HTMLElement);
297
- if (panels.length !== 2) {
298
- throw new Error(`${SELECTOR} must have exactly two panels.`);
299
- }
300
- this.#splitter = new Splitter(this, panels);
301
- }
302
- // Methods
303
- connectedCallback() {
304
- this.#splitter.updateConnections(1);
305
- }
306
- disconnectedCallback() {
307
- this.#splitter.updateConnections(0);
308
- }
309
- attributeChangedCallback(name) {
310
- switch (name) {
311
- case 'max':
312
- case 'min':
313
- case 'size':
314
- this.#splitter.updateValues();
315
- break;
316
- case 'type':
317
- this.#splitter.updateOrientation();
318
- break;
319
- }
320
- }
321
- }
487
+ var OuiSplitterElement = class extends HTMLElement {
488
+ static observedAttributes = [
489
+ "max",
490
+ "min",
491
+ "size",
492
+ "type"
493
+ ];
494
+ #splitter;
495
+ get max() {
496
+ return this.#splitter.values.max;
497
+ }
498
+ set max(value) {
499
+ this.setAttribute("max", String(value));
500
+ }
501
+ get min() {
502
+ return this.#splitter.values.min;
503
+ }
504
+ set min(value) {
505
+ this.setAttribute("min", String(value));
506
+ }
507
+ get size() {
508
+ return this.#splitter.values.now.current;
509
+ }
510
+ set size(value) {
511
+ this.setAttribute("size", String(value));
512
+ }
513
+ get type() {
514
+ return this.getAttribute("type") ?? "vertical";
515
+ }
516
+ set type(value) {
517
+ this.setAttribute("type", value);
518
+ }
519
+ constructor() {
520
+ super();
521
+ const panels = [...this.children].filter((child) => child instanceof HTMLElement);
522
+ if (panels.length !== 2) throw new Error(`${SELECTOR} must have exactly two panels.`);
523
+ this.#splitter = new Splitter(this, panels);
524
+ }
525
+ connectedCallback() {
526
+ this.#splitter.updateConnections(1);
527
+ }
528
+ disconnectedCallback() {
529
+ this.#splitter.updateConnections(0);
530
+ }
531
+ attributeChangedCallback(name) {
532
+ switch (name) {
533
+ case "max":
534
+ case "min":
535
+ case "size":
536
+ this.#splitter.updateValues();
537
+ break;
538
+ case "type":
539
+ this.#splitter.updateOrientation();
540
+ break;
541
+ default: break;
542
+ }
543
+ }
544
+ };
322
545
  let index = 0;
323
- class Splitter {
324
- element;
325
- handle;
326
- panels;
327
- rectangle;
328
- separator;
329
- types;
330
- values;
331
- constructor(element, panels) {
332
- this.element = element;
333
- this.panels = panels;
334
- if (isNullableOrWhitespace(element.id)) {
335
- element.id = `oui_splitter_${++index}`;
336
- }
337
- this.values = getValues(element);
338
- this.handle = createHandle();
339
- this.rectangle = element.getBoundingClientRect();
340
- this.separator = createSeparator(this);
341
- this.separator.append(this.handle);
342
- panels[0].insertAdjacentElement('afterend', this.separator);
343
- this.updateOrientation();
344
- this.updateValues();
345
- }
346
- updateConnections(add) {
347
- const method = METHODS_CONNECT[add];
348
- MAPPED_ELEMENTS[method](this.element, this);
349
- MAPPED_ELEMENTS[method](this.handle, this);
350
- MAPPED_ELEMENTS[method](this.separator, this);
351
- if (this.types.auto) {
352
- RESIZE_OBSERVER[METHODS_OBSERVE[add]](this.element);
353
- }
354
- }
355
- updateOrientation() {
356
- this.types = getTypes(this);
357
- if (this.types.auto) {
358
- RESIZE_OBSERVER.observe(this.element);
359
- }
360
- else {
361
- RESIZE_OBSERVER.unobserve(this.element);
362
- }
363
- if (this.types.horizontal) {
364
- this.element.setAttribute(ATTRIBUTE_HORIZONTAL, '');
365
- }
366
- else {
367
- this.element.removeAttribute(ATTRIBUTE_HORIZONTAL);
368
- }
369
- setAriaOrientation(this);
370
- }
371
- updateValues() {
372
- this.values = getValues(this.element);
373
- requestAnimationFrame(() => {
374
- setSize(this, this.values.now.current);
375
- setAriaValue(this);
376
- });
377
- }
378
- }
379
- //
546
+ var Splitter = class {
547
+ element;
548
+ handle;
549
+ panels;
550
+ rectangle;
551
+ separator;
552
+ types;
553
+ values;
554
+ constructor(element, panels) {
555
+ this.element = element;
556
+ this.panels = panels;
557
+ if (isNullableOrWhitespace(element.id)) element.id = `oui_splitter_${++index}`;
558
+ this.values = getValues(element);
559
+ this.handle = createHandle();
560
+ this.rectangle = element.getBoundingClientRect();
561
+ this.separator = createSeparator(this);
562
+ this.separator.append(this.handle);
563
+ panels[0].insertAdjacentElement("afterend", this.separator);
564
+ this.updateOrientation();
565
+ this.updateValues();
566
+ }
567
+ updateConnections(add) {
568
+ const method = METHODS_CONNECT[add];
569
+ MAPPED_ELEMENTS[method](this.element, this);
570
+ MAPPED_ELEMENTS[method](this.handle, this);
571
+ MAPPED_ELEMENTS[method](this.separator, this);
572
+ if (this.types.auto) RESIZE_OBSERVER[METHODS_OBSERVE[add]](this.element);
573
+ }
574
+ updateOrientation() {
575
+ this.types = getTypes(this);
576
+ if (this.types.auto) RESIZE_OBSERVER.observe(this.element);
577
+ else RESIZE_OBSERVER.unobserve(this.element);
578
+ if (this.types.horizontal) this.element.setAttribute(ATTRIBUTE_HORIZONTAL, "");
579
+ else this.element.removeAttribute(ATTRIBUTE_HORIZONTAL);
580
+ setAriaOrientation(this);
581
+ }
582
+ updateValues() {
583
+ this.values = getValues(this.element);
584
+ requestAnimationFrame(() => {
585
+ setSize(this, this.values.now.current);
586
+ setAriaValue(this);
587
+ });
588
+ }
589
+ };
380
590
  function createHandle() {
381
- const handle = document.createElement('span');
382
- handle.setAttribute('aria-hidden', 'true');
383
- handle.setAttribute(ATTRIBUTE_HANDLE, '');
384
- return handle;
385
- }
386
- function createSeparator(splitter) {
387
- const separator = document.createElement('div');
388
- separator.role = 'separator';
389
- separator.tabIndex = 0;
390
- separator.setAttribute('aria-controls', splitter.element.id);
391
- separator.setAttribute('aria-label', 'Resize panels');
392
- separator.setAttribute(ATTRIBUTE_SEPARATOR, '');
393
- return separator;
591
+ const handle = document.createElement("span");
592
+ handle.setAttribute("aria-hidden", "true");
593
+ handle.setAttribute(ATTRIBUTE_HANDLE, "");
594
+ return handle;
595
+ }
596
+ function createSeparator(splitter$1) {
597
+ const separator = document.createElement("div");
598
+ separator.role = "separator";
599
+ separator.tabIndex = 0;
600
+ separator.setAttribute("aria-controls", splitter$1.element.id);
601
+ separator.setAttribute("aria-label", "Resize panels");
602
+ separator.setAttribute(ATTRIBUTE_SEPARATOR, "");
603
+ return separator;
394
604
  }
395
605
  function getContained(min, value, max) {
396
- return round(clamp(value, min, max), VALUE_DECIMALS);
397
- }
398
- function getSize(splitter, value) {
399
- const { height, left, top, width } = splitter.rectangle;
400
- const offset = value - (splitter.types.horizontal ? top : left);
401
- const fraction = offset / (splitter.types.horizontal ? height : width);
402
- return getContained(splitter.values.min, fraction, splitter.values.max);
403
- }
404
- function getTypes(splitter, width, height) {
405
- const type = splitter.element.getAttribute('type')?.trim() ?? '';
406
- if (type === 'horizontal') {
407
- return {
408
- auto: false,
409
- horizontal: true,
410
- };
411
- }
412
- if (type === 'auto') {
413
- return {
414
- auto: true,
415
- horizontal: (height ?? splitter.rectangle.height) >
416
- (width ?? splitter.rectangle.width),
417
- };
418
- }
419
- return {
420
- auto: false,
421
- horizontal: false,
422
- };
606
+ return round(clamp(value, min, max), VALUE_DECIMALS);
607
+ }
608
+ function getSize(splitter$1, value) {
609
+ const { height, left, top, width } = splitter$1.rectangle;
610
+ const fraction = (value - (splitter$1.types.horizontal ? top : left)) / (splitter$1.types.horizontal ? height : width);
611
+ return getContained(splitter$1.values.min, fraction, splitter$1.values.max);
612
+ }
613
+ function getTypes(splitter$1, width, height) {
614
+ const type = splitter$1.element.getAttribute("type")?.trim() ?? "";
615
+ if (type === "horizontal") return {
616
+ auto: false,
617
+ horizontal: true
618
+ };
619
+ if (type === "auto") return {
620
+ auto: true,
621
+ horizontal: (height ?? splitter$1.rectangle.height) > (width ?? splitter$1.rectangle.width)
622
+ };
623
+ return {
624
+ auto: false,
625
+ horizontal: false
626
+ };
423
627
  }
424
628
  function getValue(element, name, defaultValue) {
425
- const value = element.getAttribute(name);
426
- if (isNullableOrWhitespace(value)) {
427
- return defaultValue;
428
- }
429
- const parsed = Number.parseFloat(value);
430
- if (Number.isNaN(parsed)) {
431
- return defaultValue;
432
- }
433
- if (parsed < 0) {
434
- return defaultValue;
435
- }
436
- return parsed > 1 ? parsed / NAVIGATION_MAXIMUM_TOTAL : parsed;
629
+ const value = element.getAttribute(name);
630
+ if (isNullableOrWhitespace(value)) return defaultValue;
631
+ const parsed = Number.parseFloat(value);
632
+ if (Number.isNaN(parsed)) return defaultValue;
633
+ if (parsed < 0) return defaultValue;
634
+ return parsed > 1 ? parsed / NAVIGATION_MAXIMUM_TOTAL : parsed;
437
635
  }
438
636
  function getValues(element) {
439
- const values = {
440
- max: getValue(element, 'max', NAVIGATION_MAXIMUM_PERCENTAGE),
441
- min: getValue(element, 'min', NAVIGATION_MINIMUM_PERCENTAGE),
442
- now: {
443
- current: 0.5,
444
- previous: 0.5,
445
- },
446
- };
447
- const value = getContained(values.min, getValue(element, 'size', values.now.current), values.max);
448
- values.now.current = value;
449
- values.now.previous = value;
450
- return values;
637
+ const values = {
638
+ max: getValue(element, "max", NAVIGATION_MAXIMUM_PERCENTAGE),
639
+ min: getValue(element, "min", NAVIGATION_MINIMUM_PERCENTAGE),
640
+ now: {
641
+ current: .5,
642
+ previous: .5
643
+ }
644
+ };
645
+ const value = getContained(values.min, getValue(element, "size", values.now.current), values.max);
646
+ values.now.current = value;
647
+ values.now.previous = value;
648
+ return values;
451
649
  }
452
650
  function onEnd(reset) {
453
- if (splitter == null) {
454
- return;
455
- }
456
- splitter.handle.removeAttribute(ATTRIBUTE_ACTIVE);
457
- splitter.separator.removeAttribute(ATTRIBUTE_ACTIVE);
458
- if (reset) {
459
- setSize(splitter, splitter.values.now.previous);
460
- }
461
- else {
462
- splitter.values.now.previous = splitter.values.now.current;
463
- }
464
- splitter = undefined;
465
- STYLING_TOGGLER.remove();
651
+ if (splitter == null) return;
652
+ splitter.handle.removeAttribute(ATTRIBUTE_ACTIVE);
653
+ splitter.separator.removeAttribute(ATTRIBUTE_ACTIVE);
654
+ if (reset) setSize(splitter, splitter.values.now.previous);
655
+ else splitter.values.now.previous = splitter.values.now.current;
656
+ splitter = void 0;
657
+ STYLING_TOGGLER.remove();
466
658
  }
467
659
  function onKeydown(event) {
468
- switch (true) {
469
- case KEYS_ALL.has(event.key):
470
- onNavigate(event);
471
- break;
472
- case event.key === 'Escape':
473
- onEnd(true);
474
- break;
475
- }
660
+ switch (true) {
661
+ case KEYS_ALL.has(event.key):
662
+ onNavigate(event);
663
+ break;
664
+ case event.key === "Escape":
665
+ onEnd(true);
666
+ break;
667
+ default: break;
668
+ }
476
669
  }
477
670
  function onNavigate(event) {
478
- const splitter = MAPPED_ELEMENTS.get(findAncestor(event.target, '[oui-splitter-separator]'));
479
- if (splitter == null) {
480
- return;
481
- }
482
- const { types, values } = splitter;
483
- if (KEYS_ABSOLUTE.has(event.key)) {
484
- setSize(splitter, event.key === 'End' ? values.max : values.min, true);
485
- return;
486
- }
487
- if ((types.horizontal && !KEYS_HORIZONTAL.has(event.key)) ||
488
- !(types.horizontal || KEYS_VERTICAL.has(event.key))) {
489
- return;
490
- }
491
- const offset = KEYS_NEGATIVE.has(event.key) ? -1 : 1;
492
- setSize(splitter, getContained(values.min, values.now.current + offset * NAVIGATION_MODIFIER, values.max), true);
671
+ const splitter$1 = MAPPED_ELEMENTS.get(findAncestor(event.target, "[oui-splitter-separator]"));
672
+ if (splitter$1 == null) return;
673
+ const { types, values } = splitter$1;
674
+ if (KEYS_ABSOLUTE.has(event.key)) {
675
+ setSize(splitter$1, event.key === "End" ? values.max : values.min, true);
676
+ return;
677
+ }
678
+ if (types.horizontal && !KEYS_HORIZONTAL.has(event.key) || !(types.horizontal || KEYS_VERTICAL.has(event.key))) return;
679
+ const offset = KEYS_NEGATIVE.has(event.key) ? -1 : 1;
680
+ setSize(splitter$1, getContained(values.min, values.now.current + offset * NAVIGATION_MODIFIER, values.max), true);
493
681
  }
494
682
  function onObservation(entries) {
495
- if (frame != null) {
496
- cancelAnimationFrame(frame);
497
- }
498
- frame = requestAnimationFrame(() => {
499
- for (const entry of entries) {
500
- const splitter = MAPPED_ELEMENTS.get(entry.target);
501
- if (splitter == null) {
502
- return;
503
- }
504
- splitter.types = getTypes(splitter, entry.contentRect.width, entry.contentRect.height);
505
- if (splitter.types.horizontal) {
506
- splitter.element.setAttribute(ATTRIBUTE_HORIZONTAL, '');
507
- }
508
- else {
509
- splitter.element.removeAttribute(ATTRIBUTE_HORIZONTAL);
510
- }
511
- setAriaOrientation(splitter);
512
- }
513
- frame = undefined;
514
- });
683
+ if (frame != null) cancelAnimationFrame(frame);
684
+ frame = requestAnimationFrame(() => {
685
+ for (const entry of entries) {
686
+ const splitter$1 = MAPPED_ELEMENTS.get(entry.target);
687
+ if (splitter$1 == null) return;
688
+ splitter$1.types = getTypes(splitter$1, entry.contentRect.width, entry.contentRect.height);
689
+ if (splitter$1.types.horizontal) splitter$1.element.setAttribute(ATTRIBUTE_HORIZONTAL, "");
690
+ else splitter$1.element.removeAttribute(ATTRIBUTE_HORIZONTAL);
691
+ setAriaOrientation(splitter$1);
692
+ }
693
+ frame = void 0;
694
+ });
515
695
  }
516
696
  function onPointerdown(event) {
517
- if ((event.type === 'mousedown' && touch_default.value) ||
518
- (event.type === 'touchstart' && !touch_default.value)) {
519
- return;
520
- }
521
- splitter = MAPPED_ELEMENTS.get(findAncestor(event.target, SELECTOR_HANDLE));
522
- if (splitter == null) {
523
- return;
524
- }
525
- if (touch_default.value) {
526
- event.preventDefault();
527
- }
528
- splitter.handle.setAttribute(ATTRIBUTE_ACTIVE, '');
529
- splitter.separator.setAttribute(ATTRIBUTE_ACTIVE, '');
530
- splitter.rectangle = splitter.element.getBoundingClientRect();
531
- STYLING_TOGGLER.set();
697
+ if (event.type === "mousedown" && touch_default.value || event.type === "touchstart" && !touch_default.value) return;
698
+ splitter = MAPPED_ELEMENTS.get(findAncestor(event.target, SELECTOR_HANDLE));
699
+ if (splitter == null) return;
700
+ if (touch_default.value) event.preventDefault();
701
+ splitter.handle.setAttribute(ATTRIBUTE_ACTIVE, "");
702
+ splitter.separator.setAttribute(ATTRIBUTE_ACTIVE, "");
703
+ splitter.rectangle = splitter.element.getBoundingClientRect();
704
+ STYLING_TOGGLER.set();
532
705
  }
533
706
  function onPointermove(event) {
534
- if (splitter == null) {
535
- return;
536
- }
537
- const position = getPosition(event);
538
- if (position != null) {
539
- splitter.values.now.current = getSize(splitter, splitter.types.horizontal ? position.y : position.x);
540
- setSize(splitter, splitter.values.now.current);
541
- }
707
+ if (splitter == null) return;
708
+ const position = getPosition(event);
709
+ if (position != null) {
710
+ splitter.values.now.current = getSize(splitter, splitter.types.horizontal ? position.y : position.x);
711
+ setSize(splitter, splitter.values.now.current);
712
+ }
542
713
  }
543
714
  function onPointerup() {
544
- if (splitter != null) {
545
- onEnd(false);
546
- }
547
- }
548
- function setAriaOrientation(splitter) {
549
- splitter.separator.setAttribute('aria-orientation', splitter.types.horizontal ? 'horizontal' : 'vertical');
550
- }
551
- function setAriaValue(splitter) {
552
- splitter.separator.setAttribute('aria-valuemax', String(splitter.values.max));
553
- splitter.separator.setAttribute('aria-valuemin', String(splitter.values.min));
554
- splitter.separator.setAttribute('aria-valuenow', String(splitter.values.now.current));
555
- }
556
- function setSize(splitter, size, previous) {
557
- splitter.values.now.current = size;
558
- if (previous) {
559
- splitter.values.now.previous = size;
560
- }
561
- splitter.element.style.setProperty('--oui-splitter-size', `${size}`);
562
- setAriaValue(splitter);
563
- }
564
- //
565
- const SELECTOR = 'oui-splitter';
715
+ if (splitter != null) onEnd(false);
716
+ }
717
+ function setAriaOrientation(splitter$1) {
718
+ splitter$1.separator.setAttribute("aria-orientation", splitter$1.types.horizontal ? "horizontal" : "vertical");
719
+ }
720
+ function setAriaValue(splitter$1) {
721
+ splitter$1.separator.setAttribute("aria-valuemax", String(splitter$1.values.max));
722
+ splitter$1.separator.setAttribute("aria-valuemin", String(splitter$1.values.min));
723
+ splitter$1.separator.setAttribute("aria-valuenow", String(splitter$1.values.now.current));
724
+ }
725
+ function setSize(splitter$1, size, previous) {
726
+ splitter$1.values.now.current = size;
727
+ if (previous) splitter$1.values.now.previous = size;
728
+ splitter$1.element.style.setProperty("--oui-splitter-size", `${size}`);
729
+ setAriaValue(splitter$1);
730
+ }
731
+ const SELECTOR = "oui-splitter";
566
732
  const ATTRIBUTE_ACTIVE = `${SELECTOR}-active`;
567
733
  const ATTRIBUTE_HANDLE = `${SELECTOR}-handle`;
568
734
  const ATTRIBUTE_HORIZONTAL = `${SELECTOR}-horizontal`;
569
735
  const ATTRIBUTE_SEPARATOR = `${SELECTOR}-separator`;
570
- const KEYS_ABSOLUTE = new Set(['End', 'Home']);
571
- const KEYS_HORIZONTAL = new Set(['ArrowDown', 'ArrowUp']);
572
- const KEYS_NEGATIVE = new Set(['ArrowLeft', 'ArrowUp']);
573
- const KEYS_VERTICAL = new Set(['ArrowLeft', 'ArrowRight']);
736
+ const KEYS_ABSOLUTE = new Set(["End", "Home"]);
737
+ const KEYS_HORIZONTAL = new Set(["ArrowDown", "ArrowUp"]);
738
+ const KEYS_NEGATIVE = new Set(["ArrowLeft", "ArrowUp"]);
739
+ const KEYS_VERTICAL = new Set(["ArrowLeft", "ArrowRight"]);
574
740
  const KEYS_ALL = new Set([
575
- ...KEYS_ABSOLUTE,
576
- ...KEYS_HORIZONTAL,
577
- ...KEYS_VERTICAL,
741
+ ...KEYS_ABSOLUTE,
742
+ ...KEYS_HORIZONTAL,
743
+ ...KEYS_VERTICAL
578
744
  ]);
579
- const MAPPED_ELEMENTS = new WeakMap();
580
- const METHODS_CONNECT = ['delete', 'set'];
581
- const METHODS_OBSERVE = ['unobserve', 'observe'];
582
- const NAVIGATION_MAXIMUM_PERCENTAGE = 0.9;
745
+ const MAPPED_ELEMENTS = /* @__PURE__ */ new WeakMap();
746
+ const METHODS_CONNECT = ["delete", "set"];
747
+ const METHODS_OBSERVE = ["unobserve", "observe"];
748
+ const NAVIGATION_MAXIMUM_PERCENTAGE = .9;
583
749
  const NAVIGATION_MAXIMUM_TOTAL = 100;
584
- const NAVIGATION_MINIMUM_PERCENTAGE = 0.1;
585
- const NAVIGATION_MODIFIER = 0.05;
750
+ const NAVIGATION_MINIMUM_PERCENTAGE = .1;
751
+ const NAVIGATION_MODIFIER = .05;
586
752
  const RESIZE_OBSERVER = new ResizeObserver(onObservation);
587
753
  const SELECTOR_HANDLE = `[${ATTRIBUTE_HANDLE}]`;
588
754
  const STYLING_TOGGLER = toggleStyles(document.body, {
589
- touchAction: 'none',
590
- userSelect: 'none',
591
- webkitUserSelect: 'none',
755
+ touchAction: "none",
756
+ userSelect: "none",
757
+ webkitUserSelect: "none"
592
758
  });
593
759
  const VALUE_DECIMALS = 6;
594
760
  let frame;
595
761
  let splitter;
596
- //
597
762
  customElements.define(SELECTOR, OuiSplitterElement);
598
- on(document, 'keydown', onKeydown);
599
- on(document, 'mousedown', onPointerdown);
600
- on(document, 'pointermove', onPointermove);
601
- on(document, 'pointerup', onPointerup);
602
- on(document, 'touchcancel', onPointerup, { passive: false });
603
- on(document, 'touchstart', onPointerdown, { passive: false });
604
-
763
+ on(document, "keydown", onKeydown);
764
+ on(document, "mousedown", onPointerdown);
765
+ on(document, "pointermove", onPointermove);
766
+ on(document, "pointerup", onPointerup);
767
+ on(document, "touchcancel", onPointerup, { passive: false });
768
+ on(document, "touchstart", onPointerdown, { passive: false });
605
769
  export { OuiSplitterElement };