@zag-js/rect-utils 0.38.1 → 0.40.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,40 +1,198 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => {
4
+ __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
5
+ return value;
6
+ };
7
+
8
+ // src/affine-transform.ts
9
+ var AffineTransform = class _AffineTransform {
10
+ constructor([m00, m01, m02, m10, m11, m12] = [0, 0, 0, 0, 0, 0]) {
11
+ __publicField(this, "m00");
12
+ __publicField(this, "m01");
13
+ __publicField(this, "m02");
14
+ __publicField(this, "m10");
15
+ __publicField(this, "m11");
16
+ __publicField(this, "m12");
17
+ __publicField(this, "rotate", (...args) => {
18
+ return this.prepend(_AffineTransform.rotate(...args));
19
+ });
20
+ __publicField(this, "scale", (...args) => {
21
+ return this.prepend(_AffineTransform.scale(...args));
22
+ });
23
+ __publicField(this, "translate", (...args) => {
24
+ return this.prepend(_AffineTransform.translate(...args));
25
+ });
26
+ this.m00 = m00;
27
+ this.m01 = m01;
28
+ this.m02 = m02;
29
+ this.m10 = m10;
30
+ this.m11 = m11;
31
+ this.m12 = m12;
32
+ }
33
+ applyTo(point) {
34
+ const { x, y } = point;
35
+ const { m00, m01, m02, m10, m11, m12 } = this;
36
+ return {
37
+ x: m00 * x + m01 * y + m02,
38
+ y: m10 * x + m11 * y + m12
39
+ };
40
+ }
41
+ prepend(other) {
42
+ return new _AffineTransform([
43
+ this.m00 * other.m00 + this.m01 * other.m10,
44
+ // m00
45
+ this.m00 * other.m01 + this.m01 * other.m11,
46
+ // m01
47
+ this.m00 * other.m02 + this.m01 * other.m12 + this.m02,
48
+ // m02
49
+ this.m10 * other.m00 + this.m11 * other.m10,
50
+ // m10
51
+ this.m10 * other.m01 + this.m11 * other.m11,
52
+ // m11
53
+ this.m10 * other.m02 + this.m11 * other.m12 + this.m12
54
+ // m12
55
+ ]);
56
+ }
57
+ append(other) {
58
+ return new _AffineTransform([
59
+ other.m00 * this.m00 + other.m01 * this.m10,
60
+ // m00
61
+ other.m00 * this.m01 + other.m01 * this.m11,
62
+ // m01
63
+ other.m00 * this.m02 + other.m01 * this.m12 + other.m02,
64
+ // m02
65
+ other.m10 * this.m00 + other.m11 * this.m10,
66
+ // m10
67
+ other.m10 * this.m01 + other.m11 * this.m11,
68
+ // m11
69
+ other.m10 * this.m02 + other.m11 * this.m12 + other.m12
70
+ // m12
71
+ ]);
72
+ }
73
+ get determinant() {
74
+ return this.m00 * this.m11 - this.m01 * this.m10;
75
+ }
76
+ get isInvertible() {
77
+ const det = this.determinant;
78
+ return isFinite(det) && isFinite(this.m02) && isFinite(this.m12) && det !== 0;
79
+ }
80
+ invert() {
81
+ const det = this.determinant;
82
+ return new _AffineTransform([
83
+ this.m11 / det,
84
+ // m00
85
+ -this.m01 / det,
86
+ // m01
87
+ (this.m01 * this.m12 - this.m11 * this.m02) / det,
88
+ // m02
89
+ -this.m10 / det,
90
+ // m10
91
+ this.m00 / det,
92
+ // m11
93
+ (this.m10 * this.m02 - this.m00 * this.m12) / det
94
+ // m12
95
+ ]);
96
+ }
97
+ get array() {
98
+ return [this.m00, this.m01, this.m02, this.m10, this.m11, this.m12, 0, 0, 1];
99
+ }
100
+ get float32Array() {
101
+ return new Float32Array(this.array);
102
+ }
103
+ // Static
104
+ static get identity() {
105
+ return new _AffineTransform([1, 0, 0, 0, 1, 0]);
106
+ }
107
+ static rotate(theta, origin) {
108
+ const rotation = new _AffineTransform([Math.cos(theta), -Math.sin(theta), 0, Math.sin(theta), Math.cos(theta), 0]);
109
+ if (origin && (origin.x !== 0 || origin.y !== 0)) {
110
+ return _AffineTransform.multiply(
111
+ _AffineTransform.translate(origin.x, origin.y),
112
+ rotation,
113
+ _AffineTransform.translate(-origin.x, -origin.y)
114
+ );
115
+ }
116
+ return rotation;
117
+ }
118
+ static scale(sx, sy = sx, origin = { x: 0, y: 0 }) {
119
+ const scale = new _AffineTransform([sx, 0, 0, 0, sy, 0]);
120
+ if (origin.x !== 0 || origin.y !== 0) {
121
+ return _AffineTransform.multiply(
122
+ _AffineTransform.translate(origin.x, origin.y),
123
+ scale,
124
+ _AffineTransform.translate(-origin.x, -origin.y)
125
+ );
126
+ }
127
+ return scale;
128
+ }
129
+ static translate(tx, ty) {
130
+ return new _AffineTransform([1, 0, tx, 0, 1, ty]);
131
+ }
132
+ static multiply(...[first, ...rest]) {
133
+ if (!first)
134
+ return _AffineTransform.identity;
135
+ return rest.reduce((result, item) => result.prepend(item), first);
136
+ }
137
+ get a() {
138
+ return this.m00;
139
+ }
140
+ get b() {
141
+ return this.m10;
142
+ }
143
+ get c() {
144
+ return this.m01;
145
+ }
146
+ get d() {
147
+ return this.m11;
148
+ }
149
+ get tx() {
150
+ return this.m02;
151
+ }
152
+ get ty() {
153
+ return this.m12;
154
+ }
155
+ get scaleComponents() {
156
+ return { x: this.a, y: this.d };
157
+ }
158
+ get translationComponents() {
159
+ return { x: this.tx, y: this.ty };
160
+ }
161
+ get skewComponents() {
162
+ return { x: this.c, y: this.b };
163
+ }
164
+ toString() {
165
+ return `matrix(${this.a}, ${this.b}, ${this.c}, ${this.d}, ${this.tx}, ${this.ty})`;
166
+ }
167
+ };
168
+
1
169
  // src/align.ts
