@oyerinde/caliper 0.1.0 → 0.1.1

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