@zag-js/rect-utils 0.1.2 → 0.1.5

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/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ "use strict";
1
2
  var __defProp = Object.defineProperty;
2
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
@@ -19,112 +20,275 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
19
20
  // src/index.ts
20
21
  var src_exports = {};
21
22
  __export(src_exports, {
22
- Rect: () => Rect,
23
+ alignRect: () => alignRect,
23
24
  closest: () => closest,
25
+ closestSideToPoint: () => closestSideToPoint,
26
+ closestSideToRect: () => closestSideToRect,
27
+ collisions: () => collisions,
28
+ contains: () => contains,
29
+ containsPoint: () => containsPoint,
30
+ containsRect: () => containsRect,
31
+ createRect: () => createRect,
24
32
  debugPolygon: () => debugPolygon,
25
33
  distance: () => distance,
34
+ distanceBtwEdges: () => distanceBtwEdges,
35
+ distanceFromPoint: () => distanceFromPoint,
36
+ distanceFromRect: () => distanceFromRect,
26
37
  expand: () => expand,
38
+ fromRange: () => fromRange,
39
+ getElementPolygon: () => getElementPolygon,
27
40
  getElementRect: () => getElementRect,
28
- getEventPoint: () => getEventPoint,
41
+ getRectCenters: () => getRectCenters,
42
+ getRectCorners: () => getRectCorners,
43
+ getRectEdges: () => getRectEdges,
44
+ getRectFromPoints: () => getRectFromPoints,
45
+ getRotationRect: () => getRotationRect,
46
+ getViewportRect: () => getViewportRect,
47
+ getWindowRect: () => getWindowRect,
29
48
  inset: () => inset,
49
+ intersection: () => intersection,
50
+ intersects: () => intersects,
51
+ isPointInPolygon: () => isPointInPolygon,
52
+ isRect: () => isRect,
30
53
  isSymmetric: () => isSymmetric,
31
- relativeToNode: () => relativeToNode,
54
+ rotate: () => rotate,
32
55
  shift: () => shift,
33
56
  shrink: () => shrink,
34
- withinPolygon: () => withinPolygon
57
+ toRad: () => toRad,
58
+ union: () => union
35
59
  });
36
60
  module.exports = __toCommonJS(src_exports);
37
61
 
