@oscarpalmer/oui 0.27.0 → 0.29.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/floatable.css +9 -0
- package/dist/js/dialog.d.mts +3 -1
- package/dist/js/dialog.mjs +35 -19
- package/dist/js/{draggable-zszaW1qS.d.mts → draggable-fIYXd8eO.d.mts} +3 -3
- package/dist/js/floatable/floatable.embedded.d.mts +2 -2
- package/dist/js/floatable/floatable.embedded.mjs +17 -16
- package/dist/js/floatable/floatable.standalone.d.mts +1 -1
- package/dist/js/{floatable.embedded-YxGwzgbE.d.mts → floatable.embedded-DUR8bQBK.d.mts} +1 -2
- package/dist/js/focus-trap/focus-trap.embedded.mjs +6 -5
- package/dist/js/index.d.mts +4 -3
- package/dist/js/index.mjs +6 -2
- package/dist/js/internal/attributable.mjs +3 -4
- package/dist/js/internal/draggable.d.mts +1 -1
- package/dist/js/internal/draggable.mjs +12 -9
- package/dist/js/internal/navigable.d.mts +32 -0
- package/dist/js/internal/navigable.mjs +107 -0
- package/dist/js/menu.d.mts +1 -0
- package/dist/js/menu.mjs +168 -0
- package/dist/js/movable/movable.embedded.d.mts +1 -1
- package/dist/js/movable/movable.embedded.mjs +8 -13
- package/dist/js/movable/movable.standalone.d.mts +1 -1
- package/dist/js/popover.d.mts +1 -1
- package/dist/js/popover.mjs +27 -12
- package/dist/js/resizable/resizable.embedded.d.mts +2 -0
- package/dist/js/resizable/resizable.embedded.mjs +191 -0
- package/dist/js/resizable/resizable.standalone.d.mts +2 -0
- package/dist/js/resizable/resizable.standalone.mjs +2 -0
- package/dist/js/resizable.embedded-CXrUVPzR.d.mts +35 -0
- package/dist/js/sortable/sortable.embedded.d.mts +1 -1
- package/dist/js/sortable/sortable.embedded.mjs +15 -13
- package/dist/js/sortable/sortable.standalone.d.mts +1 -1
- package/dist/js/splitter.mjs +30 -26
- package/dist/js/toolbar.mjs +12 -88
- package/dist/js/tooltip.d.mts +1 -1
- package/dist/js/tooltip.mjs +12 -17
- package/package.json +11 -3
- package/src/css/floatable.scss +9 -0
- package/src/css/form.scss +6 -6
- package/src/js/dialog.ts +50 -24
- package/src/js/floatable/floatable.embedded.ts +19 -18
- package/src/js/focus-trap/focus-trap.embedded.ts +6 -5
- package/src/js/index.ts +3 -1
- package/src/js/internal/attributable.ts +3 -5
- package/src/js/internal/draggable.ts +13 -10
- package/src/js/internal/navigable.ts +247 -0
- package/src/js/menu.ts +345 -0
- package/src/js/movable/movable.embedded.ts +10 -13
- package/src/js/popover.ts +41 -15
- package/src/js/resizable/resizable.embedded.ts +390 -0
- package/src/js/resizable/resizable.standalone.ts +5 -0
- package/src/js/sortable/sortable.embedded.ts +17 -22
- package/src/js/splitter.ts +41 -36
- package/src/js/toolbar.ts +27 -178
- package/src/js/tooltip.ts +18 -30
package/src/js/toolbar.ts
CHANGED
|
@@ -1,153 +1,41 @@
|
|
|
1
|
-
import {clamp} from '@oscarpalmer/atoms/number';
|
|
2
|
-
import {on} from '@oscarpalmer/toretto/event';
|
|
3
|
-
import {findAncestor} from '@oscarpalmer/toretto/find';
|
|
4
|
-
import {isHTMLOrSVGElement} from '@oscarpalmer/toretto/is';
|
|
5
|
-
import type {RemovableEventListener} from '@oscarpalmer/toretto/models';
|
|
6
1
|
import {attributable} from './internal/attributable';
|
|
2
|
+
import {getNavigable, OuiNavigable, updateNavigableFocus} from './internal/navigable';
|
|
3
|
+
|
|
4
|
+
// #region Types
|
|
7
5
|
|
|
8
6
|
class OuiToolbar {
|
|
9
|
-
|
|
7
|
+
#navigable: OuiNavigable;
|
|
10
8
|
|
|
11
|
-
constructor(
|
|
12
|
-
this.#
|
|
9
|
+
constructor(navigable: OuiNavigable) {
|
|
10
|
+
this.#navigable = navigable;
|
|
13
11
|
|
|
14
|
-
|
|
12
|
+
updateNavigableFocus(this.#navigable, false);
|
|
15
13
|
}
|
|
16
14
|
|
|
17
15
|
destroy(): void {
|
|
18
|
-
|
|
19
|
-
listener();
|
|
20
|
-
}
|
|
16
|
+
this.#navigable.destroy();
|
|
21
17
|
|
|
22
|
-
this.#
|
|
23
|
-
this.#state.element = undefined as never;
|
|
24
|
-
this.#state.listeners = undefined as never;
|
|
18
|
+
this.#navigable = undefined as never;
|
|
25
19
|
}
|
|
26
20
|
}
|
|
27
21
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
type OuiToolbarState = {
|
|
31
|
-
active: OuiToolbarStateActive;
|
|
32
|
-
element: HTMLElement;
|
|
33
|
-
listeners: RemovableEventListener[];
|
|
34
|
-
orientation: OuiToolbarOrientation;
|
|
35
|
-
};
|
|
22
|
+
// #endregion
|
|
36
23
|
|
|
37
|
-
|
|
38
|
-
element?: HTMLElement;
|
|
39
|
-
index: number;
|
|
40
|
-
};
|
|
24
|
+
// #region Functions
|
|
41
25
|
|
|
42
26
|
function addToolbar(element: HTMLElement): void {
|
|
43
27
|
if (!instances.has(element)) {
|
|
44
|
-
instances.set(
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
function getOrientation(element: HTMLElement): OuiToolbarOrientation {
|
|
53
|
-
const attribute = element.getAttribute(ARIA_ORIENTATION);
|
|
54
|
-
|
|
55
|
-
return ORIENTATIONS.has(attribute as OuiToolbarOrientation)
|
|
56
|
-
? (attribute as OuiToolbarOrientation)
|
|
57
|
-
: ORIENTATION_HORIZONTAL;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
function getState(element: HTMLElement): OuiToolbarState {
|
|
61
|
-
const state: OuiToolbarState = {
|
|
62
|
-
element,
|
|
63
|
-
active: {
|
|
64
|
-
index: 0,
|
|
65
|
-
},
|
|
66
|
-
listeners: [
|
|
67
|
-
on(element, EVENT_FOCUSIN, event => {
|
|
68
|
-
onFocusin(state, event);
|
|
69
|
-
}),
|
|
70
|
-
on(
|
|
71
|
-
element,
|
|
72
|
-
EVENT_KEYDOWN,
|
|
73
|
-
event => {
|
|
74
|
-
onKeydown(state, event);
|
|
75
|
-
},
|
|
76
|
-
{
|
|
77
|
-
passive: false,
|
|
78
|
-
},
|
|
28
|
+
instances.set(
|
|
29
|
+
element,
|
|
30
|
+
new OuiToolbar(
|
|
31
|
+
getNavigable(element, {
|
|
32
|
+
role: 'toolbar',
|
|
33
|
+
selector: SELECTOR,
|
|
34
|
+
vertical: false,
|
|
35
|
+
}),
|
|
79
36
|
),
|
|
80
|
-
],
|
|
81
|
-
orientation: getOrientation(element),
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
return state;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
function isValidItem(element: HTMLElement): boolean {
|
|
88
|
-
return PROPERTY_DISABLED in element ? element.disabled !== true : true;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function onKeydown(state: OuiToolbarState, event: KeyboardEvent): void {
|
|
92
|
-
if (!KEYS_ALL.has(event.key)) {
|
|
93
|
-
return;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
const items = getItems(state.element);
|
|
97
|
-
|
|
98
|
-
if (items.length === 0) {
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
let index: number | undefined;
|
|
103
|
-
|
|
104
|
-
if (KEYS_ABSOLUTE.has(event.key)) {
|
|
105
|
-
index = event.key === KEY_HOME ? 0 : items.length - 1;
|
|
106
|
-
} else if (
|
|
107
|
-
state.orientation === ORIENTATION_HORIZONTAL
|
|
108
|
-
? KEYS_HORIZONTAL.has(event.key)
|
|
109
|
-
: KEYS_VERTICAL.has(event.key)
|
|
110
|
-
) {
|
|
111
|
-
if (state.active.element instanceof HTMLSelectElement) {
|
|
112
|
-
event.preventDefault();
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
index = clamp(
|
|
116
|
-
state.active.index + (KEYS_NEXT.has(event.key) ? 1 : -1),
|
|
117
|
-
0,
|
|
118
|
-
items.length - 1,
|
|
119
|
-
true,
|
|
120
37
|
);
|
|
121
38
|
}
|
|
122
|
-
|
|
123
|
-
if (index == null || index === state.active.index) {
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
state.active.element = items[index];
|
|
128
|
-
state.active.index = index;
|
|
129
|
-
|
|
130
|
-
updateFocus(state, true, items);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
function onFocusin(state: OuiToolbarState, event: FocusEvent): void {
|
|
134
|
-
const item = findAncestor(event, SELECTOR);
|
|
135
|
-
|
|
136
|
-
if (!isHTMLOrSVGElement(item) || !isValidItem(item)) {
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
const items = getItems(state.element);
|
|
141
|
-
const index = items.indexOf(item);
|
|
142
|
-
|
|
143
|
-
if (index === -1) {
|
|
144
|
-
return;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
state.active.element = item;
|
|
148
|
-
state.active.index = index;
|
|
149
|
-
|
|
150
|
-
updateFocus(state, false, items);
|
|
151
39
|
}
|
|
152
40
|
|
|
153
41
|
function removeToolbar(element: HTMLElement): void {
|
|
@@ -156,59 +44,20 @@ function removeToolbar(element: HTMLElement): void {
|
|
|
156
44
|
instances.delete(element);
|
|
157
45
|
}
|
|
158
46
|
|
|
159
|
-
|
|
160
|
-
const updated = items ?? getItems(state.element);
|
|
161
|
-
const {length} = updated;
|
|
162
|
-
|
|
163
|
-
if (length === 0) {
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
for (let index = 0; index < length; index += 1) {
|
|
168
|
-
updated[index].tabIndex = index === state.active.index ? 0 : -1;
|
|
169
|
-
}
|
|
47
|
+
// #endregion
|
|
170
48
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
if (focus) {
|
|
174
|
-
state.active.element?.focus();
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
const ARIA_ORIENTATION = 'aria-orientation';
|
|
49
|
+
// #region Variables
|
|
179
50
|
|
|
180
51
|
const ATTRIBUTE = 'oui-toolbar';
|
|
181
52
|
|
|
182
|
-
const EVENT_KEYDOWN = 'keydown';
|
|
183
|
-
|
|
184
|
-
const EVENT_FOCUSIN = 'focusin';
|
|
185
|
-
|
|
186
|
-
const KEY_ARROW_DOWN = 'ArrowDown';
|
|
187
|
-
|
|
188
|
-
const KEY_ARROW_RIGHT = 'ArrowRight';
|
|
189
|
-
|
|
190
|
-
const KEY_END = 'End';
|
|
191
|
-
|
|
192
|
-
const KEY_HOME = 'Home';
|
|
193
|
-
|
|
194
|
-
const KEYS_ABSOLUTE = new Set([KEY_END, KEY_HOME]);
|
|
195
|
-
|
|
196
|
-
const KEYS_HORIZONTAL = new Set([KEY_ARROW_RIGHT, 'ArrowLeft']);
|
|
197
|
-
|
|
198
|
-
const KEYS_VERTICAL = new Set([KEY_ARROW_DOWN, 'ArrowUp']);
|
|
199
|
-
|
|
200
|
-
const KEYS_ALL = new Set([...KEYS_ABSOLUTE, ...KEYS_HORIZONTAL, ...KEYS_VERTICAL]);
|
|
201
|
-
|
|
202
|
-
const KEYS_NEXT = new Set([KEY_ARROW_DOWN, KEY_ARROW_RIGHT]);
|
|
203
|
-
|
|
204
|
-
const ORIENTATION_HORIZONTAL: OuiToolbarOrientation = 'horizontal';
|
|
205
|
-
|
|
206
|
-
const ORIENTATIONS = new Set<OuiToolbarOrientation>([ORIENTATION_HORIZONTAL, 'vertical']);
|
|
207
|
-
|
|
208
|
-
const PROPERTY_DISABLED = 'disabled';
|
|
209
|
-
|
|
210
53
|
const SELECTOR = `[${ATTRIBUTE}-item]`;
|
|
211
54
|
|
|
212
55
|
const instances = new WeakMap<HTMLElement, OuiToolbar>();
|
|
213
56
|
|
|
57
|
+
// #endregion
|
|
58
|
+
|
|
59
|
+
// #region Initialization
|
|
60
|
+
|
|
214
61
|
attributable(ATTRIBUTE, addToolbar, removeToolbar);
|
|
62
|
+
|
|
63
|
+
// #endregion
|
package/src/js/tooltip.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {isNullableOrWhitespace} from '@oscarpalmer/atoms/is';
|
|
2
|
+
import {getAria} from '@oscarpalmer/toretto/aria';
|
|
3
|
+
import {setAttribute} from '@oscarpalmer/toretto/attribute';
|
|
2
4
|
import {createElement} from '@oscarpalmer/toretto/create';
|
|
3
5
|
import {on} from '@oscarpalmer/toretto/event';
|
|
4
6
|
import {findAncestor} from '@oscarpalmer/toretto/find';
|
|
5
|
-
import {isHTMLOrSVGElement} from '@oscarpalmer/toretto/is';
|
|
6
7
|
import {
|
|
7
8
|
createEmbeddedFloatable,
|
|
8
|
-
FLOATABLE_STATE_OPEN,
|
|
9
9
|
type OuiFloatable,
|
|
10
10
|
type OuiFloatableOptions,
|
|
11
11
|
} from './floatable/floatable.embedded';
|
|
@@ -154,7 +154,11 @@ function destroyTooltip(state: OuiTooltipState): void {
|
|
|
154
154
|
state.tooltip = undefined as never;
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
-
function findElements(attribute
|
|
157
|
+
function findElements(attribute?: string): HTMLElement[] | undefined {
|
|
158
|
+
if (attribute == null) {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
|
|
158
162
|
const ids = attribute?.split(EXPRESSION_WHITESPACE) ?? [];
|
|
159
163
|
const elements: HTMLElement[] = [];
|
|
160
164
|
|
|
@@ -165,7 +169,7 @@ function findElements(attribute: string | null): HTMLElement[] {
|
|
|
165
169
|
|
|
166
170
|
const element = document.querySelector(`#${id}`);
|
|
167
171
|
|
|
168
|
-
if (
|
|
172
|
+
if (element != null) {
|
|
169
173
|
const cloned = element.cloneNode(true) as HTMLElement;
|
|
170
174
|
|
|
171
175
|
cloned.hidden = false;
|
|
@@ -178,34 +182,32 @@ function findElements(attribute: string | null): HTMLElement[] {
|
|
|
178
182
|
}
|
|
179
183
|
|
|
180
184
|
function getContent(): HTMLElement {
|
|
181
|
-
const content = createElement(
|
|
185
|
+
const content = createElement('div', {
|
|
182
186
|
popover: 'hint',
|
|
183
187
|
role: 'tooltip',
|
|
184
188
|
tabIndex: -1,
|
|
185
189
|
});
|
|
186
190
|
|
|
187
|
-
|
|
191
|
+
setAttribute(content, ATTRIBUTE_CONTENT, '');
|
|
188
192
|
|
|
189
193
|
return content;
|
|
190
194
|
}
|
|
191
195
|
|
|
192
196
|
function getElements(anchor: HTMLElement): HTMLElement[] | undefined {
|
|
193
|
-
let elements = findElements(anchor
|
|
197
|
+
let elements = findElements(getAria(anchor, 'labelledby'));
|
|
194
198
|
|
|
195
|
-
if (elements.length
|
|
196
|
-
|
|
199
|
+
if (elements == null || elements.length === 0) {
|
|
200
|
+
elements = findElements(getAria(anchor, 'describedby'));
|
|
197
201
|
}
|
|
198
202
|
|
|
199
|
-
elements
|
|
200
|
-
|
|
201
|
-
if (elements.length > 0) {
|
|
202
|
-
return elements;
|
|
203
|
+
if (elements != null && elements.length > 0) {
|
|
204
|
+
return elements as HTMLElement[];
|
|
203
205
|
}
|
|
204
206
|
|
|
205
|
-
let text = anchor
|
|
207
|
+
let text = getAria(anchor, 'label');
|
|
206
208
|
|
|
207
209
|
if (isNullableOrWhitespace(text)) {
|
|
208
|
-
text = anchor
|
|
210
|
+
text = getAria(anchor, 'description');
|
|
209
211
|
}
|
|
210
212
|
|
|
211
213
|
if (isNullableOrWhitespace(text)) {
|
|
@@ -276,11 +278,7 @@ function onPointermove(event: Event): void {
|
|
|
276
278
|
}
|
|
277
279
|
|
|
278
280
|
function onToggle(event: ToggleEvent): void {
|
|
279
|
-
|
|
280
|
-
content.setAttribute(ATTRIBUTE_CONTENT_OPEN, '');
|
|
281
|
-
} else {
|
|
282
|
-
content.removeAttribute(ATTRIBUTE_CONTENT_OPEN);
|
|
283
|
-
}
|
|
281
|
+
setAttribute(content, ATTRIBUTE_CONTENT_OPEN, event.newState === 'open' ? '' : undefined);
|
|
284
282
|
}
|
|
285
283
|
|
|
286
284
|
function removeTooltip(element: HTMLElement): void {
|
|
@@ -311,16 +309,6 @@ function setTooltipDelay(value: number): void {
|
|
|
311
309
|
|
|
312
310
|
// #region Variables
|
|
313
311
|
|
|
314
|
-
const ARIA_DESCRIBEDBY = 'aria-describedby';
|
|
315
|
-
|
|
316
|
-
const ARIA_DESCRIPTION = 'aria-description';
|
|
317
|
-
|
|
318
|
-
const ARIA_LABEL = 'aria-label';
|
|
319
|
-
|
|
320
|
-
const ARIA_LABELLEDBY = 'aria-labelledby';
|
|
321
|
-
|
|
322
|
-
const CONTENT_TAGNAME = 'div';
|
|
323
|
-
|
|
324
312
|
const EXPRESSION_WHITESPACE = /\s+/;
|
|
325
313
|
|
|
326
314
|
const ATTRIBUTE = 'oui-tooltip';
|