@oscarpalmer/oui 0.37.0 → 0.39.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/css/a11y.css +1 -0
- package/dist/css/badge.css +12 -8
- package/dist/css/button.css +111 -14
- package/dist/css/color-picker.css +859 -0
- package/dist/css/color.css +86 -87
- package/dist/css/combobox.css +105 -4
- package/dist/css/content.css +8 -6
- package/dist/css/floatable.css +3 -3
- package/dist/css/form.css +106 -6
- package/dist/css/icon.css +99 -0
- package/dist/css/listbox.css +5 -0
- package/dist/css/message.css +6 -3
- package/dist/css/mixins/badge.mixins.css +2 -0
- package/dist/css/mixins/button.mixins.css +3 -0
- package/dist/css/mixins/message.mixins.css +1 -0
- package/dist/css/mixins/misc.mixins.css +2 -0
- package/dist/css/mixins/shadow.mixins.css +1 -0
- package/dist/css/reset.css +3 -3
- package/dist/css/splitter.css +1 -1
- package/dist/css/tabs.css +115 -23
- package/dist/css/typography.css +90 -0
- package/dist/js/color-picker/constants.color-picker.d.mts +2 -0
- package/dist/js/color-picker/constants.color-picker.mjs +59 -0
- package/dist/js/color-picker/dom.color-picker.d.mts +8 -0
- package/dist/js/color-picker/dom.color-picker.mjs +191 -0
- package/dist/js/color-picker/event.color-picker.d.mts +9 -0
- package/dist/js/color-picker/event.color-picker.mjs +2 -0
- package/dist/js/color-picker/form.color-picker.d.mts +5 -0
- package/dist/js/color-picker/form.color-picker.mjs +24 -0
- package/dist/js/color-picker/index.d.mts +2 -0
- package/dist/js/color-picker/index.mjs +303 -0
- package/dist/js/color-picker/misc.color-picker.d.mts +2 -0
- package/dist/js/color-picker/misc.color-picker.mjs +2 -0
- package/dist/js/color-picker/models.color-picker.d.mts +2 -0
- package/dist/js/color-picker/models.color-picker.mjs +24 -0
- package/dist/js/color-picker/output.color-picker.d.mts +8 -0
- package/dist/js/color-picker/output.color-picker.mjs +233 -0
- package/dist/js/color-picker/state.color-picker.d.mts +8 -0
- package/dist/js/color-picker/state.color-picker.mjs +2 -0
- package/dist/js/combobox/constants.combobox.d.mts +1 -1
- package/dist/js/combobox/dom.combobox.d.mts +12 -13
- package/dist/js/combobox/dom.combobox.mjs +12 -5
- package/dist/js/combobox/event.combobox.d.mts +20 -21
- package/dist/js/combobox/event.combobox.mjs +1 -1
- package/dist/js/combobox/index.d.mts +1 -1
- package/dist/js/combobox/index.mjs +56 -2
- package/dist/js/combobox/misc.combobox.d.mts +1 -1
- package/dist/js/combobox/misc.combobox.mjs +1 -1
- package/dist/js/combobox/models.combobox.d.mts +12 -13
- package/dist/js/combobox/state.combobox.d.mts +8 -9
- package/dist/js/combobox/state.combobox.mjs +1 -1
- package/dist/js/constants.color-picker-B-gFjL8m.d.mts +364 -0
- package/dist/js/constants.combobox-8EMRmv09.d.mts +18 -0
- package/dist/js/constants.listbox-DGnX32kv.d.mts +8 -0
- package/dist/js/dialog.d.mts +2 -2
- package/dist/js/dialog.mjs +1 -1
- package/dist/js/{draggable-a6w0J1OD.d.mts → draggable-B5-70SZm.d.mts} +5 -4
- package/dist/js/event.color-picker-BEpq0Adu.mjs +485 -0
- package/dist/js/floatable/floatable.embedded.d.mts +1 -1
- package/dist/js/floatable/floatable.embedded.mjs +11 -8
- package/dist/js/floatable/floatable.standalone.d.mts +1 -1
- package/dist/js/{floatable.embedded-Bct4U5Dm.d.mts → floatable.embedded-DQYkXt8X.d.mts} +1 -1
- package/dist/js/focus-trap/focus-trap.embedded.d.mts +1 -1
- package/dist/js/focus-trap/focus-trap.standalone.d.mts +1 -1
- package/dist/js/{focus-trap.embedded-DR8NpZfr.d.mts → focus-trap.embedded-CjyFQYow.d.mts} +2 -2
- package/dist/js/{index-EfkUSals.d.mts → index-C5D3-oiI.d.mts} +41 -3
- package/dist/js/index.d.mts +8 -7
- package/dist/js/index.mjs +6 -3
- package/dist/js/internal/attributable.d.mts +2 -3
- package/dist/js/internal/draggable.d.mts +1 -1
- package/dist/js/internal/draggable.mjs +1 -1
- package/dist/js/internal/listbox/listbox.constants.d.mts +7 -10
- package/dist/js/internal/listbox/listbox.constants.mjs +15 -16
- package/dist/js/internal/listbox/listbox.data.d.mts +9 -10
- package/dist/js/internal/listbox/listbox.data.mjs +1 -1
- package/dist/js/internal/listbox/listbox.dom.d.mts +19 -20
- package/dist/js/internal/listbox/listbox.dom.mjs +1 -1
- package/dist/js/internal/listbox/listbox.event.d.mts +3 -4
- package/dist/js/internal/listbox/listbox.event.mjs +4 -4
- package/dist/js/internal/listbox/listbox.form.d.mts +4 -5
- package/dist/js/internal/listbox/listbox.form.mjs +16 -15
- package/dist/js/internal/listbox/listbox.misc.d.mts +10 -11
- package/dist/js/internal/listbox/listbox.misc.mjs +1 -1
- package/dist/js/internal/listbox/listbox.model.d.mts +1 -1
- package/dist/js/internal/listbox/listbox.state.d.mts +5 -6
- package/dist/js/internal/listbox/listbox.state.mjs +3 -3
- package/dist/js/internal/misc.d.mts +4 -4
- package/dist/js/internal/misc.mjs +9 -1
- package/dist/js/internal/navigable.d.mts +9 -10
- package/dist/js/internal/navigable.mjs +1 -0
- package/dist/js/listbox/constants.listbox.d.mts +1 -1
- package/dist/js/listbox/event.listbox.d.mts +6 -7
- package/dist/js/listbox/event.listbox.mjs +1 -1
- package/dist/js/listbox/index.d.mts +43 -5
- package/dist/js/listbox/index.mjs +56 -2
- package/dist/js/listbox/misc.listbox.d.mts +1 -1
- package/dist/js/listbox/misc.listbox.mjs +1 -1
- package/dist/js/listbox/state.listbox.d.mts +7 -8
- package/dist/js/listbox/state.listbox.mjs +1 -1
- package/dist/js/{listbox.data-BWd0PCy7.mjs → listbox.data-DQ7-x2uY.mjs} +8 -7
- package/dist/js/{listbox.model-CRReGOmu.d.mts → listbox.model-BHPA7GM4.d.mts} +3 -3
- package/dist/js/menu.mjs +1 -1
- package/dist/js/{misc.listbox-BI-XsTOf.mjs → misc.listbox-DKB-j0UK.mjs} +4 -5
- package/dist/js/{misc.listbox-gnoJhrTr.d.mts → misc.listbox-mZMuYOxg.d.mts} +1 -1
- package/dist/js/movable/movable.embedded.d.mts +1 -1
- package/dist/js/movable/movable.standalone.d.mts +1 -1
- package/dist/js/popover.d.mts +2 -2
- package/dist/js/popover.mjs +1 -1
- package/dist/js/resizable/resizable.embedded.d.mts +1 -1
- package/dist/js/resizable/resizable.embedded.mjs +1 -1
- package/dist/js/resizable/resizable.standalone.d.mts +1 -1
- package/dist/js/{resizable.embedded-3qoR0Bjm.d.mts → resizable.embedded-dvhdfQgt.d.mts} +1 -1
- package/dist/js/sortable/sortable.embedded.d.mts +1 -1
- package/dist/js/sortable/sortable.standalone.d.mts +1 -1
- package/dist/js/splitter.d.mts +2 -3
- package/dist/js/splitter.mjs +2 -2
- package/dist/js/{state.combobox-4xq0FPCF.mjs → state.combobox-BWDFHwoi.mjs} +9 -9
- package/dist/js/tabs.d.mts +4 -5
- package/dist/js/tabs.mjs +4 -7
- package/dist/js/tooltip.d.mts +1 -1
- package/package.json +24 -22
- package/dist/js/constants.combobox-DmRAMC64.d.mts +0 -26
- package/dist/js/constants.listbox-DRsXUxd3.d.mts +0 -14
- package/src/css/a11y.scss +0 -13
- package/src/css/badge.scss +0 -62
- package/src/css/button.scss +0 -50
- package/src/css/color.scss +0 -115
- package/src/css/combobox.scss +0 -252
- package/src/css/content.scss +0 -180
- package/src/css/flex.scss +0 -107
- package/src/css/floatable.scss +0 -152
- package/src/css/form.scss +0 -573
- package/src/css/listbox.scss +0 -120
- package/src/css/message.scss +0 -73
- package/src/css/mixins.scss +0 -419
- package/src/css/reset.scss +0 -392
- package/src/css/splitter.scss +0 -89
- package/src/css/table.scss +0 -107
- package/src/css/tabs.scss +0 -85
- package/src/js/combobox/constants.combobox.ts +0 -83
- package/src/js/combobox/dom.combobox.ts +0 -407
- package/src/js/combobox/event.combobox.ts +0 -365
- package/src/js/combobox/index.ts +0 -320
- package/src/js/combobox/misc.combobox.ts +0 -104
- package/src/js/combobox/models.combobox.ts +0 -54
- package/src/js/combobox/state.combobox.ts +0 -246
- package/src/js/dialog.ts +0 -255
- package/src/js/floatable/floatable.embedded.ts +0 -332
- package/src/js/floatable/floatable.standalone.ts +0 -6
- package/src/js/focus-trap/focus-trap.embedded.ts +0 -411
- package/src/js/focus-trap/focus-trap.standalone.ts +0 -1
- package/src/js/index.ts +0 -15
- package/src/js/internal/attributable.ts +0 -73
- package/src/js/internal/draggable.ts +0 -657
- package/src/js/internal/listbox/listbox.constants.ts +0 -25
- package/src/js/internal/listbox/listbox.data.ts +0 -287
- package/src/js/internal/listbox/listbox.dom.ts +0 -445
- package/src/js/internal/listbox/listbox.event.ts +0 -129
- package/src/js/internal/listbox/listbox.form.ts +0 -115
- package/src/js/internal/listbox/listbox.misc.ts +0 -135
- package/src/js/internal/listbox/listbox.model.ts +0 -169
- package/src/js/internal/listbox/listbox.state.ts +0 -82
- package/src/js/internal/misc.ts +0 -27
- package/src/js/internal/navigable.ts +0 -315
- package/src/js/l10n.ts +0 -192
- package/src/js/listbox/constants.listbox.ts +0 -61
- package/src/js/listbox/event.listbox.ts +0 -106
- package/src/js/listbox/index.ts +0 -302
- package/src/js/listbox/misc.listbox.ts +0 -70
- package/src/js/listbox/state.listbox.ts +0 -196
- package/src/js/menu.ts +0 -348
- package/src/js/movable/movable.embedded.ts +0 -318
- package/src/js/movable/movable.standalone.ts +0 -2
- package/src/js/popover.ts +0 -229
- package/src/js/resizable/resizable.embedded.ts +0 -413
- package/src/js/resizable/resizable.standalone.ts +0 -5
- package/src/js/sortable/sortable.embedded.ts +0 -527
- package/src/js/sortable/sortable.standalone.ts +0 -2
- package/src/js/splitter.ts +0 -583
- package/src/js/tabs.ts +0 -447
- package/src/js/toolbar.ts +0 -63
- package/src/js/tooltip.ts +0 -367
- /package/dist/css/{mixins.css → mixins/input.mixins.css} +0 -0
|
@@ -1,411 +0,0 @@
|
|
|
1
|
-
import {isPlainObject} from '@oscarpalmer/atoms/is';
|
|
2
|
-
import {clamp} from '@oscarpalmer/atoms/number';
|
|
3
|
-
import {setAttribute} from '@oscarpalmer/toretto/attribute';
|
|
4
|
-
import {dispatch, on} from '@oscarpalmer/toretto/event';
|
|
5
|
-
import {findAncestor} from '@oscarpalmer/toretto/find';
|
|
6
|
-
import {getFocusable} from '@oscarpalmer/toretto/focusable';
|
|
7
|
-
import {isHTMLOrSVGElement} from '@oscarpalmer/toretto/is';
|
|
8
|
-
import {attributable} from '../internal/attributable';
|
|
9
|
-
|
|
10
|
-
// #region Types
|
|
11
|
-
|
|
12
|
-
export class OuiFocusTrap {
|
|
13
|
-
#destroyed = false;
|
|
14
|
-
#tabIndex: number;
|
|
15
|
-
|
|
16
|
-
readonly #state: OuiFocusTrapState;
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Is focused maintained within the _focus trap_ when clicking outside of it?
|
|
20
|
-
*/
|
|
21
|
-
get contain(): boolean {
|
|
22
|
-
return this.#state.element.hasAttribute(ATTRIBUTE_FOCUSTRAP_CONTAIN);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Should focus be maintained within the _focus trap_ when clicking outside of it?
|
|
27
|
-
*/
|
|
28
|
-
set contain(value: boolean) {
|
|
29
|
-
if (value === true) {
|
|
30
|
-
setAttribute(this.#state.element, ATTRIBUTE_FOCUSTRAP_CONTAIN, '');
|
|
31
|
-
} else if (value === false) {
|
|
32
|
-
setAttribute(this.#state.element, ATTRIBUTE_FOCUSTRAP_CONTAIN, undefined);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Is the _focus trap_ disabled?
|
|
38
|
-
*/
|
|
39
|
-
get disabled(): boolean {
|
|
40
|
-
return this.#state.disabled;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Should the _focus trap_ be disabled?
|
|
45
|
-
*/
|
|
46
|
-
set disabled(value: boolean) {
|
|
47
|
-
if (value === true) {
|
|
48
|
-
this.disable();
|
|
49
|
-
} else if (value === false) {
|
|
50
|
-
this.enable();
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Is focus allowed to escape when pressing _Escape_ within the _focus trap_?
|
|
56
|
-
*/
|
|
57
|
-
get noescape(): boolean {
|
|
58
|
-
return this.#state.element.hasAttribute(ATTRIBUTE_FOCUSTRAP_NOESCAPE);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Should the _focus trap_ allow focus to escape when pressing _Escape_?
|
|
63
|
-
*/
|
|
64
|
-
set noescape(value: boolean) {
|
|
65
|
-
if (value === true) {
|
|
66
|
-
setAttribute(this.#state.element, ATTRIBUTE_FOCUSTRAP_NOESCAPE, '');
|
|
67
|
-
} else if (value === false) {
|
|
68
|
-
setAttribute(this.#state.element, ATTRIBUTE_FOCUSTRAP_NOESCAPE, undefined);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
constructor(state: OuiFocusTrapState) {
|
|
73
|
-
this.#state = state;
|
|
74
|
-
this.#tabIndex = state.element.tabIndex;
|
|
75
|
-
|
|
76
|
-
state.element.tabIndex = -1;
|
|
77
|
-
|
|
78
|
-
setAttribute(state.element, ATTRIBUTE_FOCUSTRAP, '');
|
|
79
|
-
|
|
80
|
-
this.contain = state.options.contain;
|
|
81
|
-
this.noescape = state.options.noescape;
|
|
82
|
-
|
|
83
|
-
states.set(this, state);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Destroys the _focus trap_
|
|
88
|
-
*/
|
|
89
|
-
destroy(): void {
|
|
90
|
-
if (this.#destroyed) {
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
this.#destroyed = true;
|
|
95
|
-
|
|
96
|
-
disabled.delete(this);
|
|
97
|
-
instances.delete(this.#state.element);
|
|
98
|
-
states.delete(this);
|
|
99
|
-
|
|
100
|
-
this.#state.element.tabIndex = this.#tabIndex;
|
|
101
|
-
|
|
102
|
-
this.#state.element.removeAttribute(ATTRIBUTE_FOCUSTRAP);
|
|
103
|
-
this.#state.element.removeAttribute(ATTRIBUTE_FOCUSTRAP_CONTAIN);
|
|
104
|
-
this.#state.element.removeAttribute(ATTRIBUTE_FOCUSTRAP_NOESCAPE);
|
|
105
|
-
|
|
106
|
-
this.#state.element = undefined as never;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Disables the _focus trap_
|
|
111
|
-
*/
|
|
112
|
-
disable(): void {
|
|
113
|
-
if (!this.#destroyed && !(this.disabled || this.#state.options.noescape)) {
|
|
114
|
-
setDisabled(this, this.#state, true);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* Enables the _focus trap_
|
|
120
|
-
*/
|
|
121
|
-
enable(): void {
|
|
122
|
-
if (!this.#destroyed && this.disabled) {
|
|
123
|
-
setDisabled(this, this.#state, false);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Focuses the _focus trap_
|
|
129
|
-
*
|
|
130
|
-
* @param last When `true`, focuses the last focusable element within the _focus trap_ instead of the first
|
|
131
|
-
*/
|
|
132
|
-
focus(last: boolean): void {
|
|
133
|
-
if (!this.#destroyed && !this.disabled) {
|
|
134
|
-
tabToTrap(this, getFocusable(this.#state.element), this.#state.element, last ? -1 : 0);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
export type OuiFocusTrapOptions = {
|
|
140
|
-
/**
|
|
141
|
-
* Should focus be maintained within the _focus trap_ when clicking outside of it?
|
|
142
|
-
*/
|
|
143
|
-
contain?: boolean;
|
|
144
|
-
/**
|
|
145
|
-
* Should the _focus trap_ allow focus to escape when pressing _Escape_?
|
|
146
|
-
*/
|
|
147
|
-
noescape?: boolean;
|
|
148
|
-
};
|
|
149
|
-
|
|
150
|
-
type OuiFocusTrapState = {
|
|
151
|
-
disabled: boolean;
|
|
152
|
-
element: HTMLElement;
|
|
153
|
-
options: Required<OuiFocusTrapOptions>;
|
|
154
|
-
};
|
|
155
|
-
|
|
156
|
-
// #endregion
|
|
157
|
-
|
|
158
|
-
// #region Functions
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* Creates _(or retrieves)_ a _focus trap_ for an element
|
|
162
|
-
*
|
|
163
|
-
* @param element Element to trap focus within
|
|
164
|
-
* @param options _Focus trap_ options
|
|
165
|
-
* @returns _Focus trap_ instance
|
|
166
|
-
*/
|
|
167
|
-
export function createFocusTrap(element: HTMLElement, options?: OuiFocusTrapOptions): OuiFocusTrap {
|
|
168
|
-
if (!isHTMLOrSVGElement(element)) {
|
|
169
|
-
throw new TypeError(MESSAGE);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
let instance = instances.get(element);
|
|
173
|
-
|
|
174
|
-
if (instance == null) {
|
|
175
|
-
instance = new OuiFocusTrap(getState(element, options));
|
|
176
|
-
|
|
177
|
-
instances.set(element, instance);
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
return instance;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
function getOptions(
|
|
184
|
-
element: HTMLElement,
|
|
185
|
-
input?: OuiFocusTrapOptions,
|
|
186
|
-
): Required<OuiFocusTrapOptions> {
|
|
187
|
-
const options = isPlainObject(input) ? input : {};
|
|
188
|
-
|
|
189
|
-
return {
|
|
190
|
-
contain:
|
|
191
|
-
typeof options.contain === 'boolean'
|
|
192
|
-
? options.contain
|
|
193
|
-
: element.hasAttribute(ATTRIBUTE_FOCUSTRAP_CONTAIN),
|
|
194
|
-
noescape:
|
|
195
|
-
typeof options.noescape === 'boolean'
|
|
196
|
-
? options.noescape
|
|
197
|
-
: element.hasAttribute(ATTRIBUTE_FOCUSTRAP_NOESCAPE),
|
|
198
|
-
};
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
function getState(element: HTMLElement, options?: OuiFocusTrapOptions): OuiFocusTrapState {
|
|
202
|
-
return {
|
|
203
|
-
element,
|
|
204
|
-
disabled: false,
|
|
205
|
-
options: getOptions(element, options),
|
|
206
|
-
};
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
function onEscape(event: KeyboardEvent): void {
|
|
210
|
-
let element = findAncestor(event, SELECTOR) as HTMLElement;
|
|
211
|
-
|
|
212
|
-
let instance = instances.get(element);
|
|
213
|
-
let state = states.get(instance!);
|
|
214
|
-
|
|
215
|
-
if (element == null || instance == null || state == null) {
|
|
216
|
-
return;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
while (state.disabled) {
|
|
220
|
-
element = findAncestor(state.element.parentElement as HTMLElement, SELECTOR) as HTMLElement;
|
|
221
|
-
|
|
222
|
-
instance = instances.get(element);
|
|
223
|
-
state = states.get(instance!);
|
|
224
|
-
|
|
225
|
-
if (element == null || instance == null || state == null) {
|
|
226
|
-
return;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
if (!state.disabled) {
|
|
230
|
-
break;
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
instance?.disable();
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
function onFocusIn(event: Event): void {
|
|
238
|
-
const focusTrap = instances.get(findAncestor(event, SELECTOR) as HTMLElement);
|
|
239
|
-
|
|
240
|
-
lastTarget = focusTrap == null ? undefined : (event.target as HTMLElement);
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
function onKeydown(event: KeyboardEvent): void {
|
|
244
|
-
switch (event.key) {
|
|
245
|
-
case 'Escape':
|
|
246
|
-
onEscape(event);
|
|
247
|
-
break;
|
|
248
|
-
|
|
249
|
-
case 'Tab':
|
|
250
|
-
onTab(event);
|
|
251
|
-
break;
|
|
252
|
-
|
|
253
|
-
default:
|
|
254
|
-
return;
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
function onPointerdown(event: MouseEvent | TouchEvent): void {
|
|
259
|
-
const last = findAncestor(lastTarget as HTMLElement, SELECTOR) as HTMLElement;
|
|
260
|
-
const next = findAncestor(event, SELECTOR) as HTMLElement;
|
|
261
|
-
|
|
262
|
-
if (last != null && next !== last) {
|
|
263
|
-
if (states.get(instances.get(last)!)?.options.contain ?? false) {
|
|
264
|
-
event.preventDefault();
|
|
265
|
-
|
|
266
|
-
lastTarget?.focus();
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
if (disabled.size === 0) {
|
|
271
|
-
return;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
for (const focusTrap of disabled) {
|
|
275
|
-
const state = states.get(focusTrap);
|
|
276
|
-
|
|
277
|
-
if (state != null && state.element !== next) {
|
|
278
|
-
focusTrap.enable();
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
function onTab(event: KeyboardEvent): void {
|
|
284
|
-
const element = findAncestor(event, SELECTOR) as HTMLElement;
|
|
285
|
-
|
|
286
|
-
const instance = instances.get(element);
|
|
287
|
-
|
|
288
|
-
if (instance == null || dispatch(element, 'oui:focus-trap').defaultPrevented) {
|
|
289
|
-
return;
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
if (!instance.disabled) {
|
|
293
|
-
event.preventDefault();
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
const elements = getFocusable(element);
|
|
297
|
-
|
|
298
|
-
const index = elements.indexOf(event.target as HTMLElement);
|
|
299
|
-
|
|
300
|
-
if (index === -1 || elements.length === 0) {
|
|
301
|
-
tabToTrap(instance, elements, element);
|
|
302
|
-
} else {
|
|
303
|
-
tabToElement(instance, elements, index, event.shiftKey ? -1 : 1);
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
export function removeFocusTrap(element: HTMLElement): void {
|
|
308
|
-
instances.get(element)?.destroy();
|
|
309
|
-
|
|
310
|
-
instances.delete(element);
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
function setDisabled(focusTrap: OuiFocusTrap, state: OuiFocusTrapState, value: boolean): void {
|
|
314
|
-
state.disabled = value;
|
|
315
|
-
|
|
316
|
-
if (value) {
|
|
317
|
-
disabled.add(focusTrap);
|
|
318
|
-
} else {
|
|
319
|
-
disabled.delete(focusTrap);
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
function tabToElement(
|
|
324
|
-
instance: OuiFocusTrap,
|
|
325
|
-
elements: Element[],
|
|
326
|
-
index: number,
|
|
327
|
-
modifier: number,
|
|
328
|
-
): void {
|
|
329
|
-
const {length} = elements;
|
|
330
|
-
const next = clamp(index + modifier, 0, length - 1, true);
|
|
331
|
-
|
|
332
|
-
if (instance.disabled) {
|
|
333
|
-
if ((index === length - 1 && next === 0) || (index === 0 && next === length - 1)) {
|
|
334
|
-
lastTarget = undefined;
|
|
335
|
-
|
|
336
|
-
instance.enable();
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
return;
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
const element = elements[next] as HTMLElement;
|
|
343
|
-
const elementFocusTrap = instances.get(element);
|
|
344
|
-
|
|
345
|
-
if (elementFocusTrap != null) {
|
|
346
|
-
elementFocusTrap.focus(modifier === -1);
|
|
347
|
-
} else {
|
|
348
|
-
(elements[next] as HTMLElement).focus();
|
|
349
|
-
|
|
350
|
-
lastTarget = elements[next] as HTMLElement;
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
function tabToTrap(
|
|
355
|
-
instance: OuiFocusTrap,
|
|
356
|
-
elements: Element[],
|
|
357
|
-
element: HTMLElement,
|
|
358
|
-
index?: number,
|
|
359
|
-
): void {
|
|
360
|
-
if (instance.disabled) {
|
|
361
|
-
lastTarget = undefined;
|
|
362
|
-
|
|
363
|
-
instance.enable();
|
|
364
|
-
} else {
|
|
365
|
-
const next = elements.length === 0 ? element : elements.at(index ?? 0);
|
|
366
|
-
|
|
367
|
-
(next as HTMLElement).focus();
|
|
368
|
-
|
|
369
|
-
lastTarget = next as HTMLElement;
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
// #endregion
|
|
374
|
-
|
|
375
|
-
// #region Variables
|
|
376
|
-
|
|
377
|
-
export const ATTRIBUTE_FOCUSTRAP = 'oui-focus-trap';
|
|
378
|
-
|
|
379
|
-
export const ATTRIBUTE_FOCUSTRAP_CONTAIN = `${ATTRIBUTE_FOCUSTRAP}-contain`;
|
|
380
|
-
|
|
381
|
-
export const ATTRIBUTE_FOCUSTRAP_NOESCAPE = `${ATTRIBUTE_FOCUSTRAP}-noescape`;
|
|
382
|
-
|
|
383
|
-
const EVENT_OPTIONS: AddEventListenerOptions = {
|
|
384
|
-
capture: true,
|
|
385
|
-
passive: false,
|
|
386
|
-
};
|
|
387
|
-
|
|
388
|
-
const MESSAGE = 'Element must be an HTMLElement or SVGElement';
|
|
389
|
-
|
|
390
|
-
const SELECTOR = `[${ATTRIBUTE_FOCUSTRAP}]`;
|
|
391
|
-
|
|
392
|
-
const disabled = new Set<OuiFocusTrap>();
|
|
393
|
-
|
|
394
|
-
const instances = new WeakMap<HTMLElement, OuiFocusTrap>();
|
|
395
|
-
|
|
396
|
-
const states = new WeakMap<OuiFocusTrap, OuiFocusTrapState>();
|
|
397
|
-
|
|
398
|
-
let lastTarget: HTMLElement | undefined;
|
|
399
|
-
|
|
400
|
-
// #endregion
|
|
401
|
-
|
|
402
|
-
// #region Initialization
|
|
403
|
-
|
|
404
|
-
attributable(ATTRIBUTE_FOCUSTRAP, createFocusTrap, removeFocusTrap);
|
|
405
|
-
|
|
406
|
-
on(document, 'focusin', onFocusIn, EVENT_OPTIONS);
|
|
407
|
-
on(document, 'keydown', onKeydown, EVENT_OPTIONS);
|
|
408
|
-
on(document, 'mousedown', onPointerdown, EVENT_OPTIONS);
|
|
409
|
-
on(document, 'touchstart', onPointerdown, EVENT_OPTIONS);
|
|
410
|
-
|
|
411
|
-
// #endregion
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {createFocusTrap, type OuiFocusTrap, type OuiFocusTrapOptions} from './focus-trap.embedded';
|
package/src/js/index.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import './menu';
|
|
2
|
-
import './toolbar';
|
|
3
|
-
|
|
4
|
-
export * from './combobox/index';
|
|
5
|
-
export * from './dialog';
|
|
6
|
-
export * from './floatable/floatable.standalone';
|
|
7
|
-
export * from './focus-trap/focus-trap.standalone';
|
|
8
|
-
export * from './listbox/index';
|
|
9
|
-
export * from './movable/movable.standalone';
|
|
10
|
-
export * from './popover';
|
|
11
|
-
export * from './resizable/resizable.standalone';
|
|
12
|
-
export * from './sortable/sortable.standalone';
|
|
13
|
-
export * from './splitter';
|
|
14
|
-
export * from './tabs';
|
|
15
|
-
export * from './tooltip';
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
export function attributable(
|
|
2
|
-
attribute: string,
|
|
3
|
-
add: (element: HTMLElement) => void,
|
|
4
|
-
remove: (element: HTMLElement) => void,
|
|
5
|
-
): void {
|
|
6
|
-
const observer = new MutationObserver(entries => {
|
|
7
|
-
const {length} = entries;
|
|
8
|
-
|
|
9
|
-
for (let index = 0; index < length; index += 1) {
|
|
10
|
-
const entry = entries[index];
|
|
11
|
-
|
|
12
|
-
if (entry.type === 'attributes' && entry.target instanceof Element) {
|
|
13
|
-
if (entry.target.hasAttribute(attribute)) {
|
|
14
|
-
handleAdded(attribute, [entry.target], add);
|
|
15
|
-
} else {
|
|
16
|
-
handleRemoved([entry.target], remove);
|
|
17
|
-
}
|
|
18
|
-
} else if (entry.type === 'childList') {
|
|
19
|
-
handleAdded(attribute, entry.addedNodes, add);
|
|
20
|
-
handleRemoved(entry.removedNodes, remove);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
observer.observe(document, {
|
|
26
|
-
attributeFilter: [attribute],
|
|
27
|
-
attributes: true,
|
|
28
|
-
childList: true,
|
|
29
|
-
subtree: true,
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
requestAnimationFrame(() => {
|
|
33
|
-
handleAdded(attribute, document.querySelectorAll(`[${attribute}]`), add);
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function handleAdded(
|
|
38
|
-
attribute: string,
|
|
39
|
-
nodes: Node[] | NodeList,
|
|
40
|
-
add: (element: HTMLElement) => void,
|
|
41
|
-
): void {
|
|
42
|
-
const elements = [...nodes].filter(node => node instanceof Element) as HTMLElement[];
|
|
43
|
-
|
|
44
|
-
const {length} = elements;
|
|
45
|
-
|
|
46
|
-
for (let index = 0; index < length; index += 1) {
|
|
47
|
-
const element = elements[index];
|
|
48
|
-
|
|
49
|
-
if (element.hasAttribute(attribute)) {
|
|
50
|
-
add(element);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
if (element.hasChildNodes()) {
|
|
54
|
-
handleAdded(attribute, element.childNodes, add);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function handleRemoved(nodes: Node[] | NodeList, remove: (element: HTMLElement) => void): void {
|
|
60
|
-
const elements = [...nodes].filter(node => node instanceof Element) as HTMLElement[];
|
|
61
|
-
|
|
62
|
-
const {length} = elements;
|
|
63
|
-
|
|
64
|
-
for (let index = 0; index < length; index += 1) {
|
|
65
|
-
const element = elements[index];
|
|
66
|
-
|
|
67
|
-
remove(element);
|
|
68
|
-
|
|
69
|
-
if (element.hasChildNodes()) {
|
|
70
|
-
handleRemoved(element.childNodes, remove);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|