@y14e/portal 1.2.27 → 1.2.29

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/README.md CHANGED
@@ -13,11 +13,11 @@ npm i @y14e/portal
13
13
  import { createPortal } from '@y14e/portal';
14
14
 
15
15
  // CDNs
16
- import { createPortal } from 'https://esm.sh/@y14e/portal@1.2.27';
16
+ import { createPortal } from 'https://esm.sh/@y14e/portal@1.2.29';
17
17
  // or
18
- import { createPortal } from 'https://cdn.jsdelivr.net/npm/@y14e/portal@1.2.27/+esm';
18
+ import { createPortal } from 'https://cdn.jsdelivr.net/npm/@y14e/portal@1.2.29/+esm';
19
19
  // or
20
- import { createPortal } from 'https://esm.unpkg.com/@y14e/portal@1.2.27';
20
+ import { createPortal } from 'https://esm.unpkg.com/@y14e/portal@1.2.29';
21
21
  ```
22
22
 
23
23
  ## 📦 APIs
@@ -388,7 +388,6 @@ var Portal = class {
388
388
  #exitSentinel;
389
389
  #focusables = /* @__PURE__ */ new Set();
390
390
  #controller = null;
391
- #timer;
392
391
  #isDestroyed = false;
393
392
  constructor(host, container) {
394
393
  this.#host = host;
@@ -408,10 +407,6 @@ var Portal = class {
408
407
  this.#isDestroyed = true;
409
408
  this.#controller?.abort();
410
409
  this.#controller = null;
411
- if (this.#timer !== void 0) {
412
- cancelAnimationFrame(this.#timer);
413
- this.#timer = void 0;
414
- }
415
410
  restoreAttributes([...this.#focusables]);
416
411
  this.#focusables.clear();
417
412
  this.#exitSentinel.after(this.#host);
@@ -429,9 +424,6 @@ var Portal = class {
429
424
  [this.#entranceSentinel, this.#exitSentinel].forEach((sentinel) => {
430
425
  sentinel.addEventListener("focus", this.#onFocus, { signal });
431
426
  });
432
- if (!(this.#host instanceof HTMLElement)) {
433
- return;
434
- }
435
427
  this.#host.addEventListener("keydown", this.#onKeyDown, { signal });
436
428
  this.#host.setAttribute("data-portaled", "");
437
429
  }
@@ -448,15 +440,7 @@ var Portal = class {
448
440
  }
449
441
  this.#update();
450
442
  const first = [...this.#focusables][0];
451
- if (first) {
452
- focusElement(first);
453
- } else {
454
- const next = getNextFocusable(document.body, {
455
- anchor: this.#exitSentinel,
456
- composed: true
457
- });
458
- next && focusElement(next);
459
- }
443
+ first ? focusElement(first) : this.#moveFocus("next");
460
444
  } else {
461
445
  if (this.#host.contains(previous)) {
462
446
  this.#moveFocus("next");
@@ -464,18 +448,13 @@ var Portal = class {
464
448
  }
465
449
  this.#update();
466
450
  const last = [...this.#focusables].at(-1);
467
- if (last) {
468
- focusElement(last);
469
- } else {
470
- const previous2 = getPreviousFocusable(document.body, {
471
- anchor: this.#entranceSentinel,
472
- composed: true
473
- });
474
- previous2 && focusElement(previous2);
475
- }
451
+ last ? focusElement(last) : this.#moveFocus("previous");
476
452
  }
477
453
  };
478
454
  #onKeyDown = (event) => {
455
+ if (!(event instanceof KeyboardEvent)) {
456
+ return;
457
+ }
479
458
  const { key, altKey, ctrlKey, metaKey, shiftKey } = event;
480
459
  if (key !== "Tab" || altKey || ctrlKey || metaKey) {
481
460
  return;
@@ -526,13 +505,7 @@ var Portal = class {
526
505
  return sentinel;
527
506
  }
528
507
  #focusSentinel(isPrevious) {
529
- const sentinel = isPrevious ? this.#entranceSentinel : this.#exitSentinel;
530
- if (isPrevious) {
531
- sentinel.focus();
532
- } else {
533
- this.#timer && cancelAnimationFrame(this.#timer);
534
- this.#timer = requestAnimationFrame(() => sentinel.focus());
535
- }
508
+ (isPrevious ? this.#entranceSentinel : this.#exitSentinel).focus();
536
509
  }
537
510
  #getFocusables() {
538
511
  return getFocusables(this.#host, {
@@ -564,7 +537,7 @@ function containsComposed2(container, element) {
564
537
  * Lightweight DOM portal (teleport) utility with fully focus management.
565
538
  * Designed for accessible dialogs, menus, overlays, popovers.
566
539
  *
567
- * @version 1.2.27
540
+ * @version 1.2.29
568
541
  * @author Yusuke Kamiyamane
569
542
  * @license MIT
570
543
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -576,7 +549,7 @@ function containsComposed2(container, element) {
576
549
  (**
577
550
  * Attributes Utils
578
551
  *
579
- * @version 1.1.2
552
+ * @version 1.1.3
580
553
  * @author Yusuke Kamiyamane
581
554
  * @license MIT
582
555
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -589,7 +562,7 @@ power-focusable/dist/index.js:
589
562
  * High-precision focus management utility with full composed tree support.
590
563
  * Handles complex focus rules including tabindex ordering, radio groups, inert.
591
564
  *
592
- * @version 4.3.6
565
+ * @version 4.3.8
593
566
  * @author Yusuke Kamiyamane
594
567
  * @license MIT
595
568
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -386,7 +386,6 @@ var Portal = class {
386
386
  #exitSentinel;
387
387
  #focusables = /* @__PURE__ */ new Set();
388
388
  #controller = null;
389
- #timer;
390
389
  #isDestroyed = false;
391
390
  constructor(host, container) {
392
391
  this.#host = host;
@@ -406,10 +405,6 @@ var Portal = class {
406
405
  this.#isDestroyed = true;
407
406
  this.#controller?.abort();
408
407
  this.#controller = null;
409
- if (this.#timer !== void 0) {
410
- cancelAnimationFrame(this.#timer);
411
- this.#timer = void 0;
412
- }
413
408
  restoreAttributes([...this.#focusables]);
414
409
  this.#focusables.clear();
415
410
  this.#exitSentinel.after(this.#host);
@@ -427,9 +422,6 @@ var Portal = class {
427
422
  [this.#entranceSentinel, this.#exitSentinel].forEach((sentinel) => {
428
423
  sentinel.addEventListener("focus", this.#onFocus, { signal });
429
424
  });
430
- if (!(this.#host instanceof HTMLElement)) {
431
- return;
432
- }
433
425
  this.#host.addEventListener("keydown", this.#onKeyDown, { signal });
434
426
  this.#host.setAttribute("data-portaled", "");
435
427
  }
@@ -446,15 +438,7 @@ var Portal = class {
446
438
  }
447
439
  this.#update();
448
440
  const first = [...this.#focusables][0];
449
- if (first) {
450
- focusElement(first);
451
- } else {
452
- const next = getNextFocusable(document.body, {
453
- anchor: this.#exitSentinel,
454
- composed: true
455
- });
456
- next && focusElement(next);
457
- }
441
+ first ? focusElement(first) : this.#moveFocus("next");
458
442
  } else {
459
443
  if (this.#host.contains(previous)) {
460
444
  this.#moveFocus("next");
@@ -462,18 +446,13 @@ var Portal = class {
462
446
  }
463
447
  this.#update();
464
448
  const last = [...this.#focusables].at(-1);
465
- if (last) {
466
- focusElement(last);
467
- } else {
468
- const previous2 = getPreviousFocusable(document.body, {
469
- anchor: this.#entranceSentinel,
470
- composed: true
471
- });
472
- previous2 && focusElement(previous2);
473
- }
449
+ last ? focusElement(last) : this.#moveFocus("previous");
474
450
  }
475
451
  };
476
452
  #onKeyDown = (event) => {
453
+ if (!(event instanceof KeyboardEvent)) {
454
+ return;
455
+ }
477
456
  const { key, altKey, ctrlKey, metaKey, shiftKey } = event;
478
457
  if (key !== "Tab" || altKey || ctrlKey || metaKey) {
479
458
  return;
@@ -524,13 +503,7 @@ var Portal = class {
524
503
  return sentinel;
525
504
  }
526
505
  #focusSentinel(isPrevious) {
527
- const sentinel = isPrevious ? this.#entranceSentinel : this.#exitSentinel;
528
- if (isPrevious) {
529
- sentinel.focus();
530
- } else {
531
- this.#timer && cancelAnimationFrame(this.#timer);
532
- this.#timer = requestAnimationFrame(() => sentinel.focus());
533
- }
506
+ (isPrevious ? this.#entranceSentinel : this.#exitSentinel).focus();
534
507
  }
535
508
  #getFocusables() {
536
509
  return getFocusables(this.#host, {
@@ -562,7 +535,7 @@ function containsComposed2(container, element) {
562
535
  * Lightweight DOM portal (teleport) utility with fully focus management.
563
536
  * Designed for accessible dialogs, menus, overlays, popovers.
564
537
  *
565
- * @version 1.2.27
538
+ * @version 1.2.29
566
539
  * @author Yusuke Kamiyamane
567
540
  * @license MIT
568
541
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -574,7 +547,7 @@ function containsComposed2(container, element) {
574
547
  (**
575
548
  * Attributes Utils
576
549
  *
577
- * @version 1.1.2
550
+ * @version 1.1.3
578
551
  * @author Yusuke Kamiyamane
579
552
  * @license MIT
580
553
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -587,7 +560,7 @@ power-focusable/dist/index.js:
587
560
  * High-precision focus management utility with full composed tree support.
588
561
  * Handles complex focus rules including tabindex ordering, radio groups, inert.
589
562
  *
590
- * @version 4.3.6
563
+ * @version 4.3.8
591
564
  * @author Yusuke Kamiyamane
592
565
  * @license MIT
593
566
  * @copyright Copyright (c) Yusuke Kamiyamane
package/dist/index.cjs CHANGED
@@ -31,7 +31,6 @@ var Portal = class {
31
31
  #exitSentinel;
32
32
  #focusables = /* @__PURE__ */ new Set();
33
33
  #controller = null;
34
- #timer;
35
34
  #isDestroyed = false;
36
35
  constructor(host, container) {
37
36
  this.#host = host;
@@ -51,10 +50,6 @@ var Portal = class {
51
50
  this.#isDestroyed = true;
52
51
  this.#controller?.abort();
53
52
  this.#controller = null;
54
- if (this.#timer !== void 0) {
55
- cancelAnimationFrame(this.#timer);
56
- this.#timer = void 0;
57
- }
58
53
  attributesUtils.restoreAttributes([...this.#focusables]);
59
54
  this.#focusables.clear();
60
55
  this.#exitSentinel.after(this.#host);
@@ -72,9 +67,6 @@ var Portal = class {
72
67
  [this.#entranceSentinel, this.#exitSentinel].forEach((sentinel) => {
73
68
  sentinel.addEventListener("focus", this.#onFocus, { signal });
74
69
  });
75
- if (!(this.#host instanceof HTMLElement)) {
76
- return;
77
- }
78
70
  this.#host.addEventListener("keydown", this.#onKeyDown, { signal });
79
71
  this.#host.setAttribute("data-portaled", "");
80
72
  }
@@ -91,15 +83,7 @@ var Portal = class {
91
83
  }
92
84
  this.#update();
93
85
  const first = [...this.#focusables][0];
94
- if (first) {
95
- powerFocusable.focusElement(first);
96
- } else {
97
- const next = powerFocusable.getNextFocusable(document.body, {
98
- anchor: this.#exitSentinel,
99
- composed: true
100
- });
101
- next && powerFocusable.focusElement(next);
102
- }
86
+ first ? powerFocusable.focusElement(first) : this.#moveFocus("next");
103
87
  } else {
104
88
  if (this.#host.contains(previous)) {
105
89
  this.#moveFocus("next");
@@ -107,18 +91,13 @@ var Portal = class {
107
91
  }
108
92
  this.#update();
109
93
  const last = [...this.#focusables].at(-1);
110
- if (last) {
111
- powerFocusable.focusElement(last);
112
- } else {
113
- const previous2 = powerFocusable.getPreviousFocusable(document.body, {
114
- anchor: this.#entranceSentinel,
115
- composed: true
116
- });
117
- previous2 && powerFocusable.focusElement(previous2);
118
- }
94
+ last ? powerFocusable.focusElement(last) : this.#moveFocus("previous");
119
95
  }
120
96
  };
121
97
  #onKeyDown = (event) => {
98
+ if (!(event instanceof KeyboardEvent)) {
99
+ return;
100
+ }
122
101
  const { key, altKey, ctrlKey, metaKey, shiftKey } = event;
123
102
  if (key !== "Tab" || altKey || ctrlKey || metaKey) {
124
103
  return;
@@ -169,13 +148,7 @@ var Portal = class {
169
148
  return sentinel;
170
149
  }
171
150
  #focusSentinel(isPrevious) {
172
- const sentinel = isPrevious ? this.#entranceSentinel : this.#exitSentinel;
173
- if (isPrevious) {
174
- sentinel.focus();
175
- } else {
176
- this.#timer && cancelAnimationFrame(this.#timer);
177
- this.#timer = requestAnimationFrame(() => sentinel.focus());
178
- }
151
+ (isPrevious ? this.#entranceSentinel : this.#exitSentinel).focus();
179
152
  }
180
153
  #getFocusables() {
181
154
  return powerFocusable.getFocusables(this.#host, {
@@ -207,7 +180,7 @@ function containsComposed(container, element) {
207
180
  * Lightweight DOM portal (teleport) utility with fully focus management.
208
181
  * Designed for accessible dialogs, menus, overlays, popovers.
209
182
  *
210
- * @version 1.2.27
183
+ * @version 1.2.29
211
184
  * @author Yusuke Kamiyamane
212
185
  * @license MIT
213
186
  * @copyright Copyright (c) Yusuke Kamiyamane
package/dist/index.d.cts CHANGED
@@ -3,7 +3,7 @@
3
3
  * Lightweight DOM portal (teleport) utility with fully focus management.
4
4
  * Designed for accessible dialogs, menus, overlays, popovers.
5
5
  *
6
- * @version 1.2.27
6
+ * @version 1.2.29
7
7
  * @author Yusuke Kamiyamane
8
8
  * @license MIT
9
9
  * @copyright Copyright (c) Yusuke Kamiyamane
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  * Lightweight DOM portal (teleport) utility with fully focus management.
4
4
  * Designed for accessible dialogs, menus, overlays, popovers.
5
5
  *
6
- * @version 1.2.27
6
+ * @version 1.2.29
7
7
  * @author Yusuke Kamiyamane
8
8
  * @license MIT
9
9
  * @copyright Copyright (c) Yusuke Kamiyamane
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { restoreAttributes, saveAttributes } from '@y14e/attributes-utils';
2
- import { focusElement, getNextFocusable, getPreviousFocusable, getActiveElement, getFocusables } from 'power-focusable';
2
+ import { focusElement, getActiveElement, getFocusables, getPreviousFocusable, getNextFocusable } from 'power-focusable';
3
3
 
4
4
  // src/index.ts
5
5
  var VISUALLY_HIDDEN_CSS = `border: 0; clip: rect(0, 0, 0, 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; user-select: none; white-space: nowrap; width: 1px;`;
@@ -29,7 +29,6 @@ var Portal = class {
29
29
  #exitSentinel;
30
30
  #focusables = /* @__PURE__ */ new Set();
31
31
  #controller = null;
32
- #timer;
33
32
  #isDestroyed = false;
34
33
  constructor(host, container) {
35
34
  this.#host = host;
@@ -49,10 +48,6 @@ var Portal = class {
49
48
  this.#isDestroyed = true;
50
49
  this.#controller?.abort();
51
50
  this.#controller = null;
52
- if (this.#timer !== void 0) {
53
- cancelAnimationFrame(this.#timer);
54
- this.#timer = void 0;
55
- }
56
51
  restoreAttributes([...this.#focusables]);
57
52
  this.#focusables.clear();
58
53
  this.#exitSentinel.after(this.#host);
@@ -70,9 +65,6 @@ var Portal = class {
70
65
  [this.#entranceSentinel, this.#exitSentinel].forEach((sentinel) => {
71
66
  sentinel.addEventListener("focus", this.#onFocus, { signal });
72
67
  });
73
- if (!(this.#host instanceof HTMLElement)) {
74
- return;
75
- }
76
68
  this.#host.addEventListener("keydown", this.#onKeyDown, { signal });
77
69
  this.#host.setAttribute("data-portaled", "");
78
70
  }
@@ -89,15 +81,7 @@ var Portal = class {
89
81
  }
90
82
  this.#update();
91
83
  const first = [...this.#focusables][0];
92
- if (first) {
93
- focusElement(first);
94
- } else {
95
- const next = getNextFocusable(document.body, {
96
- anchor: this.#exitSentinel,
97
- composed: true
98
- });
99
- next && focusElement(next);
100
- }
84
+ first ? focusElement(first) : this.#moveFocus("next");
101
85
  } else {
102
86
  if (this.#host.contains(previous)) {
103
87
  this.#moveFocus("next");
@@ -105,18 +89,13 @@ var Portal = class {
105
89
  }
106
90
  this.#update();
107
91
  const last = [...this.#focusables].at(-1);
108
- if (last) {
109
- focusElement(last);
110
- } else {
111
- const previous2 = getPreviousFocusable(document.body, {
112
- anchor: this.#entranceSentinel,
113
- composed: true
114
- });
115
- previous2 && focusElement(previous2);
116
- }
92
+ last ? focusElement(last) : this.#moveFocus("previous");
117
93
  }
118
94
  };
119
95
  #onKeyDown = (event) => {
96
+ if (!(event instanceof KeyboardEvent)) {
97
+ return;
98
+ }
120
99
  const { key, altKey, ctrlKey, metaKey, shiftKey } = event;
121
100
  if (key !== "Tab" || altKey || ctrlKey || metaKey) {
122
101
  return;
@@ -167,13 +146,7 @@ var Portal = class {
167
146
  return sentinel;
168
147
  }
169
148
  #focusSentinel(isPrevious) {
170
- const sentinel = isPrevious ? this.#entranceSentinel : this.#exitSentinel;
171
- if (isPrevious) {
172
- sentinel.focus();
173
- } else {
174
- this.#timer && cancelAnimationFrame(this.#timer);
175
- this.#timer = requestAnimationFrame(() => sentinel.focus());
176
- }
149
+ (isPrevious ? this.#entranceSentinel : this.#exitSentinel).focus();
177
150
  }
178
151
  #getFocusables() {
179
152
  return getFocusables(this.#host, {
@@ -205,7 +178,7 @@ function containsComposed(container, element) {
205
178
  * Lightweight DOM portal (teleport) utility with fully focus management.
206
179
  * Designed for accessible dialogs, menus, overlays, popovers.
207
180
  *
208
- * @version 1.2.27
181
+ * @version 1.2.29
209
182
  * @author Yusuke Kamiyamane
210
183
  * @license MIT
211
184
  * @copyright Copyright (c) Yusuke Kamiyamane
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@y14e/portal",
3
- "version": "1.2.27",
3
+ "version": "1.2.29",
4
4
  "description": "Lightweight DOM portal (teleport) utility with fully focus management",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -55,7 +55,7 @@
55
55
  "node": ">=18"
56
56
  },
57
57
  "dependencies": {
58
- "@y14e/attributes-utils": "^1.1.2",
59
- "power-focusable": "^4.3.6"
58
+ "@y14e/attributes-utils": "^1.1.3",
59
+ "power-focusable": "^4.3.8"
60
60
  }
61
61
  }