@oyerinde/caliper 0.1.0 → 0.1.2

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.
@@ -801,6 +801,7 @@
801
801
  function createReader() {
802
802
  let rafId = null;
803
803
  let idleId = null;
804
+ let taskController = null;
804
805
  let timeoutId = null;
805
806
  function detectBestStrategy() {
806
807
  if ("scheduler" in globalThis) {
@@ -822,19 +823,19 @@
822
823
  scheduleWithIdle(callback, urgent);
823
824
  return;
824
825
  }
825
- const controller = new TaskController({
826
+ taskController = new TaskController({
826
827
  priority: urgent ? "user-visible" : "background"
827
828
  });
828
- controller.signal;
829
829
  Scheduler2.postTask(
830
830
  () => {
831
831
  callback();
832
832
  },
833
833
  {
834
- signal: controller.signal,
834
+ signal: taskController?.signal,
835
835
  priority: urgent ? "user-visible" : "background"
836
836
  }
837
- );
837
+ ).catch(() => {
838
+ });
838
839
  }
839
840
  function scheduleWithIdle(callback, urgent) {
840
841
  if (!("requestIdleCallback" in window)) {
@@ -893,6 +894,10 @@
893
894
  cancelIdleCallback(idleId);
894
895
  idleId = null;
895
896
  }
897
+ if (taskController) {
898
+ taskController.abort();
899
+ taskController = null;
900
+ }
896
901
  if (timeoutId !== null) {
897
902
  clearTimeout(timeoutId);
898
903
  timeoutId = null;
@@ -1030,6 +1035,13 @@
1030
1035
  const rect = element.getBoundingClientRect();
1031
1036
  return rect.width > 0 && rect.height > 0;
1032
1037
  }
1038
+ function isEditable(element) {
1039
+ if (!element || !(element instanceof HTMLElement)) {
1040
+ return false;
1041
+ }
1042
+ const tagName = element.tagName;
1043
+ return tagName === "INPUT" || tagName === "TEXTAREA" || tagName === "SELECT" || element.isContentEditable;
1044
+ }
1033
1045
  function isEligible(element) {
1034
1046
  if (element.closest("[data-caliper-ignore]")) {
1035
1047
  return false;
@@ -1050,8 +1062,7 @@
1050
1062
  }
1051
1063
  function getTopElementAtPoint(x, y) {
1052
1064
  const node = document.elementFromPoint(x, y);
1053
- if (!node) return null;
1054
- if (isCaliperNode(node) || !isEligible(node)) return null;
1065
+ if (!node || isCaliperNode(node) || !isEligible(node)) return null;
1055
1066
  return node;
1056
1067
  }
1057
1068
  function detectBestContext(selectedElement, cursorX, cursorY) {
@@ -1726,7 +1737,7 @@
1726
1737
  result: null,
1727
1738
  isActive: false
1728
1739
  };
1729
- function calculate2() {
1740
+ function calculate() {
1730
1741
  const val = state.inputValue === "" ? "0" : state.inputValue;
1731
1742
  const inputNum = parseFloat(val);
1732
1743
  if (isNaN(inputNum)) {
@@ -1787,7 +1798,7 @@
1787
1798
  const hasResult = state.result !== null;
1788
1799
  const isSwitchable = state.inputValue === "" || state.inputValue === "0";
1789
1800
  if (hasResult || state.operation && !isSwitchable) {
1790
- const newBase = hasResult ? state.result : calculate2() ?? state.baseValue;
1801
+ const newBase = hasResult ? state.result : calculate() ?? state.baseValue;
1791
1802
  state = {
1792
1803
  baseValue: newBase,
1793
1804
  operation: action.operation,
@@ -1842,7 +1853,7 @@
1842
1853
  if (!state.isActive || !state.operation) {
1843
1854
  return state;
1844
1855
  }
1845
- const result = calculate2();
1856
+ const result = calculate();
1846
1857
  state = {
1847
1858
  ...state,
1848
1859
  result
@@ -1863,7 +1874,7 @@
1863
1874
  function getState() {
1864
1875
  return { ...state };
1865
1876
  }
1866
- return { getState, dispatch, calculate: calculate2 };
1877
+ return { getState, dispatch, calculate };
1867
1878
  }
1868
1879
  function createCalculatorIntegration() {
1869
1880
  const calculator = createCalculatorState();
@@ -1936,6 +1947,12 @@
1936
1947
  );
1937
1948
  if (measurement) {
1938
1949
  const { result, element } = measurement;
1950
+ if (!stateMachine.isMeasuring() && !stateMachine.isArmed()) {
1951
+ return;
1952
+ }
1953
+ if (stateMachine.isMeasuring() && element === previousElement && result.context === previousContext) {
1954
+ return;
1955
+ }
1939
1956
  currentResult = result;
1940
1957
  previousContext = result.context;
1941
1958
  previousElement = element;
@@ -1947,6 +1964,7 @@
1947
1964
  function freeze() {
1948
1965
  const state = stateMachine.getState();
1949
1966
  if (state === "MEASURING" || state === "IDLE" || state === "ARMED") {
1967
+ reader.cancel();
1950
1968
  stateMachine.transitionTo("FROZEN");
1951
1969
  notifyListeners();
1952
1970
  }
@@ -2304,8 +2322,8 @@
2304
2322
  calcBg: "rgba(30, 30, 30, 0.95)",
2305
2323
  calcShadow: "rgba(0, 0, 0, 0.25)",
2306
2324
  calcOpHighlight: "rgba(24, 160, 251, 0.3)",
2307
- calcText: "white",
2308
- text: "white",
2325
+ calcText: "rgba(255, 255, 255, 1)",
2326
+ text: "rgba(255, 255, 255, 1)",
2309
2327
  projection: "rgba(155, 81, 224, 1)",
2310
2328
  ruler: "rgba(24, 160, 251, 1)"
2311
2329
  };
@@ -2318,18 +2336,49 @@
2318
2336
  const num = Number(value);
2319
2337
  return isFinite(num) && !isNaN(num) ? num : defaultValue;
2320
2338
  }
2339
+ function withOpacity(color, opacity) {
2340
+ if (color.startsWith("#")) {
2341
+ let hex = color.slice(1);
2342
+ if (hex.length === 3) hex = hex.split("").map((c) => c + c).join("");
2343
+ const r = parseInt(hex.slice(0, 2), 16);
2344
+ const g = parseInt(hex.slice(2, 4), 16);
2345
+ const b = parseInt(hex.slice(4, 6), 16);
2346
+ return `rgba(${r}, ${g}, ${b}, ${opacity})`;
2347
+ }
2348
+ if (color.startsWith("rgba")) {
2349
+ return color.replace(/[\d.]+\)$/g, `${opacity})`);
2350
+ }
2351
+ if (color.startsWith("rgb")) {
2352
+ return color.replace(")", `, ${opacity})`).replace("rgb", "rgba");
2353
+ }
2354
+ return color;
2355
+ }
2321
2356
  function applyTheme(theme) {
2322
2357
  if (!theme) return;
2323
2358
  const root = document.documentElement;
2324
- if (theme.primary) root.style.setProperty("--caliper-primary", theme.primary);
2325
- if (theme.secondary) root.style.setProperty("--caliper-secondary", theme.secondary);
2359
+ if (theme.primary) {
2360
+ root.style.setProperty("--caliper-primary", theme.primary);
2361
+ root.style.setProperty("--caliper-primary-90", withOpacity(theme.primary, 0.9));
2362
+ root.style.setProperty("--caliper-primary-95", withOpacity(theme.primary, 0.95));
2363
+ root.style.setProperty("--caliper-primary-50", withOpacity(theme.primary, 0.5));
2364
+ root.style.setProperty("--caliper-primary-05", withOpacity(theme.primary, 0.05));
2365
+ }
2366
+ if (theme.secondary) {
2367
+ root.style.setProperty("--caliper-secondary", theme.secondary);
2368
+ root.style.setProperty("--caliper-secondary-50", withOpacity(theme.secondary, 0.5));
2369
+ root.style.setProperty("--caliper-secondary-05", withOpacity(theme.secondary, 0.05));
2370
+ }
2326
2371
  if (theme.calcBg) root.style.setProperty("--caliper-calc-bg", theme.calcBg);
2327
2372
  if (theme.calcShadow) root.style.setProperty("--caliper-calc-shadow", theme.calcShadow);
2328
2373
  if (theme.calcOpHighlight)
2329
2374
  root.style.setProperty("--caliper-calc-op-highlight", theme.calcOpHighlight);
2330
2375
  if (theme.calcText) root.style.setProperty("--caliper-calc-text", theme.calcText);
2331
2376
  if (theme.text) root.style.setProperty("--caliper-text", theme.text);
2332
- if (theme.projection) root.style.setProperty("--caliper-projection", theme.projection);
2377
+ if (theme.projection) {
2378
+ root.style.setProperty("--caliper-projection", theme.projection);
2379
+ root.style.setProperty("--caliper-projection-90", withOpacity(theme.projection, 0.9));
2380
+ root.style.setProperty("--caliper-projection-light", withOpacity(theme.projection, 0.2));
2381
+ }
2333
2382
  if (theme.ruler) root.style.setProperty("--caliper-ruler", theme.ruler);
2334
2383
  }
2335
2384
  function mergeCommands(userCommands) {
@@ -2364,6 +2413,19 @@
2364
2413
  lerpFactor: parseNumber(userAnimation?.lerpFactor, DEFAULT_ANIMATION.lerpFactor)
2365
2414
  };
2366
2415
  }
2416
+ function mergeTheme(userTheme) {
2417
+ return {
2418
+ primary: userTheme?.primary ?? DEFAULT_THEME.primary,
2419
+ secondary: userTheme?.secondary ?? DEFAULT_THEME.secondary,
2420
+ calcBg: userTheme?.calcBg ?? DEFAULT_THEME.calcBg,
2421
+ calcShadow: userTheme?.calcShadow ?? DEFAULT_THEME.calcShadow,
2422
+ calcOpHighlight: userTheme?.calcOpHighlight ?? DEFAULT_THEME.calcOpHighlight,
2423
+ calcText: userTheme?.calcText ?? DEFAULT_THEME.calcText,
2424
+ text: userTheme?.text ?? DEFAULT_THEME.text,
2425
+ projection: userTheme?.projection ?? DEFAULT_THEME.projection,
2426
+ ruler: userTheme?.ruler ?? DEFAULT_THEME.ruler
2427
+ };
2428
+ }
2367
2429
  function getConfig() {
2368
2430
  if (typeof window !== "undefined") {
2369
2431
  const windowConfig = window.__CALIPER_CONFIG__ ?? {};
@@ -2390,7 +2452,7 @@
2390
2452
  var CALIPER_LOGO_SVG = `data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTcyIiBoZWlnaHQ9IjUwIiB2aWV3Qm94PSIwIDAgMTcyIDUwIiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTQ3LjIxNDQgNy42MjkzOWUtMDZIMzIuNzkyOEwyNS44MjUgNDMuMzIyNUgzNS4wNjEzTDM2LjE5NTYgMzUuMDE2M0g0NC4xMzU2TDQ1LjI2OTkgNDMuMzIyNUg1NC42NjgzTDQ3LjIxNDQgNy42MjkzOWUtMDZaTTM5LjU5ODUgOC4zMDYySDQwLjczMjhMNDQuMTM1NiAyOC4xNzU5SDM2LjE5NTZMMzkuNTk4NSA4LjMwNjJaIiBmaWxsPSIjQUMyMzIzIi8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNNS4wMjMyOCAwTDAgNS4wNDg4NlYyOC4zMzg4TDUuMTg1MzIgMzMuMzg3NkgxNy41MDA0VjM1LjM0MkgxNS41NTZWNDYuNzQyN0gxOS4xMjA5TDI0LjMwNjIgMzUuNjY3OFYyNS44OTU4SDcuMTI5ODFWNy4zMjg5OUgxMy40NDk0VjBINS4wMjMyOFoiIGZpbGw9IiNBQzIzMjMiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik02Ni40OTc0IDcuNjI5MzllLTA2SDU3LjI2MVY0LjM5NzRINjIuNDQ2M1Y1LjIxMTczSDU3LjI2MVY2LjY3NzU0SDYwLjE3NzdWNy4zMjg5OUg1Ny4yNjFWOC45NTc2Nkg2MC4xNzc3VjkuNjA5MTNINTcuMjYxVjExLjA3NDlINjAuMTc3N1YxMS43MjY0SDU3LjI2MVYxMy4xOTIySDYyLjQ0NjNWMTMuODQzN0g1Ny4yNjFWMTUuNDcyM0g2MC4xNzc3VjE2LjEyMzhINTcuMjYxVjE3LjU4OTZINjAuMTc3N1YxOC4yNDExSDU3LjI2MVYxOS44Njk3SDYwLjE3NzdWMjAuNTIxMkg1Ny4yNjFWMjEuODI0MUg2Mi40NDYzVjIyLjYzODRINTcuMjYxVjI0LjI2NzFINjAuMTc3N1YyNC43NTU3SDU3LjI2MVYyNi4zODQ0SDYwLjE3NzdWMjcuMDM1OEg1Ny4yNjFWMjguNTAxNkg2MC4xNzc3VjI5LjE1MzFINTcuMjYxVjMwLjYxODlINjIuNDQ2M1YzMS40MzMySDU3LjI2MVYzMi44OTlINjAuMTc3N1YzMy41NTA1SDU3LjI2MVYzNS4wMTYzSDYwLjE3NzdWMzUuODMwNkg1Ny4yNjFWMzcuMjk2NEg2MC4xNzc3VjM3Ljk0NzlINTcuMjYxVjM5LjQxMzdINjIuNDQ2M1Y0MC4yMjhINTcuMjYxVjQzLjMyMjVINzcuODQwMlYzNS4wMTYzSDY2LjQ5NzRWNy42MjkzOWUtMDZaIiBmaWxsPSIjQUMyMzIzIi8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNNzcuODQwMiAyNy42ODczSDY3LjQ2OTZMNjkuNDE0MSAzMC42MTg5TDc5Ljc4NDcgMzQuMjAyVjQzLjk3MzlDNzcuNTQzOSA0NC4zNzMgNzYuNTQzOSA0NS4yNzY5IDc2LjU0MzkgNDcuMDY4NEM3Ni41NDM5IDQ5LjE4NTcgNzcuNTc4IDQ5Ljg1MjEgNzkuNzg0NyA1MEg4Mi44NjM1VjI4LjUwMTZINzcuODQwMlYyNy42ODczWiIgZmlsbD0iI0FDMjMyMyIvPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTg5Ljk5MzMgNy42MjkzOWUtMDZIODAuNzU3VjQuMzk3NEg4NS43ODAzVjUuMjExNzNIODAuNzU3VjYuNjc3NTRIODMuNTExN1Y3LjMyODk5SDgwLjc1N1Y4Ljk1NzY2SDgzLjUxMTdWOS40NDYyNkg4MC43NTdWMTEuMDc0OUg4My41MTE3VjExLjcyNjRIODAuNzU3VjEzLjE5MjJIODUuNzgwM1YxMy44NDM3SDgwLjc1N1YxNS40NzIzSDgzLjUxMTdWMTYuMTIzOEg4MC43NTdWMTcuNTg5Nkg4My41MTE3VjE4LjI0MTFIODAuNzU3VjE5Ljg2OTdIODMuNTExN1YyMC41MjEySDgwLjc1N1YyMS44MjQxSDg1Ljc4MDNWMjIuNjM4NEg4MC43NTdWMjcuMDM1OEg4My44MzU4VjQzLjMyMjVIODcuMjM4NlYxMi4zNzc5SDkyLjI2MTlWOS40NDYyNkg5My4wNzIxVjEwLjA5NzdIOTkuNzE1OEM5OC45MDU2IDguNzk0NzkgOTcuMTIzMSA3LjY1NDczIDk0Ljg1NDYgNy4wMDMyN0g4OS45OTMzVjcuNjI5MzllLTA2WiIgZmlsbD0iI0FDMjMyMyIvPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTkyLjI2MTkgMTMuODQzN0g4OC4wNDg4VjQzLjMyMjVIOTIuMjYxOVYyOC41MDE2SDkzLjA3MjFWMjkuMzE2SDk0Ljg1NDZWMjUuNTdIOTMuMDcyMVYyNi4zODQ0SDkyLjI2MTlWMTMuODQzN1oiIGZpbGw9IiNBQzIzMjMiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik05NS42NjQ4IDYuMzUxOFY3LjYyOTM5ZS0wNkgxMTMuMDAzTDExOS42NDcgNi4zNTE4VjIxLjgyNDFMMTEzLjAwMyAyOC41MDE2SDEwNC45MDFMMTA0LjczOSA0My4zMjI1SDk1LjY2NDhWMTEuMDc0OUgxMDAuODVDMTAwLjUyNiA4LjYzMTkzIDk4LjkwNTYgNy4zMjkgOTUuNjY0OCA2LjM1MThaTTEwNC45MDEgNy45ODA0NkgxMTAuNTczVjIwLjUyMTJIMTA0LjkwMVY3Ljk4MDQ2WiIgZmlsbD0iI0FDMjMyMyIvPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTE0My4zMDUgNy42MjkzOWUtMDZIMTIzLjIxMlY0My4zMjI1SDE0My4zMDVWMzUuMDE2M0gxMzIuNDQ4VjI0LjQzSDE0MS42ODVWMTYuMTIzOEgxMzIuNDQ4VjcuOTgwNDZIMTQzLjMwNVY3LjYyOTM5ZS0wNloiIGZpbGw9IiNBQzIzMjMiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xNDcuMTk0IDQzLjMyMjVWNy42MjkzOWUtMDZIMTY1LjE4TDE3MS41IDUuODYzMlYxNi45MzgxTDE2Ni4xNTMgMjEuODI0MUwxNzEuNSAyNS41N1Y0My4zMjI1SDE2Mi40MjZWMjUuNTdIMTU2LjI2OFY0My4zMjI1SDE0Ny4xOTRaTTE1Ni4yNjggNy45ODA0NkgxNjIuNDI2VjE3LjU4OTZIMTU2LjI2OFY3Ljk4MDQ2WiIgZmlsbD0iI0FDMjMyMyIvPgo8L3N2Zz4K`;
2391
2453
  async function fetchLatestVersion() {
2392
2454
  try {
2393
- const endpoint = `https://unpkg.com/@oyerinde/caliper@latest/package.json`;
2455
+ const endpoint = `https://unpkg.com/@oyerinde/caliper@latest/dist/version.json`;
2394
2456
  const response = await fetch(endpoint, {
2395
2457
  method: "GET",
2396
2458
  cache: "no-store",
@@ -2463,21 +2525,13 @@
2463
2525
  :root {
2464
2526
  interpolate-size: allow-keywords;
2465
2527
  --caliper-primary: ${DEFAULT_THEME.primary};
2466
- --caliper-primary-90: ${DEFAULT_THEME.primary.replace("1)", "0.9)")};
2467
- --caliper-primary-95: ${DEFAULT_THEME.primary.replace("1)", "0.95)")};
2468
- --caliper-primary-50: ${DEFAULT_THEME.primary.replace("1)", "0.5)")};
2469
- --caliper-primary-05: ${DEFAULT_THEME.primary.replace("1)", "0.05)")};
2470
2528
  --caliper-secondary: ${DEFAULT_THEME.secondary};
2471
- --caliper-secondary-50: ${DEFAULT_THEME.secondary.replace("1)", "0.5)")};
2472
- --caliper-secondary-05: ${DEFAULT_THEME.secondary.replace("1)", "0.05)")};
2473
2529
  --caliper-calc-bg: ${DEFAULT_THEME.calcBg};
2474
2530
  --caliper-calc-shadow: ${DEFAULT_THEME.calcShadow};
2475
2531
  --caliper-calc-op-highlight: ${DEFAULT_THEME.calcOpHighlight};
2476
2532
  --caliper-calc-text: ${DEFAULT_THEME.calcText};
2477
2533
  --caliper-text: ${DEFAULT_THEME.text};
2478
2534
  --caliper-projection: ${DEFAULT_THEME.projection};
2479
- --caliper-projection-90: ${DEFAULT_THEME.projection.replace("1)", "0.9)")};
2480
- --caliper-projection-light: ${DEFAULT_THEME.projection.replace("1)", "0.2)")};
2481
2535
  --caliper-ruler: ${DEFAULT_THEME.ruler};
2482
2536
  }
2483
2537
 
@@ -3136,7 +3190,7 @@
3136
3190
  const liveSecondaryTarget = createMemo(() => {
3137
3191
  props.viewport.version;
3138
3192
  const res = props.result;
3139
- if (!(props.isAltPressed || props.isFrozen) || !res) return null;
3193
+ if (!(props.isActivatePressed || props.isFrozen) || !res) return null;
3140
3194
  return getLiveGeometry(res.secondary, res.secondaryHierarchy, res.secondaryPosition, res.secondarySticky, res.secondaryWinX, res.secondaryWinY);
3141
3195
  });
3142
3196
  createEffect(on([liveSelectionTarget, liveSecondaryTarget, () => props.animation.lerpFactor, () => props.metadata.element], ([selection, secondary, factor, element]) => {
@@ -3290,7 +3344,7 @@
3290
3344
  insert(_el$, () => data().width, _el$2);
3291
3345
  insert(_el$, () => data().height, null);
3292
3346
  createRenderEffect((_p$) => {
3293
- 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;
3347
+ var _v$ = `translate3d(${data().x - props.viewport.scrollX}px, ${data().y - props.viewport.scrollY}px, 0) translate(-50%, 0)`, _v$2 = props.isActivatePressed ? 0 : 1;
3294
3348
  _v$ !== _p$.e && setStyleProperty(_el$, "transform", _p$.e = _v$);
3295
3349
  _v$2 !== _p$.t && setStyleProperty(_el$, "opacity", _p$.t = _v$2);
3296
3350
  return _p$;
@@ -3543,6 +3597,7 @@
3543
3597
  const [draggingId, setDraggingId] = createSignal(null);
3544
3598
  const [hoveredId, setHoveredId] = createSignal(null);
3545
3599
  const [selectedIds, setSelectedIds] = createSignal(/* @__PURE__ */ new Set());
3600
+ const [rulerOrigins, setRulerOrigins] = createSignal(/* @__PURE__ */ new Map());
3546
3601
  createEffect(() => {
3547
3602
  const lines = props.state().lines;
3548
3603
  const currentIds = selectedIds();
@@ -3556,6 +3611,45 @@
3556
3611
  setSelectedIds(validIds);
3557
3612
  }
3558
3613
  });
3614
+ createEffect(() => {
3615
+ const lines = props.state().lines;
3616
+ const vp = props.viewport();
3617
+ const origins = rulerOrigins();
3618
+ let updated = false;
3619
+ const newOrigins = new Map(origins);
3620
+ lines.forEach((line) => {
3621
+ if (!newOrigins.has(line.id)) {
3622
+ newOrigins.set(line.id, {
3623
+ width: vp.width,
3624
+ height: vp.height
3625
+ });
3626
+ updated = true;
3627
+ }
3628
+ });
3629
+ const lineIds = new Set(lines.map((l) => l.id));
3630
+ newOrigins.forEach((_, id) => {
3631
+ if (!lineIds.has(id)) {
3632
+ newOrigins.delete(id);
3633
+ updated = true;
3634
+ }
3635
+ });
3636
+ if (updated) {
3637
+ setRulerOrigins(newOrigins);
3638
+ }
3639
+ });
3640
+ const getProportionalPosition = (line) => {
3641
+ const vp = props.viewport();
3642
+ const origin = rulerOrigins().get(line.id);
3643
+ if (!origin) {
3644
+ return line.position;
3645
+ }
3646
+ const isV = line.type === "vertical";
3647
+ const originDim = isV ? origin.width : origin.height;
3648
+ const currentDim = isV ? vp.width : vp.height;
3649
+ if (originDim === 0) return line.position;
3650
+ const ratio = line.position / originDim;
3651
+ return ratio * currentDim;
3652
+ };
3559
3653
  const getSnapPoints = (isV) => {
3560
3654
  const points = [];
3561
3655
  const state = props.projectionState?.();
@@ -3639,8 +3733,17 @@
3639
3733
  activeLines.forEach((line) => {
3640
3734
  const isLineV = line.type === "vertical";
3641
3735
  const max = (isLineV ? vp.width : vp.height) - 1;
3642
- let newPos = Math.max(0, Math.min(line.position + delta, max));
3736
+ const currentPos = getProportionalPosition(line);
3737
+ let newPos = Math.max(0, Math.min(currentPos + delta, max));
3643
3738
  newPos = applySnap(newPos, isLineV);
3739
+ setRulerOrigins((prev) => {
3740
+ const next = new Map(prev);
3741
+ next.set(line.id, {
3742
+ width: vp.width,
3743
+ height: vp.height
3744
+ });
3745
+ return next;
3746
+ });
3644
3747
  props.onUpdate(line.id, newPos);
3645
3748
  });
3646
3749
  }
@@ -3676,6 +3779,20 @@
3676
3779
  e.stopPropagation();
3677
3780
  setDraggingId(id);
3678
3781
  target.setPointerCapture(e.pointerId);
3782
+ const vp = props.viewport();
3783
+ const line = props.state().lines.find((l) => l.id === id);
3784
+ if (line) {
3785
+ const currentPos = getProportionalPosition(line);
3786
+ setRulerOrigins((prev) => {
3787
+ const next = new Map(prev);
3788
+ next.set(id, {
3789
+ width: vp.width,
3790
+ height: vp.height
3791
+ });
3792
+ return next;
3793
+ });
3794
+ props.onUpdate(id, currentPos);
3795
+ }
3679
3796
  if (e.shiftKey) {
3680
3797
  setSelectedIds((prev) => {
3681
3798
  const next = new Set(prev);
@@ -3689,10 +3806,10 @@
3689
3806
  }
3690
3807
  }
3691
3808
  const onPointerMove = (moveEvent) => {
3692
- const vp = props.viewport();
3809
+ const vp2 = props.viewport();
3693
3810
  const isV = type === "vertical";
3694
3811
  let pos = isV ? moveEvent.clientX : moveEvent.clientY;
3695
- const max = (isV ? vp.width : vp.height) - 1;
3812
+ const max = (isV ? vp2.width : vp2.height) - 1;
3696
3813
  pos = Math.max(0, Math.min(pos, max));
3697
3814
  pos = applySnap(pos, isV);
3698
3815
  props.onUpdate(id, pos);
@@ -3731,42 +3848,48 @@
3731
3848
  const ids = selectedIds();
3732
3849
  if (ids.size < 2) return [];
3733
3850
  const lines = props.state().lines.filter((l) => ids.has(l.id));
3734
- const vLines = lines.filter((l) => l.type === "vertical").sort((a, b) => a.position - b.position);
3735
- const hLines = lines.filter((l) => l.type === "horizontal").sort((a, b) => a.position - b.position);
3851
+ const vLinesWithPos = lines.filter((l) => l.type === "vertical").map((l) => ({
3852
+ line: l,
3853
+ pos: getProportionalPosition(l)
3854
+ })).sort((a, b) => a.pos - b.pos);
3855
+ const hLinesWithPos = lines.filter((l) => l.type === "horizontal").map((l) => ({
3856
+ line: l,
3857
+ pos: getProportionalPosition(l)
3858
+ })).sort((a, b) => a.pos - b.pos);
3736
3859
  const result = [];
3737
3860
  const vp = props.viewport();
3738
- for (let i = 0; i < vLines.length - 1; i++) {
3739
- const l1 = vLines[i];
3740
- const l2 = vLines[i + 1];
3741
- const val = l2.position - l1.position;
3861
+ for (let i = 0; i < vLinesWithPos.length - 1; i++) {
3862
+ const l1 = vLinesWithPos[i];
3863
+ const l2 = vLinesWithPos[i + 1];
3864
+ const val = l2.pos - l1.pos;
3742
3865
  if (val > 0) {
3743
3866
  result.push({
3744
- x1: l1.position,
3867
+ x1: l1.pos,
3745
3868
  y1: vp.height / 2 + 100,
3746
3869
  // Move default bridge line off center for better visibility
3747
- x2: l2.position,
3870
+ x2: l2.pos,
3748
3871
  y2: vp.height / 2 + 100,
3749
3872
  value: val,
3750
3873
  type: "vertical",
3751
- labelX: l1.position + val / 2,
3874
+ labelX: l1.pos + val / 2,
3752
3875
  labelY: vp.height / 2 + 85
3753
3876
  });
3754
3877
  }
3755
3878
  }
3756
- for (let i = 0; i < hLines.length - 1; i++) {
3757
- const l1 = hLines[i];
3758
- const l2 = hLines[i + 1];
3759
- const val = l2.position - l1.position;
3879
+ for (let i = 0; i < hLinesWithPos.length - 1; i++) {
3880
+ const l1 = hLinesWithPos[i];
3881
+ const l2 = hLinesWithPos[i + 1];
3882
+ const val = l2.pos - l1.pos;
3760
3883
  if (val > 0) {
3761
3884
  result.push({
3762
3885
  x1: vp.width / 2 + 100,
3763
- y1: l1.position,
3886
+ y1: l1.pos,
3764
3887
  x2: vp.width / 2 + 100,
3765
- y2: l2.position,
3888
+ y2: l2.pos,
3766
3889
  value: val,
3767
3890
  type: "horizontal",
3768
3891
  labelX: vp.width / 2 + 115,
3769
- labelY: l1.position + val / 2
3892
+ labelY: l1.pos + val / 2
3770
3893
  });
3771
3894
  }
3772
3895
  }
@@ -3854,6 +3977,9 @@
3854
3977
  },
3855
3978
  children: (line) => createComponent(RulerLineItem, {
3856
3979
  line,
3980
+ get pixelPosition() {
3981
+ return getProportionalPosition(line);
3982
+ },
3857
3983
  get isDragging() {
3858
3984
  return draggingId() === line.id;
3859
3985
  },
@@ -3877,7 +4003,7 @@
3877
4003
  function RulerLineItem(props) {
3878
4004
  const lineStyle = createMemo(() => {
3879
4005
  const isV = props.line.type === "vertical";
3880
- const pos = props.line.position;
4006
+ const pos = props.pixelPosition;
3881
4007
  const isActive = props.isDragging || props.isHovered || props.isSelected;
3882
4008
  return {
3883
4009
  left: "0",
@@ -3896,7 +4022,7 @@
3896
4022
  var _el$9 = _tmpl$43();
3897
4023
  className(_el$9, `${PREFIX}ruler-line-hit`);
3898
4024
  createRenderEffect((_p$) => {
3899
- 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";
4025
+ 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.pixelPosition - hitOffset() : 0}px, ${props.line.type === "vertical" ? 0 : props.pixelPosition - hitOffset()}px, 0)`, _v$16 = props.line.type === "vertical" ? "col-resize" : "row-resize";
3900
4026
  _v$11 !== _p$.e && setAttribute(_el$9, "data-ruler-id", _p$.e = _v$11);
3901
4027
  _v$12 !== _p$.t && setAttribute(_el$9, "data-ruler-type", _p$.t = _v$12);
3902
4028
  _v$13 !== _p$.a && setStyleProperty(_el$9, "width", _p$.a = _v$13);
@@ -3930,29 +4056,30 @@
3930
4056
  e.stopPropagation();
3931
4057
  const isV = props.line.type === "vertical";
3932
4058
  const vp = props.viewport();
4059
+ const pos = props.pixelPosition;
3933
4060
  props.onLineClick?.({
3934
4061
  type: "distance",
3935
- value: props.line.position,
4062
+ value: pos,
3936
4063
  start: isV ? {
3937
- x: props.line.position,
4064
+ x: pos,
3938
4065
  y: 0
3939
4066
  } : {
3940
4067
  x: 0,
3941
- y: props.line.position
4068
+ y: pos
3942
4069
  },
3943
4070
  end: isV ? {
3944
- x: props.line.position,
4071
+ x: pos,
3945
4072
  y: vp.height
3946
4073
  } : {
3947
4074
  x: vp.width,
3948
- y: props.line.position
4075
+ y: pos
3949
4076
  }
3950
- }, props.line.position);
4077
+ }, pos);
3951
4078
  };
3952
4079
  className(_el$1, `${PREFIX}label ${PREFIX}ruler-label`);
3953
- insert(_el$1, () => Math.round(props.line.position * 100) / 100);
4080
+ insert(_el$1, () => Math.round(props.pixelPosition * 100) / 100);
3954
4081
  createRenderEffect((_p$) => {
3955
- 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";
4082
+ var _v$17 = `translate3d(${props.line.type === "vertical" ? props.pixelPosition + 10 : 20}px, ${props.line.type === "vertical" ? 20 : props.pixelPosition + 10}px, 0)`, _v$18 = props.isSelected && !props.isHovered && !props.isDragging ? "0.7" : "1";
3956
4083
  _v$17 !== _p$.e && setStyleProperty(_el$1, "transform", _p$.e = _v$17);
3957
4084
  _v$18 !== _p$.t && setStyleProperty(_el$1, "opacity", _p$.t = _v$18);
3958
4085
  return _p$;
@@ -3993,8 +4120,8 @@
3993
4120
  get result() {
3994
4121
  return props.result();
3995
4122
  },
3996
- get isAltPressed() {
3997
- return props.isAltPressed();
4123
+ get isActivatePressed() {
4124
+ return props.isActivatePressed();
3998
4125
  },
3999
4126
  get isFrozen() {
4000
4127
  return props.isFrozen();
@@ -4009,15 +4136,15 @@
4009
4136
  get metadata() {
4010
4137
  return props.selectionMetadata();
4011
4138
  },
4012
- get isAltPressed() {
4013
- return props.isAltPressed();
4139
+ get isActivatePressed() {
4140
+ return props.isActivatePressed();
4014
4141
  },
4015
4142
  get viewport() {
4016
4143
  return props.viewport();
4017
4144
  }
4018
4145
  }), createComponent(Show, {
4019
4146
  get when() {
4020
- return memo(() => !!(props.isAltPressed() || props.isFrozen()))() && resultData();
4147
+ return memo(() => !!(props.isActivatePressed() || props.isFrozen()))() && resultData();
4021
4148
  },
4022
4149
  get children() {
4023
4150
  return createComponent(Portal, {
@@ -4204,12 +4331,34 @@
4204
4331
  const [rulerState, setRulerState] = createSignal({
4205
4332
  lines: []
4206
4333
  });
4207
- const [isAltPressed, setIsAltPressed] = createSignal(false);
4334
+ const [isActivatePressed, setIsActivatePressed] = createSignal(false);
4208
4335
  const [isFrozen, setIsFrozen] = createSignal(false);
4336
+ const ignoredElements = /* @__PURE__ */ new WeakSet();
4209
4337
  let viewportRafId = null;
4210
4338
  let resizeObserver = null;
4339
+ let observedRoot = false;
4211
4340
  let observedPrimary = null;
4212
4341
  let observedSecondary = null;
4342
+ const resetCalculatorUI = () => {
4343
+ setCalculatorState(null);
4344
+ setActiveCalculatorLine(null);
4345
+ if (projectionState().direction !== null) {
4346
+ setActiveInputFocus("projection");
4347
+ }
4348
+ };
4349
+ const syncCalculatorUI = (state) => {
4350
+ if (!state.isActive) {
4351
+ resetCalculatorUI();
4352
+ return;
4353
+ }
4354
+ setCalculatorState(state);
4355
+ if (state.operation) {
4356
+ setActiveCalculatorLine(null);
4357
+ }
4358
+ };
4359
+ const isActive = createMemo(() => {
4360
+ return !!selectionMetadata().element || !!result() || rulerState().lines.length > 0 || projectionState().direction !== null;
4361
+ });
4213
4362
  const syncViewport = () => {
4214
4363
  setViewport((prev) => ({
4215
4364
  scrollX: window.scrollX,
@@ -4221,6 +4370,7 @@
4221
4370
  viewportRafId = null;
4222
4371
  };
4223
4372
  const scheduleUpdate = () => {
4373
+ if (!isActive()) return;
4224
4374
  if (!viewportRafId) {
4225
4375
  viewportRafId = requestAnimationFrame(syncViewport);
4226
4376
  }
@@ -4238,6 +4388,8 @@
4238
4388
  if (system?.getState() === "FROZEN") {
4239
4389
  system?.unfreeze(false);
4240
4390
  }
4391
+ } else {
4392
+ setActiveInputFocus("projection");
4241
4393
  }
4242
4394
  });
4243
4395
  rulerSystem = createRulerSystem();
@@ -4249,8 +4401,6 @@
4249
4401
  setResult(system.getCurrentResult());
4250
4402
  setIsFrozen(system.getState() === "FROZEN");
4251
4403
  });
4252
- const currentResult = system.getCurrentResult();
4253
- setResult(currentResult);
4254
4404
  const unsubscribeUpdate = selectionSystem.onUpdate((metadata) => {
4255
4405
  setSelectionMetadata(metadata);
4256
4406
  });
@@ -4262,16 +4412,14 @@
4262
4412
  const performSelection = (x, y) => {
4263
4413
  const element = getTopElementAtPoint(x, y);
4264
4414
  if (element && selectionSystem) {
4265
- setResult(null);
4266
- setCalculatorState(null);
4267
- setActiveInputFocus("calculator");
4268
- if (projectionSystem) {
4269
- projectionSystem.clear();
4270
- }
4271
4415
  if (system) {
4272
4416
  system.abort();
4273
- system.getCalculator().close();
4274
4417
  }
4418
+ if (projectionSystem) {
4419
+ projectionSystem.clear();
4420
+ }
4421
+ resetCalculatorUI();
4422
+ setActiveInputFocus("calculator");
4275
4423
  lastHoveredElement = null;
4276
4424
  selectionDelegate.cancel();
4277
4425
  measureDelegate.cancel();
@@ -4297,6 +4445,9 @@
4297
4445
  }
4298
4446
  return isSelectKeyDown() && !ctrlKey && !metaKey && !altKey && !shiftKey;
4299
4447
  };
4448
+ const isActivateActive = (e) => {
4449
+ return e.key === commands.activate || commands.activate === "Alt" && (e.key === "Alt" || e.key === "AltGraph");
4450
+ };
4300
4451
  const handlePointerDown = (e) => {
4301
4452
  lastPointerPos = {
4302
4453
  x: e.clientX,
@@ -4336,6 +4487,9 @@
4336
4487
  let mouseMoveRafId = null;
4337
4488
  let lastHoveredElement = null;
4338
4489
  const selectionDelegate = createSuppressionDelegate((el) => {
4490
+ if (selectionSystem?.getSelected() !== el) {
4491
+ system?.abort();
4492
+ }
4339
4493
  lastHoveredElement = el;
4340
4494
  selectionSystem?.select(el);
4341
4495
  });
@@ -4357,7 +4511,7 @@
4357
4511
  };
4358
4512
  setCursor(cursorPoint);
4359
4513
  const selectedElement = selectionSystem.getSelected();
4360
- const isAlt = isAltPressed();
4514
+ const isAlt = isActivatePressed();
4361
4515
  const state = system?.getState();
4362
4516
  if (selectedElement) {
4363
4517
  const hoveredElement = getTopElementAtPoint(e.clientX, e.clientY);
@@ -4385,15 +4539,14 @@
4385
4539
  }
4386
4540
  };
4387
4541
  const handleKeyDown = (e) => {
4388
- if (e.key === commands.clear) {
4389
- setIsAltPressed(false);
4390
- setCalculatorState(null);
4391
- setActiveCalculatorLine(null);
4392
- if (selectionSystem) {
4393
- lastHoveredElement = null;
4394
- selectionDelegate.cancel();
4395
- measureDelegate.cancel();
4396
- selectionSystem.clear();
4542
+ if (e.key === commands.clear && !isEditable(e.target)) {
4543
+ if (!isActive()) return;
4544
+ e.preventDefault();
4545
+ e.stopImmediatePropagation();
4546
+ setIsActivatePressed(false);
4547
+ resetCalculatorUI();
4548
+ if (system) {
4549
+ system.abort();
4397
4550
  }
4398
4551
  if (projectionSystem) {
4399
4552
  projectionSystem.clear();
@@ -4401,18 +4554,18 @@
4401
4554
  if (rulerSystem) {
4402
4555
  rulerSystem.clear();
4403
4556
  }
4404
- if (system) {
4405
- system.abort();
4406
- const calc = system.getCalculator();
4407
- calc.close();
4408
- setResult(null);
4557
+ if (selectionSystem) {
4558
+ lastHoveredElement = null;
4559
+ selectionDelegate.cancel();
4560
+ measureDelegate.cancel();
4561
+ selectionSystem.clear();
4409
4562
  }
4410
4563
  return;
4411
4564
  }
4412
- if (e.key === commands.select) {
4565
+ if (e.key === commands.select && !isEditable(e.target)) {
4413
4566
  setIsSelectKeyDown(true);
4414
4567
  }
4415
- if (e.key.toLowerCase() === commands.ruler && e.shiftKey && rulerSystem) {
4568
+ if (e.key.toLowerCase() === commands.ruler.toLowerCase() && e.shiftKey && rulerSystem && !isEditable(e.target)) {
4416
4569
  e.preventDefault();
4417
4570
  const vp = viewport();
4418
4571
  const x = Math.max(0, Math.min(cursor().x, vp.width));
@@ -4420,31 +4573,34 @@
4420
4573
  rulerSystem.addPair(x, y);
4421
4574
  return;
4422
4575
  }
4423
- const isAltKey = e.key === "Alt" || e.key === "AltGraph" || e.key === commands.activate;
4424
- if (isAltKey) {
4425
- e.preventDefault();
4426
- if (!isAltPressed()) {
4576
+ if (isActivateActive(e)) {
4577
+ if (selectionMetadata().element) {
4578
+ e.preventDefault();
4579
+ e.stopImmediatePropagation();
4580
+ }
4581
+ if (!isActivatePressed() && isActive()) {
4427
4582
  if (system) {
4428
4583
  system.abort();
4429
- setResult(null);
4430
- handleCalculatorClose();
4431
4584
  }
4432
4585
  if (projectionSystem) {
4433
4586
  projectionSystem.clear();
4434
4587
  }
4588
+ resetCalculatorUI();
4435
4589
  }
4436
- setIsAltPressed(true);
4437
- } else if (e.key === commands.freeze && e.target === document.body && system) {
4590
+ setIsActivatePressed(true);
4591
+ } else if (e.key === commands.freeze && !isEditable(e.target) && system) {
4438
4592
  const state = system.getState();
4439
4593
  if (state === "FROZEN") {
4440
4594
  e.preventDefault();
4441
- system.unfreeze(isAltPressed());
4595
+ e.stopImmediatePropagation();
4596
+ system.unfreeze(isActivatePressed());
4442
4597
  } else if (selectionMetadata().element) {
4443
4598
  e.preventDefault();
4599
+ e.stopImmediatePropagation();
4444
4600
  system.freeze();
4445
4601
  }
4446
4602
  } else {
4447
- const key = e.key.toLowerCase();
4603
+ const key = e.key;
4448
4604
  const {
4449
4605
  calculator,
4450
4606
  projection
@@ -4480,7 +4636,7 @@
4480
4636
  [projection.right]: "right"
4481
4637
  };
4482
4638
  const dir = dirMap[key];
4483
- if (dir && selectionMetadata().element) {
4639
+ if (dir && selectionMetadata().element && !isEditable(e.target)) {
4484
4640
  e.preventDefault();
4485
4641
  e.stopImmediatePropagation();
4486
4642
  setActiveInputFocus("projection");
@@ -4534,10 +4690,11 @@
4534
4690
  };
4535
4691
  const targetType = typeMap[key];
4536
4692
  if (targetType) {
4537
- e.preventDefault();
4538
4693
  const currentLines = result()?.lines || [];
4539
4694
  const targetLine = currentLines.find((l) => l.type === targetType);
4540
4695
  if (targetLine) {
4696
+ e.preventDefault();
4697
+ e.stopImmediatePropagation();
4541
4698
  const liveValue = getLiveLineValue(targetLine, result());
4542
4699
  handleLineClick(targetLine, liveValue);
4543
4700
  }
@@ -4549,26 +4706,29 @@
4549
4706
  if (e.key === commands.select) {
4550
4707
  setIsSelectKeyDown(false);
4551
4708
  }
4552
- const isAltKey = e.key === "Alt" || e.key === "AltGraph" || e.key === commands.activate;
4553
- if (isAltKey) {
4709
+ if (isActivateActive(e)) {
4554
4710
  e.preventDefault();
4555
- if (isAltPressed()) {
4556
- setIsAltPressed(false);
4557
- if (system) {
4711
+ if (isActivatePressed()) {
4712
+ setIsActivatePressed(false);
4713
+ if (system && isActive()) {
4558
4714
  system.stop();
4559
4715
  }
4560
4716
  }
4561
4717
  }
4562
4718
  };
4563
4719
  const handleBlur = () => {
4564
- if (isAltPressed()) {
4565
- setIsAltPressed(false);
4566
- if (system) {
4720
+ if (isActivatePressed()) {
4721
+ setIsActivatePressed(false);
4722
+ if (system && isActive()) {
4567
4723
  system.stop();
4568
- setResult(null);
4569
4724
  }
4570
4725
  }
4571
4726
  };
4727
+ const handleFocus = () => {
4728
+ if (!isActive()) return;
4729
+ scheduleUpdate();
4730
+ window.focus();
4731
+ };
4572
4732
  window.addEventListener("pointerdown", handlePointerDown, {
4573
4733
  capture: true
4574
4734
  });
@@ -4586,6 +4746,7 @@
4586
4746
  capture: true
4587
4747
  });
4588
4748
  window.addEventListener("blur", handleBlur);
4749
+ window.addEventListener("focus", handleFocus);
4589
4750
  onCleanup(() => {
4590
4751
  window.removeEventListener("pointerdown", handlePointerDown, {
4591
4752
  capture: true
@@ -4604,6 +4765,7 @@
4604
4765
  capture: true
4605
4766
  });
4606
4767
  window.removeEventListener("blur", handleBlur);
4768
+ window.removeEventListener("focus", handleFocus);
4607
4769
  if (mouseMoveRafId) {
4608
4770
  cancelAnimationFrame(mouseMoveRafId);
4609
4771
  }
@@ -4613,7 +4775,9 @@
4613
4775
  unsubscribeUpdate();
4614
4776
  unsubscribeProjection();
4615
4777
  unsubscribeRuler();
4616
- handleCleanup();
4778
+ if (system) {
4779
+ system.cleanup();
4780
+ }
4617
4781
  if (projectionSystem) {
4618
4782
  projectionSystem = null;
4619
4783
  }
@@ -4623,8 +4787,7 @@
4623
4787
  });
4624
4788
  });
4625
4789
  createEffect(() => {
4626
- const active = !!selectionMetadata().element || !!result();
4627
- if (active) {
4790
+ if (isActive()) {
4628
4791
  window.addEventListener("scroll", scheduleUpdate, {
4629
4792
  passive: true,
4630
4793
  capture: true
@@ -4641,8 +4804,15 @@
4641
4804
  });
4642
4805
  }
4643
4806
  });
4644
- const updateResizeObservations = (primaryEl, secondaryEl) => {
4807
+ const updateResizeObservations = (active, primaryEl, secondaryEl) => {
4645
4808
  if (!resizeObserver) return;
4809
+ if (active && !observedRoot) {
4810
+ resizeObserver.observe(document.documentElement);
4811
+ observedRoot = true;
4812
+ } else if (!active && observedRoot) {
4813
+ resizeObserver.unobserve(document.documentElement);
4814
+ observedRoot = false;
4815
+ }
4646
4816
  if (primaryEl === observedPrimary && secondaryEl === observedSecondary) {
4647
4817
  return;
4648
4818
  }
@@ -4655,10 +4825,12 @@
4655
4825
  observedSecondary = null;
4656
4826
  }
4657
4827
  if (primaryEl && primaryEl !== observedPrimary) {
4828
+ ignoredElements.add(primaryEl);
4658
4829
  resizeObserver.observe(primaryEl);
4659
4830
  observedPrimary = primaryEl;
4660
4831
  }
4661
4832
  if (secondaryEl && secondaryEl !== primaryEl && secondaryEl !== observedSecondary) {
4833
+ ignoredElements.add(secondaryEl);
4662
4834
  resizeObserver.observe(secondaryEl);
4663
4835
  observedSecondary = secondaryEl;
4664
4836
  }
@@ -4688,6 +4860,16 @@
4688
4860
  secondaryChanged = false;
4689
4861
  };
4690
4862
  resizeObserver = new ResizeObserver((entries) => {
4863
+ if (!isActive()) return;
4864
+ let hasActualResize = false;
4865
+ for (const entry of entries) {
4866
+ if (ignoredElements.has(entry.target)) {
4867
+ ignoredElements.delete(entry.target);
4868
+ continue;
4869
+ }
4870
+ hasActualResize = true;
4871
+ }
4872
+ if (!hasActualResize) return;
4691
4873
  for (const entry of entries) {
4692
4874
  if (entry.target === document.documentElement) {
4693
4875
  sentinelResized = true;
@@ -4714,7 +4896,6 @@
4714
4896
  }, remaining);
4715
4897
  }
4716
4898
  });
4717
- resizeObserver.observe(document.documentElement);
4718
4899
  onCleanup(() => {
4719
4900
  resizeObserver?.disconnect();
4720
4901
  resizeObserver = null;
@@ -4724,14 +4905,15 @@
4724
4905
  });
4725
4906
  });
4726
4907
  createEffect(() => {
4908
+ const active = isActive();
4727
4909
  const primaryEl = selectionMetadata().element;
4728
4910
  const currentResult = result();
4729
4911
  const secondaryEl = isFrozen() ? currentResult?.secondaryElement ?? null : null;
4730
- if (!primaryEl && !secondaryEl) {
4731
- updateResizeObservations(null, null);
4912
+ if (!active) {
4913
+ updateResizeObservations(false, null, null);
4732
4914
  return;
4733
4915
  }
4734
- updateResizeObservations(primaryEl, secondaryEl);
4916
+ updateResizeObservations(true, primaryEl, secondaryEl);
4735
4917
  });
4736
4918
  createEffect(() => {
4737
4919
  const calcLine = activeCalculatorLine();
@@ -4752,12 +4934,10 @@
4752
4934
  });
4753
4935
  const handleLineClick = (line, liveValue) => {
4754
4936
  if (system) {
4755
- setActiveCalculatorLine(null);
4756
4937
  const calc = system.getCalculator();
4757
4938
  calc.open(liveValue);
4758
4939
  setActiveInputFocus("calculator");
4759
- const calcState = calc.getState();
4760
- setCalculatorState(calcState.isActive ? calcState : null);
4940
+ syncCalculatorUI(calc.getState());
4761
4941
  if ("startSync" in line) {
4762
4942
  setActiveCalculatorLine(line);
4763
4943
  }
@@ -4770,67 +4950,35 @@
4770
4950
  if (/^[+\-*/.]$/.test(key)) {
4771
4951
  setActiveInputFocus("calculator");
4772
4952
  }
4773
- const calcState = calc.getState();
4774
- const isActive = calcState.isActive;
4775
- setCalculatorState(isActive ? calcState : null);
4776
- if (calcState.operation) {
4777
- setActiveCalculatorLine(null);
4778
- }
4779
- if (!isActive && projectionState().direction !== null) {
4780
- setActiveInputFocus("projection");
4781
- }
4953
+ syncCalculatorUI(calc.getState());
4782
4954
  }
4783
4955
  };
4784
4956
  const handleCalculatorBackspace = () => {
4785
4957
  if (system) {
4786
4958
  const calc = system.getCalculator();
4787
4959
  calc.handleBackspace();
4788
- const calcState = calc.getState();
4789
- const isActive = calcState.isActive;
4790
- setCalculatorState(isActive ? calcState : null);
4791
- if (!isActive) {
4792
- setActiveCalculatorLine(null);
4793
- if (projectionState().direction !== null) {
4794
- setActiveInputFocus("projection");
4795
- }
4796
- }
4960
+ syncCalculatorUI(calc.getState());
4797
4961
  }
4798
4962
  };
4799
4963
  const handleCalculatorDelete = () => {
4800
4964
  if (system) {
4801
4965
  const calc = system.getCalculator();
4802
4966
  calc.handleDelete();
4803
- const calcState = calc.getState();
4804
- const isActive = calcState.isActive;
4805
- setCalculatorState(isActive ? calcState : null);
4806
- setActiveCalculatorLine(null);
4807
- if (!isActive && projectionState().direction !== null) {
4808
- setActiveInputFocus("projection");
4809
- }
4967
+ syncCalculatorUI(calc.getState());
4810
4968
  }
4811
4969
  };
4812
4970
  const handleCalculatorEnter = () => {
4813
4971
  if (system) {
4814
4972
  const calc = system.getCalculator();
4815
4973
  calc.handleEnter();
4816
- const calcState = calc.getState();
4817
- const isActive = calcState.isActive;
4818
- setCalculatorState(isActive ? calcState : null);
4819
- setActiveCalculatorLine(null);
4820
- if (!isActive && projectionState().direction !== null) {
4821
- setActiveInputFocus("projection");
4822
- }
4974
+ syncCalculatorUI(calc.getState());
4823
4975
  }
4824
4976
  };
4825
4977
  const handleCalculatorClose = () => {
4826
4978
  if (system) {
4827
4979
  const calc = system.getCalculator();
4828
4980
  calc.close();
4829
- setCalculatorState(null);
4830
- setActiveCalculatorLine(null);
4831
- if (projectionState().direction !== null) {
4832
- setActiveInputFocus("projection");
4833
- }
4981
+ resetCalculatorUI();
4834
4982
  }
4835
4983
  };
4836
4984
  const handleRulerUpdate = (id, position) => {
@@ -4839,17 +4987,11 @@
4839
4987
  const handleRulerRemove = (id) => {
4840
4988
  rulerSystem?.removeLine(id);
4841
4989
  };
4842
- const handleCleanup = () => {
4843
- if (system) system.cleanup();
4844
- if (selectionSystem) selectionSystem.clear();
4845
- if (projectionSystem) projectionSystem.clear();
4846
- if (rulerSystem) rulerSystem.clear();
4847
- };
4848
4990
  return createComponent(Overlay, {
4849
4991
  result,
4850
4992
  cursor,
4851
4993
  selectionMetadata,
4852
- isAltPressed,
4994
+ isActivatePressed,
4853
4995
  isFrozen,
4854
4996
  animation,
4855
4997
  viewport,
@@ -4940,6 +5082,7 @@
4940
5082
  };
4941
5083
  const commands = mergeCommands(mergedConfig.commands);
4942
5084
  const animation = mergeAnimation(mergedConfig.animation);
5085
+ const theme = mergeTheme(mergedConfig.theme);
4943
5086
  let cleanup = null;
4944
5087
  const instance = {
4945
5088
  mounted: false,
@@ -4949,9 +5092,7 @@
4949
5092
  instance.mounted = true;
4950
5093
  return;
4951
5094
  }
4952
- if (mergedConfig.theme) {
4953
- applyTheme(mergedConfig.theme);
4954
- }
5095
+ applyTheme(theme);
4955
5096
  const target = container || document.body;
4956
5097
  injectStyles();
4957
5098
  const overlayContainer = document.createElement("div");
@@ -4982,7 +5123,7 @@
4982
5123
  return instance;
4983
5124
  }
4984
5125
  if (IS_BROWSER2) {
4985
- showVersionInfo("0.1.0").catch(() => {
5126
+ showVersionInfo("0.1.2").catch(() => {
4986
5127
  });
4987
5128
  }
4988
5129