@spscommerce/positioning 0.0.0-20260319-8230915ce

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/README.md ADDED
@@ -0,0 +1,48 @@
1
+ [//]: # "START_AUTOGENERATED"
2
+
3
+ ## [@spscommerce/positioning](https://github.com/spscommerce/design-system/tree/main/packages/@spscommerce/positioning#readme)
4
+
5
+ ![release: 1.1.0](https://img.shields.io/badge/release-1.1.0-blue.svg?style=flat-square)
6
+ ![build: passing](https://img.shields.io/badge/build-passing-green.svg?style=flat-square)
7
+ ![tests: failing](https://img.shields.io/badge/tests-failing-red.svg?style=flat-square)
8
+
9
+ Service for positioning dropdown/popup elements.
10
+
11
+ ### Installation
12
+
13
+ ```shell
14
+ npm install --save @spscommerce/positioning
15
+ ```
16
+
17
+ #### Peer Dependencies
18
+
19
+ <div class="row">
20
+ <div class="col-5">
21
+ <table class="sps-table">
22
+ <thead class="sps-table__head">
23
+ <tr class="sps-table__row">
24
+ <th class="sps-table__header">
25
+ <span class="sps-table__header-cell-body">
26
+ Package
27
+ </span>
28
+ </th>
29
+ <th class="sps-table__header text-right">
30
+ <span class="sps-table__header-cell-body">
31
+ Version
32
+ </span>
33
+ </th>
34
+ </tr>
35
+ </thead>
36
+ <tbody class="sps-table__body">
37
+ <tr class="sps-table__row"><td class="sps-table__cell"><a href="https://github.com/spscommerce/design-system/tree/main/packages/@spscommerce/utils#readme">@spscommerce/utils</a></td><td class="sps-table__cell text-right">^1.1.0</td></tr>
38
+ <tr class="sps-table__row"><td class="sps-table__cell"><a href="git://github.com/primus/eventemitter3.git">eventemitter3</a></td><td class="sps-table__cell text-right">^3.1.0</td></tr>
39
+ <tr class="sps-table__row"><td class="sps-table__cell"><a href="git@github.com:w3c/IntersectionObserver.git">intersection-observer</a></td><td class="sps-table__cell text-right">^0.5.1</td></tr>
40
+ </tbody>
41
+ </table>
42
+ </div>
43
+ <div class="col-7">
44
+ &nbsp;
45
+ </div>
46
+ </div>
47
+
48
+ [//]: # "END_AUTOGENERATED"
package/lib/index.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ export * from "./position.enum";
2
+ export * from "./position-anchor.enum";
3
+ export * from "./positioning-options.interface";
4
+ export * from "./positioning.service";
package/lib/index.js ADDED
@@ -0,0 +1,691 @@
1
+ import { onNextTick as U, lockedToAnimationFrames as j } from "@spscommerce/utils";
2
+ var S = /* @__PURE__ */ ((g) => (g.TOP_LEFT = "top left", g.TOP_MIDDLE = "top middle", g.TOP_RIGHT = "top right", g.RIGHT_TOP = "right top", g.RIGHT_MIDDLE = "right middle", g.RIGHT_BOTTOM = "right bottom", g.BOTTOM_RIGHT = "bottom right", g.BOTTOM_MIDDLE = "bottom middle", g.BOTTOM_LEFT = "bottom left", g.LEFT_BOTTOM = "left bottom", g.LEFT_MIDDLE = "left middle", g.LEFT_TOP = "left top", g))(S || {}), M = /* @__PURE__ */ ((g) => (g.TOP_LEFT = "top left", g.TOP_RIGHT = "top right", g.BOTTOM_LEFT = "bottom left", g.BOTTOM_RIGHT = "bottom right", g))(M || {});
3
+ const V = {
4
+ anchor: M.TOP_LEFT,
5
+ offsets: [],
6
+ position: S.TOP_LEFT
7
+ };
8
+ var A = {}, F;
9
+ function q() {
10
+ return F || (F = 1, function() {
11
+ if (typeof window != "object")
12
+ return;
13
+ if ("IntersectionObserver" in window && "IntersectionObserverEntry" in window && "intersectionRatio" in window.IntersectionObserverEntry.prototype) {
14
+ "isIntersecting" in window.IntersectionObserverEntry.prototype || Object.defineProperty(
15
+ window.IntersectionObserverEntry.prototype,
16
+ "isIntersecting",
17
+ {
18
+ get: function() {
19
+ return this.intersectionRatio > 0;
20
+ }
21
+ }
22
+ );
23
+ return;
24
+ }
25
+ function g(t) {
26
+ try {
27
+ return t.defaultView && t.defaultView.frameElement || null;
28
+ } catch {
29
+ return null;
30
+ }
31
+ }
32
+ var n = function(t) {
33
+ for (var e = t, o = g(e); o; )
34
+ e = o.ownerDocument, o = g(e);
35
+ return e;
36
+ }(window.document), i = [], p = null, f = null;
37
+ function w(t) {
38
+ this.time = t.time, this.target = t.target, this.rootBounds = b(t.rootBounds), this.boundingClientRect = b(t.boundingClientRect), this.intersectionRect = b(t.intersectionRect || y()), this.isIntersecting = !!t.intersectionRect;
39
+ var e = this.boundingClientRect, o = e.width * e.height, s = this.intersectionRect, u = s.width * s.height;
40
+ o ? this.intersectionRatio = Number((u / o).toFixed(4)) : this.intersectionRatio = this.isIntersecting ? 1 : 0;
41
+ }
42
+ function a(t, e) {
43
+ var o = e || {};
44
+ if (typeof t != "function")
45
+ throw new Error("callback must be a function");
46
+ if (o.root && o.root.nodeType != 1 && o.root.nodeType != 9)
47
+ throw new Error("root must be a Document or Element");
48
+ this._checkForIntersections = d(
49
+ this._checkForIntersections.bind(this),
50
+ this.THROTTLE_TIMEOUT
51
+ ), this._callback = t, this._observationTargets = [], this._queuedEntries = [], this._rootMarginValues = this._parseRootMargin(o.rootMargin), this.thresholds = this._initThresholds(o.threshold), this.root = o.root || null, this.rootMargin = this._rootMarginValues.map(function(s) {
52
+ return s.value + s.unit;
53
+ }).join(" "), this._monitoringDocuments = [], this._monitoringUnsubscribes = [];
54
+ }
55
+ a.prototype.THROTTLE_TIMEOUT = 100, a.prototype.POLL_INTERVAL = null, a.prototype.USE_MUTATION_OBSERVER = !0, a._setupCrossOriginUpdater = function() {
56
+ return p || (p = function(t, e) {
57
+ !t || !e ? f = y() : f = x(t, e), i.forEach(function(o) {
58
+ o._checkForIntersections();
59
+ });
60
+ }), p;
61
+ }, a._resetCrossOriginUpdater = function() {
62
+ p = null, f = null;
63
+ }, a.prototype.observe = function(t) {
64
+ var e = this._observationTargets.some(function(o) {
65
+ return o.element == t;
66
+ });
67
+ if (!e) {
68
+ if (!(t && t.nodeType == 1))
69
+ throw new Error("target must be an Element");
70
+ this._registerInstance(), this._observationTargets.push({ element: t, entry: null }), this._monitorIntersections(t.ownerDocument), this._checkForIntersections();
71
+ }
72
+ }, a.prototype.unobserve = function(t) {
73
+ this._observationTargets = this._observationTargets.filter(function(e) {
74
+ return e.element != t;
75
+ }), this._unmonitorIntersections(t.ownerDocument), this._observationTargets.length == 0 && this._unregisterInstance();
76
+ }, a.prototype.disconnect = function() {
77
+ this._observationTargets = [], this._unmonitorAllIntersections(), this._unregisterInstance();
78
+ }, a.prototype.takeRecords = function() {
79
+ var t = this._queuedEntries.slice();
80
+ return this._queuedEntries = [], t;
81
+ }, a.prototype._initThresholds = function(t) {
82
+ var e = t || [0];
83
+ return Array.isArray(e) || (e = [e]), e.sort().filter(function(o, s, u) {
84
+ if (typeof o != "number" || isNaN(o) || o < 0 || o > 1)
85
+ throw new Error("threshold must be a number between 0 and 1 inclusively");
86
+ return o !== u[s - 1];
87
+ });
88
+ }, a.prototype._parseRootMargin = function(t) {
89
+ var e = t || "0px", o = e.split(/\s+/).map(function(s) {
90
+ var u = /^(-?\d*\.?\d+)(px|%)$/.exec(s);
91
+ if (!u)
92
+ throw new Error("rootMargin must be specified in pixels or percent");
93
+ return { value: parseFloat(u[1]), unit: u[2] };
94
+ });
95
+ return o[1] = o[1] || o[0], o[2] = o[2] || o[0], o[3] = o[3] || o[1], o;
96
+ }, a.prototype._monitorIntersections = function(t) {
97
+ var e = t.defaultView;
98
+ if (e && this._monitoringDocuments.indexOf(t) == -1) {
99
+ var o = this._checkForIntersections, s = null, u = null;
100
+ this.POLL_INTERVAL ? s = e.setInterval(o, this.POLL_INTERVAL) : (c(e, "resize", o, !0), c(t, "scroll", o, !0), this.USE_MUTATION_OBSERVER && "MutationObserver" in e && (u = new e.MutationObserver(o), u.observe(t, {
101
+ attributes: !0,
102
+ childList: !0,
103
+ characterData: !0,
104
+ subtree: !0
105
+ }))), this._monitoringDocuments.push(t), this._monitoringUnsubscribes.push(function() {
106
+ var I = t.defaultView;
107
+ I && (s && I.clearInterval(s), l(I, "resize", o, !0)), l(t, "scroll", o, !0), u && u.disconnect();
108
+ });
109
+ var O = this.root && (this.root.ownerDocument || this.root) || n;
110
+ if (t != O) {
111
+ var E = g(t);
112
+ E && this._monitorIntersections(E.ownerDocument);
113
+ }
114
+ }
115
+ }, a.prototype._unmonitorIntersections = function(t) {
116
+ var e = this._monitoringDocuments.indexOf(t);
117
+ if (e != -1) {
118
+ var o = this.root && (this.root.ownerDocument || this.root) || n, s = this._observationTargets.some(function(E) {
119
+ var I = E.element.ownerDocument;
120
+ if (I == t)
121
+ return !0;
122
+ for (; I && I != o; ) {
123
+ var L = g(I);
124
+ if (I = L && L.ownerDocument, I == t)
125
+ return !0;
126
+ }
127
+ return !1;
128
+ });
129
+ if (!s) {
130
+ var u = this._monitoringUnsubscribes[e];
131
+ if (this._monitoringDocuments.splice(e, 1), this._monitoringUnsubscribes.splice(e, 1), u(), t != o) {
132
+ var O = g(t);
133
+ O && this._unmonitorIntersections(O.ownerDocument);
134
+ }
135
+ }
136
+ }
137
+ }, a.prototype._unmonitorAllIntersections = function() {
138
+ var t = this._monitoringUnsubscribes.slice(0);
139
+ this._monitoringDocuments.length = 0, this._monitoringUnsubscribes.length = 0;
140
+ for (var e = 0; e < t.length; e++)
141
+ t[e]();
142
+ }, a.prototype._checkForIntersections = function() {
143
+ if (!(!this.root && p && !f)) {
144
+ var t = this._rootIsInDom(), e = t ? this._getRootRect() : y();
145
+ this._observationTargets.forEach(function(o) {
146
+ var s = o.element, u = T(s), O = this._rootContainsTarget(s), E = o.entry, I = t && O && this._computeTargetAndRootIntersection(s, u, e), L = null;
147
+ this._rootContainsTarget(s) ? (!p || this.root) && (L = e) : L = y();
148
+ var D = o.entry = new w({
149
+ time: m(),
150
+ target: s,
151
+ boundingClientRect: u,
152
+ rootBounds: L,
153
+ intersectionRect: I
154
+ });
155
+ E ? t && O ? this._hasCrossedThreshold(E, D) && this._queuedEntries.push(D) : E && E.isIntersecting && this._queuedEntries.push(D) : this._queuedEntries.push(D);
156
+ }, this), this._queuedEntries.length && this._callback(this.takeRecords(), this);
157
+ }
158
+ }, a.prototype._computeTargetAndRootIntersection = function(t, e, o) {
159
+ if (window.getComputedStyle(t).display != "none") {
160
+ for (var s = e, u = _(t), O = !1; !O && u; ) {
161
+ var E = null, I = u.nodeType == 1 ? window.getComputedStyle(u) : {};
162
+ if (I.display == "none") return null;
163
+ if (u == this.root || u.nodeType == /* DOCUMENT */
164
+ 9)
165
+ if (O = !0, u == this.root || u == n)
166
+ p && !this.root ? !f || f.width == 0 && f.height == 0 ? (u = null, E = null, s = null) : E = f : E = o;
167
+ else {
168
+ var L = _(u), D = L && T(L), B = L && this._computeTargetAndRootIntersection(L, D, o);
169
+ D && B ? (u = L, E = x(D, B)) : (u = null, s = null);
170
+ }
171
+ else {
172
+ var C = u.ownerDocument;
173
+ u != C.body && u != C.documentElement && I.overflow != "visible" && (E = T(u));
174
+ }
175
+ if (E && (s = v(E, s)), !s) break;
176
+ u = u && _(u);
177
+ }
178
+ return s;
179
+ }
180
+ }, a.prototype._getRootRect = function() {
181
+ var t;
182
+ if (this.root && !R(this.root))
183
+ t = T(this.root);
184
+ else {
185
+ var e = R(this.root) ? this.root : n, o = e.documentElement, s = e.body;
186
+ t = {
187
+ top: 0,
188
+ left: 0,
189
+ right: o.clientWidth || s.clientWidth,
190
+ width: o.clientWidth || s.clientWidth,
191
+ bottom: o.clientHeight || s.clientHeight,
192
+ height: o.clientHeight || s.clientHeight
193
+ };
194
+ }
195
+ return this._expandRectByRootMargin(t);
196
+ }, a.prototype._expandRectByRootMargin = function(t) {
197
+ var e = this._rootMarginValues.map(function(s, u) {
198
+ return s.unit == "px" ? s.value : s.value * (u % 2 ? t.width : t.height) / 100;
199
+ }), o = {
200
+ top: t.top - e[0],
201
+ right: t.right + e[1],
202
+ bottom: t.bottom + e[2],
203
+ left: t.left - e[3]
204
+ };
205
+ return o.width = o.right - o.left, o.height = o.bottom - o.top, o;
206
+ }, a.prototype._hasCrossedThreshold = function(t, e) {
207
+ var o = t && t.isIntersecting ? t.intersectionRatio || 0 : -1, s = e.isIntersecting ? e.intersectionRatio || 0 : -1;
208
+ if (o !== s)
209
+ for (var u = 0; u < this.thresholds.length; u++) {
210
+ var O = this.thresholds[u];
211
+ if (O == o || O == s || O < o != O < s)
212
+ return !0;
213
+ }
214
+ }, a.prototype._rootIsInDom = function() {
215
+ return !this.root || h(n, this.root);
216
+ }, a.prototype._rootContainsTarget = function(t) {
217
+ var e = this.root && (this.root.ownerDocument || this.root) || n;
218
+ return h(e, t) && (!this.root || e == t.ownerDocument);
219
+ }, a.prototype._registerInstance = function() {
220
+ i.indexOf(this) < 0 && i.push(this);
221
+ }, a.prototype._unregisterInstance = function() {
222
+ var t = i.indexOf(this);
223
+ t != -1 && i.splice(t, 1);
224
+ };
225
+ function m() {
226
+ return window.performance && performance.now && performance.now();
227
+ }
228
+ function d(t, e) {
229
+ var o = null;
230
+ return function() {
231
+ o || (o = setTimeout(function() {
232
+ t(), o = null;
233
+ }, e));
234
+ };
235
+ }
236
+ function c(t, e, o, s) {
237
+ typeof t.addEventListener == "function" ? t.addEventListener(e, o, s) : typeof t.attachEvent == "function" && t.attachEvent("on" + e, o);
238
+ }
239
+ function l(t, e, o, s) {
240
+ typeof t.removeEventListener == "function" ? t.removeEventListener(e, o, s) : typeof t.detatchEvent == "function" && t.detatchEvent("on" + e, o);
241
+ }
242
+ function v(t, e) {
243
+ var o = Math.max(t.top, e.top), s = Math.min(t.bottom, e.bottom), u = Math.max(t.left, e.left), O = Math.min(t.right, e.right), E = O - u, I = s - o;
244
+ return E >= 0 && I >= 0 && {
245
+ top: o,
246
+ bottom: s,
247
+ left: u,
248
+ right: O,
249
+ width: E,
250
+ height: I
251
+ } || null;
252
+ }
253
+ function T(t) {
254
+ var e;
255
+ try {
256
+ e = t.getBoundingClientRect();
257
+ } catch {
258
+ }
259
+ return e ? (e.width && e.height || (e = {
260
+ top: e.top,
261
+ right: e.right,
262
+ bottom: e.bottom,
263
+ left: e.left,
264
+ width: e.right - e.left,
265
+ height: e.bottom - e.top
266
+ }), e) : y();
267
+ }
268
+ function y() {
269
+ return {
270
+ top: 0,
271
+ bottom: 0,
272
+ left: 0,
273
+ right: 0,
274
+ width: 0,
275
+ height: 0
276
+ };
277
+ }
278
+ function b(t) {
279
+ return !t || "x" in t ? t : {
280
+ top: t.top,
281
+ y: t.top,
282
+ bottom: t.bottom,
283
+ left: t.left,
284
+ x: t.left,
285
+ right: t.right,
286
+ width: t.width,
287
+ height: t.height
288
+ };
289
+ }
290
+ function x(t, e) {
291
+ var o = e.top - t.top, s = e.left - t.left;
292
+ return {
293
+ top: o,
294
+ left: s,
295
+ height: e.height,
296
+ width: e.width,
297
+ bottom: o + e.height,
298
+ right: s + e.width
299
+ };
300
+ }
301
+ function h(t, e) {
302
+ for (var o = e; o; ) {
303
+ if (o == t) return !0;
304
+ o = _(o);
305
+ }
306
+ return !1;
307
+ }
308
+ function _(t) {
309
+ var e = t.parentNode;
310
+ return t.nodeType == /* DOCUMENT */
311
+ 9 && t != n ? g(t) : (e && e.assignedSlot && (e = e.assignedSlot.parentNode), e && e.nodeType == 11 && e.host ? e.host : e);
312
+ }
313
+ function R(t) {
314
+ return t && t.nodeType === 9;
315
+ }
316
+ window.IntersectionObserver = a, window.IntersectionObserverEntry = w;
317
+ }()), A;
318
+ }
319
+ q();
320
+ var P = { exports: {} }, H;
321
+ function G() {
322
+ return H || (H = 1, function(g) {
323
+ var n = Object.prototype.hasOwnProperty, i = "~";
324
+ function p() {
325
+ }
326
+ Object.create && (p.prototype = /* @__PURE__ */ Object.create(null), new p().__proto__ || (i = !1));
327
+ function f(d, c, l) {
328
+ this.fn = d, this.context = c, this.once = l || !1;
329
+ }
330
+ function w(d, c, l, v, T) {
331
+ if (typeof l != "function")
332
+ throw new TypeError("The listener must be a function");
333
+ var y = new f(l, v || d, T), b = i ? i + c : c;
334
+ return d._events[b] ? d._events[b].fn ? d._events[b] = [d._events[b], y] : d._events[b].push(y) : (d._events[b] = y, d._eventsCount++), d;
335
+ }
336
+ function a(d, c) {
337
+ --d._eventsCount === 0 ? d._events = new p() : delete d._events[c];
338
+ }
339
+ function m() {
340
+ this._events = new p(), this._eventsCount = 0;
341
+ }
342
+ m.prototype.eventNames = function() {
343
+ var c = [], l, v;
344
+ if (this._eventsCount === 0) return c;
345
+ for (v in l = this._events)
346
+ n.call(l, v) && c.push(i ? v.slice(1) : v);
347
+ return Object.getOwnPropertySymbols ? c.concat(Object.getOwnPropertySymbols(l)) : c;
348
+ }, m.prototype.listeners = function(c) {
349
+ var l = i ? i + c : c, v = this._events[l];
350
+ if (!v) return [];
351
+ if (v.fn) return [v.fn];
352
+ for (var T = 0, y = v.length, b = new Array(y); T < y; T++)
353
+ b[T] = v[T].fn;
354
+ return b;
355
+ }, m.prototype.listenerCount = function(c) {
356
+ var l = i ? i + c : c, v = this._events[l];
357
+ return v ? v.fn ? 1 : v.length : 0;
358
+ }, m.prototype.emit = function(c, l, v, T, y, b) {
359
+ var x = i ? i + c : c;
360
+ if (!this._events[x]) return !1;
361
+ var h = this._events[x], _ = arguments.length, R, t;
362
+ if (h.fn) {
363
+ switch (h.once && this.removeListener(c, h.fn, void 0, !0), _) {
364
+ case 1:
365
+ return h.fn.call(h.context), !0;
366
+ case 2:
367
+ return h.fn.call(h.context, l), !0;
368
+ case 3:
369
+ return h.fn.call(h.context, l, v), !0;
370
+ case 4:
371
+ return h.fn.call(h.context, l, v, T), !0;
372
+ case 5:
373
+ return h.fn.call(h.context, l, v, T, y), !0;
374
+ case 6:
375
+ return h.fn.call(h.context, l, v, T, y, b), !0;
376
+ }
377
+ for (t = 1, R = new Array(_ - 1); t < _; t++)
378
+ R[t - 1] = arguments[t];
379
+ h.fn.apply(h.context, R);
380
+ } else {
381
+ var e = h.length, o;
382
+ for (t = 0; t < e; t++)
383
+ switch (h[t].once && this.removeListener(c, h[t].fn, void 0, !0), _) {
384
+ case 1:
385
+ h[t].fn.call(h[t].context);
386
+ break;
387
+ case 2:
388
+ h[t].fn.call(h[t].context, l);
389
+ break;
390
+ case 3:
391
+ h[t].fn.call(h[t].context, l, v);
392
+ break;
393
+ case 4:
394
+ h[t].fn.call(h[t].context, l, v, T);
395
+ break;
396
+ default:
397
+ if (!R) for (o = 1, R = new Array(_ - 1); o < _; o++)
398
+ R[o - 1] = arguments[o];
399
+ h[t].fn.apply(h[t].context, R);
400
+ }
401
+ }
402
+ return !0;
403
+ }, m.prototype.on = function(c, l, v) {
404
+ return w(this, c, l, v, !1);
405
+ }, m.prototype.once = function(c, l, v) {
406
+ return w(this, c, l, v, !0);
407
+ }, m.prototype.removeListener = function(c, l, v, T) {
408
+ var y = i ? i + c : c;
409
+ if (!this._events[y]) return this;
410
+ if (!l)
411
+ return a(this, y), this;
412
+ var b = this._events[y];
413
+ if (b.fn)
414
+ b.fn === l && (!T || b.once) && (!v || b.context === v) && a(this, y);
415
+ else {
416
+ for (var x = 0, h = [], _ = b.length; x < _; x++)
417
+ (b[x].fn !== l || T && !b[x].once || v && b[x].context !== v) && h.push(b[x]);
418
+ h.length ? this._events[y] = h.length === 1 ? h[0] : h : a(this, y);
419
+ }
420
+ return this;
421
+ }, m.prototype.removeAllListeners = function(c) {
422
+ var l;
423
+ return c ? (l = i ? i + c : c, this._events[l] && a(this, l)) : (this._events = new p(), this._eventsCount = 0), this;
424
+ }, m.prototype.off = m.prototype.removeListener, m.prototype.addListener = m.prototype.on, m.prefixed = i, m.EventEmitter = m, g.exports = m;
425
+ }(P)), P.exports;
426
+ }
427
+ var z = G(), W = Object.defineProperty, $ = Object.getOwnPropertyDescriptor, Y = (g, n, i, p) => {
428
+ for (var f = $(n, i), w = g.length - 1, a; w >= 0; w--)
429
+ (a = g[w]) && (f = a(n, i, f) || f);
430
+ return f && W(n, i, f), f;
431
+ };
432
+ const k = 60;
433
+ var r;
434
+ const N = (r = class {
435
+ static on(n, i) {
436
+ r.events.on(n, i);
437
+ }
438
+ static off(n, i) {
439
+ r.events.off(n, i);
440
+ }
441
+ static once(n, i) {
442
+ r.events.once(n, i);
443
+ }
444
+ static checkCollisions(n, i) {
445
+ const p = i || Array.from(r.elements.keys()), f = n.getBoundingClientRect(), w = [];
446
+ for (const a of p)
447
+ if (a !== n) {
448
+ const m = a.getBoundingClientRect();
449
+ m.left <= f.right && m.right >= f.left && m.top <= f.bottom && m.bottom >= f.top && w.push(a);
450
+ }
451
+ w.length && r.onElementIntersection(n, w);
452
+ }
453
+ /**
454
+ * Returns `true` if the element is currently being positioned by the service
455
+ * and `false` otherwise.
456
+ */
457
+ static isPositioned(n) {
458
+ return r.elements.has(n);
459
+ }
460
+ /**
461
+ * Returns the options currently beinng used for positioning the element,
462
+ * if it is indeed being positioned by the service.
463
+ */
464
+ static getPositioningOptions(n) {
465
+ return r.elements.has(n) ? r.elements.get(n) : null;
466
+ }
467
+ /** PositioningService will start controlling the position of the given element. */
468
+ static position(n, i = {}) {
469
+ const p = {
470
+ ...V,
471
+ ...i
472
+ };
473
+ let f = n;
474
+ for (; f !== document.body; )
475
+ if (f = f.parentElement, f.classList.contains("sps-focused-task")) {
476
+ p.scrollParent = f, r.registeredScrollParents.has(f) || (r.registeredScrollParents.add(f), f.addEventListener("scroll", r.update));
477
+ break;
478
+ }
479
+ if (n.style.visibility = "hidden", r.elements.size === 0 && (window.addEventListener("resize", r.update), window.addEventListener("scroll", r.update)), !p.relativeTo)
480
+ throw new Error(
481
+ "You must provide an element for the relativeTo option to position an element."
482
+ );
483
+ r.elements.set(n, p), U(() => {
484
+ r.fixElementPosition(n), r.viewportObserver.observe(n), n.style.visibility = "", r.checkCollisions(n);
485
+ });
486
+ }
487
+ /** PositioningService will stop controlling the position of the given element. */
488
+ static release(n) {
489
+ if (r.elements.has(n)) {
490
+ r.clearStyles(n);
491
+ const i = r.elements.get(n);
492
+ i.scrollParent && (i.scrollParent.removeEventListener("scroll", r.update), r.registeredScrollParents.delete(i.scrollParent)), r.elements.delete(n), r.elements.size === 0 && (window.removeEventListener("resize", r.update), window.removeEventListener("scroll", r.update)), r.viewportObserver.unobserve(n);
493
+ }
494
+ }
495
+ static releaseAll() {
496
+ for (const n of r.elements.keys())
497
+ r.release(n);
498
+ }
499
+ /** PositioningService will refresh the positioning of the given element */
500
+ static refresh(n) {
501
+ r.elements.has(n) && (r.clearStyles(n), r.fixElementPosition(n), r.checkCollisions(n));
502
+ }
503
+ static refreshAll() {
504
+ for (const n of r.elements.keys())
505
+ r.refresh(n);
506
+ }
507
+ /** Update the positioning options of a currently positioned element */
508
+ static reposition(n, i) {
509
+ if (r.elements.has(n)) {
510
+ const p = r.elements.get(n);
511
+ r.elements.set(n, Object.assign(p, i)), r.refresh(n);
512
+ }
513
+ }
514
+ static onViewportIntersection(n) {
515
+ for (const i of n) {
516
+ const p = Object.keys(IntersectionObserverEntry.prototype).reduce(
517
+ (f, w) => ({
518
+ ...f,
519
+ [w]: i[w]
520
+ }),
521
+ {}
522
+ );
523
+ p.rootBounds = p.rootBounds || r.getRootBounds(), r.events.emit("viewportIntersection", Object.freeze(p));
524
+ }
525
+ }
526
+ static onElementIntersection(n, i) {
527
+ r.events.emit("elementIntersection", { target: n, intersectingWith: i });
528
+ }
529
+ static getRootBounds() {
530
+ const n = Math.max(document.documentElement.clientWidth, window.innerWidth || 0), i = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
531
+ return {
532
+ x: 0,
533
+ y: k,
534
+ left: 0,
535
+ top: k,
536
+ right: n,
537
+ bottom: i,
538
+ height: i - k,
539
+ width: n
540
+ };
541
+ }
542
+ static clearStyles(n) {
543
+ Object.assign(n.style, {
544
+ position: "",
545
+ width: "",
546
+ top: "",
547
+ left: "",
548
+ right: "",
549
+ bottom: "",
550
+ visibility: "",
551
+ zIndex: ""
552
+ });
553
+ }
554
+ static fixElementPosition(n, i) {
555
+ if (!this.elements.has(n))
556
+ return;
557
+ const p = i || this.elements.get(n), f = this.getRootBounds(), w = n.getBoundingClientRect(), a = p.relativeTo.getBoundingClientRect(), { width: m } = p.useRelativeTargetWidth ? a : w;
558
+ Object.assign(n.style, {
559
+ minWidth: `${m}px`,
560
+ position: "fixed",
561
+ zIndex: p.zIndex || ""
562
+ });
563
+ let d, c;
564
+ const l = p.position.split(" "), v = p.offsets[0] || 0, T = p.offsets[1] || 0;
565
+ switch (d = 0, c = 0, l[0]) {
566
+ case "top":
567
+ d = a.top - w.height - v;
568
+ break;
569
+ case "left":
570
+ c = a.left - m - v;
571
+ break;
572
+ case "right":
573
+ c = a.right + v;
574
+ break;
575
+ case "bottom":
576
+ d = a.bottom + v;
577
+ break;
578
+ default:
579
+ throw new Error(`${p.position} is not a valid position`);
580
+ }
581
+ switch (l[1]) {
582
+ case "left":
583
+ c = a.left - T;
584
+ break;
585
+ case "top":
586
+ d = a.top - T;
587
+ break;
588
+ case "middle":
589
+ l[0] === "top" || l[0] === "bottom" ? c = a.left + a.width / 2 - m / 2 + T : (l[0] === "left" || l[0] === "right") && (d = a.top + a.height / 2 - w.height / 2 + T);
590
+ break;
591
+ case "bottom":
592
+ d = a.bottom - w.height + T;
593
+ break;
594
+ case "right":
595
+ c = a.right - m + T;
596
+ break;
597
+ default:
598
+ throw new Error(`${p.position} is not a valid position`);
599
+ }
600
+ const y = d + w.height, b = c + w.width, x = `${Math.round(d)}px`, h = `${Math.round(f.bottom - y)}px`, _ = `${Math.round(c)}px`, R = `${Math.round(f.right - b)}px`;
601
+ switch (p.anchor) {
602
+ case M.TOP_LEFT:
603
+ Object.assign(n.style, {
604
+ top: x,
605
+ bottom: "auto",
606
+ left: _,
607
+ right: "auto"
608
+ });
609
+ break;
610
+ case M.TOP_RIGHT:
611
+ Object.assign(n.style, {
612
+ top: x,
613
+ bottom: "auto",
614
+ left: "auto",
615
+ right: R
616
+ });
617
+ break;
618
+ case M.BOTTOM_LEFT:
619
+ Object.assign(n.style, {
620
+ top: "auto",
621
+ bottom: h,
622
+ left: _,
623
+ right: "auto"
624
+ });
625
+ break;
626
+ case M.BOTTOM_RIGHT:
627
+ Object.assign(n.style, {
628
+ top: "auto",
629
+ bottom: h,
630
+ left: "auto",
631
+ right: R
632
+ });
633
+ break;
634
+ }
635
+ }
636
+ static update(n) {
637
+ const i = r.elements.entries(), p = [];
638
+ for (const [f, w] of i)
639
+ (!n || n.target === document || n.target === w.scrollParent || n.target === window) && (r.fixElementPosition(f, w), r.checkCollisions(f, p), p.push(f));
640
+ }
641
+ /* eslint class-methods-use-this: "off" */
642
+ on(n, i) {
643
+ r.on(n, i);
644
+ }
645
+ off(n, i) {
646
+ r.off(n, i);
647
+ }
648
+ once(n, i) {
649
+ r.once(n, i);
650
+ }
651
+ isPositioned(n) {
652
+ return r.isPositioned(n);
653
+ }
654
+ getPositioningOptions(n) {
655
+ return r.getPositioningOptions(n);
656
+ }
657
+ position(n, i = {}) {
658
+ r.position(n, i);
659
+ }
660
+ release(n) {
661
+ r.release(n);
662
+ }
663
+ releaseAll() {
664
+ r.releaseAll();
665
+ }
666
+ refresh(n) {
667
+ r.refresh(n);
668
+ }
669
+ refreshAll() {
670
+ r.refreshAll();
671
+ }
672
+ reposition(n, i) {
673
+ r.reposition(n, i);
674
+ }
675
+ }, r.elements = /* @__PURE__ */ new Map(), r.registeredScrollParents = /* @__PURE__ */ new Set(), r.events = new z.EventEmitter(), r.viewportObserver = new IntersectionObserver(
676
+ r.onViewportIntersection,
677
+ {
678
+ rootMargin: `-${k}px 0px 0px`,
679
+ threshold: 1
680
+ }
681
+ ), r);
682
+ Y([
683
+ j
684
+ ], N, "update");
685
+ let K = N;
686
+ export {
687
+ V as DEFAULT_POSITIONING_OPTIONS,
688
+ S as Position,
689
+ M as PositionAnchor,
690
+ K as PositioningService
691
+ };
@@ -0,0 +1 @@
1
+ (function(D,k){typeof exports=="object"&&typeof module<"u"?k(exports,require("@spscommerce/utils")):typeof define=="function"&&define.amd?define(["exports","@spscommerce/utils"],k):(D=typeof globalThis<"u"?globalThis:D||self,k(D.Positioning={},D.utils))})(this,function(D,k){"use strict";var r;var A=(g=>(g.TOP_LEFT="top left",g.TOP_MIDDLE="top middle",g.TOP_RIGHT="top right",g.RIGHT_TOP="right top",g.RIGHT_MIDDLE="right middle",g.RIGHT_BOTTOM="right bottom",g.BOTTOM_RIGHT="bottom right",g.BOTTOM_MIDDLE="bottom middle",g.BOTTOM_LEFT="bottom left",g.LEFT_BOTTOM="left bottom",g.LEFT_MIDDLE="left middle",g.LEFT_TOP="left top",g))(A||{}),P=(g=>(g.TOP_LEFT="top left",g.TOP_RIGHT="top right",g.BOTTOM_LEFT="bottom left",g.BOTTOM_RIGHT="bottom right",g))(P||{});const F={anchor:P.TOP_LEFT,offsets:[],position:A.TOP_LEFT};var S={},N;function q(){return N||(N=1,function(){if(typeof window!="object")return;if("IntersectionObserver"in window&&"IntersectionObserverEntry"in window&&"intersectionRatio"in window.IntersectionObserverEntry.prototype){"isIntersecting"in window.IntersectionObserverEntry.prototype||Object.defineProperty(window.IntersectionObserverEntry.prototype,"isIntersecting",{get:function(){return this.intersectionRatio>0}});return}function g(t){try{return t.defaultView&&t.defaultView.frameElement||null}catch{return null}}var n=function(t){for(var e=t,o=g(e);o;)e=o.ownerDocument,o=g(e);return e}(window.document),i=[],p=null,f=null;function w(t){this.time=t.time,this.target=t.target,this.rootBounds=b(t.rootBounds),this.boundingClientRect=b(t.boundingClientRect),this.intersectionRect=b(t.intersectionRect||y()),this.isIntersecting=!!t.intersectionRect;var e=this.boundingClientRect,o=e.width*e.height,s=this.intersectionRect,u=s.width*s.height;o?this.intersectionRatio=Number((u/o).toFixed(4)):this.intersectionRatio=this.isIntersecting?1:0}function a(t,e){var o=e||{};if(typeof t!="function")throw new Error("callback must be a function");if(o.root&&o.root.nodeType!=1&&o.root.nodeType!=9)throw new Error("root must be a Document or Element");this._checkForIntersections=d(this._checkForIntersections.bind(this),this.THROTTLE_TIMEOUT),this._callback=t,this._observationTargets=[],this._queuedEntries=[],this._rootMarginValues=this._parseRootMargin(o.rootMargin),this.thresholds=this._initThresholds(o.threshold),this.root=o.root||null,this.rootMargin=this._rootMarginValues.map(function(s){return s.value+s.unit}).join(" "),this._monitoringDocuments=[],this._monitoringUnsubscribes=[]}a.prototype.THROTTLE_TIMEOUT=100,a.prototype.POLL_INTERVAL=null,a.prototype.USE_MUTATION_OBSERVER=!0,a._setupCrossOriginUpdater=function(){return p||(p=function(t,e){!t||!e?f=y():f=R(t,e),i.forEach(function(o){o._checkForIntersections()})}),p},a._resetCrossOriginUpdater=function(){p=null,f=null},a.prototype.observe=function(t){var e=this._observationTargets.some(function(o){return o.element==t});if(!e){if(!(t&&t.nodeType==1))throw new Error("target must be an Element");this._registerInstance(),this._observationTargets.push({element:t,entry:null}),this._monitorIntersections(t.ownerDocument),this._checkForIntersections()}},a.prototype.unobserve=function(t){this._observationTargets=this._observationTargets.filter(function(e){return e.element!=t}),this._unmonitorIntersections(t.ownerDocument),this._observationTargets.length==0&&this._unregisterInstance()},a.prototype.disconnect=function(){this._observationTargets=[],this._unmonitorAllIntersections(),this._unregisterInstance()},a.prototype.takeRecords=function(){var t=this._queuedEntries.slice();return this._queuedEntries=[],t},a.prototype._initThresholds=function(t){var e=t||[0];return Array.isArray(e)||(e=[e]),e.sort().filter(function(o,s,u){if(typeof o!="number"||isNaN(o)||o<0||o>1)throw new Error("threshold must be a number between 0 and 1 inclusively");return o!==u[s-1]})},a.prototype._parseRootMargin=function(t){var e=t||"0px",o=e.split(/\s+/).map(function(s){var u=/^(-?\d*\.?\d+)(px|%)$/.exec(s);if(!u)throw new Error("rootMargin must be specified in pixels or percent");return{value:parseFloat(u[1]),unit:u[2]}});return o[1]=o[1]||o[0],o[2]=o[2]||o[0],o[3]=o[3]||o[1],o},a.prototype._monitorIntersections=function(t){var e=t.defaultView;if(e&&this._monitoringDocuments.indexOf(t)==-1){var o=this._checkForIntersections,s=null,u=null;this.POLL_INTERVAL?s=e.setInterval(o,this.POLL_INTERVAL):(c(e,"resize",o,!0),c(t,"scroll",o,!0),this.USE_MUTATION_OBSERVER&&"MutationObserver"in e&&(u=new e.MutationObserver(o),u.observe(t,{attributes:!0,childList:!0,characterData:!0,subtree:!0}))),this._monitoringDocuments.push(t),this._monitoringUnsubscribes.push(function(){var I=t.defaultView;I&&(s&&I.clearInterval(s),l(I,"resize",o,!0)),l(t,"scroll",o,!0),u&&u.disconnect()});var O=this.root&&(this.root.ownerDocument||this.root)||n;if(t!=O){var E=g(t);E&&this._monitorIntersections(E.ownerDocument)}}},a.prototype._unmonitorIntersections=function(t){var e=this._monitoringDocuments.indexOf(t);if(e!=-1){var o=this.root&&(this.root.ownerDocument||this.root)||n,s=this._observationTargets.some(function(E){var I=E.element.ownerDocument;if(I==t)return!0;for(;I&&I!=o;){var L=g(I);if(I=L&&L.ownerDocument,I==t)return!0}return!1});if(!s){var u=this._monitoringUnsubscribes[e];if(this._monitoringDocuments.splice(e,1),this._monitoringUnsubscribes.splice(e,1),u(),t!=o){var O=g(t);O&&this._unmonitorIntersections(O.ownerDocument)}}}},a.prototype._unmonitorAllIntersections=function(){var t=this._monitoringUnsubscribes.slice(0);this._monitoringDocuments.length=0,this._monitoringUnsubscribes.length=0;for(var e=0;e<t.length;e++)t[e]()},a.prototype._checkForIntersections=function(){if(!(!this.root&&p&&!f)){var t=this._rootIsInDom(),e=t?this._getRootRect():y();this._observationTargets.forEach(function(o){var s=o.element,u=T(s),O=this._rootContainsTarget(s),E=o.entry,I=t&&O&&this._computeTargetAndRootIntersection(s,u,e),L=null;this._rootContainsTarget(s)?(!p||this.root)&&(L=e):L=y();var M=o.entry=new w({time:m(),target:s,boundingClientRect:u,rootBounds:L,intersectionRect:I});E?t&&O?this._hasCrossedThreshold(E,M)&&this._queuedEntries.push(M):E&&E.isIntersecting&&this._queuedEntries.push(M):this._queuedEntries.push(M)},this),this._queuedEntries.length&&this._callback(this.takeRecords(),this)}},a.prototype._computeTargetAndRootIntersection=function(t,e,o){if(window.getComputedStyle(t).display!="none"){for(var s=e,u=_(t),O=!1;!O&&u;){var E=null,I=u.nodeType==1?window.getComputedStyle(u):{};if(I.display=="none")return null;if(u==this.root||u.nodeType==9)if(O=!0,u==this.root||u==n)p&&!this.root?!f||f.width==0&&f.height==0?(u=null,E=null,s=null):E=f:E=o;else{var L=_(u),M=L&&T(L),U=L&&this._computeTargetAndRootIntersection(L,M,o);M&&U?(u=L,E=R(M,U)):(u=null,s=null)}else{var V=u.ownerDocument;u!=V.body&&u!=V.documentElement&&I.overflow!="visible"&&(E=T(u))}if(E&&(s=v(E,s)),!s)break;u=u&&_(u)}return s}},a.prototype._getRootRect=function(){var t;if(this.root&&!x(this.root))t=T(this.root);else{var e=x(this.root)?this.root:n,o=e.documentElement,s=e.body;t={top:0,left:0,right:o.clientWidth||s.clientWidth,width:o.clientWidth||s.clientWidth,bottom:o.clientHeight||s.clientHeight,height:o.clientHeight||s.clientHeight}}return this._expandRectByRootMargin(t)},a.prototype._expandRectByRootMargin=function(t){var e=this._rootMarginValues.map(function(s,u){return s.unit=="px"?s.value:s.value*(u%2?t.width:t.height)/100}),o={top:t.top-e[0],right:t.right+e[1],bottom:t.bottom+e[2],left:t.left-e[3]};return o.width=o.right-o.left,o.height=o.bottom-o.top,o},a.prototype._hasCrossedThreshold=function(t,e){var o=t&&t.isIntersecting?t.intersectionRatio||0:-1,s=e.isIntersecting?e.intersectionRatio||0:-1;if(o!==s)for(var u=0;u<this.thresholds.length;u++){var O=this.thresholds[u];if(O==o||O==s||O<o!=O<s)return!0}},a.prototype._rootIsInDom=function(){return!this.root||h(n,this.root)},a.prototype._rootContainsTarget=function(t){var e=this.root&&(this.root.ownerDocument||this.root)||n;return h(e,t)&&(!this.root||e==t.ownerDocument)},a.prototype._registerInstance=function(){i.indexOf(this)<0&&i.push(this)},a.prototype._unregisterInstance=function(){var t=i.indexOf(this);t!=-1&&i.splice(t,1)};function m(){return window.performance&&performance.now&&performance.now()}function d(t,e){var o=null;return function(){o||(o=setTimeout(function(){t(),o=null},e))}}function c(t,e,o,s){typeof t.addEventListener=="function"?t.addEventListener(e,o,s):typeof t.attachEvent=="function"&&t.attachEvent("on"+e,o)}function l(t,e,o,s){typeof t.removeEventListener=="function"?t.removeEventListener(e,o,s):typeof t.detatchEvent=="function"&&t.detatchEvent("on"+e,o)}function v(t,e){var o=Math.max(t.top,e.top),s=Math.min(t.bottom,e.bottom),u=Math.max(t.left,e.left),O=Math.min(t.right,e.right),E=O-u,I=s-o;return E>=0&&I>=0&&{top:o,bottom:s,left:u,right:O,width:E,height:I}||null}function T(t){var e;try{e=t.getBoundingClientRect()}catch{}return e?(e.width&&e.height||(e={top:e.top,right:e.right,bottom:e.bottom,left:e.left,width:e.right-e.left,height:e.bottom-e.top}),e):y()}function y(){return{top:0,bottom:0,left:0,right:0,width:0,height:0}}function b(t){return!t||"x"in t?t:{top:t.top,y:t.top,bottom:t.bottom,left:t.left,x:t.left,right:t.right,width:t.width,height:t.height}}function R(t,e){var o=e.top-t.top,s=e.left-t.left;return{top:o,left:s,height:e.height,width:e.width,bottom:o+e.height,right:s+e.width}}function h(t,e){for(var o=e;o;){if(o==t)return!0;o=_(o)}return!1}function _(t){var e=t.parentNode;return t.nodeType==9&&t!=n?g(t):(e&&e.assignedSlot&&(e=e.assignedSlot.parentNode),e&&e.nodeType==11&&e.host?e.host:e)}function x(t){return t&&t.nodeType===9}window.IntersectionObserver=a,window.IntersectionObserverEntry=w}()),S}q();var C={exports:{}},H;function G(){return H||(H=1,function(g){var n=Object.prototype.hasOwnProperty,i="~";function p(){}Object.create&&(p.prototype=Object.create(null),new p().__proto__||(i=!1));function f(d,c,l){this.fn=d,this.context=c,this.once=l||!1}function w(d,c,l,v,T){if(typeof l!="function")throw new TypeError("The listener must be a function");var y=new f(l,v||d,T),b=i?i+c:c;return d._events[b]?d._events[b].fn?d._events[b]=[d._events[b],y]:d._events[b].push(y):(d._events[b]=y,d._eventsCount++),d}function a(d,c){--d._eventsCount===0?d._events=new p:delete d._events[c]}function m(){this._events=new p,this._eventsCount=0}m.prototype.eventNames=function(){var c=[],l,v;if(this._eventsCount===0)return c;for(v in l=this._events)n.call(l,v)&&c.push(i?v.slice(1):v);return Object.getOwnPropertySymbols?c.concat(Object.getOwnPropertySymbols(l)):c},m.prototype.listeners=function(c){var l=i?i+c:c,v=this._events[l];if(!v)return[];if(v.fn)return[v.fn];for(var T=0,y=v.length,b=new Array(y);T<y;T++)b[T]=v[T].fn;return b},m.prototype.listenerCount=function(c){var l=i?i+c:c,v=this._events[l];return v?v.fn?1:v.length:0},m.prototype.emit=function(c,l,v,T,y,b){var R=i?i+c:c;if(!this._events[R])return!1;var h=this._events[R],_=arguments.length,x,t;if(h.fn){switch(h.once&&this.removeListener(c,h.fn,void 0,!0),_){case 1:return h.fn.call(h.context),!0;case 2:return h.fn.call(h.context,l),!0;case 3:return h.fn.call(h.context,l,v),!0;case 4:return h.fn.call(h.context,l,v,T),!0;case 5:return h.fn.call(h.context,l,v,T,y),!0;case 6:return h.fn.call(h.context,l,v,T,y,b),!0}for(t=1,x=new Array(_-1);t<_;t++)x[t-1]=arguments[t];h.fn.apply(h.context,x)}else{var e=h.length,o;for(t=0;t<e;t++)switch(h[t].once&&this.removeListener(c,h[t].fn,void 0,!0),_){case 1:h[t].fn.call(h[t].context);break;case 2:h[t].fn.call(h[t].context,l);break;case 3:h[t].fn.call(h[t].context,l,v);break;case 4:h[t].fn.call(h[t].context,l,v,T);break;default:if(!x)for(o=1,x=new Array(_-1);o<_;o++)x[o-1]=arguments[o];h[t].fn.apply(h[t].context,x)}}return!0},m.prototype.on=function(c,l,v){return w(this,c,l,v,!1)},m.prototype.once=function(c,l,v){return w(this,c,l,v,!0)},m.prototype.removeListener=function(c,l,v,T){var y=i?i+c:c;if(!this._events[y])return this;if(!l)return a(this,y),this;var b=this._events[y];if(b.fn)b.fn===l&&(!T||b.once)&&(!v||b.context===v)&&a(this,y);else{for(var R=0,h=[],_=b.length;R<_;R++)(b[R].fn!==l||T&&!b[R].once||v&&b[R].context!==v)&&h.push(b[R]);h.length?this._events[y]=h.length===1?h[0]:h:a(this,y)}return this},m.prototype.removeAllListeners=function(c){var l;return c?(l=i?i+c:c,this._events[l]&&a(this,l)):(this._events=new p,this._eventsCount=0),this},m.prototype.off=m.prototype.removeListener,m.prototype.addListener=m.prototype.on,m.prefixed=i,m.EventEmitter=m,g.exports=m}(C)),C.exports}var z=G(),W=Object.defineProperty,$=Object.getOwnPropertyDescriptor,Y=(g,n,i,p)=>{for(var f=$(n,i),w=g.length-1,a;w>=0;w--)(a=g[w])&&(f=a(n,i,f)||f);return f&&W(n,i,f),f};const B=60,j=(r=class{static on(n,i){r.events.on(n,i)}static off(n,i){r.events.off(n,i)}static once(n,i){r.events.once(n,i)}static checkCollisions(n,i){const p=i||Array.from(r.elements.keys()),f=n.getBoundingClientRect(),w=[];for(const a of p)if(a!==n){const m=a.getBoundingClientRect();m.left<=f.right&&m.right>=f.left&&m.top<=f.bottom&&m.bottom>=f.top&&w.push(a)}w.length&&r.onElementIntersection(n,w)}static isPositioned(n){return r.elements.has(n)}static getPositioningOptions(n){return r.elements.has(n)?r.elements.get(n):null}static position(n,i={}){const p={...F,...i};let f=n;for(;f!==document.body;)if(f=f.parentElement,f.classList.contains("sps-focused-task")){p.scrollParent=f,r.registeredScrollParents.has(f)||(r.registeredScrollParents.add(f),f.addEventListener("scroll",r.update));break}if(n.style.visibility="hidden",r.elements.size===0&&(window.addEventListener("resize",r.update),window.addEventListener("scroll",r.update)),!p.relativeTo)throw new Error("You must provide an element for the relativeTo option to position an element.");r.elements.set(n,p),k.onNextTick(()=>{r.fixElementPosition(n),r.viewportObserver.observe(n),n.style.visibility="",r.checkCollisions(n)})}static release(n){if(r.elements.has(n)){r.clearStyles(n);const i=r.elements.get(n);i.scrollParent&&(i.scrollParent.removeEventListener("scroll",r.update),r.registeredScrollParents.delete(i.scrollParent)),r.elements.delete(n),r.elements.size===0&&(window.removeEventListener("resize",r.update),window.removeEventListener("scroll",r.update)),r.viewportObserver.unobserve(n)}}static releaseAll(){for(const n of r.elements.keys())r.release(n)}static refresh(n){r.elements.has(n)&&(r.clearStyles(n),r.fixElementPosition(n),r.checkCollisions(n))}static refreshAll(){for(const n of r.elements.keys())r.refresh(n)}static reposition(n,i){if(r.elements.has(n)){const p=r.elements.get(n);r.elements.set(n,Object.assign(p,i)),r.refresh(n)}}static onViewportIntersection(n){for(const i of n){const p=Object.keys(IntersectionObserverEntry.prototype).reduce((f,w)=>({...f,[w]:i[w]}),{});p.rootBounds=p.rootBounds||r.getRootBounds(),r.events.emit("viewportIntersection",Object.freeze(p))}}static onElementIntersection(n,i){r.events.emit("elementIntersection",{target:n,intersectingWith:i})}static getRootBounds(){const n=Math.max(document.documentElement.clientWidth,window.innerWidth||0),i=Math.max(document.documentElement.clientHeight,window.innerHeight||0);return{x:0,y:B,left:0,top:B,right:n,bottom:i,height:i-B,width:n}}static clearStyles(n){Object.assign(n.style,{position:"",width:"",top:"",left:"",right:"",bottom:"",visibility:"",zIndex:""})}static fixElementPosition(n,i){if(!this.elements.has(n))return;const p=i||this.elements.get(n),f=this.getRootBounds(),w=n.getBoundingClientRect(),a=p.relativeTo.getBoundingClientRect(),{width:m}=p.useRelativeTargetWidth?a:w;Object.assign(n.style,{minWidth:`${m}px`,position:"fixed",zIndex:p.zIndex||""});let d,c;const l=p.position.split(" "),v=p.offsets[0]||0,T=p.offsets[1]||0;switch(d=0,c=0,l[0]){case"top":d=a.top-w.height-v;break;case"left":c=a.left-m-v;break;case"right":c=a.right+v;break;case"bottom":d=a.bottom+v;break;default:throw new Error(`${p.position} is not a valid position`)}switch(l[1]){case"left":c=a.left-T;break;case"top":d=a.top-T;break;case"middle":l[0]==="top"||l[0]==="bottom"?c=a.left+a.width/2-m/2+T:(l[0]==="left"||l[0]==="right")&&(d=a.top+a.height/2-w.height/2+T);break;case"bottom":d=a.bottom-w.height+T;break;case"right":c=a.right-m+T;break;default:throw new Error(`${p.position} is not a valid position`)}const y=d+w.height,b=c+w.width,R=`${Math.round(d)}px`,h=`${Math.round(f.bottom-y)}px`,_=`${Math.round(c)}px`,x=`${Math.round(f.right-b)}px`;switch(p.anchor){case P.TOP_LEFT:Object.assign(n.style,{top:R,bottom:"auto",left:_,right:"auto"});break;case P.TOP_RIGHT:Object.assign(n.style,{top:R,bottom:"auto",left:"auto",right:x});break;case P.BOTTOM_LEFT:Object.assign(n.style,{top:"auto",bottom:h,left:_,right:"auto"});break;case P.BOTTOM_RIGHT:Object.assign(n.style,{top:"auto",bottom:h,left:"auto",right:x});break}}static update(n){const i=r.elements.entries(),p=[];for(const[f,w]of i)(!n||n.target===document||n.target===w.scrollParent||n.target===window)&&(r.fixElementPosition(f,w),r.checkCollisions(f,p),p.push(f))}on(n,i){r.on(n,i)}off(n,i){r.off(n,i)}once(n,i){r.once(n,i)}isPositioned(n){return r.isPositioned(n)}getPositioningOptions(n){return r.getPositioningOptions(n)}position(n,i={}){r.position(n,i)}release(n){r.release(n)}releaseAll(){r.releaseAll()}refresh(n){r.refresh(n)}refreshAll(){r.refreshAll()}reposition(n,i){r.reposition(n,i)}},r.elements=new Map,r.registeredScrollParents=new Set,r.events=new z.EventEmitter,r.viewportObserver=new IntersectionObserver(r.onViewportIntersection,{rootMargin:`-${B}px 0px 0px`,threshold:1}),r);Y([k.lockedToAnimationFrames],j,"update");let J=j;D.DEFAULT_POSITIONING_OPTIONS=F,D.Position=A,D.PositionAnchor=P,D.PositioningService=J,Object.defineProperty(D,Symbol.toStringTag,{value:"Module"})});
@@ -0,0 +1,7 @@
1
+ /** Indicates which point on a positioned element it should be positioned by. */
2
+ export declare enum PositionAnchor {
3
+ TOP_LEFT = "top left",
4
+ TOP_RIGHT = "top right",
5
+ BOTTOM_LEFT = "bottom left",
6
+ BOTTOM_RIGHT = "bottom right"
7
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * These are the possibilities for the `position` option of
3
+ * `PositioningOptions` when using `relativeTo`.
4
+ */
5
+ export declare enum Position {
6
+ TOP_LEFT = "top left",
7
+ TOP_MIDDLE = "top middle",
8
+ TOP_RIGHT = "top right",
9
+ RIGHT_TOP = "right top",
10
+ RIGHT_MIDDLE = "right middle",
11
+ RIGHT_BOTTOM = "right bottom",
12
+ BOTTOM_RIGHT = "bottom right",
13
+ BOTTOM_MIDDLE = "bottom middle",
14
+ BOTTOM_LEFT = "bottom left",
15
+ LEFT_BOTTOM = "left bottom",
16
+ LEFT_MIDDLE = "left middle",
17
+ LEFT_TOP = "left top"
18
+ }
@@ -0,0 +1,37 @@
1
+ import { Position } from "./position.enum";
2
+ import { PositionAnchor } from "./position-anchor.enum";
3
+ /** Options that can be passed to `position()` method. */
4
+ export interface PositioningOptions {
5
+ /** Indicates which point on the positioned element it should be positioned by. */
6
+ anchor?: PositionAnchor;
7
+ /**
8
+ * An array of pixel offsets. Each offset is applied
9
+ * to the corresponding term in `position`. So to continue the above example of
10
+ * `"bottom left"`, if the offsets are `[-7, 9]`, the element will be placed at
11
+ * the bottom of the `relativeTo` element minus 7 pixels, and at the left of it
12
+ * plus 9 pixels. (NB: The values will be converted to rem.)
13
+ */
14
+ offsets?: number[];
15
+ /**
16
+ * When using `relativeTo`, this describes the positioning relationship between
17
+ * the two elements. For example, if it's `"bottom left"`, the positioned element
18
+ * will be placed at the bottom left of the `relativeTo` element.
19
+ */
20
+ position?: Position;
21
+ /**
22
+ * Normally, an element positioned by the service will simply have its current
23
+ * position on the page locked in place. Instead you can have it positioned
24
+ * relative to another element.
25
+ */
26
+ relativeTo?: HTMLElement;
27
+ /**
28
+ * The width of the positioned element will be set to the width of the element
29
+ * provided to the relativeTo option, rather than its own natural width.
30
+ */
31
+ useRelativeTargetWidth?: boolean;
32
+ /** Specify a z-index override for the positioned element. */
33
+ zIndex?: number;
34
+ /** The element's ancestor that scrolls, if it's not the window itself */
35
+ scrollParent?: HTMLElement;
36
+ }
37
+ export declare const DEFAULT_POSITIONING_OPTIONS: PositioningOptions;
@@ -0,0 +1,55 @@
1
+ import "intersection-observer";
2
+ import type { PositioningOptions } from "./positioning-options.interface";
3
+ /**
4
+ * This class follows a singleton pattern where you can create an instance by calling
5
+ * `new PositioningService()` if you wish, but all instance methods pass through to
6
+ * static methods, so there's really only one set of elements being positioned that's
7
+ * shared between all instances and static usages of PositioningService.
8
+ */
9
+ export declare class PositioningService {
10
+ static elements: Map<HTMLElement, PositioningOptions>;
11
+ private static registeredScrollParents;
12
+ private static events;
13
+ private static viewportObserver;
14
+ static on(eventName: any, handler: any): void;
15
+ static off(eventName: any, handler: any): void;
16
+ static once(eventName: any, handler: any): void;
17
+ static checkCollisions(element: HTMLElement, otherElements?: HTMLElement[]): void;
18
+ /**
19
+ * Returns `true` if the element is currently being positioned by the service
20
+ * and `false` otherwise.
21
+ */
22
+ static isPositioned(element: HTMLElement): boolean;
23
+ /**
24
+ * Returns the options currently beinng used for positioning the element,
25
+ * if it is indeed being positioned by the service.
26
+ */
27
+ static getPositioningOptions(element: HTMLElement): PositioningOptions | null;
28
+ /** PositioningService will start controlling the position of the given element. */
29
+ static position(element: HTMLElement, options?: PositioningOptions): void;
30
+ /** PositioningService will stop controlling the position of the given element. */
31
+ static release(element: HTMLElement): void;
32
+ static releaseAll(): void;
33
+ /** PositioningService will refresh the positioning of the given element */
34
+ static refresh(element: HTMLElement): void;
35
+ static refreshAll(): void;
36
+ /** Update the positioning options of a currently positioned element */
37
+ static reposition(element: HTMLElement, newOptions: PositioningOptions): void;
38
+ private static onViewportIntersection;
39
+ private static onElementIntersection;
40
+ private static getRootBounds;
41
+ private static clearStyles;
42
+ private static fixElementPosition;
43
+ private static update;
44
+ on(eventName: any, handler: any): void;
45
+ off(eventName: any, handler: any): void;
46
+ once(eventName: any, handler: any): void;
47
+ isPositioned(element: HTMLElement): boolean;
48
+ getPositioningOptions(element: HTMLElement): PositioningOptions | null;
49
+ position(element: HTMLElement, options?: PositioningOptions): void;
50
+ release(element: HTMLElement): void;
51
+ releaseAll(): void;
52
+ refresh(element: HTMLElement): void;
53
+ refreshAll(): void;
54
+ reposition(element: HTMLElement, newOptions: PositioningOptions): void;
55
+ }
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@spscommerce/positioning",
3
+ "description": "Service for positioning dropdown/popup elements.",
4
+ "version": "0.0.0-20260319-8230915ce",
5
+ "author": "SPS Commerce",
6
+ "license": "UNLICENSED",
7
+ "repository": "https://github.com/spscommerce/woodland/tree/main/packages/@spscommerce/positioning",
8
+ "homepage": "https://github.com/spscommerce/woodland/tree/main/packages/@spscommerce/positioning#readme",
9
+ "type": "module",
10
+ "module": "./lib/index.js",
11
+ "main": "./lib/index.umd.cjs",
12
+ "types": "./lib/index.d.ts",
13
+ "exports": {
14
+ "types": "./lib/index.d.ts",
15
+ "require": "./lib/index.umd.cjs",
16
+ "import": "./lib/index.js",
17
+ "default": "./lib/index.js"
18
+ },
19
+ "publishConfig": {
20
+ "access": "public"
21
+ },
22
+ "peerDependencies": {
23
+ "@spscommerce/utils": "^7.0.0 || ^8.0.0"
24
+ },
25
+ "devDependencies": {
26
+ "@spscommerce/utils": "^7.0.0",
27
+ "raf-stub": "^3.0.0"
28
+ },
29
+ "dependencies": {
30
+ "eventemitter3": "^3.1.0",
31
+ "intersection-observer": "0.12.0"
32
+ },
33
+ "scripts": {
34
+ "build": "pnpm run build:js && pnpm run build:types",
35
+ "build:js": "vite build",
36
+ "build:types": "tsc --emitDeclarationOnly --declaration --declarationDir lib",
37
+ "watch": "vite build --watch",
38
+ "clean": "git clean -fdX",
39
+ "pub": "node ../../scripts/publish-package.mjs"
40
+ }
41
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,13 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "baseUrl": "tsconfig",
5
+ "rootDir": "src/",
6
+ "outDir": "./dist/out-tsc",
7
+ "target": "es5",
8
+ "esModuleInterop": true,
9
+ "declaration": true
10
+ },
11
+ "include": ["src/**/*"],
12
+ "exclude": ["node_modules", "lib"]
13
+ }
@@ -0,0 +1,20 @@
1
+ import path from "node:path";
2
+
3
+ import { defineConfig } from "vite";
4
+
5
+ import pkg from "./package.json";
6
+
7
+ export default defineConfig({
8
+ build: {
9
+ lib: {
10
+ entry: path.resolve(__dirname, "src/index.ts"),
11
+ name: "Positioning",
12
+ fileName: "index",
13
+ },
14
+ outDir: path.resolve(__dirname, "./lib"),
15
+ emptyOutDir: false,
16
+ rollupOptions: {
17
+ external: pkg.peerDependencies ? Object.keys(pkg.peerDependencies) : [],
18
+ },
19
+ },
20
+ });