@oscarpalmer/oui 0.29.0 → 0.30.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 (46) hide show
  1. package/dist/css/combobox.css +26 -0
  2. package/dist/js/combobox.d.mts +27 -0
  3. package/dist/js/combobox.mjs +474 -0
  4. package/dist/js/dialog.d.mts +4 -3
  5. package/dist/js/dialog.mjs +1 -1
  6. package/dist/js/{draggable-fIYXd8eO.d.mts → draggable-a6w0J1OD.d.mts} +1 -2
  7. package/dist/js/floatable/floatable.embedded.d.mts +1 -1
  8. package/dist/js/floatable/floatable.embedded.mjs +2 -2
  9. package/dist/js/floatable/floatable.standalone.d.mts +1 -1
  10. package/dist/js/{floatable.embedded-DUR8bQBK.d.mts → floatable.embedded-Bct4U5Dm.d.mts} +0 -1
  11. package/dist/js/focus-trap/focus-trap.embedded.mjs +13 -8
  12. package/dist/js/index.d.mts +9 -4
  13. package/dist/js/index.mjs +2 -1
  14. package/dist/js/internal/draggable.d.mts +1 -1
  15. package/dist/js/internal/draggable.mjs +24 -15
  16. package/dist/js/internal/navigable.d.mts +0 -1
  17. package/dist/js/internal/navigable.mjs +4 -3
  18. package/dist/js/menu.mjs +1 -1
  19. package/dist/js/movable/movable.embedded.d.mts +1 -1
  20. package/dist/js/movable/movable.embedded.mjs +3 -4
  21. package/dist/js/movable/movable.standalone.d.mts +1 -1
  22. package/dist/js/popover.d.mts +1 -2
  23. package/dist/js/popover.mjs +2 -2
  24. package/dist/js/resizable/resizable.embedded.d.mts +1 -1
  25. package/dist/js/resizable/resizable.embedded.mjs +47 -19
  26. package/dist/js/resizable/resizable.standalone.d.mts +1 -1
  27. package/dist/js/{resizable.embedded-CXrUVPzR.d.mts → resizable.embedded-3qoR0Bjm.d.mts} +0 -1
  28. package/dist/js/sortable/sortable.embedded.d.mts +1 -1
  29. package/dist/js/sortable/sortable.embedded.mjs +11 -15
  30. package/dist/js/sortable/sortable.standalone.d.mts +1 -1
  31. package/dist/js/splitter.d.mts +2 -2
  32. package/dist/js/splitter.mjs +11 -11
  33. package/dist/js/tooltip.d.mts +1 -2
  34. package/dist/js/tooltip.mjs +3 -3
  35. package/package.json +6 -2
  36. package/src/css/combobox.scss +26 -0
  37. package/src/js/combobox.ts +917 -0
  38. package/src/js/focus-trap/focus-trap.embedded.ts +22 -10
  39. package/src/js/index.ts +1 -0
  40. package/src/js/internal/draggable.ts +37 -29
  41. package/src/js/internal/navigable.ts +5 -1
  42. package/src/js/movable/movable.embedded.ts +1 -3
  43. package/src/js/popover.ts +1 -1
  44. package/src/js/resizable/resizable.embedded.ts +68 -18
  45. package/src/js/sortable/sortable.embedded.ts +7 -15
  46. package/src/js/splitter.ts +37 -23
@@ -289,19 +289,31 @@ function onTab(event: KeyboardEvent): void {
289
289
  return;
290
290
  }
291
291
 
292
- if (!instance.disabled) {
293
- event.preventDefault();
294
- }
292
+ const dispatch = new CustomEvent('focus-trap:tab', {
293
+ cancelable: true,
294
+ });
295
295
 
296
- const elements = getFocusable(element);
296
+ element.dispatchEvent(dispatch);
297
297
 
