@y14e/portal 0.0.3 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -11
- package/dist/index.cjs +37 -41
- package/dist/index.d.cts +4 -8
- package/dist/index.d.ts +4 -8
- package/dist/index.js +37 -41
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Portal
|
|
2
2
|
|
|
3
|
-
Lightweight DOM portal (teleport) utility with fully focus management. Designed for accessible dialogs, menus, overlays, popovers
|
|
3
|
+
Lightweight DOM portal (teleport) utility with fully focus management. Designed for accessible dialogs, menus, overlays, popovers.
|
|
4
4
|
|
|
5
5
|
> [!NOTE]
|
|
6
6
|
> Focus traversal works across portals using invisible sentinels and composed-tree-aware focus detection powered by [Power Focusable](https://github.com/y14e/power-focusable).
|
|
@@ -27,18 +27,12 @@ import { createPortal } from 'https://unpkg.com/@y14e/portal/dist/index.js';
|
|
|
27
27
|
|
|
28
28
|
### `createPortal`
|
|
29
29
|
|
|
30
|
-
Creates a portal and preserves keyboard focus
|
|
30
|
+
Creates a portal and preserves keyboard focus order between the original DOM and the portal.
|
|
31
31
|
|
|
32
32
|
```ts
|
|
33
|
-
const
|
|
34
|
-
// =>
|
|
33
|
+
const cleanup = createPortal(source, target);
|
|
34
|
+
// => () => void
|
|
35
35
|
//
|
|
36
36
|
// source: Element
|
|
37
|
-
//
|
|
38
|
-
|
|
39
|
-
// Element
|
|
40
|
-
console.log(portal.element);
|
|
41
|
-
|
|
42
|
-
// Cleanup
|
|
43
|
-
portal.cleanup();
|
|
37
|
+
// target (optional): Element (default: <body>)
|
|
44
38
|
```
|
package/dist/index.cjs
CHANGED
|
@@ -7,12 +7,12 @@ function getFocusables(container = document.body, options = {}) {
|
|
|
7
7
|
console.warn("Invalid container element. Fallback: <body> element.");
|
|
8
8
|
container = document.body;
|
|
9
9
|
}
|
|
10
|
-
const { composed = false, filter = () => true } = options;
|
|
10
|
+
const { composed = false, filter = () => true, include } = options;
|
|
11
11
|
const elements = [];
|
|
12
|
-
if (composed) {
|
|
12
|
+
if (composed || typeof include === "function") {
|
|
13
13
|
let traverse2 = function(node) {
|
|
14
14
|
if (node instanceof Element) {
|
|
15
|
-
if (isFocusable(node)) {
|
|
15
|
+
if (isFocusable(node) || include?.(node)) {
|
|
16
16
|
elements[elements.length] = node;
|
|
17
17
|
}
|
|
18
18
|
}
|
|
@@ -85,9 +85,10 @@ function getRelativeFocusable(container, offset, options) {
|
|
|
85
85
|
anchor = getActiveElement(),
|
|
86
86
|
composed = false,
|
|
87
87
|
filter = () => true,
|
|
88
|
+
include,
|
|
88
89
|
wrap = false
|
|
89
90
|
} = options;
|
|
90
|
-
const focusables = getFocusables(container, { composed, filter });
|
|
91
|
+
const focusables = getFocusables(container, { composed, filter, include });
|
|
91
92
|
const { length } = focusables;
|
|
92
93
|
if (!length) {
|
|
93
94
|
return null;
|
|
@@ -253,39 +254,30 @@ function isUngroupedRadio(element) {
|
|
|
253
254
|
|
|
254
255
|
// src/index.ts
|
|
255
256
|
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;`;
|
|
256
|
-
function createPortal(source,
|
|
257
|
+
function createPortal(source, target = document.body) {
|
|
257
258
|
if (!(source instanceof Element)) {
|
|
258
259
|
throw new Error("Invalid source element");
|
|
259
260
|
}
|
|
260
|
-
if (!(
|
|
261
|
-
console.warn("Invalid
|
|
262
|
-
|
|
261
|
+
if (!(target instanceof Element)) {
|
|
262
|
+
console.warn("Invalid target element. Fallback: <body> element.");
|
|
263
|
+
target = document.body;
|
|
263
264
|
}
|
|
264
|
-
const portal = new Portal(source,
|
|
265
|
-
return
|
|
266
|
-
element: portal.getElement(),
|
|
267
|
-
cleanup: () => portal.destroy()
|
|
268
|
-
};
|
|
265
|
+
const portal = new Portal(source, target);
|
|
266
|
+
return () => portal.destroy();
|
|
269
267
|
}
|
|
270
268
|
var Portal = class {
|
|
271
269
|
#source;
|
|
272
|
-
#
|
|
273
|
-
#portal;
|
|
270
|
+
#target;
|
|
274
271
|
#entranceSentinel;
|
|
275
272
|
#exitSentinel;
|
|
276
|
-
#focusables = [];
|
|
277
273
|
#tabIndexes = /* @__PURE__ */ new WeakMap();
|
|
278
274
|
#controller = null;
|
|
279
275
|
#isDestroyed = false;
|
|
280
|
-
constructor(source,
|
|
276
|
+
constructor(source, target) {
|
|
281
277
|
this.#source = source;
|
|
282
|
-
this.#
|
|
283
|
-
this.#portal = document.createElement("div");
|
|
284
|
-
this.#portal.setAttribute("data-portal", "");
|
|
285
|
-
this.#portal.setAttribute("tabindex", "-1");
|
|
278
|
+
this.#target = target;
|
|
286
279
|
this.#entranceSentinel = this.#createSentinel();
|
|
287
280
|
this.#exitSentinel = this.#createSentinel();
|
|
288
|
-
this.#focusables = getFocusables(this.#source, { composed: true });
|
|
289
281
|
this.#initialize();
|
|
290
282
|
}
|
|
291
283
|
destroy() {
|
|
@@ -295,7 +287,10 @@ var Portal = class {
|
|
|
295
287
|
this.#isDestroyed = true;
|
|
296
288
|
this.#controller?.abort();
|
|
297
289
|
this.#controller = null;
|
|
298
|
-
this.#
|
|
290
|
+
this.#getFocusables().forEach((focusable) => {
|
|
291
|
+
if (!this.#tabIndexes.has(focusable)) {
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
299
294
|
const index = this.#tabIndexes.get(focusable);
|
|
300
295
|
if (index === null) {
|
|
301
296
|
focusable.removeAttribute("tabindex");
|
|
@@ -303,21 +298,16 @@ var Portal = class {
|
|
|
303
298
|
focusable.setAttribute("tabindex", String(index));
|
|
304
299
|
}
|
|
305
300
|
});
|
|
306
|
-
this.#focusables.length = 0;
|
|
307
301
|
this.#exitSentinel.after(this.#source);
|
|
308
|
-
this.#portal.remove();
|
|
309
302
|
this.#entranceSentinel.remove();
|
|
310
303
|
this.#exitSentinel.remove();
|
|
311
|
-
|
|
312
|
-
getElement() {
|
|
313
|
-
return this.#portal;
|
|
304
|
+
this.#source.removeAttribute("data-portal");
|
|
314
305
|
}
|
|
315
306
|
#initialize() {
|
|
316
307
|
this.#source.before(this.#entranceSentinel);
|
|
317
308
|
this.#entranceSentinel.after(this.#exitSentinel);
|
|
318
|
-
this.#
|
|
319
|
-
this.#
|
|
320
|
-
this.#focusables.forEach((focusable) => {
|
|
309
|
+
this.#target.append(this.#source);
|
|
310
|
+
this.#getFocusables().forEach((focusable) => {
|
|
321
311
|
const index = focusable.getAttribute("tabindex")?.trim();
|
|
322
312
|
this.#tabIndexes.set(focusable, index === null ? null : Number(index));
|
|
323
313
|
focusable.setAttribute("tabindex", "-1");
|
|
@@ -332,6 +322,7 @@ var Portal = class {
|
|
|
332
322
|
capture: true,
|
|
333
323
|
signal
|
|
334
324
|
});
|
|
325
|
+
this.#source.setAttribute("data-portal", "");
|
|
335
326
|
}
|
|
336
327
|
#onFocusIn = (event) => {
|
|
337
328
|
const current = event.target;
|
|
@@ -343,14 +334,14 @@ var Portal = class {
|
|
|
343
334
|
if (this.#source.contains(before)) {
|
|
344
335
|
this.#focusOutside("backward");
|
|
345
336
|
} else {
|
|
346
|
-
const first = this.#
|
|
337
|
+
const first = this.#getFocusables()[0];
|
|
347
338
|
first && focus(first);
|
|
348
339
|
}
|
|
349
340
|
} else if (current === this.#exitSentinel) {
|
|
350
341
|
if (this.#source.contains(before)) {
|
|
351
342
|
this.#focusOutside("forward");
|
|
352
343
|
} else {
|
|
353
|
-
const last = this.#
|
|
344
|
+
const last = this.#getFocusables().at(-1);
|
|
354
345
|
last && focus(last);
|
|
355
346
|
}
|
|
356
347
|
}
|
|
@@ -366,16 +357,16 @@ var Portal = class {
|
|
|
366
357
|
if (!this.#source.contains(active)) {
|
|
367
358
|
return;
|
|
368
359
|
}
|
|
369
|
-
if (!this.#
|
|
360
|
+
if (!this.#getFocusables().length) {
|
|
370
361
|
event.preventDefault();
|
|
371
362
|
(event.shiftKey ? this.#entranceSentinel : this.#exitSentinel).focus();
|
|
372
363
|
}
|
|
373
|
-
const index = this.#
|
|
364
|
+
const index = this.#getFocusables().indexOf(active);
|
|
374
365
|
if (index === -1) {
|
|
375
366
|
return;
|
|
376
367
|
}
|
|
377
368
|
event.preventDefault();
|
|
378
|
-
const focusable = this.#
|
|
369
|
+
const focusable = this.#getFocusables()[index + (event.shiftKey ? -1 : 1)];
|
|
379
370
|
if (focusable) {
|
|
380
371
|
focus(focusable);
|
|
381
372
|
} else {
|
|
@@ -397,6 +388,12 @@ var Portal = class {
|
|
|
397
388
|
const focusable = direction === "backward" ? getPreviousFocusable(document.body, options) : getNextFocusable(document.body, options);
|
|
398
389
|
focusable && focus(focusable);
|
|
399
390
|
}
|
|
391
|
+
#getFocusables() {
|
|
392
|
+
return getFocusables(this.#source, {
|
|
393
|
+
composed: true,
|
|
394
|
+
include: (element) => this.#tabIndexes.has(element)
|
|
395
|
+
});
|
|
396
|
+
}
|
|
400
397
|
};
|
|
401
398
|
function focus(element) {
|
|
402
399
|
"focus" in element && typeof element.focus === "function" && element.focus();
|
|
@@ -411,9 +408,9 @@ function getActiveElement2() {
|
|
|
411
408
|
/**
|
|
412
409
|
* Portal
|
|
413
410
|
* Lightweight DOM portal (teleport) utility with fully focus management.
|
|
414
|
-
* Designed for accessible dialogs, menus, overlays, popovers
|
|
411
|
+
* Designed for accessible dialogs, menus, overlays, popovers.
|
|
415
412
|
*
|
|
416
|
-
* @version 0.0
|
|
413
|
+
* @version 0.1.0
|
|
417
414
|
* @author Yusuke Kamiyamane
|
|
418
415
|
* @license MIT
|
|
419
416
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -425,10 +422,9 @@ power-focusable/dist/index.js:
|
|
|
425
422
|
(**
|
|
426
423
|
* Power Focusable
|
|
427
424
|
* High-precision focus management utility with full composed tree support.
|
|
428
|
-
* Handles complex focus rules including tabindex ordering, radio groups, inert
|
|
429
|
-
* and shadow DOM.
|
|
425
|
+
* Handles complex focus rules including tabindex ordering, radio groups, inert.
|
|
430
426
|
*
|
|
431
|
-
* @version 4.0
|
|
427
|
+
* @version 4.1.0
|
|
432
428
|
* @author Yusuke Kamiyamane
|
|
433
429
|
* @license MIT
|
|
434
430
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
package/dist/index.d.cts
CHANGED
|
@@ -1,23 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Portal
|
|
3
3
|
* Lightweight DOM portal (teleport) utility with fully focus management.
|
|
4
|
-
* Designed for accessible dialogs, menus, overlays, popovers
|
|
4
|
+
* Designed for accessible dialogs, menus, overlays, popovers.
|
|
5
5
|
*
|
|
6
|
-
* @version 0.0
|
|
6
|
+
* @version 0.1.0
|
|
7
7
|
* @author Yusuke Kamiyamane
|
|
8
8
|
* @license MIT
|
|
9
9
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
10
10
|
* @see {@link https://github.com/y14e/portal}
|
|
11
11
|
*/
|
|
12
|
-
declare function createPortal(source: Element,
|
|
13
|
-
element: Element;
|
|
14
|
-
cleanup: () => void;
|
|
15
|
-
};
|
|
12
|
+
declare function createPortal(source: Element, target?: HTMLElement): () => void;
|
|
16
13
|
declare class Portal {
|
|
17
14
|
#private;
|
|
18
|
-
constructor(source: Element,
|
|
15
|
+
constructor(source: Element, target: Element);
|
|
19
16
|
destroy(): void;
|
|
20
|
-
getElement(): HTMLElement;
|
|
21
17
|
}
|
|
22
18
|
|
|
23
19
|
export { Portal, createPortal };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,23 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Portal
|
|
3
3
|
* Lightweight DOM portal (teleport) utility with fully focus management.
|
|
4
|
-
* Designed for accessible dialogs, menus, overlays, popovers
|
|
4
|
+
* Designed for accessible dialogs, menus, overlays, popovers.
|
|
5
5
|
*
|
|
6
|
-
* @version 0.0
|
|
6
|
+
* @version 0.1.0
|
|
7
7
|
* @author Yusuke Kamiyamane
|
|
8
8
|
* @license MIT
|
|
9
9
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
10
10
|
* @see {@link https://github.com/y14e/portal}
|
|
11
11
|
*/
|
|
12
|
-
declare function createPortal(source: Element,
|
|
13
|
-
element: Element;
|
|
14
|
-
cleanup: () => void;
|
|
15
|
-
};
|
|
12
|
+
declare function createPortal(source: Element, target?: HTMLElement): () => void;
|
|
16
13
|
declare class Portal {
|
|
17
14
|
#private;
|
|
18
|
-
constructor(source: Element,
|
|
15
|
+
constructor(source: Element, target: Element);
|
|
19
16
|
destroy(): void;
|
|
20
|
-
getElement(): HTMLElement;
|
|
21
17
|
}
|
|
22
18
|
|
|
23
19
|
export { Portal, createPortal };
|
package/dist/index.js
CHANGED
|
@@ -5,12 +5,12 @@ function getFocusables(container = document.body, options = {}) {
|
|
|
5
5
|
console.warn("Invalid container element. Fallback: <body> element.");
|
|
6
6
|
container = document.body;
|
|
7
7
|
}
|
|
8
|
-
const { composed = false, filter = () => true } = options;
|
|
8
|
+
const { composed = false, filter = () => true, include } = options;
|
|
9
9
|
const elements = [];
|
|
10
|
-
if (composed) {
|
|
10
|
+
if (composed || typeof include === "function") {
|
|
11
11
|
let traverse2 = function(node) {
|
|
12
12
|
if (node instanceof Element) {
|
|
13
|
-
if (isFocusable(node)) {
|
|
13
|
+
if (isFocusable(node) || include?.(node)) {
|
|
14
14
|
elements[elements.length] = node;
|
|
15
15
|
}
|
|
16
16
|
}
|
|
@@ -83,9 +83,10 @@ function getRelativeFocusable(container, offset, options) {
|
|
|
83
83
|
anchor = getActiveElement(),
|
|
84
84
|
composed = false,
|
|
85
85
|
filter = () => true,
|
|
86
|
+
include,
|
|
86
87
|
wrap = false
|
|
87
88
|
} = options;
|
|
88
|
-
const focusables = getFocusables(container, { composed, filter });
|
|
89
|
+
const focusables = getFocusables(container, { composed, filter, include });
|
|
89
90
|
const { length } = focusables;
|
|
90
91
|
if (!length) {
|
|
91
92
|
return null;
|
|
@@ -251,39 +252,30 @@ function isUngroupedRadio(element) {
|
|
|
251
252
|
|
|
252
253
|
// src/index.ts
|
|
253
254
|
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;`;
|
|
254
|
-
function createPortal(source,
|
|
255
|
+
function createPortal(source, target = document.body) {
|
|
255
256
|
if (!(source instanceof Element)) {
|
|
256
257
|
throw new Error("Invalid source element");
|
|
257
258
|
}
|
|
258
|
-
if (!(
|
|
259
|
-
console.warn("Invalid
|
|
260
|
-
|
|
259
|
+
if (!(target instanceof Element)) {
|
|
260
|
+
console.warn("Invalid target element. Fallback: <body> element.");
|
|
261
|
+
target = document.body;
|
|
261
262
|
}
|
|
262
|
-
const portal = new Portal(source,
|
|
263
|
-
return
|
|
264
|
-
element: portal.getElement(),
|
|
265
|
-
cleanup: () => portal.destroy()
|
|
266
|
-
};
|
|
263
|
+
const portal = new Portal(source, target);
|
|
264
|
+
return () => portal.destroy();
|
|
267
265
|
}
|
|
268
266
|
var Portal = class {
|
|
269
267
|
#source;
|
|
270
|
-
#
|
|
271
|
-
#portal;
|
|
268
|
+
#target;
|
|
272
269
|
#entranceSentinel;
|
|
273
270
|
#exitSentinel;
|
|
274
|
-
#focusables = [];
|
|
275
271
|
#tabIndexes = /* @__PURE__ */ new WeakMap();
|
|
276
272
|
#controller = null;
|
|
277
273
|
#isDestroyed = false;
|
|
278
|
-
constructor(source,
|
|
274
|
+
constructor(source, target) {
|
|
279
275
|
this.#source = source;
|
|
280
|
-
this.#
|
|
281
|
-
this.#portal = document.createElement("div");
|
|
282
|
-
this.#portal.setAttribute("data-portal", "");
|
|
283
|
-
this.#portal.setAttribute("tabindex", "-1");
|
|
276
|
+
this.#target = target;
|
|
284
277
|
this.#entranceSentinel = this.#createSentinel();
|
|
285
278
|
this.#exitSentinel = this.#createSentinel();
|
|
286
|
-
this.#focusables = getFocusables(this.#source, { composed: true });
|
|
287
279
|
this.#initialize();
|
|
288
280
|
}
|
|
289
281
|
destroy() {
|
|
@@ -293,7 +285,10 @@ var Portal = class {
|
|
|
293
285
|
this.#isDestroyed = true;
|
|
294
286
|
this.#controller?.abort();
|
|
295
287
|
this.#controller = null;
|
|
296
|
-
this.#
|
|
288
|
+
this.#getFocusables().forEach((focusable) => {
|
|
289
|
+
if (!this.#tabIndexes.has(focusable)) {
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
297
292
|
const index = this.#tabIndexes.get(focusable);
|
|
298
293
|
if (index === null) {
|
|
299
294
|
focusable.removeAttribute("tabindex");
|
|
@@ -301,21 +296,16 @@ var Portal = class {
|
|
|
301
296
|
focusable.setAttribute("tabindex", String(index));
|
|
302
297
|
}
|
|
303
298
|
});
|
|
304
|
-
this.#focusables.length = 0;
|
|
305
299
|
this.#exitSentinel.after(this.#source);
|
|
306
|
-
this.#portal.remove();
|
|
307
300
|
this.#entranceSentinel.remove();
|
|
308
301
|
this.#exitSentinel.remove();
|
|
309
|
-
|
|
310
|
-
getElement() {
|
|
311
|
-
return this.#portal;
|
|
302
|
+
this.#source.removeAttribute("data-portal");
|
|
312
303
|
}
|
|
313
304
|
#initialize() {
|
|
314
305
|
this.#source.before(this.#entranceSentinel);
|
|
315
306
|
this.#entranceSentinel.after(this.#exitSentinel);
|
|
316
|
-
this.#
|
|
317
|
-
this.#
|
|
318
|
-
this.#focusables.forEach((focusable) => {
|
|
307
|
+
this.#target.append(this.#source);
|
|
308
|
+
this.#getFocusables().forEach((focusable) => {
|
|
319
309
|
const index = focusable.getAttribute("tabindex")?.trim();
|
|
320
310
|
this.#tabIndexes.set(focusable, index === null ? null : Number(index));
|
|
321
311
|
focusable.setAttribute("tabindex", "-1");
|
|
@@ -330,6 +320,7 @@ var Portal = class {
|
|
|
330
320
|
capture: true,
|
|
331
321
|
signal
|
|
332
322
|
});
|
|
323
|
+
this.#source.setAttribute("data-portal", "");
|
|
333
324
|
}
|
|
334
325
|
#onFocusIn = (event) => {
|
|
335
326
|
const current = event.target;
|
|
@@ -341,14 +332,14 @@ var Portal = class {
|
|
|
341
332
|
if (this.#source.contains(before)) {
|
|
342
333
|
this.#focusOutside("backward");
|
|
343
334
|
} else {
|
|
344
|
-
const first = this.#
|
|
335
|
+
const first = this.#getFocusables()[0];
|
|
345
336
|
first && focus(first);
|
|
346
337
|
}
|
|
347
338
|
} else if (current === this.#exitSentinel) {
|
|
348
339
|
if (this.#source.contains(before)) {
|
|
349
340
|
this.#focusOutside("forward");
|
|
350
341
|
} else {
|
|
351
|
-
const last = this.#
|
|
342
|
+
const last = this.#getFocusables().at(-1);
|
|
352
343
|
last && focus(last);
|
|
353
344
|
}
|
|
354
345
|
}
|
|
@@ -364,16 +355,16 @@ var Portal = class {
|
|
|
364
355
|
if (!this.#source.contains(active)) {
|
|
365
356
|
return;
|
|
366
357
|
}
|
|
367
|
-
if (!this.#
|
|
358
|
+
if (!this.#getFocusables().length) {
|
|
368
359
|
event.preventDefault();
|
|
369
360
|
(event.shiftKey ? this.#entranceSentinel : this.#exitSentinel).focus();
|
|
370
361
|
}
|
|
371
|
-
const index = this.#
|
|
362
|
+
const index = this.#getFocusables().indexOf(active);
|
|
372
363
|
if (index === -1) {
|
|
373
364
|
return;
|
|
374
365
|
}
|
|
375
366
|
event.preventDefault();
|
|
376
|
-
const focusable = this.#
|
|
367
|
+
const focusable = this.#getFocusables()[index + (event.shiftKey ? -1 : 1)];
|
|
377
368
|
if (focusable) {
|
|
378
369
|
focus(focusable);
|
|
379
370
|
} else {
|
|
@@ -395,6 +386,12 @@ var Portal = class {
|
|
|
395
386
|
const focusable = direction === "backward" ? getPreviousFocusable(document.body, options) : getNextFocusable(document.body, options);
|
|
396
387
|
focusable && focus(focusable);
|
|
397
388
|
}
|
|
389
|
+
#getFocusables() {
|
|
390
|
+
return getFocusables(this.#source, {
|
|
391
|
+
composed: true,
|
|
392
|
+
include: (element) => this.#tabIndexes.has(element)
|
|
393
|
+
});
|
|
394
|
+
}
|
|
398
395
|
};
|
|
399
396
|
function focus(element) {
|
|
400
397
|
"focus" in element && typeof element.focus === "function" && element.focus();
|
|
@@ -409,9 +406,9 @@ function getActiveElement2() {
|
|
|
409
406
|
/**
|
|
410
407
|
* Portal
|
|
411
408
|
* Lightweight DOM portal (teleport) utility with fully focus management.
|
|
412
|
-
* Designed for accessible dialogs, menus, overlays, popovers
|
|
409
|
+
* Designed for accessible dialogs, menus, overlays, popovers.
|
|
413
410
|
*
|
|
414
|
-
* @version 0.0
|
|
411
|
+
* @version 0.1.0
|
|
415
412
|
* @author Yusuke Kamiyamane
|
|
416
413
|
* @license MIT
|
|
417
414
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -423,10 +420,9 @@ power-focusable/dist/index.js:
|
|
|
423
420
|
(**
|
|
424
421
|
* Power Focusable
|
|
425
422
|
* High-precision focus management utility with full composed tree support.
|
|
426
|
-
* Handles complex focus rules including tabindex ordering, radio groups, inert
|
|
427
|
-
* and shadow DOM.
|
|
423
|
+
* Handles complex focus rules including tabindex ordering, radio groups, inert.
|
|
428
424
|
*
|
|
429
|
-
* @version 4.0
|
|
425
|
+
* @version 4.1.0
|
|
430
426
|
* @author Yusuke Kamiyamane
|
|
431
427
|
* @license MIT
|
|
432
428
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@y14e/portal",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "Lightweight DOM portal (teleport) utility with fully focus management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"homepage": "https://github.com/y14e/portal#readme",
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"bun-types": "latest",
|
|
51
|
-
"power-focusable": "^4.0
|
|
51
|
+
"power-focusable": "^4.1.0",
|
|
52
52
|
"tsup": "^8.0.0",
|
|
53
53
|
"typescript": "^5.6.0"
|
|
54
54
|
},
|