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