38
- // src/rect.ts
39
- var point = (x, y) => ({ x, y });
40
- var Rect = class {
41
- constructor(v) {
42
- this.v = v;
43
- }
44
- static create(v) {
45
- return new Rect(v);
62
+ // src/align.ts
63
+ function hAlign(a, ref, h) {
64
+ let x = ref.minX;
65
+ if (h === "left-inside") {
66
+ x = ref.minX;
46
67
  }
47
- set(n) {
48
- return new Rect(Object.assign({}, this.v, n));
68
+ if (h === "left-outside") {
69
+ x = ref.minX - ref.width;
49
70
  }
50
- clone() {
51
- return new Rect(this.v);
71
+ if (h === "right-inside") {
72
+ x = ref.maxX - ref.width;
52
73
  }
53
- get x() {
54
- return this.v.x;
74
+ if (h === "right-outside") {
75
+ x = ref.maxX;
55
76
  }
56
- get y() {
57
- return this.v.y;
77
+ if (h === "center") {
78
+ x = ref.midX - ref.width / 2;
58
79
  }
59
- get width() {
60
- return this.v.width;
80
+ return { ...a, x };
81
+ }
82
+ function vAlign(a, ref, v) {
83
+ let y = ref.minY;
84
+ if (v === "top-inside") {
85
+ y = ref.minY;
61
86
  }
62
- get height() {
63
- return this.v.height;
87
+ if (v === "top-outside") {
88
+ y = ref.minY - a.height;
64
89
  }
65
- get minX() {
66
- return this.v.x;
90
+ if (v === "bottom-inside") {
91
+ y = ref.maxY - a.height;
67
92
  }
68
- get midX() {
69
- return this.v.x + this.v.width / 2;
93
+ if (v === "bottom-outside") {
94
+ y = ref.maxY;
70
95
  }
71
- get maxX() {
72
- return this.v.x + this.v.width;
96
+ if (v === "center") {
97
+ y = ref.midY - a.height / 2;
73
98
  }
74
- get minY() {
75
- return this.v.y;
99
+ return { ...a, y };
100
+ }
101
+ function alignRect(a, ref, options) {
102
+ const { h, v } = options;
103
+ return vAlign(hAlign(a, ref, h), ref, v);
104
+ }
105
+
106
+ // ../core/dist/index.mjs
107
+ var hasProp = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop);
108
+
109
+ // src/rect.ts
110
+ var point = (x, y) => ({ x, y });
111
+ function createRect(r) {
112
+ const { x, y, width, height } = r;
113
+ const midX = x + width / 2;
114
+ const midY = y + height / 2;
115
+ return {
116
+ x,
117
+ y,
118
+ width,
119
+ height,
120
+ minX: x,
121
+ minY: y,
122
+ maxX: x + width,
123
+ maxY: y + height,
124
+ midX,
125
+ midY,
126
+ center: point(midX, midY)
127
+ };
128
+ }
129
+ function isRect(v) {
130
+ return hasProp(v, "x") && hasProp(v, "y") && hasProp(v, "width") && hasProp(v, "height");
131
+ }
132
+ function getRectCenters(v) {
133
+ const top = point(v.midX, v.minY);
134
+ const right = point(v.maxX, v.midY);
135
+ const bottom = point(v.midX, v.maxY);
136
+ const left = point(v.minX, v.midY);
137
+ return { top, right, bottom, left };
138
+ }
139
+ function getRectCorners(v) {
140
+ const top = point(v.minX, v.minY);
141
+ const right = point(v.maxX, v.minY);
142
+ const bottom = point(v.maxX, v.maxY);
143
+ const left = point(v.minX, v.maxY);
144
+ return { top, right, bottom, left };
145
+ }
146
+ function getRectEdges(v) {
147
+ const c = getRectCorners(v);
148
+ const top = [c.top, c.right];
149
+ const right = [c.right, c.bottom];
150
+ const bottom = [c.left, c.bottom];
151
+ const left = [c.top, c.left];
152
+ return { top, right, bottom, left };
153
+ }
154
+
155
+ // src/intersection.ts
156
+ function intersects(a, b) {
157
+ return a.x < b.maxX && a.y < b.maxY && a.maxX > b.x && a.maxY > b.y;
158
+ }
159
+ function intersection(a, b) {
160
+ const x = Math.max(a.x, b.x);
161
+ const y = Math.max(a.y, b.y);
162
+ const x2 = Math.min(a.x + a.width, b.x + b.width);
163
+ const y2 = Math.min(a.y + a.height, b.y + b.height);
164
+ return createRect({ x, y, width: x2 - x, height: y2 - y });
165
+ }
166
+ function collisions(a, b) {
167
+ return {
168
+ top: a.minY <= b.minY,
169
+ right: a.maxX >= b.maxX,
170
+ bottom: a.maxY >= b.maxY,
171
+ left: a.minX <= b.minX
172
+ };
173
+ }
174
+
175
+ // src/distance.ts
176
+ function distance(a, b = { x: 0, y: 0 }) {
177
+ return Math.sqrt(Math.pow(a.x - b.x, 2) + Math.pow(a.y - b.y, 2));
178
+ }
179
+ function distanceFromPoint(r, p) {
180
+ let x = 0;
181
+ let y = 0;
182
+ if (p.x < r.x)
183
+ x = r.x - p.x;
184
+ else if (p.x > r.maxX)
185
+ x = p.x - r.maxX;
186
+ if (p.y < r.y)
187
+ y = r.y - p.y;
188
+ else if (p.y > r.maxY)
189
+ y = p.y - r.maxY;
190
+ return { x, y, value: distance({ x, y }) };
191
+ }
192
+ function distanceFromRect(a, b) {
193
+ if (intersects(a, b))
194
+ return { x: 0, y: 0, value: 0 };
195
+ const left = a.x < b.x ? a : b;
196
+ const right = b.x < a.x ? a : b;
197
+ const upper = a.y < b.y ? a : b;
198
+ const lower = b.y < a.y ? a : b;
199
+ let x = left.x === right.x ? 0 : right.x - left.maxX;
200
+ x = Math.max(0, x);
201
+ let y = upper.y === lower.y ? 0 : lower.y - upper.maxY;
202
+ y = Math.max(0, y);
203
+ return { x, y, value: distance({ x, y }) };
204
+ }
205
+ function distanceBtwEdges(a, b) {
206
+ return {
207
+ left: b.x - a.x,
208
+ top: b.y - a.y,
209
+ right: a.maxX - b.maxX,
210
+ bottom: a.maxY - b.maxY
211
+ };
212
+ }
213
+
214
+ // src/closest.ts
215
+ function closest(...pts) {
216
+ return (a) => {
217
+ const ds = pts.map((b) => distance(b, a));
218
+ const c = Math.min.apply(Math, ds);
219
+ return pts[ds.indexOf(c)];
220
+ };
221
+ }
222
+ function closestSideToRect(ref, r) {
223
+ if (r.maxX <= ref.minX) {
224
+ return "left";
76
225
  }
77
- get midY() {
78
- return this.v.y + this.v.height / 2;
226
+ if (r.minX >= ref.maxX) {
227
+ return "right";
79
228
  }
80
- get maxY() {
81
- return this.v.y + this.v.height;
229
+ if (r.maxY <= ref.minY) {
230
+ return "top";
82
231
  }
83
- get center() {
84
- return point(this.midX, this.midY);
232
+ if (r.minY >= ref.maxY) {
233
+ return "bottom";
85
234
  }
86
- get centers() {
87
- const top = point(this.midX, this.minY);
88
- const right = point(this.maxX, this.midY);
89
- const bottom = point(this.midX, this.maxY);
90
- const left = point(this.minX, this.midY);
91
- return { top, right, bottom, left };
235
+ return "left";
236
+ }
237
+ function closestSideToPoint(ref, p) {
238
+ const { x, y } = p;
239
+ const dl = x - ref.minX;
240
+ const dr = ref.maxX - x;
241
+ const dt = y - ref.minY;
242
+ const db = ref.maxY - y;
243
+ let closest2 = dl;
244
+ let side = "left";
245
+ if (dr < closest2) {
246
+ closest2 = dr;
247
+ side = "right";
92
248
  }
93
- get corners() {
94
- const top = point(this.minX, this.minY);
95
- const right = point(this.maxX, this.minY);
96
- const bottom = point(this.maxX, this.maxY);
97
- const left = point(this.minX, this.maxY);
98
- return { top, right, bottom, left };
249
+ if (dt < closest2) {
250
+ closest2 = dt;
251
+ side = "top";
99
252
  }
100
- get edges() {
101
- const c = this.corners;
102
- const top = [c.top, c.right];
103
- const right = [c.right, c.bottom];
104
- const bottom = [c.left, c.bottom];
105
- const left = [c.top, c.left];
106
- return { top, right, bottom, left };
253
+ if (db < closest2) {
254
+ side = "bottom";
107
255
  }
108
- };
256
+ return side;
257
+ }
109
258
 
110
- // src/computed-style.ts
111
- var styleCache = /* @__PURE__ */ new WeakMap();
259
+ // src/contains.ts
260
+ function containsPoint(r, p) {
261
+ return r.minX <= p.x && p.x <= r.maxX && r.minY <= p.y && p.y <= r.maxY;
262
+ }
263
+ function containsRect(a, b) {
264
+ return Object.values(getRectCorners(b)).every((c) => containsPoint(a, c));
265
+ }
266
+ function contains(r, v) {
267
+ return isRect(v) ? containsRect(r, v) : containsPoint(r, v);
268
+ }
269
+
270
+ // ../dom/dist/index.mjs
271
+ function getCache() {
272
+ const g = globalThis;
273
+ g.__styleCache = g.__styleCache || /* @__PURE__ */ new WeakMap();
274
+ return g.__styleCache;
275
+ }
112
276
  function getComputedStyle(el) {
113
- var _a;
114
277
  if (!el)
115
278
  return {};
116
- let style = styleCache.get(el);
279
+ const cache = getCache();
280
+ let style = cache.get(el);
117
281
  if (!style) {
118
- const win = (_a = el == null ? void 0 : el.ownerDocument.defaultView) != null ? _a : window;
282
+ const win = (el == null ? void 0 : el.ownerDocument.defaultView) ?? window;
119
283
  style = win.getComputedStyle(el);
120
- styleCache.set(el, style);
284
+ cache.set(el, style);
121
285
  }
122
286
  return style;
123
287
  }
124
288
 
125
289
  // src/from-element.ts
126
290
  function getElementRect(el, opts = {}) {
127
- return Rect.create(getClientRect(el, opts));
291
+ return createRect(getClientRect(el, opts));
128
292
  }
129
293
  function getClientRect(el, opts = {}) {
130
294
  const { excludeScrollbar = false, excludeBorders = false } = opts;
@@ -151,45 +315,124 @@ function getClientRect(el, opts = {}) {
151
315
  var px = (v) => parseFloat(v.replace("px", ""));
152
316
  var sum = (...vals) => vals.reduce((sum2, v) => sum2 + (v ? px(v) : 0), 0);
153
317
 
154
- // ../core/dist/index.mjs
155
- var isDom = () => typeof window !== "undefined";
156
- var isArray = (v) => Array.isArray(v);
157
- var isObject = (v) => !(v == null || typeof v !== "object" || isArray(v));
158
- var hasProp = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop);
159
- var isTouchDevice = isDom() && !!navigator.maxTouchPoints;
160
- var isTouchEvent = (v) => isObject(v) && hasProp(v, "touches");
161
-
162
- // src/point.ts
163
- function distance(a, b = { x: 0, y: 0 }) {
164
- return Math.sqrt(Math.pow(a.x - b.x, 2) + Math.pow(a.y - b.y, 2));
318
+ // src/from-points.ts
319
+ function getRectFromPoints(...pts) {
320
+ const xs = pts.map((p) => p.x);
321
+ const ys = pts.map((p) => p.y);
322
+ const x = Math.min(...xs);
323
+ const y = Math.min(...ys);
324
+ const width = Math.max(...xs) - x;
325
+ const height = Math.max(...ys) - y;
326
+ return createRect({ x, y, width, height });
165
327
  }
166
- function closest(...pts) {
167
- return (a) => {
168
- const ds = pts.map((b) => distance(b, a));
169
- const c = Math.min.apply(Math, ds);
170
- return pts[ds.indexOf(c)];
328
+
329
+ // src/union.ts
330
+ var { min, max } = Math;
331
+ function union(...rs) {
332
+ const pMin = {
333
+ x: min.apply(Math, rs.map((r) => r.minX)),
334
+ y: min.apply(Math, rs.map((r) => r.minY))
335
+ };
336
+ const pMax = {
337
+ x: max.apply(Math, rs.map((r) => r.maxX)),
338
+ y: max.apply(Math, rs.map((r) => r.maxY))
171
339
  };
340
+ return getRectFromPoints(pMin, pMax);
172
341
  }
173
- var fallback = { pageX: 0, pageY: 0, clientX: 0, clientY: 0 };
174
- function getEventPoint(e, t = "page") {
175
- const p = isTouchEvent(e) ? e.touches[0] || e.changedTouches[0] || fallback : e;
176
- return { x: p[`${t}X`], y: p[`${t}Y`] };
342
+
343
+ // src/from-range.ts
344
+ function fromRange(range) {
345
+ let rs = [];
346
+ const rects = Array.from(range.getClientRects());
347
+ if (rects.length) {
348
+ rs = rs.concat(rects.map(createRect));
349
+ return union.apply(void 0, rs);
350
+ }
351
+ let start = range.startContainer;
352
+ if (start.nodeType === Node.TEXT_NODE) {
353
+ start = start.parentNode;
354
+ }
355
+ if (start instanceof HTMLElement) {
356
+ const r = getElementRect(start);
357
+ rs.push({ ...r, x: r.maxX, width: 0 });
358
+ }
359
+ return union.apply(void 0, rs);
360
+ }
361
+
362
+ // src/from-rotation.ts
363
+ function toRad(d) {
364
+ return d % 360 * Math.PI / 180;
177
365
  }
178
- function relativeToNode(p, el) {
179
- const dx = p.x - el.offsetLeft - el.clientLeft + el.scrollLeft;
180
- const dy = p.y - el.offsetTop - el.clientTop + el.scrollTop;
366
+ function rotate(a, d, c) {
367
+ const r = toRad(d);
368
+ const sin = Math.sin(r);
369
+ const cos = Math.cos(r);
370
+ const x = a.x - c.x;
371
+ const y = a.y - c.y;
181
372
  return {
182
- point: { x: dx, y: dy },
183
- progress: { x: dx / el.offsetWidth, y: dy / el.offsetHeight }
373
+ x: c.x + x * cos - y * sin,
374
+ y: c.y + x * sin + y * cos
184
375
  };
185
376
  }
377
+ function getRotationRect(r, deg) {
378
+ const rr = Object.values(getRectCorners(r)).map((p) => rotate(p, deg, r.center));
379
+ const xs = rr.map((p) => p.x);
380
+ const ys = rr.map((p) => p.y);
381
+ const minX = Math.min(...xs);
382
+ const minY = Math.min(...ys);
383
+ const maxX = Math.max(...xs);
384
+ const maxY = Math.max(...ys);
385
+ return createRect({
386
+ x: minX,
387
+ y: minY,
388
+ width: maxX - minX,
389
+ height: maxY - minY
390
+ });
391
+ }
392
+
393
+ // src/from-window.ts
394
+ function getWindowRect(win, opts = {}) {
395
+ return createRect(getViewportRect(win, opts));
396
+ }
397
+ function getViewportRect(win, opts) {
398
+ const { excludeScrollbar = false } = opts;
399
+ const { innerWidth: innerWidth2, innerHeight: innerHeight2, document: doc, visualViewport } = win;
400
+ const width = visualViewport.width || innerWidth2;
401
+ const height = visualViewport.height || innerHeight2;
402
+ const rect = { x: 0, y: 0, width, height };
403
+ if (excludeScrollbar) {
404
+ const scrollbarWidth = innerWidth2 - doc.documentElement.clientWidth;
405
+ const scrollbarHeight = innerHeight2 - doc.documentElement.clientHeight;
406
+ rect.width -= scrollbarWidth;
407
+ rect.height -= scrollbarHeight;
408
+ }
409
+ return rect;
410
+ }
411
+
412
+ // src/get-polygon.ts
413
+ function getElementPolygon(rectValue, placement) {
414
+ const rect = createRect(rectValue);
415
+ const { top, right, left, bottom } = getRectCorners(rect);
416
+ const [base] = placement.split("-");
417
+ return {
418
+ top: [left, top, right, bottom],
419
+ right: [top, right, bottom, left],
420
+ bottom: [top, left, bottom, right],
421
+ left: [right, top, left, bottom]
422
+ }[base];
423
+ }
186
424
 
187
425
  // src/operations.ts
188
426
  var isSymmetric = (v) => "dx" in v || "dy" in v;
189
427
  function inset(r, i) {
190
428
  const v = isSymmetric(i) ? { left: i.dx, right: i.dx, top: i.dy, bottom: i.dy } : i;
191
429
  const { top = 0, right = 0, bottom = 0, left = 0 } = v;
192
- return Rect.create({ x: r.x + left, y: r.y + top, width: r.width - left - right, height: r.height - top - bottom });
430
+ return createRect({
431
+ x: r.x + left,
432
+ y: r.y + top,
433
+ width: r.width - left - right,
434
+ height: r.height - top - bottom
435
+ });
193
436
  }
194
437
  function expand(r, v) {
195
438
  const value = typeof v === "number" ? { dx: -v, dy: -v } : v;
@@ -201,11 +444,16 @@ function shrink(r, v) {
201
444
  }
202
445
  function shift(r, o) {
203
446
  const { x = 0, y = 0 } = o;
204
- return Rect.create({ x: r.x + x, y: r.y + y, width: r.width, height: r.height });
447
+ return createRect({
448
+ x: r.x + x,
449
+ y: r.y + y,
450
+ width: r.width,
451
+ height: r.height
452
+ });
205
453
  }
206
454
 
207
455
  // src/polygon.ts
208
- function withinPolygon(polygon, point2) {
456
+ function isPointInPolygon(polygon, point2) {
209
457
  const { x, y } = point2;
210
458
  let c = false;
211
459
  for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
@@ -233,7 +481,8 @@ function createPolygonElement() {
233
481
  height: "100%",
234
482
  opacity: "0.15",
235
483
  position: "fixed",
236
- pointerEvents: "none"
484
+ pointerEvents: "none",
485
+ fill: "red"
237
486
  });
238
487
  const polygon = document.createElementNS("http://www.w3.org/2000/svg", "polygon");
239
488
  polygon.setAttribute("id", id);
@@ -246,5 +495,46 @@ function debugPolygon(polygon) {
246
495
  const el = createPolygonElement();
247
496
  const points = polygon.map((point2) => `${point2.x},${point2.y}`).join(" ");
248
497
  el.setAttribute("points", points);
498
+ return () => {
499
+ el.remove();
500
+ };
249
501
  }
250
- //# sourceMappingURL=index.js.map
502
+ // Annotate the CommonJS export names for ESM import in node:
503
+ 0 && (module.exports = {
504
+ alignRect,
505
+ closest,
506
+ closestSideToPoint,
507
+ closestSideToRect,
508
+ collisions,
509
+ contains,
510
+ containsPoint,
511
+ containsRect,
512
+ createRect,
513
+ debugPolygon,
514
+ distance,
515
+ distanceBtwEdges,
516
+ distanceFromPoint,
517
+ distanceFromRect,
518
+ expand,
519
+ fromRange,
520
+ getElementPolygon,
521
+ getElementRect,
522
+ getRectCenters,
523
+ getRectCorners,
524
+ getRectEdges,
525
+ getRectFromPoints,
526
+ getRotationRect,
527
+ getViewportRect,
528
+ getWindowRect,
529
+ inset,
530
+ intersection,
531
+ intersects,
532
+ isPointInPolygon,
533
+ isRect,
534
+ isSymmetric,
535
+ rotate,
536
+ shift,
537
+ shrink,
538
+ toRad,
539
+ union
540
+ });