@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/dist/css/floatable.css
CHANGED
|
@@ -30,6 +30,15 @@
|
|
|
30
30
|
transition-delay: 0.125s;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
:where([oui-dialog]) {
|
|
34
|
+
position: relative;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
:where([oui-dialog-resizer]) {
|
|
38
|
+
position: absolute;
|
|
39
|
+
inset: auto 0 0 auto;
|
|
40
|
+
}
|
|
41
|
+
|
|
33
42
|
:where([oui-popover], [oui-tooltip-content]) {
|
|
34
43
|
--margin-bottom: 0.5em;
|
|
35
44
|
--margin-left: 0.5em;
|
package/dist/js/dialog.d.mts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { h as OuiMovable } from "./draggable-
|
|
1
|
+
import { h as OuiMovable } from "./draggable-fIYXd8eO.mjs";
|
|
2
|
+
import { n as OuiResizable } from "./resizable.embedded-CXrUVPzR.mjs";
|
|
2
3
|
import { RemovableEventListener } from "@oscarpalmer/toretto/models";
|
|
3
4
|
|
|
4
5
|
//#region src/js/dialog.d.ts
|
|
@@ -32,6 +33,7 @@ type OuiDialogState = {
|
|
|
32
33
|
listeners: RemovableEventListener[];
|
|
33
34
|
modal: boolean;
|
|
34
35
|
movable?: OuiMovable;
|
|
36
|
+
resizable?: OuiResizable;
|
|
35
37
|
};
|
|
36
38
|
/**
|
|
37
39
|
* Get the _OuiDialog_ for an element
|
package/dist/js/dialog.mjs
CHANGED
|
@@ -2,7 +2,11 @@ import { getOnBeforeToggleListener } from "./floatable/floatable.embedded.mjs";
|
|
|
2
2
|
import { attributable } from "./internal/attributable.mjs";
|
|
3
3
|
import { ATTRIBUTE_MOVABLE_HANDLE, createMovable } from "./movable/movable.embedded.mjs";
|
|
4
4
|
import "./movable/movable.standalone.mjs";
|
|
5
|
+
import { RESIZABLE_ATTRIBUTE_HANDLE, createResizable } from "./resizable/resizable.embedded.mjs";
|
|
6
|
+
import { getAria, setAria } from "@oscarpalmer/toretto/aria";
|
|
5
7
|
import { on } from "@oscarpalmer/toretto/event";
|
|
8
|
+
import { getAttribute, setAttribute } from "@oscarpalmer/toretto/attribute";
|
|
9
|
+
import { setStyles } from "@oscarpalmer/toretto/style";
|
|
6
10
|
//#region src/js/dialog.ts
|
|
7
11
|
var OuiDialog = class {
|
|
8
12
|
#state;
|
|
@@ -34,7 +38,7 @@ var OuiDialog = class {
|
|
|
34
38
|
const { element } = this.#state;
|
|
35
39
|
if (element == null || element.open) return;
|
|
36
40
|
const isModal = modal !== false;
|
|
37
|
-
element
|
|
41
|
+
setAria(element, "modal", isModal);
|
|
38
42
|
if (isModal) element.showModal();
|
|
39
43
|
else element.show();
|
|
40
44
|
}
|
|
@@ -45,12 +49,16 @@ function addDialog(element) {
|
|
|
45
49
|
}
|
|
46
50
|
function destroyDialog(state) {
|
|
47
51
|
state.element.close();
|
|
48
|
-
state.element
|
|
52
|
+
setAria(state.element, "modal", state.modal);
|
|
49
53
|
state.element.removeAttribute(ATTRIBUTE_OPEN);
|
|
50
54
|
for (const listener of state.listeners) listener();
|
|
55
|
+
state.movable?.destroy();
|
|
56
|
+
state.resizable?.destroy();
|
|
51
57
|
state.dialog = void 0;
|
|
52
58
|
state.element = void 0;
|
|
53
59
|
state.listeners = void 0;
|
|
60
|
+
state.movable = void 0;
|
|
61
|
+
state.resizable = void 0;
|
|
54
62
|
}
|
|
55
63
|
/**
|
|
56
64
|
* Get the _OuiDialog_ for an element
|
|
@@ -64,32 +72,44 @@ function getDialog(element) {
|
|
|
64
72
|
function getMovable(element) {
|
|
65
73
|
const handles = element.querySelectorAll(SELECTOR_MOVER);
|
|
66
74
|
if (handles.length === 0) return;
|
|
67
|
-
for (const handle of handles)
|
|
68
|
-
return createMovable(element, { container:
|
|
75
|
+
for (const handle of handles) setAttribute(handle, ATTRIBUTE_MOVABLE_HANDLE, "");
|
|
76
|
+
return createMovable(element, { container: getAttribute(element, ATTRIBUTE_CONTAINER) });
|
|
77
|
+
}
|
|
78
|
+
function getResizable(element) {
|
|
79
|
+
const handle = element.querySelector(SELECTOR_RESIZER);
|
|
80
|
+
if (handle == null) return;
|
|
81
|
+
setAttribute(handle, RESIZABLE_ATTRIBUTE_HANDLE, "");
|
|
82
|
+
return createResizable(element);
|
|
69
83
|
}
|
|
70
84
|
function getState(element) {
|
|
71
85
|
const state = {
|
|
72
86
|
element,
|
|
73
87
|
dialog: void 0,
|
|
74
|
-
listeners: [getOnBeforeToggleListener(element), on(element,
|
|
88
|
+
listeners: [getOnBeforeToggleListener(element), on(element, "toggle", (event) => {
|
|
75
89
|
const { source } = event;
|
|
76
90
|
if (element.open) {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
element.setAttribute(ATTRIBUTE_OPEN, "");
|
|
91
|
+
setAria(element, "modal", source instanceof HTMLButtonElement && source.command === "show-modal" || element.matches(":modal"));
|
|
92
|
+
setAttribute(element, ATTRIBUTE_OPEN, "");
|
|
80
93
|
element.focus();
|
|
94
|
+
setTimeout(() => {
|
|
95
|
+
state.resizable?.set();
|
|
96
|
+
}, 500);
|
|
81
97
|
} else {
|
|
82
|
-
element
|
|
83
|
-
element
|
|
84
|
-
element
|
|
85
|
-
|
|
86
|
-
|
|
98
|
+
setAttribute(element, ATTRIBUTE_OPEN);
|
|
99
|
+
setAria(element, "modal", state.modal);
|
|
100
|
+
setStyles(element, {
|
|
101
|
+
inset: "",
|
|
102
|
+
position: "",
|
|
103
|
+
transform: ""
|
|
104
|
+
});
|
|
105
|
+
state.resizable?.reset();
|
|
87
106
|
}
|
|
88
107
|
})],
|
|
89
|
-
modal: element
|
|
108
|
+
modal: getAria(element, "modal") === "true" || element.matches(":modal")
|
|
90
109
|
};
|
|
91
110
|
state.dialog = new OuiDialog(state);
|
|
92
111
|
state.movable = getMovable(element);
|
|
112
|
+
state.resizable = getResizable(element);
|
|
93
113
|
return state;
|
|
94
114
|
}
|
|
95
115
|
function removeDialog(element) {
|
|
@@ -98,16 +118,12 @@ function removeDialog(element) {
|
|
|
98
118
|
destroyDialog(state);
|
|
99
119
|
states.delete(element);
|
|
100
120
|
}
|
|
101
|
-
const ARIA_MODAL = "aria-modal";
|
|
102
121
|
const ATTRIBUTE = "oui-dialog";
|
|
103
122
|
const ATTRIBUTE_CONTAINER = `${ATTRIBUTE}-container`;
|
|
104
123
|
const ATTRIBUTE_OPEN = `${ATTRIBUTE}-open`;
|
|
105
|
-
const COMMAND_SHOW_MODAL = "show-modal";
|
|
106
|
-
const EVENT_TOGGLE = "toggle";
|
|
107
124
|
const MESSAGE = "The element must be an instance of HTMLDialogElement";
|
|
108
125
|
const SELECTOR_MOVER = `[${ATTRIBUTE}-mover]`;
|
|
109
|
-
const
|
|
110
|
-
const TRUE = "true";
|
|
126
|
+
const SELECTOR_RESIZER = `[${ATTRIBUTE}-resizer]`;
|
|
111
127
|
const states = /* @__PURE__ */ new WeakMap();
|
|
112
128
|
attributable(ATTRIBUTE, addDialog, removeDialog);
|
|
113
129
|
//#endregion
|
|
@@ -17,8 +17,8 @@ type OuiMovableState = {
|
|
|
17
17
|
style: OuiMovableStyle;
|
|
18
18
|
};
|
|
19
19
|
type OuiMovableStyle = {
|
|
20
|
-
inset: string;
|
|
21
|
-
position: string;
|
|
20
|
+
inset: string | undefined;
|
|
21
|
+
position: string | undefined;
|
|
22
22
|
};
|
|
23
23
|
/**
|
|
24
24
|
* Creates _(or retrieves)_ a _OuiMovable_ instance for an element
|
|
@@ -35,7 +35,7 @@ declare class OuiSortable extends OuiDraggable<OuiSortableState> {
|
|
|
35
35
|
constructor(element: HTMLElement, options?: CreateOuiDraggableOptions);
|
|
36
36
|
}
|
|
37
37
|
type OuiSortableState = {
|
|
38
|
-
connections: string | null;
|
|
38
|
+
connections: string | null | undefined;
|
|
39
39
|
origin?: HTMLElement;
|
|
40
40
|
};
|
|
41
41
|
/**
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
export { ATTRIBUTE_FLOATABLE, CreateOuiFloatableOptions,
|
|
1
|
+
import { a as OuiFloatablePosition, c as getOnBeforeToggleListener, i as OuiFloatableOptions, l as removeFloatable, n as CreateOuiFloatableOptions, o as createEmbeddedFloatable, r as OuiFloatable, s as createFloatable, t as ATTRIBUTE_FLOATABLE } from "../floatable.embedded-DUR8bQBK.mjs";
|
|
2
|
+
export { ATTRIBUTE_FLOATABLE, CreateOuiFloatableOptions, OuiFloatable, OuiFloatableOptions, OuiFloatablePosition, createEmbeddedFloatable, createFloatable, getOnBeforeToggleListener, removeFloatable };
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import { getAria } from "@oscarpalmer/toretto/aria";
|
|
1
2
|
import { on } from "@oscarpalmer/toretto/event";
|
|
2
3
|
import { isPlainObject } from "@oscarpalmer/atoms/is";
|
|
4
|
+
import { getAttribute, setAttribute } from "@oscarpalmer/toretto/attribute";
|
|
3
5
|
import { isHTMLOrSVGElement } from "@oscarpalmer/toretto/is";
|
|
6
|
+
import { setStyle, setStyles } from "@oscarpalmer/toretto/style";
|
|
4
7
|
//#region src/js/floatable/floatable.embedded.ts
|
|
5
8
|
var OuiFloatable = class {
|
|
6
9
|
#destroyed = false;
|
|
@@ -22,11 +25,11 @@ var OuiFloatable = class {
|
|
|
22
25
|
this.#state = state;
|
|
23
26
|
const { anchor, content } = state;
|
|
24
27
|
if (standalone) {
|
|
25
|
-
|
|
28
|
+
setAttribute(content, ATTRIBUTE_FLOATABLE, "");
|
|
26
29
|
content.popover = "manual";
|
|
27
|
-
}
|
|
28
|
-
anchor
|
|
29
|
-
content
|
|
30
|
+
} else content.popover ??= "auto";
|
|
31
|
+
setStyle(anchor, "anchorName", state.name);
|
|
32
|
+
setStyle(content, "positionAnchor", state.name);
|
|
30
33
|
}
|
|
31
34
|
/**
|
|
32
35
|
* Destroy the floatable, removing it from the DOM and cleaning up references
|
|
@@ -96,9 +99,9 @@ function createInstance(anchor, content, options, standalone) {
|
|
|
96
99
|
return floatable;
|
|
97
100
|
}
|
|
98
101
|
function getOnBeforeToggleListener(element) {
|
|
99
|
-
return on(element,
|
|
102
|
+
return on(element, "beforetoggle", (event) => {
|
|
100
103
|
const { newState, source } = event;
|
|
101
|
-
if (newState === "open" && source
|
|
104
|
+
if (newState === "open" && source != null && getAria(source, "disabled") === "true") event.preventDefault();
|
|
102
105
|
}, { passive: false });
|
|
103
106
|
}
|
|
104
107
|
function getOptions(input) {
|
|
@@ -112,8 +115,8 @@ function getPosition$1(state, override) {
|
|
|
112
115
|
if (override != null && override in AREAS) return override;
|
|
113
116
|
const { anchor, options } = state;
|
|
114
117
|
if (options.attribute == null) return options.position;
|
|
115
|
-
const attribute =
|
|
116
|
-
return attribute in AREAS ? attribute : options.position;
|
|
118
|
+
const attribute = getAttribute(anchor, options.attribute);
|
|
119
|
+
return attribute != null && attribute in AREAS ? attribute : options.position;
|
|
117
120
|
}
|
|
118
121
|
function getState(anchor, content, options) {
|
|
119
122
|
return {
|
|
@@ -130,9 +133,11 @@ function removeFloatable(content) {
|
|
|
130
133
|
function setPosition(state, override) {
|
|
131
134
|
const position = getPosition$1(state, override);
|
|
132
135
|
const area = AREAS[position];
|
|
133
|
-
state.content
|
|
134
|
-
state.content
|
|
135
|
-
|
|
136
|
+
setAttribute(state.content, ATTRIBUTE_POSITION, POSITIONS[area]);
|
|
137
|
+
setStyles(state.content, {
|
|
138
|
+
positionAnchor: state.name,
|
|
139
|
+
positionArea: area
|
|
140
|
+
});
|
|
136
141
|
}
|
|
137
142
|
const AREAS = {
|
|
138
143
|
above: "block-start",
|
|
@@ -148,15 +153,11 @@ const AREAS = {
|
|
|
148
153
|
"start-bottom": "span-start start",
|
|
149
154
|
"start-top": "span-end start"
|
|
150
155
|
};
|
|
151
|
-
const ARIA_DISABLED = "aria-disabled";
|
|
152
156
|
const ATTRIBUTE_FLOATABLE = "oui-floatable";
|
|
153
157
|
const ATTRIBUTE_POSITION = "oui-position";
|
|
154
|
-
const EVENT_BEFORE = "beforetoggle";
|
|
155
|
-
const FLOATABLE_STATE_OPEN = "open";
|
|
156
158
|
const MESSAGE = "Anchor and content must be an HTMLElement or SVGElement";
|
|
157
159
|
const POSITIONS = Object.fromEntries(Object.entries(AREAS).map(([position, area]) => [area, position]));
|
|
158
|
-
const TRUE = "true";
|
|
159
160
|
const instances = /* @__PURE__ */ new WeakMap();
|
|
160
161
|
let index = 0;
|
|
161
162
|
//#endregion
|
|
162
|
-
export { ATTRIBUTE_FLOATABLE,
|
|
163
|
+
export { ATTRIBUTE_FLOATABLE, OuiFloatable, createEmbeddedFloatable, createFloatable, getOnBeforeToggleListener, removeFloatable };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as OuiFloatablePosition, n as CreateOuiFloatableOptions, r as OuiFloatable, s as createFloatable } from "../floatable.embedded-DUR8bQBK.mjs";
|
|
2
2
|
export { type CreateOuiFloatableOptions, type OuiFloatable, type OuiFloatablePosition, createFloatable };
|
|
@@ -66,6 +66,5 @@ declare function createFloatable(anchor: HTMLElement, content: HTMLElement, opti
|
|
|
66
66
|
declare function getOnBeforeToggleListener(element: HTMLElement): RemovableEventListener;
|
|
67
67
|
declare function removeFloatable(content: HTMLElement): void;
|
|
68
68
|
declare const ATTRIBUTE_FLOATABLE = "oui-floatable";
|
|
69
|
-
declare const FLOATABLE_STATE_OPEN = "open";
|
|
70
69
|
//#endregion
|
|
71
|
-
export {
|
|
70
|
+
export { OuiFloatablePosition as a, getOnBeforeToggleListener as c, OuiFloatableOptions as i, removeFloatable as l, CreateOuiFloatableOptions as n, createEmbeddedFloatable as o, OuiFloatable as r, createFloatable as s, ATTRIBUTE_FLOATABLE as t };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { attributable } from "../internal/attributable.mjs";
|
|
2
2
|
import { on } from "@oscarpalmer/toretto/event";
|
|
3
3
|
import { isPlainObject } from "@oscarpalmer/atoms/is";
|
|
4
|
+
import { setAttribute } from "@oscarpalmer/toretto/attribute";
|
|
4
5
|
import { isHTMLOrSVGElement } from "@oscarpalmer/toretto/is";
|
|
5
6
|
import { clamp } from "@oscarpalmer/atoms/number";
|
|
6
7
|
import { findAncestor } from "@oscarpalmer/toretto/find";
|
|
@@ -20,8 +21,8 @@ var OuiFocusTrap = class {
|
|
|
20
21
|
* Should focus be maintained within the _focus trap_ when clicking outside of it?
|
|
21
22
|
*/
|
|
22
23
|
set contain(value) {
|
|
23
|
-
if (value === true) this.#state.element
|
|
24
|
-
else if (value === false) this.#state.element
|
|
24
|
+
if (value === true) setAttribute(this.#state.element, ATTRIBUTE_FOCUSTRAP_CONTAIN, "");
|
|
25
|
+
else if (value === false) setAttribute(this.#state.element, ATTRIBUTE_FOCUSTRAP_CONTAIN, void 0);
|
|
25
26
|
}
|
|
26
27
|
/**
|
|
27
28
|
* Is the _focus trap_ disabled?
|
|
@@ -46,14 +47,14 @@ var OuiFocusTrap = class {
|
|
|
46
47
|
* Should the _focus trap_ allow focus to escape when pressing _Escape_?
|
|
47
48
|
*/
|
|
48
49
|
set noescape(value) {
|
|
49
|
-
if (value === true) this.#state.element
|
|
50
|
-
else if (value === false) this.#state.element
|
|
50
|
+
if (value === true) setAttribute(this.#state.element, ATTRIBUTE_FOCUSTRAP_NOESCAPE, "");
|
|
51
|
+
else if (value === false) setAttribute(this.#state.element, ATTRIBUTE_FOCUSTRAP_NOESCAPE, void 0);
|
|
51
52
|
}
|
|
52
53
|
constructor(state) {
|
|
53
54
|
this.#state = state;
|
|
54
55
|
this.#tabIndex = state.element.tabIndex;
|
|
55
56
|
state.element.tabIndex = -1;
|
|
56
|
-
state.element
|
|
57
|
+
setAttribute(state.element, ATTRIBUTE_FOCUSTRAP, "");
|
|
57
58
|
this.contain = state.options.contain;
|
|
58
59
|
this.noescape = state.options.noescape;
|
|
59
60
|
states.set(this, state);
|
package/dist/js/index.d.mts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { g as createMovable, h as OuiMovable, t as CreateOuiDraggableOptions } from "./draggable-
|
|
1
|
+
import { d as OuiSortable, f as createSortable, g as createMovable, h as OuiMovable, t as CreateOuiDraggableOptions } from "./draggable-fIYXd8eO.mjs";
|
|
2
|
+
import { a as createResizable, n as OuiResizable, t as CreateOuiResizableOptions } from "./resizable.embedded-CXrUVPzR.mjs";
|
|
2
3
|
import { OuiDialog, getDialog } from "./dialog.mjs";
|
|
3
|
-
import {
|
|
4
|
+
import { a as OuiFloatablePosition, n as CreateOuiFloatableOptions, r as OuiFloatable, s as createFloatable } from "./floatable.embedded-DUR8bQBK.mjs";
|
|
4
5
|
import { a as OuiFocusTrapOptions, i as OuiFocusTrap, o as createFocusTrap } from "./focus-trap.embedded-DR8NpZfr.mjs";
|
|
5
6
|
import { OuiPopover, getPopover } from "./popover.mjs";
|
|
6
7
|
import { OuiSplitterElement } from "./splitter.mjs";
|
|
7
8
|
import { OuiTooltip, getTooltip, setTooltipDelay } from "./tooltip.mjs";
|
|
8
|
-
export { type CreateOuiFloatableOptions, type CreateOuiDraggableOptions as CreateOuiMovableOptions, type OuiDialog, type OuiFloatable, type OuiFloatablePosition, type OuiFocusTrap, type OuiFocusTrapOptions, type OuiMovable, type OuiPopover, OuiSplitterElement, type OuiTooltip, createFloatable, createFocusTrap, createMovable, getDialog, getPopover, getTooltip, setTooltipDelay };
|
|
9
|
+
export { type CreateOuiFloatableOptions, type CreateOuiDraggableOptions as CreateOuiMovableOptions, type CreateOuiDraggableOptions as CreateOuiSortableOptions, type CreateOuiResizableOptions, type OuiDialog, type OuiFloatable, type OuiFloatablePosition, type OuiFocusTrap, type OuiFocusTrapOptions, type OuiMovable, type OuiPopover, type OuiResizable, type OuiSortable, OuiSplitterElement, type OuiTooltip, createFloatable, createFocusTrap, createMovable, createResizable as createOuiResizable, createSortable, getDialog, getPopover, getTooltip, setTooltipDelay };
|
package/dist/js/index.mjs
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import { createFloatable } from "./floatable/floatable.embedded.mjs";
|
|
2
2
|
import { createMovable } from "./movable/movable.embedded.mjs";
|
|
3
3
|
import "./movable/movable.standalone.mjs";
|
|
4
|
+
import { createResizable } from "./resizable/resizable.embedded.mjs";
|
|
4
5
|
import { getDialog } from "./dialog.mjs";
|
|
5
|
-
import "./
|
|
6
|
+
import "./menu.mjs";
|
|
6
7
|
import "./toolbar.mjs";
|
|
7
8
|
import "./floatable/floatable.standalone.mjs";
|
|
8
9
|
import { createFocusTrap } from "./focus-trap/focus-trap.embedded.mjs";
|
|
9
10
|
import "./focus-trap/focus-trap.standalone.mjs";
|
|
10
11
|
import { getPopover } from "./popover.mjs";
|
|
12
|
+
import "./resizable/resizable.standalone.mjs";
|
|
13
|
+
import { createSortable } from "./sortable/sortable.embedded.mjs";
|
|
14
|
+
import "./sortable/sortable.standalone.mjs";
|
|
11
15
|
import { OuiSplitterElement } from "./splitter.mjs";
|
|
12
16
|
import { getTooltip, setTooltipDelay } from "./tooltip.mjs";
|
|
13
|
-
export { OuiSplitterElement, createFloatable, createFocusTrap, createMovable, getDialog, getPopover, getTooltip, setTooltipDelay };
|
|
17
|
+
export { OuiSplitterElement, createFloatable, createFocusTrap, createMovable, createResizable as createOuiResizable, createSortable, getDialog, getPopover, getTooltip, setTooltipDelay };
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { isHTMLOrSVGElement } from "@oscarpalmer/toretto/is";
|
|
2
1
|
//#region src/js/internal/attributable.ts
|
|
3
2
|
function attributable(attribute, add, remove) {
|
|
4
3
|
new MutationObserver((entries) => {
|
|
5
4
|
const { length } = entries;
|
|
6
5
|
for (let index = 0; index < length; index += 1) {
|
|
7
6
|
const entry = entries[index];
|
|
8
|
-
if (entry.type === "attributes" &&
|
|
7
|
+
if (entry.type === "attributes" && entry.target instanceof Element) if (entry.target.hasAttribute(attribute)) handleAdded(attribute, [entry.target], add);
|
|
9
8
|
else handleRemoved([entry.target], remove);
|
|
10
9
|
else if (entry.type === "childList") {
|
|
11
10
|
handleAdded(attribute, entry.addedNodes, add);
|
|
@@ -23,7 +22,7 @@ function attributable(attribute, add, remove) {
|
|
|
23
22
|
});
|
|
24
23
|
}
|
|
25
24
|
function handleAdded(attribute, nodes, add) {
|
|
26
|
-
const elements = [...nodes].filter(
|
|
25
|
+
const elements = [...nodes].filter((node) => node instanceof Element);
|
|
27
26
|
const { length } = elements;
|
|
28
27
|
for (let index = 0; index < length; index += 1) {
|
|
29
28
|
const element = elements[index];
|
|
@@ -32,7 +31,7 @@ function handleAdded(attribute, nodes, add) {
|
|
|
32
31
|
}
|
|
33
32
|
}
|
|
34
33
|
function handleRemoved(nodes, remove) {
|
|
35
|
-
const elements = [...nodes].filter(
|
|
34
|
+
const elements = [...nodes].filter((node) => node instanceof Element);
|
|
36
35
|
const { length } = elements;
|
|
37
36
|
for (let index = 0; index < length; index += 1) {
|
|
38
37
|
const element = elements[index];
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as OuiDraggableGlobals, c as addDraggable, i as OuiDraggableBound, l as getDraggableStates, n as OuiDragMovePosition, o as OuiDraggableItem, r as OuiDraggable, s as OuiDraggableState, t as CreateOuiDraggableOptions, u as removeDraggable } from "../draggable-
|
|
1
|
+
import { a as OuiDraggableGlobals, c as addDraggable, i as OuiDraggableBound, l as getDraggableStates, n as OuiDragMovePosition, o as OuiDraggableItem, r as OuiDraggable, s as OuiDraggableState, t as CreateOuiDraggableOptions, u as removeDraggable } from "../draggable-fIYXd8eO.mjs";
|
|
2
2
|
export { CreateOuiDraggableOptions, OuiDragMovePosition, OuiDraggable, OuiDraggableBound, OuiDraggableGlobals, OuiDraggableItem, OuiDraggableState, addDraggable, getDraggableStates, removeDraggable };
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { getPosition, on } from "@oscarpalmer/toretto/event";
|
|
2
|
+
import { getAttribute, setAttribute } from "@oscarpalmer/toretto/attribute";
|
|
2
3
|
import { isHTMLOrSVGElement } from "@oscarpalmer/toretto/is";
|
|
4
|
+
import { setStyle, setStyles, toggleStyles } from "@oscarpalmer/toretto/style";
|
|
3
5
|
import { clamp } from "@oscarpalmer/atoms/number";
|
|
4
6
|
import { findAncestor } from "@oscarpalmer/toretto/find";
|
|
5
|
-
import { toggleStyles } from "@oscarpalmer/toretto/style";
|
|
6
7
|
import supportsTouch from "@oscarpalmer/toretto/touch";
|
|
7
8
|
//#region src/js/internal/draggable.ts
|
|
8
9
|
var OuiDraggable = class {
|
|
@@ -30,7 +31,7 @@ var OuiDraggable = class {
|
|
|
30
31
|
};
|
|
31
32
|
setContainer(item);
|
|
32
33
|
setDirection(item);
|
|
33
|
-
|
|
34
|
+
setAttribute(element, attribute, "");
|
|
34
35
|
let states = globals.states.get(element);
|
|
35
36
|
states ??= {};
|
|
36
37
|
states[this.#name] = this.#state;
|
|
@@ -142,9 +143,11 @@ function onPointerdown(event) {
|
|
|
142
143
|
return;
|
|
143
144
|
}
|
|
144
145
|
const next = getNextPosition(item, position);
|
|
145
|
-
dragged
|
|
146
|
-
|
|
147
|
-
|
|
146
|
+
setStyles(dragged, {
|
|
147
|
+
position: "fixed",
|
|
148
|
+
inset: `${next.y}px auto auto ${next.x}px`,
|
|
149
|
+
transform: "translate3d(0, 0, 0)"
|
|
150
|
+
});
|
|
148
151
|
item.state.options.drag.onBegin?.(event, globals, item, element, handle, next);
|
|
149
152
|
item.state.styling.set();
|
|
150
153
|
styleToggler.set();
|
|
@@ -155,7 +158,7 @@ function onPointermove(event) {
|
|
|
155
158
|
const position = getPosition(event);
|
|
156
159
|
if (position == null) return;
|
|
157
160
|
const next = getNextPosition(current, position);
|
|
158
|
-
if (globals.element != null) globals.element.node
|
|
161
|
+
if (globals.element != null) setStyle(globals.element.node, "inset", `${next.y}px auto auto ${next.x}px`);
|
|
159
162
|
const detail = current.state.options.drag.onMove(event, globals, current, {
|
|
160
163
|
calculated: next,
|
|
161
164
|
original: position
|
|
@@ -192,7 +195,7 @@ function setContainer(item) {
|
|
|
192
195
|
setContainerElement(item, container);
|
|
193
196
|
return;
|
|
194
197
|
}
|
|
195
|
-
const selector = container ?? item.instance.element
|
|
198
|
+
const selector = container ?? getAttribute(item.instance.element, item.state.options.container.attribute);
|
|
196
199
|
if (typeof selector !== "string") return;
|
|
197
200
|
const element = containers.has(selector) ? item.state.element.ownerDocument.body : document.querySelector(selector) ?? void 0;
|
|
198
201
|
if (isHTMLOrSVGElement(element)) setContainerElement(item, element);
|
|
@@ -205,7 +208,7 @@ function setContainerElement(item, element) {
|
|
|
205
208
|
item.state.options.container.onInitialize?.(item);
|
|
206
209
|
}
|
|
207
210
|
function setDirection(item) {
|
|
208
|
-
const direction = item.state.element
|
|
211
|
+
const direction = getAttribute(item.state.element, item.state.options.direction.attribute);
|
|
209
212
|
if (horizontals.has(direction)) item.state.vertical = false;
|
|
210
213
|
else if (verticals.has(direction)) item.state.horizontal = false;
|
|
211
214
|
item.state.options.direction.onAfter?.(item);
|
|
@@ -261,7 +264,7 @@ on(document, "keydown", onKeydown);
|
|
|
261
264
|
on(document, "mousedown", onPointerdown);
|
|
262
265
|
on(document, "pointermove", onPointermove);
|
|
263
266
|
on(document, "pointerup", onPointerup);
|
|
264
|
-
on(document, "touchcancel", onPointerup
|
|
267
|
+
on(document, "touchcancel", onPointerup);
|
|
265
268
|
on(document, "touchstart", onPointerdown, { passive: false });
|
|
266
269
|
//#endregion
|
|
267
270
|
export { OuiDraggable, addDraggable, getDraggableStates, removeDraggable };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { AriaRole, RemovableEventListener } from "@oscarpalmer/toretto/models";
|
|
2
|
+
|
|
3
|
+
//#region src/js/internal/navigable.d.ts
|
|
4
|
+
declare class OuiNavigable {
|
|
5
|
+
active: OuiNavigableActive;
|
|
6
|
+
element: HTMLElement;
|
|
7
|
+
listeners: RemovableEventListener[];
|
|
8
|
+
options: OuiNavigableOptions;
|
|
9
|
+
orientation: OuiNavigableOrientation;
|
|
10
|
+
constructor(element: HTMLElement, options: OuiNavigableOptions);
|
|
11
|
+
destroy(): void;
|
|
12
|
+
}
|
|
13
|
+
type OuiNavigableActive = {
|
|
14
|
+
element?: HTMLElement;
|
|
15
|
+
index: number;
|
|
16
|
+
};
|
|
17
|
+
type OuiNavigableOptions = {
|
|
18
|
+
role?: AriaRole;
|
|
19
|
+
selector: string;
|
|
20
|
+
vertical: boolean;
|
|
21
|
+
onDeactivate?: (event: KeyboardEvent, navigable: OuiNavigable) => void;
|
|
22
|
+
onPreventNavigation?: (event: KeyboardEvent, navigable: OuiNavigable) => boolean;
|
|
23
|
+
onShouldActivate?: (event: KeyboardEvent, navigable: OuiNavigable) => boolean;
|
|
24
|
+
onShouldDeactivate?: (event: KeyboardEvent, navigable: OuiNavigable) => boolean | undefined;
|
|
25
|
+
};
|
|
26
|
+
type OuiNavigableOrientation = 'horizontal' | 'vertical';
|
|
27
|
+
declare function getNavigable(element: HTMLElement, options: OuiNavigableOptions): OuiNavigable;
|
|
28
|
+
declare function updateNavigableFocus(navigable: OuiNavigable, focus: boolean, items?: HTMLElement[]): void;
|
|
29
|
+
declare const NAVIGABLE_KEYS_HORIZONTAL: Set<string>;
|
|
30
|
+
declare const NAVIGABLE_KEYS_VERTICAL: Set<string>;
|
|
31
|
+
//#endregion
|
|
32
|
+
export { NAVIGABLE_KEYS_HORIZONTAL, NAVIGABLE_KEYS_VERTICAL, OuiNavigable, OuiNavigableOptions, getNavigable, updateNavigableFocus };
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { getAria, setRole } from "@oscarpalmer/toretto/aria";
|
|
2
|
+
import { on } from "@oscarpalmer/toretto/event";
|
|
3
|
+
import { isHTMLOrSVGElement } from "@oscarpalmer/toretto/is";
|
|
4
|
+
import { clamp } from "@oscarpalmer/atoms/number";
|
|
5
|
+
import { findAncestor } from "@oscarpalmer/toretto/find";
|
|
6
|
+
//#region src/js/internal/navigable.ts
|
|
7
|
+
var OuiNavigable = class {
|
|
8
|
+
active = { index: 0 };
|
|
9
|
+
element;
|
|
10
|
+
listeners;
|
|
11
|
+
options;
|
|
12
|
+
orientation;
|
|
13
|
+
constructor(element, options) {
|
|
14
|
+
this.element = element;
|
|
15
|
+
this.options = options;
|
|
16
|
+
this.listeners = [on(element, "focusin", (event) => {
|
|
17
|
+
onFocusin(this, event);
|
|
18
|
+
}), on(element, "keydown", (event) => {
|
|
19
|
+
onKeydown(this, event);
|
|
20
|
+
})];
|
|
21
|
+
this.orientation = getOrientation(element, options);
|
|
22
|
+
if (options.role != null) setRole(element, options.role);
|
|
23
|
+
}
|
|
24
|
+
destroy() {
|
|
25
|
+
const listeners = this.listeners.splice(0);
|
|
26
|
+
for (const listener of listeners) listener();
|
|
27
|
+
this.active.element = void 0;
|
|
28
|
+
this.element = void 0;
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
function getItems(container, selector) {
|
|
32
|
+
return [...container.querySelectorAll(selector)].filter(isValidItem);
|
|
33
|
+
}
|
|
34
|
+
function getNavigable(element, options) {
|
|
35
|
+
return new OuiNavigable(element, options);
|
|
36
|
+
}
|
|
37
|
+
function getOrientation(element, options) {
|
|
38
|
+
const attribute = getAria(element, "orientation");
|
|
39
|
+
return ORIENTATIONS.has(attribute) ? attribute : options.vertical ? ORIENTATION_VERTICAL : ORIENTATION_HORIZONTAL;
|
|
40
|
+
}
|
|
41
|
+
function isValidItem(element) {
|
|
42
|
+
return "disabled" in element ? element.disabled !== true : true;
|
|
43
|
+
}
|
|
44
|
+
function onFocusin(navigable, event) {
|
|
45
|
+
const item = findAncestor(event, navigable.options.selector);
|
|
46
|
+
if (!isHTMLOrSVGElement(item) || !isValidItem(item)) return;
|
|
47
|
+
const items = getItems(navigable.element, navigable.options.selector);
|
|
48
|
+
const index = items.indexOf(item);
|
|
49
|
+
if (index === -1) return;
|
|
50
|
+
navigable.active.element = item;
|
|
51
|
+
navigable.active.index = index;
|
|
52
|
+
updateNavigableFocus(navigable, false, items);
|
|
53
|
+
}
|
|
54
|
+
function onKeydown(navigable, event) {
|
|
55
|
+
const escaped = event.key === "Escape";
|
|
56
|
+
const stopPropagation = navigable.options.onShouldDeactivate?.(event, navigable);
|
|
57
|
+
if (escaped || stopPropagation != null) {
|
|
58
|
+
if (escaped || stopPropagation) event.stopPropagation();
|
|
59
|
+
navigable.options.onDeactivate?.(event, navigable);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
if (!KEYS_ALL.has(event.key)) return;
|
|
63
|
+
const mustActivate = KEYS_ACTIVATE.has(event.key);
|
|
64
|
+
const shouldActivate = navigable.options.onShouldActivate?.(event, navigable) === true;
|
|
65
|
+
if (mustActivate || shouldActivate || navigable.options.onPreventNavigation?.(event, navigable) === true) event.stopPropagation();
|
|
66
|
+
if (mustActivate || shouldActivate) return;
|
|
67
|
+
const items = getItems(navigable.element, navigable.options.selector);
|
|
68
|
+
const { length } = items;
|
|
69
|
+
if (length === 0) return;
|
|
70
|
+
let index;
|
|
71
|
+
if (KEYS_ABSOLUTE.has(event.key)) index = event.key === "Home" ? 0 : items.length - 1;
|
|
72
|
+
else {
|
|
73
|
+
const direction = NAVIGABLE_KEYS_HORIZONTAL.has(event.key) ? ORIENTATION_HORIZONTAL : ORIENTATION_VERTICAL;
|
|
74
|
+
if (navigable.orientation === direction) {
|
|
75
|
+
if (navigable.active.element instanceof HTMLSelectElement) event.preventDefault();
|
|
76
|
+
index = clamp(navigable.active.index + (KEYS_NEXT.has(event.key) ? 1 : -1), 0, length - 1, true);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (index == null || index === navigable.active.index) return;
|
|
80
|
+
navigable.active.element = items[index];
|
|
81
|
+
navigable.active.index = index;
|
|
82
|
+
updateNavigableFocus(navigable, true, items);
|
|
83
|
+
}
|
|
84
|
+
function updateNavigableFocus(navigable, focus, items) {
|
|
85
|
+
const updated = items ?? getItems(navigable.element, navigable.options.selector);
|
|
86
|
+
const { length } = updated;
|
|
87
|
+
if (length === 0) return;
|
|
88
|
+
for (let index = 0; index < length; index += 1) updated[index].tabIndex = index === navigable.active.index ? 0 : -1;
|
|
89
|
+
navigable.active.element ??= updated[navigable.active.index];
|
|
90
|
+
if (focus) navigable.active.element?.focus();
|
|
91
|
+
}
|
|
92
|
+
const KEYS_ABSOLUTE = /* @__PURE__ */ new Set(["End", "Home"]);
|
|
93
|
+
const KEYS_ACTIVATE = /* @__PURE__ */ new Set(["Enter", " "]);
|
|
94
|
+
const NAVIGABLE_KEYS_HORIZONTAL = /* @__PURE__ */ new Set(["ArrowRight", "ArrowLeft"]);
|
|
95
|
+
const NAVIGABLE_KEYS_VERTICAL = /* @__PURE__ */ new Set(["ArrowDown", "ArrowUp"]);
|
|
96
|
+
const KEYS_ALL = /* @__PURE__ */ new Set([
|
|
97
|
+
...KEYS_ABSOLUTE,
|
|
98
|
+
...KEYS_ACTIVATE,
|
|
99
|
+
...NAVIGABLE_KEYS_HORIZONTAL,
|
|
100
|
+
...NAVIGABLE_KEYS_VERTICAL
|
|
101
|
+
]);
|
|
102
|
+
const KEYS_NEXT = /* @__PURE__ */ new Set(["ArrowDown", "ArrowRight"]);
|
|
103
|
+
const ORIENTATION_HORIZONTAL = "horizontal";
|
|
104
|
+
const ORIENTATION_VERTICAL = "vertical";
|
|
105
|
+
const ORIENTATIONS = /* @__PURE__ */ new Set([ORIENTATION_HORIZONTAL, ORIENTATION_VERTICAL]);
|
|
106
|
+
//#endregion
|
|
107
|
+
export { NAVIGABLE_KEYS_HORIZONTAL, NAVIGABLE_KEYS_VERTICAL, OuiNavigable, getNavigable, updateNavigableFocus };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|