@oyerinde/caliper 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.
package/dist/index.cjs ADDED
@@ -0,0 +1,4999 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * @license MIT
5
+ *
6
+ * Caliper - Browser Measurement Tool
7
+ *
8
+ * This source code is licensed under the MIT license found in the
9
+ * LICENSE file in the root directory of this source tree.
10
+ */
11
+
12
+ var IS_DEV = false;
13
+ var equalFn = (a, b) => a === b;
14
+ var $TRACK = /* @__PURE__ */ Symbol("solid-track");
15
+ var signalOptions = {
16
+ equals: equalFn
17
+ };
18
+ var runEffects = runQueue;
19
+ var STALE = 1;
20
+ var PENDING = 2;
21
+ var UNOWNED = {
22
+ owned: null,
23
+ cleanups: null,
24
+ context: null,
25
+ owner: null
26
+ };
27
+ var Owner = null;
28
+ var Transition = null;
29
+ var ExternalSourceConfig = null;
30
+ var Listener = null;
31
+ var Updates = null;
32
+ var Effects = null;
33
+ var ExecCount = 0;
34
+ function createRoot(fn, detachedOwner) {
35
+ const listener = Listener, owner = Owner, unowned = fn.length === 0, current = detachedOwner === void 0 ? owner : detachedOwner, root = unowned ? UNOWNED : {
36
+ owned: null,
37
+ cleanups: null,
38
+ context: current ? current.context : null,
39
+ owner: current
40
+ }, updateFn = unowned ? fn : () => fn(() => untrack(() => cleanNode(root)));
41
+ Owner = root;
42
+ Listener = null;
43
+ try {
44
+ return runUpdates(updateFn, true);
45
+ } finally {
46
+ Listener = listener;
47
+ Owner = owner;
48
+ }
49
+ }
50
+ function createSignal(value, options) {
51
+ options = options ? Object.assign({}, signalOptions, options) : signalOptions;
52
+ const s = {
53
+ value,
54
+ observers: null,
55
+ observerSlots: null,
56
+ comparator: options.equals || void 0
57
+ };
58
+ const setter = (value2) => {
59
+ if (typeof value2 === "function") {
60
+ value2 = value2(s.value);
61
+ }
62
+ return writeSignal(s, value2);
63
+ };
64
+ return [readSignal.bind(s), setter];
65
+ }
66
+ function createRenderEffect(fn, value, options) {
67
+ const c = createComputation(fn, value, false, STALE);
68
+ updateComputation(c);
69
+ }
70
+ function createEffect(fn, value, options) {
71
+ runEffects = runUserEffects;
72
+ const c = createComputation(fn, value, false, STALE);
73
+ if (!options || !options.render) c.user = true;
74
+ Effects ? Effects.push(c) : updateComputation(c);
75
+ }
76
+ function createMemo(fn, value, options) {
77
+ options = options ? Object.assign({}, signalOptions, options) : signalOptions;
78
+ const c = createComputation(fn, value, true, 0);
79
+ c.observers = null;
80
+ c.observerSlots = null;
81
+ c.comparator = options.equals || void 0;
82
+ updateComputation(c);
83
+ return readSignal.bind(c);
84
+ }
85
+ function untrack(fn) {
86
+ if (Listener === null) return fn();
87
+ const listener = Listener;
88
+ Listener = null;
89
+ try {
90
+ if (ExternalSourceConfig) ;
91
+ return fn();
92
+ } finally {
93
+ Listener = listener;
94
+ }
95
+ }
96
+ function on(deps, fn, options) {
97
+ const isArray = Array.isArray(deps);
98
+ let prevInput;
99
+ return (prevValue) => {
100
+ let input;
101
+ if (isArray) {
102
+ input = Array(deps.length);
103
+ for (let i = 0; i < deps.length; i++) input[i] = deps[i]();
104
+ } else input = deps();
105
+ const result = untrack(() => fn(input, prevInput, prevValue));
106
+ prevInput = input;
107
+ return result;
108
+ };
109
+ }
110
+ function onMount(fn) {
111
+ createEffect(() => untrack(fn));
112
+ }
113
+ function onCleanup(fn) {
114
+ if (Owner === null) ;
115
+ else if (Owner.cleanups === null) Owner.cleanups = [fn];
116
+ else Owner.cleanups.push(fn);
117
+ return fn;
118
+ }
119
+ function getOwner() {
120
+ return Owner;
121
+ }
122
+ function runWithOwner(o, fn) {
123
+ const prev = Owner;
124
+ const prevListener = Listener;
125
+ Owner = o;
126
+ Listener = null;
127
+ try {
128
+ return runUpdates(fn, true);
129
+ } catch (err) {
130
+ handleError(err);
131
+ } finally {
132
+ Owner = prev;
133
+ Listener = prevListener;
134
+ }
135
+ }
136
+ var [transPending, setTransPending] = /* @__PURE__ */ createSignal(false);
137
+ function readSignal() {
138
+ if (this.sources && (this.state)) {
139
+ if ((this.state) === STALE) updateComputation(this);
140
+ else {
141
+ const updates = Updates;
142
+ Updates = null;
143
+ runUpdates(() => lookUpstream(this), false);
144
+ Updates = updates;
145
+ }
146
+ }
147
+ if (Listener) {
148
+ const sSlot = this.observers ? this.observers.length : 0;
149
+ if (!Listener.sources) {
150
+ Listener.sources = [this];
151
+ Listener.sourceSlots = [sSlot];
152
+ } else {
153
+ Listener.sources.push(this);
154
+ Listener.sourceSlots.push(sSlot);
155
+ }
156
+ if (!this.observers) {
157
+ this.observers = [Listener];
158
+ this.observerSlots = [Listener.sources.length - 1];
159
+ } else {
160
+ this.observers.push(Listener);
161
+ this.observerSlots.push(Listener.sources.length - 1);
162
+ }
163
+ }
164
+ return this.value;
165
+ }
166
+ function writeSignal(node, value, isComp) {
167
+ let current = node.value;
168
+ if (!node.comparator || !node.comparator(current, value)) {
169
+ node.value = value;
170
+ if (node.observers && node.observers.length) {
171
+ runUpdates(() => {
172
+ for (let i = 0; i < node.observers.length; i += 1) {
173
+ const o = node.observers[i];
174
+ const TransitionRunning = Transition && Transition.running;
175
+ if (TransitionRunning && Transition.disposed.has(o)) ;
176
+ if (TransitionRunning ? !o.tState : !o.state) {
177
+ if (o.pure) Updates.push(o);
178
+ else Effects.push(o);
179
+ if (o.observers) markDownstream(o);
180
+ }
181
+ if (!TransitionRunning) o.state = STALE;
182
+ }
183
+ if (Updates.length > 1e6) {
184
+ Updates = [];
185
+ if (IS_DEV) ;
186
+ throw new Error();
187
+ }
188
+ }, false);
189
+ }
190
+ }
191
+ return value;
192
+ }
193
+ function updateComputation(node) {
194
+ if (!node.fn) return;
195
+ cleanNode(node);
196
+ const time = ExecCount;
197
+ runComputation(node, node.value, time);
198
+ }
199
+ function runComputation(node, value, time) {
200
+ let nextValue;
201
+ const owner = Owner, listener = Listener;
202
+ Listener = Owner = node;
203
+ try {
204
+ nextValue = node.fn(value);
205
+ } catch (err) {
206
+ if (node.pure) {
207
+ {
208
+ node.state = STALE;
209
+ node.owned && node.owned.forEach(cleanNode);
210
+ node.owned = null;
211
+ }
212
+ }
213
+ node.updatedAt = time + 1;
214
+ return handleError(err);
215
+ } finally {
216
+ Listener = listener;
217
+ Owner = owner;
218
+ }
219
+ if (!node.updatedAt || node.updatedAt <= time) {
220
+ if (node.updatedAt != null && "observers" in node) {
221
+ writeSignal(node, nextValue);
222
+ } else node.value = nextValue;
223
+ node.updatedAt = time;
224
+ }
225
+ }
226
+ function createComputation(fn, init, pure, state = STALE, options) {
227
+ const c = {
228
+ fn,
229
+ state,
230
+ updatedAt: null,
231
+ owned: null,
232
+ sources: null,
233
+ sourceSlots: null,
234
+ cleanups: null,
235
+ value: init,
236
+ owner: Owner,
237
+ context: Owner ? Owner.context : null,
238
+ pure
239
+ };
240
+ if (Owner === null) ;
241
+ else if (Owner !== UNOWNED) {
242
+ {
243
+ if (!Owner.owned) Owner.owned = [c];
244
+ else Owner.owned.push(c);
245
+ }
246
+ }
247
+ return c;
248
+ }
249
+ function runTop(node) {
250
+ if ((node.state) === 0) return;
251
+ if ((node.state) === PENDING) return lookUpstream(node);
252
+ if (node.suspense && untrack(node.suspense.inFallback)) return node.suspense.effects.push(node);
253
+ const ancestors = [node];
254
+ while ((node = node.owner) && (!node.updatedAt || node.updatedAt < ExecCount)) {
255
+ if (node.state) ancestors.push(node);
256
+ }
257
+ for (let i = ancestors.length - 1; i >= 0; i--) {
258
+ node = ancestors[i];
259
+ if ((node.state) === STALE) {
260
+ updateComputation(node);
261
+ } else if ((node.state) === PENDING) {
262
+ const updates = Updates;
263
+ Updates = null;
264
+ runUpdates(() => lookUpstream(node, ancestors[0]), false);
265
+ Updates = updates;
266
+ }
267
+ }
268
+ }
269
+ function runUpdates(fn, init) {
270
+ if (Updates) return fn();
271
+ let wait = false;
272
+ if (!init) Updates = [];
273
+ if (Effects) wait = true;
274
+ else Effects = [];
275
+ ExecCount++;
276
+ try {
277
+ const res = fn();
278
+ completeUpdates(wait);
279
+ return res;
280
+ } catch (err) {
281
+ if (!wait) Effects = null;
282
+ Updates = null;
283
+ handleError(err);
284
+ }
285
+ }
286
+ function completeUpdates(wait) {
287
+ if (Updates) {
288
+ runQueue(Updates);
289
+ Updates = null;
290
+ }
291
+ if (wait) return;
292
+ const e = Effects;
293
+ Effects = null;
294
+ if (e.length) runUpdates(() => runEffects(e), false);
295
+ }
296
+ function runQueue(queue) {
297
+ for (let i = 0; i < queue.length; i++) runTop(queue[i]);
298
+ }
299
+ function runUserEffects(queue) {
300
+ let i, userLength = 0;
301
+ for (i = 0; i < queue.length; i++) {
302
+ const e = queue[i];
303
+ if (!e.user) runTop(e);
304
+ else queue[userLength++] = e;
305
+ }
306
+ for (i = 0; i < userLength; i++) runTop(queue[i]);
307
+ }
308
+ function lookUpstream(node, ignore) {
309
+ node.state = 0;
310
+ for (let i = 0; i < node.sources.length; i += 1) {
311
+ const source = node.sources[i];
312
+ if (source.sources) {
313
+ const state = source.state;
314
+ if (state === STALE) {
315
+ if (source !== ignore && (!source.updatedAt || source.updatedAt < ExecCount)) runTop(source);
316
+ } else if (state === PENDING) lookUpstream(source, ignore);
317
+ }
318
+ }
319
+ }
320
+ function markDownstream(node) {
321
+ for (let i = 0; i < node.observers.length; i += 1) {
322
+ const o = node.observers[i];
323
+ if (!o.state) {
324
+ o.state = PENDING;
325
+ if (o.pure) Updates.push(o);
326
+ else Effects.push(o);
327
+ o.observers && markDownstream(o);
328
+ }
329
+ }
330
+ }
331
+ function cleanNode(node) {
332
+ let i;
333
+ if (node.sources) {
334
+ while (node.sources.length) {
335
+ const source = node.sources.pop(), index = node.sourceSlots.pop(), obs = source.observers;
336
+ if (obs && obs.length) {
337
+ const n = obs.pop(), s = source.observerSlots.pop();
338
+ if (index < obs.length) {
339
+ n.sourceSlots[s] = index;
340
+ obs[index] = n;
341
+ source.observerSlots[index] = s;
342
+ }
343
+ }
344
+ }
345
+ }
346
+ if (node.tOwned) {
347
+ for (i = node.tOwned.length - 1; i >= 0; i--) cleanNode(node.tOwned[i]);
348
+ delete node.tOwned;
349
+ }
350
+ if (node.owned) {
351
+ for (i = node.owned.length - 1; i >= 0; i--) cleanNode(node.owned[i]);
352
+ node.owned = null;
353
+ }
354
+ if (node.cleanups) {
355
+ for (i = node.cleanups.length - 1; i >= 0; i--) node.cleanups[i]();
356
+ node.cleanups = null;
357
+ }
358
+ node.state = 0;
359
+ }
360
+ function castError(err) {
361
+ if (err instanceof Error) return err;
362
+ return new Error(typeof err === "string" ? err : "Unknown error", {
363
+ cause: err
364
+ });
365
+ }
366
+ function handleError(err, owner = Owner) {
367
+ const error = castError(err);
368
+ throw error;
369
+ }
370
+ var FALLBACK = /* @__PURE__ */ Symbol("fallback");
371
+ function dispose(d) {
372
+ for (let i = 0; i < d.length; i++) d[i]();
373
+ }
374
+ function mapArray(list, mapFn, options = {}) {
375
+ let items = [], mapped = [], disposers = [], len = 0, indexes = mapFn.length > 1 ? [] : null;
376
+ onCleanup(() => dispose(disposers));
377
+ return () => {
378
+ let newItems = list() || [], newLen = newItems.length, i, j;
379
+ newItems[$TRACK];
380
+ return untrack(() => {
381
+ let newIndices, newIndicesNext, temp, tempdisposers, tempIndexes, start, end, newEnd, item;
382
+ if (newLen === 0) {
383
+ if (len !== 0) {
384
+ dispose(disposers);
385
+ disposers = [];
386
+ items = [];
387
+ mapped = [];
388
+ len = 0;
389
+ indexes && (indexes = []);
390
+ }
391
+ if (options.fallback) {
392
+ items = [FALLBACK];
393
+ mapped[0] = createRoot((disposer) => {
394
+ disposers[0] = disposer;
395
+ return options.fallback();
396
+ });
397
+ len = 1;
398
+ }
399
+ } else if (len === 0) {
400
+ mapped = new Array(newLen);
401
+ for (j = 0; j < newLen; j++) {
402
+ items[j] = newItems[j];
403
+ mapped[j] = createRoot(mapper);
404
+ }
405
+ len = newLen;
406
+ } else {
407
+ temp = new Array(newLen);
408
+ tempdisposers = new Array(newLen);
409
+ indexes && (tempIndexes = new Array(newLen));
410
+ for (start = 0, end = Math.min(len, newLen); start < end && items[start] === newItems[start]; start++) ;
411
+ for (end = len - 1, newEnd = newLen - 1; end >= start && newEnd >= start && items[end] === newItems[newEnd]; end--, newEnd--) {
412
+ temp[newEnd] = mapped[end];
413
+ tempdisposers[newEnd] = disposers[end];
414
+ indexes && (tempIndexes[newEnd] = indexes[end]);
415
+ }
416
+ newIndices = /* @__PURE__ */ new Map();
417
+ newIndicesNext = new Array(newEnd + 1);
418
+ for (j = newEnd; j >= start; j--) {
419
+ item = newItems[j];
420
+ i = newIndices.get(item);
421
+ newIndicesNext[j] = i === void 0 ? -1 : i;
422
+ newIndices.set(item, j);
423
+ }
424
+ for (i = start; i <= end; i++) {
425
+ item = items[i];
426
+ j = newIndices.get(item);
427
+ if (j !== void 0 && j !== -1) {
428
+ temp[j] = mapped[i];
429
+ tempdisposers[j] = disposers[i];
430
+ indexes && (tempIndexes[j] = indexes[i]);
431
+ j = newIndicesNext[j];
432
+ newIndices.set(item, j);
433
+ } else disposers[i]();
434
+ }
435
+ for (j = start; j < newLen; j++) {
436
+ if (j in temp) {
437
+ mapped[j] = temp[j];
438
+ disposers[j] = tempdisposers[j];
439
+ if (indexes) {
440
+ indexes[j] = tempIndexes[j];
441
+ indexes[j](j);
442
+ }
443
+ } else mapped[j] = createRoot(mapper);
444
+ }
445
+ mapped = mapped.slice(0, len = newLen);
446
+ items = newItems.slice(0);
447
+ }
448
+ return mapped;
449
+ });
450
+ function mapper(disposer) {
451
+ disposers[j] = disposer;
452
+ if (indexes) {
453
+ const [s, set] = createSignal(j);
454
+ indexes[j] = set;
455
+ return mapFn(newItems[j], s);
456
+ }
457
+ return mapFn(newItems[j]);
458
+ }
459
+ };
460
+ }
461
+ function createComponent(Comp, props) {
462
+ return untrack(() => Comp(props || {}));
463
+ }
464
+ var narrowedError = (name) => `Stale read from <${name}>.`;
465
+ function For(props) {
466
+ const fallback = "fallback" in props && {
467
+ fallback: () => props.fallback
468
+ };
469
+ return createMemo(mapArray(() => props.each, props.children, fallback || void 0));
470
+ }
471
+ function Show(props) {
472
+ const keyed = props.keyed;
473
+ const conditionValue = createMemo(() => props.when, void 0, void 0);
474
+ const condition = keyed ? conditionValue : createMemo(conditionValue, void 0, {
475
+ equals: (a, b) => !a === !b
476
+ });
477
+ return createMemo(() => {
478
+ const c = condition();
479
+ if (c) {
480
+ const child = props.children;
481
+ const fn = typeof child === "function" && child.length > 0;
482
+ return fn ? untrack(() => child(keyed ? c : () => {
483
+ if (!untrack(condition)) throw narrowedError("Show");
484
+ return conditionValue();
485
+ })) : child;
486
+ }
487
+ return props.fallback;
488
+ }, void 0, void 0);
489
+ }
490
+ var memo = (fn) => createMemo(() => fn());
491
+ function reconcileArrays(parentNode, a, b) {
492
+ let bLength = b.length, aEnd = a.length, bEnd = bLength, aStart = 0, bStart = 0, after = a[aEnd - 1].nextSibling, map = null;
493
+ while (aStart < aEnd || bStart < bEnd) {
494
+ if (a[aStart] === b[bStart]) {
495
+ aStart++;
496
+ bStart++;
497
+ continue;
498
+ }
499
+ while (a[aEnd - 1] === b[bEnd - 1]) {
500
+ aEnd--;
501
+ bEnd--;
502
+ }
503
+ if (aEnd === aStart) {
504
+ const node = bEnd < bLength ? bStart ? b[bStart - 1].nextSibling : b[bEnd - bStart] : after;
505
+ while (bStart < bEnd) parentNode.insertBefore(b[bStart++], node);
506
+ } else if (bEnd === bStart) {
507
+ while (aStart < aEnd) {
508
+ if (!map || !map.has(a[aStart])) a[aStart].remove();
509
+ aStart++;
510
+ }
511
+ } else if (a[aStart] === b[bEnd - 1] && b[bStart] === a[aEnd - 1]) {
512
+ const node = a[--aEnd].nextSibling;
513
+ parentNode.insertBefore(b[bStart++], a[aStart++].nextSibling);
514
+ parentNode.insertBefore(b[--bEnd], node);
515
+ a[aEnd] = b[bEnd];
516
+ } else {
517
+ if (!map) {
518
+ map = /* @__PURE__ */ new Map();
519
+ let i = bStart;
520
+ while (i < bEnd) map.set(b[i], i++);
521
+ }
522
+ const index = map.get(a[aStart]);
523
+ if (index != null) {
524
+ if (bStart < index && index < bEnd) {
525
+ let i = aStart, sequence = 1, t;
526
+ while (++i < aEnd && i < bEnd) {
527
+ if ((t = map.get(a[i])) == null || t !== index + sequence) break;
528
+ sequence++;
529
+ }
530
+ if (sequence > index - bStart) {
531
+ const node = a[aStart];
532
+ while (bStart < index) parentNode.insertBefore(b[bStart++], node);
533
+ } else parentNode.replaceChild(b[bStart++], a[aStart++]);
534
+ } else aStart++;
535
+ } else a[aStart++].remove();
536
+ }
537
+ }
538
+ }
539
+ var $$EVENTS = "_$DX_DELEGATE";
540
+ function render(code, element, init, options = {}) {
541
+ let disposer;
542
+ createRoot((dispose2) => {
543
+ disposer = dispose2;
544
+ element === document ? code() : insert(element, code(), element.firstChild ? null : void 0, init);
545
+ }, options.owner);
546
+ return () => {
547
+ disposer();
548
+ element.textContent = "";
549
+ };
550
+ }
551
+ function template(html, isImportNode, isSVG, isMathML) {
552
+ let node;
553
+ const create = () => {
554
+ const t = isMathML ? document.createElementNS("http://www.w3.org/1998/Math/MathML", "template") : document.createElement("template");
555
+ t.innerHTML = html;
556
+ return isSVG ? t.content.firstChild.firstChild : isMathML ? t.firstChild : t.content.firstChild;
557
+ };
558
+ const fn = isImportNode ? () => untrack(() => document.importNode(node || (node = create()), true)) : () => (node || (node = create())).cloneNode(true);
559
+ fn.cloneNode = fn;
560
+ return fn;
561
+ }
562
+ function delegateEvents(eventNames, document2 = window.document) {
563
+ const e = document2[$$EVENTS] || (document2[$$EVENTS] = /* @__PURE__ */ new Set());
564
+ for (let i = 0, l = eventNames.length; i < l; i++) {
565
+ const name = eventNames[i];
566
+ if (!e.has(name)) {
567
+ e.add(name);
568
+ document2.addEventListener(name, eventHandler);
569
+ }
570
+ }
571
+ }
572
+ function setAttribute(node, name, value) {
573
+ if (value == null) node.removeAttribute(name);
574
+ else node.setAttribute(name, value);
575
+ }
576
+ function className(node, value) {
577
+ if (value == null) node.removeAttribute("class");
578
+ else node.className = value;
579
+ }
580
+ function style(node, value, prev) {
581
+ if (!value) return prev ? setAttribute(node, "style") : value;
582
+ const nodeStyle = node.style;
583
+ if (typeof value === "string") return nodeStyle.cssText = value;
584
+ typeof prev === "string" && (nodeStyle.cssText = prev = void 0);
585
+ prev || (prev = {});
586
+ value || (value = {});
587
+ let v, s;
588
+ for (s in prev) {
589
+ value[s] == null && nodeStyle.removeProperty(s);
590
+ delete prev[s];
591
+ }
592
+ for (s in value) {
593
+ v = value[s];
594
+ if (v !== prev[s]) {
595
+ nodeStyle.setProperty(s, v);
596
+ prev[s] = v;
597
+ }
598
+ }
599
+ return prev;
600
+ }
601
+ function setStyleProperty(node, name, value) {
602
+ value != null ? node.style.setProperty(name, value) : node.style.removeProperty(name);
603
+ }
604
+ function insert(parent, accessor, marker, initial) {
605
+ if (marker !== void 0 && !initial) initial = [];
606
+ if (typeof accessor !== "function") return insertExpression(parent, accessor, initial, marker);
607
+ createRenderEffect((current) => insertExpression(parent, accessor(), current, marker), initial);
608
+ }
609
+ function eventHandler(e) {
610
+ let node = e.target;
611
+ const key = `$$${e.type}`;
612
+ const oriTarget = e.target;
613
+ const oriCurrentTarget = e.currentTarget;
614
+ const retarget = (value) => Object.defineProperty(e, "target", {
615
+ configurable: true,
616
+ value
617
+ });
618
+ const handleNode = () => {
619
+ const handler = node[key];
620
+ if (handler && !node.disabled) {
621
+ const data = node[`${key}Data`];
622
+ data !== void 0 ? handler.call(node, data, e) : handler.call(node, e);
623
+ if (e.cancelBubble) return;
624
+ }
625
+ node.host && typeof node.host !== "string" && !node.host._$host && node.contains(e.target) && retarget(node.host);
626
+ return true;
627
+ };
628
+ const walkUpTree = () => {
629
+ while (handleNode() && (node = node._$host || node.parentNode || node.host)) ;
630
+ };
631
+ Object.defineProperty(e, "currentTarget", {
632
+ configurable: true,
633
+ get() {
634
+ return node || document;
635
+ }
636
+ });
637
+ if (e.composedPath) {
638
+ const path = e.composedPath();
639
+ retarget(path[0]);
640
+ for (let i = 0; i < path.length - 2; i++) {
641
+ node = path[i];
642
+ if (!handleNode()) break;
643
+ if (node._$host) {
644
+ node = node._$host;
645
+ walkUpTree();
646
+ break;
647
+ }
648
+ if (node.parentNode === oriCurrentTarget) {
649
+ break;
650
+ }
651
+ }
652
+ } else walkUpTree();
653
+ retarget(oriTarget);
654
+ }
655
+ function insertExpression(parent, value, current, marker, unwrapArray) {
656
+ while (typeof current === "function") current = current();
657
+ if (value === current) return current;
658
+ const t = typeof value, multi = marker !== void 0;
659
+ parent = multi && current[0] && current[0].parentNode || parent;
660
+ if (t === "string" || t === "number") {
661
+ if (t === "number") {
662
+ value = value.toString();
663
+ if (value === current) return current;
664
+ }
665
+ if (multi) {
666
+ let node = current[0];
667
+ if (node && node.nodeType === 3) {
668
+ node.data !== value && (node.data = value);
669
+ } else node = document.createTextNode(value);
670
+ current = cleanChildren(parent, current, marker, node);
671
+ } else {
672
+ if (current !== "" && typeof current === "string") {
673
+ current = parent.firstChild.data = value;
674
+ } else current = parent.textContent = value;
675
+ }
676
+ } else if (value == null || t === "boolean") {
677
+ current = cleanChildren(parent, current, marker);
678
+ } else if (t === "function") {
679
+ createRenderEffect(() => {
680
+ let v = value();
681
+ while (typeof v === "function") v = v();
682
+ current = insertExpression(parent, v, current, marker);
683
+ });
684
+ return () => current;
685
+ } else if (Array.isArray(value)) {
686
+ const array = [];
687
+ const currentArray = current && Array.isArray(current);
688
+ if (normalizeIncomingArray(array, value, current, unwrapArray)) {
689
+ createRenderEffect(() => current = insertExpression(parent, array, current, marker, true));
690
+ return () => current;
691
+ }
692
+ if (array.length === 0) {
693
+ current = cleanChildren(parent, current, marker);
694
+ if (multi) return current;
695
+ } else if (currentArray) {
696
+ if (current.length === 0) {
697
+ appendNodes(parent, array, marker);
698
+ } else reconcileArrays(parent, current, array);
699
+ } else {
700
+ current && cleanChildren(parent);
701
+ appendNodes(parent, array);
702
+ }
703
+ current = array;
704
+ } else if (value.nodeType) {
705
+ if (Array.isArray(current)) {
706
+ if (multi) return current = cleanChildren(parent, current, marker, value);
707
+ cleanChildren(parent, current, null, value);
708
+ } else if (current == null || current === "" || !parent.firstChild) {
709
+ parent.appendChild(value);
710
+ } else parent.replaceChild(value, parent.firstChild);
711
+ current = value;
712
+ } else ;
713
+ return current;
714
+ }
715
+ function normalizeIncomingArray(normalized, array, current, unwrap) {
716
+ let dynamic = false;
717
+ for (let i = 0, len = array.length; i < len; i++) {
718
+ let item = array[i], prev = current && current[normalized.length], t;
719
+ if (item == null || item === true || item === false) ;
720
+ else if ((t = typeof item) === "object" && item.nodeType) {
721
+ normalized.push(item);
722
+ } else if (Array.isArray(item)) {
723
+ dynamic = normalizeIncomingArray(normalized, item, prev) || dynamic;
724
+ } else if (t === "function") {
725
+ if (unwrap) {
726
+ while (typeof item === "function") item = item();
727
+ dynamic = normalizeIncomingArray(normalized, Array.isArray(item) ? item : [item], Array.isArray(prev) ? prev : [prev]) || dynamic;
728
+ } else {
729
+ normalized.push(item);
730
+ dynamic = true;
731
+ }
732
+ } else {
733
+ const value = String(item);
734
+ if (prev && prev.nodeType === 3 && prev.data === value) normalized.push(prev);
735
+ else normalized.push(document.createTextNode(value));
736
+ }
737
+ }
738
+ return dynamic;
739
+ }
740
+ function appendNodes(parent, array, marker = null) {
741
+ for (let i = 0, len = array.length; i < len; i++) parent.insertBefore(array[i], marker);
742
+ }
743
+ function cleanChildren(parent, current, marker, replacement) {
744
+ if (marker === void 0) return parent.textContent = "";
745
+ const node = replacement || document.createTextNode("");
746
+ if (current.length) {
747
+ let inserted = false;
748
+ for (let i = current.length - 1; i >= 0; i--) {
749
+ const el = current[i];
750
+ if (node !== el) {
751
+ const isParent = el.parentNode === parent;
752
+ if (!inserted && !i) isParent ? parent.replaceChild(node, el) : parent.insertBefore(node, marker);
753
+ else isParent && el.remove();
754
+ } else inserted = true;
755
+ }
756
+ } else parent.insertBefore(node, marker);
757
+ return [node];
758
+ }
759
+ var SVG_NAMESPACE = "http://www.w3.org/2000/svg";
760
+ function createElement(tagName, isSVG = false, is = void 0) {
761
+ return isSVG ? document.createElementNS(SVG_NAMESPACE, tagName) : document.createElement(tagName, {
762
+ is
763
+ });
764
+ }
765
+ function Portal(props) {
766
+ const {
767
+ useShadow
768
+ } = props, marker = document.createTextNode(""), mount = () => props.mount || document.body, owner = getOwner();
769
+ let content;
770
+ createEffect(() => {
771
+ content || (content = runWithOwner(owner, () => createMemo(() => props.children)));
772
+ const el = mount();
773
+ if (el instanceof HTMLHeadElement) {
774
+ const [clean, setClean] = createSignal(false);
775
+ const cleanup = () => setClean(true);
776
+ createRoot((dispose2) => insert(el, () => !clean() ? content() : dispose2(), null));
777
+ onCleanup(cleanup);
778
+ } else {
779
+ const container = createElement(props.isSVG ? "g" : "div", props.isSVG), renderRoot = useShadow && container.attachShadow ? container.attachShadow({
780
+ mode: "open"
781
+ }) : container;
782
+ Object.defineProperty(container, "_$host", {
783
+ get() {
784
+ return marker.parentNode;
785
+ },
786
+ configurable: true
787
+ });
788
+ insert(renderRoot, content);
789
+ el.appendChild(container);
790
+ props.ref && props.ref(container);
791
+ onCleanup(() => el.removeChild(container));
792
+ }
793
+ }, void 0, {
794
+ render: true
795
+ });
796
+ return marker;
797
+ }
798
+
799
+ // ../core/dist/index.js
800
+ function createReader() {
801
+ let rafId = null;
802
+ let idleId = null;
803
+ let timeoutId = null;
804
+ function detectBestStrategy() {
805
+ if ("scheduler" in globalThis) {
806
+ return "scheduler";
807
+ }
808
+ if ("requestIdleCallback" in window) {
809
+ return "idle";
810
+ }
811
+ return "post-raf";
812
+ }
813
+ function scheduleWithScheduler(callback, urgent) {
814
+ if (!("scheduler" in globalThis)) {
815
+ scheduleWithIdle(callback, urgent);
816
+ return;
817
+ }
818
+ const Scheduler2 = globalThis.scheduler;
819
+ const TaskController = globalThis.TaskController;
820
+ if (!TaskController) {
821
+ scheduleWithIdle(callback, urgent);
822
+ return;
823
+ }
824
+ const controller = new TaskController({
825
+ priority: urgent ? "user-visible" : "background"
826
+ });
827
+ controller.signal;
828
+ Scheduler2.postTask(
829
+ () => {
830
+ callback();
831
+ },
832
+ {
833
+ signal: controller.signal,
834
+ priority: urgent ? "user-visible" : "background"
835
+ }
836
+ );
837
+ }
838
+ function scheduleWithIdle(callback, urgent) {
839
+ if (!("requestIdleCallback" in window)) {
840
+ scheduleWithRAF(callback);
841
+ return;
842
+ }
843
+ idleId = requestIdleCallback(
844
+ (deadline) => {
845
+ if (deadline.timeRemaining() > 0 || deadline.didTimeout) {
846
+ callback();
847
+ } else if (!urgent) {
848
+ scheduleWithIdle(callback, false);
849
+ } else {
850
+ scheduleWithRAF(callback);
851
+ }
852
+ },
853
+ { timeout: urgent ? 5 : 50 }
854
+ );
855
+ }
856
+ function scheduleWithRAF(callback) {
857
+ rafId = requestAnimationFrame(() => {
858
+ Promise.resolve().then(() => {
859
+ callback();
860
+ });
861
+ });
862
+ }
863
+ function scheduleWithTimeout(callback) {
864
+ timeoutId = setTimeout(() => {
865
+ callback();
866
+ }, 0);
867
+ }
868
+ function scheduleRead(callback, urgent = false) {
869
+ cancel();
870
+ const strategy = detectBestStrategy();
871
+ switch (strategy) {
872
+ case "scheduler":
873
+ scheduleWithScheduler(callback, urgent);
874
+ break;
875
+ case "idle":
876
+ scheduleWithIdle(callback, urgent);
877
+ break;
878
+ case "post-raf":
879
+ scheduleWithRAF(callback);
880
+ break;
881
+ case "timeout":
882
+ scheduleWithTimeout(callback);
883
+ break;
884
+ }
885
+ }
886
+ function cancel() {
887
+ if (rafId !== null) {
888
+ cancelAnimationFrame(rafId);
889
+ rafId = null;
890
+ }
891
+ if (idleId !== null && "cancelIdleCallback" in window) {
892
+ cancelIdleCallback(idleId);
893
+ idleId = null;
894
+ }
895
+ if (timeoutId !== null) {
896
+ clearTimeout(timeoutId);
897
+ timeoutId = null;
898
+ }
899
+ }
900
+ return { scheduleRead, cancel };
901
+ }
902
+ var MAX_FRAME_TIMES = 30;
903
+ var DEFAULT_READ_INTERVAL = 16;
904
+ var SUPPRESSION_MAX_FRAMES = 8;
905
+ var RESIZE_THROTTLE_MS = 60;
906
+ var SUPPRESSION_DELAY = 30;
907
+ var MAX_RULER_PAIRS = 8;
908
+ var MAX_RULER_LINES = MAX_RULER_PAIRS * 2;
909
+ var RULER_SNAP_THRESHOLD = 6;
910
+ var RULER_HIT_SIZE = 11;
911
+ var CALIPER_PREFIX = "caliper-";
912
+ function createFrequencyControlledReader(baseReader) {
913
+ let lastReadTime = 0;
914
+ let readInterval = DEFAULT_READ_INTERVAL;
915
+ const frameTimes = [];
916
+ let trailingTimeoutId = null;
917
+ let pendingTask = null;
918
+ function adaptToFrameRate(fps) {
919
+ readInterval = Math.ceil(1e3 / (fps / 2));
920
+ }
921
+ function recordFrameTime(timestamp) {
922
+ frameTimes.push(timestamp);
923
+ if (frameTimes.length > MAX_FRAME_TIMES) {
924
+ frameTimes.shift();
925
+ }
926
+ if (frameTimes.length >= 2) {
927
+ const last = frameTimes[frameTimes.length - 1];
928
+ const first = frameTimes[0];
929
+ if (last !== void 0 && first !== void 0) {
930
+ const duration = last - first;
931
+ const fps = frameTimes.length / duration * 1e3;
932
+ adaptToFrameRate(fps);
933
+ }
934
+ }
935
+ }
936
+ function executeNow() {
937
+ if (!pendingTask) return;
938
+ const { callback, urgent } = pendingTask;
939
+ pendingTask = null;
940
+ lastReadTime = performance.now();
941
+ baseReader.scheduleRead(callback, urgent);
942
+ }
943
+ function scheduleRead(callback, urgent = false) {
944
+ pendingTask = { callback, urgent };
945
+ const now = performance.now();
946
+ const timeSinceLastRead = now - lastReadTime;
947
+ if (urgent || timeSinceLastRead >= readInterval) {
948
+ if (trailingTimeoutId !== null) {
949
+ clearTimeout(trailingTimeoutId);
950
+ trailingTimeoutId = null;
951
+ }
952
+ executeNow();
953
+ return;
954
+ }
955
+ if (trailingTimeoutId === null) {
956
+ trailingTimeoutId = setTimeout(() => {
957
+ trailingTimeoutId = null;
958
+ executeNow();
959
+ }, readInterval - timeSinceLastRead);
960
+ }
961
+ }
962
+ function cancel() {
963
+ baseReader.cancel();
964
+ pendingTask = null;
965
+ if (trailingTimeoutId !== null) {
966
+ clearTimeout(trailingTimeoutId);
967
+ trailingTimeoutId = null;
968
+ }
969
+ }
970
+ return {
971
+ scheduleRead,
972
+ cancel,
973
+ adaptToFrameRate,
974
+ recordFrameTime
975
+ };
976
+ }
977
+ function createSuppressionDelegate(action, options = {}) {
978
+ const maxFrames = options.maxFrames ?? SUPPRESSION_MAX_FRAMES;
979
+ const delay = options.delay ?? SUPPRESSION_DELAY;
980
+ let suppressionFrames = 0;
981
+ let trailingTimer = null;
982
+ return {
983
+ execute(shouldSuppress, ...args) {
984
+ if (trailingTimer) {
985
+ clearTimeout(trailingTimer);
986
+ trailingTimer = null;
987
+ }
988
+ if (shouldSuppress && suppressionFrames < maxFrames) {
989
+ suppressionFrames++;
990
+ trailingTimer = setTimeout(() => {
991
+ suppressionFrames = 0;
992
+ action(...args);
993
+ trailingTimer = null;
994
+ }, delay);
995
+ } else {
996
+ suppressionFrames = 0;
997
+ action(...args);
998
+ }
999
+ },
1000
+ cancel() {
1001
+ if (trailingTimer) {
1002
+ clearTimeout(trailingTimer);
1003
+ trailingTimer = null;
1004
+ }
1005
+ suppressionFrames = 0;
1006
+ }
1007
+ };
1008
+ }
1009
+ function isVisible(element) {
1010
+ if (!(element instanceof HTMLElement || element instanceof SVGElement)) {
1011
+ return false;
1012
+ }
1013
+ const style2 = window.getComputedStyle(element);
1014
+ if (style2.display === "none") {
1015
+ return false;
1016
+ }
1017
+ if (style2.visibility === "hidden") {
1018
+ return false;
1019
+ }
1020
+ if (parseFloat(style2.opacity) === 0) {
1021
+ return false;
1022
+ }
1023
+ return true;
1024
+ }
1025
+ function hasSize(element) {
1026
+ if (!(element instanceof HTMLElement || element instanceof SVGElement)) {
1027
+ return false;
1028
+ }
1029
+ const rect = element.getBoundingClientRect();
1030
+ return rect.width > 0 && rect.height > 0;
1031
+ }
1032
+ function isEligible(element) {
1033
+ if (element.closest("[data-caliper-ignore]")) {
1034
+ return false;
1035
+ }
1036
+ return isVisible(element) && hasSize(element);
1037
+ }
1038
+ var HYSTERESIS_THRESHOLD = 2;
1039
+ function isCaliperNode(node) {
1040
+ if (!node || !(node instanceof Element)) return false;
1041
+ return !!(node.closest("#caliper-overlay-root") || node.closest("[class*='caliper-']"));
1042
+ }
1043
+ function getElementAtPoint(x, y) {
1044
+ const nodes = document.elementsFromPoint(x, y);
1045
+ return nodes.find((node) => {
1046
+ if (isCaliperNode(node)) return false;
1047
+ return isEligible(node);
1048
+ }) || null;
1049
+ }
1050
+ function getTopElementAtPoint(x, y) {
1051
+ const node = document.elementFromPoint(x, y);
1052
+ if (!node) return null;
1053
+ if (isCaliperNode(node) || !isEligible(node)) return null;
1054
+ return node;
1055
+ }
1056
+ function detectBestContext(selectedElement, cursorX, cursorY) {
1057
+ let node = getElementAtPoint(cursorX, cursorY);
1058
+ if (!node) return null;
1059
+ while (node) {
1060
+ if (node !== selectedElement) {
1061
+ if (selectedElement.contains(node)) {
1062
+ return { context: "child", element: node };
1063
+ }
1064
+ if (node.contains(selectedElement)) {
1065
+ return { context: "parent", element: node };
1066
+ }
1067
+ return { context: "sibling", element: node };
1068
+ }
1069
+ node = node.parentElement;
1070
+ }
1071
+ return null;
1072
+ }
1073
+ function getDistanceToEdge(x, y, rect) {
1074
+ const dx = Math.min(Math.abs(x - rect.left), Math.abs(x - rect.right));
1075
+ const dy = Math.min(Math.abs(y - rect.top), Math.abs(y - rect.bottom));
1076
+ return Math.min(dx, dy);
1077
+ }
1078
+ function resolveAmbiguousContext(selectedElement, cursorX, cursorY, previousContext, previousElement = null) {
1079
+ const result = detectBestContext(selectedElement, cursorX, cursorY);
1080
+ if (!result) return null;
1081
+ const { context: winnerContext, element: winnerElement } = result;
1082
+ if (previousContext && previousElement && (winnerContext !== previousContext || winnerElement !== previousElement)) {
1083
+ const rect = previousElement.getBoundingClientRect();
1084
+ const distance = getDistanceToEdge(cursorX, cursorY, rect);
1085
+ if (distance <= HYSTERESIS_THRESHOLD) {
1086
+ const isSwitchingToSpecific = (winnerContext === "sibling" || winnerContext === "child") && previousContext === "parent";
1087
+ if (!isSwitchingToSpecific) {
1088
+ return { context: previousContext, element: previousElement };
1089
+ }
1090
+ }
1091
+ }
1092
+ return result;
1093
+ }
1094
+ function getScrollAwareRect(rect) {
1095
+ return new DOMRect(
1096
+ rect.left + window.scrollX,
1097
+ rect.top + window.scrollY,
1098
+ rect.width,
1099
+ rect.height
1100
+ );
1101
+ }
1102
+ function isScrollContainer(element) {
1103
+ if (!(element instanceof HTMLElement)) return false;
1104
+ const style2 = window.getComputedStyle(element);
1105
+ return /(auto|scroll)/.test(style2.overflow + style2.overflowY + style2.overflowX);
1106
+ }
1107
+ function getScrollHierarchy(element) {
1108
+ const hierarchy = [];
1109
+ let parent = element.parentElement;
1110
+ while (parent && parent !== document.body) {
1111
+ if (isScrollContainer(parent)) {
1112
+ const el = parent;
1113
+ hierarchy.push({
1114
+ element: el,
1115
+ initialScrollTop: el.scrollTop,
1116
+ initialScrollLeft: el.scrollLeft,
1117
+ containerRect: getScrollAwareRect(el.getBoundingClientRect())
1118
+ });
1119
+ }
1120
+ parent = parent.parentElement;
1121
+ }
1122
+ return hierarchy;
1123
+ }
1124
+ function calculateStickyRef(scroll, naturalPos, threshold, containerDim, elementDim, isOppositeMode) {
1125
+ const staticRel = naturalPos - scroll;
1126
+ if (!isOppositeMode) {
1127
+ let stuck = Math.max(staticRel, threshold);
1128
+ stuck = Math.min(stuck, containerDim - elementDim);
1129
+ return stuck;
1130
+ } else {
1131
+ let stuck = Math.min(staticRel, containerDim - elementDim - threshold);
1132
+ stuck = Math.max(stuck, 0);
1133
+ return stuck;
1134
+ }
1135
+ }
1136
+ function calculateStickyDelta(currentScroll, initialScroll, naturalPos, threshold, containerDim, elementDim, isOppositeMode = false) {
1137
+ if (threshold === null) return currentScroll - initialScroll;
1138
+ const startRef = calculateStickyRef(
1139
+ initialScroll,
1140
+ naturalPos,
1141
+ threshold,
1142
+ containerDim,
1143
+ elementDim,
1144
+ isOppositeMode
1145
+ );
1146
+ const endRef = calculateStickyRef(
1147
+ currentScroll,
1148
+ naturalPos,
1149
+ threshold,
1150
+ containerDim,
1151
+ elementDim,
1152
+ isOppositeMode
1153
+ );
1154
+ return startRef - endRef;
1155
+ }
1156
+ function getTotalScrollDelta(hierarchy, position = "static", sticky, initWinX = 0, initWinY = 0) {
1157
+ if (position === "fixed") {
1158
+ return {
1159
+ deltaX: initWinX - window.scrollX,
1160
+ deltaY: initWinY - window.scrollY
1161
+ };
1162
+ }
1163
+ let deltaX = 0;
1164
+ let deltaY = 0;
1165
+ for (let i = 0; i < hierarchy.length; i++) {
1166
+ const s = hierarchy[i];
1167
+ if (!s) continue;
1168
+ let dX = s.element.scrollLeft - s.initialScrollLeft;
1169
+ let dY = s.element.scrollTop - s.initialScrollTop;
1170
+ if (i === 0 && position === "sticky" && sticky) {
1171
+ dX = calculateStickyDelta(
1172
+ s.element.scrollLeft,
1173
+ s.initialScrollLeft,
1174
+ sticky.naturalLeft,
1175
+ sticky.left,
1176
+ sticky.containerWidth,
1177
+ sticky.elementWidth
1178
+ );
1179
+ dY = calculateStickyDelta(
1180
+ s.element.scrollTop,
1181
+ s.initialScrollTop,
1182
+ sticky.naturalTop,
1183
+ sticky.top,
1184
+ sticky.containerHeight,
1185
+ sticky.elementHeight
1186
+ );
1187
+ }
1188
+ deltaX += dX;
1189
+ deltaY += dY;
1190
+ }
1191
+ if (hierarchy.length === 0 && position === "sticky" && sticky) {
1192
+ deltaX = calculateStickyDelta(
1193
+ window.scrollX,
1194
+ initWinX,
1195
+ sticky.naturalLeft,
1196
+ sticky.left,
1197
+ window.innerWidth,
1198
+ sticky.elementWidth
1199
+ );
1200
+ deltaY = calculateStickyDelta(
1201
+ window.scrollY,
1202
+ initWinY,
1203
+ sticky.naturalTop,
1204
+ sticky.top,
1205
+ window.innerHeight,
1206
+ sticky.elementHeight
1207
+ );
1208
+ }
1209
+ return { deltaX, deltaY };
1210
+ }
1211
+ function getCommonVisibilityWindow(h1, h2, el1, el2) {
1212
+ const h1Map = /* @__PURE__ */ new Map();
1213
+ for (let i = 0; i < h1.length; i++) {
1214
+ const item = h1[i];
1215
+ if (item) h1Map.set(item.element, i);
1216
+ }
1217
+ const h2Map = /* @__PURE__ */ new Map();
1218
+ for (let i = 0; i < h2.length; i++) {
1219
+ const item = h2[i];
1220
+ if (item) h2Map.set(item.element, i);
1221
+ }
1222
+ const commonElements = [];
1223
+ for (let i = 0; i < h1.length; i++) {
1224
+ const s = h1[i];
1225
+ if (s && h2Map.has(s.element)) {
1226
+ commonElements.push(s);
1227
+ }
1228
+ }
1229
+ if (isScrollContainer(el2)) {
1230
+ const sIdx = h1Map.get(el2);
1231
+ if (sIdx !== void 0) {
1232
+ const s = h1[sIdx];
1233
+ if (s && !commonElements.includes(s)) commonElements.push(s);
1234
+ }
1235
+ }
1236
+ if (isScrollContainer(el1)) {
1237
+ const sIdx = h2Map.get(el1);
1238
+ if (sIdx !== void 0) {
1239
+ const s = h2[sIdx];
1240
+ if (s && !commonElements.includes(s)) commonElements.push(s);
1241
+ }
1242
+ }
1243
+ if (commonElements.length === 0) {
1244
+ return { minX: -Infinity, maxX: Infinity, minY: -Infinity, maxY: Infinity };
1245
+ }
1246
+ let minX = -Infinity;
1247
+ let maxX = Infinity;
1248
+ let minY = -Infinity;
1249
+ let maxY = Infinity;
1250
+ const getSuffixSums = (h) => {
1251
+ const sumsX = new Float64Array(h.length + 1);
1252
+ const sumsY = new Float64Array(h.length + 1);
1253
+ for (let i = h.length - 1; i >= 0; i--) {
1254
+ const item = h[i];
1255
+ if (item) {
1256
+ sumsX[i] = (sumsX[i + 1] ?? 0) + (item.element.scrollLeft - item.initialScrollLeft);
1257
+ sumsY[i] = (sumsY[i + 1] ?? 0) + (item.element.scrollTop - item.initialScrollTop);
1258
+ }
1259
+ }
1260
+ return { sumsX, sumsY };
1261
+ };
1262
+ const h1Suffix = getSuffixSums(h1);
1263
+ const h2Suffix = getSuffixSums(h2);
1264
+ for (let i = 0; i < commonElements.length; i++) {
1265
+ const s = commonElements[i];
1266
+ if (!s) continue;
1267
+ const isH1 = h1Map.has(s.element);
1268
+ const suffix = isH1 ? h1Suffix : h2Suffix;
1269
+ const sIndex = isH1 ? h1Map.get(s.element) : h2Map.get(s.element);
1270
+ if (sIndex === void 0 || sIndex === -1) continue;
1271
+ const ancestorDeltaX = suffix.sumsX[sIndex + 1] ?? 0;
1272
+ const ancestorDeltaY = suffix.sumsY[sIndex + 1] ?? 0;
1273
+ const cLiveLeft = s.containerRect.left - ancestorDeltaX;
1274
+ const cLiveTop = s.containerRect.top - ancestorDeltaY;
1275
+ const clipL = cLiveLeft + s.element.clientLeft;
1276
+ const clipT = cLiveTop + s.element.clientTop;
1277
+ const clipR = clipL + s.element.clientWidth;
1278
+ const clipB = clipT + s.element.clientHeight;
1279
+ if (minX === -Infinity) {
1280
+ minX = clipL;
1281
+ maxX = clipR;
1282
+ minY = clipT;
1283
+ maxY = clipB;
1284
+ } else {
1285
+ minX = Math.max(minX, clipL);
1286
+ maxX = Math.min(maxX, clipR);
1287
+ minY = Math.max(minY, clipT);
1288
+ maxY = Math.min(maxY, clipB);
1289
+ }
1290
+ }
1291
+ return { minX, maxX, minY, maxY };
1292
+ }
1293
+ function getLiveGeometry(stableRect, hierarchy, position = "static", sticky, initWinX = 0, initWinY = 0) {
1294
+ if (!stableRect) return null;
1295
+ const { deltaX, deltaY } = getTotalScrollDelta(hierarchy, position, sticky, initWinX, initWinY);
1296
+ let vMinX = -Infinity;
1297
+ let vMaxX = Infinity;
1298
+ let vMinY = -Infinity;
1299
+ let vMaxY = Infinity;
1300
+ const len = hierarchy.length;
1301
+ const suffixX = new Float64Array(len + 1);
1302
+ const suffixY = new Float64Array(len + 1);
1303
+ for (let i = len - 1; i >= 0; i--) {
1304
+ const item = hierarchy[i];
1305
+ if (item) {
1306
+ suffixX[i] = (suffixX[i + 1] ?? 0) + (item.element.scrollLeft - item.initialScrollLeft);
1307
+ suffixY[i] = (suffixY[i + 1] ?? 0) + (item.element.scrollTop - item.initialScrollTop);
1308
+ }
1309
+ }
1310
+ for (let i = 0; i < len; i++) {
1311
+ const s = hierarchy[i];
1312
+ if (!s) continue;
1313
+ const ancestorDeltaX = suffixX[i + 1] ?? 0;
1314
+ const ancestorDeltaY = suffixY[i + 1] ?? 0;
1315
+ const cLiveLeft = s.containerRect.left - ancestorDeltaX;
1316
+ const cLiveTop = s.containerRect.top - ancestorDeltaY;
1317
+ const clipL = cLiveLeft + s.element.clientLeft;
1318
+ const clipT = cLiveTop + s.element.clientTop;
1319
+ if (vMinX === -Infinity) {
1320
+ vMinX = clipL;
1321
+ vMaxX = clipL + s.element.clientWidth;
1322
+ vMinY = clipT;
1323
+ vMaxY = clipT + s.element.clientHeight;
1324
+ } else {
1325
+ vMinX = Math.max(vMinX, clipL);
1326
+ vMaxX = Math.min(vMaxX, clipL + s.element.clientWidth);
1327
+ vMinY = Math.max(vMinY, clipT);
1328
+ vMaxY = Math.min(vMaxY, clipT + s.element.clientHeight);
1329
+ }
1330
+ }
1331
+ const left = stableRect.left - deltaX;
1332
+ const top = stableRect.top - deltaY;
1333
+ const width = stableRect.width;
1334
+ const height = stableRect.height;
1335
+ const isHidden = vMinX !== -Infinity && (top + height < vMinY || top > vMaxY || left + width < vMinX || left > vMaxX);
1336
+ const t = Math.max(0, vMinY - top);
1337
+ const l = Math.max(0, vMinX - left);
1338
+ const b = Math.max(0, top + height - vMaxY);
1339
+ const r = Math.max(0, left + width - vMaxX);
1340
+ return {
1341
+ left,
1342
+ top,
1343
+ width,
1344
+ height,
1345
+ clipPath: vMinX === -Infinity ? "none" : `inset(${t}px ${r}px ${b}px ${l}px)`,
1346
+ isHidden,
1347
+ visibleMinX: vMinX,
1348
+ visibleMaxX: vMaxX,
1349
+ visibleMinY: vMinY,
1350
+ visibleMaxY: vMaxY
1351
+ };
1352
+ }
1353
+ function parseStickyOffset(val) {
1354
+ if (val === "auto") return null;
1355
+ const parsed = parseFloat(val);
1356
+ return isNaN(parsed) ? null : parsed;
1357
+ }
1358
+ function getInheritedPositionMode(element) {
1359
+ let curr = element;
1360
+ while (curr && curr !== document.body) {
1361
+ if (!(curr instanceof HTMLElement)) {
1362
+ curr = curr.parentElement;
1363
+ continue;
1364
+ }
1365
+ const style2 = window.getComputedStyle(curr);
1366
+ if (style2.position === "fixed") return { mode: "fixed", anchor: curr };
1367
+ if (style2.position === "sticky") return { mode: "sticky", anchor: curr };
1368
+ curr = curr.parentElement;
1369
+ }
1370
+ return { mode: "static", anchor: null };
1371
+ }
1372
+ function getDistanceFromContainer(target, container) {
1373
+ let x = 0;
1374
+ let y = 0;
1375
+ let current = target;
1376
+ while (current && current !== container && current.offsetParent) {
1377
+ x += current.offsetLeft;
1378
+ y += current.offsetTop;
1379
+ const parent = current.offsetParent;
1380
+ x += parent.clientLeft || 0;
1381
+ y += parent.clientTop || 0;
1382
+ current = parent;
1383
+ }
1384
+ if (container instanceof HTMLElement) {
1385
+ x -= container.clientLeft || 0;
1386
+ y -= container.clientTop || 0;
1387
+ }
1388
+ return { x, y };
1389
+ }
1390
+ function deduceGeometry(element) {
1391
+ const rect = element.getBoundingClientRect();
1392
+ const scrollHierarchy = getScrollHierarchy(element);
1393
+ const initialWindowX = window.scrollX;
1394
+ const initialWindowY = window.scrollY;
1395
+ const { mode: position, anchor } = getInheritedPositionMode(element);
1396
+ let stickyConfig;
1397
+ if (position === "sticky" && anchor) {
1398
+ const style2 = window.getComputedStyle(anchor);
1399
+ const parent = getScrollHierarchy(anchor)[0]?.element || document.documentElement;
1400
+ const isDoc = parent === document.documentElement;
1401
+ const anchorRect = anchor.getBoundingClientRect();
1402
+ const childRelTop = rect.top - anchorRect.top;
1403
+ const childRelLeft = rect.left - anchorRect.left;
1404
+ const childRelBottom = anchorRect.bottom - rect.bottom;
1405
+ const childRelRight = anchorRect.right - rect.right;
1406
+ const t = parseStickyOffset(style2.top);
1407
+ const b = parseStickyOffset(style2.bottom);
1408
+ const l = parseStickyOffset(style2.left);
1409
+ const r = parseStickyOffset(style2.right);
1410
+ const naturalPos = getDistanceFromContainer(anchor, parent);
1411
+ stickyConfig = {
1412
+ top: t === null ? null : t + childRelTop,
1413
+ bottom: b === null ? null : b + childRelBottom,
1414
+ left: l === null ? null : l + childRelLeft,
1415
+ right: r === null ? null : r + childRelRight,
1416
+ naturalTop: naturalPos.y + childRelTop,
1417
+ naturalLeft: naturalPos.x + childRelLeft,
1418
+ containerWidth: isDoc ? window.innerWidth : parent.clientWidth,
1419
+ containerHeight: isDoc ? window.innerHeight : parent.clientHeight,
1420
+ elementWidth: anchorRect.width,
1421
+ elementHeight: anchorRect.height
1422
+ };
1423
+ }
1424
+ return {
1425
+ rect: getScrollAwareRect(rect),
1426
+ scrollHierarchy,
1427
+ position,
1428
+ stickyConfig,
1429
+ initialWindowX,
1430
+ initialWindowY
1431
+ };
1432
+ }
1433
+ function clampPointToGeometry(pt, geo, viewport) {
1434
+ if (!geo) return pt;
1435
+ return {
1436
+ x: Math.max(
1437
+ geo.visibleMinX - viewport.scrollX,
1438
+ Math.min(pt.x, geo.visibleMaxX - viewport.scrollX)
1439
+ ),
1440
+ y: Math.max(
1441
+ geo.visibleMinY - viewport.scrollY,
1442
+ Math.min(pt.y, geo.visibleMaxY - viewport.scrollY)
1443
+ )
1444
+ };
1445
+ }
1446
+ function createMeasurementLines(context, primary, secondary) {
1447
+ if (!context || !secondary) {
1448
+ return [];
1449
+ }
1450
+ const lines = [];
1451
+ if (context === "sibling") {
1452
+ const distance = calculateSiblingDistance(primary, secondary);
1453
+ lines.push(distance);
1454
+ } else if (context === "parent" || context === "child") {
1455
+ const padding = calculatePaddingLines(primary, secondary, context);
1456
+ lines.push(...padding);
1457
+ }
1458
+ return lines;
1459
+ }
1460
+ function calculateSiblingDistance(primary, sibling) {
1461
+ const overlapXStart = Math.max(primary.left, sibling.left);
1462
+ const overlapXEnd = Math.min(primary.right, sibling.right);
1463
+ const hasOverlapX = overlapXEnd > overlapXStart;
1464
+ const overlapYStart = Math.max(primary.top, sibling.top);
1465
+ const overlapYEnd = Math.min(primary.bottom, sibling.bottom);
1466
+ const hasOverlapY = overlapYEnd > overlapYStart;
1467
+ const syncBase = { startSync: "primary", endSync: "secondary" };
1468
+ if (hasOverlapX && !hasOverlapY) {
1469
+ const centerX = (overlapXStart + overlapXEnd) / 2;
1470
+ const distBtoT = Math.abs(sibling.top - primary.bottom);
1471
+ const distTtoB = Math.abs(primary.top - sibling.bottom);
1472
+ const startY = distBtoT < distTtoB ? primary.bottom : primary.top;
1473
+ const endY = distBtoT < distTtoB ? sibling.top : sibling.bottom;
1474
+ return {
1475
+ type: "distance",
1476
+ value: Math.min(distBtoT, distTtoB),
1477
+ start: { x: centerX, y: startY },
1478
+ end: { x: centerX, y: endY },
1479
+ ...syncBase
1480
+ };
1481
+ }
1482
+ if (hasOverlapY && !hasOverlapX) {
1483
+ const centerY = (overlapYStart + overlapYEnd) / 2;
1484
+ const distRtoL = Math.abs(sibling.left - primary.right);
1485
+ const distLtoR = Math.abs(primary.left - sibling.right);
1486
+ const startX = distRtoL < distLtoR ? primary.right : primary.left;
1487
+ const endX = distRtoL < distLtoR ? sibling.left : sibling.right;
1488
+ return {
1489
+ type: "distance",
1490
+ value: Math.min(distRtoL, distLtoR),
1491
+ start: { x: startX, y: centerY },
1492
+ end: { x: endX, y: centerY },
1493
+ ...syncBase
1494
+ };
1495
+ }
1496
+ const pFaces = [
1497
+ { x: (primary.left + primary.right) / 2, y: primary.top },
1498
+ { x: (primary.left + primary.right) / 2, y: primary.bottom }
1499
+ ];
1500
+ const sFaces = [
1501
+ { x: (sibling.left + sibling.right) / 2, y: sibling.top },
1502
+ { x: (sibling.left + sibling.right) / 2, y: sibling.bottom }
1503
+ ];
1504
+ let minD2 = Infinity;
1505
+ let bestP = pFaces[0];
1506
+ let bestS = sFaces[0];
1507
+ for (const p of pFaces) {
1508
+ for (const s of sFaces) {
1509
+ const dx = p.x - s.x;
1510
+ const dy = p.y - s.y;
1511
+ const d2 = dx * dx + dy * dy;
1512
+ if (d2 < minD2) {
1513
+ minD2 = d2;
1514
+ bestP = p;
1515
+ bestS = s;
1516
+ }
1517
+ }
1518
+ }
1519
+ const pFace = bestP ?? pFaces[0];
1520
+ const sFace = bestS ?? sFaces[0];
1521
+ return {
1522
+ type: "distance",
1523
+ value: Math.sqrt(minD2),
1524
+ start: { x: pFace.x, y: pFace.y },
1525
+ end: { x: sFace.x, y: sFace.y },
1526
+ ...syncBase
1527
+ };
1528
+ }
1529
+ function calculatePaddingLines(primary, container, context) {
1530
+ if (context === "parent") {
1531
+ return [
1532
+ {
1533
+ type: "left",
1534
+ value: Math.abs(primary.left - container.left),
1535
+ start: { x: container.left, y: primary.top + primary.height / 2 },
1536
+ end: { x: primary.left, y: primary.top + primary.height / 2 },
1537
+ startSync: "secondary",
1538
+ endSync: "primary"
1539
+ },
1540
+ {
1541
+ type: "top",
1542
+ value: Math.abs(primary.top - container.top),
1543
+ start: { x: primary.left + primary.width / 2, y: container.top },
1544
+ end: { x: primary.left + primary.width / 2, y: primary.top },
1545
+ startSync: "secondary",
1546
+ endSync: "primary"
1547
+ },
1548
+ {
1549
+ type: "right",
1550
+ value: Math.abs(container.right - primary.right),
1551
+ start: { x: primary.right, y: primary.top + primary.height / 2 },
1552
+ end: { x: container.right, y: primary.top + primary.height / 2 },
1553
+ startSync: "primary",
1554
+ endSync: "secondary"
1555
+ },
1556
+ {
1557
+ type: "bottom",
1558
+ value: Math.abs(container.bottom - primary.bottom),
1559
+ start: { x: primary.left + primary.width / 2, y: primary.bottom },
1560
+ end: { x: primary.left + primary.width / 2, y: container.bottom },
1561
+ startSync: "primary",
1562
+ endSync: "secondary"
1563
+ }
1564
+ ];
1565
+ } else {
1566
+ return [
1567
+ {
1568
+ type: "left",
1569
+ value: Math.abs(container.left - primary.left),
1570
+ start: { x: primary.left, y: container.top + container.height / 2 },
1571
+ end: { x: container.left, y: container.top + container.height / 2 },
1572
+ startSync: "primary",
1573
+ endSync: "secondary"
1574
+ },
1575
+ {
1576
+ type: "top",
1577
+ value: Math.abs(container.top - primary.top),
1578
+ start: { x: container.left + container.width / 2, y: primary.top },
1579
+ end: { x: container.left + container.width / 2, y: container.top },
1580
+ startSync: "primary",
1581
+ endSync: "secondary"
1582
+ },
1583
+ {
1584
+ type: "right",
1585
+ value: Math.abs(primary.right - container.right),
1586
+ start: { x: container.right, y: container.top + container.height / 2 },
1587
+ end: { x: primary.right, y: container.top + container.height / 2 },
1588
+ startSync: "secondary",
1589
+ endSync: "primary"
1590
+ },
1591
+ {
1592
+ type: "bottom",
1593
+ value: Math.abs(primary.bottom - container.bottom),
1594
+ start: { x: container.left + container.width / 2, y: container.bottom },
1595
+ end: { x: container.left + container.width / 2, y: primary.bottom },
1596
+ startSync: "secondary",
1597
+ endSync: "primary"
1598
+ }
1599
+ ];
1600
+ }
1601
+ }
1602
+ function getLivePoint(pt, owner, line, primaryDelta, secondaryDelta, scrollX = 0, scrollY = 0) {
1603
+ const syncX = owner === "secondary" ? secondaryDelta : primaryDelta;
1604
+ const syncY = owner === "secondary" ? secondaryDelta : primaryDelta;
1605
+ return {
1606
+ x: pt.x - (syncX?.deltaX ?? 0) - scrollX,
1607
+ y: pt.y - (syncY?.deltaY ?? 0) - scrollY
1608
+ };
1609
+ }
1610
+ function getLiveLineValue(line, result) {
1611
+ if (!result) {
1612
+ return line.value;
1613
+ }
1614
+ const primaryDelta = getTotalScrollDelta(
1615
+ result.primaryHierarchy,
1616
+ result.primaryPosition,
1617
+ result.primarySticky,
1618
+ result.primaryWinX,
1619
+ result.primaryWinY
1620
+ );
1621
+ const secondaryDelta = getTotalScrollDelta(
1622
+ result.secondaryHierarchy,
1623
+ result.secondaryPosition,
1624
+ result.secondarySticky,
1625
+ result.secondaryWinX,
1626
+ result.secondaryWinY
1627
+ );
1628
+ const startPoint = getLivePoint(line.start, line.startSync, line, primaryDelta, secondaryDelta);
1629
+ const endPoint = getLivePoint(line.end, line.endSync, line, primaryDelta, secondaryDelta);
1630
+ const dx = Math.abs(startPoint.x - endPoint.x);
1631
+ const dy = Math.abs(startPoint.y - endPoint.y);
1632
+ if (line.type === "top" || line.type === "bottom") {
1633
+ return dy;
1634
+ }
1635
+ if (line.type === "left" || line.type === "right") {
1636
+ return dx;
1637
+ }
1638
+ return Math.sqrt(dx * dx + dy * dy);
1639
+ }
1640
+ function createMeasurement(selectedElement, cursorX, cursorY, previousContext = null, previousElement = null) {
1641
+ const result = resolveAmbiguousContext(
1642
+ selectedElement,
1643
+ cursorX,
1644
+ cursorY,
1645
+ previousContext,
1646
+ previousElement
1647
+ );
1648
+ if (!result) {
1649
+ return null;
1650
+ }
1651
+ const { context, element: secondaryElement } = result;
1652
+ if (secondaryElement === selectedElement) return null;
1653
+ const primaryGeom = deduceGeometry(selectedElement);
1654
+ const secondaryGeom = deduceGeometry(secondaryElement);
1655
+ const primary = primaryGeom.rect;
1656
+ const secondary = secondaryGeom.rect;
1657
+ const lines = createMeasurementLines(context, primary, secondary);
1658
+ return {
1659
+ element: secondaryElement,
1660
+ result: {
1661
+ context,
1662
+ lines,
1663
+ primary,
1664
+ secondary,
1665
+ timestamp: performance.now(),
1666
+ primaryHierarchy: primaryGeom.scrollHierarchy,
1667
+ secondaryHierarchy: secondaryGeom.scrollHierarchy,
1668
+ secondaryElement,
1669
+ primaryPosition: primaryGeom.position,
1670
+ secondaryPosition: secondaryGeom.position,
1671
+ primarySticky: primaryGeom.stickyConfig,
1672
+ secondarySticky: secondaryGeom.stickyConfig,
1673
+ primaryWinX: primaryGeom.initialWindowX,
1674
+ primaryWinY: primaryGeom.initialWindowY,
1675
+ secondaryWinX: secondaryGeom.initialWindowX,
1676
+ secondaryWinY: secondaryGeom.initialWindowY
1677
+ }
1678
+ };
1679
+ }
1680
+ function createStateMachine() {
1681
+ let state = "IDLE";
1682
+ function getState() {
1683
+ return state;
1684
+ }
1685
+ function transitionTo(newState) {
1686
+ const validTransitions = {
1687
+ IDLE: ["ARMED", "FROZEN"],
1688
+ ARMED: ["MEASURING", "FROZEN", "IDLE"],
1689
+ MEASURING: ["FROZEN", "IDLE"],
1690
+ FROZEN: ["MEASURING", "IDLE"]
1691
+ };
1692
+ const allowed = validTransitions[state];
1693
+ if (allowed && allowed.includes(newState)) {
1694
+ state = newState;
1695
+ return true;
1696
+ }
1697
+ return false;
1698
+ }
1699
+ function isIdle() {
1700
+ return state === "IDLE";
1701
+ }
1702
+ function isArmed() {
1703
+ return state === "ARMED";
1704
+ }
1705
+ function isMeasuring() {
1706
+ return state === "MEASURING";
1707
+ }
1708
+ function isFrozen() {
1709
+ return state === "FROZEN";
1710
+ }
1711
+ return {
1712
+ getState,
1713
+ transitionTo,
1714
+ isIdle,
1715
+ isArmed,
1716
+ isMeasuring,
1717
+ isFrozen
1718
+ };
1719
+ }
1720
+ function createCalculatorState() {
1721
+ let state = {
1722
+ baseValue: 0,
1723
+ operation: null,
1724
+ inputValue: "",
1725
+ result: null,
1726
+ isActive: false
1727
+ };
1728
+ function calculate2() {
1729
+ const val = state.inputValue === "" ? "0" : state.inputValue;
1730
+ const inputNum = parseFloat(val);
1731
+ if (isNaN(inputNum)) {
1732
+ return null;
1733
+ }
1734
+ switch (state.operation) {
1735
+ case "+":
1736
+ return state.baseValue + inputNum;
1737
+ case "-":
1738
+ return state.baseValue - inputNum;
1739
+ case "*":
1740
+ return state.baseValue * inputNum;
1741
+ case "/":
1742
+ return inputNum !== 0 ? state.baseValue / inputNum : null;
1743
+ default:
1744
+ return null;
1745
+ }
1746
+ }
1747
+ function dispatch(action) {
1748
+ switch (action.type) {
1749
+ case "OPEN":
1750
+ state = {
1751
+ baseValue: action.baseValue,
1752
+ operation: null,
1753
+ inputValue: "",
1754
+ result: null,
1755
+ isActive: true
1756
+ };
1757
+ break;
1758
+ case "SYNC_VALUE":
1759
+ if (state.isActive && state.operation === null) {
1760
+ state = {
1761
+ ...state,
1762
+ baseValue: action.value
1763
+ };
1764
+ }
1765
+ break;
1766
+ case "INPUT_DIGIT":
1767
+ if (!state.isActive || !state.operation) return state;
1768
+ const isDot = action.digit === ".";
1769
+ const alreadyHasDot = (state.inputValue || "").includes(".");
1770
+ if (isDot && alreadyHasDot) return state;
1771
+ if (state.result !== null) {
1772
+ state = {
1773
+ ...state,
1774
+ inputValue: isDot ? "0." : action.digit,
1775
+ result: null
1776
+ };
1777
+ } else {
1778
+ state = {
1779
+ ...state,
1780
+ inputValue: state.inputValue === "0" && !isDot ? action.digit : state.inputValue + action.digit
1781
+ };
1782
+ }
1783
+ break;
1784
+ case "INPUT_OPERATION":
1785
+ if (!state.isActive) return state;
1786
+ const hasResult = state.result !== null;
1787
+ const isSwitchable = state.inputValue === "" || state.inputValue === "0";
1788
+ if (hasResult || state.operation && !isSwitchable) {
1789
+ const newBase = hasResult ? state.result : calculate2() ?? state.baseValue;
1790
+ state = {
1791
+ baseValue: newBase,
1792
+ operation: action.operation,
1793
+ inputValue: "",
1794
+ result: null,
1795
+ isActive: true
1796
+ };
1797
+ } else {
1798
+ state = {
1799
+ ...state,
1800
+ operation: action.operation,
1801
+ inputValue: "",
1802
+ result: null
1803
+ };
1804
+ }
1805
+ break;
1806
+ case "BACKSPACE":
1807
+ if (!state.isActive) return state;
1808
+ if (state.result !== null) {
1809
+ state = {
1810
+ ...state,
1811
+ result: null
1812
+ };
1813
+ } else if (state.inputValue.length > 0) {
1814
+ state = {
1815
+ ...state,
1816
+ inputValue: state.inputValue.slice(0, -1)
1817
+ };
1818
+ } else if (state.operation) {
1819
+ state = {
1820
+ ...state,
1821
+ operation: null
1822
+ };
1823
+ } else {
1824
+ state = {
1825
+ ...state,
1826
+ isActive: false
1827
+ };
1828
+ }
1829
+ break;
1830
+ case "DELETE":
1831
+ if (!state.isActive) return state;
1832
+ state = {
1833
+ baseValue: state.baseValue,
1834
+ operation: null,
1835
+ inputValue: "",
1836
+ result: null,
1837
+ isActive: false
1838
+ };
1839
+ break;
1840
+ case "ENTER":
1841
+ if (!state.isActive || !state.operation) {
1842
+ return state;
1843
+ }
1844
+ const result = calculate2();
1845
+ state = {
1846
+ ...state,
1847
+ result
1848
+ };
1849
+ break;
1850
+ case "CLOSE":
1851
+ state = {
1852
+ baseValue: 0,
1853
+ operation: null,
1854
+ inputValue: "",
1855
+ result: null,
1856
+ isActive: false
1857
+ };
1858
+ break;
1859
+ }
1860
+ return state;
1861
+ }
1862
+ function getState() {
1863
+ return { ...state };
1864
+ }
1865
+ return { getState, dispatch, calculate: calculate2 };
1866
+ }
1867
+ function createCalculatorIntegration() {
1868
+ const calculator = createCalculatorState();
1869
+ function open(baseValue) {
1870
+ calculator.dispatch({ type: "OPEN", baseValue });
1871
+ }
1872
+ function handleInput(key) {
1873
+ if (/^[0-9.]$/.test(key)) {
1874
+ calculator.dispatch({ type: "INPUT_DIGIT", digit: key });
1875
+ } else if (/^[+\-*/]$/.test(key)) {
1876
+ calculator.dispatch({
1877
+ type: "INPUT_OPERATION",
1878
+ operation: key
1879
+ });
1880
+ }
1881
+ }
1882
+ function handleBackspace() {
1883
+ calculator.dispatch({ type: "BACKSPACE" });
1884
+ }
1885
+ function handleDelete() {
1886
+ calculator.dispatch({ type: "DELETE" });
1887
+ }
1888
+ function handleEnter() {
1889
+ calculator.dispatch({ type: "ENTER" });
1890
+ }
1891
+ function close() {
1892
+ calculator.dispatch({ type: "CLOSE" });
1893
+ }
1894
+ function syncValue(value) {
1895
+ calculator.dispatch({ type: "SYNC_VALUE", value });
1896
+ }
1897
+ function getResult() {
1898
+ const state = calculator.getState();
1899
+ return state.result;
1900
+ }
1901
+ return {
1902
+ getState: calculator.getState,
1903
+ open,
1904
+ handleInput,
1905
+ handleBackspace,
1906
+ handleDelete,
1907
+ handleEnter,
1908
+ close,
1909
+ syncValue,
1910
+ getResult
1911
+ };
1912
+ }
1913
+ function createMeasurementSystem() {
1914
+ const baseReader = createReader();
1915
+ const reader = createFrequencyControlledReader(baseReader);
1916
+ const stateMachine = createStateMachine();
1917
+ const calculator = createCalculatorIntegration();
1918
+ const listeners = /* @__PURE__ */ new Set();
1919
+ let currentResult = null;
1920
+ let previousContext = null;
1921
+ let previousElement = null;
1922
+ function notifyListeners() {
1923
+ listeners.forEach((listener) => listener());
1924
+ }
1925
+ function measure(selectedElement, cursor) {
1926
+ stateMachine.transitionTo("ARMED");
1927
+ reader.scheduleRead(() => {
1928
+ performance.now();
1929
+ const measurement = createMeasurement(
1930
+ selectedElement,
1931
+ cursor.x,
1932
+ cursor.y,
1933
+ previousContext,
1934
+ previousElement
1935
+ );
1936
+ if (measurement) {
1937
+ const { result, element } = measurement;
1938
+ currentResult = result;
1939
+ previousContext = result.context;
1940
+ previousElement = element;
1941
+ stateMachine.transitionTo("MEASURING");
1942
+ notifyListeners();
1943
+ }
1944
+ });
1945
+ }
1946
+ function freeze() {
1947
+ const state = stateMachine.getState();
1948
+ if (state === "MEASURING" || state === "IDLE" || state === "ARMED") {
1949
+ stateMachine.transitionTo("FROZEN");
1950
+ notifyListeners();
1951
+ }
1952
+ }
1953
+ function unfreeze(isAltDown) {
1954
+ if (stateMachine.isFrozen()) {
1955
+ stateMachine.transitionTo(isAltDown ? "MEASURING" : "IDLE");
1956
+ notifyListeners();
1957
+ }
1958
+ }
1959
+ function abort() {
1960
+ reader.cancel();
1961
+ stateMachine.transitionTo("IDLE");
1962
+ calculator.close();
1963
+ currentResult = null;
1964
+ previousContext = null;
1965
+ previousElement = null;
1966
+ notifyListeners();
1967
+ }
1968
+ function stop() {
1969
+ reader.cancel();
1970
+ if (stateMachine.getState() === "MEASURING") {
1971
+ stateMachine.transitionTo("IDLE");
1972
+ notifyListeners();
1973
+ }
1974
+ }
1975
+ function cleanup() {
1976
+ abort();
1977
+ listeners.clear();
1978
+ currentResult = null;
1979
+ previousContext = null;
1980
+ previousElement = null;
1981
+ }
1982
+ function getState() {
1983
+ return stateMachine.getState();
1984
+ }
1985
+ function getCurrentResult() {
1986
+ return currentResult;
1987
+ }
1988
+ function getCalculator() {
1989
+ return calculator;
1990
+ }
1991
+ function onStateChange(listener) {
1992
+ listeners.add(listener);
1993
+ return () => {
1994
+ listeners.delete(listener);
1995
+ };
1996
+ }
1997
+ function updatePrimaryRect(rect) {
1998
+ if (!currentResult) return;
1999
+ const newPrimary = new DOMRect(
2000
+ rect.left + window.scrollX,
2001
+ rect.top + window.scrollY,
2002
+ rect.width,
2003
+ rect.height
2004
+ );
2005
+ currentResult = {
2006
+ ...currentResult,
2007
+ primary: newPrimary,
2008
+ primaryWinX: window.scrollX,
2009
+ primaryWinY: window.scrollY,
2010
+ lines: createMeasurementLines(currentResult.context, newPrimary, currentResult.secondary)
2011
+ };
2012
+ notifyListeners();
2013
+ }
2014
+ function updateSecondaryRect(rect) {
2015
+ if (!currentResult) return;
2016
+ const newSecondary = new DOMRect(
2017
+ rect.left + window.scrollX,
2018
+ rect.top + window.scrollY,
2019
+ rect.width,
2020
+ rect.height
2021
+ );
2022
+ currentResult = {
2023
+ ...currentResult,
2024
+ secondary: newSecondary,
2025
+ secondaryWinX: window.scrollX,
2026
+ secondaryWinY: window.scrollY,
2027
+ lines: createMeasurementLines(currentResult.context, currentResult.primary, newSecondary)
2028
+ };
2029
+ notifyListeners();
2030
+ }
2031
+ return {
2032
+ measure,
2033
+ abort,
2034
+ stop,
2035
+ freeze,
2036
+ unfreeze,
2037
+ cleanup,
2038
+ getState,
2039
+ getCurrentResult,
2040
+ getCalculator,
2041
+ onStateChange,
2042
+ updatePrimaryRect,
2043
+ updateSecondaryRect
2044
+ };
2045
+ }
2046
+ function createSelectionSystem() {
2047
+ let selectedElement = null;
2048
+ let selectedRect = null;
2049
+ let scrollHierarchy = [];
2050
+ let position = "static";
2051
+ let stickyConfig;
2052
+ let initialWindowX = 0;
2053
+ let initialWindowY = 0;
2054
+ const updateListeners = /* @__PURE__ */ new Set();
2055
+ function getMetadata() {
2056
+ return {
2057
+ element: selectedElement,
2058
+ rect: selectedRect,
2059
+ scrollHierarchy,
2060
+ position,
2061
+ stickyConfig,
2062
+ initialWindowX,
2063
+ initialWindowY
2064
+ };
2065
+ }
2066
+ function notifyListeners() {
2067
+ const metadata = getMetadata();
2068
+ updateListeners.forEach((listener) => listener(metadata));
2069
+ }
2070
+ function select(element) {
2071
+ if (selectedElement === element && (element !== null || selectedRect === null)) return;
2072
+ selectedElement = element;
2073
+ if (element) {
2074
+ requestAnimationFrame(() => {
2075
+ Promise.resolve().then(() => {
2076
+ if (selectedElement === element) {
2077
+ const geometry = deduceGeometry(element);
2078
+ selectedRect = geometry.rect;
2079
+ scrollHierarchy = geometry.scrollHierarchy;
2080
+ position = geometry.position;
2081
+ stickyConfig = geometry.stickyConfig;
2082
+ initialWindowX = geometry.initialWindowX;
2083
+ initialWindowY = geometry.initialWindowY;
2084
+ notifyListeners();
2085
+ }
2086
+ });
2087
+ });
2088
+ } else {
2089
+ selectedRect = null;
2090
+ scrollHierarchy = [];
2091
+ position = "static";
2092
+ stickyConfig = void 0;
2093
+ initialWindowX = 0;
2094
+ initialWindowY = 0;
2095
+ notifyListeners();
2096
+ }
2097
+ }
2098
+ function getSelected() {
2099
+ return selectedElement;
2100
+ }
2101
+ function getSelectedRect() {
2102
+ return selectedRect;
2103
+ }
2104
+ function clear() {
2105
+ select(null);
2106
+ }
2107
+ function onUpdate(callback) {
2108
+ updateListeners.add(callback);
2109
+ return () => {
2110
+ updateListeners.delete(callback);
2111
+ };
2112
+ }
2113
+ function updateRect(rect) {
2114
+ if (!selectedElement) return;
2115
+ selectedRect = new DOMRect(
2116
+ rect.left + window.scrollX,
2117
+ rect.top + window.scrollY,
2118
+ rect.width,
2119
+ rect.height
2120
+ );
2121
+ initialWindowX = window.scrollX;
2122
+ initialWindowY = window.scrollY;
2123
+ notifyListeners();
2124
+ }
2125
+ return {
2126
+ select,
2127
+ getSelected,
2128
+ getSelectedRect,
2129
+ getMetadata,
2130
+ clear,
2131
+ onUpdate,
2132
+ updateRect
2133
+ };
2134
+ }
2135
+ function createProjectionSystem() {
2136
+ let state = {
2137
+ direction: null,
2138
+ value: "",
2139
+ element: null
2140
+ };
2141
+ const listeners = /* @__PURE__ */ new Set();
2142
+ const notify = () => {
2143
+ listeners.forEach((l) => l({ ...state }));
2144
+ };
2145
+ return {
2146
+ getState: () => ({ ...state }),
2147
+ setDirection: (direction) => {
2148
+ state.direction = direction;
2149
+ notify();
2150
+ },
2151
+ setElement: (element) => {
2152
+ state.element = element;
2153
+ notify();
2154
+ },
2155
+ appendValue: (char, max) => {
2156
+ if (/^[0-9.]$/.test(char)) {
2157
+ const isDot = char === ".";
2158
+ const alreadyHasDot = state.value.includes(".");
2159
+ if (isDot && alreadyHasDot) return;
2160
+ const newValueStr = state.value + char;
2161
+ const newValueNum = parseFloat(newValueStr) || 0;
2162
+ if (max !== void 0 && newValueNum > max) {
2163
+ state.value = Math.floor(max).toString();
2164
+ } else {
2165
+ state.value = newValueStr;
2166
+ }
2167
+ notify();
2168
+ }
2169
+ },
2170
+ capValue: (max) => {
2171
+ const currentVal = parseFloat(state.value) || 0;
2172
+ if (currentVal > max) {
2173
+ state.value = Math.floor(max).toString();
2174
+ notify();
2175
+ }
2176
+ },
2177
+ backspace: () => {
2178
+ if (state.value.length > 0) {
2179
+ state.value = state.value.slice(0, -1);
2180
+ notify();
2181
+ } else if (state.direction) {
2182
+ state.direction = null;
2183
+ notify();
2184
+ }
2185
+ },
2186
+ clear: () => {
2187
+ state = { direction: null, value: "", element: null };
2188
+ notify();
2189
+ },
2190
+ onUpdate: (listener) => {
2191
+ listeners.add(listener);
2192
+ return () => listeners.delete(listener);
2193
+ }
2194
+ };
2195
+ }
2196
+ function createRulerSystem() {
2197
+ let state = {
2198
+ lines: []
2199
+ };
2200
+ const listeners = /* @__PURE__ */ new Set();
2201
+ const notify = () => {
2202
+ listeners.forEach((l) => l({ lines: [...state.lines] }));
2203
+ };
2204
+ return {
2205
+ getState: () => ({ lines: [...state.lines] }),
2206
+ addPair: (x, y) => {
2207
+ if (state.lines.length >= MAX_RULER_LINES) return null;
2208
+ const hLine = {
2209
+ id: `ruler-h-${Math.random().toString(36).slice(2, 9)}`,
2210
+ type: "horizontal",
2211
+ position: y
2212
+ };
2213
+ const vLine = {
2214
+ id: `ruler-v-${Math.random().toString(36).slice(2, 9)}`,
2215
+ type: "vertical",
2216
+ position: x
2217
+ };
2218
+ state.lines.push(hLine, vLine);
2219
+ notify();
2220
+ return vLine.id;
2221
+ },
2222
+ updateLine: (id, position) => {
2223
+ const index = state.lines.findIndex((l) => l.id === id);
2224
+ if (index !== -1 && state.lines[index]) {
2225
+ state.lines[index] = { ...state.lines[index], position };
2226
+ notify();
2227
+ }
2228
+ },
2229
+ removeLine: (id) => {
2230
+ state.lines = state.lines.filter((l) => l.id !== id);
2231
+ notify();
2232
+ },
2233
+ clear: () => {
2234
+ state.lines = [];
2235
+ notify();
2236
+ },
2237
+ onUpdate: (listener) => {
2238
+ listeners.add(listener);
2239
+ return () => listeners.delete(listener);
2240
+ }
2241
+ };
2242
+ }
2243
+ var IS_BROWSER = typeof window !== "undefined";
2244
+ function detectOS() {
2245
+ if (!IS_BROWSER) return "other";
2246
+ const platform = navigator.userAgentData?.platform;
2247
+ if (platform) {
2248
+ switch (platform) {
2249
+ case "macOS":
2250
+ return "macos";
2251
+ case "iOS":
2252
+ return "ios";
2253
+ case "Windows":
2254
+ return "windows";
2255
+ case "Android":
2256
+ return "android";
2257
+ case "Linux":
2258
+ return "linux";
2259
+ }
2260
+ }
2261
+ const ua = navigator.userAgent;
2262
+ if (/iPhone|iPad|iPod/.test(ua)) return "ios";
2263
+ if (/Macintosh/.test(ua)) return "macos";
2264
+ if (/Windows/.test(ua)) return "windows";
2265
+ if (/Android/.test(ua)) return "android";
2266
+ if (/Linux/.test(ua)) return "linux";
2267
+ return "other";
2268
+ }
2269
+ var OS_NAME = detectOS();
2270
+ var IS_APPLE = OS_NAME === "macos" || OS_NAME === "ios";
2271
+ var OS = {
2272
+ IS_BROWSER,
2273
+ NAME: OS_NAME,
2274
+ IS_MAC: OS_NAME === "macos",
2275
+ IS_IOS: OS_NAME === "ios",
2276
+ IS_APPLE,
2277
+ getControlKey: () => IS_APPLE ? "Meta" : "Control"
2278
+ };
2279
+ var DEFAULT_COMMANDS = {
2280
+ activate: "Alt",
2281
+ freeze: " ",
2282
+ select: OS.getControlKey(),
2283
+ clear: "Escape",
2284
+ calculator: {
2285
+ top: "t",
2286
+ right: "r",
2287
+ bottom: "b",
2288
+ left: "l",
2289
+ distance: "g"
2290
+ },
2291
+ projection: {
2292
+ top: "w",
2293
+ left: "a",
2294
+ bottom: "s",
2295
+ right: "d"
2296
+ },
2297
+ ruler: "r",
2298
+ selectionHoldDuration: 250
2299
+ };
2300
+ var DEFAULT_THEME = {
2301
+ primary: "rgba(24, 160, 251, 1)",
2302
+ secondary: "rgba(242, 78, 30, 1)",
2303
+ calcBg: "rgba(30, 30, 30, 0.95)",
2304
+ calcShadow: "rgba(0, 0, 0, 0.25)",
2305
+ calcOpHighlight: "rgba(24, 160, 251, 0.3)",
2306
+ calcText: "white",
2307
+ text: "white",
2308
+ projection: "rgba(155, 81, 224, 1)",
2309
+ ruler: "rgba(24, 160, 251, 1)"
2310
+ };
2311
+ var DEFAULT_ANIMATION = {
2312
+ enabled: true,
2313
+ lerpFactor: 0.25
2314
+ };
2315
+ function parseNumber(value, defaultValue) {
2316
+ if (value === void 0 || value === null || value === "") return defaultValue;
2317
+ const num = Number(value);
2318
+ return isFinite(num) && !isNaN(num) ? num : defaultValue;
2319
+ }
2320
+ function applyTheme(theme) {
2321
+ if (!theme) return;
2322
+ const root = document.documentElement;
2323
+ if (theme.primary) root.style.setProperty("--caliper-primary", theme.primary);
2324
+ if (theme.secondary) root.style.setProperty("--caliper-secondary", theme.secondary);
2325
+ if (theme.calcBg) root.style.setProperty("--caliper-calc-bg", theme.calcBg);
2326
+ if (theme.calcShadow) root.style.setProperty("--caliper-calc-shadow", theme.calcShadow);
2327
+ if (theme.calcOpHighlight)
2328
+ root.style.setProperty("--caliper-calc-op-highlight", theme.calcOpHighlight);
2329
+ if (theme.calcText) root.style.setProperty("--caliper-calc-text", theme.calcText);
2330
+ if (theme.text) root.style.setProperty("--caliper-text", theme.text);
2331
+ if (theme.projection) root.style.setProperty("--caliper-projection", theme.projection);
2332
+ if (theme.ruler) root.style.setProperty("--caliper-ruler", theme.ruler);
2333
+ }
2334
+ function mergeCommands(userCommands) {
2335
+ return {
2336
+ activate: userCommands?.activate ?? DEFAULT_COMMANDS.activate,
2337
+ freeze: userCommands?.freeze ?? DEFAULT_COMMANDS.freeze,
2338
+ select: userCommands?.select ?? DEFAULT_COMMANDS.select,
2339
+ clear: userCommands?.clear ?? DEFAULT_COMMANDS.clear,
2340
+ calculator: {
2341
+ top: userCommands?.calculator?.top ?? DEFAULT_COMMANDS.calculator.top,
2342
+ right: userCommands?.calculator?.right ?? DEFAULT_COMMANDS.calculator.right,
2343
+ bottom: userCommands?.calculator?.bottom ?? DEFAULT_COMMANDS.calculator.bottom,
2344
+ left: userCommands?.calculator?.left ?? DEFAULT_COMMANDS.calculator.left,
2345
+ distance: userCommands?.calculator?.distance ?? DEFAULT_COMMANDS.calculator.distance
2346
+ },
2347
+ projection: {
2348
+ top: userCommands?.projection?.top ?? DEFAULT_COMMANDS.projection.top,
2349
+ left: userCommands?.projection?.left ?? DEFAULT_COMMANDS.projection.left,
2350
+ bottom: userCommands?.projection?.bottom ?? DEFAULT_COMMANDS.projection.bottom,
2351
+ right: userCommands?.projection?.right ?? DEFAULT_COMMANDS.projection.right
2352
+ },
2353
+ ruler: userCommands?.ruler ?? DEFAULT_COMMANDS.ruler,
2354
+ selectionHoldDuration: parseNumber(
2355
+ userCommands?.selectionHoldDuration,
2356
+ DEFAULT_COMMANDS.selectionHoldDuration
2357
+ )
2358
+ };
2359
+ }
2360
+ function mergeAnimation(userAnimation) {
2361
+ return {
2362
+ enabled: userAnimation?.enabled ?? DEFAULT_ANIMATION.enabled,
2363
+ lerpFactor: parseNumber(userAnimation?.lerpFactor, DEFAULT_ANIMATION.lerpFactor)
2364
+ };
2365
+ }
2366
+ function getConfig() {
2367
+ if (typeof window !== "undefined") {
2368
+ const windowConfig = window.__CALIPER_CONFIG__ ?? {};
2369
+ const currentScript = typeof document !== "undefined" ? document.currentScript : null;
2370
+ const dataConfig = currentScript?.getAttribute("data-config") || (typeof document !== "undefined" ? document.querySelector("script[data-config]")?.getAttribute("data-config") : null);
2371
+ if (dataConfig) {
2372
+ try {
2373
+ const parsed = JSON.parse(dataConfig);
2374
+ return {
2375
+ ...windowConfig,
2376
+ ...parsed,
2377
+ theme: { ...windowConfig.theme, ...parsed.theme },
2378
+ commands: { ...windowConfig.commands, ...parsed.commands },
2379
+ animation: { ...windowConfig.animation, ...parsed.animation }
2380
+ };
2381
+ } catch (e) {
2382
+ console.warn("[CALIPER] Failed to parse data-config attribute", e);
2383
+ }
2384
+ }
2385
+ return windowConfig;
2386
+ }
2387
+ return {};
2388
+ }
2389
+ function setConfig(config) {
2390
+ if (typeof window !== "undefined") {
2391
+ window.__CALIPER_CONFIG__ = config;
2392
+ }
2393
+ }
2394
+ var CALIPER_LOGO_SVG = `data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTcyIiBoZWlnaHQ9IjUwIiB2aWV3Qm94PSIwIDAgMTcyIDUwIiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTQ3LjIxNDQgNy42MjkzOWUtMDZIMzIuNzkyOEwyNS44MjUgNDMuMzIyNUgzNS4wNjEzTDM2LjE5NTYgMzUuMDE2M0g0NC4xMzU2TDQ1LjI2OTkgNDMuMzIyNUg1NC42NjgzTDQ3LjIxNDQgNy42MjkzOWUtMDZaTTM5LjU5ODUgOC4zMDYySDQwLjczMjhMNDQuMTM1NiAyOC4xNzU5SDM2LjE5NTZMMzkuNTk4NSA4LjMwNjJaIiBmaWxsPSIjQUMyMzIzIi8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNNS4wMjMyOCAwTDAgNS4wNDg4NlYyOC4zMzg4TDUuMTg1MzIgMzMuMzg3NkgxNy41MDA0VjM1LjM0MkgxNS41NTZWNDYuNzQyN0gxOS4xMjA5TDI0LjMwNjIgMzUuNjY3OFYyNS44OTU4SDcuMTI5ODFWNy4zMjg5OUgxMy40NDk0VjBINS4wMjMyOFoiIGZpbGw9IiNBQzIzMjMiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik02Ni40OTc0IDcuNjI5MzllLTA2SDU3LjI2MVY0LjM5NzRINjIuNDQ2M1Y1LjIxMTczSDU3LjI2MVY2LjY3NzU0SDYwLjE3NzdWNy4zMjg5OUg1Ny4yNjFWOC45NTc2Nkg2MC4xNzc3VjkuNjA5MTNINTcuMjYxVjExLjA3NDlINjAuMTc3N1YxMS43MjY0SDU3LjI2MVYxMy4xOTIySDYyLjQ0NjNWMTMuODQzN0g1Ny4yNjFWMTUuNDcyM0g2MC4xNzc3VjE2LjEyMzhINTcuMjYxVjE3LjU4OTZINjAuMTc3N1YxOC4yNDExSDU3LjI2MVYxOS44Njk3SDYwLjE3NzdWMjAuNTIxMkg1Ny4yNjFWMjEuODI0MUg2Mi40NDYzVjIyLjYzODRINTcuMjYxVjI0LjI2NzFINjAuMTc3N1YyNC43NTU3SDU3LjI2MVYyNi4zODQ0SDYwLjE3NzdWMjcuMDM1OEg1Ny4yNjFWMjguNTAxNkg2MC4xNzc3VjI5LjE1MzFINTcuMjYxVjMwLjYxODlINjIuNDQ2M1YzMS40MzMySDU3LjI2MVYzMi44OTlINjAuMTc3N1YzMy41NTA1SDU3LjI2MVYzNS4wMTYzSDYwLjE3NzdWMzUuODMwNkg1Ny4yNjFWMzcuMjk2NEg2MC4xNzc3VjM3Ljk0NzlINTcuMjYxVjM5LjQxMzdINjIuNDQ2M1Y0MC4yMjhINTcuMjYxVjQzLjMyMjVINzcuODQwMlYzNS4wMTYzSDY2LjQ5NzRWNy42MjkzOWUtMDZaIiBmaWxsPSIjQUMyMzIzIi8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNNzcuODQwMiAyNy42ODczSDY3LjQ2OTZMNjkuNDE0MSAzMC42MTg5TDc5Ljc4NDcgMzQuMjAyVjQzLjk3MzlDNzcuNTQzOSA0NC4zNzMgNzYuNTQzOSA0NS4yNzY5IDc2LjU0MzkgNDcuMDY4NEM3Ni41NDM5IDQ5LjE4NTcgNzcuNTc4IDQ5Ljg1MjEgNzkuNzg0NyA1MEg4Mi44NjM1VjI4LjUwMTZINzcuODQwMlYyNy42ODczWiIgZmlsbD0iI0FDMjMyMyIvPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTg5Ljk5MzMgNy42MjkzOWUtMDZIODAuNzU3VjQuMzk3NEg4NS43ODAzVjUuMjExNzNIODAuNzU3VjYuNjc3NTRIODMuNTExN1Y3LjMyODk5SDgwLjc1N1Y4Ljk1NzY2SDgzLjUxMTdWOS40NDYyNkg4MC43NTdWMTEuMDc0OUg4My41MTE3VjExLjcyNjRIODAuNzU3VjEzLjE5MjJIODUuNzgwM1YxMy44NDM3SDgwLjc1N1YxNS40NzIzSDgzLjUxMTdWMTYuMTIzOEg4MC43NTdWMTcuNTg5Nkg4My41MTE3VjE4LjI0MTFIODAuNzU3VjE5Ljg2OTdIODMuNTExN1YyMC41MjEySDgwLjc1N1YyMS44MjQxSDg1Ljc4MDNWMjIuNjM4NEg4MC43NTdWMjcuMDM1OEg4My44MzU4VjQzLjMyMjVIODcuMjM4NlYxMi4zNzc5SDkyLjI2MTlWOS40NDYyNkg5My4wNzIxVjEwLjA5NzdIOTkuNzE1OEM5OC45MDU2IDguNzk0NzkgOTcuMTIzMSA3LjY1NDczIDk0Ljg1NDYgNy4wMDMyN0g4OS45OTMzVjcuNjI5MzllLTA2WiIgZmlsbD0iI0FDMjMyMyIvPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTkyLjI2MTkgMTMuODQzN0g4OC4wNDg4VjQzLjMyMjVIOTIuMjYxOVYyOC41MDE2SDkzLjA3MjFWMjkuMzE2SDk0Ljg1NDZWMjUuNTdIOTMuMDcyMVYyNi4zODQ0SDkyLjI2MTlWMTMuODQzN1oiIGZpbGw9IiNBQzIzMjMiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik05NS42NjQ4IDYuMzUxOFY3LjYyOTM5ZS0wNkgxMTMuMDAzTDExOS42NDcgNi4zNTE4VjIxLjgyNDFMMTEzLjAwMyAyOC41MDE2SDEwNC45MDFMMTA0LjczOSA0My4zMjI1SDk1LjY2NDhWMTEuMDc0OUgxMDAuODVDMTAwLjUyNiA4LjYzMTkzIDk4LjkwNTYgNy4zMjkgOTUuNjY0OCA2LjM1MThaTTEwNC45MDEgNy45ODA0NkgxMTAuNTczVjIwLjUyMTJIMTA0LjkwMVY3Ljk4MDQ2WiIgZmlsbD0iI0FDMjMyMyIvPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTE0My4zMDUgNy42MjkzOWUtMDZIMTIzLjIxMlY0My4zMjI1SDE0My4zMDVWMzUuMDE2M0gxMzIuNDQ4VjI0LjQzSDE0MS42ODVWMTYuMTIzOEgxMzIuNDQ4VjcuOTgwNDZIMTQzLjMwNVY3LjYyOTM5ZS0wNloiIGZpbGw9IiNBQzIzMjMiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xNDcuMTk0IDQzLjMyMjVWNy42MjkzOWUtMDZIMTY1LjE4TDE3MS41IDUuODYzMlYxNi45MzgxTDE2Ni4xNTMgMjEuODI0MUwxNzEuNSAyNS41N1Y0My4zMjI1SDE2Mi40MjZWMjUuNTdIMTU2LjI2OFY0My4zMjI1SDE0Ny4xOTRaTTE1Ni4yNjggNy45ODA0NkgxNjIuNDI2VjE3LjU4OTZIMTU2LjI2OFY3Ljk4MDQ2WiIgZmlsbD0iI0FDMjMyMyIvPgo8L3N2Zz4K`;
2395
+ async function fetchLatestVersion() {
2396
+ try {
2397
+ const endpoint = `https://unpkg.com/@oyerinde/caliper@latest/package.json`;
2398
+ const response = await fetch(endpoint, {
2399
+ method: "GET",
2400
+ cache: "no-store",
2401
+ headers: {
2402
+ Accept: "application/json"
2403
+ },
2404
+ signal: AbortSignal.timeout(3e3)
2405
+ });
2406
+ if (response.ok) {
2407
+ return await response.json();
2408
+ }
2409
+ } catch (error) {
2410
+ }
2411
+ return null;
2412
+ }
2413
+ function compareVersions(v1, v2) {
2414
+ const parts1 = v1.split(".").map(Number);
2415
+ const parts2 = v2.split(".").map(Number);
2416
+ for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {
2417
+ const part1 = parts1[i] || 0;
2418
+ const part2 = parts2[i] || 0;
2419
+ if (part1 < part2) return -1;
2420
+ if (part1 > part2) return 1;
2421
+ }
2422
+ return 0;
2423
+ }
2424
+ async function showVersionInfo(currentVersion) {
2425
+ if (typeof window === "undefined") return;
2426
+ const style2 = `
2427
+ font-size: 1px;
2428
+ padding: 10px 34px;
2429
+ background-image: url('${CALIPER_LOGO_SVG}');
2430
+ background-size: contain;
2431
+ background-repeat: no-repeat;
2432
+ background-position: center;
2433
+ `;
2434
+ console.log(`%c `, style2);
2435
+ console.log(
2436
+ `%cMeasurement Tool v${currentVersion}
2437
+ %cDocs -> https://caliper.danieloyerinde.com`,
2438
+ "color: #3b82f6; font-weight: bold; font-family: monospace; padding-top: 5px;",
2439
+ "color: #6b7280; font-family: monospace;"
2440
+ );
2441
+ fetchLatestVersion().then((latestInfo) => {
2442
+ if (!latestInfo) return;
2443
+ const comparison = compareVersions(currentVersion, latestInfo.version);
2444
+ if (comparison < 0) {
2445
+ console.log(
2446
+ `%c\u26A0 Update available: ${latestInfo.version} (you're on ${currentVersion})`,
2447
+ "color: #f59e0b; font-weight: bold; font-family: monospace;"
2448
+ );
2449
+ }
2450
+ }).catch(() => {
2451
+ });
2452
+ }
2453
+ function lerp(start, end, t) {
2454
+ return start + (end - start) * t;
2455
+ }
2456
+ function lerpRect(start, end, t) {
2457
+ return {
2458
+ left: lerp(start.left, end.left, t),
2459
+ top: lerp(start.top, end.top, t),
2460
+ width: lerp(start.width, end.width, t),
2461
+ height: lerp(start.height, end.height, t)
2462
+ };
2463
+ }
2464
+
2465
+ // ../overlay/dist/index.js
2466
+ var OVERLAY_STYLES = `
2467
+ :root {
2468
+ interpolate-size: allow-keywords;
2469
+ --caliper-primary: ${DEFAULT_THEME.primary};
2470
+ --caliper-primary-90: ${DEFAULT_THEME.primary.replace("1)", "0.9)")};
2471
+ --caliper-primary-95: ${DEFAULT_THEME.primary.replace("1)", "0.95)")};
2472
+ --caliper-primary-50: ${DEFAULT_THEME.primary.replace("1)", "0.5)")};
2473
+ --caliper-primary-05: ${DEFAULT_THEME.primary.replace("1)", "0.05)")};
2474
+ --caliper-secondary: ${DEFAULT_THEME.secondary};
2475
+ --caliper-secondary-50: ${DEFAULT_THEME.secondary.replace("1)", "0.5)")};
2476
+ --caliper-secondary-05: ${DEFAULT_THEME.secondary.replace("1)", "0.05)")};
2477
+ --caliper-calc-bg: ${DEFAULT_THEME.calcBg};
2478
+ --caliper-calc-shadow: ${DEFAULT_THEME.calcShadow};
2479
+ --caliper-calc-op-highlight: ${DEFAULT_THEME.calcOpHighlight};
2480
+ --caliper-calc-text: ${DEFAULT_THEME.calcText};
2481
+ --caliper-text: ${DEFAULT_THEME.text};
2482
+ --caliper-projection: ${DEFAULT_THEME.projection};
2483
+ --caliper-projection-90: ${DEFAULT_THEME.projection.replace("1)", "0.9)")};
2484
+ --caliper-projection-light: ${DEFAULT_THEME.projection.replace("1)", "0.2)")};
2485
+ --caliper-ruler: ${DEFAULT_THEME.ruler};
2486
+ }
2487
+
2488
+ #caliper-overlay-root {
2489
+ position: fixed;
2490
+ top: 0;
2491
+ left: 0;
2492
+ width: 100vw;
2493
+ height: 100vh;
2494
+ pointer-events: none;
2495
+ overflow: visible;
2496
+ z-index: 999999;
2497
+ }
2498
+
2499
+ .${CALIPER_PREFIX}viewport-fixed {
2500
+ position: fixed;
2501
+ top: 0;
2502
+ left: 0;
2503
+ width: 100vw;
2504
+ height: 100vh;
2505
+ pointer-events: none;
2506
+ overflow: visible;
2507
+ }
2508
+
2509
+ .${CALIPER_PREFIX}overlay {
2510
+ position: fixed;
2511
+ top: 0;
2512
+ left: 0;
2513
+ width: 100vw;
2514
+ height: 100vh;
2515
+ pointer-events: none;
2516
+ z-index: 999999;
2517
+ }
2518
+
2519
+ .${CALIPER_PREFIX}ruler-layer {
2520
+ position: fixed;
2521
+ top: 0;
2522
+ left: 0;
2523
+ width: 100vw;
2524
+ height: 100vh;
2525
+ pointer-events: none;
2526
+ z-index: 1000000;
2527
+ touch-action: none;
2528
+ }
2529
+
2530
+ .${CALIPER_PREFIX}alt-mode * {
2531
+ pointer-events: none !important;
2532
+ }
2533
+
2534
+ .${CALIPER_PREFIX}line {
2535
+ stroke: var(--caliper-secondary);
2536
+ stroke-width: 1px;
2537
+ pointer-events: auto;
2538
+ cursor: pointer;
2539
+ }
2540
+
2541
+ .${CALIPER_PREFIX}projection-line {
2542
+ stroke: var(--caliper-projection);
2543
+ stroke-width: 2px;
2544
+ stroke-dasharray: 4 2;
2545
+ pointer-events: auto;
2546
+ }
2547
+
2548
+ .${CALIPER_PREFIX}label {
2549
+ position: fixed;
2550
+ pointer-events: auto;
2551
+ cursor: pointer;
2552
+ background: var(--caliper-secondary);
2553
+ color: var(--caliper-text);
2554
+ padding: 2px 6px;
2555
+ border-radius: 3px;
2556
+ font-size: 11px;
2557
+ font-weight: 500;
2558
+ font-family: Inter, system-ui, -apple-system, sans-serif;
2559
+ white-space: nowrap;
2560
+ z-index: 1000000;
2561
+ will-change: transform;
2562
+ }
2563
+
2564
+ .${CALIPER_PREFIX}projection-label {
2565
+ background: var(--caliper-projection);
2566
+ z-index: 1000001;
2567
+ }
2568
+
2569
+ .${CALIPER_PREFIX}selection-label {
2570
+ position: fixed;
2571
+ pointer-events: none;
2572
+ background: var(--caliper-primary);
2573
+ color: var(--caliper-text);
2574
+ padding: 2px 4px;
2575
+ border-radius: 2px;
2576
+ font-size: 10px;
2577
+ font-weight: 500;
2578
+ font-family: Inter, system-ui, -apple-system, sans-serif;
2579
+ white-space: nowrap;
2580
+ z-index: 1000001;
2581
+ will-change: transform, opacity;
2582
+ transition: opacity 0.2s ease-in-out;
2583
+ }
2584
+
2585
+ .${CALIPER_PREFIX}boundary-box {
2586
+ position: fixed;
2587
+ pointer-events: none;
2588
+ box-sizing: border-box;
2589
+ touch-action: none;
2590
+ }
2591
+
2592
+ .${CALIPER_PREFIX}boundary-box-selected {
2593
+ border: 2px solid var(--caliper-primary);
2594
+ background: transparent;
2595
+ z-index: 999998;
2596
+ will-change: transform, width, height;
2597
+ }
2598
+
2599
+ .${CALIPER_PREFIX}boundary-box-secondary {
2600
+ border: 1px dashed var(--caliper-secondary-50);
2601
+ background: var(--caliper-secondary-05);
2602
+ z-index: 999997;
2603
+ }
2604
+
2605
+ .${CALIPER_PREFIX}calculator, .${CALIPER_PREFIX}projection-input {
2606
+ position: fixed;
2607
+ pointer-events: auto;
2608
+ background: var(--caliper-calc-bg);
2609
+ color: var(--caliper-calc-text);
2610
+ padding: 0 8px;
2611
+ border-radius: 4px;
2612
+ font-size: 12px;
2613
+ font-weight: 500;
2614
+ font-family: Inter, system-ui, -apple-system, sans-serif;
2615
+ z-index: 1000005;
2616
+ box-shadow: 0 4px 12px var(--caliper-calc-shadow);
2617
+ display: flex;
2618
+ align-items: center;
2619
+ gap: 6px;
2620
+ height: 28px;
2621
+ user-select: none;
2622
+ overflow: hidden;
2623
+ will-change: transform, width;
2624
+ transform-origin: center;
2625
+ width: fit-content;
2626
+ min-width: 32px;
2627
+ white-space: nowrap;
2628
+ transition: width 0.2s cubic-bezier(0.4, 0, 0.2, 1), border-color 0.2s, box-shadow 0.2s, background-color 0.2s;
2629
+ border: 1px solid transparent;
2630
+ }
2631
+
2632
+ .${CALIPER_PREFIX}calculator-focused, .${CALIPER_PREFIX}projection-input-focused {
2633
+ border-color: var(--caliper-primary);
2634
+ box-shadow: 0 0 0 2px var(--caliper-primary-50), 0 4px 12px var(--caliper-calc-shadow);
2635
+ background: var(--caliper-calc-bg);
2636
+ }
2637
+
2638
+ .${CALIPER_PREFIX}projection-input {
2639
+ border-left: 3px solid var(--caliper-projection);
2640
+ }
2641
+
2642
+ .${CALIPER_PREFIX}projection-direction-tag {
2643
+ background: var(--caliper-projection-light);
2644
+ color: var(--caliper-projection);
2645
+ font-size: 10px;
2646
+ padding: 2px 4px;
2647
+ border-radius: 2px;
2648
+ text-transform: uppercase;
2649
+ font-weight: 700;
2650
+ }
2651
+
2652
+ .${CALIPER_PREFIX}calculator-base {
2653
+ opacity: 0.7;
2654
+ transition: opacity 0.2s;
2655
+ }
2656
+
2657
+ .${CALIPER_PREFIX}calculator-base-active {
2658
+ opacity: 1;
2659
+ }
2660
+
2661
+ .${CALIPER_PREFIX}calculator-operation {
2662
+ background-color: var(--caliper-calc-op-highlight);
2663
+ padding: 4px;
2664
+ border-radius: 2px;
2665
+ transition: all 0.2s;
2666
+ display: inline-flex;
2667
+ align-items: center;
2668
+ justify-content: center;
2669
+ animation: pulse 0.3s ease-in-out;
2670
+ }
2671
+
2672
+ .${CALIPER_PREFIX}calculator-input, .${CALIPER_PREFIX}projection-current-value {
2673
+ min-width: 8px;
2674
+ text-align: right;
2675
+ transition: all 0.2s;
2676
+ }
2677
+
2678
+ .${CALIPER_PREFIX}projection-current-value {
2679
+ color: var(--caliper-projection);
2680
+ font-weight: bold;
2681
+ }
2682
+
2683
+ .${CALIPER_PREFIX}calculator-result {
2684
+ font-weight: bold;
2685
+ color: var(--caliper-primary);
2686
+ animation: slideIn 0.3s ease-out;
2687
+ }
2688
+
2689
+ @keyframes pulse {
2690
+ 0%, 100% { transform: scale(1); }
2691
+ 50% { transform: scale(1.1); }
2692
+ }
2693
+
2694
+ @keyframes slideIn {
2695
+ from {
2696
+ opacity: 0;
2697
+ transform: translateX(-10px);
2698
+ }
2699
+ to {
2700
+ opacity: 1;
2701
+ transform: translateX(0);
2702
+ }
2703
+ }
2704
+
2705
+ @keyframes slideOut {
2706
+ from {
2707
+ opacity: 1;
2708
+ transform: translateX(0);
2709
+ }
2710
+ to {
2711
+ opacity: 0;
2712
+ transform: translateX(10px);
2713
+ }
2714
+ }
2715
+
2716
+ .${CALIPER_PREFIX}line-clickable {
2717
+ pointer-events: auto;
2718
+ cursor: pointer;
2719
+ transition: stroke-width 0.2s;
2720
+ }
2721
+
2722
+ .${CALIPER_PREFIX}line-hit-target {
2723
+ stroke: transparent;
2724
+ stroke-width: 12px;
2725
+ pointer-events: auto;
2726
+ cursor: pointer;
2727
+ }
2728
+
2729
+
2730
+ .${CALIPER_PREFIX}line-clickable:hover {
2731
+ }
2732
+
2733
+ .${CALIPER_PREFIX}ruler-line-visual {
2734
+ transition: transform 0.1s ease-out;
2735
+ will-change: transform;
2736
+ position: fixed;
2737
+ background-color: var(--caliper-ruler, var(--caliper-primary, rgba(24, 160, 251, 1)));
2738
+ z-index: 1000000;
2739
+ }
2740
+
2741
+ .${CALIPER_PREFIX}ruler-label {
2742
+ background: var(--caliper-primary);
2743
+ border: 1px solid rgba(255, 255, 255, 0.2);
2744
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
2745
+ position: fixed;
2746
+ z-index: 1000002;
2747
+ }
2748
+
2749
+ .${CALIPER_PREFIX}ruler-bridge-label {
2750
+ position: fixed;
2751
+ background: var(--caliper-secondary);
2752
+ z-index: 1000003;
2753
+ color: white;
2754
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
2755
+ }
2756
+ `;
2757
+ var PREFIX = CALIPER_PREFIX;
2758
+ var _tmpl$ = /* @__PURE__ */ template(`<svg><defs><clipPath><rect></svg>`, false, true, false);
2759
+ var _tmpl$2 = /* @__PURE__ */ template(`<svg style=z-index:999999><g>`);
2760
+ var _tmpl$3 = /* @__PURE__ */ template(`<svg><g data-caliper-ignore style=pointer-events:auto;cursor:pointer><line></line><line></svg>`, false, true, false);
2761
+ function MeasurementLinesWithCalculator(props) {
2762
+ const [hoveredLine, setHoveredLine] = createSignal(null);
2763
+ const hasClipping = () => isFinite(props.data.common.minX);
2764
+ const clipPathId = createSignal(`caliper-lines-clip-${Math.random().toString(36).substring(2, 9)}`)[0]();
2765
+ const vCommon = () => ({
2766
+ minX: props.data.common.minX - props.viewport.scrollX,
2767
+ maxX: props.data.common.maxX - props.viewport.scrollX,
2768
+ minY: props.data.common.minY - props.viewport.scrollY,
2769
+ maxY: props.data.common.maxY - props.viewport.scrollY
2770
+ });
2771
+ return (() => {
2772
+ var _el$ = _tmpl$2(), _el$5 = _el$.firstChild;
2773
+ setAttribute(_el$, "class", `${PREFIX}viewport-fixed`);
2774
+ insert(_el$, createComponent(Show, {
2775
+ get when() {
2776
+ return hasClipping();
2777
+ },
2778
+ get children() {
2779
+ var _el$2 = _tmpl$(), _el$3 = _el$2.firstChild, _el$4 = _el$3.firstChild;
2780
+ setAttribute(_el$3, "id", clipPathId);
2781
+ createRenderEffect((_p$) => {
2782
+ var _v$ = vCommon().minX, _v$2 = vCommon().minY, _v$3 = Math.max(0, vCommon().maxX - vCommon().minX), _v$4 = Math.max(0, vCommon().maxY - vCommon().minY);
2783
+ _v$ !== _p$.e && setAttribute(_el$4, "x", _p$.e = _v$);
2784
+ _v$2 !== _p$.t && setAttribute(_el$4, "y", _p$.t = _v$2);
2785
+ _v$3 !== _p$.a && setAttribute(_el$4, "width", _p$.a = _v$3);
2786
+ _v$4 !== _p$.o && setAttribute(_el$4, "height", _p$.o = _v$4);
2787
+ return _p$;
2788
+ }, {
2789
+ e: void 0,
2790
+ t: void 0,
2791
+ a: void 0,
2792
+ o: void 0
2793
+ });
2794
+ return _el$2;
2795
+ }
2796
+ }), _el$5);
2797
+ insert(_el$5, createComponent(For, {
2798
+ get each() {
2799
+ return props.lines;
2800
+ },
2801
+ children: (line, index) => {
2802
+ const lineData = createMemo(() => {
2803
+ const sRaw = getLivePoint(line.start, line.startSync, line, props.data.primary.delta, props.data.secondary.delta, props.viewport.scrollX, props.viewport.scrollY);
2804
+ const eRaw = getLivePoint(line.end, line.endSync, line, props.data.primary.delta, props.data.secondary.delta, props.viewport.scrollX, props.viewport.scrollY);
2805
+ let start = sRaw;
2806
+ let end = eRaw;
2807
+ if (!props.data.isSameContext) {
2808
+ start = clampPointToGeometry(sRaw, line.startSync === "secondary" ? props.data.secondary.geo : props.data.primary.geo, props.viewport);
2809
+ const eRawClamped = clampPointToGeometry(eRaw, line.endSync === "secondary" ? props.data.secondary.geo : props.data.primary.geo, props.viewport);
2810
+ end = {
2811
+ ...eRawClamped
2812
+ };
2813
+ }
2814
+ if (line.type === "top" || line.type === "bottom") {
2815
+ if (line.startSync === "primary") end.x = start.x;
2816
+ else start.x = end.x;
2817
+ } else if (line.type === "left" || line.type === "right") {
2818
+ if (line.startSync === "primary") end.y = start.y;
2819
+ else start.y = end.y;
2820
+ }
2821
+ let liveValue = 0;
2822
+ if (line.type === "top" || line.type === "bottom") {
2823
+ liveValue = Math.abs(start.y - end.y);
2824
+ } else if (line.type === "left" || line.type === "right") {
2825
+ liveValue = Math.abs(start.x - end.x);
2826
+ } else {
2827
+ liveValue = Math.sqrt(Math.pow(start.x - end.x, 2) + Math.pow(start.y - end.y, 2));
2828
+ }
2829
+ return {
2830
+ x1: start.x,
2831
+ y1: start.y,
2832
+ x2: end.x,
2833
+ y2: end.y,
2834
+ liveValue
2835
+ };
2836
+ });
2837
+ const isHovered = () => hoveredLine() === index();
2838
+ return (() => {
2839
+ var _el$6 = _tmpl$3(), _el$7 = _el$6.firstChild, _el$8 = _el$7.nextSibling;
2840
+ _el$6.$$click = (e) => {
2841
+ e.stopPropagation();
2842
+ const data = lineData();
2843
+ props.onLineClick?.(line, data.liveValue);
2844
+ };
2845
+ _el$6.addEventListener("mouseleave", () => setHoveredLine(null));
2846
+ _el$6.addEventListener("mouseenter", () => setHoveredLine(index()));
2847
+ setAttribute(_el$7, "class", `${PREFIX}line-hit-target`);
2848
+ setAttribute(_el$8, "class", `${PREFIX}line ${PREFIX}line-clickable`);
2849
+ createRenderEffect((_p$) => {
2850
+ var _v$5 = lineData().x1, _v$6 = lineData().y1, _v$7 = lineData().x2, _v$8 = lineData().y2, _v$9 = lineData().x1, _v$0 = lineData().y1, _v$1 = lineData().x2, _v$10 = lineData().y2, _v$11 = isHovered() ? 2 : 1;
2851
+ _v$5 !== _p$.e && setAttribute(_el$7, "x1", _p$.e = _v$5);
2852
+ _v$6 !== _p$.t && setAttribute(_el$7, "y1", _p$.t = _v$6);
2853
+ _v$7 !== _p$.a && setAttribute(_el$7, "x2", _p$.a = _v$7);
2854
+ _v$8 !== _p$.o && setAttribute(_el$7, "y2", _p$.o = _v$8);
2855
+ _v$9 !== _p$.i && setAttribute(_el$8, "x1", _p$.i = _v$9);
2856
+ _v$0 !== _p$.n && setAttribute(_el$8, "y1", _p$.n = _v$0);
2857
+ _v$1 !== _p$.s && setAttribute(_el$8, "x2", _p$.s = _v$1);
2858
+ _v$10 !== _p$.h && setAttribute(_el$8, "y2", _p$.h = _v$10);
2859
+ _v$11 !== _p$.r && setAttribute(_el$8, "stroke-width", _p$.r = _v$11);
2860
+ return _p$;
2861
+ }, {
2862
+ e: void 0,
2863
+ t: void 0,
2864
+ a: void 0,
2865
+ o: void 0,
2866
+ i: void 0,
2867
+ n: void 0,
2868
+ s: void 0,
2869
+ h: void 0,
2870
+ r: void 0
2871
+ });
2872
+ return _el$6;
2873
+ })();
2874
+ }
2875
+ }));
2876
+ createRenderEffect(() => setAttribute(_el$5, "clip-path", hasClipping() ? `url(#${clipPathId})` : void 0));
2877
+ return _el$;
2878
+ })();
2879
+ }
2880
+ delegateEvents(["click"]);
2881
+ var _tmpl$4 = /* @__PURE__ */ template(`<div style=z-index:1000000>`);
2882
+ var _tmpl$22 = /* @__PURE__ */ template(`<div data-caliper-ignore style=left:0;top:0>`);
2883
+ function MeasurementLabels(props) {
2884
+ const margin = 16;
2885
+ return (() => {
2886
+ var _el$ = _tmpl$4();
2887
+ className(_el$, `${PREFIX}viewport-fixed`);
2888
+ insert(_el$, createComponent(For, {
2889
+ get each() {
2890
+ return props.lines;
2891
+ },
2892
+ children: (line) => {
2893
+ const position = createMemo(() => {
2894
+ props.viewport.version;
2895
+ const sRaw = getLivePoint(line.start, line.startSync, line, props.data.primary.delta, props.data.secondary.delta, props.viewport.scrollX, props.viewport.scrollY);
2896
+ const eRaw = getLivePoint(line.end, line.endSync, line, props.data.primary.delta, props.data.secondary.delta, props.viewport.scrollX, props.viewport.scrollY);
2897
+ const dxRaw = Math.abs(sRaw.x - eRaw.x);
2898
+ const dyRaw = Math.abs(sRaw.y - eRaw.y);
2899
+ let liveValue = 0;
2900
+ if (line.type === "top" || line.type === "bottom") {
2901
+ liveValue = dyRaw;
2902
+ } else if (line.type === "left" || line.type === "right") {
2903
+ liveValue = dxRaw;
2904
+ } else {
2905
+ liveValue = Math.sqrt(dxRaw * dxRaw + dyRaw * dyRaw);
2906
+ }
2907
+ let start = sRaw;
2908
+ let end = eRaw;
2909
+ if (!props.data.isSameContext) {
2910
+ start = clampPointToGeometry(sRaw, line.startSync === "secondary" ? props.data.secondary.geo : props.data.primary.geo, props.viewport);
2911
+ const eClamped = clampPointToGeometry(eRaw, line.endSync === "secondary" ? props.data.secondary.geo : props.data.primary.geo, props.viewport);
2912
+ end = {
2913
+ ...eClamped
2914
+ };
2915
+ }
2916
+ if (line.type === "top" || line.type === "bottom") {
2917
+ if (line.startSync === "primary") end.x = start.x;
2918
+ else start.x = end.x;
2919
+ } else if (line.type === "left" || line.type === "right") {
2920
+ if (line.startSync === "primary") end.y = start.y;
2921
+ else start.y = end.y;
2922
+ }
2923
+ const naturalX = (start.x + end.x) / 2;
2924
+ const naturalY = (start.y + end.y) / 2;
2925
+ const vpMinX = 0;
2926
+ const vpMaxX = props.viewport.width;
2927
+ const vpMinY = 0;
2928
+ const vpMaxY = props.viewport.height;
2929
+ const common = props.data.common;
2930
+ const hasCommon = isFinite(common.minX);
2931
+ const cMinX = hasCommon ? Math.max(vpMinX, common.minX - props.viewport.scrollX) : vpMinX;
2932
+ const cMaxX = hasCommon ? Math.min(vpMaxX, common.maxX - props.viewport.scrollX) : vpMaxX;
2933
+ const cMinY = hasCommon ? Math.max(vpMinY, common.minY - props.viewport.scrollY) : vpMinY;
2934
+ const cMaxY = hasCommon ? Math.min(vpMaxY, common.maxY - props.viewport.scrollY) : vpMaxY;
2935
+ const lineMinX = Math.min(start.x, end.x);
2936
+ const lineMaxX = Math.max(start.x, end.x);
2937
+ const lineMinY = Math.min(start.y, end.y);
2938
+ const lineMaxY = Math.max(start.y, end.y);
2939
+ const isFullyHidden = lineMaxY < cMinY || lineMinY > cMaxY || lineMaxX < cMinX || lineMinX > cMaxX;
2940
+ if (isFullyHidden) return {
2941
+ x: 0,
2942
+ y: 0,
2943
+ isHidden: true,
2944
+ value: 0
2945
+ };
2946
+ const visibleLineMinX = Math.max(lineMinX, cMinX);
2947
+ const visibleLineMaxX = Math.min(lineMaxX, cMaxX);
2948
+ const visibleLineMinY = Math.max(lineMinY, cMinY);
2949
+ const visibleLineMaxY = Math.min(lineMaxY, cMaxY);
2950
+ const centerX = (visibleLineMinX + visibleLineMaxX) / 2;
2951
+ const centerY = (visibleLineMinY + visibleLineMaxY) / 2;
2952
+ let targetX = naturalX;
2953
+ let targetY = naturalY;
2954
+ if (Math.abs(start.x - end.x) < 1) {
2955
+ targetY = centerY;
2956
+ targetX = Math.max(cMinX + margin, Math.min(cMaxX - margin, targetX));
2957
+ } else if (Math.abs(start.y - end.y) < 1) {
2958
+ targetX = centerX;
2959
+ targetY = Math.max(cMinY + margin, Math.min(cMaxY - margin, targetY));
2960
+ } else {
2961
+ targetX = Math.max(cMinX + margin, Math.min(cMaxX - margin, naturalX));
2962
+ targetY = Math.max(cMinY + margin, Math.min(cMaxY - margin, naturalY));
2963
+ }
2964
+ return {
2965
+ x: targetX,
2966
+ y: targetY,
2967
+ isHidden: false,
2968
+ value: liveValue
2969
+ };
2970
+ });
2971
+ return createComponent(Show, {
2972
+ get when() {
2973
+ return memo(() => !!position())() && !position().isHidden;
2974
+ },
2975
+ get children() {
2976
+ var _el$2 = _tmpl$22();
2977
+ _el$2.$$click = (e) => {
2978
+ e.stopPropagation();
2979
+ const pos = position();
2980
+ if (pos && !pos.isHidden) {
2981
+ props.onLineClick?.(line, pos.value);
2982
+ }
2983
+ };
2984
+ className(_el$2, `${PREFIX}label`);
2985
+ insert(_el$2, () => Math.round(position().value * 100) / 100);
2986
+ createRenderEffect((_$p) => setStyleProperty(_el$2, "transform", `translate3d(${position().x}px, ${position().y}px, 0) translate(-50%, -50%)`));
2987
+ return _el$2;
2988
+ }
2989
+ });
2990
+ }
2991
+ }));
2992
+ return _el$;
2993
+ })();
2994
+ }
2995
+ delegateEvents(["click"]);
2996
+ var _tmpl$5 = /* @__PURE__ */ template(`<svg viewBox="0 0 24 24"><line x1=12 y1=5 x2=12 y2=19></line><line x1=5 y1=12 x2=19 y2=12>`);
2997
+ var _tmpl$23 = /* @__PURE__ */ template(`<svg viewBox="0 0 24 24"><line x1=5 y1=12 x2=19 y2=12>`);
2998
+ var _tmpl$32 = /* @__PURE__ */ template(`<svg viewBox="0 0 24 24"><line x1=18 y1=6 x2=6 y2=18></line><line x1=6 y1=6 x2=18 y2=18>`);
2999
+ var _tmpl$42 = /* @__PURE__ */ template(`<svg viewBox="0 0 24 24"><line x1=19 y1=5 x2=5 y2=19>`);
3000
+ var iconStyle = {
3001
+ width: "12px",
3002
+ height: "12px",
3003
+ "stroke-width": "2.5",
3004
+ stroke: "currentColor",
3005
+ fill: "none",
3006
+ "stroke-linecap": "round",
3007
+ "stroke-linejoin": "round",
3008
+ display: "block"
3009
+ };
3010
+ var Icons = {
3011
+ "+": () => (() => {
3012
+ var _el$ = _tmpl$5();
3013
+ createRenderEffect((_$p) => style(_el$, iconStyle, _$p));
3014
+ return _el$;
3015
+ })(),
3016
+ "-": () => (() => {
3017
+ var _el$2 = _tmpl$23();
3018
+ createRenderEffect((_$p) => style(_el$2, iconStyle, _$p));
3019
+ return _el$2;
3020
+ })(),
3021
+ "*": () => (() => {
3022
+ var _el$3 = _tmpl$32();
3023
+ createRenderEffect((_$p) => style(_el$3, iconStyle, _$p));
3024
+ return _el$3;
3025
+ })(),
3026
+ "/": () => (() => {
3027
+ var _el$4 = _tmpl$42();
3028
+ createRenderEffect((_$p) => style(_el$4, iconStyle, _$p));
3029
+ return _el$4;
3030
+ })()
3031
+ };
3032
+ var _tmpl$6 = /* @__PURE__ */ template(`<span>`);
3033
+ var _tmpl$24 = /* @__PURE__ */ template(`<span>= `);
3034
+ var _tmpl$33 = /* @__PURE__ */ template(`<div data-caliper-ignore style=top:0;left:0><span>`);
3035
+ function Calculator(props) {
3036
+ const formatValue = (value) => {
3037
+ return Math.round(value * 100) / 100 + "";
3038
+ };
3039
+ return createComponent(Show, {
3040
+ get when() {
3041
+ return props.state.isActive;
3042
+ },
3043
+ get children() {
3044
+ var _el$ = _tmpl$33(), _el$2 = _el$.firstChild;
3045
+ insert(_el$2, () => formatValue(props.state.baseValue));
3046
+ insert(_el$, createComponent(Show, {
3047
+ keyed: true,
3048
+ get when() {
3049
+ return props.state.operation;
3050
+ },
3051
+ children: (operation) => {
3052
+ const Icon = Icons[operation];
3053
+ return (() => {
3054
+ var _el$6 = _tmpl$6();
3055
+ className(_el$6, `${PREFIX}calculator-operation`);
3056
+ insert(_el$6, createComponent(Show, {
3057
+ when: Icon,
3058
+ fallback: operation,
3059
+ get children() {
3060
+ return createComponent(Icon, {});
3061
+ }
3062
+ }));
3063
+ return _el$6;
3064
+ })();
3065
+ }
3066
+ }), null);
3067
+ insert(_el$, createComponent(Show, {
3068
+ get when() {
3069
+ return props.state.inputValue || props.state.operation;
3070
+ },
3071
+ get children() {
3072
+ var _el$3 = _tmpl$6();
3073
+ className(_el$3, `${PREFIX}calculator-input`);
3074
+ insert(_el$3, () => props.state.inputValue || "0");
3075
+ return _el$3;
3076
+ }
3077
+ }), null);
3078
+ insert(_el$, createComponent(Show, {
3079
+ get when() {
3080
+ return props.state.result !== null;
3081
+ },
3082
+ get children() {
3083
+ var _el$4 = _tmpl$24(); _el$4.firstChild;
3084
+ className(_el$4, `${PREFIX}calculator-result`);
3085
+ insert(_el$4, (() => {
3086
+ var _c$ = memo(() => props.state.result !== null);
3087
+ return () => _c$() ? formatValue(props.state.result) : "";
3088
+ })(), null);
3089
+ return _el$4;
3090
+ }
3091
+ }), null);
3092
+ createRenderEffect((_p$) => {
3093
+ var _v$ = `${PREFIX}calculator ${props.isFocused ? `${PREFIX}calculator-focused` : ""}`, _v$2 = `translate3d(${props.position.x + 10}px, ${props.position.y + 10}px, 0)`, _v$3 = `${PREFIX}calculator-base ${props.state.operation ? `${PREFIX}calculator-base-active` : ""}`;
3094
+ _v$ !== _p$.e && className(_el$, _p$.e = _v$);
3095
+ _v$2 !== _p$.t && setStyleProperty(_el$, "transform", _p$.t = _v$2);
3096
+ _v$3 !== _p$.a && className(_el$2, _p$.a = _v$3);
3097
+ return _p$;
3098
+ }, {
3099
+ e: void 0,
3100
+ t: void 0,
3101
+ a: void 0
3102
+ });
3103
+ return _el$;
3104
+ }
3105
+ });
3106
+ }
3107
+ var _tmpl$7 = /* @__PURE__ */ template(`<div style=left:0;top:0>`);
3108
+ function BoundaryBoxes(props) {
3109
+ const [anchor, setAnchor] = createSignal(null);
3110
+ const [target, setTarget] = createSignal(null);
3111
+ let lastElement = null;
3112
+ let rafId = null;
3113
+ const isRectSame = (a, b, threshold = 0.1) => {
3114
+ if (!a || !b) return false;
3115
+ return Math.abs(a.left - b.left) < threshold && Math.abs(a.top - b.top) < threshold && Math.abs(a.width - b.width) < threshold && Math.abs(a.height - b.height) < threshold;
3116
+ };
3117
+ const lerpTo = (current, targetGeo, lerpFactor) => {
3118
+ if (!targetGeo) return null;
3119
+ if (!current) return {
3120
+ ...targetGeo
3121
+ };
3122
+ const next = lerpRect(current, targetGeo, lerpFactor);
3123
+ if (isRectSame(next, targetGeo, 0.1)) {
3124
+ return {
3125
+ ...targetGeo
3126
+ };
3127
+ }
3128
+ return {
3129
+ ...targetGeo,
3130
+ left: next.left,
3131
+ top: next.top,
3132
+ width: next.width,
3133
+ height: next.height
3134
+ };
3135
+ };
3136
+ const liveSelectionTarget = createMemo(() => {
3137
+ props.viewport.version;
3138
+ return getLiveGeometry(props.metadata.rect, props.metadata.scrollHierarchy, props.metadata.position, props.metadata.stickyConfig, props.metadata.initialWindowX, props.metadata.initialWindowY);
3139
+ });
3140
+ const liveSecondaryTarget = createMemo(() => {
3141
+ props.viewport.version;
3142
+ const res = props.result;
3143
+ if (!(props.isAltPressed || props.isFrozen) || !res) return null;
3144
+ return getLiveGeometry(res.secondary, res.secondaryHierarchy, res.secondaryPosition, res.secondarySticky, res.secondaryWinX, res.secondaryWinY);
3145
+ });
3146
+ createEffect(on([liveSelectionTarget, liveSecondaryTarget, () => props.animation.lerpFactor, () => props.metadata.element], ([selection, secondary, factor, element]) => {
3147
+ if (!selection) {
3148
+ setAnchor(null);
3149
+ setTarget(null);
3150
+ lastElement = null;
3151
+ if (rafId) {
3152
+ cancelAnimationFrame(rafId);
3153
+ rafId = null;
3154
+ }
3155
+ return;
3156
+ }
3157
+ const isNewElement = lastElement !== element;
3158
+ const useLerp = props.animation.enabled !== false;
3159
+ setTarget(secondary);
3160
+ if (isNewElement) {
3161
+ lastElement = element;
3162
+ if (useLerp) {
3163
+ const animate = () => {
3164
+ const currentAnchor = anchor();
3165
+ const nextAnchor = lerpTo(currentAnchor, selection, factor);
3166
+ setAnchor(nextAnchor);
3167
+ if (selection && !isRectSame(nextAnchor, selection, 0.05)) {
3168
+ rafId = requestAnimationFrame(animate);
3169
+ } else {
3170
+ rafId = null;
3171
+ }
3172
+ };
3173
+ if (rafId) cancelAnimationFrame(rafId);
3174
+ rafId = requestAnimationFrame(animate);
3175
+ } else {
3176
+ if (rafId) {
3177
+ cancelAnimationFrame(rafId);
3178
+ rafId = null;
3179
+ }
3180
+ setAnchor(selection);
3181
+ }
3182
+ } else {
3183
+ if (!rafId) {
3184
+ setAnchor(selection);
3185
+ }
3186
+ }
3187
+ }));
3188
+ onCleanup(() => {
3189
+ if (rafId) cancelAnimationFrame(rafId);
3190
+ });
3191
+ return [createComponent(Show, {
3192
+ get when() {
3193
+ return anchor();
3194
+ },
3195
+ children: (current) => createComponent(Portal, {
3196
+ get mount() {
3197
+ return document.body;
3198
+ },
3199
+ get children() {
3200
+ var _el$ = _tmpl$7();
3201
+ className(_el$, `${PREFIX}boundary-box ${PREFIX}boundary-box-selected`);
3202
+ createRenderEffect((_p$) => {
3203
+ var _v$ = `${current().width}px`, _v$2 = `${current().height}px`, _v$3 = `translate3d(${current().left - props.viewport.scrollX}px, ${current().top - props.viewport.scrollY}px, 0)`, _v$4 = current().clipPath;
3204
+ _v$ !== _p$.e && setStyleProperty(_el$, "width", _p$.e = _v$);
3205
+ _v$2 !== _p$.t && setStyleProperty(_el$, "height", _p$.t = _v$2);
3206
+ _v$3 !== _p$.a && setStyleProperty(_el$, "transform", _p$.a = _v$3);
3207
+ _v$4 !== _p$.o && setStyleProperty(_el$, "clip-path", _p$.o = _v$4);
3208
+ return _p$;
3209
+ }, {
3210
+ e: void 0,
3211
+ t: void 0,
3212
+ a: void 0,
3213
+ o: void 0
3214
+ });
3215
+ return _el$;
3216
+ }
3217
+ })
3218
+ }), createComponent(Show, {
3219
+ get when() {
3220
+ return target();
3221
+ },
3222
+ children: (current) => createComponent(Portal, {
3223
+ get mount() {
3224
+ return document.body;
3225
+ },
3226
+ get children() {
3227
+ var _el$2 = _tmpl$7();
3228
+ className(_el$2, `${PREFIX}boundary-box ${PREFIX}boundary-box-secondary`);
3229
+ createRenderEffect((_p$) => {
3230
+ var _v$5 = `${current().width}px`, _v$6 = `${current().height}px`, _v$7 = `translate3d(${current().left - props.viewport.scrollX}px, ${current().top - props.viewport.scrollY}px, 0)`, _v$8 = current().clipPath;
3231
+ _v$5 !== _p$.e && setStyleProperty(_el$2, "width", _p$.e = _v$5);
3232
+ _v$6 !== _p$.t && setStyleProperty(_el$2, "height", _p$.t = _v$6);
3233
+ _v$7 !== _p$.a && setStyleProperty(_el$2, "transform", _p$.a = _v$7);
3234
+ _v$8 !== _p$.o && setStyleProperty(_el$2, "clip-path", _p$.o = _v$8);
3235
+ return _p$;
3236
+ }, {
3237
+ e: void 0,
3238
+ t: void 0,
3239
+ a: void 0,
3240
+ o: void 0
3241
+ });
3242
+ return _el$2;
3243
+ }
3244
+ })
3245
+ })];
3246
+ }
3247
+ var _tmpl$8 = /* @__PURE__ */ template(`<div style=left:0;top:0> \xD7 `);
3248
+ function SelectionLabel(props) {
3249
+ const margin = 16;
3250
+ const liveGeo = createMemo(() => {
3251
+ props.viewport.version;
3252
+ return getLiveGeometry(props.metadata.rect, props.metadata.scrollHierarchy, props.metadata.position, props.metadata.stickyConfig, props.metadata.initialWindowX, props.metadata.initialWindowY);
3253
+ });
3254
+ const labelData = createMemo(() => {
3255
+ const geo = liveGeo();
3256
+ if (!geo || geo.isHidden) return null;
3257
+ const vLeft = props.viewport.scrollX;
3258
+ const vRight = props.viewport.scrollX + props.viewport.width;
3259
+ const vBottom = props.viewport.scrollY + props.viewport.height;
3260
+ const cLeft = geo.visibleMinX;
3261
+ const cRight = geo.visibleMaxX;
3262
+ const cBottom = geo.visibleMaxY;
3263
+ const effectiveMinX = Math.max(vLeft, cLeft);
3264
+ const effectiveMaxX = Math.min(vRight, cRight);
3265
+ const effectiveMaxY = Math.min(vBottom, cBottom);
3266
+ const visibleLeft = Math.max(geo.left, effectiveMinX + margin);
3267
+ const visibleRight = Math.min(geo.left + geo.width, effectiveMaxX - margin);
3268
+ let snapX = (visibleLeft + visibleRight) / 2;
3269
+ let snapY = geo.top + geo.height + 8;
3270
+ if (snapY > effectiveMaxY - margin - 24) {
3271
+ if (geo.top < effectiveMaxY - margin) {
3272
+ snapY = effectiveMaxY - margin - 24;
3273
+ }
3274
+ }
3275
+ snapY = Math.max(snapY, geo.top + margin);
3276
+ return {
3277
+ width: Math.round(geo.width),
3278
+ height: Math.round(geo.height),
3279
+ x: snapX,
3280
+ y: snapY
3281
+ };
3282
+ });
3283
+ return createComponent(Show, {
3284
+ get when() {
3285
+ return labelData();
3286
+ },
3287
+ children: (data) => createComponent(Portal, {
3288
+ get mount() {
3289
+ return document.body;
3290
+ },
3291
+ get children() {
3292
+ var _el$ = _tmpl$8(), _el$2 = _el$.firstChild;
3293
+ className(_el$, `${PREFIX}selection-label`);
3294
+ insert(_el$, () => data().width, _el$2);
3295
+ insert(_el$, () => data().height, null);
3296
+ createRenderEffect((_p$) => {
3297
+ var _v$ = `translate3d(${data().x - props.viewport.scrollX}px, ${data().y - props.viewport.scrollY}px, 0) translate(-50%, 0)`, _v$2 = props.isAltPressed ? 0 : 1;
3298
+ _v$ !== _p$.e && setStyleProperty(_el$, "transform", _p$.e = _v$);
3299
+ _v$2 !== _p$.t && setStyleProperty(_el$, "opacity", _p$.t = _v$2);
3300
+ return _p$;
3301
+ }, {
3302
+ e: void 0,
3303
+ t: void 0
3304
+ });
3305
+ return _el$;
3306
+ }
3307
+ })
3308
+ });
3309
+ }
3310
+ var _tmpl$9 = /* @__PURE__ */ template(`<svg style=z-index:1000000><line data-caliper-ignore stroke=transparent stroke-width=15></line><line>`);
3311
+ var _tmpl$25 = /* @__PURE__ */ template(`<div data-caliper-ignore style=top:0;left:0>`);
3312
+ var _tmpl$34 = /* @__PURE__ */ template(`<div data-caliper-ignore><span></span><span>`);
3313
+ function ProjectionOverlay(props) {
3314
+ return createComponent(Show, {
3315
+ get when() {
3316
+ return memo(() => !!props.metadata().element)() && props.projectionState().direction;
3317
+ },
3318
+ get children() {
3319
+ return [createComponent(ProjectionLines, {
3320
+ get projectionState() {
3321
+ return props.projectionState;
3322
+ },
3323
+ get metadata() {
3324
+ return props.metadata;
3325
+ },
3326
+ get viewport() {
3327
+ return props.viewport;
3328
+ },
3329
+ get onLineClick() {
3330
+ return props.onLineClick;
3331
+ }
3332
+ }), createComponent(ProjectionInput, {
3333
+ get projectionState() {
3334
+ return props.projectionState;
3335
+ },
3336
+ get metadata() {
3337
+ return props.metadata;
3338
+ },
3339
+ get viewport() {
3340
+ return props.viewport;
3341
+ },
3342
+ get isFocused() {
3343
+ return props.isFocused;
3344
+ }
3345
+ })];
3346
+ }
3347
+ });
3348
+ }
3349
+ function ProjectionLines(props) {
3350
+ const lineData = createMemo(() => {
3351
+ const vp = props.viewport();
3352
+ vp.version;
3353
+ const state = props.projectionState();
3354
+ const value = parseFloat(state.value) || 0;
3355
+ const metadata = props.metadata();
3356
+ const live = getLiveGeometry(metadata.rect, metadata.scrollHierarchy, metadata.position, metadata.stickyConfig, metadata.initialWindowX, metadata.initialWindowY);
3357
+ if (!live) return null;
3358
+ let x1 = 0, y1 = 0, x2 = 0, y2 = 0;
3359
+ let labelX = 0, labelY = 0;
3360
+ let visibleY1 = 0, visibleY2 = 0, visibleX1 = 0, visibleX2 = 0;
3361
+ const docWidth = document.documentElement.scrollWidth;
3362
+ const docHeight = document.documentElement.scrollHeight;
3363
+ const liveX = live.left - vp.scrollX;
3364
+ const liveY = live.top - vp.scrollY;
3365
+ let isOffScreen = false;
3366
+ switch (state.direction) {
3367
+ case "top":
3368
+ x1 = x2 = liveX + live.width / 2;
3369
+ y1 = liveY;
3370
+ y2 = Math.max(-vp.scrollY, y1 - value);
3371
+ labelX = x1;
3372
+ visibleY1 = Math.max(0, Math.min(vp.height, y1));
3373
+ visibleY2 = Math.max(0, Math.min(vp.height, y2));
3374
+ if (Math.abs(visibleY1 - visibleY2) < 1) isOffScreen = true;
3375
+ labelY = (Math.min(visibleY1, visibleY2) + Math.max(visibleY1, visibleY2)) / 2;
3376
+ break;
3377
+ case "bottom":
3378
+ x1 = x2 = liveX + live.width / 2;
3379
+ y1 = liveY + live.height;
3380
+ y2 = Math.min(docHeight - vp.scrollY, y1 + value);
3381
+ labelX = x1;
3382
+ visibleY1 = Math.max(0, Math.min(vp.height, y1));
3383
+ visibleY2 = Math.max(0, Math.min(vp.height, y2));
3384
+ if (Math.abs(visibleY1 - visibleY2) < 1) isOffScreen = true;
3385
+ labelY = (Math.min(visibleY1, visibleY2) + Math.max(visibleY1, visibleY2)) / 2;
3386
+ break;
3387
+ case "left":
3388
+ y1 = y2 = liveY + live.height / 2;
3389
+ x1 = liveX;
3390
+ x2 = Math.max(-vp.scrollX, x1 - value);
3391
+ visibleX1 = Math.max(0, Math.min(vp.width, x1));
3392
+ visibleX2 = Math.max(0, Math.min(vp.width, x2));
3393
+ if (Math.abs(visibleX1 - visibleX2) < 1) isOffScreen = true;
3394
+ labelX = (Math.min(visibleX1, visibleX2) + Math.max(visibleX1, visibleX2)) / 2;
3395
+ labelY = y1;
3396
+ break;
3397
+ case "right":
3398
+ y1 = y2 = liveY + live.height / 2;
3399
+ x1 = liveX + live.width;
3400
+ x2 = Math.min(docWidth - vp.scrollX, x1 + value);
3401
+ visibleX1 = Math.max(0, Math.min(vp.width, x1));
3402
+ visibleX2 = Math.max(0, Math.min(vp.width, x2));
3403
+ if (Math.abs(visibleX1 - visibleX2) < 1) isOffScreen = true;
3404
+ labelX = (Math.min(visibleX1, visibleX2) + Math.max(visibleX1, visibleX2)) / 2;
3405
+ labelY = y1;
3406
+ break;
3407
+ }
3408
+ const rawValue = Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2);
3409
+ const actualValue = Number.isInteger(rawValue) ? rawValue : Math.round(rawValue * 100) / 100;
3410
+ const displayValue = state.value || String(actualValue);
3411
+ const labelWidthGuess = displayValue.length * 8 + 12;
3412
+ const labelHeightGuess = 20;
3413
+ const isHorizontal = state.direction === "left" || state.direction === "right";
3414
+ const visibleLineLength = isHorizontal ? Math.abs(visibleX1 - visibleX2) : Math.abs(visibleY1 - visibleY2);
3415
+ const labelSize = isHorizontal ? labelWidthGuess : labelHeightGuess;
3416
+ const showLabel = visibleLineLength >= labelSize * 1.5;
3417
+ return {
3418
+ x1,
3419
+ y1,
3420
+ x2,
3421
+ y2,
3422
+ labelX,
3423
+ labelY,
3424
+ actualValue,
3425
+ isHidden: live.isHidden || isOffScreen,
3426
+ showLabel
3427
+ };
3428
+ });
3429
+ const [isHovered, setIsHovered] = createSignal(false);
3430
+ const handleLineClick = (e) => {
3431
+ e.stopPropagation();
3432
+ const data = lineData();
3433
+ if (data) {
3434
+ props.onLineClick?.({
3435
+ type: "distance",
3436
+ value: data.actualValue,
3437
+ start: {
3438
+ x: data.x1,
3439
+ y: data.y1
3440
+ },
3441
+ end: {
3442
+ x: data.x2,
3443
+ y: data.y2
3444
+ }
3445
+ }, data.actualValue);
3446
+ }
3447
+ };
3448
+ return createComponent(Show, {
3449
+ get when() {
3450
+ return memo(() => !!lineData())() && !lineData()?.isHidden;
3451
+ },
3452
+ get children() {
3453
+ return [(() => {
3454
+ var _el$ = _tmpl$9(), _el$2 = _el$.firstChild, _el$3 = _el$2.nextSibling;
3455
+ setAttribute(_el$, "class", `${PREFIX}viewport-fixed`);
3456
+ _el$2.addEventListener("mouseleave", () => setIsHovered(false));
3457
+ _el$2.addEventListener("mouseenter", () => setIsHovered(true));
3458
+ _el$2.$$click = handleLineClick;
3459
+ setAttribute(_el$2, "class", `${PREFIX}line-hit-target`);
3460
+ setAttribute(_el$3, "class", `${PREFIX}projection-line`);
3461
+ createRenderEffect((_p$) => {
3462
+ var _v$ = lineData().x1, _v$2 = lineData().y1, _v$3 = lineData().x2, _v$4 = lineData().y2, _v$5 = lineData().x1, _v$6 = lineData().y1, _v$7 = lineData().x2, _v$8 = lineData().y2, _v$9 = isHovered() ? 2 : 1;
3463
+ _v$ !== _p$.e && setAttribute(_el$2, "x1", _p$.e = _v$);
3464
+ _v$2 !== _p$.t && setAttribute(_el$2, "y1", _p$.t = _v$2);
3465
+ _v$3 !== _p$.a && setAttribute(_el$2, "x2", _p$.a = _v$3);
3466
+ _v$4 !== _p$.o && setAttribute(_el$2, "y2", _p$.o = _v$4);
3467
+ _v$5 !== _p$.i && setAttribute(_el$3, "x1", _p$.i = _v$5);
3468
+ _v$6 !== _p$.n && setAttribute(_el$3, "y1", _p$.n = _v$6);
3469
+ _v$7 !== _p$.s && setAttribute(_el$3, "x2", _p$.s = _v$7);
3470
+ _v$8 !== _p$.h && setAttribute(_el$3, "y2", _p$.h = _v$8);
3471
+ _v$9 !== _p$.r && setAttribute(_el$3, "stroke-width", _p$.r = _v$9);
3472
+ return _p$;
3473
+ }, {
3474
+ e: void 0,
3475
+ t: void 0,
3476
+ a: void 0,
3477
+ o: void 0,
3478
+ i: void 0,
3479
+ n: void 0,
3480
+ s: void 0,
3481
+ h: void 0,
3482
+ r: void 0
3483
+ });
3484
+ return _el$;
3485
+ })(), createComponent(Show, {
3486
+ get when() {
3487
+ return lineData().showLabel;
3488
+ },
3489
+ get children() {
3490
+ var _el$4 = _tmpl$25();
3491
+ _el$4.$$click = handleLineClick;
3492
+ className(_el$4, `${PREFIX}label ${PREFIX}projection-label`);
3493
+ insert(_el$4, () => lineData().actualValue);
3494
+ createRenderEffect((_$p) => setStyleProperty(_el$4, "transform", `translate3d(${lineData().labelX}px, ${lineData().labelY}px, 0) translate(-50%, -50%)`));
3495
+ return _el$4;
3496
+ }
3497
+ })];
3498
+ }
3499
+ });
3500
+ }
3501
+ function ProjectionInput(props) {
3502
+ const style2 = createMemo(() => {
3503
+ const vp = props.viewport();
3504
+ vp.version;
3505
+ const metadata = props.metadata();
3506
+ const live = getLiveGeometry(metadata.rect, metadata.scrollHierarchy, metadata.position, metadata.stickyConfig, metadata.initialWindowX, metadata.initialWindowY);
3507
+ if (!live || live.isHidden) return {
3508
+ display: "none"
3509
+ };
3510
+ const windowTop = live.top - vp.scrollY;
3511
+ const windowLeft = live.left - vp.scrollX;
3512
+ const inputHeight = 35;
3513
+ const margin = 10;
3514
+ const shouldFlip = windowTop < inputHeight + margin;
3515
+ const y = shouldFlip ? windowTop + live.height + margin : windowTop - inputHeight;
3516
+ return {
3517
+ top: "0",
3518
+ left: "0",
3519
+ transform: `translate3d(${windowLeft}px, ${y}px, 0)`
3520
+ };
3521
+ });
3522
+ return (() => {
3523
+ var _el$5 = _tmpl$34(), _el$6 = _el$5.firstChild, _el$7 = _el$6.nextSibling;
3524
+ className(_el$6, `${PREFIX}projection-direction-tag`);
3525
+ insert(_el$6, () => props.projectionState().direction);
3526
+ className(_el$7, `${PREFIX}projection-current-value`);
3527
+ insert(_el$7, () => props.projectionState().value || "0");
3528
+ createRenderEffect((_p$) => {
3529
+ var _v$0 = `${PREFIX}projection-input ${props.isFocused ? `${PREFIX}projection-input-focused` : ""}`, _v$1 = style2();
3530
+ _v$0 !== _p$.e && className(_el$5, _p$.e = _v$0);
3531
+ _p$.t = style(_el$5, _v$1, _p$.t);
3532
+ return _p$;
3533
+ }, {
3534
+ e: void 0,
3535
+ t: void 0
3536
+ });
3537
+ return _el$5;
3538
+ })();
3539
+ }
3540
+ delegateEvents(["click"]);
3541
+ var _tmpl$10 = /* @__PURE__ */ template(`<div data-caliper-ignore><svg style=z-index:999999>`);
3542
+ var _tmpl$26 = /* @__PURE__ */ template(`<svg><g data-caliper-ignore style=cursor:pointer;pointer-events:auto><line stroke=transparent stroke-width=15></line><line stroke=var(--caliper-secondary) stroke-width=1 stroke-dasharray="4 2"></line><circle r=2.5 fill=var(--caliper-secondary)></circle><circle r=2.5 fill=var(--caliper-secondary)></svg>`, false, true, false);
3543
+ var _tmpl$35 = /* @__PURE__ */ template(`<div data-caliper-ignore style=left:0;top:0>`);
3544
+ var _tmpl$43 = /* @__PURE__ */ template(`<div data-caliper-ignore style=position:fixed;left:0;top:0;pointer-events:auto;z-index:1000001>`);
3545
+ var _tmpl$52 = /* @__PURE__ */ template(`<div data-caliper-ignore>`);
3546
+ function RulerOverlay(props) {
3547
+ const [draggingId, setDraggingId] = createSignal(null);
3548
+ const [hoveredId, setHoveredId] = createSignal(null);
3549
+ const [selectedIds, setSelectedIds] = createSignal(/* @__PURE__ */ new Set());
3550
+ createEffect(() => {
3551
+ const lines = props.state().lines;
3552
+ const currentIds = selectedIds();
3553
+ const validIds = /* @__PURE__ */ new Set();
3554
+ currentIds.forEach((id) => {
3555
+ if (lines.find((l) => l.id === id)) {
3556
+ validIds.add(id);
3557
+ }
3558
+ });
3559
+ if (validIds.size !== currentIds.size) {
3560
+ setSelectedIds(validIds);
3561
+ }
3562
+ });
3563
+ const getSnapPoints = (isV) => {
3564
+ const points = [];
3565
+ const state = props.projectionState?.();
3566
+ const meta = props.metadata?.();
3567
+ const res = props.result?.();
3568
+ const vp = props.viewport();
3569
+ if (meta && meta.element) {
3570
+ const live = getLiveGeometry(meta.rect, meta.scrollHierarchy, meta.position, meta.stickyConfig, meta.initialWindowX, meta.initialWindowY);
3571
+ if (live) {
3572
+ const liveX = live.left - vp.scrollX;
3573
+ const liveY = live.top - vp.scrollY;
3574
+ if (isV) {
3575
+ points.push(liveX, liveX + live.width, liveX + live.width / 2);
3576
+ } else {
3577
+ points.push(liveY, liveY + live.height, liveY + live.height / 2);
3578
+ }
3579
+ if (state && state.direction && state.element === meta.element) {
3580
+ const value = parseFloat(state.value) || 0;
3581
+ if (isV) {
3582
+ if (state.direction === "left") points.push(liveX - value);
3583
+ else if (state.direction === "right") points.push(liveX + live.width + value);
3584
+ } else {
3585
+ if (state.direction === "top") points.push(liveY - value);
3586
+ else if (state.direction === "bottom") points.push(liveY + live.height + value);
3587
+ }
3588
+ }
3589
+ }
3590
+ }
3591
+ if (res && res.secondary) {
3592
+ const live = getLiveGeometry(res.secondary, res.secondaryHierarchy, res.secondaryPosition, res.secondarySticky, res.secondaryWinX, res.secondaryWinY);
3593
+ if (live) {
3594
+ const liveX = live.left - vp.scrollX;
3595
+ const liveY = live.top - vp.scrollY;
3596
+ if (isV) {
3597
+ points.push(liveX, liveX + live.width, liveX + live.width / 2);
3598
+ } else {
3599
+ points.push(liveY, liveY + live.height, liveY + live.height / 2);
3600
+ }
3601
+ }
3602
+ }
3603
+ return points;
3604
+ };
3605
+ const applySnap = (pos, isV) => {
3606
+ const points = getSnapPoints(isV);
3607
+ for (const p of points) {
3608
+ if (Math.abs(pos - p) <= RULER_SNAP_THRESHOLD) {
3609
+ return p;
3610
+ }
3611
+ }
3612
+ return pos;
3613
+ };
3614
+ const handleKeyDown = (e) => {
3615
+ const activeIds = selectedIds();
3616
+ if (activeIds.size === 0) return;
3617
+ if (e.key === "Delete" || e.key === "Backspace") {
3618
+ const idsToRemove = Array.from(activeIds);
3619
+ idsToRemove.forEach((id) => props.onRemove(id));
3620
+ setSelectedIds(/* @__PURE__ */ new Set());
3621
+ return;
3622
+ }
3623
+ const lines = props.state().lines;
3624
+ const activeLines = lines.filter((l) => activeIds.has(l.id));
3625
+ if (activeLines.length === 0) return;
3626
+ let step = 1;
3627
+ if (e.shiftKey) step = 10;
3628
+ else if (e.altKey) step = 0.1;
3629
+ const firstLine = activeLines[0];
3630
+ if (!firstLine) return;
3631
+ const isV = firstLine.type === "vertical";
3632
+ let delta = 0;
3633
+ if (isV) {
3634
+ if (e.key === "ArrowLeft") delta = -step;
3635
+ if (e.key === "ArrowRight") delta = step;
3636
+ } else {
3637
+ if (e.key === "ArrowUp") delta = -step;
3638
+ if (e.key === "ArrowDown") delta = step;
3639
+ }
3640
+ if (delta !== 0) {
3641
+ e.preventDefault();
3642
+ const vp = props.viewport();
3643
+ activeLines.forEach((line) => {
3644
+ const isLineV = line.type === "vertical";
3645
+ const max = (isLineV ? vp.width : vp.height) - 1;
3646
+ let newPos = Math.max(0, Math.min(line.position + delta, max));
3647
+ newPos = applySnap(newPos, isLineV);
3648
+ props.onUpdate(line.id, newPos);
3649
+ });
3650
+ }
3651
+ };
3652
+ onMount(() => {
3653
+ const handleGlobalClick = (e) => {
3654
+ const target = e.target;
3655
+ if (!target.closest(`.${PREFIX}ruler-line-hit`) && !target.closest(`.${PREFIX}ruler-bridge-label`) && !target.closest(`.${PREFIX}line-hit-target`) && !target.closest(`[data-caliper-ignore]`)) {
3656
+ setSelectedIds(/* @__PURE__ */ new Set());
3657
+ }
3658
+ };
3659
+ window.addEventListener("pointerdown", handleGlobalClick, {
3660
+ capture: true
3661
+ });
3662
+ window.addEventListener("keydown", handleKeyDown, {
3663
+ capture: true
3664
+ });
3665
+ onCleanup(() => {
3666
+ window.removeEventListener("pointerdown", handleGlobalClick, {
3667
+ capture: true
3668
+ });
3669
+ window.removeEventListener("keydown", handleKeyDown, {
3670
+ capture: true
3671
+ });
3672
+ });
3673
+ });
3674
+ const handlePointerDown = (e) => {
3675
+ const target = e.target;
3676
+ const id = target.getAttribute("data-ruler-id");
3677
+ const type = target.getAttribute("data-ruler-type");
3678
+ if (!id || !type) return;
3679
+ e.preventDefault();
3680
+ e.stopPropagation();
3681
+ setDraggingId(id);
3682
+ target.setPointerCapture(e.pointerId);
3683
+ if (e.shiftKey) {
3684
+ setSelectedIds((prev) => {
3685
+ const next = new Set(prev);
3686
+ if (next.has(id)) next.delete(id);
3687
+ else next.add(id);
3688
+ return next;
3689
+ });
3690
+ } else {
3691
+ if (!selectedIds().has(id)) {
3692
+ setSelectedIds(/* @__PURE__ */ new Set([id]));
3693
+ }
3694
+ }
3695
+ const onPointerMove = (moveEvent) => {
3696
+ const vp = props.viewport();
3697
+ const isV = type === "vertical";
3698
+ let pos = isV ? moveEvent.clientX : moveEvent.clientY;
3699
+ const max = (isV ? vp.width : vp.height) - 1;
3700
+ pos = Math.max(0, Math.min(pos, max));
3701
+ pos = applySnap(pos, isV);
3702
+ props.onUpdate(id, pos);
3703
+ };
3704
+ const onPointerUp = (upEvent) => {
3705
+ setDraggingId(null);
3706
+ target.releasePointerCapture(upEvent.pointerId);
3707
+ window.removeEventListener("pointermove", onPointerMove);
3708
+ window.removeEventListener("pointerup", onPointerUp);
3709
+ };
3710
+ window.addEventListener("pointermove", onPointerMove);
3711
+ window.addEventListener("pointerup", onPointerUp);
3712
+ };
3713
+ const handleDoubleClick = (e) => {
3714
+ const target = e.target;
3715
+ const id = target.getAttribute("data-ruler-id");
3716
+ if (id) {
3717
+ props.onRemove(id);
3718
+ setSelectedIds((prev) => {
3719
+ const next = new Set(prev);
3720
+ next.delete(id);
3721
+ return next;
3722
+ });
3723
+ }
3724
+ };
3725
+ const handlePointerOver = (e) => {
3726
+ const target = e.target;
3727
+ const id = target.getAttribute("data-ruler-id");
3728
+ if (id) setHoveredId(id);
3729
+ };
3730
+ const handlePointerOut = (e) => {
3731
+ const target = e.target;
3732
+ if (target.hasAttribute("data-ruler-id")) setHoveredId(null);
3733
+ };
3734
+ const bridges = createMemo(() => {
3735
+ const ids = selectedIds();
3736
+ if (ids.size < 2) return [];
3737
+ const lines = props.state().lines.filter((l) => ids.has(l.id));
3738
+ const vLines = lines.filter((l) => l.type === "vertical").sort((a, b) => a.position - b.position);
3739
+ const hLines = lines.filter((l) => l.type === "horizontal").sort((a, b) => a.position - b.position);
3740
+ const result = [];
3741
+ const vp = props.viewport();
3742
+ for (let i = 0; i < vLines.length - 1; i++) {
3743
+ const l1 = vLines[i];
3744
+ const l2 = vLines[i + 1];
3745
+ const val = l2.position - l1.position;
3746
+ if (val > 0) {
3747
+ result.push({
3748
+ x1: l1.position,
3749
+ y1: vp.height / 2 + 100,
3750
+ // Move default bridge line off center for better visibility
3751
+ x2: l2.position,
3752
+ y2: vp.height / 2 + 100,
3753
+ value: val,
3754
+ type: "vertical",
3755
+ labelX: l1.position + val / 2,
3756
+ labelY: vp.height / 2 + 85
3757
+ });
3758
+ }
3759
+ }
3760
+ for (let i = 0; i < hLines.length - 1; i++) {
3761
+ const l1 = hLines[i];
3762
+ const l2 = hLines[i + 1];
3763
+ const val = l2.position - l1.position;
3764
+ if (val > 0) {
3765
+ result.push({
3766
+ x1: vp.width / 2 + 100,
3767
+ y1: l1.position,
3768
+ x2: vp.width / 2 + 100,
3769
+ y2: l2.position,
3770
+ value: val,
3771
+ type: "horizontal",
3772
+ labelX: vp.width / 2 + 115,
3773
+ labelY: l1.position + val / 2
3774
+ });
3775
+ }
3776
+ }
3777
+ return result;
3778
+ });
3779
+ const handleClick = (bridge, e) => {
3780
+ e.stopPropagation();
3781
+ props.onLineClick?.({
3782
+ type: "distance",
3783
+ value: bridge.value,
3784
+ start: {
3785
+ x: bridge.x1,
3786
+ y: bridge.y1
3787
+ },
3788
+ end: {
3789
+ x: bridge.x2,
3790
+ y: bridge.y2
3791
+ }
3792
+ }, bridge.value);
3793
+ };
3794
+ return (() => {
3795
+ var _el$ = _tmpl$10(), _el$2 = _el$.firstChild;
3796
+ _el$.$$pointerout = handlePointerOut;
3797
+ _el$.$$pointerover = handlePointerOver;
3798
+ _el$.$$dblclick = handleDoubleClick;
3799
+ _el$.$$pointerdown = handlePointerDown;
3800
+ className(_el$, `${PREFIX}ruler-layer`);
3801
+ setAttribute(_el$2, "class", `${PREFIX}viewport-fixed`);
3802
+ insert(_el$2, createComponent(For, {
3803
+ get each() {
3804
+ return bridges();
3805
+ },
3806
+ children: (bridge) => (() => {
3807
+ var _el$3 = _tmpl$26(), _el$4 = _el$3.firstChild, _el$5 = _el$4.nextSibling, _el$6 = _el$5.nextSibling, _el$7 = _el$6.nextSibling;
3808
+ _el$3.$$click = (e) => handleClick(bridge, e);
3809
+ setAttribute(_el$4, "class", `${PREFIX}line-hit-target`);
3810
+ createRenderEffect((_p$) => {
3811
+ var _v$ = bridge.x1, _v$2 = bridge.y1, _v$3 = bridge.x2, _v$4 = bridge.y2, _v$5 = bridge.x1, _v$6 = bridge.y1, _v$7 = bridge.x2, _v$8 = bridge.y2, _v$9 = bridge.x1, _v$0 = bridge.y1, _v$1 = bridge.x2, _v$10 = bridge.y2;
3812
+ _v$ !== _p$.e && setAttribute(_el$4, "x1", _p$.e = _v$);
3813
+ _v$2 !== _p$.t && setAttribute(_el$4, "y1", _p$.t = _v$2);
3814
+ _v$3 !== _p$.a && setAttribute(_el$4, "x2", _p$.a = _v$3);
3815
+ _v$4 !== _p$.o && setAttribute(_el$4, "y2", _p$.o = _v$4);
3816
+ _v$5 !== _p$.i && setAttribute(_el$5, "x1", _p$.i = _v$5);
3817
+ _v$6 !== _p$.n && setAttribute(_el$5, "y1", _p$.n = _v$6);
3818
+ _v$7 !== _p$.s && setAttribute(_el$5, "x2", _p$.s = _v$7);
3819
+ _v$8 !== _p$.h && setAttribute(_el$5, "y2", _p$.h = _v$8);
3820
+ _v$9 !== _p$.r && setAttribute(_el$6, "cx", _p$.r = _v$9);
3821
+ _v$0 !== _p$.d && setAttribute(_el$6, "cy", _p$.d = _v$0);
3822
+ _v$1 !== _p$.l && setAttribute(_el$7, "cx", _p$.l = _v$1);
3823
+ _v$10 !== _p$.u && setAttribute(_el$7, "cy", _p$.u = _v$10);
3824
+ return _p$;
3825
+ }, {
3826
+ e: void 0,
3827
+ t: void 0,
3828
+ a: void 0,
3829
+ o: void 0,
3830
+ i: void 0,
3831
+ n: void 0,
3832
+ s: void 0,
3833
+ h: void 0,
3834
+ r: void 0,
3835
+ d: void 0,
3836
+ l: void 0,
3837
+ u: void 0
3838
+ });
3839
+ return _el$3;
3840
+ })()
3841
+ }));
3842
+ insert(_el$, createComponent(For, {
3843
+ get each() {
3844
+ return bridges();
3845
+ },
3846
+ children: (bridge) => (() => {
3847
+ var _el$8 = _tmpl$35();
3848
+ _el$8.$$click = (e) => handleClick(bridge, e);
3849
+ className(_el$8, `${PREFIX}label ${PREFIX}ruler-bridge-label`);
3850
+ insert(_el$8, () => Math.round(bridge.value * 100) / 100);
3851
+ createRenderEffect((_$p) => setStyleProperty(_el$8, "transform", `translate3d(${bridge.labelX}px, ${bridge.labelY}px, 0) translate(-50%, -50%)`));
3852
+ return _el$8;
3853
+ })()
3854
+ }), null);
3855
+ insert(_el$, createComponent(For, {
3856
+ get each() {
3857
+ return props.state().lines;
3858
+ },
3859
+ children: (line) => createComponent(RulerLineItem, {
3860
+ line,
3861
+ get isDragging() {
3862
+ return draggingId() === line.id;
3863
+ },
3864
+ get isHovered() {
3865
+ return hoveredId() === line.id;
3866
+ },
3867
+ get isSelected() {
3868
+ return selectedIds().has(line.id);
3869
+ },
3870
+ get onLineClick() {
3871
+ return props.onLineClick;
3872
+ },
3873
+ get viewport() {
3874
+ return props.viewport;
3875
+ }
3876
+ })
3877
+ }), null);
3878
+ return _el$;
3879
+ })();
3880
+ }
3881
+ function RulerLineItem(props) {
3882
+ const lineStyle = createMemo(() => {
3883
+ const isV = props.line.type === "vertical";
3884
+ const pos = props.line.position;
3885
+ const isActive = props.isDragging || props.isHovered || props.isSelected;
3886
+ return {
3887
+ left: "0",
3888
+ top: "0",
3889
+ width: isV ? "1px" : "100%",
3890
+ height: isV ? "100%" : "1px",
3891
+ transform: `translate3d(${isV ? pos : 0}px, ${isV ? 0 : pos}px, 0) ${isActive ? isV ? "scaleX(1.5)" : "scaleY(1.5)" : "scale(1)"}`,
3892
+ opacity: props.isSelected ? "1" : props.isHovered ? "0.8" : "0.6",
3893
+ filter: props.isSelected ? "drop-shadow(0 0 1.5px var(--caliper-primary))" : "none",
3894
+ "transform-origin": "center"
3895
+ };
3896
+ });
3897
+ const hitSize = createMemo(() => `${RULER_HIT_SIZE}px`);
3898
+ const hitOffset = createMemo(() => (RULER_HIT_SIZE - 1) / 2);
3899
+ return [(() => {
3900
+ var _el$9 = _tmpl$43();
3901
+ className(_el$9, `${PREFIX}ruler-line-hit`);
3902
+ createRenderEffect((_p$) => {
3903
+ var _v$11 = props.line.id, _v$12 = props.line.type, _v$13 = props.line.type === "vertical" ? hitSize() : "100%", _v$14 = props.line.type === "vertical" ? "100%" : hitSize(), _v$15 = `translate3d(${props.line.type === "vertical" ? props.line.position - hitOffset() : 0}px, ${props.line.type === "vertical" ? 0 : props.line.position - hitOffset()}px, 0)`, _v$16 = props.line.type === "vertical" ? "col-resize" : "row-resize";
3904
+ _v$11 !== _p$.e && setAttribute(_el$9, "data-ruler-id", _p$.e = _v$11);
3905
+ _v$12 !== _p$.t && setAttribute(_el$9, "data-ruler-type", _p$.t = _v$12);
3906
+ _v$13 !== _p$.a && setStyleProperty(_el$9, "width", _p$.a = _v$13);
3907
+ _v$14 !== _p$.o && setStyleProperty(_el$9, "height", _p$.o = _v$14);
3908
+ _v$15 !== _p$.i && setStyleProperty(_el$9, "transform", _p$.i = _v$15);
3909
+ _v$16 !== _p$.n && setStyleProperty(_el$9, "cursor", _p$.n = _v$16);
3910
+ return _p$;
3911
+ }, {
3912
+ e: void 0,
3913
+ t: void 0,
3914
+ a: void 0,
3915
+ o: void 0,
3916
+ i: void 0,
3917
+ n: void 0
3918
+ });
3919
+ return _el$9;
3920
+ })(), (() => {
3921
+ var _el$0 = _tmpl$52();
3922
+ className(_el$0, `${PREFIX}ruler-line-visual`);
3923
+ createRenderEffect((_$p) => style(_el$0, {
3924
+ ...lineStyle()
3925
+ }, _$p));
3926
+ return _el$0;
3927
+ })(), createComponent(Show, {
3928
+ get when() {
3929
+ return props.isDragging || props.isHovered || props.isSelected;
3930
+ },
3931
+ get children() {
3932
+ var _el$1 = _tmpl$35();
3933
+ _el$1.$$click = (e) => {
3934
+ e.stopPropagation();
3935
+ const isV = props.line.type === "vertical";
3936
+ const vp = props.viewport();
3937
+ props.onLineClick?.({
3938
+ type: "distance",
3939
+ value: props.line.position,
3940
+ start: isV ? {
3941
+ x: props.line.position,
3942
+ y: 0
3943
+ } : {
3944
+ x: 0,
3945
+ y: props.line.position
3946
+ },
3947
+ end: isV ? {
3948
+ x: props.line.position,
3949
+ y: vp.height
3950
+ } : {
3951
+ x: vp.width,
3952
+ y: props.line.position
3953
+ }
3954
+ }, props.line.position);
3955
+ };
3956
+ className(_el$1, `${PREFIX}label ${PREFIX}ruler-label`);
3957
+ insert(_el$1, () => Math.round(props.line.position * 100) / 100);
3958
+ createRenderEffect((_p$) => {
3959
+ var _v$17 = `translate3d(${props.line.type === "vertical" ? props.line.position + 10 : 20}px, ${props.line.type === "vertical" ? 20 : props.line.position + 10}px, 0)`, _v$18 = props.isSelected && !props.isHovered && !props.isDragging ? "0.7" : "1";
3960
+ _v$17 !== _p$.e && setStyleProperty(_el$1, "transform", _p$.e = _v$17);
3961
+ _v$18 !== _p$.t && setStyleProperty(_el$1, "opacity", _p$.t = _v$18);
3962
+ return _p$;
3963
+ }, {
3964
+ e: void 0,
3965
+ t: void 0
3966
+ });
3967
+ return _el$1;
3968
+ }
3969
+ })];
3970
+ }
3971
+ delegateEvents(["pointerdown", "dblclick", "pointerover", "pointerout", "click"]);
3972
+ var _tmpl$11 = /* @__PURE__ */ template(`<div>`);
3973
+ function Overlay(props) {
3974
+ const resultData = createMemo(() => {
3975
+ const res = props.result();
3976
+ if (!res) return null;
3977
+ props.viewport().version;
3978
+ const primaryGeo = getLiveGeometry(res.primary, res.primaryHierarchy, res.primaryPosition, res.primarySticky, res.primaryWinX, res.primaryWinY);
3979
+ if (!primaryGeo) return null;
3980
+ return {
3981
+ primary: {
3982
+ geo: primaryGeo,
3983
+ delta: getTotalScrollDelta(res.primaryHierarchy, res.primaryPosition, res.primarySticky, res.primaryWinX, res.primaryWinY)
3984
+ },
3985
+ secondary: {
3986
+ geo: getLiveGeometry(res.secondary, res.secondaryHierarchy, res.secondaryPosition, res.secondarySticky, res.secondaryWinX, res.secondaryWinY),
3987
+ delta: getTotalScrollDelta(res.secondaryHierarchy, res.secondaryPosition, res.secondarySticky, res.secondaryWinX, res.secondaryWinY)
3988
+ },
3989
+ common: getCommonVisibilityWindow(res.primaryHierarchy, res.secondaryHierarchy, props.selectionMetadata().element, res.secondaryElement),
3990
+ isSameContext: !!(res.primaryPosition === res.secondaryPosition && res.primaryHierarchy.length === res.secondaryHierarchy.length && res.primaryHierarchy.every((p, i) => p.element === res.secondaryHierarchy[i]?.element) || res.primaryHierarchy.length > 0 && res.primaryHierarchy[0]?.element === res.secondaryElement || res.secondaryHierarchy.length > 0 && res.secondaryHierarchy[0]?.element === props.selectionMetadata().element)
3991
+ };
3992
+ });
3993
+ return [createComponent(BoundaryBoxes, {
3994
+ get metadata() {
3995
+ return props.selectionMetadata();
3996
+ },
3997
+ get result() {
3998
+ return props.result();
3999
+ },
4000
+ get isAltPressed() {
4001
+ return props.isAltPressed();
4002
+ },
4003
+ get isFrozen() {
4004
+ return props.isFrozen();
4005
+ },
4006
+ get animation() {
4007
+ return props.animation;
4008
+ },
4009
+ get viewport() {
4010
+ return props.viewport();
4011
+ }
4012
+ }), createComponent(SelectionLabel, {
4013
+ get metadata() {
4014
+ return props.selectionMetadata();
4015
+ },
4016
+ get isAltPressed() {
4017
+ return props.isAltPressed();
4018
+ },
4019
+ get viewport() {
4020
+ return props.viewport();
4021
+ }
4022
+ }), createComponent(Show, {
4023
+ get when() {
4024
+ return memo(() => !!(props.isAltPressed() || props.isFrozen()))() && resultData();
4025
+ },
4026
+ get children() {
4027
+ return createComponent(Portal, {
4028
+ get mount() {
4029
+ return document.body;
4030
+ },
4031
+ get children() {
4032
+ var _el$ = _tmpl$11();
4033
+ className(_el$, `${PREFIX}overlay`);
4034
+ insert(_el$, createComponent(MeasurementLinesWithCalculator, {
4035
+ get lines() {
4036
+ return props.result().lines;
4037
+ },
4038
+ get data() {
4039
+ return resultData();
4040
+ },
4041
+ get viewport() {
4042
+ return props.viewport();
4043
+ },
4044
+ get onLineClick() {
4045
+ return props.onLineClick;
4046
+ }
4047
+ }), null);
4048
+ insert(_el$, createComponent(MeasurementLabels, {
4049
+ get lines() {
4050
+ return props.result().lines;
4051
+ },
4052
+ get data() {
4053
+ return resultData();
4054
+ },
4055
+ get viewport() {
4056
+ return props.viewport();
4057
+ },
4058
+ get onLineClick() {
4059
+ return props.onLineClick;
4060
+ }
4061
+ }), null);
4062
+ return _el$;
4063
+ }
4064
+ });
4065
+ }
4066
+ }), createComponent(Show, {
4067
+ get when() {
4068
+ return memo(() => !!props.calculatorState)() && props.calculatorState() !== null;
4069
+ },
4070
+ get children() {
4071
+ return createComponent(Portal, {
4072
+ get mount() {
4073
+ return document.body;
4074
+ },
4075
+ get children() {
4076
+ return createComponent(Calculator, {
4077
+ get state() {
4078
+ return props.calculatorState();
4079
+ },
4080
+ get onClose() {
4081
+ return props.onCalculatorClose || (() => {
4082
+ });
4083
+ },
4084
+ get position() {
4085
+ return {
4086
+ x: props.cursor().x,
4087
+ y: props.cursor().y
4088
+ };
4089
+ },
4090
+ get isFocused() {
4091
+ return props.activeFocus?.() === "calculator";
4092
+ }
4093
+ });
4094
+ }
4095
+ });
4096
+ }
4097
+ }), createComponent(Show, {
4098
+ get when() {
4099
+ return memo(() => !!(props.projectionState && props.projectionState()?.direction !== null))() && props.projectionState()?.element === props.selectionMetadata().element;
4100
+ },
4101
+ get children() {
4102
+ return createComponent(Portal, {
4103
+ get mount() {
4104
+ return document.body;
4105
+ },
4106
+ get children() {
4107
+ return createComponent(ProjectionOverlay, {
4108
+ get projectionState() {
4109
+ return props.projectionState;
4110
+ },
4111
+ get metadata() {
4112
+ return props.selectionMetadata;
4113
+ },
4114
+ get viewport() {
4115
+ return props.viewport;
4116
+ },
4117
+ get isFocused() {
4118
+ return props.activeFocus?.() === "projection";
4119
+ },
4120
+ get onLineClick() {
4121
+ return props.onLineClick;
4122
+ }
4123
+ });
4124
+ }
4125
+ });
4126
+ }
4127
+ }), createComponent(Show, {
4128
+ get when() {
4129
+ return memo(() => !!props.rulerState)() && props.rulerState().lines.length > 0;
4130
+ },
4131
+ get children() {
4132
+ return createComponent(Portal, {
4133
+ get mount() {
4134
+ return document.body;
4135
+ },
4136
+ get children() {
4137
+ return createComponent(RulerOverlay, {
4138
+ get state() {
4139
+ return props.rulerState;
4140
+ },
4141
+ get viewport() {
4142
+ return props.viewport;
4143
+ },
4144
+ get projectionState() {
4145
+ return props.projectionState;
4146
+ },
4147
+ get metadata() {
4148
+ return props.selectionMetadata;
4149
+ },
4150
+ get result() {
4151
+ return props.result;
4152
+ },
4153
+ get onUpdate() {
4154
+ return props.onRulerUpdate || (() => {
4155
+ });
4156
+ },
4157
+ get onRemove() {
4158
+ return props.onRulerRemove || (() => {
4159
+ });
4160
+ },
4161
+ get onLineClick() {
4162
+ return props.onLineClick;
4163
+ }
4164
+ });
4165
+ }
4166
+ });
4167
+ }
4168
+ })];
4169
+ }
4170
+ function Root(config) {
4171
+ const {
4172
+ commands,
4173
+ animation
4174
+ } = config;
4175
+ const [result, setResult] = createSignal(null);
4176
+ const [cursor, setCursor] = createSignal({
4177
+ x: 0,
4178
+ y: 0
4179
+ });
4180
+ const [viewport, setViewport] = createSignal({
4181
+ scrollX: window.scrollX,
4182
+ scrollY: window.scrollY,
4183
+ width: document.documentElement.clientWidth,
4184
+ height: document.documentElement.clientHeight,
4185
+ version: 0
4186
+ });
4187
+ const [selectionMetadata, setSelectionMetadata] = createSignal({
4188
+ element: null,
4189
+ rect: null,
4190
+ scrollHierarchy: [],
4191
+ position: "static",
4192
+ initialWindowX: 0,
4193
+ initialWindowY: 0
4194
+ });
4195
+ const [calculatorState, setCalculatorState] = createSignal(null);
4196
+ const [projectionState, setProjectionState] = createSignal({
4197
+ direction: null,
4198
+ value: "",
4199
+ element: null
4200
+ });
4201
+ const [activeCalculatorLine, setActiveCalculatorLine] = createSignal(null);
4202
+ const [isSelectKeyDown, setIsSelectKeyDown] = createSignal(false);
4203
+ const [activeInputFocus, setActiveInputFocus] = createSignal("calculator");
4204
+ let system = null;
4205
+ let selectionSystem = null;
4206
+ let projectionSystem = null;
4207
+ let rulerSystem = null;
4208
+ const [rulerState, setRulerState] = createSignal({
4209
+ lines: []
4210
+ });
4211
+ const [isAltPressed, setIsAltPressed] = createSignal(false);
4212
+ const [isFrozen, setIsFrozen] = createSignal(false);
4213
+ let viewportRafId = null;
4214
+ let resizeObserver = null;
4215
+ let observedPrimary = null;
4216
+ let observedSecondary = null;
4217
+ const syncViewport = () => {
4218
+ setViewport((prev) => ({
4219
+ scrollX: window.scrollX,
4220
+ scrollY: window.scrollY,
4221
+ width: document.documentElement.clientWidth,
4222
+ height: document.documentElement.clientHeight,
4223
+ version: (prev.version || 0) + 1
4224
+ }));
4225
+ viewportRafId = null;
4226
+ };
4227
+ const scheduleUpdate = () => {
4228
+ if (!viewportRafId) {
4229
+ viewportRafId = requestAnimationFrame(syncViewport);
4230
+ }
4231
+ };
4232
+ onMount(() => {
4233
+ selectionSystem = createSelectionSystem();
4234
+ system = createMeasurementSystem();
4235
+ projectionSystem = createProjectionSystem();
4236
+ const unsubscribeProjection = projectionSystem.onUpdate((state) => {
4237
+ setProjectionState(state);
4238
+ if (state.direction === null) {
4239
+ if (calculatorState()?.isActive) {
4240
+ setActiveInputFocus("calculator");
4241
+ }
4242
+ if (system?.getState() === "FROZEN") {
4243
+ system?.unfreeze(false);
4244
+ }
4245
+ }
4246
+ });
4247
+ rulerSystem = createRulerSystem();
4248
+ const unsubscribeRuler = rulerSystem.onUpdate((state) => {
4249
+ setRulerState(state);
4250
+ });
4251
+ const unsubscribe = system.onStateChange(() => {
4252
+ if (!system) return;
4253
+ setResult(system.getCurrentResult());
4254
+ setIsFrozen(system.getState() === "FROZEN");
4255
+ });
4256
+ const currentResult = system.getCurrentResult();
4257
+ setResult(currentResult);
4258
+ const unsubscribeUpdate = selectionSystem.onUpdate((metadata) => {
4259
+ setSelectionMetadata(metadata);
4260
+ });
4261
+ let selectionTimeoutId = null;
4262
+ let lastPointerPos = {
4263
+ x: 0,
4264
+ y: 0
4265
+ };
4266
+ const performSelection = (x, y) => {
4267
+ const element = getTopElementAtPoint(x, y);
4268
+ if (element && selectionSystem) {
4269
+ setResult(null);
4270
+ setCalculatorState(null);
4271
+ setActiveInputFocus("calculator");
4272
+ if (projectionSystem) {
4273
+ projectionSystem.clear();
4274
+ }
4275
+ if (system) {
4276
+ system.abort();
4277
+ system.getCalculator().close();
4278
+ }
4279
+ lastHoveredElement = null;
4280
+ selectionDelegate.cancel();
4281
+ measureDelegate.cancel();
4282
+ selectionSystem.select(element);
4283
+ }
4284
+ };
4285
+ const isCommandActive = (e) => {
4286
+ const {
4287
+ ctrlKey,
4288
+ metaKey,
4289
+ altKey,
4290
+ shiftKey
4291
+ } = e;
4292
+ const key = commands.select;
4293
+ const modifiers = {
4294
+ Control: ctrlKey,
4295
+ Meta: metaKey,
4296
+ Alt: altKey,
4297
+ Shift: shiftKey
4298
+ };
4299
+ if (key in modifiers) {
4300
+ return Object.entries(modifiers).every(([name, value]) => name === key ? value === true : value === false);
4301
+ }
4302
+ return isSelectKeyDown() && !ctrlKey && !metaKey && !altKey && !shiftKey;
4303
+ };
4304
+ const handlePointerDown = (e) => {
4305
+ lastPointerPos = {
4306
+ x: e.clientX,
4307
+ y: e.clientY
4308
+ };
4309
+ if (isCommandActive(e)) {
4310
+ e.preventDefault();
4311
+ if (selectionTimeoutId) window.clearTimeout(selectionTimeoutId);
4312
+ selectionTimeoutId = window.setTimeout(() => {
4313
+ performSelection(lastPointerPos.x, lastPointerPos.y);
4314
+ selectionTimeoutId = null;
4315
+ }, commands.selectionHoldDuration);
4316
+ } else {
4317
+ if (selectionTimeoutId) window.clearTimeout(selectionTimeoutId);
4318
+ }
4319
+ };
4320
+ const handlePointerUp = (e) => {
4321
+ if (selectionTimeoutId) {
4322
+ window.clearTimeout(selectionTimeoutId);
4323
+ selectionTimeoutId = null;
4324
+ }
4325
+ const target = e.target;
4326
+ if (target.closest(`[data-caliper-ignore]`) || target.closest(`.${PREFIX}projection-input`)) {
4327
+ if (target.closest(`.${PREFIX}projection-input`)) {
4328
+ setActiveInputFocus("projection");
4329
+ } else if (target.closest(`.${PREFIX}calculator`)) {
4330
+ setActiveInputFocus("calculator");
4331
+ }
4332
+ }
4333
+ };
4334
+ const handleContextMenu = (e) => {
4335
+ if (isCommandActive(e)) {
4336
+ e.preventDefault();
4337
+ }
4338
+ };
4339
+ let lastMouseEvent = null;
4340
+ let mouseMoveRafId = null;
4341
+ let lastHoveredElement = null;
4342
+ const selectionDelegate = createSuppressionDelegate((el) => {
4343
+ lastHoveredElement = el;
4344
+ selectionSystem?.select(el);
4345
+ });
4346
+ const measureDelegate = createSuppressionDelegate((el, cursor2, hover) => {
4347
+ if (hover) {
4348
+ lastHoveredElement = hover;
4349
+ }
4350
+ system?.measure(el, cursor2);
4351
+ });
4352
+ const processMouseMove = () => {
4353
+ if (!lastMouseEvent || !selectionSystem) {
4354
+ mouseMoveRafId = null;
4355
+ return;
4356
+ }
4357
+ const e = lastMouseEvent;
4358
+ const cursorPoint = {
4359
+ x: e.clientX,
4360
+ y: e.clientY
4361
+ };
4362
+ setCursor(cursorPoint);
4363
+ const selectedElement = selectionSystem.getSelected();
4364
+ const isAlt = isAltPressed();
4365
+ const state = system?.getState();
4366
+ if (selectedElement) {
4367
+ const hoveredElement = getTopElementAtPoint(e.clientX, e.clientY);
4368
+ const isAncestor = hoveredElement && lastHoveredElement && hoveredElement.contains(lastHoveredElement) && hoveredElement !== lastHoveredElement;
4369
+ if (isAlt) {
4370
+ if (system) {
4371
+ measureDelegate.execute(!!isAncestor, selectedElement, cursorPoint, hoveredElement);
4372
+ }
4373
+ } else if (state !== "FROZEN") {
4374
+ if (hoveredElement) {
4375
+ selectionDelegate.execute(!!isAncestor, hoveredElement);
4376
+ }
4377
+ }
4378
+ }
4379
+ mouseMoveRafId = null;
4380
+ };
4381
+ const handleMouseMove = (e) => {
4382
+ lastMouseEvent = e;
4383
+ lastPointerPos = {
4384
+ x: e.clientX,
4385
+ y: e.clientY
4386
+ };
4387
+ if (!mouseMoveRafId) {
4388
+ mouseMoveRafId = requestAnimationFrame(processMouseMove);
4389
+ }
4390
+ };
4391
+ const handleKeyDown = (e) => {
4392
+ if (e.key === commands.clear) {
4393
+ setIsAltPressed(false);
4394
+ setCalculatorState(null);
4395
+ setActiveCalculatorLine(null);
4396
+ if (selectionSystem) {
4397
+ lastHoveredElement = null;
4398
+ selectionDelegate.cancel();
4399
+ measureDelegate.cancel();
4400
+ selectionSystem.clear();
4401
+ }
4402
+ if (projectionSystem) {
4403
+ projectionSystem.clear();
4404
+ }
4405
+ if (rulerSystem) {
4406
+ rulerSystem.clear();
4407
+ }
4408
+ if (system) {
4409
+ system.abort();
4410
+ const calc = system.getCalculator();
4411
+ calc.close();
4412
+ setResult(null);
4413
+ }
4414
+ return;
4415
+ }
4416
+ if (e.key === commands.select) {
4417
+ setIsSelectKeyDown(true);
4418
+ }
4419
+ if (e.key.toLowerCase() === commands.ruler && e.shiftKey && rulerSystem) {
4420
+ e.preventDefault();
4421
+ const vp = viewport();
4422
+ const x = Math.max(0, Math.min(cursor().x, vp.width));
4423
+ const y = Math.max(0, Math.min(cursor().y, vp.height));
4424
+ rulerSystem.addPair(x, y);
4425
+ return;
4426
+ }
4427
+ const isAltKey = e.key === "Alt" || e.key === "AltGraph" || e.key === commands.activate;
4428
+ if (isAltKey) {
4429
+ e.preventDefault();
4430
+ if (!isAltPressed()) {
4431
+ if (system) {
4432
+ system.abort();
4433
+ setResult(null);
4434
+ handleCalculatorClose();
4435
+ }
4436
+ if (projectionSystem) {
4437
+ projectionSystem.clear();
4438
+ }
4439
+ }
4440
+ setIsAltPressed(true);
4441
+ } else if (e.key === commands.freeze && e.target === document.body && system) {
4442
+ const state = system.getState();
4443
+ if (state === "FROZEN") {
4444
+ e.preventDefault();
4445
+ system.unfreeze(isAltPressed());
4446
+ } else if (selectionMetadata().element) {
4447
+ e.preventDefault();
4448
+ system.freeze();
4449
+ }
4450
+ } else {
4451
+ const key = e.key.toLowerCase();
4452
+ const {
4453
+ calculator,
4454
+ projection
4455
+ } = commands;
4456
+ const isCalcActive = !!calculatorState();
4457
+ const isProjActive = projectionState().direction !== null;
4458
+ const shouldCalcGetNumbers = isCalcActive && (activeInputFocus() === "calculator" || !isProjActive);
4459
+ if (isCalcActive && (shouldCalcGetNumbers || !/^\d$/.test(e.key))) {
4460
+ const isNumeric = /^[0-9]$/.test(e.key);
4461
+ const isOperator = /^[+\-*/]$/.test(e.key);
4462
+ const isDecimal = e.key === ".";
4463
+ const isBackspace = e.key === "Backspace";
4464
+ const isDelete = e.key === "Delete";
4465
+ const isEnter = e.key === "Enter";
4466
+ const isEscape = e.key === "Escape";
4467
+ if (isNumeric || isOperator || isDecimal || isBackspace || isDelete || isEnter || isEscape) {
4468
+ if ((isNumeric || isBackspace || isDecimal) && !shouldCalcGetNumbers) ; else {
4469
+ e.preventDefault();
4470
+ e.stopImmediatePropagation();
4471
+ if (isNumeric || isOperator || isDecimal) handleCalculatorInput(e.key);
4472
+ else if (isBackspace) handleCalculatorBackspace();
4473
+ else if (isDelete) handleCalculatorDelete();
4474
+ else if (isEnter) handleCalculatorEnter();
4475
+ else if (isEscape) handleCalculatorClose();
4476
+ return;
4477
+ }
4478
+ }
4479
+ }
4480
+ const dirMap = {
4481
+ [projection.top]: "top",
4482
+ [projection.left]: "left",
4483
+ [projection.bottom]: "bottom",
4484
+ [projection.right]: "right"
4485
+ };
4486
+ const dir = dirMap[key];
4487
+ if (dir && selectionMetadata().element) {
4488
+ e.preventDefault();
4489
+ e.stopImmediatePropagation();
4490
+ setActiveInputFocus("projection");
4491
+ const currentElement = selectionMetadata().element;
4492
+ if (currentElement) {
4493
+ projectionSystem?.setElement(currentElement);
4494
+ }
4495
+ projectionSystem?.setDirection(dir);
4496
+ if (system) {
4497
+ system.freeze();
4498
+ }
4499
+ const getRunway = (dir2) => {
4500
+ const metadata = selectionMetadata();
4501
+ const live = getLiveGeometry(metadata.rect, metadata.scrollHierarchy, metadata.position, metadata.stickyConfig, metadata.initialWindowX, metadata.initialWindowY);
4502
+ if (!live) return void 0;
4503
+ return getMaxProjectionDistance(dir2, live);
4504
+ };
4505
+ const maxRunway = getRunway(dir);
4506
+ if (maxRunway !== void 0) projectionSystem?.capValue(maxRunway);
4507
+ return;
4508
+ }
4509
+ if (isProjActive) {
4510
+ const isNumeric = /^[0-9.]$/.test(key);
4511
+ const isBackspace = e.key === "Backspace";
4512
+ const hasPriority = activeInputFocus() === "projection" || !isCalcActive;
4513
+ if ((isNumeric || isBackspace) && hasPriority) {
4514
+ e.preventDefault();
4515
+ e.stopImmediatePropagation();
4516
+ const currentDir = projectionState().direction;
4517
+ if (isNumeric && currentDir) {
4518
+ const metadata = selectionMetadata();
4519
+ const live = getLiveGeometry(metadata.rect, metadata.scrollHierarchy, metadata.position, metadata.stickyConfig, metadata.initialWindowX, metadata.initialWindowY);
4520
+ let max;
4521
+ if (live) {
4522
+ max = getMaxProjectionDistance(currentDir, live);
4523
+ }
4524
+ projectionSystem?.appendValue(key, max);
4525
+ } else if (isBackspace) {
4526
+ projectionSystem?.backspace();
4527
+ }
4528
+ return;
4529
+ }
4530
+ }
4531
+ if (isFrozen() && result()) {
4532
+ const typeMap = {
4533
+ [calculator.top]: "top",
4534
+ [calculator.right]: "right",
4535
+ [calculator.bottom]: "bottom",
4536
+ [calculator.left]: "left",
4537
+ [calculator.distance]: "distance"
4538
+ };
4539
+ const targetType = typeMap[key];
4540
+ if (targetType) {
4541
+ e.preventDefault();
4542
+ const currentLines = result()?.lines || [];
4543
+ const targetLine = currentLines.find((l) => l.type === targetType);
4544
+ if (targetLine) {
4545
+ const liveValue = getLiveLineValue(targetLine, result());
4546
+ handleLineClick(targetLine, liveValue);
4547
+ }
4548
+ }
4549
+ }
4550
+ }
4551
+ };
4552
+ const handleKeyUp = (e) => {
4553
+ if (e.key === commands.select) {
4554
+ setIsSelectKeyDown(false);
4555
+ }
4556
+ const isAltKey = e.key === "Alt" || e.key === "AltGraph" || e.key === commands.activate;
4557
+ if (isAltKey) {
4558
+ e.preventDefault();
4559
+ if (isAltPressed()) {
4560
+ setIsAltPressed(false);
4561
+ if (system) {
4562
+ system.stop();
4563
+ }
4564
+ }
4565
+ }
4566
+ };
4567
+ const handleBlur = () => {
4568
+ if (isAltPressed()) {
4569
+ setIsAltPressed(false);
4570
+ if (system) {
4571
+ system.stop();
4572
+ setResult(null);
4573
+ }
4574
+ }
4575
+ };
4576
+ window.addEventListener("pointerdown", handlePointerDown, {
4577
+ capture: true
4578
+ });
4579
+ window.addEventListener("pointerup", handlePointerUp, {
4580
+ capture: true
4581
+ });
4582
+ window.addEventListener("mousemove", handleMouseMove);
4583
+ window.addEventListener("keydown", handleKeyDown, {
4584
+ capture: true
4585
+ });
4586
+ window.addEventListener("keyup", handleKeyUp, {
4587
+ capture: true
4588
+ });
4589
+ window.addEventListener("contextmenu", handleContextMenu, {
4590
+ capture: true
4591
+ });
4592
+ window.addEventListener("blur", handleBlur);
4593
+ onCleanup(() => {
4594
+ window.removeEventListener("pointerdown", handlePointerDown, {
4595
+ capture: true
4596
+ });
4597
+ window.removeEventListener("pointerup", handlePointerUp, {
4598
+ capture: true
4599
+ });
4600
+ window.removeEventListener("mousemove", handleMouseMove);
4601
+ window.removeEventListener("keydown", handleKeyDown, {
4602
+ capture: true
4603
+ });
4604
+ window.removeEventListener("keyup", handleKeyUp, {
4605
+ capture: true
4606
+ });
4607
+ window.removeEventListener("contextmenu", handleContextMenu, {
4608
+ capture: true
4609
+ });
4610
+ window.removeEventListener("blur", handleBlur);
4611
+ if (mouseMoveRafId) {
4612
+ cancelAnimationFrame(mouseMoveRafId);
4613
+ }
4614
+ selectionDelegate.cancel();
4615
+ measureDelegate.cancel();
4616
+ unsubscribe();
4617
+ unsubscribeUpdate();
4618
+ unsubscribeProjection();
4619
+ unsubscribeRuler();
4620
+ handleCleanup();
4621
+ if (projectionSystem) {
4622
+ projectionSystem = null;
4623
+ }
4624
+ if (rulerSystem) {
4625
+ rulerSystem = null;
4626
+ }
4627
+ });
4628
+ });
4629
+ createEffect(() => {
4630
+ const active = !!selectionMetadata().element || !!result();
4631
+ if (active) {
4632
+ window.addEventListener("scroll", scheduleUpdate, {
4633
+ passive: true,
4634
+ capture: true
4635
+ });
4636
+ syncViewport();
4637
+ onCleanup(() => {
4638
+ window.removeEventListener("scroll", scheduleUpdate, {
4639
+ capture: true
4640
+ });
4641
+ if (viewportRafId) {
4642
+ cancelAnimationFrame(viewportRafId);
4643
+ viewportRafId = null;
4644
+ }
4645
+ });
4646
+ }
4647
+ });
4648
+ const updateResizeObservations = (primaryEl, secondaryEl) => {
4649
+ if (!resizeObserver) return;
4650
+ if (primaryEl === observedPrimary && secondaryEl === observedSecondary) {
4651
+ return;
4652
+ }
4653
+ if (observedPrimary && observedPrimary !== primaryEl) {
4654
+ resizeObserver.unobserve(observedPrimary);
4655
+ observedPrimary = null;
4656
+ }
4657
+ if (observedSecondary && observedSecondary !== secondaryEl && observedSecondary !== primaryEl) {
4658
+ resizeObserver.unobserve(observedSecondary);
4659
+ observedSecondary = null;
4660
+ }
4661
+ if (primaryEl && primaryEl !== observedPrimary) {
4662
+ resizeObserver.observe(primaryEl);
4663
+ observedPrimary = primaryEl;
4664
+ }
4665
+ if (secondaryEl && secondaryEl !== primaryEl && secondaryEl !== observedSecondary) {
4666
+ resizeObserver.observe(secondaryEl);
4667
+ observedSecondary = secondaryEl;
4668
+ }
4669
+ };
4670
+ createEffect(() => {
4671
+ let resizeTimer = null;
4672
+ let lastRun = 0;
4673
+ let sentinelResized = false;
4674
+ let primaryChanged = false;
4675
+ let secondaryChanged = false;
4676
+ const runUpdates2 = () => {
4677
+ if (sentinelResized || primaryChanged) {
4678
+ if (observedPrimary) {
4679
+ const rect = observedPrimary.getBoundingClientRect();
4680
+ selectionSystem?.updateRect(rect);
4681
+ if (system) system.updatePrimaryRect(rect);
4682
+ }
4683
+ }
4684
+ if (sentinelResized || secondaryChanged) {
4685
+ if (observedSecondary) {
4686
+ const rect = observedSecondary.getBoundingClientRect();
4687
+ system?.updateSecondaryRect(rect);
4688
+ }
4689
+ }
4690
+ sentinelResized = false;
4691
+ primaryChanged = false;
4692
+ secondaryChanged = false;
4693
+ };
4694
+ resizeObserver = new ResizeObserver((entries) => {
4695
+ for (const entry of entries) {
4696
+ if (entry.target === document.documentElement) {
4697
+ sentinelResized = true;
4698
+ } else if (entry.target === observedPrimary) {
4699
+ primaryChanged = true;
4700
+ } else if (entry.target === observedSecondary) {
4701
+ secondaryChanged = true;
4702
+ }
4703
+ }
4704
+ if (sentinelResized) {
4705
+ scheduleUpdate();
4706
+ }
4707
+ const now = Date.now();
4708
+ const remaining = RESIZE_THROTTLE_MS - (now - lastRun);
4709
+ if (remaining <= 0) {
4710
+ if (resizeTimer) clearTimeout(resizeTimer);
4711
+ lastRun = now;
4712
+ runUpdates2();
4713
+ } else if (!resizeTimer) {
4714
+ resizeTimer = window.setTimeout(() => {
4715
+ lastRun = Date.now();
4716
+ resizeTimer = null;
4717
+ runUpdates2();
4718
+ }, remaining);
4719
+ }
4720
+ });
4721
+ resizeObserver.observe(document.documentElement);
4722
+ onCleanup(() => {
4723
+ resizeObserver?.disconnect();
4724
+ resizeObserver = null;
4725
+ observedPrimary = null;
4726
+ observedSecondary = null;
4727
+ if (resizeTimer) clearTimeout(resizeTimer);
4728
+ });
4729
+ });
4730
+ createEffect(() => {
4731
+ const primaryEl = selectionMetadata().element;
4732
+ const currentResult = result();
4733
+ const secondaryEl = isFrozen() ? currentResult?.secondaryElement ?? null : null;
4734
+ if (!primaryEl && !secondaryEl) {
4735
+ updateResizeObservations(null, null);
4736
+ return;
4737
+ }
4738
+ updateResizeObservations(primaryEl, secondaryEl);
4739
+ });
4740
+ createEffect(() => {
4741
+ const calcLine = activeCalculatorLine();
4742
+ const currentResult = result();
4743
+ if (calcLine && currentResult && system) {
4744
+ const state = untrack(() => calculatorState());
4745
+ if (state?.isActive) {
4746
+ viewport().version;
4747
+ const matchingLine = currentResult.lines.find((l) => l.type === calcLine.type);
4748
+ if (matchingLine) {
4749
+ const liveValue = getLiveLineValue(matchingLine, currentResult);
4750
+ const calc = system.getCalculator();
4751
+ calc.syncValue(liveValue);
4752
+ setCalculatorState(calc.getState());
4753
+ }
4754
+ }
4755
+ }
4756
+ });
4757
+ const handleLineClick = (line, liveValue) => {
4758
+ if (system) {
4759
+ setActiveCalculatorLine(null);
4760
+ const calc = system.getCalculator();
4761
+ calc.open(liveValue);
4762
+ setActiveInputFocus("calculator");
4763
+ const calcState = calc.getState();
4764
+ setCalculatorState(calcState.isActive ? calcState : null);
4765
+ if ("startSync" in line) {
4766
+ setActiveCalculatorLine(line);
4767
+ }
4768
+ }
4769
+ };
4770
+ const handleCalculatorInput = (key) => {
4771
+ if (system) {
4772
+ const calc = system.getCalculator();
4773
+ calc.handleInput(key);
4774
+ if (/^[+\-*/.]$/.test(key)) {
4775
+ setActiveInputFocus("calculator");
4776
+ }
4777
+ const calcState = calc.getState();
4778
+ const isActive = calcState.isActive;
4779
+ setCalculatorState(isActive ? calcState : null);
4780
+ if (calcState.operation) {
4781
+ setActiveCalculatorLine(null);
4782
+ }
4783
+ if (!isActive && projectionState().direction !== null) {
4784
+ setActiveInputFocus("projection");
4785
+ }
4786
+ }
4787
+ };
4788
+ const handleCalculatorBackspace = () => {
4789
+ if (system) {
4790
+ const calc = system.getCalculator();
4791
+ calc.handleBackspace();
4792
+ const calcState = calc.getState();
4793
+ const isActive = calcState.isActive;
4794
+ setCalculatorState(isActive ? calcState : null);
4795
+ if (!isActive) {
4796
+ setActiveCalculatorLine(null);
4797
+ if (projectionState().direction !== null) {
4798
+ setActiveInputFocus("projection");
4799
+ }
4800
+ }
4801
+ }
4802
+ };
4803
+ const handleCalculatorDelete = () => {
4804
+ if (system) {
4805
+ const calc = system.getCalculator();
4806
+ calc.handleDelete();
4807
+ const calcState = calc.getState();
4808
+ const isActive = calcState.isActive;
4809
+ setCalculatorState(isActive ? calcState : null);
4810
+ setActiveCalculatorLine(null);
4811
+ if (!isActive && projectionState().direction !== null) {
4812
+ setActiveInputFocus("projection");
4813
+ }
4814
+ }
4815
+ };
4816
+ const handleCalculatorEnter = () => {
4817
+ if (system) {
4818
+ const calc = system.getCalculator();
4819
+ calc.handleEnter();
4820
+ const calcState = calc.getState();
4821
+ const isActive = calcState.isActive;
4822
+ setCalculatorState(isActive ? calcState : null);
4823
+ setActiveCalculatorLine(null);
4824
+ if (!isActive && projectionState().direction !== null) {
4825
+ setActiveInputFocus("projection");
4826
+ }
4827
+ }
4828
+ };
4829
+ const handleCalculatorClose = () => {
4830
+ if (system) {
4831
+ const calc = system.getCalculator();
4832
+ calc.close();
4833
+ setCalculatorState(null);
4834
+ setActiveCalculatorLine(null);
4835
+ if (projectionState().direction !== null) {
4836
+ setActiveInputFocus("projection");
4837
+ }
4838
+ }
4839
+ };
4840
+ const handleRulerUpdate = (id, position) => {
4841
+ rulerSystem?.updateLine(id, position);
4842
+ };
4843
+ const handleRulerRemove = (id) => {
4844
+ rulerSystem?.removeLine(id);
4845
+ };
4846
+ const handleCleanup = () => {
4847
+ if (system) system.cleanup();
4848
+ if (selectionSystem) selectionSystem.clear();
4849
+ if (projectionSystem) projectionSystem.clear();
4850
+ if (rulerSystem) rulerSystem.clear();
4851
+ };
4852
+ return createComponent(Overlay, {
4853
+ result,
4854
+ cursor,
4855
+ selectionMetadata,
4856
+ isAltPressed,
4857
+ isFrozen,
4858
+ animation,
4859
+ viewport,
4860
+ calculatorState,
4861
+ projectionState,
4862
+ rulerState,
4863
+ activeFocus: activeInputFocus,
4864
+ onLineClick: handleLineClick,
4865
+ onRulerUpdate: handleRulerUpdate,
4866
+ onRulerRemove: handleRulerRemove,
4867
+ onCalculatorClose: handleCalculatorClose
4868
+ });
4869
+ }
4870
+ function getMaxProjectionDistance(dir, live) {
4871
+ const docWidth = document.documentElement.scrollWidth;
4872
+ const docHeight = document.documentElement.scrollHeight;
4873
+ switch (dir) {
4874
+ case "top":
4875
+ return live.top;
4876
+ case "bottom":
4877
+ return docHeight - (live.top + live.height);
4878
+ case "left":
4879
+ return live.left;
4880
+ case "right":
4881
+ return docWidth - (live.left + live.width);
4882
+ }
4883
+ }
4884
+ var styleElement = null;
4885
+ var injectionCount = 0;
4886
+ function injectStyles() {
4887
+ if (styleElement) {
4888
+ injectionCount++;
4889
+ return;
4890
+ }
4891
+ styleElement = document.createElement("style");
4892
+ styleElement.textContent = OVERLAY_STYLES;
4893
+ styleElement.setAttribute("data-caliper-styles", "true");
4894
+ const head = document.head || document.getElementsByTagName("head")[0];
4895
+ head.appendChild(styleElement);
4896
+ injectionCount = 1;
4897
+ }
4898
+ function removeStyles() {
4899
+ if (!styleElement) {
4900
+ return;
4901
+ }
4902
+ injectionCount--;
4903
+ if (injectionCount <= 0) {
4904
+ styleElement.remove();
4905
+ styleElement = null;
4906
+ injectionCount = 0;
4907
+ }
4908
+ }
4909
+ var IS_BROWSER2 = typeof window !== "undefined";
4910
+ var activeInstance = null;
4911
+ function createOverlay(config) {
4912
+ if (!IS_BROWSER2) {
4913
+ return {
4914
+ mount: () => {
4915
+ },
4916
+ dispose: () => {
4917
+ },
4918
+ mounted: false
4919
+ };
4920
+ }
4921
+ if (activeInstance?.mounted) {
4922
+ return activeInstance;
4923
+ }
4924
+ if (window.__CALIPER__?.mounted) {
4925
+ activeInstance = window.__CALIPER__;
4926
+ return activeInstance;
4927
+ }
4928
+ const windowConfig = getConfig();
4929
+ const mergedConfig = {
4930
+ theme: { ...windowConfig?.theme, ...config?.theme },
4931
+ commands: {
4932
+ ...windowConfig?.commands,
4933
+ ...config?.commands,
4934
+ calculator: {
4935
+ ...windowConfig?.commands?.calculator,
4936
+ ...config?.commands?.calculator
4937
+ },
4938
+ projection: {
4939
+ ...windowConfig?.commands?.projection,
4940
+ ...config?.commands?.projection
4941
+ }
4942
+ },
4943
+ animation: { ...windowConfig?.animation, ...config?.animation }
4944
+ };
4945
+ const commands = mergeCommands(mergedConfig.commands);
4946
+ const animation = mergeAnimation(mergedConfig.animation);
4947
+ let cleanup = null;
4948
+ const instance = {
4949
+ mounted: false,
4950
+ mount: (container) => {
4951
+ if (instance.mounted) return;
4952
+ if (document.getElementById("caliper-overlay-root")) {
4953
+ instance.mounted = true;
4954
+ return;
4955
+ }
4956
+ if (mergedConfig.theme) {
4957
+ applyTheme(mergedConfig.theme);
4958
+ }
4959
+ const target = container || document.body;
4960
+ injectStyles();
4961
+ const overlayContainer = document.createElement("div");
4962
+ overlayContainer.id = "caliper-overlay-root";
4963
+ target.appendChild(overlayContainer);
4964
+ const disposeRender = render(() => Root({ commands, animation }), overlayContainer);
4965
+ cleanup = () => {
4966
+ disposeRender();
4967
+ overlayContainer.remove();
4968
+ removeStyles();
4969
+ instance.mounted = false;
4970
+ if (activeInstance === instance) activeInstance = null;
4971
+ };
4972
+ instance.mounted = true;
4973
+ },
4974
+ dispose: () => {
4975
+ if (cleanup) {
4976
+ cleanup();
4977
+ cleanup = null;
4978
+ }
4979
+ }
4980
+ };
4981
+ activeInstance = instance;
4982
+ window.__CALIPER__ = instance;
4983
+ if (IS_BROWSER2) {
4984
+ instance.mount();
4985
+ }
4986
+ return instance;
4987
+ }
4988
+ if (IS_BROWSER2) {
4989
+ showVersionInfo("0.1.0").catch(() => {
4990
+ });
4991
+ }
4992
+
4993
+ // src/index.ts
4994
+ var VERSION = "0.1.0";
4995
+
4996
+ exports.VERSION = VERSION;
4997
+ exports.getConfig = getConfig;
4998
+ exports.init = createOverlay;
4999
+ exports.setConfig = setConfig;