2
170
  function hAlign(a, ref, h) {
3
171
  let x = ref.minX;
4
- if (h === "left-inside") {
172
+ if (h === "left-inside")
5
173
  x = ref.minX;
6
- }
7
- if (h === "left-outside") {
174
+ if (h === "left-outside")
8
175
  x = ref.minX - ref.width;
9
- }
10
- if (h === "right-inside") {
176
+ if (h === "right-inside")
11
177
  x = ref.maxX - ref.width;
12
- }
13
- if (h === "right-outside") {
178
+ if (h === "right-outside")
14
179
  x = ref.maxX;
15
- }
16
- if (h === "center") {
180
+ if (h === "center")
17
181
  x = ref.midX - ref.width / 2;
18
- }
19
182
  return { ...a, x };
20
183
  }
21
184
  function vAlign(a, ref, v) {
22
185
  let y = ref.minY;
23
- if (v === "top-inside") {
186
+ if (v === "top-inside")
24
187
  y = ref.minY;
25
- }
26
- if (v === "top-outside") {
188
+ if (v === "top-outside")
27
189
  y = ref.minY - a.height;
28
- }
29
- if (v === "bottom-inside") {
190
+ if (v === "bottom-inside")
30
191
  y = ref.maxY - a.height;
31
- }
32
- if (v === "bottom-outside") {
192
+ if (v === "bottom-outside")
33
193
  y = ref.maxY;
34
- }
35
- if (v === "center") {
194
+ if (v === "center")
36
195
  y = ref.midY - a.height / 2;
37
- }
38
196
  return { ...a, y };
39
197
  }