298
- const index = elements.indexOf(event.target as HTMLElement);
298
+ setTimeout(() => {
299
+ if (dispatch.defaultPrevented) {
300
+ return;
301
+ }
299
302
 
300
- if (index === -1 || elements.length === 0) {
301
- tabToTrap(instance, elements, element);
302
- } else {
303
- tabToElement(instance, elements, index, event.shiftKey ? -1 : 1);
304
- }
303
+ if (!instance.disabled) {
304
+ event.preventDefault();
305
+ }
306
+
307
+ const elements = getFocusable(element);
308
+
309
+ const index = elements.indexOf(event.target as HTMLElement);
310
+
311
+ if (index === -1 || elements.length === 0) {
312
+ tabToTrap(instance, elements, element);
313
+ } else {
314
+ tabToElement(instance, elements, index, event.shiftKey ? -1 : 1);
315
+ }
316
+ });
305
317
  }
306
318
 
307
319
  export function removeFocusTrap(element: HTMLElement): void {
package/src/js/index.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import './menu';
2
2
  import './toolbar';
3
3
 
4
+ export * from './combobox';
4
5
  export * from './dialog';
5
6
  export * from './floatable/floatable.standalone';
6
7
  export * from './focus-trap/focus-trap.standalone';
@@ -1,7 +1,7 @@
1
1
  import type {EventPosition, PlainObject} from '@oscarpalmer/atoms/models';
2
2
  import {clamp} from '@oscarpalmer/atoms/number';
3
3
  import {getAttribute, setAttribute} from '@oscarpalmer/toretto/attribute';
4
- import {getPosition, on} from '@oscarpalmer/toretto/event';
4
+ import {dispatch, getPosition, on} from '@oscarpalmer/toretto/event';
5
5
  import {findAncestor} from '@oscarpalmer/toretto/find';
6
6
  import {isHTMLOrSVGElement} from '@oscarpalmer/toretto/is';
7
7
  import {setStyle, setStyles, toggleStyles, type StyleToggler} from '@oscarpalmer/toretto/style';
@@ -27,8 +27,6 @@ type OuiDraggableDirection = 'horizontal' | 'vertical' | 'x' | 'y';
27
27
  export abstract class OuiDraggable<ExtraState extends PlainObject = PlainObject> {
28
28
  #destroyed = false;
29
29
 
30
- #name: keyof OuiDraggableStates;
31
-
32
30
  readonly #state: OuiDraggableState & ExtraState;
33
31
 
34
32
  get element(): HTMLElement {
@@ -43,13 +41,12 @@ export abstract class OuiDraggable<ExtraState extends PlainObject = PlainObject>
43
41
  options: OuiDraggableOptions<ExtraState>,
44
42
  extras: ExtraState,
45
43
  ) {
46
- this.#name = name;
47
-
48
44
  this.#state = {
49
45
  ...extras,
50
46
  attribute,
51
47
  element,
52
48
  event,
49
+ name,
53
50
  options,
54
51
  horizontal: true,
55
52
  vertical: true,
@@ -70,7 +67,7 @@ export abstract class OuiDraggable<ExtraState extends PlainObject = PlainObject>
70
67
 
71
68
  states ??= {};
72
69
 
73
- states[this.#name] = this.#state;
70
+ states[this.#state.name] = this.#state;
74
71
 
75
72
  globals.states.set(element, states);
76
73
  }
@@ -216,9 +213,9 @@ export type OuiDraggableState = {
216
213
  attribute: string;
217
214
  container?: HTMLElement;
218
215
  element: HTMLElement;
219
- event: string;
220
216
  hasHandles?: boolean;
221
217
  horizontal: boolean;
218
+ name: keyof OuiDraggableStates;
222
219
  options: OuiDraggableOptions;
223
220
  styling: StyleToggler;
224
221
  vertical: boolean;
@@ -254,6 +251,22 @@ export function addDraggable<
254
251
  return instances[this.property] as Instance;
255
252
  }
256
253
 
254
+ function cancelDrag(item?: OuiDraggableItem): void {
255
+ if (item == null) {
256
+ return;
257
+ }
258
+
259
+ item.state.options.drag.onCancel?.(globals, item);
260
+
261
+ dispatch(item.state.element, `${item.state.name}:cancel`, {
262
+ detail: {
263
+ element: item.state.options.getOrigin(),
264
+ },
265
+ });
266
+
267
+ reset();
268
+ }
269
+
257
270
  function destroyInstance(instance: OuiDraggable, state: OuiDraggableState): void {
258
271
  unsetContainer({
259
272
  instance,
@@ -312,21 +325,9 @@ function getNextPosition(item: OuiDraggableItem, position: EventPosition): Event
312
325
  }
313
326
 
314
327
  function onKeydown(event: KeyboardEvent): void {
315
- if (current == null || event.key !== KEY_ESCAPE) {
316
- return;
328
+ if (current != null && event.key === KEY_ESCAPE) {
329
+ cancelDrag(current);
317
330
  }
318
-
319
- current.state.options.drag.onCancel?.(globals, current);
320
-
321
- current.state.element.dispatchEvent(
322
- new CustomEvent(`${current.state.event}:cancel`, {
323
- detail: {
324
- element: current.state.options.getOrigin(),
325
- },
326
- }),
327
- );
328
-
329
- reset();
330
331
  }
331
332
 
332
333
  function onPointerdown(event: MouseEvent | TouchEvent): void {
@@ -405,7 +406,7 @@ function onPointerdown(event: MouseEvent | TouchEvent): void {
405
406
  globals.offset = item.state.options.position.getOffset(globals, item, element, position);
406
407
  globals.original = item.state.options.position.getOriginal(globals, item, position);
407
408
 
408
- const begin = new CustomEvent(`${item.state.event}:begin`, {
409
+ const dispatch = new CustomEvent(`${item.state.name}:begin`, {
409
410
  detail: {
410
411
  element,
411
412
  position: {...globals.original},
@@ -413,10 +414,10 @@ function onPointerdown(event: MouseEvent | TouchEvent): void {
413
414
  cancelable: true,
414
415
  });
415
416
 
416
- item.state.element.dispatchEvent(begin);
417
+ item.state.element.dispatchEvent(dispatch);
417
418
 
418
419
  setTimeout(() => {
419
- if (begin.defaultPrevented) {
420
+ if (dispatch.defaultPrevented) {
420
421
  item.state.options.drag.onCancel?.(globals, item);
421
422
 
422
423
  reset();
@@ -461,11 +462,18 @@ function onPointermove(event: MouseEvent | TouchEvent): void {
461
462
  original: position,
462
463
  });
463
464
 
464
- current.state.element.dispatchEvent(
465
- new CustomEvent(`${current.state.event}:move`, {
466
- detail,
467
- }),
468
- );
465
+ const dispatch = new CustomEvent(`${current.state.name}:move`, {
466
+ detail,
467
+ cancelable: true,
468
+ });
469
+
470
+ current.state.element.dispatchEvent(dispatch);
471
+
472
+ setTimeout(() => {
473
+ if (dispatch.defaultPrevented) {
474
+ cancelDrag(current);
475
+ }
476
+ });
469
477
  }
470
478
 
471
479
  function onPointerup(event: MouseEvent | TouchEvent): void {
@@ -1,6 +1,6 @@
1
1
  import {clamp} from '@oscarpalmer/atoms/number';
2
2
  import {getAria, setRole} from '@oscarpalmer/toretto/aria';
3
- import {on} from '@oscarpalmer/toretto/event';
3
+ import {dispatch, on} from '@oscarpalmer/toretto/event';
4
4
  import {findAncestor} from '@oscarpalmer/toretto/find';
5
5
  import {isHTMLOrSVGElement} from '@oscarpalmer/toretto/is';
6
6
  import type {AriaRole, RemovableEventListener} from '@oscarpalmer/toretto/models';
@@ -212,6 +212,10 @@ export function updateNavigableFocus(
212
212
  if (focus) {
213
213
  navigable.active.element?.focus();
214
214
  }
215
+
216
+ dispatch(navigable.active.element, 'navigable:change', {
217
+ detail: {...navigable.active},
218
+ });
215
219
  }
216
220
 
217
221
  // #endregion
@@ -199,7 +199,7 @@ function onEnd(
199
199
  setOffset(state, container);
200
200
  }
201
201
 
202
- const end = new CustomEvent(EVENT_END, {
202
+ const end = new CustomEvent('movable:end', {
203
203
  detail: {
204
204
  from: {...globals.original},
205
205
  to: getPosition(event),
@@ -295,8 +295,6 @@ const ATTRIBUTE_MOVING = `${ATTRIBUTE_MOVABLE}-moving`;
295
295
 
296
296
  const CONTAINERS = new Map<HTMLElement, Set<OuiMovable>>();
297
297
 
298
- const EVENT_END = 'move:end';
299
-
300
298
  const MESSAGE = 'The element must be an instance of HTMLElement or SVGElement';
301
299
 
302
300
  const MOVED = new Set<OuiMovable>();
package/src/js/popover.ts CHANGED
@@ -199,7 +199,7 @@ const ATTRIBUTE = 'oui-popover';
199
199
  const ATTRIBUTE_OPEN = `${ATTRIBUTE}-open`;
200
200
 
201
201
  const options: OuiFloatableOptions = {
202
- attribute: `${ATTRIBUTE}position`,
202
+ attribute: `${ATTRIBUTE}-position`,
203
203
  position: 'below-start',
204
204
  reusable: false,
205
205
  };
@@ -2,7 +2,7 @@ import {isPlainObject} from '@oscarpalmer/atoms/is';
2
2
  import type {EventPosition} from '@oscarpalmer/atoms/models';
3
3
  import {getNumber} from '@oscarpalmer/atoms/number';
4
4
  import {getAttribute, setAttribute} from '@oscarpalmer/toretto/attribute';
5
- import {getPosition, on} from '@oscarpalmer/toretto/event';
5
+ import {dispatch, getPosition, on} from '@oscarpalmer/toretto/event';
6
6
  import {findAncestor} from '@oscarpalmer/toretto/find';
7
7
  import {isHTMLOrSVGElement} from '@oscarpalmer/toretto/is';
8
8
  import {setStyles, toggleStyles, type StyleToggler} from '@oscarpalmer/toretto/style';
@@ -91,6 +91,21 @@ function addResizable(
91
91
  return item?.instance;
92
92
  }
93
93
 
94
+ function cancelResize(item?: OuiResizableItem): void {
95
+ if (item == null) {
96
+ return;
97
+ }
98
+
99
+ setStyles(item.state.element, {
100
+ height: `${item.state.height}px`,
101
+ width: `${item.state.width}px`,
102
+ });
103
+
104
+ resetResizable();
105
+
106
+ dispatch(item.state.element, 'resizable:cancel');
107
+ }
108
+
94
109
  /**
95
110
  * Creates _(or retrieves)_ a _OuiResizable_ instance for an element
96
111
  *
@@ -245,16 +260,9 @@ function getXAndY(first: unknown, second?: unknown): [number, number] {
245
260
  }
246
261
 
247
262
  function onKeydown(event: KeyboardEvent): void {
248
- if (current == null || event.key !== 'Escape') {
249
- return;
263
+ if (current != null && event.key === 'Escape') {
264
+ cancelResize(current);
250
265
  }
251
-
252
- setStyles(current.state.element, {
253
- height: `${current.state.height}px`,
254
- width: `${current.state.width}px`,
255
- });
256
-
257
- resetResizable();
258
266
  }
259
267
 
260
268
  function onPointerdown(event: MouseEvent | TouchEvent): void {
@@ -283,11 +291,23 @@ function onPointerdown(event: MouseEvent | TouchEvent): void {
283
291
  event.preventDefault();
284
292
  }
285
293
 
286
- current = stored;
287
- start = position;
294
+ const dispatch = new CustomEvent('resizable:begin', {
295
+ cancelable: true,
296
+ });
297
+
298
+ element!.dispatchEvent(dispatch);
288
299
 
289
- current.state.styles.set();
290
- styleToggler.set();
300
+ setTimeout(() => {
301
+ if (dispatch.defaultPrevented) {
302
+ return;
303
+ }
304
+
305
+ current = stored;
306
+ start = position;
307
+
308
+ current.state.styles.set();
309
+ styleToggler.set();
310
+ });
291
311
  }
292
312
 
293
313
  function onPointermove(event: MouseEvent | TouchEvent): void {
@@ -305,6 +325,22 @@ function onPointermove(event: MouseEvent | TouchEvent): void {
305
325
  const height = current.state.height + (y - (start?.y ?? 0));
306
326
 
307
327
  getAndSetDimensions(current.state.element, current.state.options, {height, width});
328
+
329
+ const dispatch = new CustomEvent('resizable:resize', {
330
+ cancelable: true,
331
+ detail: {
332
+ height,
333
+ width,
334
+ },
335
+ });
336
+
337
+ current.state.element.dispatchEvent(dispatch);
338
+
339
+ setTimeout(() => {
340
+ if (dispatch.defaultPrevented) {
341
+ cancelResize(current);
342
+ }
343
+ });
308
344
  }
309
345
 
310
346
  function onPointerup(): void {
@@ -312,12 +348,26 @@ function onPointerup(): void {
312
348
  return;
313
349
  }
314
350
 
315
- const {height, width} = current.state.element.getBoundingClientRect();
351
+ const dispatch = new CustomEvent('resizable:end', {
352
+ cancelable: true,
353
+ });
316
354
 
317
- current.state.height = height;
318
- current.state.width = width;
355
+ current.state.element.dispatchEvent(dispatch);
319
356
 
320
- resetResizable();
357
+ setTimeout(() => {
358
+ if (current == null || dispatch.defaultPrevented) {
359
+ cancelResize(current);
360
+
361
+ return;
362
+ }
363
+
364
+ const {height, width} = current.state.element.getBoundingClientRect();
365
+
366
+ current.state.height = height;
367
+ current.state.width = width;
368
+
369
+ resetResizable();
370
+ });
321
371
  }
322
372
 
323
373
  function removeResizable(element: HTMLElement): void {
@@ -110,9 +110,9 @@ function afterEnd(
110
110
  let insertion: 'afterend' | 'beforebegin';
111
111
 
112
112
  if (position.y < top + height / 2) {
113
- insertion = INSERT_BEFORE;
113
+ insertion = 'beforebegin';
114
114
  } else {
115
- insertion = INSERT_AFTER;
115
+ insertion = 'afterend';
116
116
  }
117
117
 
118
118
  elements.target?.insertAdjacentElement(insertion, elements.origin!);
@@ -277,8 +277,8 @@ function onEnd(
277
277
  cancelable: true,
278
278
  };
279
279
 
280
- const fromEvent = new CustomEvent(EVENT_END, options);
281
- const toEvent = new CustomEvent(EVENT_END, options);
280
+ const fromEvent = new CustomEvent('sortable:end', options);
281
+ const toEvent = new CustomEvent('sortable:end', options);
282
282
 
283
283
  item.instance.element.dispatchEvent(fromEvent);
284
284
 
@@ -340,11 +340,11 @@ function onMove(
340
340
  if (position.calculated.y < top + height / 2) {
341
341
  place = 'before';
342
342
 
343
- toElement.insertAdjacentElement(INSERT_BEFORE, placeholder);
343
+ toElement.insertAdjacentElement('beforebegin', placeholder);
344
344
  } else {
345
345
  place = 'after';
346
346
 
347
- toElement.insertAdjacentElement(INSERT_AFTER, placeholder);
347
+ toElement.insertAdjacentElement('afterend', placeholder);
348
348
  }
349
349
 
350
350
  setAttribute(placeholder, ATTRIBUTE_PLACEHOLDER_POSITION, place);
@@ -383,7 +383,7 @@ function setPlaceholder(
383
383
 
384
384
  updatePlaceholder(item, element);
385
385
 
386
- const event = new CustomEvent(EVENT_PLACEHOLDER, {
386
+ const event = new CustomEvent('sortable:placeholder', {
387
387
  cancelable: true,
388
388
  detail: {
389
389
  origin,
@@ -492,14 +492,6 @@ const ATTRIBUTE_VERTICAL = `${ATTRIBUTE}-vertical`;
492
492
 
493
493
  const CONTAINERS = new Map<HTMLElement, Set<OuiSortable>>();
494
494
 
495
- const EVENT_END = 'sort:end';
496
-
497
- const EVENT_PLACEHOLDER = 'sort:placeholder';
498
-
499
- const INSERT_AFTER = 'afterend';
500
-
501
- const INSERT_BEFORE = 'beforebegin';
502
-
503
495
  const MESSAGE = 'The element must be an instance of HTMLElement or SVGElement';
504
496
 
505
497
  const SELECTOR = `[${ATTRIBUTE}]`;
@@ -5,14 +5,10 @@ import {setAria} from '@oscarpalmer/toretto/aria';
5
5
  import {getAttribute, setAttribute} from '@oscarpalmer/toretto/attribute';
6
6
  import {getPosition, on} from '@oscarpalmer/toretto/event';
7
7
  import {findAncestor} from '@oscarpalmer/toretto/find';
8
- import {setStyle, type StyleToggler, toggleStyles} from '@oscarpalmer/toretto/style';
8
+ import {setStyle, toggleStyles} from '@oscarpalmer/toretto/style';
9
9
  import supportsTouch from '@oscarpalmer/toretto/touch';
10
10
 
11
- declare global {
12
- interface HTMLElementTagNameMap {
13
- [SELECTOR]: OuiSplitterElement;
14
- }
15
- }
11
+ // #region Special variables
16
12
 
17
13
  const ATTRIBUTE_MAX = 'max';
18
14
 
@@ -22,6 +18,16 @@ const ATTRIBUTE_SIZE = 'size';
22
18
 
23
19
  const ATTRIBUTE_TYPE = 'type';
24
20
 
21
+ // #endregion
22
+
23
+ // #region Types
24
+
25
+ declare global {
26
+ interface HTMLElementTagNameMap {
27
+ [TAGNAME]: OuiSplitterElement;
28
+ }
29
+ }
30
+
25
31
  class OuiSplitter {
26
32
  element: OuiSplitterElement;
27
33
 
@@ -227,7 +233,9 @@ type OuiSplitterValuesNow = {
227
233
  previous: number;
228
234
  };
229
235
 
230
- //
236
+ // #endregion
237
+
238
+ // #region Functions
231
239
 
232
240
  function createHandle(): HTMLSpanElement {
233
241
  const handle = document.createElement('span');
@@ -498,31 +506,33 @@ function setSize(splitter: OuiSplitter, size: number, previous?: boolean): void
498
506
  setAriaValue(splitter);
499
507
  }
500
508
 
501
- //
509
+ // #endregion
502
510
 
503
- const SELECTOR = 'oui-splitter';
511
+ // #region Variables
504
512
 
505
- const ATTRIBUTE_ACTIVE = `${SELECTOR}-active`;
513
+ const TAGNAME = 'oui-splitter';
506
514
 
507
- const ATTRIBUTE_HANDLE = `${SELECTOR}-handle`;
515
+ const ATTRIBUTE_ACTIVE = `${TAGNAME}-active`;
508
516
 
509
- const ATTRIBUTE_HORIZONTAL = `${SELECTOR}-horizontal`;
517
+ const ATTRIBUTE_HANDLE = `${TAGNAME}-handle`;
510
518
 
511
- const ATTRIBUTE_SEPARATOR = `${SELECTOR}-separator`;
519
+ const ATTRIBUTE_HORIZONTAL = `${TAGNAME}-horizontal`;
512
520
 
513
- const KEYS_ABSOLUTE: Set<string> = new Set(['End', 'Home']);
521
+ const ATTRIBUTE_SEPARATOR = `${TAGNAME}-separator`;
514
522
 
515
- const KEYS_HORIZONTAL: Set<string> = new Set(['ArrowDown', 'ArrowUp']);
523
+ const KEYS_ABSOLUTE = new Set(['End', 'Home']);
516
524
 
517
- const KEYS_NEGATIVE: Set<string> = new Set(['ArrowLeft', 'ArrowUp']);
525
+ const KEYS_HORIZONTAL = new Set(['ArrowDown', 'ArrowUp']);
518
526
 
519
- const KEYS_VERTICAL: Set<string> = new Set(['ArrowLeft', 'ArrowRight']);
527
+ const KEYS_NEGATIVE = new Set(['ArrowLeft', 'ArrowUp']);
520
528
 
521
- const KEYS_ALL: Set<string> = new Set([...KEYS_ABSOLUTE, ...KEYS_HORIZONTAL, ...KEYS_VERTICAL]);
529
+ const KEYS_VERTICAL = new Set(['ArrowLeft', 'ArrowRight']);
522
530
 
523
- const MAPPED_ELEMENTS: WeakMap<HTMLElement, OuiSplitter> = new WeakMap();
531
+ const KEYS_ALL = new Set([...KEYS_ABSOLUTE, ...KEYS_HORIZONTAL, ...KEYS_VERTICAL]);
524
532
 
525
- const MESSAGE = `<${SELECTOR}> must have exactly two panels.`;
533
+ const MAPPED_ELEMENTS = new WeakMap<HTMLElement, OuiSplitter>();
534
+
535
+ const MESSAGE = `<${TAGNAME}> must have exactly two panels.`;
526
536
 
527
537
  const METHODS_CONNECT = ['delete', 'set'] as const;
528
538
 
@@ -540,7 +550,7 @@ const RESIZE_OBSERVER: ResizeObserver = new ResizeObserver(onObservation);
540
550
 
541
551
  const SELECTOR_HANDLE = `[${ATTRIBUTE_HANDLE}]`;
542
552
 
543
- const STYLING_TOGGLER: StyleToggler = toggleStyles(document.body, {
553
+ const STYLING_TOGGLER = toggleStyles(document.body, {
544
554
  touchAction: 'none',
545
555
  userSelect: 'none',
546
556
  webkitUserSelect: 'none',
@@ -554,9 +564,9 @@ let frame: DOMHighResTimeStamp | undefined;
554
564
 
555
565
  let splitter: OuiSplitter | undefined;
556
566
 
557
- //
567
+ // #endregion
558
568
 
559
- customElements.define(SELECTOR, OuiSplitterElement);
569
+ // #region Initialization
560
570
 
561
571
  on(document, 'keydown', onKeydown);
562
572
  on(document, 'mousedown', onPointerdown);
@@ -564,3 +574,7 @@ on(document, 'pointermove', onPointermove);
564
574
  on(document, 'pointerup', onPointerup);
565
575
  on(document, 'touchcancel', onPointerup);
566
576
  on(document, 'touchstart', onPointerdown, {passive: false});
577
+
578
+ customElements.define(TAGNAME, OuiSplitterElement);
579
+
580
+ // #endregion