@oscarpalmer/oui 0.25.0 → 0.26.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/dist/js/embedded-CHK82Uh5.d.mts +76 -0
- package/dist/js/{embedded-84gxpReS.d.mts → embedded-ai6cqURc.d.mts} +21 -17
- package/dist/js/floatable/embedded.d.mts +2 -2
- package/dist/js/floatable/embedded.mjs +27 -16
- package/dist/js/floatable/standalone.d.mts +2 -2
- package/dist/js/floatable/standalone.mjs +2 -2
- package/dist/js/focus-trap/embedded.d.mts +2 -2
- package/dist/js/focus-trap/embedded.mjs +157 -79
- package/dist/js/focus-trap/standalone.d.mts +2 -1
- package/dist/js/focus-trap/standalone.mjs +3 -3
- package/dist/js/index.d.mts +3 -2
- package/dist/js/index.mjs +4 -2
- package/dist/js/internal/draggable.d.mts +2 -2
- package/dist/js/internal/draggable.mjs +2 -2
- package/dist/js/{movable-BKFgoaOl.d.mts → movable-dNqBctx3.d.mts} +16 -16
- package/dist/js/movable.d.mts +2 -2
- package/dist/js/movable.mjs +4 -4
- package/dist/js/popover.d.mts +3 -3
- package/dist/js/popover.mjs +9 -9
- package/dist/js/sortable.d.mts +2 -2
- package/dist/js/sortable.mjs +4 -4
- package/dist/js/splitter.mjs +48 -47
- package/dist/js/toolbar.d.mts +1 -0
- package/dist/js/toolbar.mjs +107 -0
- package/dist/js/tooltip.d.mts +1 -1
- package/dist/js/tooltip.mjs +7 -7
- package/package.json +13 -1
- package/src/js/floatable/embedded.ts +65 -44
- package/src/js/floatable/standalone.ts +1 -1
- package/src/js/focus-trap/embedded.ts +219 -93
- package/src/js/focus-trap/standalone.ts +4 -2
- package/src/js/index.ts +1 -0
- package/src/js/internal/draggable.ts +20 -20
- package/src/js/movable.ts +17 -17
- package/src/js/popover.ts +18 -18
- package/src/js/sortable.ts +26 -26
- package/src/js/splitter.ts +98 -96
- package/src/js/toolbar.ts +214 -0
- package/src/js/tooltip.ts +14 -10
- package/dist/js/embedded-BpwzMSEF.d.mts +0 -26
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
//#region src/js/focus-trap/embedded.d.ts
|
|
2
|
+
declare class OuiFocusTrap {
|
|
3
|
+
#private;
|
|
4
|
+
/**
|
|
5
|
+
* Is focused maintained within the _FocusTrap_ when clicking outside of it?
|
|
6
|
+
*/
|
|
7
|
+
get contain(): boolean;
|
|
8
|
+
/**
|
|
9
|
+
* Should focus be maintained within the _FocusTrap_ when clicking outside of it?
|
|
10
|
+
*/
|
|
11
|
+
set contain(value: boolean);
|
|
12
|
+
/**
|
|
13
|
+
* Is the _FocusTrap_ disabled?
|
|
14
|
+
*/
|
|
15
|
+
get disabled(): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Should the _FocusTrap_ be disabled?
|
|
18
|
+
*/
|
|
19
|
+
set disabled(value: boolean);
|
|
20
|
+
/**
|
|
21
|
+
* Is focus allowed to escape when pressing _Escape_ within the _FocusTrap_?
|
|
22
|
+
*/
|
|
23
|
+
get noescape(): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Should the _FocusTrap_ allow focus to escape when pressing _Escape_?
|
|
26
|
+
*/
|
|
27
|
+
set noescape(value: boolean);
|
|
28
|
+
constructor(state: OuiFocusTrapState);
|
|
29
|
+
/**
|
|
30
|
+
* Destroys the _FocusTrap_
|
|
31
|
+
*/
|
|
32
|
+
destroy(): void;
|
|
33
|
+
/**
|
|
34
|
+
* Disables the _FocusTrap_
|
|
35
|
+
*/
|
|
36
|
+
disable(): void;
|
|
37
|
+
/**
|
|
38
|
+
* Enables the _FocusTrap_
|
|
39
|
+
*/
|
|
40
|
+
enable(): void;
|
|
41
|
+
/**
|
|
42
|
+
* Focuses the _FocusTrap_
|
|
43
|
+
*
|
|
44
|
+
* @param last When `true`, focuses the last focusable element within the _FocusTrap_ instead of the first
|
|
45
|
+
*/
|
|
46
|
+
focus(last: boolean): void;
|
|
47
|
+
}
|
|
48
|
+
type OuiFocusTrapOptions = {
|
|
49
|
+
/**
|
|
50
|
+
* Should focus be maintained within the _FocusTrap_ when clicking outside of it?
|
|
51
|
+
*/
|
|
52
|
+
contain?: boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Should the _FocusTrap_ allow focus to escape when pressing _Escape_?
|
|
55
|
+
*/
|
|
56
|
+
noescape?: boolean;
|
|
57
|
+
};
|
|
58
|
+
type OuiFocusTrapState = {
|
|
59
|
+
disabled: boolean;
|
|
60
|
+
element: HTMLElement;
|
|
61
|
+
options: Required<OuiFocusTrapOptions>;
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Creates _(or retrieves)_ a _FocusTrap_ for an element
|
|
65
|
+
*
|
|
66
|
+
* @param element Element to trap focus within
|
|
67
|
+
* @param options _FocusTrap_ options
|
|
68
|
+
* @returns _FocusTrap_ instance
|
|
69
|
+
*/
|
|
70
|
+
declare function createFocusTrap(element: HTMLElement, options?: OuiFocusTrapOptions): OuiFocusTrap;
|
|
71
|
+
declare function removeFocusTrap(element: HTMLElement): void;
|
|
72
|
+
declare const ATTRIBUTE_FOCUSTRAP = "oui-focus-trap";
|
|
73
|
+
declare const ATTRIBUTE_FOCUSTRAP_CONTAIN = "oui-focus-trap-contain";
|
|
74
|
+
declare const ATTRIBUTE_FOCUSTRAP_NOESCAPE = "oui-focus-trap-noescape";
|
|
75
|
+
//#endregion
|
|
76
|
+
export { createFocusTrap as a, OuiFocusTrap as i, ATTRIBUTE_FOCUSTRAP_CONTAIN as n, removeFocusTrap as o, ATTRIBUTE_FOCUSTRAP_NOESCAPE as r, ATTRIBUTE_FOCUSTRAP as t };
|
|
@@ -1,12 +1,26 @@
|
|
|
1
1
|
import { RemovableEventListener } from "@oscarpalmer/toretto/models";
|
|
2
2
|
|
|
3
3
|
//#region src/js/floatable/embedded.d.ts
|
|
4
|
+
type CreateOuiFloatableOptions = {
|
|
5
|
+
/**
|
|
6
|
+
* Open the _OuiFloatable_ when created? _(defaults to `true`)_
|
|
7
|
+
*/
|
|
8
|
+
open?: boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Position of the _OuiFloatable_ _(defaults to `below`)_
|
|
11
|
+
*/
|
|
12
|
+
position?: OuiFloatablePosition;
|
|
13
|
+
};
|
|
4
14
|
declare class OuiFloatable {
|
|
5
15
|
#private;
|
|
6
16
|
/**
|
|
7
|
-
* Is the
|
|
17
|
+
* Is the _OuiFloatable_ open?
|
|
8
18
|
*/
|
|
9
19
|
get open(): boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Open or close the _OuiFloatable_
|
|
22
|
+
*/
|
|
23
|
+
set open(value: boolean);
|
|
10
24
|
constructor(state: OuiFloatableState, standalone: boolean);
|
|
11
25
|
/**
|
|
12
26
|
* Destroy the _OuiFloatable_, removing it from the DOM and cleaning up references
|
|
@@ -37,28 +51,18 @@ type OuiFloatableState = {
|
|
|
37
51
|
content: HTMLElement;
|
|
38
52
|
options: OuiFloatableOptions;
|
|
39
53
|
};
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Open the _OuiFloatable_ when created? _(defaults to `true`)_
|
|
43
|
-
*/
|
|
44
|
-
open?: boolean;
|
|
45
|
-
/**
|
|
46
|
-
* Position of the _OuiFloatable_ _(defaults to `below`)_
|
|
47
|
-
*/
|
|
48
|
-
position?: OuiFloatablePosition;
|
|
49
|
-
};
|
|
50
|
-
declare function createFloatable(anchor: HTMLElement, content: HTMLElement, options: OuiFloatableOptions, standalone: boolean): OuiFloatable;
|
|
54
|
+
declare function createEmbeddedFloatable(anchor: HTMLElement, content: HTMLElement, options: OuiFloatableOptions): OuiFloatable;
|
|
51
55
|
/**
|
|
52
|
-
* Create a
|
|
56
|
+
* Create a _OuiFloatable_ for an anchor and content element
|
|
53
57
|
*
|
|
54
58
|
* @param anchor Anchor element
|
|
55
59
|
* @param content Content element
|
|
56
|
-
* @param options
|
|
57
|
-
* @returns
|
|
60
|
+
* @param options _OuiFloatable_ options
|
|
61
|
+
* @returns _OuiFloatable_ instance
|
|
58
62
|
*/
|
|
59
|
-
declare function
|
|
63
|
+
declare function createFloatable(anchor: HTMLElement, content: HTMLElement, options?: CreateOuiFloatableOptions): OuiFloatable;
|
|
60
64
|
declare function getOnBeforeToggleListener(element: HTMLElement): RemovableEventListener;
|
|
61
65
|
declare function removeFloatable(content: HTMLElement): void;
|
|
62
66
|
declare const ATTRIBUTE_FLOATABLE = "oui-floatable";
|
|
63
67
|
//#endregion
|
|
64
|
-
export {
|
|
68
|
+
export { createEmbeddedFloatable as a, removeFloatable as c, OuiFloatablePosition as i, OuiFloatable as n, createFloatable as o, OuiFloatableOptions as r, getOnBeforeToggleListener as s, ATTRIBUTE_FLOATABLE as t };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
export { ATTRIBUTE_FLOATABLE, OuiFloatable, OuiFloatableOptions, OuiFloatablePosition,
|
|
1
|
+
import { a as createEmbeddedFloatable, c as removeFloatable, i as OuiFloatablePosition, n as OuiFloatable, o as createFloatable, r as OuiFloatableOptions, s as getOnBeforeToggleListener, t as ATTRIBUTE_FLOATABLE } from "../embedded-ai6cqURc.mjs";
|
|
2
|
+
export { ATTRIBUTE_FLOATABLE, OuiFloatable, OuiFloatableOptions, OuiFloatablePosition, createEmbeddedFloatable, createFloatable, getOnBeforeToggleListener, removeFloatable };
|
|
@@ -6,11 +6,18 @@ var OuiFloatable = class {
|
|
|
6
6
|
#destroyed = false;
|
|
7
7
|
#state;
|
|
8
8
|
/**
|
|
9
|
-
* Is the
|
|
9
|
+
* Is the _OuiFloatable_ open?
|
|
10
10
|
*/
|
|
11
11
|
get open() {
|
|
12
12
|
return this.#state.content.checkVisibility();
|
|
13
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Open or close the _OuiFloatable_
|
|
16
|
+
*/
|
|
17
|
+
set open(value) {
|
|
18
|
+
if (value === true) this.show();
|
|
19
|
+
else if (value === false) this.hide();
|
|
20
|
+
}
|
|
14
21
|
constructor(state, standalone) {
|
|
15
22
|
this.#state = state;
|
|
16
23
|
const { anchor, content } = state;
|
|
@@ -53,36 +60,39 @@ var OuiFloatable = class {
|
|
|
53
60
|
if (!this.#destroyed) setPosition(this.#state, position);
|
|
54
61
|
}
|
|
55
62
|
};
|
|
56
|
-
function createFloatable(anchor, content, options, standalone) {
|
|
57
|
-
if (!isHTMLOrSVGElement(anchor) || !isHTMLOrSVGElement(content)) throw new TypeError("Anchor and content must be an HTMLElement or SVGElement.");
|
|
58
|
-
let floatable = instances.get(content);
|
|
59
|
-
if (floatable == null) {
|
|
60
|
-
floatable = new OuiFloatable(getState(anchor, content, options), standalone);
|
|
61
|
-
instances.set(content, floatable);
|
|
62
|
-
}
|
|
63
|
-
return floatable;
|
|
64
|
-
}
|
|
65
63
|
function getAnchorName(anchor) {
|
|
66
64
|
let { anchorName } = anchor.style;
|
|
67
65
|
if (anchorName.length > 0) return anchorName;
|
|
68
66
|
index += 1;
|
|
69
67
|
return `--oui-floatable-anchor-${index}`;
|
|
70
68
|
}
|
|
69
|
+
function createEmbeddedFloatable(anchor, content, options) {
|
|
70
|
+
return createInstance(anchor, content, options, false);
|
|
71
|
+
}
|
|
71
72
|
/**
|
|
72
|
-
* Create a
|
|
73
|
+
* Create a _OuiFloatable_ for an anchor and content element
|
|
73
74
|
*
|
|
74
75
|
* @param anchor Anchor element
|
|
75
76
|
* @param content Content element
|
|
76
|
-
* @param options
|
|
77
|
-
* @returns
|
|
77
|
+
* @param options _OuiFloatable_ options
|
|
78
|
+
* @returns _OuiFloatable_ instance
|
|
78
79
|
*/
|
|
79
|
-
function
|
|
80
|
+
function createFloatable(anchor, content, options) {
|
|
80
81
|
const { open, position } = getOptions(options);
|
|
81
|
-
const floatable =
|
|
82
|
+
const floatable = createInstance(anchor, content, { position }, true);
|
|
82
83
|
floatable?.update(position);
|
|
83
84
|
if (open) floatable?.show();
|
|
84
85
|
return floatable;
|
|
85
86
|
}
|
|
87
|
+
function createInstance(anchor, content, options, standalone) {
|
|
88
|
+
if (!isHTMLOrSVGElement(anchor) || !isHTMLOrSVGElement(content)) throw new TypeError(MESSAGE);
|
|
89
|
+
let floatable = instances.get(content);
|
|
90
|
+
if (floatable == null) {
|
|
91
|
+
floatable = new OuiFloatable(getState(anchor, content, options), standalone);
|
|
92
|
+
instances.set(content, floatable);
|
|
93
|
+
}
|
|
94
|
+
return floatable;
|
|
95
|
+
}
|
|
86
96
|
function getOnBeforeToggleListener(element) {
|
|
87
97
|
return on(element, EVENT_BEFORE, (event) => {
|
|
88
98
|
const { newState, source } = event;
|
|
@@ -137,10 +147,11 @@ const ARIA_DISABLED = "aria-disabled";
|
|
|
137
147
|
const ATTRIBUTE_FLOATABLE = "oui-floatable";
|
|
138
148
|
const ATTRIBUTE_POSITION = "oui-position";
|
|
139
149
|
const EVENT_BEFORE = "beforetoggle";
|
|
150
|
+
const MESSAGE = "Anchor and content must be an HTMLElement or SVGElement";
|
|
140
151
|
const POSITIONS = Object.fromEntries(Object.entries(AREAS).map(([position, area]) => [area, position]));
|
|
141
152
|
const STATE_OPEN = "open";
|
|
142
153
|
const TRUE = "true";
|
|
143
154
|
const instances = /* @__PURE__ */ new WeakMap();
|
|
144
155
|
let index = 0;
|
|
145
156
|
//#endregion
|
|
146
|
-
export { ATTRIBUTE_FLOATABLE, OuiFloatable,
|
|
157
|
+
export { ATTRIBUTE_FLOATABLE, OuiFloatable, createEmbeddedFloatable, createFloatable, getOnBeforeToggleListener, removeFloatable };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { i as OuiFloatablePosition, n as OuiFloatable, o as
|
|
2
|
-
export { type OuiFloatable, type OuiFloatablePosition,
|
|
1
|
+
import { i as OuiFloatablePosition, n as OuiFloatable, o as createFloatable } from "../embedded-ai6cqURc.mjs";
|
|
2
|
+
export { type OuiFloatable, type OuiFloatablePosition, createFloatable };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
1
|
+
import { createFloatable } from "./embedded.mjs";
|
|
2
|
+
export { createFloatable };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as createFocusTrap, i as
|
|
2
|
-
export {
|
|
1
|
+
import { a as createFocusTrap, i as OuiFocusTrap, n as ATTRIBUTE_FOCUSTRAP_CONTAIN, o as removeFocusTrap, r as ATTRIBUTE_FOCUSTRAP_NOESCAPE, t as ATTRIBUTE_FOCUSTRAP } from "../embedded-CHK82Uh5.mjs";
|
|
2
|
+
export { ATTRIBUTE_FOCUSTRAP, ATTRIBUTE_FOCUSTRAP_CONTAIN, ATTRIBUTE_FOCUSTRAP_NOESCAPE, OuiFocusTrap, createFocusTrap, removeFocusTrap };
|
|
@@ -1,67 +1,144 @@
|
|
|
1
1
|
import { on } from "@oscarpalmer/toretto/event";
|
|
2
|
+
import { isPlainObject } from "@oscarpalmer/atoms/is";
|
|
3
|
+
import { isHTMLOrSVGElement } from "@oscarpalmer/toretto/is";
|
|
2
4
|
import { clamp } from "@oscarpalmer/atoms/number";
|
|
3
5
|
import { findAncestor } from "@oscarpalmer/toretto/find";
|
|
4
6
|
import { getFocusable } from "@oscarpalmer/toretto/focusable";
|
|
5
7
|
//#region src/js/focus-trap/embedded.ts
|
|
6
|
-
var
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
var OuiFocusTrap = class {
|
|
9
|
+
#destroyed = false;
|
|
10
|
+
#tabIndex;
|
|
11
|
+
#state;
|
|
12
|
+
/**
|
|
13
|
+
* Is focused maintained within the _FocusTrap_ when clicking outside of it?
|
|
14
|
+
*/
|
|
11
15
|
get contain() {
|
|
12
|
-
return this.element.hasAttribute(
|
|
13
|
-
}
|
|
16
|
+
return this.#state.element.hasAttribute(ATTRIBUTE_FOCUSTRAP_CONTAIN);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Should focus be maintained within the _FocusTrap_ when clicking outside of it?
|
|
20
|
+
*/
|
|
21
|
+
set contain(value) {
|
|
22
|
+
if (value === true) this.#state.element.setAttribute(ATTRIBUTE_FOCUSTRAP_CONTAIN, "");
|
|
23
|
+
else if (value === false) this.#state.element.removeAttribute(ATTRIBUTE_FOCUSTRAP_CONTAIN);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Is the _FocusTrap_ disabled?
|
|
27
|
+
*/
|
|
28
|
+
get disabled() {
|
|
29
|
+
return this.#state.disabled;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Should the _FocusTrap_ be disabled?
|
|
33
|
+
*/
|
|
34
|
+
set disabled(value) {
|
|
35
|
+
if (value === true) this.disable();
|
|
36
|
+
else if (value === false) this.enable();
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Is focus allowed to escape when pressing _Escape_ within the _FocusTrap_?
|
|
40
|
+
*/
|
|
14
41
|
get noescape() {
|
|
15
|
-
return this.element.hasAttribute(
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
if (
|
|
22
|
-
if (
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
42
|
+
return this.#state.element.hasAttribute(ATTRIBUTE_FOCUSTRAP_NOESCAPE);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Should the _FocusTrap_ allow focus to escape when pressing _Escape_?
|
|
46
|
+
*/
|
|
47
|
+
set noescape(value) {
|
|
48
|
+
if (value === true) this.#state.element.setAttribute(ATTRIBUTE_FOCUSTRAP_NOESCAPE, "");
|
|
49
|
+
else if (value === false) this.#state.element.removeAttribute(ATTRIBUTE_FOCUSTRAP_NOESCAPE);
|
|
50
|
+
}
|
|
51
|
+
constructor(state) {
|
|
52
|
+
this.#state = state;
|
|
53
|
+
this.#tabIndex = state.element.tabIndex;
|
|
54
|
+
state.element.tabIndex = -1;
|
|
55
|
+
state.element.setAttribute(ATTRIBUTE_FOCUSTRAP, "");
|
|
56
|
+
this.contain = state.options.contain;
|
|
57
|
+
this.noescape = state.options.noescape;
|
|
58
|
+
states.set(this, state);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Destroys the _FocusTrap_
|
|
62
|
+
*/
|
|
27
63
|
destroy() {
|
|
28
|
-
this
|
|
29
|
-
|
|
64
|
+
if (this.#destroyed) return;
|
|
65
|
+
this.#destroyed = true;
|
|
66
|
+
disabled.delete(this);
|
|
67
|
+
instances.delete(this.#state.element);
|
|
68
|
+
states.delete(this);
|
|
69
|
+
this.#state.element.tabIndex = this.#tabIndex;
|
|
70
|
+
this.#state.element.removeAttribute(ATTRIBUTE_FOCUSTRAP);
|
|
71
|
+
this.#state.element.removeAttribute(ATTRIBUTE_FOCUSTRAP_CONTAIN);
|
|
72
|
+
this.#state.element.removeAttribute(ATTRIBUTE_FOCUSTRAP_NOESCAPE);
|
|
73
|
+
this.#state.element = void 0;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Disables the _FocusTrap_
|
|
77
|
+
*/
|
|
30
78
|
disable() {
|
|
31
|
-
if (!(this.disabled || this.noescape)) setDisabled(this, true);
|
|
32
|
-
}
|
|
33
|
-
disconnect() {
|
|
34
|
-
setConnected(this, false);
|
|
79
|
+
if (!this.#destroyed && !(this.disabled || this.#state.options.noescape)) setDisabled(this, this.#state, true);
|
|
35
80
|
}
|
|
81
|
+
/**
|
|
82
|
+
* Enables the _FocusTrap_
|
|
83
|
+
*/
|
|
36
84
|
enable() {
|
|
37
|
-
if (this.disabled) setDisabled(this, false);
|
|
85
|
+
if (!this.#destroyed && this.disabled) setDisabled(this, this.#state, false);
|
|
38
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
* Focuses the _FocusTrap_
|
|
89
|
+
*
|
|
90
|
+
* @param last When `true`, focuses the last focusable element within the _FocusTrap_ instead of the first
|
|
91
|
+
*/
|
|
39
92
|
focus(last) {
|
|
40
|
-
tabToTrap(this, getFocusable(this.element), this.element, last ? -1 : 0);
|
|
93
|
+
if (!this.#destroyed && !this.disabled) tabToTrap(this, getFocusable(this.#state.element), this.#state.element, last ? -1 : 0);
|
|
41
94
|
}
|
|
42
95
|
};
|
|
96
|
+
/**
|
|
97
|
+
* Creates _(or retrieves)_ a _FocusTrap_ for an element
|
|
98
|
+
*
|
|
99
|
+
* @param element Element to trap focus within
|
|
100
|
+
* @param options _FocusTrap_ options
|
|
101
|
+
* @returns _FocusTrap_ instance
|
|
102
|
+
*/
|
|
43
103
|
function createFocusTrap(element, options) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
104
|
+
if (!isHTMLOrSVGElement(element)) throw new TypeError(MESSAGE);
|
|
105
|
+
let instance = instances.get(element);
|
|
106
|
+
if (instance == null) {
|
|
107
|
+
instance = new OuiFocusTrap(getState(element, options));
|
|
108
|
+
instances.set(element, instance);
|
|
48
109
|
}
|
|
49
|
-
return
|
|
110
|
+
return instance;
|
|
111
|
+
}
|
|
112
|
+
function getOptions(element, input) {
|
|
113
|
+
const options = isPlainObject(input) ? input : {};
|
|
114
|
+
return {
|
|
115
|
+
contain: typeof options.contain === "boolean" ? options.contain : element.hasAttribute(ATTRIBUTE_FOCUSTRAP_CONTAIN),
|
|
116
|
+
noescape: typeof options.noescape === "boolean" ? options.noescape : element.hasAttribute(ATTRIBUTE_FOCUSTRAP_NOESCAPE)
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
function getState(element, options) {
|
|
120
|
+
return {
|
|
121
|
+
element,
|
|
122
|
+
disabled: false,
|
|
123
|
+
options: getOptions(element, options)
|
|
124
|
+
};
|
|
50
125
|
}
|
|
51
126
|
function onEscape(event) {
|
|
52
|
-
let element = findAncestor(event,
|
|
53
|
-
let
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
127
|
+
let element = findAncestor(event, SELECTOR);
|
|
128
|
+
let instance = instances.get(element);
|
|
129
|
+
let state = states.get(instance);
|
|
130
|
+
if (element == null || instance == null || state == null) return;
|
|
131
|
+
while (state.disabled) {
|
|
132
|
+
element = findAncestor(state.element.parentElement, SELECTOR);
|
|
133
|
+
instance = instances.get(element);
|
|
134
|
+
state = states.get(instance);
|
|
135
|
+
if (element == null || instance == null || state == null) return;
|
|
136
|
+
if (!state.disabled) break;
|
|
137
|
+
}
|
|
138
|
+
instance?.disable();
|
|
62
139
|
}
|
|
63
140
|
function onFocusIn(event) {
|
|
64
|
-
lastTarget =
|
|
141
|
+
lastTarget = instances.get(findAncestor(event, SELECTOR)) == null ? void 0 : event.target;
|
|
65
142
|
}
|
|
66
143
|
function onKeydown(event) {
|
|
67
144
|
switch (event.key) {
|
|
@@ -75,82 +152,83 @@ function onKeydown(event) {
|
|
|
75
152
|
}
|
|
76
153
|
}
|
|
77
154
|
function onPointerdown(event) {
|
|
78
|
-
const
|
|
79
|
-
const
|
|
80
|
-
if (
|
|
81
|
-
if (
|
|
155
|
+
const last = findAncestor(lastTarget, SELECTOR);
|
|
156
|
+
const next = findAncestor(event, SELECTOR);
|
|
157
|
+
if (last != null && next !== last) {
|
|
158
|
+
if (states.get(instances.get(last))?.options.contain ?? false) {
|
|
82
159
|
event.preventDefault();
|
|
83
160
|
lastTarget?.focus();
|
|
84
161
|
}
|
|
85
162
|
}
|
|
86
|
-
if (
|
|
87
|
-
for (const focusTrap of
|
|
163
|
+
if (disabled.size === 0) return;
|
|
164
|
+
for (const focusTrap of disabled) {
|
|
165
|
+
const state = states.get(focusTrap);
|
|
166
|
+
if (state != null && state.element !== next) focusTrap.enable();
|
|
167
|
+
}
|
|
88
168
|
}
|
|
89
169
|
function onTab(event) {
|
|
90
|
-
const element = findAncestor(event,
|
|
91
|
-
const
|
|
92
|
-
if (
|
|
93
|
-
if (!
|
|
170
|
+
const element = findAncestor(event, SELECTOR);
|
|
171
|
+
const instance = instances.get(element);
|
|
172
|
+
if (instance == null) return;
|
|
173
|
+
if (!instance.disabled) event.preventDefault();
|
|
94
174
|
const elements = getFocusable(element);
|
|
95
175
|
const index = elements.indexOf(event.target);
|
|
96
|
-
if (index === -1 || elements.length === 0) tabToTrap(
|
|
97
|
-
else tabToElement(
|
|
176
|
+
if (index === -1 || elements.length === 0) tabToTrap(instance, elements, element);
|
|
177
|
+
else tabToElement(instance, elements, index, event.shiftKey ? -1 : 1);
|
|
98
178
|
}
|
|
99
179
|
function removeFocusTrap(element) {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
}
|
|
103
|
-
function setConnected(focusTrap, value) {
|
|
104
|
-
if (!focusTrap.embedded || focusTrap.connected === value) return;
|
|
105
|
-
focusTrap.connected = value;
|
|
180
|
+
instances.get(element)?.destroy();
|
|
181
|
+
instances.delete(element);
|
|
106
182
|
}
|
|
107
|
-
function setDisabled(focusTrap, value) {
|
|
108
|
-
|
|
109
|
-
if (value)
|
|
110
|
-
else
|
|
183
|
+
function setDisabled(focusTrap, state, value) {
|
|
184
|
+
state.disabled = value;
|
|
185
|
+
if (value) disabled.add(focusTrap);
|
|
186
|
+
else disabled.delete(focusTrap);
|
|
111
187
|
}
|
|
112
|
-
function tabToElement(
|
|
188
|
+
function tabToElement(instance, elements, index, modifier) {
|
|
113
189
|
const { length } = elements;
|
|
114
190
|
const next = clamp(index + modifier, 0, length - 1, true);
|
|
115
|
-
if (
|
|
191
|
+
if (instance.disabled) {
|
|
116
192
|
if (index === length - 1 && next === 0 || index === 0 && next === length - 1) {
|
|
117
193
|
lastTarget = void 0;
|
|
118
|
-
|
|
194
|
+
instance.enable();
|
|
119
195
|
}
|
|
120
196
|
return;
|
|
121
197
|
}
|
|
122
198
|
const element = elements[next];
|
|
123
|
-
const elementFocusTrap =
|
|
199
|
+
const elementFocusTrap = instances.get(element);
|
|
124
200
|
if (elementFocusTrap != null) elementFocusTrap.focus(modifier === -1);
|
|
125
201
|
else {
|
|
126
202
|
elements[next].focus();
|
|
127
203
|
lastTarget = elements[next];
|
|
128
204
|
}
|
|
129
205
|
}
|
|
130
|
-
function tabToTrap(
|
|
131
|
-
if (
|
|
206
|
+
function tabToTrap(instance, elements, element, index) {
|
|
207
|
+
if (instance.disabled) {
|
|
132
208
|
lastTarget = void 0;
|
|
133
|
-
|
|
209
|
+
instance.enable();
|
|
134
210
|
} else {
|
|
135
211
|
const next = elements.length === 0 ? element : elements.at(index ?? 0);
|
|
136
212
|
next.focus();
|
|
137
213
|
lastTarget = next;
|
|
138
214
|
}
|
|
139
215
|
}
|
|
140
|
-
const
|
|
141
|
-
const
|
|
216
|
+
const ATTRIBUTE_FOCUSTRAP = "oui-focus-trap";
|
|
217
|
+
const ATTRIBUTE_FOCUSTRAP_CONTAIN = `${ATTRIBUTE_FOCUSTRAP}-contain`;
|
|
218
|
+
const ATTRIBUTE_FOCUSTRAP_NOESCAPE = `${ATTRIBUTE_FOCUSTRAP}-noescape`;
|
|
142
219
|
const EVENT_OPTIONS = {
|
|
143
220
|
capture: true,
|
|
144
221
|
passive: false
|
|
145
222
|
};
|
|
146
|
-
const
|
|
147
|
-
const
|
|
148
|
-
const
|
|
149
|
-
const
|
|
223
|
+
const MESSAGE = "Element must be an HTMLElement or SVGElement";
|
|
224
|
+
const SELECTOR = `[${ATTRIBUTE_FOCUSTRAP}]`;
|
|
225
|
+
const disabled = /* @__PURE__ */ new Set();
|
|
226
|
+
const instances = /* @__PURE__ */ new WeakMap();
|
|
227
|
+
const states = /* @__PURE__ */ new WeakMap();
|
|
150
228
|
let lastTarget;
|
|
151
229
|
on(document, "focusin", onFocusIn, EVENT_OPTIONS);
|
|
152
230
|
on(document, "keydown", onKeydown, EVENT_OPTIONS);
|
|
153
231
|
on(document, "mousedown", onPointerdown, EVENT_OPTIONS);
|
|
154
232
|
on(document, "touchstart", onPointerdown, EVENT_OPTIONS);
|
|
155
233
|
//#endregion
|
|
156
|
-
export {
|
|
234
|
+
export { ATTRIBUTE_FOCUSTRAP, ATTRIBUTE_FOCUSTRAP_CONTAIN, ATTRIBUTE_FOCUSTRAP_NOESCAPE, OuiFocusTrap, createFocusTrap, removeFocusTrap };
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import { a as createFocusTrap, i as OuiFocusTrap } from "../embedded-CHK82Uh5.mjs";
|
|
2
|
+
export { type OuiFocusTrap, createFocusTrap };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { attributable } from "../internal/attributable.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { ATTRIBUTE_FOCUSTRAP, createFocusTrap, removeFocusTrap } from "./embedded.mjs";
|
|
3
3
|
//#region src/js/focus-trap/standalone.ts
|
|
4
|
-
attributable(
|
|
4
|
+
attributable(ATTRIBUTE_FOCUSTRAP, createFocusTrap, removeFocusTrap);
|
|
5
5
|
//#endregion
|
|
6
|
-
export {};
|
|
6
|
+
export { createFocusTrap };
|
package/dist/js/index.d.mts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { OuiDialog, getDialog } from "./dialog.mjs";
|
|
2
|
-
import { i as OuiFloatablePosition, n as OuiFloatable, o as
|
|
2
|
+
import { i as OuiFloatablePosition, n as OuiFloatable, o as createFloatable } from "./embedded-ai6cqURc.mjs";
|
|
3
|
+
import { a as createFocusTrap, i as OuiFocusTrap } from "./embedded-CHK82Uh5.mjs";
|
|
3
4
|
import { OuiPopover, getPopover } from "./popover.mjs";
|
|
4
5
|
import { OuiSplitterElement } from "./splitter.mjs";
|
|
5
6
|
import { OuiTooltip, getTooltip, setTooltipDelay } from "./tooltip.mjs";
|
|
6
|
-
export { type OuiDialog, type OuiFloatable, type OuiFloatablePosition, type OuiPopover, OuiSplitterElement, type OuiTooltip,
|
|
7
|
+
export { type OuiDialog, type OuiFloatable, type OuiFloatablePosition, type OuiFocusTrap, type OuiPopover, OuiSplitterElement, type OuiTooltip, createFloatable, createFocusTrap, getDialog, getPopover, getTooltip, setTooltipDelay };
|
package/dist/js/index.mjs
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createFloatable } from "./floatable/embedded.mjs";
|
|
2
2
|
import { getDialog } from "./dialog.mjs";
|
|
3
3
|
import "./movable.mjs";
|
|
4
4
|
import "./sortable.mjs";
|
|
5
|
+
import "./toolbar.mjs";
|
|
5
6
|
import "./floatable/standalone.mjs";
|
|
7
|
+
import { createFocusTrap } from "./focus-trap/embedded.mjs";
|
|
6
8
|
import "./focus-trap/standalone.mjs";
|
|
7
9
|
import { getPopover } from "./popover.mjs";
|
|
8
10
|
import { OuiSplitterElement } from "./splitter.mjs";
|
|
9
11
|
import { getTooltip, setTooltipDelay } from "./tooltip.mjs";
|
|
10
|
-
export { OuiSplitterElement,
|
|
12
|
+
export { OuiSplitterElement, createFloatable, createFocusTrap, getDialog, getPopover, getTooltip, setTooltipDelay };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
export { DragMovePosition,
|
|
1
|
+
import { a as OuiDraggable, i as DraggableState, n as DragMovePosition, o as addDraggable, r as DraggableBound, s as removeDraggable } from "../movable-dNqBctx3.mjs";
|
|
2
|
+
export { DragMovePosition, DraggableBound, DraggableState, OuiDraggable, addDraggable, removeDraggable };
|
|
@@ -4,7 +4,7 @@ import { findAncestor } from "@oscarpalmer/toretto/find";
|
|
|
4
4
|
import { toggleStyles } from "@oscarpalmer/toretto/style";
|
|
5
5
|
import supportsTouch from "@oscarpalmer/toretto/touch";
|
|
6
6
|
//#region src/js/internal/draggable.ts
|
|
7
|
-
var
|
|
7
|
+
var OuiDraggable = class {
|
|
8
8
|
prefix;
|
|
9
9
|
element;
|
|
10
10
|
options;
|
|
@@ -212,4 +212,4 @@ on(document, "pointerup", onPointerup);
|
|
|
212
212
|
on(document, "touchcancel", onPointerup, { passive: false });
|
|
213
213
|
on(document, "touchstart", onPointerdown, { passive: false });
|
|
214
214
|
//#endregion
|
|
215
|
-
export {
|
|
215
|
+
export { OuiDraggable, addDraggable, removeDraggable };
|