40
198
  function alignRect(a, ref, options) {
@@ -42,8 +200,35 @@ function alignRect(a, ref, options) {
42
200
  return vAlign(hAlign(a, ref, h), ref, v);
43
201
  }
44
202
 
203
+ // src/clamp.ts
204
+ var clamp = (value, min3, max2) => Math.min(Math.max(value, min3), max2);
205
+ var clampPoint = (position, size, boundaryRect) => {
206
+ const x = clamp(position.x, boundaryRect.x, boundaryRect.x + boundaryRect.width - size.width);
207
+ const y = clamp(position.y, boundaryRect.y, boundaryRect.y + boundaryRect.height - size.height);
208
+ return { x, y };
209
+ };
210
+ var defaultMinSize = {
211
+ width: 0,
212
+ height: 0
213
+ };
214
+ var defaultMaxSize = {
215
+ width: Infinity,
216
+ height: Infinity
217
+ };
218
+ var clampSize = (size, minSize = defaultMinSize, maxSize = defaultMaxSize) => {
219
+ return {
220
+ width: Math.min(Math.max(size.width, minSize.width), maxSize.width),
221
+ height: Math.min(Math.max(size.height, minSize.height), maxSize.height)
222
+ };
223
+ };
224
+
45
225
  // src/rect.ts
46
- var point = (x, y) => ({ x, y });
226
+ var createPoint = (x, y) => ({ x, y });
227
+ var subtractPoints = (a, b) => createPoint(a.x - b.x, a.y - b.y);
228
+ var addPoints = (a, b) => createPoint(a.x + b.x, a.y + b.y);
229
+ function isPoint(v) {
230
+ return Reflect.has(v, "x") && Reflect.has(v, "y");
231
+ }
47
232
  function createRect(r) {
48
233
  const { x, y, width, height } = r;
49
234
  const midX = x + width / 2;
@@ -59,25 +244,24 @@ function createRect(r) {
59
244
  maxY: y + height,
60
245
  midX,
61
246
  midY,
62
- center: point(midX, midY)
247
+ center: createPoint(midX, midY)
63
248
  };
64
249
  }
65
- var hasProp = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop);
66
250
  function isRect(v) {
67
- return hasProp(v, "x") && hasProp(v, "y") && hasProp(v, "width") && hasProp(v, "height");
251
+ return Reflect.has(v, "x") && Reflect.has(v, "y") && Reflect.has(v, "width") && Reflect.has(v, "height");
68
252
  }
69
253
  function getRectCenters(v) {
70
- const top = point(v.midX, v.minY);
71
- const right = point(v.maxX, v.midY);
72
- const bottom = point(v.midX, v.maxY);
73
- const left = point(v.minX, v.midY);
254
+ const top = createPoint(v.midX, v.minY);
255
+ const right = createPoint(v.maxX, v.midY);
256
+ const bottom = createPoint(v.midX, v.maxY);
257
+ const left = createPoint(v.minX, v.midY);
74
258
  return { top, right, bottom, left };
75
259
  }
76
260
  function getRectCorners(v) {
77
- const top = point(v.minX, v.minY);
78
- const right = point(v.maxX, v.minY);
79
- const bottom = point(v.maxX, v.maxY);
80
- const left = point(v.minX, v.maxY);
261
+ const top = createPoint(v.minX, v.minY);
262
+ const right = createPoint(v.maxX, v.minY);
263
+ const bottom = createPoint(v.maxX, v.maxY);
264
+ const left = createPoint(v.minX, v.maxY);
81
265
  return { top, right, bottom, left };
82
266
  }
83
267
  function getRectEdges(v) {
@@ -157,18 +341,14 @@ function closest(...pts) {
157
341
  };
158
342
  }
159
343
  function closestSideToRect(ref, r) {
160
- if (r.maxX <= ref.minX) {
344
+ if (r.maxX <= ref.minX)
161
345
  return "left";
162
- }
163
- if (r.minX >= ref.maxX) {
346
+ if (r.minX >= ref.maxX)
164
347
  return "right";
165
- }
166
- if (r.maxY <= ref.minY) {
348
+ if (r.maxY <= ref.minY)
167
349
  return "top";
168
- }
169
- if (r.minY >= ref.maxY) {
350
+ if (r.minY >= ref.maxY)
170
351
  return "bottom";
171
- }
172
352
  return "left";
173
353
  }
