import { jsx as tt } from "react/jsx-runtime";
import St, { useRef as j, useState as et, useEffect as nt, Children as Ct, useCallback as Nt } from "react";
var ft = { dragStart: !0 }, gt = { delay: 0, distance: 3 };
function Tt(t, e = {}) {
  let r, a, { bounds: s, axis: g = "both", gpuAcceleration: i = !0, legacyTranslate: R = !1, transform: D, applyUserSelectHack: v = !0, disabled: C = !1, ignoreMultitouch: m = !1, recomputeBounds: f = ft, grid: S, threshold: E = gt, position: y, cancel: h, handle: N, defaultClass: d = "neodrag", defaultClassDragging: T = "neodrag-dragging", defaultClassDragged: $ = "neodrag-dragged", defaultPosition: p = { x: 0, y: 0 }, onDragStart: o, onDrag: b, onDragEnd: Y } = e, I = !1, w = !1, G = 0, X = !1, l = !1, L = 0, q = 0, U = 0, k = 0, rt = 0, ot = 0, { x: Q, y: z } = y ? { x: y?.x ?? 0, y: y?.y ?? 0 } : p;
  ct(Q, z);
  let H, O, J, at, st, yt = "", At = !!y;
  f = { ...ft, ...f }, E = { ...gt, ...E ?? {} };
  let W = /* @__PURE__ */ new Set();
  function vt(n) {
    I && !w && l && X && st && (w = !0, (function(u) {
      lt("neodrag:start", o, u);
    })(n), _.add(T), v && (yt = it.userSelect, it.userSelect = "none"));
  }
  const it = document.body.style, _ = t.classList;
  function ct(n = L, u = q) {
    if (!D) {
      if (R) {
        let A = `${+n}px, ${+u}px`;
        return Z(t, "transform", i ? `translate3d(${A}, 0)` : `translate(${A})`);
      }
      return Z(t, "translate", `${+n}px ${+u}px`);
    }
    const M = D({ offsetX: n, offsetY: u, rootNode: t });
    pt(M) && Z(t, "transform", M);
  }
  function lt(n, u, M) {
    const A = /* @__PURE__ */ (function(x) {
      return { offsetX: L, offsetY: q, rootNode: t, currentNode: st, event: x };
    })(M);
    t.dispatchEvent(new CustomEvent(n, { detail: A })), u?.(A);
  }
  const K = addEventListener, ut = new AbortController(), dt = { signal: ut.signal, capture: !1 };
  function xt() {
    let n = t.offsetWidth / O.width;
    return isNaN(n) && (n = 1), n;
  }
  return Z(t, "touch-action", "none"), K("pointerdown", ((n) => {
    if (C || n.button === 2) return;
    if (W.add(n.pointerId), m && W.size > 1) return n.preventDefault();
    if (f.dragStart && (H = ht(s, t)), pt(N) && pt(h) && N === h) throw new Error("`handle` selector can't be same as `cancel` selector");
    if (_.add(d), J = (function(c, B) {
      if (!c) return [B];
      if (mt(c)) return [c];
      if (Array.isArray(c)) return c;
      const P = B.querySelectorAll(c);
      if (P === null) throw new Error("Selector passed for `handle` option should be child of the element on which the action is applied");
      return Array.from(P.values());
    })(N, t), at = (function(c, B) {
      if (!c) return [];
      if (mt(c)) return [c];
      if (Array.isArray(c)) return c;
      const P = B.querySelectorAll(c);
      if (P === null) throw new Error("Selector passed for `cancel` option should be child of the element on which the action is applied");
      return Array.from(P.values());
    })(h, t), r = /(both|x)/.test(g), a = /(both|y)/.test(g), bt(at, J)) throw new Error("Element being dragged can't be a child of the element on which `cancel` is applied");
    const u = n.composedPath()[0];
    if (!J.some(((c) => c.contains(u) || c.shadowRoot?.contains(u))) || bt(at, [u])) return;
    st = J.length === 1 ? t : J.find(((c) => c.contains(u))), I = !0, G = Date.now(), E.delay || (X = !0), O = t.getBoundingClientRect();
    const { clientX: M, clientY: A } = n, x = xt();
    r && (U = M - Q / x), a && (k = A - z / x), H && (rt = M - O.left, ot = A - O.top);
  }), dt), K("pointermove", ((n) => {
    if (!I || m && W.size > 1) return;
    if (!w) {
      if (X || Date.now() - G >= E.delay && (X = !0, vt(n)), !l) {
        const x = n.clientX - U, c = n.clientY - k;
        Math.sqrt(x ** 2 + c ** 2) >= E.distance && (l = !0, vt(n));
      }
      if (!w) return;
    }
    f.drag && (H = ht(s, t)), n.preventDefault(), O = t.getBoundingClientRect();
    let u = n.clientX, M = n.clientY;
    const A = xt();
    if (H) {
      const x = { left: H.left + rt, top: H.top + ot, right: H.right + rt - O.width, bottom: H.bottom + ot - O.height };
      u = Et(u, x.left, x.right), M = Et(M, x.top, x.bottom);
    }
    if (Array.isArray(S)) {
      let [x, c] = S;
      if (isNaN(+x) || x < 0) throw new Error("1st argument of `grid` must be a valid positive number");
      if (isNaN(+c) || c < 0) throw new Error("2nd argument of `grid` must be a valid positive number");
      let B = u - U, P = M - k;
      [B, P] = It([x / A, c / A], B, P), u = U + B, M = k + P;
    }
    r && (L = Math.round((u - U) * A)), a && (q = Math.round((M - k) * A)), Q = L, z = q, lt("neodrag", b, n), ct();
  }), dt), K("pointerup", ((n) => {
    W.delete(n.pointerId), I && (w && (K("click", ((u) => u.stopPropagation()), { once: !0, signal: ut.signal, capture: !0 }), f.dragEnd && (H = ht(s, t)), _.remove(T), _.add($), v && (it.userSelect = yt), lt("neodrag:end", Y, n), r && (U = L), a && (k = q)), I = !1, w = !1, X = !1, l = !1);
  }), dt), { destroy: () => ut.abort(), update: (n) => {
    g = n.axis || "both", C = n.disabled ?? !1, m = n.ignoreMultitouch ?? !1, N = n.handle, s = n.bounds, f = n.recomputeBounds ?? ft, h = n.cancel, v = n.applyUserSelectHack ?? !0, S = n.grid, i = n.gpuAcceleration ?? !0, R = n.legacyTranslate ?? !1, D = n.transform, E = { ...gt, ...n.threshold ?? {} };
    const u = _.contains($);
    _.remove(d, $), d = n.defaultClass ?? "neodrag", T = n.defaultClassDragging ?? "neodrag-dragging", $ = n.defaultClassDragged ?? "neodrag-dragged", _.add(d), u && _.add($), At && (Q = L = n.position?.x ?? L, z = q = n.position?.y ?? q, ct());
  } };
}
var Et = (t, e, r) => Math.min(Math.max(t, e), r), pt = (t) => typeof t == "string", It = ([t, e], r, a) => {
  const s = (g, i) => i === 0 ? 0 : Math.ceil(g / i) * i;
  return [s(r, t), s(a, e)];
}, bt = (t, e) => t.some(((r) => e.some(((a) => r.contains(a)))));
function ht(t, e) {
  if (t === void 0) return;
  if (mt(t)) return t.getBoundingClientRect();
  if (typeof t == "object") {
    const { top: a = 0, left: s = 0, right: g = 0, bottom: i = 0 } = t;
    return { top: a, right: window.innerWidth - g, bottom: window.innerHeight - i, left: s };
  }
  if (t === "parent") return e.parentNode.getBoundingClientRect();
  const r = document.querySelector(t);
  if (r === null) throw new Error("The selector provided for bound doesn't exists in the document.");
  return r.getBoundingClientRect();
}
var Z = (t, e, r) => t.style.setProperty(e, r), mt = (t) => t instanceof HTMLElement;
function V(t) {
  return t == null || typeof t == "string" || t instanceof HTMLElement ? t : "current" in t ? t.current : Array.isArray(t) ? t.map(((e) => e instanceof HTMLElement ? e : e.current)) : void 0;
}
function Lt(t, e = {}) {
  const r = j(), [a, s] = et(!1), [g, i] = et();
  let { onDragStart: R, onDrag: D, onDragEnd: v, handle: C, cancel: m } = e, f = V(C), S = V(m);
  function E(d, T) {
    i(d), T?.(d);
  }
  function y(d) {
    s(!0), E(d, R);
  }
  function h(d) {
    E(d, D);
  }
  function N(d) {
    s(!1), E(d, v);
  }
  return nt((() => {
    if (typeof window > "u") return;
    const d = t.current;
    if (!d) return;
    ({ onDragStart: R, onDrag: D, onDragEnd: v } = e);
    const { update: T, destroy: $ } = Tt(d, { ...e, handle: f, cancel: S, onDragStart: y, onDrag: h, onDragEnd: N });
    return r.current = T, $;
  }), []), nt((() => {
    r.current?.({ ...e, handle: V(C), cancel: V(m), onDragStart: y, onDrag: h, onDragEnd: N });
  }), [e]), { isDragging: a, dragState: g };
}
const F = "tiny-canvas-queue";
function wt() {
  const t = localStorage.getItem(F);
  if (!t) return [];
  try {
    const e = JSON.parse(t);
    return Array.isArray(e) ? e : [];
  } catch {
    return localStorage.setItem(F, JSON.stringify([])), [];
  }
}
const Rt = (t) => {
  if (!t) return null;
  let e = null;
  const r = (a) => {
    if (a.props && a.props.id) {
      e = a.props.id;
      return;
    }
    a.props && a.props.children && St.Children.forEach(a.props.children, r);
  };
  return r(t), e;
};
function $t(t) {
  let e = 5381;
  for (let r = 0; r < t.length; r++)
    e = (e << 5) + e + t.charCodeAt(r) >>> 0;
  return e.toString(16).padStart(8, "0");
}
function Mt(t) {
  if (t == null || typeof t == "boolean") return "";
  if (typeof t == "string" || typeof t == "number") return "#text";
  const e = t.type, r = typeof e == "function" ? e.displayName || e.name || "Anonymous" : typeof e == "string" ? e : "Fragment", a = t.props?.children;
  if (a == null) return r;
  const s = [];
  return St.Children.forEach(a, (g) => {
    const i = Mt(g);
    i && s.push(i);
  }), s.length ? `${r}(${s.join(",")})` : r;
}
const Xt = (t, e) => {
  const r = Mt(t);
  return `tc-${$t(r)}-${e}`;
}, Gt = (t) => {
  try {
    return wt().reduce((a, s) => (a[s.id] = { id: s.id, x: s.x, y: s.y }, a), {})[t] || { x: 0, y: 0 };
  } catch (e) {
    return console.error("Error getting saved coordinates:", e), { x: 0, y: 0 };
  }
}, Jt = () => {
  try {
    localStorage.getItem(F) || localStorage.setItem(F, JSON.stringify([]));
  } catch (t) {
    console.error("LocalStorage is not available:", t);
  }
}, Yt = (t, e, r) => {
  try {
    const a = wt(), s = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-"), g = { id: t, x: e, y: r, time: s }, i = a.findIndex((R) => R.id === t);
    i >= 0 ? a[i] = g : a.push(g), localStorage.setItem(F, JSON.stringify(a));
  } catch (a) {
    console.error("Error saving drag position:", a);
  }
}, qt = 250, Dt = 4, Ht = 150, Pt = 8;
function _t({ children: t, dragId: e, initialPosition: r, onDragStart: a, onDrag: s, onDragEnd: g, handle: i, snapGrid: R, locked: D = !1, boundaryPad: v = 0 }) {
  const C = j(null), m = r || { x: 0, y: 0 }, f = j(m), S = j(!1), E = j({
    timer: null,
    startX: 0,
    startY: 0,
    delayMet: !1,
    distanceMet: !1,
    active: !1,
    lastEvent: null
  }), [y, h] = et(m), [N, d] = et(m);
  r && (r.x !== N.x || r.y !== N.y) && (d(r), h(r)), nt(() => {
    const p = C.current;
    if (p && e && (m.x !== 0 || m.y !== 0)) {
      p.classList.add("tc-on-translation");
      const o = setTimeout(() => {
        p.classList.remove("tc-on-translation");
      }, qt * 4);
      return () => {
        clearTimeout(o);
      };
    }
  }, [e, m.x, m.y]), nt(() => {
    const p = C.current;
    if (!p || !i || D) return;
    const o = E.current;
    let b = null;
    function Y(l) {
      if (!(l.target instanceof Element)) return !1;
      const L = l.target.closest(i);
      return L != null && p.contains(L);
    }
    function I(l) {
      if (l === b) {
        b = null;
        return;
      }
      Y(l) && (l.stopImmediatePropagation(), o.active = !0, o.delayMet = !1, o.distanceMet = !1, o.startX = l.clientX, o.startY = l.clientY, o.target = l.target, o.pointerId = l.pointerId, o.button = l.button, o.pointerType = l.pointerType, clearTimeout(o.timer), o.timer = setTimeout(() => {
        o.delayMet = !0, w();
      }, Ht));
    }
    function w() {
      if (o.delayMet && o.distanceMet && o.active && o.target) {
        const l = new PointerEvent("pointerdown", {
          bubbles: !0,
          cancelable: !0,
          pointerId: o.pointerId,
          clientX: o.startX,
          clientY: o.startY,
          button: o.button,
          pointerType: o.pointerType
        });
        b = l, o.target.dispatchEvent(l), o.target = null;
      }
    }
    function G(l) {
      if (!o.active || o.distanceMet) return;
      const L = l.clientX - o.startX, q = l.clientY - o.startY;
      Math.hypot(L, q) >= Pt && (o.distanceMet = !0, w());
    }
    function X() {
      clearTimeout(o.timer), o.active = !1, o.target = null;
    }
    return p.addEventListener("pointerdown", I, !0), document.addEventListener("pointermove", G), document.addEventListener("pointerup", X), document.addEventListener("pointercancel", X), () => {
      p.removeEventListener("pointerdown", I, !0), document.removeEventListener("pointermove", G), document.removeEventListener("pointerup", X), document.removeEventListener("pointercancel", X), clearTimeout(o.timer);
    };
  }, [i, D]);
  const { isDragging: T } = Lt(C, {
    axis: "both",
    grid: R,
    defaultClass: "tc-drag",
    defaultClassDragging: "tc-on",
    defaultClassDragged: "tc-off",
    applyUserSelectHack: !0,
    disabled: D,
    ...i ? { handle: i } : {},
    position: { x: y.x, y: y.y },
    // Clamp in the transform callback so neodrag never paints a
    // negative position — avoids the one-frame flicker that happens
    // when clamping only in onDrag (React re-render lag).
    transform: ({ offsetX: p, offsetY: o }) => {
      const b = Math.max(v, p), Y = Math.max(v, o);
      return `translate3d(${b}px, ${Y}px, 0)`;
    },
    onDragStart: () => {
      f.current = y, S.current = !1, a?.(e, y);
    },
    onDrag: ({ offsetX: p, offsetY: o }) => {
      const b = p - f.current.x, Y = o - f.current.y, I = Math.hypot(b, Y);
      !S.current && I >= Dt && (S.current = !0);
      const w = { x: Math.max(v, p), y: Math.max(v, o) };
      h(w), s?.(e, w);
    },
    onDragEnd: (p) => {
      const o = Math.max(v, p.offsetX), b = Math.max(v, p.offsetY);
      h({ x: o, y: b });
      const Y = o - f.current.x, I = b - f.current.y;
      (S.current || Math.hypot(Y, I) >= Dt) && (e && Yt(e, o, b), g?.(e, { x: o, y: b }));
    }
  });
  return /* @__PURE__ */ tt(
    "article",
    {
      ref: C,
      style: {
        cursor: D ? void 0 : i ? T ? "grabbing" : void 0 : T ? "grabbing" : "grab",
        transform: `translate3d(${y.x}px, ${y.y}px, 0)`
      },
      children: /* @__PURE__ */ tt("div", { className: "tc-draggable-inner", children: t })
    }
  );
}
function Bt(t, e = 0) {
  const r = Number(t?.props?.["data-tc-x"]), a = Number(t?.props?.["data-tc-y"]);
  return Number.isFinite(r) && Number.isFinite(a) ? { x: Math.max(e, r), y: Math.max(e, a) } : null;
}
function Ot(t) {
  return t?.props?.["data-tc-handle"] || null;
}
function jt({
  children: t,
  dotted: e = !1,
  grid: r = !1,
  gridSize: a,
  snapGrid: s,
  colorMode: g = "auto",
  locked: i = !1,
  boundaryPad: R,
  onDragStart: D,
  onDrag: v,
  onDragEnd: C
}) {
  const m = e || r, f = a, S = R ?? a ?? 0, E = f && f < 16 ? 1 : 2, y = f ? {
    "--tc-grid-size": `${f}px`,
    "--tc-grid-offset": `${f / -2}px`,
    "--tc-dot-radius": `${E}px`
  } : void 0;
  return /* @__PURE__ */ tt(
    "main",
    {
      className: "tc-canvas",
      "data-dotted": m || void 0,
      "data-locked": i || void 0,
      "data-color-mode": g !== "auto" ? g : void 0,
      style: y,
      children: Ct.map(t, (h, N) => {
        const d = Rt(h) ?? Xt(h, N), T = Bt(h, S), $ = Ot(h);
        return /* @__PURE__ */ tt(
          _t,
          {
            gridSize: a,
            snapGrid: s,
            dragId: d,
            initialPosition: T,
            onDragStart: D,
            onDrag: v,
            onDragEnd: C,
            handle: $,
            locked: i,
            boundaryPad: S,
            children: h
          },
          d
        );
      })
    }
  );
}
function Ft({ reload: t = !1 } = {}) {
  return Nt(() => {
    try {
      localStorage.removeItem("tiny-canvas-queue");
    } catch (e) {
      console.error("Error clearing canvas state:", e);
    }
    t && window.location.reload();
  }, [t]);
}
export {
  jt as Canvas,
  _t as Draggable,
  Rt as findDragId,
  Xt as generateDragId,
  Gt as getQueue,
  Jt as refreshStorage,
  Yt as saveDrag,
  Ft as useResetCanvas
};
