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