@fiscozen/composables 0.1.19 → 0.1.20-autovertical.1
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/composables.js +368 -0
- package/dist/composables.umd.cjs +1 -0
- package/package.json +3 -3
- package/src/FzFloating.vue +31 -3
- package/src/__tests__/__snapshots__/FzFloating.spec.ts.snap +24 -12
- package/src/composables/index.ts +1 -1
- package/src/composables/useClickOutside.ts +12 -9
- package/src/composables/useFloating.ts +127 -79
- package/src/composables/useKeyDown.ts +4 -1
- package/src/composables/useKeyUp.ts +6 -4
- package/src/types.ts +10 -1
- package/src/utils/index.ts +16 -7
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
import { ref as h, reactive as W, onUnmounted as I, nextTick as T, onMounted as R, watch as w, onBeforeUnmount as $, getCurrentInstance as q, computed as C, defineComponent as U, useSlots as G, toRef as K, openBlock as x, createElementBlock as z, renderSlot as k, createElementVNode as S, unref as E, withDirectives as M, normalizeClass as P, vShow as A, createCommentVNode as D, createBlock as Q, Teleport as X } from "vue";
|
|
2
|
+
const L = (o, t, s, r) => {
|
|
3
|
+
let a = "right", e = "right-start";
|
|
4
|
+
const u = o.getBoundingClientRect(), v = t.getBoundingClientRect(), l = s.getBoundingClientRect(), m = (l.left - u.left - v.width) / u.width, n = (u.right - l.right - v.width) / u.width, i = (l.top - u.top - v.height) / u.height, f = (u.bottom - l.bottom - v.height) / u.height;
|
|
5
|
+
if (a = [
|
|
6
|
+
{
|
|
7
|
+
key: "right",
|
|
8
|
+
space: n
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
key: "top",
|
|
12
|
+
space: i
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
key: "bottom",
|
|
16
|
+
space: f
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
key: "left",
|
|
20
|
+
space: m
|
|
21
|
+
}
|
|
22
|
+
].sort((p, c) => c.space - p.space)[0].key, !r)
|
|
23
|
+
switch (a) {
|
|
24
|
+
case "right":
|
|
25
|
+
case "left":
|
|
26
|
+
const p = (v.height - l.height) / 2;
|
|
27
|
+
u.top > l.top - p && (r = "end"), u.bottom < l.top - p && (r = "start");
|
|
28
|
+
break;
|
|
29
|
+
}
|
|
30
|
+
return e = r ? `${a}-${r}` : a, e;
|
|
31
|
+
}, Y = (o, t, s, r) => ({
|
|
32
|
+
x: t.x + o.width * s / 100,
|
|
33
|
+
y: t.y + o.height * r / 100
|
|
34
|
+
}), H = (o) => {
|
|
35
|
+
const t = h(null), s = h(null), r = h(null), a = h(null), e = W({
|
|
36
|
+
position: { x: 0, y: 0 }
|
|
37
|
+
}), u = {
|
|
38
|
+
root: null,
|
|
39
|
+
rootMargin: "0px",
|
|
40
|
+
threshold: 1,
|
|
41
|
+
...o.element.intersectionOptions
|
|
42
|
+
}, v = (n, i) => {
|
|
43
|
+
}, l = h(new IntersectionObserver(v, u)), m = () => T(() => {
|
|
44
|
+
var F;
|
|
45
|
+
if (t.value = typeof o.element.domRef.value == "string" ? document.querySelector(o.element.domRef.value) : o.element.domRef.value, o.container ? (s.value = typeof o.container.domRef.value == "string" ? document.querySelector(o.container.domRef.value) : o.container.domRef.value, s.value ?? (s.value = document.body)) : s.value = document.body, !t.value)
|
|
46
|
+
throw new Error("missing reference element for floating behavior");
|
|
47
|
+
o.opener && (r.value = typeof o.opener.domRef.value == "string" ? document.querySelector(o.opener.domRef.value) : o.opener.domRef.value), a.value = t.value.getBoundingClientRect();
|
|
48
|
+
const n = (F = r.value) == null ? void 0 : F.getBoundingClientRect(), i = s.value.getBoundingClientRect(), f = window.getComputedStyle(t.value);
|
|
49
|
+
l.value.observe(t.value), l.value.observe(s.value);
|
|
50
|
+
let d = o.position ? o.position.value : "auto", p = 0, c = 0;
|
|
51
|
+
if (o.opener && r.value && n) {
|
|
52
|
+
const y = n.left - parseFloat(f.marginLeft) - parseFloat(f.marginRight), N = n.left - parseFloat(f.marginLeft), b = n.top - parseFloat(f.marginTop) - parseFloat(f.marginBottom), O = n.top - parseFloat(f.marginTop);
|
|
53
|
+
switch (d) {
|
|
54
|
+
case "auto":
|
|
55
|
+
d = L(
|
|
56
|
+
s.value,
|
|
57
|
+
t.value,
|
|
58
|
+
r.value
|
|
59
|
+
);
|
|
60
|
+
break;
|
|
61
|
+
case "auto-start":
|
|
62
|
+
d = L(
|
|
63
|
+
s.value,
|
|
64
|
+
t.value,
|
|
65
|
+
r.value,
|
|
66
|
+
"start"
|
|
67
|
+
);
|
|
68
|
+
break;
|
|
69
|
+
case "auto-end":
|
|
70
|
+
d = L(
|
|
71
|
+
s.value,
|
|
72
|
+
t.value,
|
|
73
|
+
r.value,
|
|
74
|
+
"end"
|
|
75
|
+
);
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
switch (d) {
|
|
79
|
+
case "bottom":
|
|
80
|
+
e.position.y = n.bottom, e.position.x = N + n.width / 2, c = -50, p = 0;
|
|
81
|
+
break;
|
|
82
|
+
case "bottom-start":
|
|
83
|
+
e.position.y = n.bottom, e.position.x = y, c = 0, p = 0;
|
|
84
|
+
break;
|
|
85
|
+
case "bottom-end":
|
|
86
|
+
e.position.y = n.bottom, e.position.x = n.right, c = -100, p = 0;
|
|
87
|
+
break;
|
|
88
|
+
case "left-start":
|
|
89
|
+
e.position.y = b, e.position.x = y, c = -100, p = 0;
|
|
90
|
+
break;
|
|
91
|
+
case "left":
|
|
92
|
+
e.position.y = O + n.height / 2, e.position.x = y, p = -50, c = -100;
|
|
93
|
+
break;
|
|
94
|
+
case "left-end":
|
|
95
|
+
e.position.y = n.bottom, e.position.x = y, p = -100, c = -100;
|
|
96
|
+
break;
|
|
97
|
+
case "top-start":
|
|
98
|
+
e.position.y = b, e.position.x = y, p = -100, c = 0;
|
|
99
|
+
break;
|
|
100
|
+
case "top":
|
|
101
|
+
e.position.y = b, e.position.x = N + n.width / 2, c = -50, p = -100;
|
|
102
|
+
break;
|
|
103
|
+
case "top-end":
|
|
104
|
+
e.position.y = b, e.position.x = n.right, c = -100, p = -100;
|
|
105
|
+
break;
|
|
106
|
+
case "right-start":
|
|
107
|
+
e.position.y = b, e.position.x = n.right, c = 0, p = 0;
|
|
108
|
+
break;
|
|
109
|
+
case "right":
|
|
110
|
+
e.position.y = O + n.height / 2, e.position.x = n.right, p = -50, c = 0;
|
|
111
|
+
break;
|
|
112
|
+
case "right-end":
|
|
113
|
+
e.position.y = n.bottom, e.position.x = n.right, p = -100, c = 0;
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
} else
|
|
117
|
+
switch (d) {
|
|
118
|
+
case "bottom":
|
|
119
|
+
e.position.y = i.bottom - a.value.height, e.position.x = i.left + i.width / 2, c = -50;
|
|
120
|
+
break;
|
|
121
|
+
case "left-end":
|
|
122
|
+
case "bottom-start":
|
|
123
|
+
e.position.y = i.bottom - a.value.height, e.position.x = i.left;
|
|
124
|
+
break;
|
|
125
|
+
case "right-end":
|
|
126
|
+
case "bottom-end":
|
|
127
|
+
e.position.y = i.bottom - a.value.height, e.position.x = i.right - a.value.width;
|
|
128
|
+
break;
|
|
129
|
+
case "left":
|
|
130
|
+
e.position.y = i.top + (i.height - a.value.height) / 2, e.position.x = i.left;
|
|
131
|
+
break;
|
|
132
|
+
case "top-start":
|
|
133
|
+
case "left-start":
|
|
134
|
+
e.position.y = i.top, e.position.x = i.left;
|
|
135
|
+
break;
|
|
136
|
+
case "top":
|
|
137
|
+
e.position.y = i.top, e.position.x = i.left + (i.width - a.value.width) / 2;
|
|
138
|
+
break;
|
|
139
|
+
case "top-end":
|
|
140
|
+
case "right-start":
|
|
141
|
+
e.position.y = i.top, e.position.x = i.right - a.value.width;
|
|
142
|
+
case "right":
|
|
143
|
+
e.position.y = i.top + (i.height - a.value.height) / 2, e.position.x = i.right - a.value.width;
|
|
144
|
+
break;
|
|
145
|
+
}
|
|
146
|
+
const g = Y(a.value, e.position, c, p);
|
|
147
|
+
e.position.x = g.x, e.position.y = g.y, g.x < i.left && (e.position.x = i.left, c = 0), g.x + a.value.width > i.right && (e.position.x = i.right - a.value.width, c = 0), g.y < i.top && (e.position.y = i.top, p = 0), g.y + a.value.height > i.bottom && (e.position.y = i.bottom - a.value.height, p = 0), t.value.style.top = `${e.position.y}px`, t.value.style.left = `${e.position.x}px`, t.value.style.display = "flex", a.value = t.value.getBoundingClientRect();
|
|
148
|
+
});
|
|
149
|
+
return I(() => {
|
|
150
|
+
l.value.disconnect();
|
|
151
|
+
}), {
|
|
152
|
+
float: e,
|
|
153
|
+
rect: a,
|
|
154
|
+
floatObserver: l,
|
|
155
|
+
setPosition: m
|
|
156
|
+
};
|
|
157
|
+
};
|
|
158
|
+
function B(o) {
|
|
159
|
+
const t = window.matchMedia(o), s = h(t.matches);
|
|
160
|
+
function r(a) {
|
|
161
|
+
s.value = a.matches;
|
|
162
|
+
}
|
|
163
|
+
return R(() => {
|
|
164
|
+
t.addEventListener("change", r);
|
|
165
|
+
}), I(() => {
|
|
166
|
+
t.removeEventListener("change", r);
|
|
167
|
+
}), s;
|
|
168
|
+
}
|
|
169
|
+
function Z(o) {
|
|
170
|
+
return {
|
|
171
|
+
isGreater(t) {
|
|
172
|
+
return B(`(min-width: ${o[t]})`);
|
|
173
|
+
},
|
|
174
|
+
isSmaller(t) {
|
|
175
|
+
return B(`(max-width: ${o[t]})`);
|
|
176
|
+
},
|
|
177
|
+
isInBetween(t, s) {
|
|
178
|
+
return B(`(min-width: ${o[t]}) and (max-width: ${o[s]})`);
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
function _(o, t, s) {
|
|
183
|
+
if (!o)
|
|
184
|
+
throw new Error("A target component has to be provided.");
|
|
185
|
+
if (!t)
|
|
186
|
+
throw new Error("A callback has to be provided.");
|
|
187
|
+
const r = (a) => {
|
|
188
|
+
!o.value || a.target === o.value || a.composedPath().includes(o.value) || typeof t == "function" && t();
|
|
189
|
+
};
|
|
190
|
+
s && w(s, (a, e) => {
|
|
191
|
+
e && e.removeEventListener("click", r), a == null || a.addEventListener("click", r);
|
|
192
|
+
}), R(() => {
|
|
193
|
+
s || document.addEventListener("click", r);
|
|
194
|
+
}), $(() => {
|
|
195
|
+
if (s) {
|
|
196
|
+
s.value.removeEventListener("click", r);
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
document.removeEventListener("click", r);
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
function j(o, t) {
|
|
203
|
+
if (!o)
|
|
204
|
+
throw new Error("A target component has to be provided.");
|
|
205
|
+
if (!t || typeof t != "function")
|
|
206
|
+
throw new Error("A callback has to be provided.");
|
|
207
|
+
const s = (r) => {
|
|
208
|
+
t(r);
|
|
209
|
+
};
|
|
210
|
+
R(() => {
|
|
211
|
+
o.value.addEventListener("keydown", s);
|
|
212
|
+
}), $(() => {
|
|
213
|
+
o.value.removeEventListener("keydown", s);
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
function V(o, t) {
|
|
217
|
+
if (!o || typeof o != "function")
|
|
218
|
+
throw new Error("A callback has to be provided.");
|
|
219
|
+
const s = (r) => {
|
|
220
|
+
o(r);
|
|
221
|
+
};
|
|
222
|
+
R(() => {
|
|
223
|
+
if (!t) {
|
|
224
|
+
document.addEventListener("keyup", s);
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
t.value.addEventListener("keyup", s);
|
|
228
|
+
}), $(() => {
|
|
229
|
+
if (!t) {
|
|
230
|
+
document.removeEventListener("keyup", s);
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
t.value.removeEventListener("keyup", s);
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
const ee = () => {
|
|
237
|
+
const o = h(null), t = q(), s = C(() => t == null ? void 0 : t.props.amount), r = h(), a = (n) => n.toLocaleString("it-IT", {
|
|
238
|
+
minimumFractionDigits: 2,
|
|
239
|
+
maximumFractionDigits: 2,
|
|
240
|
+
useGrouping: !1
|
|
241
|
+
}), e = (n) => parseFloat(n.replace(/,/g, ".")), u = (n) => {
|
|
242
|
+
Number.isNaN(n) || t && (r.value = n, t.emit("update:amount", n));
|
|
243
|
+
}, v = (n) => {
|
|
244
|
+
setTimeout(() => {
|
|
245
|
+
o.value && (o.value.value = n);
|
|
246
|
+
}, 0);
|
|
247
|
+
}, l = (n) => (i) => {
|
|
248
|
+
if (!o.value || !i.target)
|
|
249
|
+
return;
|
|
250
|
+
let { value: f } = n;
|
|
251
|
+
f = f.replace(/[^0-9,.]/g, ""), v(f);
|
|
252
|
+
const d = e(f);
|
|
253
|
+
u(Number.isNaN(d) ? 0 : d);
|
|
254
|
+
}, m = (n) => {
|
|
255
|
+
if (!o.value || !n.target)
|
|
256
|
+
return;
|
|
257
|
+
let i = e(n.target.value);
|
|
258
|
+
Number.isNaN(i) && (i = 0);
|
|
259
|
+
const f = a(i);
|
|
260
|
+
v(f), u(e(f));
|
|
261
|
+
};
|
|
262
|
+
return w(o, (n, i) => {
|
|
263
|
+
n && (i && (i == null || i.removeEventListener("input", l(n)), i == null || i.removeEventListener("blur", m)), n.addEventListener("input", l(n)), n.addEventListener("blur", m), s.value && (n.value = a(s.value)));
|
|
264
|
+
}), w(s, (n) => {
|
|
265
|
+
T(() => {
|
|
266
|
+
if (!(!o.value || !n) && r.value !== n) {
|
|
267
|
+
const i = a(n);
|
|
268
|
+
o.value.value = i, r.value = n;
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
}), {
|
|
272
|
+
inputRef: o,
|
|
273
|
+
parse: e,
|
|
274
|
+
format: a,
|
|
275
|
+
emitAmount: u,
|
|
276
|
+
setValue: v
|
|
277
|
+
};
|
|
278
|
+
}, te = /* @__PURE__ */ U({
|
|
279
|
+
__name: "FzFloating",
|
|
280
|
+
props: {
|
|
281
|
+
isOpen: { type: Boolean, default: !1 },
|
|
282
|
+
position: { default: "auto" },
|
|
283
|
+
container: {},
|
|
284
|
+
contentClass: {},
|
|
285
|
+
openerClass: {},
|
|
286
|
+
overrideContentClass: { type: Boolean },
|
|
287
|
+
teleport: { type: Boolean, default: !1 }
|
|
288
|
+
},
|
|
289
|
+
setup(o) {
|
|
290
|
+
const t = o, s = h(null), r = h(null), a = G(), e = {
|
|
291
|
+
position: C(() => t.position),
|
|
292
|
+
element: {
|
|
293
|
+
domRef: r
|
|
294
|
+
},
|
|
295
|
+
container: {
|
|
296
|
+
domRef: K(t.container || document.body)
|
|
297
|
+
}
|
|
298
|
+
};
|
|
299
|
+
a.opener && (e.opener = {
|
|
300
|
+
domRef: s
|
|
301
|
+
});
|
|
302
|
+
const u = H(e);
|
|
303
|
+
w(
|
|
304
|
+
() => t.position,
|
|
305
|
+
() => t.isOpen && u.setPosition()
|
|
306
|
+
), w(
|
|
307
|
+
() => t.isOpen,
|
|
308
|
+
(l) => {
|
|
309
|
+
!l || !r.value || (r.value.style.top = "0px", r.value.style.left = "0px", r.value.style.transform = "none", u.setPosition());
|
|
310
|
+
}
|
|
311
|
+
);
|
|
312
|
+
const v = C(() => t.overrideContentClass ? t.contentClass : ["bg-core-white fixed p-4 z-10", t.contentClass]);
|
|
313
|
+
return (l, m) => (x(), z("div", null, [
|
|
314
|
+
k(l.$slots, "opener-start"),
|
|
315
|
+
S("div", {
|
|
316
|
+
ref_key: "opener",
|
|
317
|
+
ref: s,
|
|
318
|
+
class: "inline-flex"
|
|
319
|
+
}, [
|
|
320
|
+
k(l.$slots, "opener", {
|
|
321
|
+
isOpen: l.isOpen,
|
|
322
|
+
floating: E(u)
|
|
323
|
+
})
|
|
324
|
+
], 512),
|
|
325
|
+
k(l.$slots, "opener-end"),
|
|
326
|
+
l.teleport ? D("", !0) : M((x(), z("div", {
|
|
327
|
+
key: 0,
|
|
328
|
+
ref_key: "content",
|
|
329
|
+
ref: r,
|
|
330
|
+
class: P(["fz__floating__content bg-core-white fixed p-4 z-10", v.value])
|
|
331
|
+
}, [
|
|
332
|
+
k(l.$slots, "default", {
|
|
333
|
+
isOpen: l.isOpen,
|
|
334
|
+
floating: E(u)
|
|
335
|
+
})
|
|
336
|
+
], 2)), [
|
|
337
|
+
[A, l.$slots.default && (!l.$slots.opener || l.$slots.opener && l.isOpen)]
|
|
338
|
+
]),
|
|
339
|
+
l.teleport ? (x(), Q(X, {
|
|
340
|
+
key: 1,
|
|
341
|
+
to: "body"
|
|
342
|
+
}, [
|
|
343
|
+
M(S("div", {
|
|
344
|
+
ref_key: "content",
|
|
345
|
+
ref: r,
|
|
346
|
+
class: P(["fz__floating__content bg-core-white absolute p-4 z-10", v.value])
|
|
347
|
+
}, [
|
|
348
|
+
k(l.$slots, "default", {
|
|
349
|
+
isOpen: l.isOpen,
|
|
350
|
+
floating: E(u)
|
|
351
|
+
})
|
|
352
|
+
], 2), [
|
|
353
|
+
[A, l.$slots.default && (!l.$slots.opener || l.$slots.opener && l.isOpen)]
|
|
354
|
+
])
|
|
355
|
+
])) : D("", !0)
|
|
356
|
+
]));
|
|
357
|
+
}
|
|
358
|
+
});
|
|
359
|
+
export {
|
|
360
|
+
te as FzFloating,
|
|
361
|
+
Z as useBreakpoints,
|
|
362
|
+
_ as useClickOutside,
|
|
363
|
+
ee as useCurrency,
|
|
364
|
+
H as useFloating,
|
|
365
|
+
j as useKeyDown,
|
|
366
|
+
V as useKeyUp,
|
|
367
|
+
B as useMediaQuery
|
|
368
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(function(h,t){typeof exports=="object"&&typeof module<"u"?t(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],t):(h=typeof globalThis<"u"?globalThis:h||self,t(h.FzComposables={},h.Vue))})(this,function(h,t){"use strict";const R=(n,o,r,a)=>{let l="right",e="right-start";const p=n.getBoundingClientRect(),m=o.getBoundingClientRect(),c=r.getBoundingClientRect(),y=(c.left-p.left-m.width)/p.width,i=(p.right-c.right-m.width)/p.width,s=(c.top-p.top-m.height)/p.height,d=(p.bottom-c.bottom-m.height)/p.height;if(l=[{key:"right",space:i},{key:"top",space:s},{key:"bottom",space:d},{key:"left",space:y}].sort((u,f)=>f.space-u.space)[0].key,!a)switch(l){case"right":case"left":const u=(m.height-c.height)/2;p.top>c.top-u&&(a="end"),p.bottom<c.top-u&&(a="start");break}return e=a?`${l}-${a}`:l,e},L=(n,o,r,a)=>({x:o.x+n.width*r/100,y:o.y+n.height*a/100}),E=n=>{const o=t.ref(null),r=t.ref(null),a=t.ref(null),l=t.ref(null),e=t.reactive({position:{x:0,y:0}}),p={root:null,rootMargin:"0px",threshold:1,...n.element.intersectionOptions},m=(i,s)=>{},c=t.ref(new IntersectionObserver(m,p)),y=()=>t.nextTick(()=>{var B;if(o.value=typeof n.element.domRef.value=="string"?document.querySelector(n.element.domRef.value):n.element.domRef.value,n.container?(r.value=typeof n.container.domRef.value=="string"?document.querySelector(n.container.domRef.value):n.container.domRef.value,r.value??(r.value=document.body)):r.value=document.body,!o.value)throw new Error("missing reference element for floating behavior");n.opener&&(a.value=typeof n.opener.domRef.value=="string"?document.querySelector(n.opener.domRef.value):n.opener.domRef.value),l.value=o.value.getBoundingClientRect();const i=(B=a.value)==null?void 0:B.getBoundingClientRect(),s=r.value.getBoundingClientRect(),d=window.getComputedStyle(o.value);c.value.observe(o.value),c.value.observe(r.value);let g=n.position?n.position.value:"auto",u=0,f=0;if(n.opener&&a.value&&i){const b=i.left-parseFloat(d.marginLeft)-parseFloat(d.marginRight),C=i.left-parseFloat(d.marginLeft),k=i.top-parseFloat(d.marginTop)-parseFloat(d.marginBottom),x=i.top-parseFloat(d.marginTop);switch(g){case"auto":g=R(r.value,o.value,a.value);break;case"auto-start":g=R(r.value,o.value,a.value,"start");break;case"auto-end":g=R(r.value,o.value,a.value,"end");break}switch(g){case"bottom":e.position.y=i.bottom,e.position.x=C+i.width/2,f=-50,u=0;break;case"bottom-start":e.position.y=i.bottom,e.position.x=b,f=0,u=0;break;case"bottom-end":e.position.y=i.bottom,e.position.x=i.right,f=-100,u=0;break;case"left-start":e.position.y=k,e.position.x=b,f=-100,u=0;break;case"left":e.position.y=x+i.height/2,e.position.x=b,u=-50,f=-100;break;case"left-end":e.position.y=i.bottom,e.position.x=b,u=-100,f=-100;break;case"top-start":e.position.y=k,e.position.x=b,u=-100,f=0;break;case"top":e.position.y=k,e.position.x=C+i.width/2,f=-50,u=-100;break;case"top-end":e.position.y=k,e.position.x=i.right,f=-100,u=-100;break;case"right-start":e.position.y=k,e.position.x=i.right,f=0,u=0;break;case"right":e.position.y=x+i.height/2,e.position.x=i.right,u=-50,f=0;break;case"right-end":e.position.y=i.bottom,e.position.x=i.right,u=-100,f=0;break}}else switch(g){case"bottom":e.position.y=s.bottom-l.value.height,e.position.x=s.left+s.width/2,f=-50;break;case"left-end":case"bottom-start":e.position.y=s.bottom-l.value.height,e.position.x=s.left;break;case"right-end":case"bottom-end":e.position.y=s.bottom-l.value.height,e.position.x=s.right-l.value.width;break;case"left":e.position.y=s.top+(s.height-l.value.height)/2,e.position.x=s.left;break;case"top-start":case"left-start":e.position.y=s.top,e.position.x=s.left;break;case"top":e.position.y=s.top,e.position.x=s.left+(s.width-l.value.width)/2;break;case"top-end":case"right-start":e.position.y=s.top,e.position.x=s.right-l.value.width;case"right":e.position.y=s.top+(s.height-l.value.height)/2,e.position.x=s.right-l.value.width;break}const v=L(l.value,e.position,f,u);e.position.x=v.x,e.position.y=v.y,v.x<s.left&&(e.position.x=s.left,f=0),v.x+l.value.width>s.right&&(e.position.x=s.right-l.value.width,f=0),v.y<s.top&&(e.position.y=s.top,u=0),v.y+l.value.height>s.bottom&&(e.position.y=s.bottom-l.value.height,u=0),o.value.style.top=`${e.position.y}px`,o.value.style.left=`${e.position.x}px`,o.value.style.display="flex",l.value=o.value.getBoundingClientRect()});return t.onUnmounted(()=>{c.value.disconnect()}),{float:e,rect:l,floatObserver:c,setPosition:y}};function w(n){const o=window.matchMedia(n),r=t.ref(o.matches);function a(l){r.value=l.matches}return t.onMounted(()=>{o.addEventListener("change",a)}),t.onUnmounted(()=>{o.removeEventListener("change",a)}),r}function $(n){return{isGreater(o){return w(`(min-width: ${n[o]})`)},isSmaller(o){return w(`(max-width: ${n[o]})`)},isInBetween(o,r){return w(`(min-width: ${n[o]}) and (max-width: ${n[r]})`)}}}function S(n,o,r){if(!n)throw new Error("A target component has to be provided.");if(!o)throw new Error("A callback has to be provided.");const a=l=>{!n.value||l.target===n.value||l.composedPath().includes(n.value)||typeof o=="function"&&o()};r&&t.watch(r,(l,e)=>{e&&e.removeEventListener("click",a),l==null||l.addEventListener("click",a)}),t.onMounted(()=>{r||document.addEventListener("click",a)}),t.onBeforeUnmount(()=>{if(r){r.value.removeEventListener("click",a);return}document.removeEventListener("click",a)})}function F(n,o){if(!n)throw new Error("A target component has to be provided.");if(!o||typeof o!="function")throw new Error("A callback has to be provided.");const r=a=>{o(a)};t.onMounted(()=>{n.value.addEventListener("keydown",r)}),t.onBeforeUnmount(()=>{n.value.removeEventListener("keydown",r)})}function N(n,o){if(!n||typeof n!="function")throw new Error("A callback has to be provided.");const r=a=>{n(a)};t.onMounted(()=>{if(!o){document.addEventListener("keyup",r);return}o.value.addEventListener("keyup",r)}),t.onBeforeUnmount(()=>{if(!o){document.removeEventListener("keyup",r);return}o.value.removeEventListener("keyup",r)})}const O=()=>{const n=t.ref(null),o=t.getCurrentInstance(),r=t.computed(()=>o==null?void 0:o.props.amount),a=t.ref(),l=i=>i.toLocaleString("it-IT",{minimumFractionDigits:2,maximumFractionDigits:2,useGrouping:!1}),e=i=>parseFloat(i.replace(/,/g,".")),p=i=>{Number.isNaN(i)||o&&(a.value=i,o.emit("update:amount",i))},m=i=>{setTimeout(()=>{n.value&&(n.value.value=i)},0)},c=i=>s=>{if(!n.value||!s.target)return;let{value:d}=i;d=d.replace(/[^0-9,.]/g,""),m(d);const g=e(d);p(Number.isNaN(g)?0:g)},y=i=>{if(!n.value||!i.target)return;let s=e(i.target.value);Number.isNaN(s)&&(s=0);const d=l(s);m(d),p(e(d))};return t.watch(n,(i,s)=>{i&&(s&&(s==null||s.removeEventListener("input",c(i)),s==null||s.removeEventListener("blur",y)),i.addEventListener("input",c(i)),i.addEventListener("blur",y),r.value&&(i.value=l(r.value)))}),t.watch(r,i=>{t.nextTick(()=>{if(!(!n.value||!i)&&a.value!==i){const s=l(i);n.value.value=s,a.value=i}})}),{inputRef:n,parse:e,format:l,emitAmount:p,setValue:m}},z=t.defineComponent({__name:"FzFloating",props:{isOpen:{type:Boolean,default:!1},position:{default:"auto"},container:{},contentClass:{},openerClass:{},overrideContentClass:{type:Boolean},teleport:{type:Boolean,default:!1}},setup(n){const o=n,r=t.ref(null),a=t.ref(null),l=t.useSlots(),e={position:t.computed(()=>o.position),element:{domRef:a},container:{domRef:t.toRef(o.container||document.body)}};l.opener&&(e.opener={domRef:r});const p=E(e);t.watch(()=>o.position,()=>o.isOpen&&p.setPosition()),t.watch(()=>o.isOpen,c=>{!c||!a.value||(a.value.style.top="0px",a.value.style.left="0px",a.value.style.transform="none",p.setPosition())});const m=t.computed(()=>o.overrideContentClass?o.contentClass:["bg-core-white fixed p-4 z-10",o.contentClass]);return(c,y)=>(t.openBlock(),t.createElementBlock("div",null,[t.renderSlot(c.$slots,"opener-start"),t.createElementVNode("div",{ref_key:"opener",ref:r,class:"inline-flex"},[t.renderSlot(c.$slots,"opener",{isOpen:c.isOpen,floating:t.unref(p)})],512),t.renderSlot(c.$slots,"opener-end"),c.teleport?t.createCommentVNode("",!0):t.withDirectives((t.openBlock(),t.createElementBlock("div",{key:0,ref_key:"content",ref:a,class:t.normalizeClass(["fz__floating__content bg-core-white fixed p-4 z-10",m.value])},[t.renderSlot(c.$slots,"default",{isOpen:c.isOpen,floating:t.unref(p)})],2)),[[t.vShow,c.$slots.default&&(!c.$slots.opener||c.$slots.opener&&c.isOpen)]]),c.teleport?(t.openBlock(),t.createBlock(t.Teleport,{key:1,to:"body"},[t.withDirectives(t.createElementVNode("div",{ref_key:"content",ref:a,class:t.normalizeClass(["fz__floating__content bg-core-white absolute p-4 z-10",m.value])},[t.renderSlot(c.$slots,"default",{isOpen:c.isOpen,floating:t.unref(p)})],2),[[t.vShow,c.$slots.default&&(!c.$slots.opener||c.$slots.opener&&c.isOpen)]])])):t.createCommentVNode("",!0)]))}});h.FzFloating=z,h.useBreakpoints=$,h.useClickOutside=S,h.useCurrency=O,h.useFloating=E,h.useKeyDown=F,h.useKeyUp=N,h.useMediaQuery=w,Object.defineProperty(h,Symbol.toStringTag,{value:"Module"})});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fiscozen/composables",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.20-autovertical.1",
|
|
4
4
|
"description": "Design System utility composables",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"type": "module",
|
|
@@ -25,9 +25,9 @@
|
|
|
25
25
|
"vite": "^5.0.10",
|
|
26
26
|
"vitest": "^1.2.0",
|
|
27
27
|
"vue-tsc": "^1.8.25",
|
|
28
|
-
"@fiscozen/
|
|
28
|
+
"@fiscozen/eslint-config": "^0.1.0",
|
|
29
29
|
"@fiscozen/prettier-config": "^0.1.0",
|
|
30
|
-
"@fiscozen/
|
|
30
|
+
"@fiscozen/tsconfig": "^0.1.0"
|
|
31
31
|
},
|
|
32
32
|
"license": "ISC",
|
|
33
33
|
"scripts": {
|
package/src/FzFloating.vue
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
-
import { ref, useSlots, watch, toRef, computed } from 'vue'
|
|
2
|
+
import { ref, useSlots, watch, toRef, computed, onMounted, onBeforeUnmount } from 'vue'
|
|
3
3
|
import { useFloating } from './composables'
|
|
4
4
|
import { FzFloatingProps, FzUseFloatingArgs } from './types'
|
|
5
5
|
|
|
@@ -9,18 +9,28 @@ const props = withDefaults(defineProps<FzFloatingProps>(), {
|
|
|
9
9
|
teleport: false
|
|
10
10
|
})
|
|
11
11
|
|
|
12
|
+
const emits = defineEmits(['fzfloating:setPosition'])
|
|
13
|
+
|
|
12
14
|
const opener = ref(null)
|
|
13
15
|
const content = ref<HTMLElement | null>(null)
|
|
14
16
|
|
|
15
17
|
const slots = useSlots()
|
|
16
18
|
|
|
19
|
+
let scheduledAnimationFrame = false;
|
|
20
|
+
|
|
17
21
|
const useFloatingOpts: FzUseFloatingArgs = {
|
|
18
22
|
position: computed(() => props.position),
|
|
19
23
|
element: {
|
|
24
|
+
// @ts-ignore
|
|
20
25
|
domRef: content
|
|
21
26
|
},
|
|
22
27
|
container: {
|
|
28
|
+
// @ts-ignore
|
|
23
29
|
domRef: toRef(props.container || document.body)
|
|
30
|
+
},
|
|
31
|
+
useViewport: computed(() => props.useViewport),
|
|
32
|
+
callback(...args) {
|
|
33
|
+
emits('fzfloating:setPosition', ...args)
|
|
24
34
|
}
|
|
25
35
|
}
|
|
26
36
|
if (slots.opener) {
|
|
@@ -31,9 +41,21 @@ if (slots.opener) {
|
|
|
31
41
|
|
|
32
42
|
const floating = useFloating(useFloatingOpts)
|
|
33
43
|
|
|
44
|
+
const setPositionWhenOpen = () => {
|
|
45
|
+
if (scheduledAnimationFrame){
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
scheduledAnimationFrame = true;
|
|
50
|
+
requestAnimationFrame(() => {
|
|
51
|
+
props.isOpen && floating.setPosition();
|
|
52
|
+
scheduledAnimationFrame = false;
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
34
56
|
watch(
|
|
35
57
|
() => props.position,
|
|
36
|
-
() =>
|
|
58
|
+
() => setPositionWhenOpen()
|
|
37
59
|
)
|
|
38
60
|
watch(
|
|
39
61
|
() => props.isOpen,
|
|
@@ -47,6 +69,12 @@ watch(
|
|
|
47
69
|
floating.setPosition()
|
|
48
70
|
}
|
|
49
71
|
)
|
|
72
|
+
onMounted(() => {
|
|
73
|
+
window.addEventListener('scroll', setPositionWhenOpen);
|
|
74
|
+
})
|
|
75
|
+
onBeforeUnmount(() => {
|
|
76
|
+
window.removeEventListener('scroll', setPositionWhenOpen);
|
|
77
|
+
})
|
|
50
78
|
|
|
51
79
|
const contentClass = computed(() => {
|
|
52
80
|
if (props.overrideContentClass) {
|
|
@@ -77,7 +105,7 @@ const contentClass = computed(() => {
|
|
|
77
105
|
<div
|
|
78
106
|
ref="content"
|
|
79
107
|
v-show="$slots.default && (!$slots.opener || ($slots.opener && isOpen))"
|
|
80
|
-
class="fz__floating__content bg-core-white
|
|
108
|
+
class="fz__floating__content bg-core-white fixed p-4 z-10"
|
|
81
109
|
:class="contentClass"
|
|
82
110
|
>
|
|
83
111
|
<slot :isOpen :floating></slot>
|
|
@@ -3,107 +3,119 @@
|
|
|
3
3
|
exports[`FzFloating > should match snapshot 1`] = `
|
|
4
4
|
"<div>
|
|
5
5
|
<div class="inline-flex"><button>opener</button></div>
|
|
6
|
-
<div class="bg-core-white
|
|
6
|
+
<div class="fz__floating__content bg-core-white fixed z-10 p-4 bg-core-white fixed p-4 z-10">
|
|
7
7
|
<div>content</div>
|
|
8
8
|
</div>
|
|
9
|
+
<!--v-if-->
|
|
9
10
|
</div>"
|
|
10
11
|
`;
|
|
11
12
|
|
|
12
13
|
exports[`FzFloating > should match snapshot 2`] = `
|
|
13
14
|
"<div>
|
|
14
15
|
<div class="inline-flex"><button>opener</button></div>
|
|
15
|
-
<div class="bg-core-white
|
|
16
|
+
<div class="fz__floating__content bg-core-white fixed z-10 p-4 bg-core-white fixed p-4 z-10">
|
|
16
17
|
<div>content</div>
|
|
17
18
|
</div>
|
|
19
|
+
<!--v-if-->
|
|
18
20
|
</div>"
|
|
19
21
|
`;
|
|
20
22
|
|
|
21
23
|
exports[`FzFloating > should match snapshot 3`] = `
|
|
22
24
|
"<div>
|
|
23
25
|
<div class="inline-flex"><button>opener</button></div>
|
|
24
|
-
<div class="bg-core-white
|
|
26
|
+
<div class="fz__floating__content bg-core-white fixed z-10 p-4 bg-core-white fixed p-4 z-10">
|
|
25
27
|
<div>content</div>
|
|
26
28
|
</div>
|
|
29
|
+
<!--v-if-->
|
|
27
30
|
</div>"
|
|
28
31
|
`;
|
|
29
32
|
|
|
30
33
|
exports[`FzFloating > should match snapshot 4`] = `
|
|
31
34
|
"<div>
|
|
32
35
|
<div class="inline-flex"><button>opener</button></div>
|
|
33
|
-
<div class="bg-core-white
|
|
36
|
+
<div class="fz__floating__content bg-core-white fixed z-10 p-4 bg-core-white fixed p-4 z-10">
|
|
34
37
|
<div>content</div>
|
|
35
38
|
</div>
|
|
39
|
+
<!--v-if-->
|
|
36
40
|
</div>"
|
|
37
41
|
`;
|
|
38
42
|
|
|
39
43
|
exports[`FzFloating > should match snapshot 5`] = `
|
|
40
44
|
"<div>
|
|
41
45
|
<div class="inline-flex"><button>opener</button></div>
|
|
42
|
-
<div class="bg-core-white
|
|
46
|
+
<div class="fz__floating__content bg-core-white fixed z-10 p-4 bg-core-white fixed p-4 z-10">
|
|
43
47
|
<div>content</div>
|
|
44
48
|
</div>
|
|
49
|
+
<!--v-if-->
|
|
45
50
|
</div>"
|
|
46
51
|
`;
|
|
47
52
|
|
|
48
53
|
exports[`FzFloating > should match snapshot 6`] = `
|
|
49
54
|
"<div>
|
|
50
55
|
<div class="inline-flex"><button>opener</button></div>
|
|
51
|
-
<div class="bg-core-white
|
|
56
|
+
<div class="fz__floating__content bg-core-white fixed z-10 p-4 bg-core-white fixed p-4 z-10">
|
|
52
57
|
<div>content</div>
|
|
53
58
|
</div>
|
|
59
|
+
<!--v-if-->
|
|
54
60
|
</div>"
|
|
55
61
|
`;
|
|
56
62
|
|
|
57
63
|
exports[`FzFloating > should match snapshot 7`] = `
|
|
58
64
|
"<div>
|
|
59
65
|
<div class="inline-flex"><button>opener</button></div>
|
|
60
|
-
<div class="bg-core-white
|
|
66
|
+
<div class="fz__floating__content bg-core-white fixed z-10 p-4 bg-core-white fixed p-4 z-10">
|
|
61
67
|
<div>content</div>
|
|
62
68
|
</div>
|
|
69
|
+
<!--v-if-->
|
|
63
70
|
</div>"
|
|
64
71
|
`;
|
|
65
72
|
|
|
66
73
|
exports[`FzFloating > should match snapshot 8`] = `
|
|
67
74
|
"<div>
|
|
68
75
|
<div class="inline-flex"><button>opener</button></div>
|
|
69
|
-
<div class="bg-core-white
|
|
76
|
+
<div class="fz__floating__content bg-core-white fixed z-10 p-4 bg-core-white fixed p-4 z-10">
|
|
70
77
|
<div>content</div>
|
|
71
78
|
</div>
|
|
79
|
+
<!--v-if-->
|
|
72
80
|
</div>"
|
|
73
81
|
`;
|
|
74
82
|
|
|
75
83
|
exports[`FzFloating > should match snapshot 9`] = `
|
|
76
84
|
"<div>
|
|
77
85
|
<div class="inline-flex"><button>opener</button></div>
|
|
78
|
-
<div class="bg-core-white
|
|
86
|
+
<div class="fz__floating__content bg-core-white fixed z-10 p-4 bg-core-white fixed p-4 z-10">
|
|
79
87
|
<div>content</div>
|
|
80
88
|
</div>
|
|
89
|
+
<!--v-if-->
|
|
81
90
|
</div>"
|
|
82
91
|
`;
|
|
83
92
|
|
|
84
93
|
exports[`FzFloating > should match snapshot 10`] = `
|
|
85
94
|
"<div>
|
|
86
95
|
<div class="inline-flex"><button>opener</button></div>
|
|
87
|
-
<div class="bg-core-white
|
|
96
|
+
<div class="fz__floating__content bg-core-white fixed z-10 p-4 bg-core-white fixed p-4 z-10">
|
|
88
97
|
<div>content</div>
|
|
89
98
|
</div>
|
|
99
|
+
<!--v-if-->
|
|
90
100
|
</div>"
|
|
91
101
|
`;
|
|
92
102
|
|
|
93
103
|
exports[`FzFloating > should match snapshot 11`] = `
|
|
94
104
|
"<div>
|
|
95
105
|
<div class="inline-flex"><button>opener</button></div>
|
|
96
|
-
<div class="bg-core-white
|
|
106
|
+
<div class="fz__floating__content bg-core-white fixed z-10 p-4 bg-core-white fixed p-4 z-10">
|
|
97
107
|
<div>content</div>
|
|
98
108
|
</div>
|
|
109
|
+
<!--v-if-->
|
|
99
110
|
</div>"
|
|
100
111
|
`;
|
|
101
112
|
|
|
102
113
|
exports[`FzFloating > should match snapshot 12`] = `
|
|
103
114
|
"<div>
|
|
104
115
|
<div class="inline-flex"><button>opener</button></div>
|
|
105
|
-
<div class="bg-core-white
|
|
116
|
+
<div class="fz__floating__content bg-core-white fixed z-10 p-4 bg-core-white fixed p-4 z-10">
|
|
106
117
|
<div>content</div>
|
|
107
118
|
</div>
|
|
119
|
+
<!--v-if-->
|
|
108
120
|
</div>"
|
|
109
121
|
`;
|
package/src/composables/index.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { onBeforeUnmount, onMounted, Ref, watch } from 'vue'
|
|
2
2
|
|
|
3
3
|
function useClickOutside(
|
|
4
|
-
component: Ref<HTMLElement | undefined>,
|
|
4
|
+
component: Ref<HTMLElement | undefined>,
|
|
5
5
|
callback: () => void,
|
|
6
|
-
elementToListenClicksOn?: Ref<HTMLElement | undefined
|
|
6
|
+
elementToListenClicksOn?: Ref<HTMLElement | undefined>
|
|
7
7
|
) {
|
|
8
8
|
// fail early if any of the required params is missing
|
|
9
9
|
if (!component) {
|
|
@@ -14,7 +14,7 @@ function useClickOutside(
|
|
|
14
14
|
throw new Error('A callback has to be provided.')
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
const listener = (event:
|
|
17
|
+
const listener = (event: Event) => {
|
|
18
18
|
if (
|
|
19
19
|
!component.value ||
|
|
20
20
|
event.target === component.value ||
|
|
@@ -28,12 +28,15 @@ function useClickOutside(
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
if (elementToListenClicksOn) {
|
|
31
|
-
watch(
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
watch(
|
|
32
|
+
elementToListenClicksOn,
|
|
33
|
+
(newVal: Element | undefined, oldVal: Element | undefined) => {
|
|
34
|
+
if (oldVal) {
|
|
35
|
+
oldVal.removeEventListener('click', listener)
|
|
36
|
+
}
|
|
37
|
+
newVal?.addEventListener('click', listener)
|
|
34
38
|
}
|
|
35
|
-
|
|
36
|
-
});
|
|
39
|
+
)
|
|
37
40
|
}
|
|
38
41
|
|
|
39
42
|
onMounted(() => {
|
|
@@ -45,7 +48,7 @@ function useClickOutside(
|
|
|
45
48
|
onBeforeUnmount(() => {
|
|
46
49
|
if (elementToListenClicksOn) {
|
|
47
50
|
elementToListenClicksOn.value!.removeEventListener('click', listener)
|
|
48
|
-
return
|
|
51
|
+
return
|
|
49
52
|
}
|
|
50
53
|
document.removeEventListener('click', listener)
|
|
51
54
|
})
|
|
@@ -1,19 +1,25 @@
|
|
|
1
1
|
import { FzFloatingPosition, FzRect, FzUseFloatingArgs } from '../types'
|
|
2
|
-
import { ref, reactive, onUnmounted, Ref, nextTick
|
|
2
|
+
import { ref, reactive, onUnmounted, Ref, nextTick } from 'vue'
|
|
3
3
|
import { calcRealPos, getHighestAvailableSpacePos } from '../utils'
|
|
4
4
|
|
|
5
5
|
export const useFloating = (
|
|
6
6
|
args: FzUseFloatingArgs
|
|
7
7
|
): {
|
|
8
8
|
float: FzRect
|
|
9
|
-
rect: Ref<DOMRect |
|
|
10
|
-
floatObserver: Ref<IntersectionObserver>
|
|
9
|
+
rect: Ref<DOMRect | undefined>
|
|
11
10
|
setPosition: () => Promise<void>
|
|
11
|
+
position: Ref<FzFloatingPosition>
|
|
12
|
+
actualPosition?: Ref<FzFloatingPosition|undefined>
|
|
13
|
+
openerRect: Ref<DOMRect | undefined>
|
|
14
|
+
containerRect: Ref<DOMRect | undefined>
|
|
12
15
|
} => {
|
|
13
16
|
const safeElementDomRef = ref<HTMLElement | null>(null)
|
|
14
17
|
const safeContainerDomRef = ref<HTMLElement | null>(null)
|
|
15
18
|
const safeOpenerDomRef = ref<HTMLElement | null>(null)
|
|
16
|
-
const
|
|
19
|
+
const openerRect = ref<DOMRect | undefined>()
|
|
20
|
+
const containerRect = ref<DOMRect | undefined>()
|
|
21
|
+
const position = ref<FzFloatingPosition>('auto')
|
|
22
|
+
const rect = ref<DOMRect | undefined>()
|
|
17
23
|
const float = reactive<FzRect>({
|
|
18
24
|
position: { x: 0, y: 0 }
|
|
19
25
|
})
|
|
@@ -30,20 +36,23 @@ export const useFloating = (
|
|
|
30
36
|
) => {}
|
|
31
37
|
|
|
32
38
|
const floatObserver = ref(new IntersectionObserver(handleIntersect, options))
|
|
39
|
+
const actualPosition = ref<FzFloatingPosition>();
|
|
40
|
+
|
|
33
41
|
|
|
34
42
|
const setPosition = () =>
|
|
35
43
|
nextTick(() => {
|
|
44
|
+
actualPosition.value = args.position ? args.position.value : 'auto';
|
|
36
45
|
safeElementDomRef.value =
|
|
37
|
-
typeof args.element.domRef.value === 'string'
|
|
38
|
-
? document.querySelector(args.element.domRef.value)
|
|
39
|
-
: args.element.domRef.value
|
|
46
|
+
(typeof args.element.domRef.value === 'string'
|
|
47
|
+
? document.querySelector(args.element.domRef.value)
|
|
48
|
+
: args.element.domRef.value) as HTMLElement
|
|
40
49
|
if (!args.container) {
|
|
41
50
|
safeContainerDomRef.value = document.body
|
|
42
51
|
} else {
|
|
43
52
|
safeContainerDomRef.value =
|
|
44
|
-
typeof args.container.domRef.value === 'string'
|
|
53
|
+
(typeof args.container.domRef.value === 'string'
|
|
45
54
|
? document.querySelector(args.container.domRef.value)
|
|
46
|
-
: args.container.domRef.value
|
|
55
|
+
: args.container.domRef.value) as HTMLElement
|
|
47
56
|
safeContainerDomRef.value ??= document.body
|
|
48
57
|
}
|
|
49
58
|
|
|
@@ -53,77 +62,102 @@ export const useFloating = (
|
|
|
53
62
|
|
|
54
63
|
if (args.opener) {
|
|
55
64
|
safeOpenerDomRef.value =
|
|
56
|
-
typeof args.opener.domRef.value === 'string'
|
|
65
|
+
(typeof args.opener.domRef.value === 'string'
|
|
57
66
|
? document.querySelector(args.opener.domRef.value)
|
|
58
|
-
: args.opener.domRef.value
|
|
67
|
+
: args.opener.domRef.value) as HTMLElement
|
|
59
68
|
}
|
|
60
69
|
|
|
61
70
|
rect.value = safeElementDomRef.value.getBoundingClientRect()
|
|
62
|
-
|
|
63
|
-
|
|
71
|
+
openerRect.value = safeOpenerDomRef.value?.getBoundingClientRect()
|
|
72
|
+
containerRect.value = safeContainerDomRef.value.getBoundingClientRect()
|
|
64
73
|
|
|
65
|
-
const elStyle = window.getComputedStyle(safeElementDomRef.value)
|
|
74
|
+
const elStyle = window.getComputedStyle(safeElementDomRef.value as HTMLElement)
|
|
66
75
|
|
|
67
76
|
// multiple observer calls on same target do not cause multiple registrations
|
|
68
|
-
floatObserver.value.observe(safeElementDomRef.value)
|
|
69
|
-
floatObserver.value.observe(safeContainerDomRef.value)
|
|
70
|
-
|
|
71
|
-
let position: FzFloatingPosition = args.position ? args.position.value : 'auto'
|
|
77
|
+
floatObserver.value.observe(safeElementDomRef.value as HTMLElement)
|
|
78
|
+
floatObserver.value.observe(safeContainerDomRef.value as HTMLElement)
|
|
72
79
|
|
|
73
80
|
let translateY = 0
|
|
74
81
|
let translateX = 0
|
|
75
82
|
|
|
76
|
-
if (args.opener && safeOpenerDomRef.value && openerRect) {
|
|
83
|
+
if (args.opener && safeOpenerDomRef.value && openerRect && openerRect.value) {
|
|
77
84
|
const leftWithoutXMargin =
|
|
78
|
-
openerRect.left - parseFloat(elStyle.marginLeft) - parseFloat(elStyle.marginRight)
|
|
79
|
-
const leftWithoutLeftMargin = openerRect.left - parseFloat(elStyle.marginLeft)
|
|
85
|
+
openerRect.value.left - parseFloat(elStyle.marginLeft) - parseFloat(elStyle.marginRight)
|
|
86
|
+
const leftWithoutLeftMargin = openerRect.value.left - parseFloat(elStyle.marginLeft)
|
|
80
87
|
const topWithoutYMargin =
|
|
81
|
-
openerRect.top - parseFloat(elStyle.marginTop) - parseFloat(elStyle.marginBottom)
|
|
82
|
-
const topWithoutTopMargin = openerRect.top - parseFloat(elStyle.marginTop)
|
|
88
|
+
openerRect.value.top - parseFloat(elStyle.marginTop) - parseFloat(elStyle.marginBottom)
|
|
89
|
+
const topWithoutTopMargin = openerRect.value.top - parseFloat(elStyle.marginTop)
|
|
83
90
|
|
|
84
|
-
switch (
|
|
91
|
+
switch (actualPosition.value) {
|
|
85
92
|
case 'auto':
|
|
86
|
-
|
|
87
|
-
safeContainerDomRef.value,
|
|
88
|
-
safeElementDomRef.value,
|
|
89
|
-
safeOpenerDomRef.value
|
|
93
|
+
actualPosition.value = getHighestAvailableSpacePos(
|
|
94
|
+
args.useViewport ? null : safeContainerDomRef.value as HTMLElement,
|
|
95
|
+
safeElementDomRef.value as HTMLElement,
|
|
96
|
+
safeOpenerDomRef.value as HTMLElement
|
|
97
|
+
)
|
|
98
|
+
break
|
|
99
|
+
case 'auto-vertical':
|
|
100
|
+
actualPosition.value = getHighestAvailableSpacePos(
|
|
101
|
+
args.useViewport ? null : safeContainerDomRef.value as HTMLElement,
|
|
102
|
+
safeElementDomRef.value as HTMLElement,
|
|
103
|
+
safeOpenerDomRef.value as HTMLElement,
|
|
104
|
+
undefined,
|
|
105
|
+
true
|
|
90
106
|
)
|
|
91
107
|
break
|
|
92
108
|
case 'auto-start':
|
|
93
|
-
|
|
94
|
-
safeContainerDomRef.value,
|
|
95
|
-
safeElementDomRef.value,
|
|
96
|
-
safeOpenerDomRef.value,
|
|
109
|
+
actualPosition.value = getHighestAvailableSpacePos(
|
|
110
|
+
args.useViewport ? null : safeContainerDomRef.value as HTMLElement,
|
|
111
|
+
safeElementDomRef.value as HTMLElement,
|
|
112
|
+
safeOpenerDomRef.value as HTMLElement,
|
|
97
113
|
'start'
|
|
98
114
|
)
|
|
99
115
|
break
|
|
116
|
+
case 'auto-vertical-start':
|
|
117
|
+
actualPosition.value = getHighestAvailableSpacePos(
|
|
118
|
+
args.useViewport ? null : safeContainerDomRef.value as HTMLElement,
|
|
119
|
+
safeElementDomRef.value as HTMLElement,
|
|
120
|
+
safeOpenerDomRef.value as HTMLElement,
|
|
121
|
+
'start',
|
|
122
|
+
true
|
|
123
|
+
)
|
|
124
|
+
break
|
|
100
125
|
case 'auto-end':
|
|
101
|
-
|
|
102
|
-
safeContainerDomRef.value,
|
|
103
|
-
safeElementDomRef.value,
|
|
104
|
-
safeOpenerDomRef.value,
|
|
126
|
+
actualPosition.value = getHighestAvailableSpacePos(
|
|
127
|
+
args.useViewport ? null : safeContainerDomRef.value as HTMLElement,
|
|
128
|
+
safeElementDomRef.value as HTMLElement,
|
|
129
|
+
safeOpenerDomRef.value as HTMLElement,
|
|
105
130
|
'end'
|
|
106
131
|
)
|
|
107
132
|
break
|
|
133
|
+
case 'auto-vertical-end':
|
|
134
|
+
actualPosition.value = getHighestAvailableSpacePos(
|
|
135
|
+
args.useViewport ? null : safeContainerDomRef.value as HTMLElement,
|
|
136
|
+
safeElementDomRef.value as HTMLElement,
|
|
137
|
+
safeOpenerDomRef.value as HTMLElement,
|
|
138
|
+
'end',
|
|
139
|
+
true
|
|
140
|
+
)
|
|
141
|
+
break
|
|
108
142
|
default:
|
|
109
143
|
break
|
|
110
144
|
}
|
|
111
|
-
switch (
|
|
145
|
+
switch (actualPosition.value) {
|
|
112
146
|
case 'bottom':
|
|
113
|
-
float.position.y = openerRect.bottom
|
|
114
|
-
float.position.x = leftWithoutLeftMargin + openerRect.width / 2
|
|
147
|
+
float.position.y = openerRect.value.bottom
|
|
148
|
+
float.position.x = leftWithoutLeftMargin + openerRect.value.width / 2
|
|
115
149
|
translateX = -50
|
|
116
150
|
translateY = 0
|
|
117
151
|
break
|
|
118
152
|
case 'bottom-start':
|
|
119
|
-
float.position.y = openerRect.bottom
|
|
153
|
+
float.position.y = openerRect.value.bottom
|
|
120
154
|
float.position.x = leftWithoutXMargin
|
|
121
155
|
translateX = 0
|
|
122
156
|
translateY = 0
|
|
123
157
|
break
|
|
124
158
|
case 'bottom-end':
|
|
125
|
-
float.position.y = openerRect.bottom
|
|
126
|
-
float.position.x = openerRect.right
|
|
159
|
+
float.position.y = openerRect.value.bottom
|
|
160
|
+
float.position.x = openerRect.value.right
|
|
127
161
|
translateX = -100
|
|
128
162
|
translateY = 0
|
|
129
163
|
break
|
|
@@ -134,13 +168,13 @@ export const useFloating = (
|
|
|
134
168
|
translateY = 0
|
|
135
169
|
break
|
|
136
170
|
case 'left':
|
|
137
|
-
float.position.y = topWithoutTopMargin + openerRect.height / 2
|
|
171
|
+
float.position.y = topWithoutTopMargin + openerRect.value.height / 2
|
|
138
172
|
float.position.x = leftWithoutXMargin
|
|
139
173
|
translateY = -50
|
|
140
174
|
translateX = -100
|
|
141
175
|
break
|
|
142
176
|
case 'left-end':
|
|
143
|
-
float.position.y = openerRect.bottom
|
|
177
|
+
float.position.y = openerRect.value.bottom
|
|
144
178
|
float.position.x = leftWithoutXMargin
|
|
145
179
|
translateY = -100
|
|
146
180
|
translateX = -100
|
|
@@ -153,31 +187,31 @@ export const useFloating = (
|
|
|
153
187
|
break
|
|
154
188
|
case 'top':
|
|
155
189
|
float.position.y = topWithoutYMargin
|
|
156
|
-
float.position.x = leftWithoutLeftMargin + openerRect.width / 2
|
|
190
|
+
float.position.x = leftWithoutLeftMargin + openerRect.value.width / 2
|
|
157
191
|
translateX = -50
|
|
158
192
|
translateY = -100
|
|
159
193
|
break
|
|
160
194
|
case 'top-end':
|
|
161
195
|
float.position.y = topWithoutYMargin
|
|
162
|
-
float.position.x = openerRect.right
|
|
196
|
+
float.position.x = openerRect.value.right
|
|
163
197
|
translateX = -100
|
|
164
198
|
translateY = -100
|
|
165
199
|
break
|
|
166
200
|
case 'right-start':
|
|
167
201
|
float.position.y = topWithoutYMargin
|
|
168
|
-
float.position.x = openerRect.right
|
|
202
|
+
float.position.x = openerRect.value.right
|
|
169
203
|
translateX = 0
|
|
170
204
|
translateY = 0
|
|
171
205
|
break
|
|
172
206
|
case 'right':
|
|
173
|
-
float.position.y = topWithoutTopMargin + openerRect.height / 2
|
|
174
|
-
float.position.x = openerRect.right
|
|
207
|
+
float.position.y = topWithoutTopMargin + openerRect.value.height / 2
|
|
208
|
+
float.position.x = openerRect.value.right
|
|
175
209
|
translateY = -50
|
|
176
210
|
translateX = 0
|
|
177
211
|
break
|
|
178
212
|
case 'right-end':
|
|
179
|
-
float.position.y = openerRect.bottom
|
|
180
|
-
float.position.x = openerRect.right
|
|
213
|
+
float.position.y = openerRect.value.bottom
|
|
214
|
+
float.position.x = openerRect.value.right
|
|
181
215
|
translateY = -100
|
|
182
216
|
translateX = 0
|
|
183
217
|
break
|
|
@@ -185,42 +219,45 @@ export const useFloating = (
|
|
|
185
219
|
break
|
|
186
220
|
}
|
|
187
221
|
} else {
|
|
188
|
-
switch (
|
|
222
|
+
switch (actualPosition.value) {
|
|
189
223
|
case 'bottom':
|
|
190
|
-
float.position.y = containerRect.bottom - rect.value.height
|
|
191
|
-
float.position.x = containerRect.left + containerRect.width / 2
|
|
224
|
+
float.position.y = containerRect.value.bottom - rect.value.height
|
|
225
|
+
float.position.x = containerRect.value.left + containerRect.value.width / 2
|
|
192
226
|
translateX = -50
|
|
193
227
|
break
|
|
194
228
|
case 'left-end':
|
|
195
229
|
case 'bottom-start':
|
|
196
|
-
float.position.y = containerRect.bottom - rect.value.height
|
|
197
|
-
float.position.x = containerRect.left
|
|
230
|
+
float.position.y = containerRect.value.bottom - rect.value.height
|
|
231
|
+
float.position.x = containerRect.value.left
|
|
198
232
|
break
|
|
199
233
|
case 'right-end':
|
|
200
234
|
case 'bottom-end':
|
|
201
|
-
float.position.y = containerRect.bottom - rect.value.height
|
|
202
|
-
float.position.x = containerRect.right - rect.value.width
|
|
235
|
+
float.position.y = containerRect.value.bottom - rect.value.height
|
|
236
|
+
float.position.x = containerRect.value.right - rect.value.width
|
|
203
237
|
break
|
|
204
238
|
case 'left':
|
|
205
|
-
float.position.y =
|
|
206
|
-
|
|
239
|
+
float.position.y =
|
|
240
|
+
containerRect.value.top + (containerRect.value.height - rect.value.height) / 2
|
|
241
|
+
float.position.x = containerRect.value.left
|
|
207
242
|
break
|
|
208
243
|
case 'top-start':
|
|
209
244
|
case 'left-start':
|
|
210
|
-
float.position.y = containerRect.top
|
|
211
|
-
float.position.x = containerRect.left
|
|
245
|
+
float.position.y = containerRect.value.top
|
|
246
|
+
float.position.x = containerRect.value.left
|
|
212
247
|
break
|
|
213
248
|
case 'top':
|
|
214
|
-
float.position.y = containerRect.top
|
|
215
|
-
float.position.x =
|
|
249
|
+
float.position.y = containerRect.value.top
|
|
250
|
+
float.position.x =
|
|
251
|
+
containerRect.value.left + (containerRect.value.width - rect.value.width) / 2
|
|
216
252
|
break
|
|
217
253
|
case 'top-end':
|
|
218
254
|
case 'right-start':
|
|
219
|
-
float.position.y = containerRect.top
|
|
220
|
-
float.position.x = containerRect.right - rect.value.width
|
|
255
|
+
float.position.y = containerRect.value.top
|
|
256
|
+
float.position.x = containerRect.value.right - rect.value.width
|
|
221
257
|
case 'right':
|
|
222
|
-
float.position.y =
|
|
223
|
-
|
|
258
|
+
float.position.y =
|
|
259
|
+
containerRect.value.top + (containerRect.value.height - rect.value.height) / 2
|
|
260
|
+
float.position.x = containerRect.value.right - rect.value.width
|
|
224
261
|
break
|
|
225
262
|
default:
|
|
226
263
|
break
|
|
@@ -232,32 +269,40 @@ export const useFloating = (
|
|
|
232
269
|
float.position.x = realPos.x
|
|
233
270
|
float.position.y = realPos.y
|
|
234
271
|
|
|
235
|
-
if (realPos.x < containerRect.left) {
|
|
236
|
-
float.position.x = containerRect.left
|
|
272
|
+
if (realPos.x < containerRect.value.left) {
|
|
273
|
+
float.position.x = containerRect.value.left
|
|
237
274
|
translateX = 0
|
|
238
275
|
}
|
|
239
276
|
|
|
240
|
-
if (realPos.x + rect.value.width > containerRect.right) {
|
|
241
|
-
|
|
277
|
+
if (realPos.x + rect.value.width > containerRect.value.right) {
|
|
278
|
+
const fixVal = containerRect.value.right - rect.value.width
|
|
279
|
+
if (fixVal > 0) {
|
|
280
|
+
float.position.x = fixVal
|
|
281
|
+
}
|
|
242
282
|
translateX = 0
|
|
243
283
|
}
|
|
244
284
|
|
|
245
|
-
if (realPos.y < containerRect.top) {
|
|
246
|
-
float.position.y = containerRect.top
|
|
285
|
+
if (realPos.y < containerRect.value.top) {
|
|
286
|
+
float.position.y = containerRect.value.top
|
|
247
287
|
translateY = 0
|
|
248
288
|
}
|
|
249
289
|
|
|
250
|
-
if (realPos.y + rect.value.height > containerRect.bottom) {
|
|
251
|
-
|
|
290
|
+
if (realPos.y + rect.value.height > containerRect.value.bottom) {
|
|
291
|
+
const fixVal = containerRect.value.bottom - rect.value.height
|
|
292
|
+
if (fixVal > 0) {
|
|
293
|
+
float.position.y = fixVal
|
|
294
|
+
}
|
|
252
295
|
translateY = 0
|
|
253
296
|
}
|
|
254
297
|
|
|
255
298
|
safeElementDomRef.value.style.top = `${float.position.y}px`
|
|
256
299
|
safeElementDomRef.value.style.left = `${float.position.x}px`
|
|
257
|
-
|
|
300
|
+
safeElementDomRef.value.style.position = 'fixed'
|
|
258
301
|
safeElementDomRef.value.style.display = 'flex'
|
|
259
302
|
|
|
260
303
|
rect.value = safeElementDomRef.value.getBoundingClientRect()
|
|
304
|
+
|
|
305
|
+
args.callback && args.callback(rect, openerRect, containerRect, position, actualPosition)
|
|
261
306
|
})
|
|
262
307
|
|
|
263
308
|
onUnmounted(() => {
|
|
@@ -267,7 +312,10 @@ export const useFloating = (
|
|
|
267
312
|
return {
|
|
268
313
|
float,
|
|
269
314
|
rect,
|
|
270
|
-
|
|
271
|
-
|
|
315
|
+
setPosition,
|
|
316
|
+
position,
|
|
317
|
+
actualPosition,
|
|
318
|
+
openerRect,
|
|
319
|
+
containerRect
|
|
272
320
|
}
|
|
273
321
|
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { onBeforeUnmount, onMounted, Ref } from 'vue'
|
|
2
2
|
|
|
3
|
-
function useKeyDown(
|
|
3
|
+
function useKeyDown(
|
|
4
|
+
component: Ref<HTMLElement | undefined>,
|
|
5
|
+
callback: (event: KeyboardEvent) => void
|
|
6
|
+
) {
|
|
4
7
|
// fail early if any of the required params is missing
|
|
5
8
|
if (!component) {
|
|
6
9
|
throw new Error('A target component has to be provided.')
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { onBeforeUnmount, onMounted, Ref } from 'vue'
|
|
2
2
|
|
|
3
|
-
function useKeyUp(
|
|
4
|
-
|
|
3
|
+
function useKeyUp(
|
|
4
|
+
callback: (event: KeyboardEvent) => void,
|
|
5
|
+
component?: Ref<HTMLElement | undefined>
|
|
6
|
+
) {
|
|
5
7
|
if (!callback || typeof callback !== 'function') {
|
|
6
8
|
throw new Error('A callback has to be provided.')
|
|
7
9
|
}
|
|
@@ -13,7 +15,7 @@ function useKeyUp(callback: (event: KeyboardEvent) => void, component?: Ref<HTML
|
|
|
13
15
|
onMounted(() => {
|
|
14
16
|
if (!component) {
|
|
15
17
|
document.addEventListener('keyup', listener)
|
|
16
|
-
return
|
|
18
|
+
return
|
|
17
19
|
}
|
|
18
20
|
component.value!.addEventListener('keyup', listener)
|
|
19
21
|
})
|
|
@@ -21,7 +23,7 @@ function useKeyUp(callback: (event: KeyboardEvent) => void, component?: Ref<HTML
|
|
|
21
23
|
onBeforeUnmount(() => {
|
|
22
24
|
if (!component) {
|
|
23
25
|
document.removeEventListener('keyup', listener)
|
|
24
|
-
return
|
|
26
|
+
return
|
|
25
27
|
}
|
|
26
28
|
component.value!.removeEventListener('keyup', listener)
|
|
27
29
|
})
|
package/src/types.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Ref } from 'vue'
|
|
2
2
|
|
|
3
|
-
type PositionPrimary = 'bottom' | 'left' | 'top' | 'right' | 'auto'
|
|
3
|
+
type PositionPrimary = 'bottom' | 'left' | 'top' | 'right' | 'auto' | 'auto-vertical'
|
|
4
4
|
type PositionSecondary = 'start' | 'end'
|
|
5
5
|
export type FzFloatingPosition = PositionPrimary | `${PositionPrimary}-${PositionSecondary}`
|
|
6
6
|
|
|
@@ -20,6 +20,7 @@ export interface FzFloatingProps {
|
|
|
20
20
|
| Array<string | Record<string, boolean | undefined>>
|
|
21
21
|
overrideContentClass?: boolean
|
|
22
22
|
teleport?: boolean
|
|
23
|
+
useViewport?: boolean
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
export interface FzAbsolutePosition {
|
|
@@ -40,4 +41,12 @@ export interface FzUseFloatingArgs {
|
|
|
40
41
|
container?: FzFloatElement
|
|
41
42
|
opener?: FzFloatElement
|
|
42
43
|
position?: Ref<FzFloatingPosition>
|
|
44
|
+
useViewport?: Ref<boolean>
|
|
45
|
+
callback?: (
|
|
46
|
+
rect: Ref<DOMRect | undefined>,
|
|
47
|
+
openerRect: Ref<DOMRect | undefined>,
|
|
48
|
+
containerRect: Ref<DOMRect | undefined>,
|
|
49
|
+
position: Ref<FzFloatingPosition>,
|
|
50
|
+
actualPosition: Ref<FzFloatingPosition|undefined>
|
|
51
|
+
) => void
|
|
43
52
|
}
|
package/src/utils/index.ts
CHANGED
|
@@ -5,18 +5,23 @@ interface PositionListItem {
|
|
|
5
5
|
key: MainPosition
|
|
6
6
|
space: number
|
|
7
7
|
}
|
|
8
|
-
|
|
8
|
+
const windowDOMrect = new DOMRect(0,0,window.innerWidth, window.innerHeight);
|
|
9
9
|
export const getHighestAvailableSpacePos = (
|
|
10
|
-
container: HTMLElement,
|
|
10
|
+
container: HTMLElement|null,
|
|
11
11
|
el: HTMLElement,
|
|
12
12
|
opener: HTMLElement,
|
|
13
|
-
justify?: 'start' | 'end'
|
|
13
|
+
justify?: 'start' | 'end',
|
|
14
|
+
verticalOnly?: boolean
|
|
14
15
|
): FzFloatingPosition => {
|
|
15
|
-
let mainPosition: MainPosition = 'right'
|
|
16
|
+
let mainPosition: MainPosition = verticalOnly ? 'bottom' : 'right'
|
|
16
17
|
|
|
17
|
-
let positionRes: FzFloatingPosition = 'right-start'
|
|
18
|
+
let positionRes: FzFloatingPosition = verticalOnly ? 'bottom-start' : 'right-start'
|
|
18
19
|
|
|
19
|
-
|
|
20
|
+
windowDOMrect.width = window.innerWidth;
|
|
21
|
+
windowDOMrect.height = window.innerHeight;
|
|
22
|
+
windowDOMrect.x = 0;
|
|
23
|
+
windowDOMrect.y = 0;
|
|
24
|
+
const containerRect = container ? container.getBoundingClientRect() : windowDOMrect;
|
|
20
25
|
const elRect = el.getBoundingClientRect()
|
|
21
26
|
const openerRect = opener.getBoundingClientRect()
|
|
22
27
|
|
|
@@ -29,7 +34,7 @@ export const getHighestAvailableSpacePos = (
|
|
|
29
34
|
const spaceBottomNormalized =
|
|
30
35
|
(containerRect.bottom - openerRect.bottom - elRect.height) / containerRect.height
|
|
31
36
|
|
|
32
|
-
|
|
37
|
+
let positionList = [
|
|
33
38
|
{
|
|
34
39
|
key: 'right',
|
|
35
40
|
space: spaceRightNormalized
|
|
@@ -48,6 +53,10 @@ export const getHighestAvailableSpacePos = (
|
|
|
48
53
|
} as PositionListItem
|
|
49
54
|
].sort((a, b) => b.space - a.space)
|
|
50
55
|
|
|
56
|
+
if (verticalOnly) {
|
|
57
|
+
positionList = positionList.filter((pos) => pos.key === 'top' || pos.key === 'bottom')
|
|
58
|
+
}
|
|
59
|
+
|
|
51
60
|
mainPosition = positionList[0].key
|
|
52
61
|
|
|
53
62
|
if (!justify) {
|