@oscarpalmer/oui 0.19.0 → 0.21.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 +0 -1
- package/dist/css/form.css +0 -1
- package/dist/css/popover.css +22 -0
- package/dist/css/reset.css +8 -8
- package/dist/css/table.css +1 -1
- package/dist/css/tooltip.css +43 -0
- package/dist/js/focus-trap/embedded.d.mts +26 -0
- package/dist/js/focus-trap/{embedded.js → embedded.mjs} +11 -9
- package/dist/js/focus-trap/standalone.d.mts +1 -0
- package/dist/js/focus-trap/{standalone.js → standalone.mjs} +5 -2
- package/dist/js/index.d.mts +4 -0
- package/dist/js/index.mjs +7 -0
- package/dist/js/internal/attributable.d.mts +4 -0
- package/dist/js/{attributable.full.js → internal/attributable.mjs} +8 -1
- package/dist/js/internal/draggable.d.mts +2 -0
- package/dist/js/internal/draggable.mjs +212 -0
- package/dist/js/internal/floatable.d.mts +26 -0
- package/dist/js/{floatable.js → internal/floatable.mjs} +73 -50
- package/dist/js/movable-BEo2LbUI.d.mts +101 -0
- package/dist/js/movable.d.mts +2 -0
- package/dist/js/movable.mjs +152 -0
- package/dist/js/popover.d.mts +20 -0
- package/dist/js/{popover.js → popover.mjs} +10 -8
- package/dist/js/sortable.d.mts +2 -0
- package/dist/js/sortable.mjs +243 -0
- package/dist/js/splitter.d.mts +25 -0
- package/dist/js/{splitter.js → splitter.mjs} +62 -60
- package/dist/js/tooltip.d.mts +4 -0
- package/dist/js/{tooltip.js → tooltip.mjs} +22 -20
- package/package.json +66 -69
- package/src/css/mixins.scss +30 -1
- package/src/css/popover.scss +6 -1
- package/src/css/reset.scss +4 -4
- package/src/css/table.scss +1 -1
- package/src/css/tooltip.scss +55 -1
- package/src/js/focus-trap/embedded.ts +4 -10
- package/src/js/focus-trap/standalone.ts +1 -1
- package/src/js/index.ts +3 -1
- package/src/js/{attributable.ts → internal/attributable.ts} +11 -1
- package/src/js/internal/draggable.ts +515 -0
- package/src/js/{floatable.ts → internal/floatable.ts} +141 -63
- package/src/js/movable.ts +260 -0
- package/src/js/popover.ts +1 -1
- package/src/js/sortable.ts +467 -0
- package/src/js/splitter.ts +3 -9
- package/src/js/tooltip.ts +11 -9
- package/dist/js/attributable.js +0 -36
- package/dist/js/floatable.full.js +0 -398
- package/dist/js/focus-trap/embedded.full.js +0 -408
- package/dist/js/focus-trap/standalone.full.js +0 -447
- package/dist/js/index.js +0 -5
- package/dist/js/oui.full.js +0 -1573
- package/dist/js/popover.full.js +0 -760
- package/dist/js/splitter.full.js +0 -769
- package/dist/js/tooltip.full.js +0 -613
- package/types/attributable.d.ts +0 -1
- package/types/floatable.d.ts +0 -24
- package/types/focus-trap/embedded.d.ts +0 -24
- package/types/focus-trap/standalone.d.ts +0 -1
- package/types/index.d.ts +0 -4
- package/types/popover.d.ts +0 -17
- package/types/splitter.d.ts +0 -23
- package/types/tooltip.d.ts +0 -2
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { on } from "@oscarpalmer/toretto/event";
|
|
2
2
|
import { findAncestor } from "@oscarpalmer/toretto/find";
|
|
3
|
+
//#region src/js/internal/floatable.ts
|
|
3
4
|
var Floatable = class {
|
|
4
5
|
active = false;
|
|
5
6
|
disabled = false;
|
|
@@ -74,44 +75,68 @@ function deactivate(floatable) {
|
|
|
74
75
|
floatable.options.anchor.insertAdjacentElement(INSERT_AFTEREND, floatable.options.content);
|
|
75
76
|
floatable.options.onAfter?.(false);
|
|
76
77
|
}
|
|
78
|
+
function getAttribute(position, anchor, top, left) {
|
|
79
|
+
switch (position) {
|
|
80
|
+
case "horizontal":
|
|
81
|
+
case "horizontal-bottom":
|
|
82
|
+
case "horizontal-top": return position.replace("horizontal", left >= anchor.right ? "right" : "left");
|
|
83
|
+
case "vertical":
|
|
84
|
+
case "vertical-end":
|
|
85
|
+
case "vertical-start": return position.replace("vertical", top >= anchor.bottom ? "bottom" : "top");
|
|
86
|
+
default: break;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function getMargin() {
|
|
90
|
+
try {
|
|
91
|
+
const fontsize = parseFloat(getComputedStyle(document.documentElement).fontSize);
|
|
92
|
+
if (Number.isNaN(fontsize)) return 5;
|
|
93
|
+
const margin = fontsize / 2;
|
|
94
|
+
return margin < 5 ? 5 : margin;
|
|
95
|
+
} catch {
|
|
96
|
+
return 5;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
77
99
|
function getState() {
|
|
78
100
|
return window._oscarpalmer_oui_floatable;
|
|
79
101
|
}
|
|
80
|
-
function getX(anchor, content, position) {
|
|
81
|
-
if (position
|
|
82
|
-
const
|
|
83
|
-
|
|
102
|
+
function getX(anchor, content, position, margin) {
|
|
103
|
+
if (position === "above" || position === "below" || position === "vertical") {
|
|
104
|
+
const center = anchor.left + anchor.width / 2;
|
|
105
|
+
const width = content.width / 2;
|
|
106
|
+
if (center + width + margin >= document.body.clientWidth) return document.body.clientWidth - content.width - margin / 2;
|
|
107
|
+
if (center - width - margin <= 0) return margin / 2;
|
|
108
|
+
return center - width;
|
|
84
109
|
}
|
|
85
|
-
if (position.
|
|
86
|
-
|
|
87
|
-
|
|
110
|
+
if (position.startsWith("end")) return anchor.right;
|
|
111
|
+
if (position.startsWith("start")) return anchor.left - content.width;
|
|
112
|
+
if (position.endsWith("end")) return anchor.right - content.width - margin <= 0 ? margin / 2 : anchor.right - content.width;
|
|
113
|
+
if (position.endsWith("start")) {
|
|
114
|
+
if (anchor.left + content.width + margin >= document.body.clientWidth) return document.body.clientWidth - content.width - margin / 2;
|
|
115
|
+
return anchor.left - margin <= 0 ? margin / 2 : anchor.left;
|
|
88
116
|
}
|
|
89
|
-
if (position.startsWith(
|
|
90
|
-
if (
|
|
91
|
-
|
|
92
|
-
if (anchor.right + content.width <= window.innerWidth) return anchor.right;
|
|
93
|
-
return anchor.left - content.width;
|
|
94
|
-
}
|
|
95
|
-
const left = anchor.left + (anchor.width - content.width) / 2;
|
|
96
|
-
return left < 0 ? 0 : left;
|
|
117
|
+
if (!position.startsWith("horizontal")) return 0;
|
|
118
|
+
if (anchor.right + content.width + margin >= document.body.clientWidth) return anchor.left - content.width;
|
|
119
|
+
return anchor.right;
|
|
97
120
|
}
|
|
98
|
-
function getY(anchor, content, position, preferAbove) {
|
|
99
|
-
if (position
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
if (position.endsWith(POSITION_TOP)) {
|
|
106
|
-
const top = anchor.top;
|
|
107
|
-
return top + content.height > window.innerHeight ? window.innerHeight - content.height : top;
|
|
121
|
+
function getY(anchor, content, position, margin, preferAbove) {
|
|
122
|
+
if (position === "end" || position === "start" || position === "horizontal") {
|
|
123
|
+
const center = anchor.top + anchor.height / 2;
|
|
124
|
+
const height = content.height / 2;
|
|
125
|
+
if (center + height + margin >= document.body.clientHeight) return document.body.clientHeight - content.height - margin / 2;
|
|
126
|
+
if (center - height - margin <= 0) return margin / 2;
|
|
127
|
+
return center - height;
|
|
108
128
|
}
|
|
109
|
-
if (position.startsWith(
|
|
110
|
-
|
|
111
|
-
|
|
129
|
+
if (position.startsWith("above")) return anchor.top - content.height;
|
|
130
|
+
if (position.startsWith("below")) return anchor.bottom;
|
|
131
|
+
if (position.endsWith("bottom")) return anchor.bottom - content.height - margin <= 0 ? margin / 2 : anchor.bottom - content.height;
|
|
132
|
+
if (position.endsWith("top")) return anchor.top + content.height + margin >= document.body.clientHeight ? document.body.clientHeight - content.height - margin : anchor.top;
|
|
133
|
+
if (!position.startsWith("vertical")) return 0;
|
|
134
|
+
if (preferAbove) {
|
|
135
|
+
if (anchor.top - content.height - margin <= 0 && anchor.bottom + content.height + margin <= document.body.clientHeight) return anchor.bottom;
|
|
112
136
|
return anchor.top - content.height;
|
|
113
137
|
}
|
|
114
|
-
|
|
138
|
+
if (anchor.bottom + content.height + margin >= document.body.clientHeight) return anchor.top - content.height;
|
|
139
|
+
return anchor.bottom;
|
|
115
140
|
}
|
|
116
141
|
function initialize(floatable) {
|
|
117
142
|
const { anchor, content, interactive } = floatable.options;
|
|
@@ -130,7 +155,7 @@ function isDisabled(element) {
|
|
|
130
155
|
return element.disabled || element.readOnly || element.getAttribute("aria-disabled") === "true";
|
|
131
156
|
}
|
|
132
157
|
function onClick(event) {
|
|
133
|
-
const related = findAncestor(event
|
|
158
|
+
const related = findAncestor(event, SELECTOR_ALL);
|
|
134
159
|
if (!(related instanceof HTMLElement)) closeAll();
|
|
135
160
|
else if (related.hasAttribute(ATTRIBUTE_CONTENT)) closeAbove(related);
|
|
136
161
|
else if (!isDisabled(related)) toggle(related);
|
|
@@ -140,12 +165,17 @@ function onKeyDown(event) {
|
|
|
140
165
|
const state = getState();
|
|
141
166
|
if (state == null || state.active.size === 0) return;
|
|
142
167
|
closeNonInteractive(state);
|
|
143
|
-
const related = findAncestor(event
|
|
168
|
+
const related = findAncestor(event, SELECTOR_CONTENT);
|
|
144
169
|
if (!(related instanceof HTMLElement)) return;
|
|
145
170
|
closeAbove(related);
|
|
146
171
|
const floatable = state.mapped.get(related);
|
|
147
172
|
if (floatable != null) floatable.toggle(false);
|
|
148
173
|
}
|
|
174
|
+
function setAttribute(position, anchor, floater, top, left) {
|
|
175
|
+
let actual;
|
|
176
|
+
if (/^(horizontal|vertical)/.test(position)) actual = getAttribute(position, anchor, top, left);
|
|
177
|
+
floater.setAttribute("position", actual ?? position);
|
|
178
|
+
}
|
|
149
179
|
function stop(floatable) {
|
|
150
180
|
if (floatable.frame != null) cancelAnimationFrame(floatable.frame);
|
|
151
181
|
floatable.frame = void 0;
|
|
@@ -165,6 +195,7 @@ function toggle(anchor) {
|
|
|
165
195
|
function updatePosition(floatable) {
|
|
166
196
|
let position = floatable.options.anchor.getAttribute(floatable.options.positionAttribute)?.trim() ?? floatable.options.defaultPosition;
|
|
167
197
|
if (!POSITIONS.has(position)) position = floatable.options.defaultPosition;
|
|
198
|
+
const margin = getMargin();
|
|
168
199
|
let previousAnchor;
|
|
169
200
|
let previousContent;
|
|
170
201
|
let calculated = false;
|
|
@@ -185,8 +216,9 @@ function updatePosition(floatable) {
|
|
|
185
216
|
function update(anchor, content) {
|
|
186
217
|
previousAnchor = anchor;
|
|
187
218
|
previousContent = content;
|
|
188
|
-
const left = getX(anchor, content, position);
|
|
189
|
-
const top = getY(anchor, content, position, floatable.options.preferAbove);
|
|
219
|
+
const left = getX(anchor, content, position, margin);
|
|
220
|
+
const top = getY(anchor, content, position, margin, floatable.options.preferAbove);
|
|
221
|
+
setAttribute(position, anchor, floatable.options.content, top, left);
|
|
190
222
|
if (top + content.height > window.innerHeight) floatable.options.content.style.height = `${window.innerHeight - top}px`;
|
|
191
223
|
else floatable.options.content.style.height = "";
|
|
192
224
|
if (left + content.width > window.innerWidth) floatable.options.content.style.width = `${window.innerWidth - left}px`;
|
|
@@ -200,20 +232,10 @@ function updatePosition(floatable) {
|
|
|
200
232
|
}
|
|
201
233
|
floatable.frame = requestAnimationFrame(run);
|
|
202
234
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
var POSITION_BELOW = "below";
|
|
208
|
-
var POSITION_BOTTOM = "bottom";
|
|
209
|
-
var POSITION_END = "end";
|
|
210
|
-
var POSITION_HORIZONTAL = "horizontal";
|
|
211
|
-
var POSITION_START = "start";
|
|
212
|
-
var POSITION_SUFFIX_END = "-end";
|
|
213
|
-
var POSITION_SUFFIX_START = "-start";
|
|
214
|
-
var POSITION_TOP = "top";
|
|
215
|
-
var POSITION_VERTICAL = "vertical";
|
|
216
|
-
var POSITIONS = new Set([
|
|
235
|
+
const ATTRIBUTE_ANCHOR = "oui-floatable-anchor";
|
|
236
|
+
const ATTRIBUTE_CONTENT = "oui-floatable-content";
|
|
237
|
+
const INSERT_AFTEREND = "afterend";
|
|
238
|
+
const POSITIONS = new Set([
|
|
217
239
|
"above",
|
|
218
240
|
"above-end",
|
|
219
241
|
"above-start",
|
|
@@ -233,14 +255,14 @@ var POSITIONS = new Set([
|
|
|
233
255
|
"vertical-end",
|
|
234
256
|
"vertical-start"
|
|
235
257
|
]);
|
|
236
|
-
|
|
258
|
+
const PROPERTIES = [
|
|
237
259
|
"bottom",
|
|
238
260
|
"left",
|
|
239
261
|
"right",
|
|
240
262
|
"top"
|
|
241
263
|
];
|
|
242
|
-
|
|
243
|
-
|
|
264
|
+
const SELECTOR_ALL = `[${ATTRIBUTE_ANCHOR}], [${ATTRIBUTE_CONTENT}]`;
|
|
265
|
+
const SELECTOR_CONTENT = `[${ATTRIBUTE_CONTENT}]`;
|
|
244
266
|
if (window._oscarpalmer_oui_floatable == null) {
|
|
245
267
|
Object.defineProperty(window, "_oscarpalmer_oui_floatable", {
|
|
246
268
|
enumerable: false,
|
|
@@ -258,4 +280,5 @@ if (window._oscarpalmer_oui_floatable == null) {
|
|
|
258
280
|
onClick(event);
|
|
259
281
|
});
|
|
260
282
|
}
|
|
283
|
+
//#endregion
|
|
261
284
|
export { Floatable, deactivate };
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { EventPosition, PlainObject } from "@oscarpalmer/atoms/models";
|
|
2
|
+
|
|
3
|
+
//#region src/js/sortable.d.ts
|
|
4
|
+
declare class Sortable extends Draggable {
|
|
5
|
+
connections: string | null;
|
|
6
|
+
origin: HTMLElement | undefined;
|
|
7
|
+
get dragged(): HTMLElement;
|
|
8
|
+
constructor(element: HTMLElement);
|
|
9
|
+
}
|
|
10
|
+
//#endregion
|
|
11
|
+
//#region src/js/internal/draggable.d.ts
|
|
12
|
+
declare abstract class Draggable {
|
|
13
|
+
prefix: string;
|
|
14
|
+
element: HTMLElement;
|
|
15
|
+
options: DraggableOptions;
|
|
16
|
+
container: HTMLElement | undefined;
|
|
17
|
+
hasHandles: boolean | undefined;
|
|
18
|
+
horizontal: boolean;
|
|
19
|
+
vertical: boolean;
|
|
20
|
+
abstract readonly dragged: HTMLElement;
|
|
21
|
+
abstract origin: HTMLElement | undefined;
|
|
22
|
+
constructor(prefix: string, element: HTMLElement, options: DraggableOptions);
|
|
23
|
+
destroy(): void;
|
|
24
|
+
}
|
|
25
|
+
type DragBegin = (event: MouseEvent | TouchEvent, state: DraggableState, draggable: Draggable, element: HTMLElement, handle: HTMLElement, position: EventPosition) => void;
|
|
26
|
+
type DragCancel = (state: DraggableState, draggable: Draggable) => void;
|
|
27
|
+
type DragEnd = (event: MouseEvent | TouchEvent, state: DraggableState, draggable: Draggable, reset: () => void) => void;
|
|
28
|
+
type DragMove = (event: MouseEvent | TouchEvent, state: DraggableState, draggable: Draggable, position: DragMovePosition) => PlainObject | undefined;
|
|
29
|
+
type DragMovePosition = {
|
|
30
|
+
calculated: EventPosition;
|
|
31
|
+
original: EventPosition;
|
|
32
|
+
};
|
|
33
|
+
type DraggableBound<Property extends keyof DraggableInstances = keyof DraggableInstances, Instance extends DraggableInstances[Property] = DraggableInstances[Property]> = {
|
|
34
|
+
constructor: new (element: HTMLElement) => Instance;
|
|
35
|
+
property: Property;
|
|
36
|
+
};
|
|
37
|
+
type DraggableInstances = {
|
|
38
|
+
movable?: Movable;
|
|
39
|
+
sortable?: Sortable;
|
|
40
|
+
};
|
|
41
|
+
type DraggableOptions = {
|
|
42
|
+
container: DraggableOptionsContainer;
|
|
43
|
+
direction: DraggableOptionsDirection;
|
|
44
|
+
drag: DraggableOptionsDrag;
|
|
45
|
+
position: DraggableOptionsPosition;
|
|
46
|
+
};
|
|
47
|
+
type DraggableOptionsContainer = {
|
|
48
|
+
attribute: string;
|
|
49
|
+
map: Map<HTMLElement, Set<Draggable>>;
|
|
50
|
+
onDestroy?: DraggableOptionsContainerOnDestroy;
|
|
51
|
+
onInitialize?: DraggableOptionsContainerOnInitialize;
|
|
52
|
+
};
|
|
53
|
+
type DraggableOptionsContainerOnDestroy = (draggable: Draggable, container: HTMLElement, empty: boolean) => void;
|
|
54
|
+
type DraggableOptionsContainerOnInitialize = (draggable: Draggable) => void;
|
|
55
|
+
type DraggableOptionsDirection = {
|
|
56
|
+
attribute: string;
|
|
57
|
+
onAfter?: DraggableOptionsDirectionOnAfter;
|
|
58
|
+
};
|
|
59
|
+
type DraggableOptionsDirectionOnAfter = (draggable: Draggable) => void;
|
|
60
|
+
type DraggableOptionsDrag = {
|
|
61
|
+
onBegin: DragBegin;
|
|
62
|
+
onCancel: DragCancel;
|
|
63
|
+
onEnd: DragEnd;
|
|
64
|
+
onMove: DragMove;
|
|
65
|
+
};
|
|
66
|
+
type DraggableOptionsPosition = {
|
|
67
|
+
getOffset: DraggableOptionsPositionGetOffset;
|
|
68
|
+
getOriginal: DraggableOptionsPositionGetOriginal;
|
|
69
|
+
};
|
|
70
|
+
type DraggableOptionsPositionGetOffset = (state: DraggableState, draggable: Draggable, element: HTMLElement, position: EventPosition) => EventPosition;
|
|
71
|
+
type DraggableOptionsPositionGetOriginal = (state: DraggableState, draggable: Draggable, position: EventPosition) => EventPosition;
|
|
72
|
+
type DraggableState = {
|
|
73
|
+
container: DOMRect | undefined;
|
|
74
|
+
element: DraggableStateElement | undefined;
|
|
75
|
+
instances: WeakMap<HTMLElement, DraggableInstances>;
|
|
76
|
+
offset: EventPosition | undefined;
|
|
77
|
+
original: EventPosition | undefined;
|
|
78
|
+
};
|
|
79
|
+
type DraggableStateElement = {
|
|
80
|
+
node: HTMLElement;
|
|
81
|
+
rectangle: DOMRect;
|
|
82
|
+
};
|
|
83
|
+
declare function addDraggable<Property extends keyof DraggableInstances, Instance extends DraggableInstances[Property]>(this: DraggableBound<Property, Instance>, element: HTMLElement): void;
|
|
84
|
+
declare function removeDraggable<Property extends keyof DraggableInstances, Instance extends DraggableInstances[Property]>(this: {
|
|
85
|
+
constructor: new (element: HTMLElement) => Instance;
|
|
86
|
+
property: Property;
|
|
87
|
+
}, element: HTMLElement): void;
|
|
88
|
+
//#endregion
|
|
89
|
+
//#region src/js/movable.d.ts
|
|
90
|
+
declare class Movable extends Draggable {
|
|
91
|
+
inset: string;
|
|
92
|
+
moved: boolean;
|
|
93
|
+
offset: Partial<EventPosition> | undefined;
|
|
94
|
+
position: string;
|
|
95
|
+
get dragged(): HTMLElement;
|
|
96
|
+
get origin(): HTMLElement | undefined;
|
|
97
|
+
constructor(element: HTMLElement);
|
|
98
|
+
destroy(): void;
|
|
99
|
+
}
|
|
100
|
+
//#endregion
|
|
101
|
+
export { DraggableState as a, Sortable as c, DraggableBound as i, DragMovePosition as n, addDraggable as o, Draggable as r, removeDraggable as s, Movable as t };
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { attributable } from "./internal/attributable.mjs";
|
|
2
|
+
import { Draggable, addDraggable, removeDraggable } from "./internal/draggable.mjs";
|
|
3
|
+
import { getPosition, on } from "@oscarpalmer/toretto/event";
|
|
4
|
+
//#region src/js/movable.ts
|
|
5
|
+
var Movable = class extends Draggable {
|
|
6
|
+
inset;
|
|
7
|
+
moved = false;
|
|
8
|
+
offset;
|
|
9
|
+
position;
|
|
10
|
+
get dragged() {
|
|
11
|
+
return this.element;
|
|
12
|
+
}
|
|
13
|
+
get origin() {
|
|
14
|
+
return this.element;
|
|
15
|
+
}
|
|
16
|
+
constructor(element) {
|
|
17
|
+
super("move", element, {
|
|
18
|
+
container: {
|
|
19
|
+
attribute: ATTRIBUTE_CONTAINER,
|
|
20
|
+
map: CONTAINERS,
|
|
21
|
+
onDestroy: destroyContainer,
|
|
22
|
+
onInitialize: initializeContainer
|
|
23
|
+
},
|
|
24
|
+
direction: {
|
|
25
|
+
attribute: ATTRIBUTE_DIRECTION,
|
|
26
|
+
onAfter: afterDirection
|
|
27
|
+
},
|
|
28
|
+
drag: {
|
|
29
|
+
onBegin,
|
|
30
|
+
onCancel,
|
|
31
|
+
onEnd,
|
|
32
|
+
onMove
|
|
33
|
+
},
|
|
34
|
+
position: {
|
|
35
|
+
getOffset: getOffsetPosition,
|
|
36
|
+
getOriginal: getOriginalPosition
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
this.hasHandles = element.querySelector(SELECTOR_HANDLE) != null;
|
|
40
|
+
this.inset = element.style.inset;
|
|
41
|
+
this.position = element.style.position;
|
|
42
|
+
}
|
|
43
|
+
destroy() {
|
|
44
|
+
super.destroy();
|
|
45
|
+
MOVED.delete(this);
|
|
46
|
+
this.element.style.inset = this.inset;
|
|
47
|
+
this.element.style.position = this.position;
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
function afterDirection(draggable) {
|
|
51
|
+
const container = draggable.container?.getBoundingClientRect();
|
|
52
|
+
if (container != null) setOffset(draggable, container);
|
|
53
|
+
}
|
|
54
|
+
function destroyContainer(_, container, empty) {
|
|
55
|
+
if (empty) resizer.unobserve(container);
|
|
56
|
+
}
|
|
57
|
+
function getOffsetPosition(state, _, __, position) {
|
|
58
|
+
return {
|
|
59
|
+
x: position.x - (state.element?.rectangle.left ?? 0),
|
|
60
|
+
y: position.y - (state.element?.rectangle.top ?? 0)
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function getOriginalPosition(state) {
|
|
64
|
+
return {
|
|
65
|
+
x: state.element?.rectangle.left ?? 0,
|
|
66
|
+
y: state.element?.rectangle.top ?? 0
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
function initializeContainer(draggable) {
|
|
70
|
+
resizer.observe(draggable.container);
|
|
71
|
+
}
|
|
72
|
+
function onBegin() {}
|
|
73
|
+
function onCancel(state, draggable) {
|
|
74
|
+
const { element, inset, moved, position } = draggable;
|
|
75
|
+
const { x, y } = state.original ?? {
|
|
76
|
+
x: 0,
|
|
77
|
+
y: 0
|
|
78
|
+
};
|
|
79
|
+
if (moved) element.style.inset = `${y}px auto auto ${x}px`;
|
|
80
|
+
else {
|
|
81
|
+
element.style.position = position;
|
|
82
|
+
element.style.inset = inset;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
function onEnd(event, state, draggable, reset) {
|
|
86
|
+
const movable = draggable;
|
|
87
|
+
if (!movable.moved) {
|
|
88
|
+
movable.moved = true;
|
|
89
|
+
if (movable.container != null) MOVED.add(movable);
|
|
90
|
+
}
|
|
91
|
+
const container = movable.container?.getBoundingClientRect();
|
|
92
|
+
if (container != null) setOffset(movable, container);
|
|
93
|
+
const end = new CustomEvent(EVENT_END, {
|
|
94
|
+
detail: {
|
|
95
|
+
from: { ...state.original },
|
|
96
|
+
to: getPosition(event)
|
|
97
|
+
},
|
|
98
|
+
cancelable: true
|
|
99
|
+
});
|
|
100
|
+
movable.element.dispatchEvent(end);
|
|
101
|
+
setTimeout(() => {
|
|
102
|
+
if (end.defaultPrevented) onCancel(state, draggable);
|
|
103
|
+
reset();
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
function onMove(_, state, __, position) {
|
|
107
|
+
return {
|
|
108
|
+
from: { ...state.original },
|
|
109
|
+
to: { ...position.calculated }
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
function onResize(entries) {
|
|
113
|
+
const { length } = entries;
|
|
114
|
+
for (let index = 0; index < length; index += 1) {
|
|
115
|
+
const entry = entries[index];
|
|
116
|
+
const set = CONTAINERS.get(entry.target);
|
|
117
|
+
if (set == null) continue;
|
|
118
|
+
for (const movable of set) reposition(movable);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
function onScroll() {
|
|
122
|
+
for (const moved of MOVED) reposition(moved);
|
|
123
|
+
}
|
|
124
|
+
function reposition(movable) {
|
|
125
|
+
if (!movable.moved || movable.container == null) return;
|
|
126
|
+
const container = movable.container.getBoundingClientRect();
|
|
127
|
+
const x = container.left + (movable.offset?.x ?? 0);
|
|
128
|
+
const y = container.top + (movable.offset?.y ?? 0);
|
|
129
|
+
movable.element.style.inset = `${y}px auto auto ${x}px`;
|
|
130
|
+
}
|
|
131
|
+
function setOffset(movable, container) {
|
|
132
|
+
movable.offset = {};
|
|
133
|
+
const element = movable.element.getBoundingClientRect();
|
|
134
|
+
movable.offset.y = element.top - container.top;
|
|
135
|
+
movable.offset.x = element.left - container.left;
|
|
136
|
+
}
|
|
137
|
+
const ATTRIBUTE = "oui-movable";
|
|
138
|
+
const ATTRIBUTE_CONTAINER = `${ATTRIBUTE}-container`;
|
|
139
|
+
const ATTRIBUTE_DIRECTION = `${ATTRIBUTE}-direction`;
|
|
140
|
+
const CONTAINERS = /* @__PURE__ */ new Map();
|
|
141
|
+
const EVENT_END = "move:end";
|
|
142
|
+
const MOVED = /* @__PURE__ */ new Set();
|
|
143
|
+
const SELECTOR_HANDLE = `[${ATTRIBUTE}-handle]`;
|
|
144
|
+
const bound = {
|
|
145
|
+
constructor: Movable,
|
|
146
|
+
property: "movable"
|
|
147
|
+
};
|
|
148
|
+
const resizer = new ResizeObserver(onResize);
|
|
149
|
+
attributable(ATTRIBUTE, addDraggable.bind(bound), removeDraggable.bind(bound));
|
|
150
|
+
on(document, "scroll", onScroll);
|
|
151
|
+
//#endregion
|
|
152
|
+
export { Movable };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
//#region src/js/popover.d.ts
|
|
2
|
+
declare global {
|
|
3
|
+
interface HTMLElementTagNameMap {
|
|
4
|
+
'oui-popover': OuiPopoverElement;
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
declare class OuiPopoverElement extends HTMLElement {
|
|
8
|
+
#private;
|
|
9
|
+
constructor();
|
|
10
|
+
close(): void;
|
|
11
|
+
connectedCallback(): void;
|
|
12
|
+
disconnectedCallback(): void;
|
|
13
|
+
hidePopover(): void;
|
|
14
|
+
open(): void;
|
|
15
|
+
showPopover(): void;
|
|
16
|
+
toggle(): void;
|
|
17
|
+
togglePopover(options?: boolean): boolean;
|
|
18
|
+
}
|
|
19
|
+
//#endregion
|
|
20
|
+
export { OuiPopoverElement };
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { createFocusTrap } from "./focus-trap/embedded.mjs";
|
|
2
|
+
import { Floatable } from "./internal/floatable.mjs";
|
|
3
3
|
import { getFocusable } from "@oscarpalmer/toretto/focusable";
|
|
4
4
|
import { isNullableOrWhitespace } from "@oscarpalmer/atoms/is";
|
|
5
|
-
|
|
5
|
+
//#region src/js/popover.ts
|
|
6
|
+
let index = 0;
|
|
6
7
|
var OuiPopoverElement = class extends HTMLElement {
|
|
7
8
|
#floatable;
|
|
8
9
|
#focusTrap;
|
|
@@ -78,10 +79,11 @@ function focus(content) {
|
|
|
78
79
|
target.focus();
|
|
79
80
|
});
|
|
80
81
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
82
|
+
const ATTRIBUTE_ID_PREFIX = "oui_popover_content_";
|
|
83
|
+
const POPOVERS = /* @__PURE__ */ new Map();
|
|
84
|
+
const SELECTOR = "oui-popover";
|
|
85
|
+
const SELECTOR_CONTENT = `:scope > [${SELECTOR}-content]`;
|
|
86
|
+
const SELECTOR_TOGGLE = `:scope > [${SELECTOR}-toggle]`;
|
|
86
87
|
customElements.define(SELECTOR, OuiPopoverElement);
|
|
88
|
+
//#endregion
|
|
87
89
|
export { OuiPopoverElement };
|