@samirdamle/calipers 0.0.0-stage → 0.1.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.
@@ -0,0 +1,274 @@
1
+ // src/geom/index.ts
2
+ var ANCHOR_FRACTIONS = {
3
+ tl: [0, 0],
4
+ tc: [0.5, 0],
5
+ tr: [1, 0],
6
+ cl: [0, 0.5],
7
+ cc: [0.5, 0.5],
8
+ cr: [1, 0.5],
9
+ bl: [0, 1],
10
+ bc: [0.5, 1],
11
+ br: [1, 1],
12
+ t: [0.5, 0],
13
+ b: [0.5, 1],
14
+ l: [0, 0.5],
15
+ r: [1, 0.5]
16
+ };
17
+ function anchorPoint(rect, anchor = "cc") {
18
+ if (typeof anchor === "function") return anchor(rect);
19
+ const [fx, fy] = typeof anchor === "string" ? ANCHOR_FRACTIONS[anchor] : "x" in anchor ? [anchor.x, anchor.y] : anchor;
20
+ return { x: rect.x + fx * rect.width, y: rect.y + fy * rect.height };
21
+ }
22
+ function distanceBetween(a, b) {
23
+ return Math.hypot(a.x - b.x, a.y - b.y);
24
+ }
25
+ function angleBetween(from, to) {
26
+ return Math.atan2(to.y - from.y, to.x - from.x);
27
+ }
28
+ function gapBetween(a, b) {
29
+ return {
30
+ x: Math.max(0, Math.max(b.x - (a.x + a.width), a.x - (b.x + b.width))),
31
+ y: Math.max(0, Math.max(b.y - (a.y + a.height), a.y - (b.y + b.height)))
32
+ };
33
+ }
34
+ function overlapArea(a, b) {
35
+ const w = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);
36
+ const h = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y);
37
+ return Math.max(0, w) * Math.max(0, h);
38
+ }
39
+ function overlaps(a, b) {
40
+ return overlapArea(a, b) > 0;
41
+ }
42
+ function containsRect(outer, inner) {
43
+ return outer.x <= inner.x && outer.y <= inner.y && outer.x + outer.width >= inner.x + inner.width && outer.y + outer.height >= inner.y + inner.height;
44
+ }
45
+
46
+ // src/internal/dom.ts
47
+ function isElement(v) {
48
+ return typeof Element !== "undefined" && v instanceof Element;
49
+ }
50
+ function px(value) {
51
+ const n = parseFloat(value);
52
+ return Number.isFinite(n) ? n : 0;
53
+ }
54
+
55
+ // src/rect/index.ts
56
+ function rectOf(target, options = {}) {
57
+ const { box = "border", space = "viewport" } = options;
58
+ const t = classify(target);
59
+ switch (t.kind) {
60
+ case "rect":
61
+ return { ...t.rect };
62
+ case "viewport":
63
+ return moveSpace(
64
+ {
65
+ x: 0,
66
+ y: 0,
67
+ width: window.innerWidth,
68
+ height: window.innerHeight
69
+ },
70
+ "viewport",
71
+ space
72
+ );
73
+ case "element":
74
+ return elementRect(t.el, box, space);
75
+ }
76
+ }
77
+ function classify(target) {
78
+ if (target === "viewport" || target === window) return { kind: "viewport" };
79
+ if (typeof target === "string") {
80
+ const el = document.querySelector(target);
81
+ if (!el)
82
+ throw new Error(`calipers: no element matches selector "${target}"`);
83
+ return { kind: "element", el };
84
+ }
85
+ if (isElement(target)) return { kind: "element", el: target };
86
+ if (isRectLike(target)) return { kind: "rect", rect: target };
87
+ if (isPointLike(target))
88
+ return {
89
+ kind: "rect",
90
+ rect: { x: target.x, y: target.y, width: 0, height: 0 }
91
+ };
92
+ const first = target[0];
93
+ if (first == null)
94
+ throw new Error("calipers: empty list has no measurable to resolve");
95
+ return classify(first);
96
+ }
97
+ function isPointLike(v) {
98
+ return typeof v === "object" && v !== null && typeof v.x === "number" && typeof v.y === "number" && typeof v.width !== "number";
99
+ }
100
+ function isRectLike(v) {
101
+ return typeof v === "object" && v !== null && typeof v.x === "number" && typeof v.y === "number" && typeof v.width === "number" && typeof v.height === "number";
102
+ }
103
+ function isSVGGraphics(el) {
104
+ return typeof SVGGraphicsElement !== "undefined" && el instanceof SVGGraphicsElement;
105
+ }
106
+ function elementRect(el, box, space) {
107
+ return isSVGGraphics(el) ? svgRect(el, box, space) : htmlRect(el, box, space);
108
+ }
109
+ function htmlRect(el, box, space) {
110
+ if (box === "visual") {
111
+ const r = el.getBoundingClientRect();
112
+ return moveSpace(
113
+ { x: r.x, y: r.y, width: r.width, height: r.height },
114
+ "viewport",
115
+ space
116
+ );
117
+ }
118
+ const border = layoutBorderBox(el);
119
+ const cs = getComputedStyle(el);
120
+ let rect;
121
+ if (box === "content") {
122
+ const bl = px(cs.borderLeftWidth);
123
+ const br = px(cs.borderRightWidth);
124
+ const bt = px(cs.borderTopWidth);
125
+ const bb = px(cs.borderBottomWidth);
126
+ const pl = px(cs.paddingLeft);
127
+ const pr = px(cs.paddingRight);
128
+ const pt = px(cs.paddingTop);
129
+ const pb = px(cs.paddingBottom);
130
+ rect = {
131
+ x: border.x + bl + pl,
132
+ y: border.y + bt + pt,
133
+ width: Math.max(0, border.width - bl - br - pl - pr),
134
+ height: Math.max(0, border.height - bt - bb - pt - pb)
135
+ };
136
+ } else if (box === "margin") {
137
+ const ml = px(cs.marginLeft);
138
+ const mr = px(cs.marginRight);
139
+ const mt = px(cs.marginTop);
140
+ const mb = px(cs.marginBottom);
141
+ rect = {
142
+ x: border.x - ml,
143
+ y: border.y - mt,
144
+ width: border.width + ml + mr,
145
+ height: border.height + mt + mb
146
+ };
147
+ } else {
148
+ rect = border;
149
+ }
150
+ return moveSpace(rect, "document", space);
151
+ }
152
+ function svgRect(el, box, space) {
153
+ if (box === "bbox") {
154
+ const b = el.getBBox();
155
+ return { x: b.x, y: b.y, width: b.width, height: b.height };
156
+ }
157
+ const r = el.getBoundingClientRect();
158
+ return moveSpace(
159
+ { x: r.x, y: r.y, width: r.width, height: r.height },
160
+ "viewport",
161
+ space
162
+ );
163
+ }
164
+ function layoutBorderBox(el) {
165
+ let x = 0;
166
+ let y = 0;
167
+ let node = el;
168
+ const fixed = getComputedStyle(el).position === "fixed";
169
+ while (node) {
170
+ x += node.offsetLeft;
171
+ y += node.offsetTop;
172
+ node = node.offsetParent;
173
+ }
174
+ if (fixed) {
175
+ x += window.scrollX;
176
+ y += window.scrollY;
177
+ }
178
+ return { x, y, width: el.offsetWidth, height: el.offsetHeight };
179
+ }
180
+ function moveSpace(rect, from, to) {
181
+ if (from === to) return rect;
182
+ const dx = from === "viewport" ? window.scrollX : -window.scrollX;
183
+ const dy = from === "viewport" ? window.scrollY : -window.scrollY;
184
+ return {
185
+ x: rect.x + dx,
186
+ y: rect.y + dy,
187
+ width: rect.width,
188
+ height: rect.height
189
+ };
190
+ }
191
+
192
+ // src/measure/index.ts
193
+ var ALL_FIELDS = [
194
+ "dx",
195
+ "dy",
196
+ "distance",
197
+ "gapX",
198
+ "gapY",
199
+ "angleDeg",
200
+ "angleRad",
201
+ "width",
202
+ "height",
203
+ "overlaps",
204
+ "overlapArea",
205
+ "contains",
206
+ "visible"
207
+ ];
208
+ function measure(a, b, options = {}) {
209
+ const {
210
+ anchor = "cc",
211
+ ofAnchor = "cc",
212
+ fields = ALL_FIELDS,
213
+ box,
214
+ space
215
+ } = options;
216
+ const rectOptions = { box, space };
217
+ const ra = rectOf(a, rectOptions);
218
+ const rb = rectOf(b, rectOptions);
219
+ const pointA = anchorPoint(ra, anchor);
220
+ const pointB = anchorPoint(rb, ofAnchor);
221
+ const result = { target: a, source: b, pointA, pointB };
222
+ const want = new Set(fields);
223
+ if (want.has("dx") || want.has("dy") || want.has("distance") || want.has("angleDeg") || want.has("angleRad")) {
224
+ const dx = pointA.x - pointB.x;
225
+ const dy = pointA.y - pointB.y;
226
+ if (want.has("dx")) result.dx = dx;
227
+ if (want.has("dy")) result.dy = dy;
228
+ if (want.has("distance")) result.distance = Math.hypot(dx, dy);
229
+ if (want.has("angleDeg") || want.has("angleRad")) {
230
+ const rad = Math.atan2(dy, dx);
231
+ if (want.has("angleRad")) result.angleRad = rad;
232
+ if (want.has("angleDeg")) result.angleDeg = rad * 180 / Math.PI;
233
+ }
234
+ }
235
+ if (want.has("gapX") || want.has("gapY")) {
236
+ const gap = gapBetween(ra, rb);
237
+ if (want.has("gapX")) result.gapX = gap.x;
238
+ if (want.has("gapY")) result.gapY = gap.y;
239
+ }
240
+ if (want.has("width")) result.width = ra.width;
241
+ if (want.has("height")) result.height = ra.height;
242
+ if (want.has("overlaps") || want.has("overlapArea")) {
243
+ const area = overlapArea(ra, rb);
244
+ if (want.has("overlapArea")) result.overlapArea = area;
245
+ if (want.has("overlaps")) result.overlaps = area > 0;
246
+ }
247
+ if (want.has("contains")) result.contains = containsRect(ra, rb);
248
+ if (want.has("visible"))
249
+ result.visible = overlapArea(ra, rectOf("viewport", { space: space ?? "viewport" })) > 0;
250
+ return result;
251
+ }
252
+ function calipers(targets, source, options = {}) {
253
+ return expandTargets(targets).map((t) => measure(t, source, options));
254
+ }
255
+ function expandTargets(targets) {
256
+ if (typeof targets === "string")
257
+ return Array.from(document.querySelectorAll(targets));
258
+ if (targets === window || targets === "viewport") return [targets];
259
+ if (isList(targets)) {
260
+ const out = [];
261
+ for (const e of Array.from(targets)) {
262
+ if (typeof e === "string")
263
+ out.push(...Array.from(document.querySelectorAll(e)));
264
+ else out.push(e);
265
+ }
266
+ return out;
267
+ }
268
+ return [targets];
269
+ }
270
+ function isList(v) {
271
+ return typeof v === "object" && v !== null && typeof v.length === "number" && !(v instanceof Element);
272
+ }
273
+
274
+ export { anchorPoint, angleBetween, calipers, containsRect, distanceBetween, gapBetween, measure, overlapArea, overlaps };
@@ -0,0 +1,45 @@
1
+ import { A as Anchor, M as Measurable, P as Point, R as Rect, G as Gap } from './types-PJD4F9tg.js';
2
+
3
+ interface PlaceAt {
4
+ /** Anchor of the `of` target. @default 'cc' */
5
+ anchor?: Anchor;
6
+ /** What to place against. @default 'viewport' */
7
+ of?: Measurable | Point | Rect;
8
+ }
9
+ interface PlaceOptions {
10
+ /** Which point of `el` to position. @default 'tl' */
11
+ anchor?: Anchor;
12
+ /**
13
+ * Target: `{ anchor, of }`, a raw viewport point, or a rect.
14
+ * @default viewport center
15
+ */
16
+ at?: PlaceAt | Point | Rect;
17
+ /** Extra shift in px. */
18
+ offset?: {
19
+ x?: number;
20
+ y?: number;
21
+ };
22
+ /**
23
+ * Gap in px between the placed box and the target. Unlike `offset`
24
+ * (a raw signed shift), the gap pushes the box *away* from the target
25
+ * along the ray from the anchor through the box center — e.g.
26
+ * `place(tip, { anchor: 'tc', at: { anchor: 'bc', of: btn }, gap: 8 })`
27
+ * puts the tooltip 8px below the button. A center anchor has no
28
+ * direction, so the gap is a no-op there (use `offset` instead).
29
+ */
30
+ gap?: Gap;
31
+ /**
32
+ * `transform` (default): sets the CSS `translate` property — compositor-friendly,
33
+ * composes with `transform`, accumulates across calls.
34
+ * `position`: sets `left`/`top` (upgrades `static` to `absolute`);
35
+ * exact for absolute/fixed positioning.
36
+ */
37
+ using?: 'transform' | 'position';
38
+ }
39
+ /**
40
+ * Position `el` so its anchor lands on the target point, plus `offset` and `gap`.
41
+ * Reads layout once per call. Repeating the same call is a no-op.
42
+ */
43
+ declare function place(el: HTMLElement, options?: PlaceOptions): void;
44
+
45
+ export { type PlaceAt, type PlaceOptions, place };
package/dist/place.js ADDED
@@ -0,0 +1,274 @@
1
+ // src/geom/index.ts
2
+ var ANCHOR_FRACTIONS = {
3
+ tl: [0, 0],
4
+ tc: [0.5, 0],
5
+ tr: [1, 0],
6
+ cl: [0, 0.5],
7
+ cc: [0.5, 0.5],
8
+ cr: [1, 0.5],
9
+ bl: [0, 1],
10
+ bc: [0.5, 1],
11
+ br: [1, 1],
12
+ t: [0.5, 0],
13
+ b: [0.5, 1],
14
+ l: [0, 0.5],
15
+ r: [1, 0.5]
16
+ };
17
+ function anchorPoint(rect, anchor = "cc") {
18
+ if (typeof anchor === "function") return anchor(rect);
19
+ const [fx, fy] = typeof anchor === "string" ? ANCHOR_FRACTIONS[anchor] : "x" in anchor ? [anchor.x, anchor.y] : anchor;
20
+ return { x: rect.x + fx * rect.width, y: rect.y + fy * rect.height };
21
+ }
22
+
23
+ // src/internal/dom.ts
24
+ function isElement(v) {
25
+ return typeof Element !== "undefined" && v instanceof Element;
26
+ }
27
+ function px(value) {
28
+ const n = parseFloat(value);
29
+ return Number.isFinite(n) ? n : 0;
30
+ }
31
+ function parseTranslate(value) {
32
+ if (!value || value === "none") return { x: 0, y: 0 };
33
+ const [x = "0", y = "0"] = value.trim().split(/\s+/);
34
+ return { x: px(x), y: px(y) };
35
+ }
36
+ function getTranslate(el) {
37
+ return parseTranslate(getComputedStyle(el).translate);
38
+ }
39
+ function shiftTranslate(el, prev, dx, dy) {
40
+ if (dx === 0 && dy === 0) return;
41
+ el.style.setProperty("translate", `${prev.x + dx}px ${prev.y + dy}px`);
42
+ }
43
+
44
+ // src/internal/gap.ts
45
+ function normalizeGap(gap) {
46
+ if (gap === void 0) return { x: 0, y: 0 };
47
+ if (typeof gap === "number") return { x: gap, y: gap };
48
+ if ("x" in gap) return { x: gap.x, y: gap.y };
49
+ return { x: gap[0], y: gap[1] };
50
+ }
51
+
52
+ // src/rect/index.ts
53
+ function rectOf(target, options = {}) {
54
+ const { box = "border", space = "viewport" } = options;
55
+ const t = classify(target);
56
+ switch (t.kind) {
57
+ case "rect":
58
+ return { ...t.rect };
59
+ case "viewport":
60
+ return moveSpace(
61
+ {
62
+ x: 0,
63
+ y: 0,
64
+ width: window.innerWidth,
65
+ height: window.innerHeight
66
+ },
67
+ "viewport",
68
+ space
69
+ );
70
+ case "element":
71
+ return elementRect(t.el, box, space);
72
+ }
73
+ }
74
+ function classify(target) {
75
+ if (target === "viewport" || target === window) return { kind: "viewport" };
76
+ if (typeof target === "string") {
77
+ const el = document.querySelector(target);
78
+ if (!el)
79
+ throw new Error(`calipers: no element matches selector "${target}"`);
80
+ return { kind: "element", el };
81
+ }
82
+ if (isElement(target)) return { kind: "element", el: target };
83
+ if (isRectLike(target)) return { kind: "rect", rect: target };
84
+ if (isPointLike(target))
85
+ return {
86
+ kind: "rect",
87
+ rect: { x: target.x, y: target.y, width: 0, height: 0 }
88
+ };
89
+ const first = target[0];
90
+ if (first == null)
91
+ throw new Error("calipers: empty list has no measurable to resolve");
92
+ return classify(first);
93
+ }
94
+ function isPointLike(v) {
95
+ return typeof v === "object" && v !== null && typeof v.x === "number" && typeof v.y === "number" && typeof v.width !== "number";
96
+ }
97
+ function isRectLike(v) {
98
+ return typeof v === "object" && v !== null && typeof v.x === "number" && typeof v.y === "number" && typeof v.width === "number" && typeof v.height === "number";
99
+ }
100
+ function isSVGGraphics(el) {
101
+ return typeof SVGGraphicsElement !== "undefined" && el instanceof SVGGraphicsElement;
102
+ }
103
+ function elementRect(el, box, space) {
104
+ return isSVGGraphics(el) ? svgRect(el, box, space) : htmlRect(el, box, space);
105
+ }
106
+ function htmlRect(el, box, space) {
107
+ if (box === "visual") {
108
+ const r = el.getBoundingClientRect();
109
+ return moveSpace(
110
+ { x: r.x, y: r.y, width: r.width, height: r.height },
111
+ "viewport",
112
+ space
113
+ );
114
+ }
115
+ const border = layoutBorderBox(el);
116
+ const cs = getComputedStyle(el);
117
+ let rect;
118
+ if (box === "content") {
119
+ const bl = px(cs.borderLeftWidth);
120
+ const br = px(cs.borderRightWidth);
121
+ const bt = px(cs.borderTopWidth);
122
+ const bb = px(cs.borderBottomWidth);
123
+ const pl = px(cs.paddingLeft);
124
+ const pr = px(cs.paddingRight);
125
+ const pt = px(cs.paddingTop);
126
+ const pb = px(cs.paddingBottom);
127
+ rect = {
128
+ x: border.x + bl + pl,
129
+ y: border.y + bt + pt,
130
+ width: Math.max(0, border.width - bl - br - pl - pr),
131
+ height: Math.max(0, border.height - bt - bb - pt - pb)
132
+ };
133
+ } else if (box === "margin") {
134
+ const ml = px(cs.marginLeft);
135
+ const mr = px(cs.marginRight);
136
+ const mt = px(cs.marginTop);
137
+ const mb = px(cs.marginBottom);
138
+ rect = {
139
+ x: border.x - ml,
140
+ y: border.y - mt,
141
+ width: border.width + ml + mr,
142
+ height: border.height + mt + mb
143
+ };
144
+ } else {
145
+ rect = border;
146
+ }
147
+ return moveSpace(rect, "document", space);
148
+ }
149
+ function svgRect(el, box, space) {
150
+ if (box === "bbox") {
151
+ const b = el.getBBox();
152
+ return { x: b.x, y: b.y, width: b.width, height: b.height };
153
+ }
154
+ const r = el.getBoundingClientRect();
155
+ return moveSpace(
156
+ { x: r.x, y: r.y, width: r.width, height: r.height },
157
+ "viewport",
158
+ space
159
+ );
160
+ }
161
+ function layoutBorderBox(el) {
162
+ let x = 0;
163
+ let y = 0;
164
+ let node = el;
165
+ const fixed = getComputedStyle(el).position === "fixed";
166
+ while (node) {
167
+ x += node.offsetLeft;
168
+ y += node.offsetTop;
169
+ node = node.offsetParent;
170
+ }
171
+ if (fixed) {
172
+ x += window.scrollX;
173
+ y += window.scrollY;
174
+ }
175
+ return { x, y, width: el.offsetWidth, height: el.offsetHeight };
176
+ }
177
+ function moveSpace(rect, from, to) {
178
+ if (from === to) return rect;
179
+ const dx = from === "viewport" ? window.scrollX : -window.scrollX;
180
+ const dy = from === "viewport" ? window.scrollY : -window.scrollY;
181
+ return {
182
+ x: rect.x + dx,
183
+ y: rect.y + dy,
184
+ width: rect.width,
185
+ height: rect.height
186
+ };
187
+ }
188
+
189
+ // src/internal/rendered.ts
190
+ function rendered(el, box) {
191
+ const rect = rectOf(el, { box, space: "viewport" });
192
+ const translate = getTranslate(el);
193
+ {
194
+ return { rect, translate };
195
+ }
196
+ }
197
+
198
+ // src/place/index.ts
199
+ function place(el, options = {}) {
200
+ const { anchor = "tl", offset = {}, using = "transform" } = options;
201
+ const ox = offset.x ?? 0;
202
+ const oy = offset.y ?? 0;
203
+ const gap = normalizeGap(options.gap);
204
+ if (using === "transform") {
205
+ const target = targetPoint(options.at, "viewport", "visual");
206
+ const { rect, translate } = rendered(el, "visual");
207
+ const cur = anchorPoint(rect, anchor);
208
+ const dir = gapDirection(rect, anchor);
209
+ shiftTranslate(
210
+ el,
211
+ translate,
212
+ target.x + ox + gap.x * dir.x - cur.x,
213
+ target.y + oy + gap.y * dir.y - cur.y
214
+ );
215
+ } else {
216
+ placeByPosition(
217
+ el,
218
+ anchor,
219
+ targetPoint(options.at, "document"),
220
+ ox,
221
+ oy,
222
+ gap
223
+ );
224
+ }
225
+ }
226
+ function gapDirection(rect, anchor) {
227
+ const c = anchorPoint(rect, "cc");
228
+ const p = anchorPoint(rect, anchor);
229
+ return { x: Math.sign(c.x - p.x), y: Math.sign(c.y - p.y) };
230
+ }
231
+ function targetPoint(at, space, box = "border") {
232
+ if (!at) return anchorPoint(rectOf("viewport", { space }), "cc");
233
+ if (isRawPoint(at)) {
234
+ return space === "document" ? { x: at.x + window.scrollX, y: at.y + window.scrollY } : { ...at };
235
+ }
236
+ const placeAt = at;
237
+ const of = typeof at.width === "number" ? at : placeAt.of ?? "viewport";
238
+ if (isRawPoint(of)) {
239
+ return space === "document" ? { x: of.x + window.scrollX, y: of.y + window.scrollY } : { ...of };
240
+ }
241
+ return anchorPoint(rectOf(of, { box, space }), placeAt.anchor ?? "cc");
242
+ }
243
+ function isRawPoint(v) {
244
+ return typeof v === "object" && v !== null && typeof v.x === "number" && typeof v.y === "number" && typeof v.width !== "number";
245
+ }
246
+ function placeByPosition(el, anchor, target, ox, oy, gap) {
247
+ const cs = getComputedStyle(el);
248
+ const positioned = cs.position === "static" ? "absolute" : cs.position;
249
+ if (cs.position === "static") el.style.position = "absolute";
250
+ const op = el.offsetParent;
251
+ const border = rectOf(el, { box: "border", space: "document" });
252
+ const a = anchorPoint(
253
+ { x: 0, y: 0, width: border.width, height: border.height },
254
+ anchor
255
+ );
256
+ const dir = gapDirection(border, anchor);
257
+ const ml = px(cs.marginLeft);
258
+ const mt = px(cs.marginTop);
259
+ let fx = target.x;
260
+ let fy = target.y;
261
+ if (op) {
262
+ const ob = rectOf(op, { box: "border", space: "document" });
263
+ const ocs = getComputedStyle(op);
264
+ fx -= ob.x + px(ocs.borderLeftWidth);
265
+ fy -= ob.y + px(ocs.borderTopWidth);
266
+ } else if (positioned === "fixed") {
267
+ fx -= window.scrollX;
268
+ fy -= window.scrollY;
269
+ }
270
+ el.style.left = `${fx + ox + gap.x * dir.x - a.x - ml}px`;
271
+ el.style.top = `${fy + oy + gap.y * dir.y - a.y - mt}px`;
272
+ }
273
+
274
+ export { place };
package/dist/rect.d.ts ADDED
@@ -0,0 +1,27 @@
1
+ import { B as Box, S as Space, M as Measurable, R as Rect } from './types-PJD4F9tg.js';
2
+
3
+ interface RectOptions {
4
+ /**
5
+ * Which box to measure.
6
+ * - `border` (default): layout border box, no transforms.
7
+ * - `content` / `margin`: derived from the border box via computed style.
8
+ * - `visual`: `getBoundingClientRect()`, including CSS transforms.
9
+ * - `bbox`: SVG only — `getBBox()` in local user units, untransformed.
10
+ * For HTML elements it falls back to `border`.
11
+ */
12
+ box?: Box;
13
+ /**
14
+ * Coordinate space of the result. `viewport` rects shift on scroll;
15
+ * `document` rects don't. `bbox` results are always in local SVG units.
16
+ * @default 'viewport'
17
+ */
18
+ space?: Space;
19
+ }
20
+ /**
21
+ * Resolve any measurable into a normalized `{ x, y, width, height }` rect.
22
+ * A `Point` resolves to a zero-size rect at that point. Lists resolve their
23
+ * first entry. Reads layout exactly once per call.
24
+ */
25
+ declare function rectOf(target: Measurable, options?: RectOptions): Rect;
26
+
27
+ export { type RectOptions, rectOf };