@oscarpalmer/oui 0.16.0 → 0.18.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 +3 -3
- package/dist/css/content.css +9 -11
- package/dist/css/form.css +36 -22
- package/dist/css/message.css +4 -0
- package/dist/css/popover.css +3 -0
- package/dist/css/reset.css +176 -56
- package/dist/css/splitter.css +3 -3
- package/dist/css/tooltip.css +8 -0
- package/dist/js/attributable.full.js +48 -0
- package/dist/js/attributable.js +30 -45
- package/dist/js/floatable.full.js +413 -0
- package/dist/js/floatable.js +259 -132
- package/dist/js/focus-trap/embedded.full.js +351 -0
- package/dist/js/focus-trap/embedded.js +131 -131
- package/dist/js/focus-trap/standalone.full.js +402 -0
- package/dist/js/focus-trap/standalone.js +4 -4
- package/dist/js/index.js +4 -5
- package/dist/js/oui.full.js +1596 -0
- package/dist/js/popover.full.js +822 -0
- package/dist/js/popover.js +83 -156
- package/dist/js/splitter.full.js +605 -0
- package/dist/js/splitter.js +279 -200
- package/dist/js/tooltip.full.js +679 -0
- package/dist/js/tooltip.js +159 -144
- package/package.json +31 -59
- package/src/css/content.scss +1 -2
- package/src/css/form.scss +12 -4
- package/src/css/message.scss +3 -0
- package/src/css/mixins.scss +7 -0
- package/src/css/popover.scss +4 -0
- package/src/css/reset.scss +180 -54
- package/src/css/splitter.scss +3 -3
- package/src/css/tooltip.scss +8 -0
- package/src/js/floatable.ts +458 -124
- package/src/js/focus-trap/embedded.ts +149 -64
- package/src/js/focus-trap/standalone.ts +4 -4
- package/src/js/index.ts +1 -0
- package/src/js/popover.ts +51 -114
- package/src/js/splitter.ts +346 -109
- package/src/js/tooltip.ts +157 -63
- package/types/floatable.d.ts +19 -7
- package/types/focus-trap/embedded.d.ts +18 -5
- package/types/index.d.ts +1 -0
- package/types/popover.d.ts +2 -0
- package/types/splitter.d.ts +13 -1
- package/types/tooltip.d.ts +2 -1
- package/dist/js/attributable.cjs +0 -51
- package/dist/js/floatable.cjs +0 -134
- package/dist/js/focus-trap/embedded.cjs +0 -150
- package/dist/js/focus-trap/standalone.cjs +0 -8
- package/dist/js/index.cjs +0 -6
- package/dist/js/popover.cjs +0 -160
- package/dist/js/splitter.cjs +0 -211
- package/dist/js/tooltip.cjs +0 -160
- package/types/attributable.d.cts +0 -5
- package/types/floatable.d.cts +0 -16
- package/types/focus-trap/embedded.d.cts +0 -15
- package/types/focus-trap/standalone.d.cts +0 -3
- package/types/index.d.cts +0 -14
- package/types/popover.d.cts +0 -14
- package/types/splitter.d.cts +0 -10
- package/types/tooltip.d.cts +0 -3
package/dist/js/floatable.js
CHANGED
|
@@ -1,134 +1,261 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
function
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
1
|
+
import { on } from "@oscarpalmer/toretto/event";
|
|
2
|
+
import { findAncestor } from "@oscarpalmer/toretto/find";
|
|
3
|
+
var Floatable = class {
|
|
4
|
+
active = false;
|
|
5
|
+
disabled = false;
|
|
6
|
+
frame;
|
|
7
|
+
ignoreFocus = false;
|
|
8
|
+
constructor(options) {
|
|
9
|
+
this.options = options;
|
|
10
|
+
initialize(this);
|
|
11
|
+
}
|
|
12
|
+
destroy() {
|
|
13
|
+
stop(this);
|
|
14
|
+
const state = getState();
|
|
15
|
+
state?.active.delete(this);
|
|
16
|
+
state?.mapped.delete(this.options.anchor);
|
|
17
|
+
state?.mapped.delete(this.options.content);
|
|
18
|
+
this.options.anchor = void 0;
|
|
19
|
+
this.options.content = void 0;
|
|
20
|
+
}
|
|
21
|
+
disable() {
|
|
22
|
+
if (this.disabled) return;
|
|
23
|
+
this.disabled = true;
|
|
24
|
+
stop(this);
|
|
25
|
+
getState()?.active.delete(this);
|
|
26
|
+
}
|
|
27
|
+
enable() {
|
|
28
|
+
if (!this.disabled) return;
|
|
29
|
+
this.disabled = false;
|
|
30
|
+
initialize(this);
|
|
31
|
+
}
|
|
32
|
+
toggle(active, ignoreFocus) {
|
|
33
|
+
if (this.disabled || this.active === active) return;
|
|
34
|
+
const state = getState();
|
|
35
|
+
if (state == null) return;
|
|
36
|
+
this.ignoreFocus = !active && (ignoreFocus ?? false);
|
|
37
|
+
stop(this);
|
|
38
|
+
if (active) state.active.add(this);
|
|
39
|
+
else state.active.delete(this);
|
|
40
|
+
if (this.options.interactive) if (active) state.order.push(this);
|
|
41
|
+
else {
|
|
42
|
+
const index = state.order.indexOf(this);
|
|
43
|
+
if (index > -1) state.order.splice(index, 1);
|
|
44
|
+
}
|
|
45
|
+
if (active) activate(this);
|
|
46
|
+
else deactivate(this);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
function activate(floatable) {
|
|
50
|
+
floatable.active = true;
|
|
51
|
+
document.body.append(floatable.options.content);
|
|
52
|
+
floatable.options.content.hidden = false;
|
|
53
|
+
updatePosition(floatable);
|
|
54
|
+
}
|
|
55
|
+
function closeAbove(element) {
|
|
56
|
+
const state = getState();
|
|
57
|
+
if (state == null) return;
|
|
58
|
+
const index = state.order.findIndex((floatable) => floatable.options.anchor === element || floatable.options.content === element);
|
|
59
|
+
if (index === -1 || index === state.order.length - 1) return;
|
|
60
|
+
while (index < state.order.length - 1) state.order.pop()?.toggle(false, true);
|
|
61
|
+
}
|
|
62
|
+
function closeAll() {
|
|
63
|
+
const state = getState();
|
|
64
|
+
const floatables = [...state?.active ?? []];
|
|
65
|
+
state?.active.clear();
|
|
66
|
+
for (const floatable of floatables) floatable.toggle(false, true);
|
|
67
|
+
}
|
|
68
|
+
function closeNonInteractive(state) {
|
|
69
|
+
for (const floatable of state.active) if (!floatable.options.interactive) floatable.toggle(false);
|
|
70
|
+
}
|
|
71
|
+
function deactivate(floatable) {
|
|
72
|
+
floatable.active = false;
|
|
73
|
+
floatable.options.content.hidden = true;
|
|
74
|
+
floatable.options.anchor.insertAdjacentElement(INSERT_AFTEREND, floatable.options.content);
|
|
75
|
+
floatable.options.onAfter?.(false);
|
|
76
|
+
}
|
|
77
|
+
function getState() {
|
|
78
|
+
return window._oscarpalmer_oui_floatable;
|
|
79
|
+
}
|
|
80
|
+
function getX(anchor, content, position) {
|
|
81
|
+
if (position.endsWith(POSITION_SUFFIX_END)) {
|
|
82
|
+
const end = anchor.right - content.width;
|
|
83
|
+
return end < 0 ? 0 : end;
|
|
84
|
+
}
|
|
85
|
+
if (position.endsWith(POSITION_SUFFIX_START)) {
|
|
86
|
+
const start = anchor.left;
|
|
87
|
+
return start + content.width > window.innerWidth ? window.innerWidth - content.width : start;
|
|
88
|
+
}
|
|
89
|
+
if (position.startsWith(POSITION_END)) return anchor.right;
|
|
90
|
+
if (position.startsWith(POSITION_START)) return anchor.left - content.width;
|
|
91
|
+
if (position.startsWith(POSITION_HORIZONTAL)) {
|
|
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;
|
|
97
|
+
}
|
|
98
|
+
function getY(anchor, content, position, preferAbove) {
|
|
99
|
+
if (position.startsWith(POSITION_ABOVE)) return anchor.top - content.height;
|
|
100
|
+
if (position.startsWith(POSITION_BELOW)) return anchor.bottom;
|
|
101
|
+
if (position.endsWith(POSITION_BOTTOM)) {
|
|
102
|
+
const bottom = anchor.bottom - content.height;
|
|
103
|
+
return bottom < 0 ? 0 : bottom;
|
|
104
|
+
}
|
|
105
|
+
if (position.endsWith(POSITION_TOP)) {
|
|
106
|
+
const top = anchor.top;
|
|
107
|
+
return top + content.height > window.innerHeight ? window.innerHeight - content.height : top;
|
|
108
|
+
}
|
|
109
|
+
if (position.startsWith(POSITION_VERTICAL)) {
|
|
110
|
+
if (preferAbove && anchor.top - content.height >= 0) return anchor.top - content.height;
|
|
111
|
+
if (anchor.bottom + content.height <= document.body.clientHeight) return anchor.bottom;
|
|
112
|
+
return anchor.top - content.height;
|
|
113
|
+
}
|
|
114
|
+
return anchor.top + (anchor.height - content.height) / 2;
|
|
115
|
+
}
|
|
116
|
+
function initialize(floatable) {
|
|
117
|
+
const { anchor, content, interactive } = floatable.options;
|
|
118
|
+
if (interactive) {
|
|
119
|
+
anchor.setAttribute(ATTRIBUTE_ANCHOR, "");
|
|
120
|
+
content.setAttribute(ATTRIBUTE_CONTENT, "");
|
|
121
|
+
}
|
|
122
|
+
content.style.position = "fixed";
|
|
123
|
+
content.style.inset = "0 auto auto 0";
|
|
124
|
+
content.style.zIndex = "10";
|
|
125
|
+
const state = getState();
|
|
126
|
+
state?.mapped.set(anchor, floatable);
|
|
127
|
+
state?.mapped.set(content, floatable);
|
|
128
|
+
}
|
|
129
|
+
function isDisabled(element) {
|
|
130
|
+
return element.disabled || element.readOnly || element.getAttribute("aria-disabled") === "true";
|
|
131
|
+
}
|
|
132
|
+
function onClick(event) {
|
|
133
|
+
const related = findAncestor(event.target, SELECTOR_ALL);
|
|
134
|
+
if (!(related instanceof HTMLElement)) closeAll();
|
|
135
|
+
else if (related.hasAttribute(ATTRIBUTE_CONTENT)) closeAbove(related);
|
|
136
|
+
else if (!isDisabled(related)) toggle(related);
|
|
137
|
+
}
|
|
138
|
+
function onKeyDown(event) {
|
|
139
|
+
if (event.key !== "Escape") return;
|
|
140
|
+
const state = getState();
|
|
141
|
+
if (state == null || state.active.size === 0) return;
|
|
142
|
+
closeNonInteractive(state);
|
|
143
|
+
const related = findAncestor(event.target, SELECTOR_CONTENT);
|
|
144
|
+
if (!(related instanceof HTMLElement)) return;
|
|
145
|
+
closeAbove(related);
|
|
146
|
+
const floatable = state.mapped.get(related);
|
|
147
|
+
if (floatable != null) floatable.toggle(false);
|
|
114
148
|
}
|
|
115
149
|
function stop(floatable) {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
150
|
+
if (floatable.frame != null) cancelAnimationFrame(floatable.frame);
|
|
151
|
+
floatable.frame = void 0;
|
|
152
|
+
}
|
|
153
|
+
function toggle(anchor) {
|
|
154
|
+
const floatable = getState()?.mapped.get(anchor);
|
|
155
|
+
if (floatable == null) {
|
|
156
|
+
closeAll();
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
const active = Boolean(floatable.active);
|
|
160
|
+
const content = findAncestor(floatable.options.anchor, SELECTOR_CONTENT);
|
|
161
|
+
if (content == null) closeAll();
|
|
162
|
+
else closeAbove(content);
|
|
163
|
+
floatable.toggle(!active);
|
|
164
|
+
}
|
|
165
|
+
function updatePosition(floatable) {
|
|
166
|
+
let position = floatable.options.anchor.getAttribute(floatable.options.positionAttribute)?.trim() ?? floatable.options.defaultPosition;
|
|
167
|
+
if (!POSITIONS.has(position)) position = floatable.options.defaultPosition;
|
|
168
|
+
let previousAnchor;
|
|
169
|
+
let previousContent;
|
|
170
|
+
let calculated = false;
|
|
171
|
+
let runOnAfter = false;
|
|
172
|
+
function run() {
|
|
173
|
+
const anchor = floatable.options.anchor.getBoundingClientRect();
|
|
174
|
+
const content = floatable.options.content.getBoundingClientRect();
|
|
175
|
+
if (calculated) {
|
|
176
|
+
if (previousAnchor != null && previousContent != null) {
|
|
177
|
+
if (PROPERTIES.every((property) => anchor[property] === previousAnchor[property]) && PROPERTIES.every((property) => content[property] === previousContent[property])) {
|
|
178
|
+
floatable.frame = requestAnimationFrame(run);
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
} else calculated = true;
|
|
183
|
+
update(anchor, content);
|
|
184
|
+
}
|
|
185
|
+
function update(anchor, content) {
|
|
186
|
+
previousAnchor = anchor;
|
|
187
|
+
previousContent = content;
|
|
188
|
+
const left = getX(anchor, content, position);
|
|
189
|
+
const top = getY(anchor, content, position, floatable.options.preferAbove);
|
|
190
|
+
if (top + content.height > window.innerHeight) floatable.options.content.style.height = `${window.innerHeight - top}px`;
|
|
191
|
+
else floatable.options.content.style.height = "";
|
|
192
|
+
if (left + content.width > window.innerWidth) floatable.options.content.style.width = `${window.innerWidth - left}px`;
|
|
193
|
+
else floatable.options.content.style.width = "";
|
|
194
|
+
floatable.options.content.style.transform = `translate3d(${left}px, ${top}px, 0)`;
|
|
195
|
+
floatable.frame = requestAnimationFrame(run);
|
|
196
|
+
if (!runOnAfter) {
|
|
197
|
+
runOnAfter = true;
|
|
198
|
+
floatable.options.onAfter?.(true);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
floatable.frame = requestAnimationFrame(run);
|
|
202
|
+
}
|
|
203
|
+
var ATTRIBUTE_ANCHOR = "oui-floatable-anchor";
|
|
204
|
+
var ATTRIBUTE_CONTENT = "oui-floatable-content";
|
|
205
|
+
var INSERT_AFTEREND = "afterend";
|
|
206
|
+
var POSITION_ABOVE = "above";
|
|
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([
|
|
217
|
+
"above",
|
|
218
|
+
"above-end",
|
|
219
|
+
"above-start",
|
|
220
|
+
"below",
|
|
221
|
+
"below-end",
|
|
222
|
+
"below-start",
|
|
223
|
+
"end",
|
|
224
|
+
"end-bottom",
|
|
225
|
+
"end-top",
|
|
226
|
+
"horizontal",
|
|
227
|
+
"horizontal-bottom",
|
|
228
|
+
"horizontal-top",
|
|
229
|
+
"start",
|
|
230
|
+
"start-bottom",
|
|
231
|
+
"start-top",
|
|
232
|
+
"vertical",
|
|
233
|
+
"vertical-end",
|
|
234
|
+
"vertical-start"
|
|
235
|
+
]);
|
|
236
|
+
var PROPERTIES = [
|
|
237
|
+
"bottom",
|
|
238
|
+
"left",
|
|
239
|
+
"right",
|
|
240
|
+
"top"
|
|
241
|
+
];
|
|
242
|
+
var SELECTOR_ALL = `[${ATTRIBUTE_ANCHOR}], [${ATTRIBUTE_CONTENT}]`;
|
|
243
|
+
var SELECTOR_CONTENT = `[${ATTRIBUTE_CONTENT}]`;
|
|
244
|
+
if (window._oscarpalmer_oui_floatable == null) {
|
|
245
|
+
Object.defineProperty(window, "_oscarpalmer_oui_floatable", {
|
|
246
|
+
enumerable: false,
|
|
247
|
+
value: {
|
|
248
|
+
active: /* @__PURE__ */ new Set(),
|
|
249
|
+
mapped: /* @__PURE__ */ new Map(),
|
|
250
|
+
order: []
|
|
251
|
+
},
|
|
252
|
+
writable: false
|
|
253
|
+
});
|
|
254
|
+
on(document, "keydown", (event) => {
|
|
255
|
+
onKeyDown(event);
|
|
256
|
+
});
|
|
257
|
+
on(document, "click", (event) => {
|
|
258
|
+
onClick(event);
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
export { Floatable, deactivate };
|