@oscarpalmer/oui 0.36.0 → 0.37.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/badge.css +18 -15
- package/dist/css/button.css +35 -31
- package/dist/css/color.css +20 -20
- package/dist/css/combobox.css +133 -34
- package/dist/css/content.css +29 -10
- package/dist/css/floatable.css +10 -10
- package/dist/css/form.css +393 -129
- package/dist/css/listbox.css +41 -17
- package/dist/css/message.css +13 -10
- package/dist/css/reset.css +29 -88
- package/dist/css/splitter.css +2 -2
- package/dist/css/tabs.css +103 -0
- package/dist/js/focus-trap/focus-trap.embedded.mjs +6 -10
- package/dist/js/index.d.mts +2 -1
- package/dist/js/index.mjs +2 -1
- package/dist/js/internal/draggable.mjs +16 -22
- package/dist/js/internal/listbox/listbox.form.mjs +1 -1
- package/dist/js/internal/listbox/listbox.state.mjs +1 -1
- package/dist/js/internal/navigable.d.mts +11 -5
- package/dist/js/internal/navigable.mjs +44 -18
- package/dist/js/movable/movable.embedded.mjs +3 -6
- package/dist/js/resizable/resizable.embedded.mjs +16 -26
- package/dist/js/splitter.mjs +15 -12
- package/dist/js/tabs.d.mts +25 -0
- package/dist/js/tabs.mjs +240 -0
- package/dist/js/tooltip.mjs +13 -12
- package/package.json +1 -1
- package/src/css/badge.scss +6 -18
- package/src/css/button.scss +6 -45
- package/src/css/color.scss +20 -20
- package/src/css/combobox.scss +20 -51
- package/src/css/content.scss +30 -3
- package/src/css/floatable.scss +17 -17
- package/src/css/form.scss +84 -72
- package/src/css/listbox.scss +2 -31
- package/src/css/message.scss +13 -28
- package/src/css/mixins.scss +253 -28
- package/src/css/reset.scss +37 -86
- package/src/css/splitter.scss +2 -2
- package/src/css/tabs.scss +85 -0
- package/src/js/focus-trap/focus-trap.embedded.ts +11 -19
- package/src/js/index.ts +1 -0
- package/src/js/internal/draggable.ts +29 -33
- package/src/js/internal/listbox/listbox.form.ts +1 -1
- package/src/js/internal/listbox/listbox.state.ts +1 -1
- package/src/js/internal/navigable.ts +80 -23
- package/src/js/movable/movable.embedded.ts +11 -13
- package/src/js/resizable/resizable.embedded.ts +25 -39
- package/src/js/splitter.ts +21 -18
- package/src/js/tabs.ts +447 -0
- package/src/js/tooltip.ts +20 -17
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
|
|
2
|
+
:where(oui-tabs) {
|
|
3
|
+
display: flex;
|
|
4
|
+
}
|
|
5
|
+
:where(oui-tabs[orientation=horizontal i]) {
|
|
6
|
+
flex-flow: column nowrap;
|
|
7
|
+
}
|
|
8
|
+
:where(oui-tabs[orientation=vertical i]) {
|
|
9
|
+
flex-flow: row nowrap;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
:where([oui-tabs-content]) {
|
|
13
|
+
padding: 1em;
|
|
14
|
+
flex: 1;
|
|
15
|
+
background-color: var(--oui-absolute);
|
|
16
|
+
}
|
|
17
|
+
:where(oui-tabs[orientation=horizontal i] > [oui-tabs-content]) {
|
|
18
|
+
border-radius: 0 0 0.5em 0.5em;
|
|
19
|
+
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.125), inset 0 1px 2px -0.5px rgba(0, 0, 0, 0.05), inset 0 2px 4px -1px rgba(0, 0, 0, 0.05);
|
|
20
|
+
}
|
|
21
|
+
:where(oui-tabs[orientation=vertical i] > [oui-tabs-content]) {
|
|
22
|
+
border-radius: 0 0.5em 0.5em 0;
|
|
23
|
+
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.125), inset 1px 1px 2px -0.5px rgba(0, 0, 0, 0.05), inset 2px 2px 4px -1px rgba(0, 0, 0, 0.05);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
:where([oui-tabs-tab]) {
|
|
27
|
+
--oui-background-percentage: 25%;
|
|
28
|
+
--oui-background-value: var(--oui-gray-2);
|
|
29
|
+
--oui-foreground-percentage: 0%;
|
|
30
|
+
--oui-foreground-value: var(--oui-gray-8);
|
|
31
|
+
--oui-outline-percentage: 100%;
|
|
32
|
+
--oui-outline-value: var(--oui-gray-6);
|
|
33
|
+
--oui-shadow-inset: color-mix(in oklab, var(--oui-absolute), transparent 75%);
|
|
34
|
+
--oui-shadow-percentage: 82.5%;
|
|
35
|
+
--oui-shadow-value: color-mix(
|
|
36
|
+
in oklab,
|
|
37
|
+
var(--oui-outline-value),
|
|
38
|
+
transparent var(--oui-shadow-percentage)
|
|
39
|
+
);
|
|
40
|
+
box-shadow: inset 0 1px 0 0 var(--oui-shadow-inset), 0 0 0 1px var(--oui-shadow-value), 0 1px 2px -0.5px var(--oui-shadow-value), 0 2px 4px -1px var(--oui-shadow-value), 0 4px 8px -2px var(--oui-shadow-value);
|
|
41
|
+
padding: 0.5em 0.75em;
|
|
42
|
+
display: inline-flex;
|
|
43
|
+
flex-flow: row wrap;
|
|
44
|
+
gap: 0.75em;
|
|
45
|
+
align-items: center;
|
|
46
|
+
border-radius: 0.25em;
|
|
47
|
+
background-color: color-mix(in oklab, var(--oui-background-value), transparent var(--oui-background-percentage));
|
|
48
|
+
outline: 4px solid color-mix(in oklab, var(--oui-outline-value), transparent var(--oui-outline-percentage));
|
|
49
|
+
border: none;
|
|
50
|
+
color: color-mix(in oklab, var(--oui-foreground-value), transparent var(--oui-foreground-percentage));
|
|
51
|
+
line-height: 1.25;
|
|
52
|
+
transition: 0.125s ease-in-out;
|
|
53
|
+
transition-property: background, outline, box-shadow, color;
|
|
54
|
+
}
|
|
55
|
+
:where([oui-tabs-tab]):focus-visible {
|
|
56
|
+
--oui-outline-percentage: 75%;
|
|
57
|
+
}
|
|
58
|
+
@media (hover: hover) {
|
|
59
|
+
:where([oui-tabs-tab]):not([disabled], [aria-disabled=true i]):hover {
|
|
60
|
+
--oui-background-percentage: 50%;
|
|
61
|
+
--oui-foreground-percentage: 25%;
|
|
62
|
+
--oui-shadow-percentage: 90%;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
:where([oui-tabs-tab]):not([disabled], [aria-disabled=true i]):active {
|
|
66
|
+
box-shadow: 0 0 0 1px var(--oui-shadow-value), inset 0 1px 2px 0 var(--oui-shadow-value), inset 0 2px 4px 0 var(--oui-shadow-value);
|
|
67
|
+
}
|
|
68
|
+
:where([oui-tabs-tab])[disabled], :where([oui-tabs-tab])[aria-disabled=true i] {
|
|
69
|
+
--oui-background-percentage: 80%;
|
|
70
|
+
--oui-foreground-percentage: 25%;
|
|
71
|
+
--oui-shadow-percentage: 92.5%;
|
|
72
|
+
font-style: italic;
|
|
73
|
+
}
|
|
74
|
+
:where([oui-tabs-tab]) {
|
|
75
|
+
--oui-background-value: var(--oui-blue-3);
|
|
76
|
+
--oui-foreground-value: var(--oui-blue-8);
|
|
77
|
+
--oui-outline-value: var(--oui-blue-6);
|
|
78
|
+
font-size: 0.875rem;
|
|
79
|
+
align-self: flex-end;
|
|
80
|
+
}
|
|
81
|
+
:where([oui-tabs-tab][aria-selected=true i]) {
|
|
82
|
+
--oui-background-percentage: 80%;
|
|
83
|
+
box-shadow: 0 0 0 1px var(--oui-shadow-value), inset 0 1px 2px -0.5px var(--oui-shadow-value), inset 0 2px 4px -1px var(--oui-shadow-value);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
:where([oui-tabs-tablist]) {
|
|
87
|
+
display: flex;
|
|
88
|
+
gap: 0.5em;
|
|
89
|
+
}
|
|
90
|
+
:where([oui-tabs-tablist][aria-orientation=horizontal i]) {
|
|
91
|
+
flex-flow: row nowrap;
|
|
92
|
+
}
|
|
93
|
+
:where([oui-tabs-tablist][aria-orientation=horizontal i] > [oui-tabs-tab]) {
|
|
94
|
+
border-radius: 0.25em 0.25em 0 0;
|
|
95
|
+
}
|
|
96
|
+
:where([oui-tabs-tablist][aria-orientation=vertical i]) {
|
|
97
|
+
flex-flow: column nowrap;
|
|
98
|
+
}
|
|
99
|
+
:where([oui-tabs-tablist][aria-orientation=vertical i] > [oui-tabs-tab]) {
|
|
100
|
+
border-radius: 0.25em 0 0 0.25em;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
|
|
@@ -171,16 +171,12 @@ function onPointerdown(event) {
|
|
|
171
171
|
function onTab(event) {
|
|
172
172
|
const element = findAncestor(event, SELECTOR);
|
|
173
173
|
const instance = instances.get(element);
|
|
174
|
-
if (instance == null) return;
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
const index = elements.indexOf(event.target);
|
|
181
|
-
if (index === -1 || elements.length === 0) tabToTrap(instance, elements, element);
|
|
182
|
-
else tabToElement(instance, elements, index, event.shiftKey ? -1 : 1);
|
|
183
|
-
});
|
|
174
|
+
if (instance == null || dispatch(element, "oui:focus-trap").defaultPrevented) return;
|
|
175
|
+
if (!instance.disabled) event.preventDefault();
|
|
176
|
+
const elements = getFocusable(element);
|
|
177
|
+
const index = elements.indexOf(event.target);
|
|
178
|
+
if (index === -1 || elements.length === 0) tabToTrap(instance, elements, element);
|
|
179
|
+
else tabToElement(instance, elements, index, event.shiftKey ? -1 : 1);
|
|
184
180
|
}
|
|
185
181
|
function removeFocusTrap(element) {
|
|
186
182
|
instances.get(element)?.destroy();
|
package/dist/js/index.d.mts
CHANGED
|
@@ -12,5 +12,6 @@ import { OuiListboxElement } from "./listbox/index.mjs";
|
|
|
12
12
|
import { OuiPopover, getPopover } from "./popover.mjs";
|
|
13
13
|
import "./sortable/sortable.standalone.mjs";
|
|
14
14
|
import { OuiSplitterElement } from "./splitter.mjs";
|
|
15
|
+
import { OuiTabsElement, OuiTabsEvent } from "./tabs.mjs";
|
|
15
16
|
import { OuiTooltip, getTooltip, setTooltipDelay } from "./tooltip.mjs";
|
|
16
|
-
export { type CreateOuiFloatableOptions, type CreateOuiDraggableOptions as CreateOuiMovableOptions, type CreateOuiDraggableOptions as CreateOuiSortableOptions, type CreateOuiResizableOptions, OuiComboboxElement, type OuiDialog, type OuiFloatable, type OuiFloatablePosition, type OuiFocusTrap, type OuiFocusTrapOptions, OuiListboxElement, type OuiMovable, type OuiPopover, type OuiResizable, type OuiSortable, OuiSplitterElement, type OuiTooltip, createFloatable, createFocusTrap, createMovable, createResizable as createOuiResizable, createSortable, getDialog, getPopover, getTooltip, setComboboxLocalizations, setListboxLocalizations, setTooltipDelay };
|
|
17
|
+
export { type CreateOuiFloatableOptions, type CreateOuiDraggableOptions as CreateOuiMovableOptions, type CreateOuiDraggableOptions as CreateOuiSortableOptions, type CreateOuiResizableOptions, OuiComboboxElement, type OuiDialog, type OuiFloatable, type OuiFloatablePosition, type OuiFocusTrap, type OuiFocusTrapOptions, OuiListboxElement, type OuiMovable, type OuiPopover, type OuiResizable, type OuiSortable, OuiSplitterElement, OuiTabsElement, OuiTabsEvent, type OuiTooltip, createFloatable, createFocusTrap, createMovable, createResizable as createOuiResizable, createSortable, getDialog, getPopover, getTooltip, setComboboxLocalizations, setListboxLocalizations, setTooltipDelay };
|
package/dist/js/index.mjs
CHANGED
|
@@ -17,5 +17,6 @@ import "./resizable/resizable.standalone.mjs";
|
|
|
17
17
|
import { createSortable } from "./sortable/sortable.embedded.mjs";
|
|
18
18
|
import "./sortable/sortable.standalone.mjs";
|
|
19
19
|
import { OuiSplitterElement } from "./splitter.mjs";
|
|
20
|
+
import { OuiTabsElement, OuiTabsEvent } from "./tabs.mjs";
|
|
20
21
|
import { getTooltip, setTooltipDelay } from "./tooltip.mjs";
|
|
21
|
-
export { OuiComboboxElement, OuiListboxElement, OuiSplitterElement, createFloatable, createFocusTrap, createMovable, createResizable as createOuiResizable, createSortable, getDialog, getPopover, getTooltip, setComboboxLocalizations, setListboxLocalizations, setTooltipDelay };
|
|
22
|
+
export { OuiComboboxElement, OuiListboxElement, OuiSplitterElement, OuiTabsElement, OuiTabsEvent, createFloatable, createFocusTrap, createMovable, createResizable as createOuiResizable, createSortable, getDialog, getPopover, getTooltip, setComboboxLocalizations, setListboxLocalizations, setTooltipDelay };
|
|
@@ -54,7 +54,7 @@ function addDraggable(element, options) {
|
|
|
54
54
|
function cancelDrag(item) {
|
|
55
55
|
if (item == null) return;
|
|
56
56
|
item.state.options.drag.onCancel?.(globals, item);
|
|
57
|
-
dispatch(item.state.element,
|
|
57
|
+
dispatch(item.state.element, `oui:${item.state.name}:cancel`, { detail: { element: item.state.options.getOrigin() } });
|
|
58
58
|
reset();
|
|
59
59
|
}
|
|
60
60
|
function destroyInstance(instance, state) {
|
|
@@ -130,26 +130,23 @@ function onPointerdown(event) {
|
|
|
130
130
|
};
|
|
131
131
|
globals.offset = item.state.options.position.getOffset(globals, item, element, position);
|
|
132
132
|
globals.original = item.state.options.position.getOriginal(globals, item, position);
|
|
133
|
-
|
|
133
|
+
if (dispatch(item.state.element, `oui:${item.state.name}:begin`, { detail: {
|
|
134
134
|
element,
|
|
135
135
|
position: { ...globals.original }
|
|
136
|
-
} })
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
inset: `${next.y}px auto auto ${next.x}px`,
|
|
147
|
-
transform: "translate3d(0, 0, 0)"
|
|
148
|
-
});
|
|
149
|
-
item.state.options.drag.onBegin?.(event, globals, item, element, handle, next);
|
|
150
|
-
item.state.styling.set();
|
|
151
|
-
styleToggler.set();
|
|
136
|
+
} }).defaultPrevented) {
|
|
137
|
+
item.state.options.drag.onCancel?.(globals, item);
|
|
138
|
+
reset();
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
const next = getNextPosition(item, position);
|
|
142
|
+
setStyles(dragged, {
|
|
143
|
+
position: "fixed",
|
|
144
|
+
inset: `${next.y}px auto auto ${next.x}px`,
|
|
145
|
+
transform: "translate3d(0, 0, 0)"
|
|
152
146
|
});
|
|
147
|
+
item.state.options.drag.onBegin?.(event, globals, item, element, handle, next);
|
|
148
|
+
item.state.styling.set();
|
|
149
|
+
styleToggler.set();
|
|
153
150
|
}
|
|
154
151
|
function onPointermove(event) {
|
|
155
152
|
if (current == null) return;
|
|
@@ -161,10 +158,7 @@ function onPointermove(event) {
|
|
|
161
158
|
calculated: next,
|
|
162
159
|
original: position
|
|
163
160
|
});
|
|
164
|
-
|
|
165
|
-
setTimeout(() => {
|
|
166
|
-
if (dispatched.defaultPrevented) cancelDrag(current);
|
|
167
|
-
});
|
|
161
|
+
if (dispatch(current.state.element, `oui:${current.state.name}:move`, { detail }).defaultPrevented) cancelDrag(current);
|
|
168
162
|
}
|
|
169
163
|
function onPointerup(event) {
|
|
170
164
|
current?.state.options.drag.onEnd?.(event, globals, current, reset);
|
|
@@ -12,7 +12,7 @@ function updateListboxForm(state, values, emit) {
|
|
|
12
12
|
state.internals.setFormValue(value, JSON.stringify(values));
|
|
13
13
|
state.callbacks.data.onForm(state);
|
|
14
14
|
updateListboxValidity(state);
|
|
15
|
-
if (emit ?? true) dispatch(state.host, "change");
|
|
15
|
+
if (emit ?? true) dispatch(state.host, "oui:change");
|
|
16
16
|
}
|
|
17
17
|
function updateListboxValidity(state) {
|
|
18
18
|
if (state.autocomplete.none && !state.listbox) {
|
|
@@ -33,7 +33,7 @@ function initializeListboxState(state, states, onAttach) {
|
|
|
33
33
|
updateListboxForm(state, state.values.current, false);
|
|
34
34
|
updateListboxMessage(state);
|
|
35
35
|
updateListboxValueLabel(state);
|
|
36
|
-
if (state.options.selected.length > 0) updateListboxPreview("none", state, state.options.selected[0]);
|
|
36
|
+
if (state.options.selected.length > 0) updateListboxPreview("none", state, state.options.selected[0], false);
|
|
37
37
|
return state;
|
|
38
38
|
}
|
|
39
39
|
//#endregion
|
|
@@ -8,24 +8,30 @@ declare class OuiNavigable {
|
|
|
8
8
|
orientation: OuiNavigableOrientation;
|
|
9
9
|
constructor(element: HTMLElement, options: OuiNavigableOptions);
|
|
10
10
|
destroy(): void;
|
|
11
|
+
navigate(index: number, focus?: boolean): void;
|
|
11
12
|
}
|
|
12
13
|
type OuiNavigableActive = {
|
|
13
14
|
element?: HTMLElement;
|
|
14
15
|
index: number;
|
|
15
16
|
};
|
|
17
|
+
type OuiNavigableCallback<ReturnType> = (event: KeyboardEvent, navigable: OuiNavigable) => ReturnType;
|
|
16
18
|
type OuiNavigableOptions = {
|
|
19
|
+
orientation?: OuiNavigableOrientation;
|
|
17
20
|
role?: AriaRole;
|
|
18
21
|
selector: string;
|
|
19
22
|
vertical: boolean;
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
onActivate?: (navigable: OuiNavigable) => void;
|
|
24
|
+
onDeactivate?: OuiNavigableCallback<void>;
|
|
25
|
+
onNavigation?: (navigable: OuiNavigable) => void;
|
|
26
|
+
onPreventNavigation?: OuiNavigableCallback<boolean>;
|
|
27
|
+
onShouldActivate?: OuiNavigableCallback<boolean>;
|
|
28
|
+
onShouldDeactivate?: OuiNavigableCallback<boolean | undefined>;
|
|
24
29
|
};
|
|
25
30
|
type OuiNavigableOrientation = 'horizontal' | 'vertical';
|
|
26
31
|
declare function getNavigable(element: HTMLElement, options: OuiNavigableOptions): OuiNavigable;
|
|
32
|
+
declare function getNavigableOrientation(element: HTMLElement, vertical: boolean, aria?: boolean): OuiNavigableOrientation;
|
|
27
33
|
declare function updateNavigableFocus(navigable: OuiNavigable, focus: boolean, items?: HTMLElement[]): void;
|
|
28
34
|
declare const NAVIGABLE_KEYS_HORIZONTAL: Set<string>;
|
|
29
35
|
declare const NAVIGABLE_KEYS_VERTICAL: Set<string>;
|
|
30
36
|
//#endregion
|
|
31
|
-
export { NAVIGABLE_KEYS_HORIZONTAL, NAVIGABLE_KEYS_VERTICAL, OuiNavigable, OuiNavigableOptions, getNavigable, updateNavigableFocus };
|
|
37
|
+
export { NAVIGABLE_KEYS_HORIZONTAL, NAVIGABLE_KEYS_VERTICAL, OuiNavigable, OuiNavigableOptions, OuiNavigableOrientation, getNavigable, getNavigableOrientation, updateNavigableFocus };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { getAria, setRole } from "@oscarpalmer/toretto/aria";
|
|
2
|
-
import {
|
|
1
|
+
import { getAria, setAria, setRole } from "@oscarpalmer/toretto/aria";
|
|
2
|
+
import { on } from "@oscarpalmer/toretto/event";
|
|
3
|
+
import { getAttribute } from "@oscarpalmer/toretto/attribute";
|
|
3
4
|
import { isHTMLOrSVGElement } from "@oscarpalmer/toretto/is";
|
|
4
5
|
import { clamp } from "@oscarpalmer/atoms/number";
|
|
5
6
|
import { findAncestor } from "@oscarpalmer/toretto/find";
|
|
@@ -13,12 +14,19 @@ var OuiNavigable = class {
|
|
|
13
14
|
constructor(element, options) {
|
|
14
15
|
this.element = element;
|
|
15
16
|
this.options = options;
|
|
16
|
-
this.listeners = [
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
this.listeners = [
|
|
18
|
+
on(element, "click", (event) => {
|
|
19
|
+
onClick(this, event);
|
|
20
|
+
}, { passive: false }),
|
|
21
|
+
on(element, "focusin", (event) => {
|
|
22
|
+
onFocusin(this, event);
|
|
23
|
+
}),
|
|
24
|
+
on(element, "keydown", (event) => {
|
|
25
|
+
onKeydown(this, event);
|
|
26
|
+
}, { passive: false })
|
|
27
|
+
];
|
|
28
|
+
this.orientation = options?.orientation ?? getNavigableOrientation(element, options.vertical);
|
|
29
|
+
setAria(element, "orientation", this.orientation);
|
|
22
30
|
if (options.role != null) setRole(element, options.role);
|
|
23
31
|
}
|
|
24
32
|
destroy() {
|
|
@@ -27,6 +35,10 @@ var OuiNavigable = class {
|
|
|
27
35
|
this.active.element = void 0;
|
|
28
36
|
this.element = void 0;
|
|
29
37
|
}
|
|
38
|
+
navigate(index, focus) {
|
|
39
|
+
const items = getItems(this.element, this.options.selector);
|
|
40
|
+
if (index >= 0 && index < items.length) onNavigate(this, index, items, focus ?? false);
|
|
41
|
+
}
|
|
30
42
|
};
|
|
31
43
|
function getItems(container, selector) {
|
|
32
44
|
return [...container.querySelectorAll(selector)].filter(isValidItem);
|
|
@@ -34,13 +46,28 @@ function getItems(container, selector) {
|
|
|
34
46
|
function getNavigable(element, options) {
|
|
35
47
|
return new OuiNavigable(element, options);
|
|
36
48
|
}
|
|
37
|
-
function
|
|
38
|
-
const attribute = getAria(element, "orientation");
|
|
39
|
-
return ORIENTATIONS.has(attribute) ? attribute :
|
|
49
|
+
function getNavigableOrientation(element, vertical, aria) {
|
|
50
|
+
const attribute = aria ?? true ? getAria(element, "orientation") : getAttribute(element, "orientation");
|
|
51
|
+
return ORIENTATIONS.has(attribute) ? attribute : vertical ? ORIENTATION_VERTICAL : ORIENTATION_HORIZONTAL;
|
|
40
52
|
}
|
|
41
53
|
function isValidItem(element) {
|
|
42
54
|
return "disabled" in element ? element.disabled !== true : true;
|
|
43
55
|
}
|
|
56
|
+
function onClick(navigable, event) {
|
|
57
|
+
const item = findAncestor(event, navigable.options.selector);
|
|
58
|
+
const items = getItems(navigable.element, navigable.options.selector);
|
|
59
|
+
const index = items.indexOf(item);
|
|
60
|
+
if (index === -1) return;
|
|
61
|
+
if (index !== navigable.active.index) onNavigate(navigable, index, items, false);
|
|
62
|
+
navigable.options.onActivate?.(navigable);
|
|
63
|
+
item.focus();
|
|
64
|
+
}
|
|
65
|
+
function onNavigate(navigable, index, items, focus) {
|
|
66
|
+
navigable.active.element = items[index];
|
|
67
|
+
navigable.active.index = index;
|
|
68
|
+
updateNavigableFocus(navigable, focus, items);
|
|
69
|
+
navigable.options.onNavigation?.(navigable);
|
|
70
|
+
}
|
|
44
71
|
function onFocusin(navigable, event) {
|
|
45
72
|
const item = findAncestor(event, navigable.options.selector);
|
|
46
73
|
if (!isHTMLOrSVGElement(item) || !isValidItem(item)) return;
|
|
@@ -63,7 +90,10 @@ function onKeydown(navigable, event) {
|
|
|
63
90
|
const mustActivate = KEYS_ACTIVATE.has(event.key);
|
|
64
91
|
const shouldActivate = navigable.options.onShouldActivate?.(event, navigable) === true;
|
|
65
92
|
if (mustActivate || shouldActivate || navigable.options.onPreventNavigation?.(event, navigable) === true) event.stopPropagation();
|
|
66
|
-
if (mustActivate || shouldActivate)
|
|
93
|
+
if (mustActivate || shouldActivate) {
|
|
94
|
+
navigable.options.onActivate?.(navigable);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
67
97
|
const items = getItems(navigable.element, navigable.options.selector);
|
|
68
98
|
const { length } = items;
|
|
69
99
|
if (length === 0) return;
|
|
@@ -76,10 +106,7 @@ function onKeydown(navigable, event) {
|
|
|
76
106
|
index = clamp(navigable.active.index + (KEYS_NEXT.has(event.key) ? 1 : -1), 0, length - 1, true);
|
|
77
107
|
}
|
|
78
108
|
}
|
|
79
|
-
if (index
|
|
80
|
-
navigable.active.element = items[index];
|
|
81
|
-
navigable.active.index = index;
|
|
82
|
-
updateNavigableFocus(navigable, true, items);
|
|
109
|
+
if (index != null && index !== navigable.active.index) onNavigate(navigable, index, items, true);
|
|
83
110
|
}
|
|
84
111
|
function updateNavigableFocus(navigable, focus, items) {
|
|
85
112
|
const updated = items ?? getItems(navigable.element, navigable.options.selector);
|
|
@@ -88,7 +115,6 @@ function updateNavigableFocus(navigable, focus, items) {
|
|
|
88
115
|
for (let index = 0; index < length; index += 1) updated[index].tabIndex = index === navigable.active.index ? 0 : -1;
|
|
89
116
|
navigable.active.element ??= updated[navigable.active.index];
|
|
90
117
|
if (focus) navigable.active.element?.focus();
|
|
91
|
-
dispatch(navigable.active.element, "navigable:change", { detail: { ...navigable.active } });
|
|
92
118
|
}
|
|
93
119
|
const KEYS_ABSOLUTE = /* @__PURE__ */ new Set(["End", "Home"]);
|
|
94
120
|
const KEYS_ACTIVATE = /* @__PURE__ */ new Set(["Enter", " "]);
|
|
@@ -105,4 +131,4 @@ const ORIENTATION_HORIZONTAL = "horizontal";
|
|
|
105
131
|
const ORIENTATION_VERTICAL = "vertical";
|
|
106
132
|
const ORIENTATIONS = /* @__PURE__ */ new Set([ORIENTATION_HORIZONTAL, ORIENTATION_VERTICAL]);
|
|
107
133
|
//#endregion
|
|
108
|
-
export { NAVIGABLE_KEYS_HORIZONTAL, NAVIGABLE_KEYS_VERTICAL, OuiNavigable, getNavigable, updateNavigableFocus };
|
|
134
|
+
export { NAVIGABLE_KEYS_HORIZONTAL, NAVIGABLE_KEYS_VERTICAL, OuiNavigable, getNavigable, getNavigableOrientation, updateNavigableFocus };
|
|
@@ -110,14 +110,11 @@ function onEnd(event, globals, item, reset) {
|
|
|
110
110
|
}
|
|
111
111
|
const container = state.container?.getBoundingClientRect();
|
|
112
112
|
if (container != null) setOffset(state, container);
|
|
113
|
-
|
|
113
|
+
if (dispatch(state.element, "oui:movable:end", { detail: {
|
|
114
114
|
from: { ...globals.original },
|
|
115
115
|
to: getEventPosition(event)
|
|
116
|
-
} });
|
|
117
|
-
|
|
118
|
-
if (dispatched.defaultPrevented) onCancel(globals, item);
|
|
119
|
-
reset();
|
|
120
|
-
});
|
|
116
|
+
} }).defaultPrevented) onCancel(globals, item);
|
|
117
|
+
reset();
|
|
121
118
|
}
|
|
122
119
|
function onMove(_, globals, __, position) {
|
|
123
120
|
setAttribute(globals.element?.node, ATTRIBUTE_MOVING, "");
|
|
@@ -49,7 +49,7 @@ function cancelResize(item) {
|
|
|
49
49
|
width: `${item.state.width}px`
|
|
50
50
|
});
|
|
51
51
|
resetResizable();
|
|
52
|
-
dispatch(item.state.element, "resizable:cancel");
|
|
52
|
+
dispatch(item.state.element, "oui:resizable:cancel");
|
|
53
53
|
}
|
|
54
54
|
/**
|
|
55
55
|
* Creates _(or retrieves)_ a _OuiResizable_ instance for an element
|
|
@@ -130,14 +130,11 @@ function onPointerdown(event) {
|
|
|
130
130
|
const position = getEventPosition(event);
|
|
131
131
|
if (stored == null || position == null) return;
|
|
132
132
|
if (supportsTouch.value) event.preventDefault();
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
current.state.styles.set();
|
|
139
|
-
styleToggler.set();
|
|
140
|
-
});
|
|
133
|
+
if (dispatch(element, "oui:resizable:begin").defaultPrevented) return;
|
|
134
|
+
current = stored;
|
|
135
|
+
start = position;
|
|
136
|
+
current.state.styles.set();
|
|
137
|
+
styleToggler.set();
|
|
141
138
|
}
|
|
142
139
|
function onPointermove(event) {
|
|
143
140
|
if (current == null) return;
|
|
@@ -149,27 +146,20 @@ function onPointermove(event) {
|
|
|
149
146
|
height,
|
|
150
147
|
width
|
|
151
148
|
});
|
|
152
|
-
|
|
149
|
+
if (dispatch(current.state.element, "oui:resizable:resize", { detail: {
|
|
153
150
|
height,
|
|
154
151
|
width
|
|
155
|
-
} });
|
|
156
|
-
setTimeout(() => {
|
|
157
|
-
if (dispatched.defaultPrevented) cancelResize(current);
|
|
158
|
-
});
|
|
152
|
+
} }).defaultPrevented) cancelResize(current);
|
|
159
153
|
}
|
|
160
154
|
function onPointerup() {
|
|
161
|
-
if (current == null)
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
current.state.height = height;
|
|
170
|
-
current.state.width = width;
|
|
171
|
-
resetResizable();
|
|
172
|
-
});
|
|
155
|
+
if (current == null || dispatch(current.state.element, "oui:resizable:end").defaultPrevented) {
|
|
156
|
+
cancelResize(current);
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
const { height, width } = current.state.element.getBoundingClientRect();
|
|
160
|
+
current.state.height = height;
|
|
161
|
+
current.state.width = width;
|
|
162
|
+
resetResizable();
|
|
173
163
|
}
|
|
174
164
|
function removeResizable(element) {
|
|
175
165
|
items.get(element)?.instance.destroy();
|
package/dist/js/splitter.mjs
CHANGED
|
@@ -6,6 +6,7 @@ import { setStyle, toggleStyles } from "@oscarpalmer/toretto/style";
|
|
|
6
6
|
import { clamp } from "@oscarpalmer/atoms/number";
|
|
7
7
|
import { findAncestor } from "@oscarpalmer/toretto/find";
|
|
8
8
|
import supportsTouch from "@oscarpalmer/toretto/touch";
|
|
9
|
+
import { createElement } from "@oscarpalmer/toretto/create";
|
|
9
10
|
import { round } from "@oscarpalmer/atoms/math";
|
|
10
11
|
//#region src/js/splitter.ts
|
|
11
12
|
const ATTRIBUTE_MAX = "max";
|
|
@@ -135,21 +136,23 @@ var OuiSplitterElement = class extends HTMLElement {
|
|
|
135
136
|
}
|
|
136
137
|
};
|
|
137
138
|
function createHandle() {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
139
|
+
return createElement("span", {
|
|
140
|
+
aria: { hidden: true },
|
|
141
|
+
attribute: { [ATTRIBUTE_HANDLE]: "" }
|
|
142
|
+
});
|
|
142
143
|
}
|
|
143
144
|
function createSeparator(splitter) {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
145
|
+
return createElement("div", {
|
|
146
|
+
aria: {
|
|
147
|
+
controls: splitter.element.id,
|
|
148
|
+
label: "Resize panels"
|
|
149
|
+
},
|
|
150
|
+
attribute: { [ATTRIBUTE_SEPARATOR]: "" },
|
|
151
|
+
property: {
|
|
152
|
+
role: "separator",
|
|
153
|
+
tabIndex: 0
|
|
154
|
+
}
|
|
150
155
|
});
|
|
151
|
-
setAttribute(separator, ATTRIBUTE_SEPARATOR, "");
|
|
152
|
-
return separator;
|
|
153
156
|
}
|
|
154
157
|
function getContained(min, value, max) {
|
|
155
158
|
return round(clamp(value, min, max), VALUE_DECIMALS);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
//#region src/js/tabs.d.ts
|
|
2
|
+
declare global {
|
|
3
|
+
interface HTMLElementTagNameMap {
|
|
4
|
+
[TAGNAME]: OuiTabsElement;
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
declare class OuiTabsEvent extends Event {
|
|
8
|
+
oldIndex: number;
|
|
9
|
+
newIndex: number;
|
|
10
|
+
constructor(name: 'oui:beforechange' | 'oui:change', oldIndex: number, newIndex: number, cancelable: boolean);
|
|
11
|
+
}
|
|
12
|
+
declare class OuiTabsElement extends HTMLElement {
|
|
13
|
+
#private;
|
|
14
|
+
static observedAttributes: string[];
|
|
15
|
+
get active(): number;
|
|
16
|
+
set active(value: number);
|
|
17
|
+
get panel(): HTMLElement;
|
|
18
|
+
get tab(): HTMLButtonElement;
|
|
19
|
+
attributeChangedCallback(name: string, _: string | null, value: string | null): void;
|
|
20
|
+
connectedCallback(): void;
|
|
21
|
+
disconnectedCallback(): void;
|
|
22
|
+
}
|
|
23
|
+
declare const TAGNAME = "oui-tabs";
|
|
24
|
+
//#endregion
|
|
25
|
+
export { OuiTabsElement, OuiTabsEvent };
|