var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var node_exports = {};
__export(node_exports, {
  ActionControls: () => ActionControls,
  Globe: () => Globe,
  GlobeContextProvider: () => GlobeContextProvider,
  Map: () => Map,
  ZoomControls: () => ZoomControls,
  closestPoint: () => closestPoint,
  controlPositions: () => controlPositions,
  createLayers: () => createLayers,
  geoCircle: () => geoCircle,
  geoInertiaDrag: () => geoInertiaDrag,
  geoLine: () => geoLine,
  geoPoint: () => geoPoint,
  geoToPosition: () => geoToPosition,
  getDistance: () => getDistance,
  loadTopology: () => import_chunk_LAICG6L2.loadTopology,
  positionToRotation: () => positionToRotation,
  renderLayers: () => renderLayers,
  restrictAxis: () => restrictAxis,
  timer: () => timer,
  useDrag: () => useDrag,
  useGlobeContext: () => useGlobeContext,
  useGlobeZoomHandler: () => useGlobeZoomHandler,
  useMapZoomHandler: () => useMapZoomHandler,
  useSpinner: () => useSpinner,
  useTour: () => useTour
});
module.exports = __toCommonJS(node_exports);
var import_chunk_LAICG6L2 = require("./chunk-LAICG6L2.cjs");
var import_tracking = require("@preact-signals/safe-react/tracking");
var import_d3 = require("d3");
var import_react = __toESM(require("react"));
var import_react_resize_detector = require("react-resize-detector");
var import_react_ui = require("@dxos/react-ui");
var import_react_ui_theme = require("@dxos/react-ui-theme");
var import_tracking2 = require("@preact-signals/safe-react/tracking");
var import_react2 = __toESM(require("react"));
var import_debug = require("@dxos/debug");
var import_react_ui2 = require("@dxos/react-ui");
var import_d32 = require("d3");
var import_react3 = require("react");
var import_d33 = require("d3");
var import_versor = __toESM(require("versor"));
var import_d34 = require("d3");
var import_d35 = require("d3");
var import_topojson_client = require("topojson-client");
var import_react4 = require("react");
var import_react5 = require("react");
var import_d36 = require("d3");
var import_react6 = require("react");
var import_d37 = require("d3");
var import_react7 = require("react");
var import_versor2 = __toESM(require("versor"));
var import_tracking3 = require("@preact-signals/safe-react/tracking");
var import_react8 = __toESM(require("react"));
var import_react_ui3 = require("@dxos/react-ui");
var import_tracking4 = require("@preact-signals/safe-react/tracking");
var import_leaflet = require("leaflet/dist/leaflet.css");
var import_leaflet2 = __toESM(require("leaflet"));
var import_react9 = __toESM(require("react"));
var import_client = require("react-dom/client");
var import_react_leaflet = require("react-leaflet");
var import_react_resize_detector2 = require("react-resize-detector");
var import_async = require("@dxos/async");
var import_react_ui4 = require("@dxos/react-ui");
var import_react_ui_theme2 = require("@dxos/react-ui-theme");
var GlobeContext = /* @__PURE__ */ (0, import_react2.createContext)(void 0);
var GlobeContextProvider = ({ children, size, center: _center, scale: _scale, translation: _translation, rotation: _rotation }) => {
  var _effect = (0, import_tracking2.useSignals)();
  try {
    const [center, setCenter] = (0, import_react_ui2.useControlledState)(_center);
    const [scale, setScale] = (0, import_react_ui2.useControlledState)(_scale);
    const [translation, setTranslation] = (0, import_react_ui2.useControlledState)(_translation);
    const [rotation, setRotation] = (0, import_react_ui2.useControlledState)(_rotation);
    return /* @__PURE__ */ import_react2.default.createElement(GlobeContext.Provider, {
      value: {
        size,
        center,
        scale,
        translation,
        rotation,
        setCenter,
        setScale,
        setTranslation,
        setRotation
      }
    }, children);
  } finally {
    _effect.f();
  }
};
var useGlobeContext = () => {
  return (0, import_react2.useContext)(GlobeContext) ?? (0, import_debug.raise)(new Error("Missing GlobeContext"));
};
var debug = false;
var timer = (cb) => {
  const start = Date.now();
  const data = cb();
  const t = Date.now() - start / 1e3;
  if (debug) {
    console.log({
      t,
      data
    });
  }
  return data;
};
var restrictAxis = (axis) => (original, current) => current.map((d, i) => axis[i] ? d : original[i]);
var geoInertiaDrag = (target, render, projection, options) => {
  if (!options) {
    options = {};
  }
  if (target.node) {
    target = target.node();
  }
  target = (0, import_d33.select)(target);
  const inertia = geoInertiaDragHelper({
    projection,
    render: (rotation) => {
      projection.rotate(rotation);
      render && render();
    },
    axis: restrictAxis(options.xAxis ? [
      true,
      false,
      false
    ] : [
      true,
      true,
      true
    ]),
    start: options.start,
    move: options.move,
    end: options.end,
    stop: options.stop,
    finish: options.finish,
    time: options.time,
    hold: options.hold
  });
  target.call((0, import_d33.drag)().on("start", inertia.start).on("drag", inertia.move).on("end", inertia.end));
  return inertia;
};
var geoInertiaDragHelper = (opt) => {
  const projection = opt.projection;
  let v0;
  let r0;
  let q0;
  let v10;
  let v11;
  let q10;
  const inertia = inertiaHelper({
    axis: opt.axis,
    start: () => {
      v0 = import_versor.default.cartesian(projection.invert(inertia.position));
      r0 = projection.rotate();
      q0 = (0, import_versor.default)(r0);
      opt.start && opt.start();
    },
    move: () => {
      const inv = projection.rotate(r0).invert(inertia.position);
      if (isNaN(inv[0])) {
        return;
      }
      const v1 = import_versor.default.cartesian(inv);
      const q1 = import_versor.default.multiply(q0, import_versor.default.delta(v0, v1));
      const r1 = import_versor.default.rotation(q1);
      const r2 = opt.axis(r0, r1);
      opt.render(r2);
      opt.move && opt.move();
    },
    end: () => {
      v10 = import_versor.default.cartesian(projection.invert(inertia.position.map((d, i) => d - inertia.velocity[i] / 1e3)));
      q10 = (0, import_versor.default)(projection.rotate());
      v11 = import_versor.default.cartesian(projection.invert(inertia.position));
      opt.end && opt.end();
    },
    stop: opt.stop,
    finish: opt.finish,
    render: (t) => {
      const r1 = import_versor.default.rotation(import_versor.default.multiply(q10, import_versor.default.delta(v10, v11, t * 1e3)));
      const r2 = opt.axis(r0, r1);
      opt.render && opt.render(r2);
    },
    time: opt.time
  });
  return inertia;
};
function inertiaHelper(opt) {
  const A = opt.time || 5e3;
  const limit = 1.0001;
  const B = -Math.log(1 - 1 / limit);
  const inertia = {
    position: [
      0,
      0
    ],
    velocity: [
      0,
      0
    ],
    timer: (0, import_d33.timer)(() => {
    }),
    time: 0,
    t: 0,
    start: function(ev) {
      const position = [
        ev.x,
        ev.y
      ];
      inertia.position = position;
      inertia.velocity = [
        0,
        0
      ];
      inertia.timer.stop();
      this.classList.remove("inertia");
      this.classList.add("dragging");
      opt.start && opt.start.call(this, position);
    },
    move: function(ev) {
      const position = [
        ev.x,
        ev.y
      ];
      const time = performance.now();
      const deltaTime = time - inertia.time;
      const decay = 1 - Math.exp(-deltaTime / 1e3);
      inertia.velocity = inertia.velocity.map((d, i) => {
        const deltaPos = position[i] - inertia.position[i];
        const deltaTime2 = time - inertia.time;
        return 1e3 * (1 - decay) * deltaPos / deltaTime2 + d * decay;
      });
      inertia.velocity = opt.axis([
        0,
        0
      ], inertia.velocity);
      inertia.time = time;
      inertia.position = position;
      opt.move && opt.move.call(this, position);
    },
    end: function(ev) {
      this.classList.remove("dragging", "inertia");
      const v = inertia.velocity;
      if (v[0] * v[0] + v[1] * v[1] < 100) {
        inertia.timer.stop();
        return opt.stop && opt.stop();
      }
      const time = performance.now();
      const deltaTime = time - inertia.time;
      if (opt.hold === void 0) {
        opt.hold = 100;
      }
      if (deltaTime >= opt.hold) {
        inertia.timer.stop();
        return opt.stop && opt.stop();
      }
      this.classList.add("inertia");
      opt.end && opt.end();
      const self = this;
      inertia.timer.restart((e) => {
        inertia.t = limit * (1 - Math.exp(-B * e / A));
        opt.render && opt.render(inertia.t);
        if (inertia.t > 1) {
          inertia.timer.stop();
          self.classList.remove("inertia");
          inertia.velocity = [
            0,
            0
          ];
          inertia.t = 1;
          opt.finish && opt.finish();
        }
      });
    }
  };
  inertia.timer.stop();
  return inertia;
}
var positionToRotation = ([lng, lat], tilt = 0) => [
  -lng,
  tilt - lat,
  0
];
var geoToPosition = ({ lat, lng }) => [
  lng,
  lat
];
var geoPoint = (point) => ({
  type: "Point",
  coordinates: geoToPosition(point)
});
var geoCircle = ({ lat, lng }, radius) => (0, import_d34.geoCircle)().radius(radius).center([
  lng,
  lat
])();
var geoLine = (p1, p2) => ({
  type: "LineString",
  coordinates: [
    [
      p1.lng,
      p1.lat
    ],
    [
      p2.lng,
      p2.lat
    ]
  ]
});
var closestPoint = (points, target) => {
  if (points.length === 0) {
    return target;
  }
  let closestPoint2 = points[0];
  let minDistance = getDistance(points[0], target);
  for (const point of points) {
    const distance = getDistance(point, target);
    if (distance < minDistance) {
      minDistance = distance;
      closestPoint2 = point;
    }
  }
  return closestPoint2;
};
var getDistance = (point1, point2) => {
  const dx = point1[0] - point2[0];
  const dy = point1[1] - point2[1];
  return Math.sqrt(dx * dx + dy * dy);
};
var createLayers = (topology, features, styles) => {
  const layers = [];
  if (styles.water) {
    layers.push({
      styles: styles.water,
      path: {
        type: "Sphere"
      }
    });
  }
  if (styles.graticule) {
    layers.push({
      styles: styles.graticule,
      path: (0, import_d35.geoGraticule)().step([
        6,
        6
      ])()
    });
  }
  if (topology) {
    if (topology.objects.land && styles.land) {
      layers.push({
        styles: styles.land,
        path: (0, import_topojson_client.feature)(topology, topology.objects.land)
      });
    }
    if (topology.objects.countries && styles.border) {
      layers.push({
        styles: styles.border,
        path: (0, import_topojson_client.mesh)(topology, topology.objects.countries, (a, b) => a !== b)
      });
    }
    if (topology.objects.dots && styles.dots) {
      layers.push({
        styles: styles.dots,
        path: topology.objects.dots
      });
    }
  }
  if (features) {
    const { points, lines } = features;
    if (points && styles.point) {
      layers.push({
        styles: styles.point,
        path: {
          type: "GeometryCollection",
          geometries: points.map((point) => geoPoint(point))
        }
      });
    }
    if (lines && styles.line) {
      layers.push({
        styles: styles.line,
        path: {
          type: "GeometryCollection",
          geometries: lines.map(({ source, target }) => geoLine(source, target))
        }
      });
    }
  }
  return layers;
};
var renderLayers = (generator, layers = [], scale, styles) => {
  const context = generator.context();
  const { canvas: { width, height } } = context;
  context.reset();
  if (styles.background) {
    context.fillStyle = styles.background.fillStyle;
    context.fillRect(0, 0, width, height);
  } else {
    context.clearRect(0, 0, width, height);
  }
  layers.forEach(({ path, styles: styles2 }) => {
    context.save();
    let fill = false;
    let stroke = false;
    if (styles2) {
      Object.entries(styles2).forEach(([key, value]) => {
        if (key === "pointRadius") {
          generator.pointRadius(value * scale);
        } else {
          context[key] = value;
          fill ||= key === "fillStyle";
          stroke ||= key === "strokeStyle";
        }
      });
    }
    context.beginPath();
    generator(path);
    fill && context.fill();
    stroke && context.stroke();
    context.restore();
  });
  return context;
};
var useDrag = (controller, options = {}) => {
  (0, import_react3.useEffect)(() => {
    const canvas = controller?.canvas;
    if (!canvas || options.disabled) {
      return;
    }
    geoInertiaDrag((0, import_d32.select)(canvas), () => {
      controller.setRotation(controller.projection.rotate());
      options.onUpdate?.({
        type: "move",
        controller
      });
    }, controller.projection, {
      xAxis: options.xAxis,
      time: 3e3,
      start: () => options.onUpdate?.({
        type: "start",
        controller
      }),
      finish: () => options.onUpdate?.({
        type: "end",
        controller
      })
    });
    return () => {
      cancelDrag((0, import_d32.select)(canvas));
    };
  }, [
    controller,
    JSON.stringify(options)
  ]);
};
var cancelDrag = (node) => node.on(".drag", null);
var useGlobeZoomHandler = (controller) => {
  return (0, import_react4.useCallback)((event) => {
    if (!controller) {
      return;
    }
    switch (event) {
      case "zoom-in": {
        controller.setScale((scale) => scale * 1.1);
        break;
      }
      case "zoom-out": {
        controller.setScale((scale) => scale * 0.9);
        break;
      }
    }
  }, [
    controller
  ]);
};
var useMapZoomHandler = (controller) => {
  return (0, import_react5.useCallback)((event) => {
    if (!controller) {
      return;
    }
    switch (event) {
      case "zoom-in": {
        controller.setZoom((scale) => scale + 1);
        break;
      }
      case "zoom-out": {
        controller.setZoom((scale) => scale - 1);
        break;
      }
    }
  }, [
    controller
  ]);
};
var useSpinner = (controller, options = {}) => {
  const [running, setRunning] = (0, import_react6.useState)(false);
  (0, import_react6.useEffect)(() => {
    let timer3;
    const start = () => {
      const delta = options.delta ?? [
        1e-3,
        0,
        0
      ];
      let t = 0;
      let lastRotation = controller.projection.rotate();
      timer3 = (0, import_d36.timer)((elapsed) => {
        const dt = elapsed - t;
        t = elapsed;
        const rotation = [
          lastRotation[0] + delta[0] * dt,
          lastRotation[1] + delta[1] * dt,
          lastRotation[2] + delta[2] * dt
        ];
        lastRotation = rotation;
        controller.setRotation(rotation);
      });
    };
    const stop = () => {
      if (timer3) {
        timer3.stop();
        timer3 = void 0;
      }
    };
    if (controller && running) {
      start();
    } else {
      stop();
    }
    return () => stop();
  }, [
    controller,
    running
  ]);
  return [
    () => {
      if (!options.disabled) {
        setRunning(true);
      }
    },
    () => setRunning(false)
  ];
};
var TRANSITION_NAME = "globe-tour";
var defaultDuration = 1500;
var useTour = (controller, points, options = {}) => {
  const selection = (0, import_react7.useMemo)(() => (0, import_d37.selection)(), []);
  const [running, setRunning] = (0, import_react7.useState)(options.running ?? false);
  (0, import_react7.useEffect)(() => {
    if (!running) {
      selection.interrupt(TRANSITION_NAME);
      return;
    }
    let t;
    if (controller && running) {
      t = setTimeout(async () => {
        const { canvas, projection, setRotation } = controller;
        const context = canvas.getContext("2d", {
          alpha: false
        });
        const path = (0, import_d37.geoPath)(projection, context).pointRadius(2);
        const tilt = options.tilt ?? 0;
        let last;
        try {
          const p = [
            ...points
          ];
          if (options.loop) {
            p.push(p[0]);
          }
          for (const next of p) {
            if (!running) {
              break;
            }
            const p1 = last ? geoToPosition(last) : void 0;
            const p2 = geoToPosition(next);
            const ip = (0, import_d37.geoInterpolate)(p1 || p2, p2);
            const distance = (0, import_d37.geoDistance)(p1 || p2, p2);
            const r1 = p1 ? positionToRotation(p1, tilt) : controller.projection.rotate();
            const r2 = positionToRotation(p2, tilt);
            const iv = import_versor2.default.interpolate(r1, r2);
            const transition2 = selection.transition(TRANSITION_NAME).duration(Math.max(options.duration ?? defaultDuration, distance * 2e3)).tween("render", () => (t2) => {
              const t1 = Math.max(0, Math.min(1, t2 * 2 - 1));
              const t22 = Math.min(1, t2 * 2);
              context.save();
              {
                context.beginPath();
                context.strokeStyle = options?.styles?.arc?.strokeStyle ?? "yellow";
                context.lineWidth = (options?.styles?.arc?.lineWidth ?? 1.5) * (controller?.scale ?? 1);
                context.setLineDash(options?.styles?.arc?.lineDash ?? []);
                path({
                  type: "LineString",
                  coordinates: [
                    ip(t1),
                    ip(t22)
                  ]
                });
                context.stroke();
                context.beginPath();
                context.fillStyle = options?.styles?.cursor?.fillStyle ?? "orange";
                path.pointRadius((options?.styles?.cursor?.pointRadius ?? 2) * (controller?.scale ?? 1));
                path({
                  type: "Point",
                  coordinates: ip(t22)
                });
                context.fill();
              }
              context.restore();
              projection.rotate(iv(t2));
              setRotation(projection.rotate());
            });
            await transition2.end();
            last = next;
          }
        } catch (err) {
        } finally {
          setRunning(false);
        }
      });
      return () => {
        clearTimeout(t);
        selection.interrupt(TRANSITION_NAME);
      };
    }
  }, [
    controller,
    running,
    JSON.stringify(options)
  ]);
  return [
    running,
    setRunning
  ];
};
var controlPositions = {
  topleft: "top-2 left-2",
  topright: "top-2 right-2",
  bottomleft: "bottom-2 left-2",
  bottomright: "bottom-2 right-2"
};
var ZoomControls = ({ classNames, onAction }) => {
  var _effect = (0, import_tracking3.useSignals)();
  try {
    return /* @__PURE__ */ import_react8.default.createElement(import_react_ui3.Toolbar.Root, {
      classNames: [
        "gap-1",
        classNames
      ]
    }, /* @__PURE__ */ import_react8.default.createElement(import_react_ui3.IconButton, {
      //
      icon: "ph--plus--regular",
      label: "zoom in",
      iconOnly: true,
      size: 5,
      classNames: "px-0 aspect-square",
      onClick: () => onAction?.("zoom-in")
    }), /* @__PURE__ */ import_react8.default.createElement(import_react_ui3.IconButton, {
      //
      icon: "ph--minus--regular",
      label: "zoom out",
      iconOnly: true,
      size: 5,
      classNames: "px-0 aspect-square",
      onClick: () => onAction?.("zoom-out")
    }));
  } finally {
    _effect.f();
  }
};
var ActionControls = ({ classNames, onAction }) => {
  var _effect = (0, import_tracking3.useSignals)();
  try {
    return /* @__PURE__ */ import_react8.default.createElement(import_react_ui3.Toolbar.Root, {
      classNames: [
        "gap-1",
        classNames
      ]
    }, /* @__PURE__ */ import_react8.default.createElement(import_react_ui3.IconButton, {
      //
      icon: "ph--play--regular",
      label: "start",
      iconOnly: true,
      size: 5,
      classNames: "px-0 aspect-square",
      onClick: () => onAction?.("start")
    }), /* @__PURE__ */ import_react8.default.createElement(import_react_ui3.IconButton, {
      //
      icon: "ph--globe-hemisphere-west--regular",
      label: "toggle",
      iconOnly: true,
      size: 5,
      classNames: "px-0 aspect-square",
      onClick: () => onAction?.("toggle")
    }));
  } finally {
    _effect.f();
  }
};
var defaultStyles = {
  light: {
    background: {
      fillStyle: "#EEE"
    },
    water: {
      fillStyle: "#555"
    },
    land: {
      fillStyle: "#999"
    },
    line: {
      strokeStyle: "darkred"
    },
    point: {
      fillStyle: "#111111",
      strokeStyle: "#111111",
      strokeWidth: 1,
      pointRadius: 0.5
    }
  },
  dark: {
    background: {
      fillStyle: "#111111"
    },
    water: {
      fillStyle: "#123E6A"
    },
    land: {
      fillStyle: "#032153"
    },
    line: {
      strokeStyle: "#111111"
    },
    point: {
      fillStyle: "#111111",
      strokeStyle: "#111111",
      strokeWidth: 1,
      pointRadius: 0.5
    }
  }
};
var projectionMap = {
  orthographic: import_d3.geoOrthographic,
  mercator: import_d3.geoMercator,
  "transverse-mercator": import_d3.geoTransverseMercator
};
var getProjection = (type = "orthographic") => {
  if (typeof type === "string") {
    const constructor = projectionMap[type] ?? import_d3.geoOrthographic;
    return constructor();
  }
  return type ?? (0, import_d3.geoOrthographic)();
};
var GlobeRoot = ({ classNames, children, ...props }) => {
  var _effect = (0, import_tracking.useSignals)();
  try {
    const { ref, width, height } = (0, import_react_resize_detector.useResizeDetector)();
    return /* @__PURE__ */ import_react.default.createElement("div", {
      ref,
      className: (0, import_react_ui_theme.mx)("relative flex grow overflow-hidden", classNames)
    }, /* @__PURE__ */ import_react.default.createElement(GlobeContextProvider, {
      size: {
        width,
        height
      },
      ...props
    }, children));
  } finally {
    _effect.f();
  }
};
var GlobeCanvas = /* @__PURE__ */ (0, import_react.forwardRef)(({ projection: _projection, topology, features, styles: _styles }, forwardRef3) => {
  var _effect = (0, import_tracking.useSignals)();
  try {
    const { themeMode } = (0, import_react_ui.useThemeContext)();
    const styles = (0, import_react.useMemo)(() => _styles ?? defaultStyles[themeMode], [
      _styles,
      themeMode
    ]);
    const [canvas, setCanvas] = (0, import_react.useState)(null);
    const canvasRef = (canvas2) => setCanvas(canvas2);
    const projection = (0, import_react.useMemo)(() => getProjection(_projection), [
      _projection
    ]);
    const layers = (0, import_react.useMemo)(() => {
      return timer(() => createLayers(topology, features, styles));
    }, [
      topology,
      features,
      styles
    ]);
    const { size, center, scale, translation, rotation, setCenter, setScale, setTranslation, setRotation } = useGlobeContext();
    const scaleRef = (0, import_react_ui.useDynamicRef)(scale);
    (0, import_react.useEffect)(() => {
      if (center) {
        setScale(1);
        setRotation(positionToRotation(geoToPosition(center)));
      }
    }, [
      center
    ]);
    const zooming = (0, import_react.useRef)(false);
    (0, import_react.useImperativeHandle)(forwardRef3, () => {
      return {
        canvas,
        projection,
        center,
        get scale() {
          return scaleRef.current;
        },
        translation,
        rotation,
        setCenter,
        setScale: (s) => {
          if (typeof s === "function") {
            const is = (0, import_d3.interpolateNumber)(scaleRef.current, s(scaleRef.current));
            (0, import_d3.transition)().ease(zooming.current ? import_d3.easeLinear : import_d3.easeSinOut).duration(200).tween("scale", () => (t) => setScale(is(t))).on("end", () => {
              zooming.current = false;
            });
          } else {
            setScale(s);
          }
        },
        setTranslation,
        setRotation
      };
    }, [
      canvas
    ]);
    const generator = (0, import_react.useMemo)(() => canvas && projection && (0, import_d3.geoPath)(projection, canvas.getContext("2d", {
      alpha: false
    })), [
      canvas,
      projection
    ]);
    (0, import_react.useEffect)(() => {
      if (canvas && projection) {
        timer(() => {
          projection.scale(Math.min(size.width, size.height) / 2 * scale).translate([
            size.width / 2 + (translation?.x ?? 0),
            size.height / 2 + (translation?.y ?? 0)
          ]).rotate(rotation ?? [
            0,
            0,
            0
          ]);
          renderLayers(generator, layers, scale, styles);
        });
      }
    }, [
      generator,
      size,
      scale,
      translation,
      rotation,
      layers
    ]);
    if (!size.width || !size.height) {
      return null;
    }
    return /* @__PURE__ */ import_react.default.createElement("canvas", {
      ref: canvasRef,
      width: size.width,
      height: size.height
    });
  } finally {
    _effect.f();
  }
});
var GlobeDebug = ({ position = "topleft" }) => {
  var _effect = (0, import_tracking.useSignals)();
  try {
    const { size, scale, translation, rotation } = useGlobeContext();
    return /* @__PURE__ */ import_react.default.createElement("div", {
      className: (0, import_react_ui_theme.mx)("z-10 absolute w-96 p-2 overflow-hidden border border-green-700 rounded", controlPositions[position])
    }, /* @__PURE__ */ import_react.default.createElement("pre", {
      className: "font-mono text-xs text-green-700"
    }, JSON.stringify({
      size,
      scale,
      translation,
      rotation
    }, null, 2)));
  } finally {
    _effect.f();
  }
};
var GlobePanel = ({ position, classNames, children }) => {
  var _effect = (0, import_tracking.useSignals)();
  try {
    return /* @__PURE__ */ import_react.default.createElement("div", {
      className: (0, import_react_ui_theme.mx)("z-10 absolute overflow-hidden", controlPositions[position], classNames)
    }, children);
  } finally {
    _effect.f();
  }
};
var CustomControl = ({ position, children }) => {
  var _effect = (0, import_tracking.useSignals)();
  try {
    return /* @__PURE__ */ import_react.default.createElement("div", {
      className: (0, import_react_ui_theme.mx)("z-10 absolute overflow-hidden", controlPositions[position])
    }, children);
  } finally {
    _effect.f();
  }
};
var Globe = {
  Root: GlobeRoot,
  Canvas: GlobeCanvas,
  Zoom: ({ onAction, position = "bottomleft", ...props }) => {
    var _effect = (0, import_tracking.useSignals)();
    try {
      return /* @__PURE__ */ import_react.default.createElement(CustomControl, {
        position,
        ...props
      }, /* @__PURE__ */ import_react.default.createElement(ZoomControls, {
        onAction
      }));
    } finally {
      _effect.f();
    }
  },
  Action: ({ onAction, position = "bottomright", ...props }) => {
    var _effect = (0, import_tracking.useSignals)();
    try {
      return /* @__PURE__ */ import_react.default.createElement(CustomControl, {
        position,
        ...props
      }, /* @__PURE__ */ import_react.default.createElement(ActionControls, {
        onAction
      }));
    } finally {
      _effect.f();
    }
  },
  Debug: GlobeDebug,
  Panel: GlobePanel
};
var defaults = {
  // TODO(burdon): Guess location.
  center: {
    lat: 51,
    lng: 0
  },
  zoom: 4
};
var MapRoot = ({ classNames, center = defaults.center, zoom = defaults.zoom, ...props }) => {
  var _effect = (0, import_tracking4.useSignals)();
  try {
    return /* @__PURE__ */ import_react9.default.createElement(import_react_leaflet.MapContainer, {
      className: (0, import_react_ui_theme2.mx)("relative grid grow bg-baseSurface", classNames),
      attributionControl: false,
      // TODO(burdon): Only if attention.
      scrollWheelZoom: true,
      zoomControl: false,
      center,
      zoom,
      ...props
    });
  } finally {
    _effect.f();
  }
};
var MapCanvas = /* @__PURE__ */ (0, import_react9.forwardRef)(({ markers, center, zoom, onChange }, forwardedRef) => {
  var _effect = (0, import_tracking4.useSignals)();
  try {
    const { ref, width, height } = (0, import_react_resize_detector2.useResizeDetector)({
      refreshRate: 200
    });
    const map = (0, import_react_leaflet.useMap)();
    (0, import_react9.useImperativeHandle)(forwardedRef, () => ({
      setCenter: (center2, zoom2) => {
        map.setView(center2, zoom2);
      },
      setZoom: (cb) => {
        map.setZoom(cb(map.getZoom()));
      }
    }), [
      map
    ]);
    (0, import_react9.useEffect)(() => {
      if (width && height) {
        map.invalidateSize();
      }
    }, [
      width,
      height
    ]);
    (0, import_react9.useEffect)(() => {
      if (center) {
        map.setView(center, zoom);
      } else if (zoom !== void 0) {
        map.setZoom(zoom);
      }
    }, [
      center,
      zoom
    ]);
    (0, import_react9.useEffect)(() => {
      const handler = (0, import_async.debounce)(() => {
        onChange?.({
          center: map.getCenter(),
          zoom: map.getZoom()
        });
      }, 100);
      map.on("move", handler);
      map.on("zoom", handler);
      return () => {
        map.off("move", handler);
        map.off("zoom", handler);
      };
    }, [
      map,
      onChange
    ]);
    (0, import_react9.useEffect)(() => {
      if (markers.length > 0) {
        const bounds = (0, import_leaflet2.latLngBounds)(markers.map((marker) => marker.location));
        map.fitBounds(bounds);
      } else {
        map.setView(defaults.center, defaults.zoom);
      }
    }, [
      markers
    ]);
    return /* @__PURE__ */ import_react9.default.createElement("div", {
      ref,
      className: "flex w-full h-full overflow-hidden bg-baseSurface"
    }, /* @__PURE__ */ import_react9.default.createElement(import_react_leaflet.TileLayer, {
      className: "dark:filter dark:grayscale dark:invert",
      url: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
    }), markers?.map(({ id, title, location: { lat, lng } }) => {
      return /* @__PURE__ */ import_react9.default.createElement(import_react_leaflet.Marker, {
        key: id,
        position: {
          lat,
          lng
        },
        icon: (
          // TODO(burdon): Create custom icon from bundled assets.
          new import_leaflet2.default.Icon({
            iconUrl: "https://dxos.network/marker-icon.png",
            iconRetinaUrl: "https://dxos.network/marker-icon-2x.png",
            shadowUrl: "https://dxos.network/marker-shadow.png",
            iconSize: [
              25,
              41
            ],
            iconAnchor: [
              12,
              41
            ],
            popupAnchor: [
              1,
              -34
            ],
            shadowSize: [
              41,
              41
            ]
          })
        )
      }, title && /* @__PURE__ */ import_react9.default.createElement(import_react_leaflet.Popup, null, title));
    }));
  } finally {
    _effect.f();
  }
});
var CustomControl2 = ({ position, children }) => {
  var _effect = (0, import_tracking4.useSignals)();
  try {
    const map = (0, import_react_leaflet.useMap)();
    (0, import_react9.useEffect)(() => {
      const control = new import_leaflet2.Control({
        position
      });
      control.onAdd = () => {
        const container = import_leaflet2.DomUtil.create("div", (0, import_react_ui_theme2.mx)("!m-0", controlPositions[position]));
        import_leaflet2.DomEvent.disableClickPropagation(container);
        import_leaflet2.DomEvent.disableScrollPropagation(container);
        const root = (0, import_client.createRoot)(container);
        root.render(/* @__PURE__ */ import_react9.default.createElement(import_react_ui4.ThemeProvider, {
          tx: import_react_ui_theme2.defaultTx
        }, /* @__PURE__ */ import_react9.default.createElement(import_react_ui4.Tooltip.Provider, null, children)));
        return container;
      };
      control.addTo(map);
      return () => {
        control.remove();
      };
    }, [
      map,
      position,
      children
    ]);
    return null;
  } finally {
    _effect.f();
  }
};
var Map = {
  Root: MapRoot,
  Canvas: MapCanvas,
  Zoom: ({ onAction, position = "bottomleft", ...props }) => {
    var _effect = (0, import_tracking4.useSignals)();
    try {
      return /* @__PURE__ */ import_react9.default.createElement(CustomControl2, {
        position,
        ...props
      }, /* @__PURE__ */ import_react9.default.createElement(ZoomControls, {
        onAction
      }));
    } finally {
      _effect.f();
    }
  },
  Action: ({ onAction, position = "bottomright", ...props }) => {
    var _effect = (0, import_tracking4.useSignals)();
    try {
      return /* @__PURE__ */ import_react9.default.createElement(CustomControl2, {
        position,
        ...props
      }, /* @__PURE__ */ import_react9.default.createElement(ActionControls, {
        onAction
      }));
    } finally {
      _effect.f();
    }
  }
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  ActionControls,
  Globe,
  GlobeContextProvider,
  Map,
  ZoomControls,
  closestPoint,
  controlPositions,
  createLayers,
  geoCircle,
  geoInertiaDrag,
  geoLine,
  geoPoint,
  geoToPosition,
  getDistance,
  loadTopology,
  positionToRotation,
  renderLayers,
  restrictAxis,
  timer,
  useDrag,
  useGlobeContext,
  useGlobeZoomHandler,
  useMapZoomHandler,
  useSpinner,
  useTour
});
//# sourceMappingURL=index.cjs.map