174
354
  function closestSideToPoint(ref, p) {
@@ -193,6 +373,20 @@ function closestSideToPoint(ref, p) {
193
373
  return side;
194
374
  }
195
375
 
376
+ // src/constrain.ts
377
+ var constrainRect = (rect, boundary) => {
378
+ const { x, y, width, height } = rect;
379
+ const { x: bx, y: by, width: bw, height: bh } = boundary;
380
+ const left = Math.max(bx, Math.min(x, bx + bw - width));
381
+ const top = Math.max(by, Math.min(y, by + bh - height));
382
+ return {
383
+ x: left,
384
+ y: top,
385
+ width: Math.min(width, bw),
386
+ height: Math.min(height, bh)
387
+ };
388
+ };
389
+
196
390
  // src/contains.ts
197
391
  function containsPoint(r, p) {
198
392
  return r.minX <= p.x && p.x <= r.maxX && r.minY <= p.y && p.y <= r.maxY;
@@ -204,6 +398,17 @@ function contains(r, v) {
204
398
  return isRect(v) ? containsRect(r, v) : containsPoint(r, v);
205
399
  }
206
400
 
401
+ // src/equality.ts
402
+ var isSizeEqual = (a, b) => {
403
+ return a.width === b.width && a.height === b.height;
404
+ };
405
+ var isPointEqual = (a, b) => {
406
+ return a.x === b.x && a.y === b.y;
407
+ };
408
+ var isRectEqual = (a, b) => {
409
+ return isPointEqual(a, b) && isSizeEqual(a, b);
410
+ };
411
+
207
412
  // src/from-element.ts
208
413
  var styleCache = /* @__PURE__ */ new WeakMap();
209
414
  function getCacheComputedStyle(el) {
@@ -256,24 +461,12 @@ function getRectFromPoints(...pts) {
256
461
  var { min, max } = Math;
257
462
  function union(...rs) {
258
463
  const pMin = {
259
- x: min.apply(
260
- Math,
261
- rs.map((r) => r.minX)
262
- ),
263
- y: min.apply(
264
- Math,
265
- rs.map((r) => r.minY)
266
- )
464
+ x: min(...rs.map((r) => r.minX)),
465
+ y: min(...rs.map((r) => r.minY))
267
466
  };
268
467
  const pMax = {
269
- x: max.apply(
270
- Math,
271
- rs.map((r) => r.maxX)
272
- ),
273
- y: max.apply(
274
- Math,
275
- rs.map((r) => r.maxY)
276
- )
468
+ x: max(...rs.map((r) => r.maxX)),
469
+ y: max(...rs.map((r) => r.maxY))
277
470
  };
278
471
  return getRectFromPoints(pMin, pMax);
279
472
  }
@@ -347,19 +540,6 @@ function getViewportRect(win, opts) {
347
540
  return rect;
348
541
  }
349
542
 
350
- // src/get-polygon.ts
351
- function getElementPolygon(rectValue, placement) {
352
- const rect = createRect(rectValue);
353
- const { top, right, left, bottom } = getRectCorners(rect);
354
- const [base] = placement.split("-");
355
- return {
356
- top: [left, top, right, bottom],
357
- right: [top, right, bottom, left],
358
- bottom: [top, left, bottom, right],
359
- left: [right, top, left, bottom]
360
- }[base];
361
- }
362
-
363
543
  // src/operations.ts
364
544
  var isSymmetric = (v) => "dx" in v || "dy" in v;
365
545
  function inset(r, i) {
@@ -391,8 +571,19 @@ function shift(r, o) {
391
571
  }
392
572
 
393
573
  // src/polygon.ts
394
- function isPointInPolygon(polygon, point2) {
395
- const { x, y } = point2;
574
+ function getElementPolygon(rectValue, placement) {
575
+ const rect = createRect(rectValue);
576
+ const { top, right, left, bottom } = getRectCorners(rect);
577
+ const [base] = placement.split("-");
578
+ return {
579
+ top: [left, top, right, bottom],
580
+ right: [top, right, bottom, left],
581
+ bottom: [top, left, bottom, right],
582
+ left: [right, top, left, bottom]
583
+ }[base];
584
+ }
585
+ function isPointInPolygon(polygon, point) {
586
+ const { x, y } = point;
396
587
  let c = false;
397
588
  for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
398
589
  const xi = polygon[i].x;
@@ -431,21 +622,133 @@ function createPolygonElement() {
431
622
  }
432
623
  function debugPolygon(polygon) {
433
624
  const el = createPolygonElement();
434
- const points = polygon.map((point2) => `${point2.x},${point2.y}`).join(" ");
625
+ const points = polygon.map((point) => `${point.x},${point.y}`).join(" ");
435
626
  el.setAttribute("points", points);
436
627
  return () => {
437
628
  el.remove();
438
629
  };
439
630
  }
631
+
632
+ // src/compass.ts
633
+ var compassDirectionMap = {
634
+ n: { x: 0.5, y: 0 },
635
+ ne: { x: 1, y: 0 },
636
+ e: { x: 1, y: 0.5 },
637
+ se: { x: 1, y: 1 },
638
+ s: { x: 0.5, y: 1 },
639
+ sw: { x: 0, y: 1 },
640
+ w: { x: 0, y: 0.5 },
641
+ nw: { x: 0, y: 0 }
642
+ };
643
+ var oppositeDirectionMap = {
644
+ n: "s",
645
+ ne: "sw",
646
+ e: "w",
647
+ se: "nw",
648
+ s: "n",
649
+ sw: "ne",
650
+ w: "e",
651
+ nw: "se"
652
+ };
653
+
654
+ // src/resize.ts
655
+ var { sign, abs, min: min2 } = Math;
656
+ function getRectExtentPoint(rect, direction) {
657
+ const { minX, minY, maxX, maxY, midX, midY } = rect;
658
+ const x = direction.includes("w") ? minX : direction.includes("e") ? maxX : midX;
659
+ const y = direction.includes("n") ? minY : direction.includes("s") ? maxY : midY;
660
+ return { x, y };
661
+ }
662
+ function getOppositeDirection(direction) {
663
+ return oppositeDirectionMap[direction];
664
+ }
665
+ function resizeRect(rect, offset, direction, opts) {
666
+ const { scalingOriginMode, lockAspectRatio } = opts;
667
+ const extent = getRectExtentPoint(rect, direction);
668
+ const oppositeDirection = getOppositeDirection(direction);
669
+ const oppositeExtent = getRectExtentPoint(rect, oppositeDirection);
670
+ if (scalingOriginMode === "center") {
671
+ offset = { x: offset.x * 2, y: offset.y * 2 };
672
+ }
673
+ const newExtent = {
674
+ x: extent.x + offset.x,
675
+ y: extent.y + offset.y
676
+ };
677
+ const multiplier = {
678
+ x: compassDirectionMap[direction].x * 2 - 1,
679
+ y: compassDirectionMap[direction].y * 2 - 1
680
+ };
681
+ const newSize = {
682
+ width: newExtent.x - oppositeExtent.x,
683
+ height: newExtent.y - oppositeExtent.y
684
+ };
685
+ const scaleX = multiplier.x * newSize.width / rect.width;
686
+ const scaleY = multiplier.y * newSize.height / rect.height;
687
+ const largestMagnitude = abs(scaleX) > abs(scaleY) ? scaleX : scaleY;
688
+ const scale = lockAspectRatio ? { x: largestMagnitude, y: largestMagnitude } : {
689
+ x: extent.x === oppositeExtent.x ? 1 : scaleX,
690
+ y: extent.y === oppositeExtent.y ? 1 : scaleY
691
+ };
692
+ if (extent.y === oppositeExtent.y) {
693
+ scale.y = abs(scale.y);
694
+ } else if (sign(scale.y) !== sign(scaleY)) {
695
+ scale.y *= -1;
696
+ }
697
+ if (extent.x === oppositeExtent.x) {
698
+ scale.x = abs(scale.x);
699
+ } else if (sign(scale.x) !== sign(scaleX)) {
700
+ scale.x *= -1;
701
+ }
702
+ switch (scalingOriginMode) {
703
+ case "extent":
704
+ return transformRect(rect, AffineTransform.scale(scale.x, scale.y, oppositeExtent), false);
705
+ case "center":
706
+ return transformRect(
707
+ rect,
708
+ AffineTransform.scale(scale.x, scale.y, {
709
+ x: rect.midX,
710
+ y: rect.midY
711
+ }),
712
+ false
713
+ );
714
+ }
715
+ }
716
+ function createRectFromPoints(initialPoint, finalPoint, normalized = true) {
717
+ if (normalized) {
718
+ return {
719
+ x: min2(finalPoint.x, initialPoint.x),
720
+ y: min2(finalPoint.y, initialPoint.y),
721
+ width: abs(finalPoint.x - initialPoint.x),
722
+ height: abs(finalPoint.y - initialPoint.y)
723
+ };
724
+ }
725
+ return {
726
+ x: initialPoint.x,
727
+ y: initialPoint.y,
728
+ width: finalPoint.x - initialPoint.x,
729
+ height: finalPoint.y - initialPoint.y
730
+ };
731
+ }
732
+ function transformRect(rect, transform, normalized = true) {
733
+ const p1 = transform.applyTo({ x: rect.minX, y: rect.minY });
734
+ const p2 = transform.applyTo({ x: rect.maxX, y: rect.maxY });
735
+ return createRectFromPoints(p1, p2, normalized);
736
+ }
440
737
  export {
738
+ AffineTransform,
739
+ addPoints,
441
740
  alignRect,
741
+ clampPoint,
742
+ clampSize,
442
743
  closest,
443
744
  closestSideToPoint,
444
745
  closestSideToRect,
445
746
  collisions,
747
+ constrainRect,
446
748
  contains,
447
749
  containsPoint,
448
750
  containsRect,
751
+ createPoint,
449
752
  createRect,
450
753
  debugPolygon,
451
754
  distance,
@@ -466,12 +769,18 @@ export {
466
769
  inset,
467
770
  intersection,
468
771
  intersects,
772
+ isPoint,
773
+ isPointEqual,
469
774
  isPointInPolygon,
470
775
  isRect,
776
+ isRectEqual,
777
+ isSizeEqual,
471
778
  isSymmetric,
779
+ resizeRect,
472
780
  rotate,
473
781
  shift,
474
782
  shrink,
783
+ subtractPoints,
475
784
  toRad,
476
785
  union
477
786
  };