UNPKG

@bmunozg/react-image-area

Version:

React component to select multiple areas/regions of images.

234 lines (233 loc) 16.9 kB
import ye, { Fragment as fe, useRef as se, useState as re, useCallback as $, useEffect as ge } from "react"; var le, ne = { exports: {} }, J = {}, ce, q = {}; /** * @license React * react-jsx-runtime.development.js * * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ process.env.NODE_ENV === "production" ? ne.exports = function() { if (le) return J; le = 1; var t = Symbol.for("react.transitional.element"), l = Symbol.for("react.fragment"); function g(_, v, j) { var y = null; if (j !== void 0 && (y = "" + j), v.key !== void 0 && (y = "" + v.key), "key" in v) for (var S in j = {}, v) S !== "key" && (j[S] = v[S]); else j = v; return v = j.ref, { $$typeof: t, type: _, key: y, ref: v !== void 0 ? v : null, props: j }; } return J.Fragment = l, J.jsx = g, J.jsxs = g, J; }() : ne.exports = (ce || (ce = 1, process.env.NODE_ENV !== "production" && function() { function t(e) { if (e == null) return null; if (typeof e == "function") return e.$$typeof === E ? null : e.displayName || e.name || null; if (typeof e == "string") return e; switch (e) { case D: return "Fragment"; case V: return "Profiler"; case Z: return "StrictMode"; case Y: return "Suspense"; case N: return "SuspenseList"; case G: return "Activity"; } if (typeof e == "object") switch (typeof e.tag == "number" && console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."), e.$$typeof) { case Q: return "Portal"; case te: return e.displayName || "Context"; case ee: return (e._context.displayName || "Context") + ".Consumer"; case u: var r = e.render; return (e = e.displayName) || (e = (e = r.displayName || r.name || "") !== "" ? "ForwardRef(" + e + ")" : "ForwardRef"), e; case I: return (r = e.displayName || null) !== null ? r : t(e.type) || "Memo"; case A: r = e._payload, e = e._init; try { return t(e(r)); } catch { } } return null; } function l(e) { return "" + e; } function g(e) { try { l(e); var r = !1; } catch { r = !0; } if (r) { var n = (r = console).error, i = typeof Symbol == "function" && Symbol.toStringTag && e[Symbol.toStringTag] || e.constructor.name || "Object"; return n.call(r, "The provided key is an unsupported type %s. This value must be coerced to a string before using it here.", i), l(e); } } function _(e) { if (e === D) return "<>"; if (typeof e == "object" && e !== null && e.$$typeof === A) return "<...>"; try { var r = t(e); return r ? "<" + r + ">" : "<...>"; } catch { return "<...>"; } } function v() { return Error("react-stack-top-frame"); } function j() { var e = t(this.type); return o[e] || (o[e] = !0, console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.")), (e = this.props.ref) !== void 0 ? e : null; } function y(e, r, n, i, b, s) { var w, p = r.children; if (p !== void 0) if (i) if (B(p)) { for (i = 0; i < p.length; i++) S(p[i]); Object.freeze && Object.freeze(p); } else console.error("React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead."); else S(p); if (W.call(r, "key")) { p = t(e); var x = Object.keys(r).filter(function(f) { return f !== "key"; }); i = 0 < x.length ? "{key: someKey, " + x.join(": ..., ") + ": ...}" : "{key: someKey}", c[p + i] || (x = 0 < x.length ? "{" + x.join(": ..., ") + ": ...}" : "{}", console.error(`A props object containing a "key" prop is being spread into JSX: let props = %s; <%s {...props} /> React keys must be passed directly to JSX without using spread: let props = %s; <%s key={someKey} {...props} />`, i, p, x, p), c[p + i] = !0); } if (p = null, n !== void 0 && (g(n), p = "" + n), function(f) { if (W.call(f, "key")) { var k = Object.getOwnPropertyDescriptor(f, "key").get; if (k && k.isReactWarning) return !1; } return f.key !== void 0; }(r) && (g(r.key), p = "" + r.key), "key" in r) for (var R in n = {}, r) R !== "key" && (n[R] = r[R]); else n = r; return p && function(f, k) { function C() { M || (M = !0, console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)", k)); } C.isReactWarning = !0, Object.defineProperty(f, "key", { get: C, configurable: !0 }); }(n, typeof e == "function" ? e.displayName || e.name || "Unknown" : e), function(f, k, C, F, H, a) { var U = C.ref; return f = { $$typeof: K, type: f, key: k, props: C, _owner: F }, (U !== void 0 ? U : null) !== null ? Object.defineProperty(f, "ref", { enumerable: !1, get: j }) : Object.defineProperty(f, "ref", { enumerable: !1, value: null }), f._store = {}, Object.defineProperty(f._store, "validated", { configurable: !1, enumerable: !1, writable: !0, value: 0 }), Object.defineProperty(f, "_debugInfo", { configurable: !1, enumerable: !1, writable: !0, value: null }), Object.defineProperty(f, "_debugStack", { configurable: !1, enumerable: !1, writable: !0, value: H }), Object.defineProperty(f, "_debugTask", { configurable: !1, enumerable: !1, writable: !0, value: a }), Object.freeze && (Object.freeze(f.props), Object.freeze(f)), f; }(e, p, n, (w = z.A) === null ? null : w.getOwner(), b, s); } function S(e) { P(e) ? e._store && (e._store.validated = 1) : typeof e == "object" && e !== null && e.$$typeof === A && (e._payload.status === "fulfilled" ? P(e._payload.value) && e._payload.value._store && (e._payload.value._store.validated = 1) : e._store && (e._store.validated = 1)); } function P(e) { return typeof e == "object" && e !== null && e.$$typeof === K; } var M, L = ye, K = Symbol.for("react.transitional.element"), Q = Symbol.for("react.portal"), D = Symbol.for("react.fragment"), Z = Symbol.for("react.strict_mode"), V = Symbol.for("react.profiler"), ee = Symbol.for("react.consumer"), te = Symbol.for("react.context"), u = Symbol.for("react.forward_ref"), Y = Symbol.for("react.suspense"), N = Symbol.for("react.suspense_list"), I = Symbol.for("react.memo"), A = Symbol.for("react.lazy"), G = Symbol.for("react.activity"), E = Symbol.for("react.client.reference"), z = L.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, W = Object.prototype.hasOwnProperty, B = Array.isArray, X = console.createTask ? console.createTask : function() { return null; }, o = {}, h = (L = { react_stack_bottom_frame: function(e) { return e(); } }).react_stack_bottom_frame.bind(L, v)(), d = X(_(v)), c = {}; q.Fragment = D, q.jsx = function(e, r, n) { var i = 1e4 > z.recentlyCreatedOwnerStacks++; return y(e, r, n, !1, i ? Error("react-stack-top-frame") : h, i ? X(_(e)) : d); }, q.jsxs = function(e, r, n) { var i = 1e4 > z.recentlyCreatedOwnerStacks++; return y(e, r, n, !0, i ? Error("react-stack-top-frame") : h, i ? X(_(e)) : d); }; }()), q); var m = ne.exports; const ie = { x: 0, y: 0, width: 0, height: 0, unit: "px" }; function he(t, l, g) { return Math.min(Math.max(t, l), g); } const de = (t, l, g, _) => _ === "pixel" ? ae(t, l, g) : me(t, l, g), me = (t, l, g) => t.unit === "%" ? { ...ie, ...t, unit: "%" } : { unit: "%", x: t.x ? t.x / l * 100 : 0, y: t.y ? t.y / g * 100 : 0, width: t.width ? t.width / l * 100 : 0, height: t.height ? t.height / g * 100 : 0 }; function ae(t, l, g) { return t.unit ? t.unit === "px" ? { ...ie, ...t, unit: "px" } : { unit: "px", x: t.x ? t.x * l / 100 : 0, y: t.y ? t.y * g / 100 : 0, width: t.width ? t.width * l / 100 : 0, height: t.height ? t.height * g / 100 : 0 } : { ...ie, ...t, unit: "px" }; } const ue = 10, O = { position: "absolute", outline: "1px solid rgba(0,0,0,0.5)", border: "1px solid rgba(255,255,255,0.5)", width: ue, height: ue }, xe = () => m.jsxs(fe, { children: [m.jsx("div", { "data-dir": "s", "data-ord": "s", style: { ...O, bottom: 0, left: "50%", marginBottom: -5, marginLeft: -5, cursor: "s-resize" } }), m.jsx("div", { "data-dir": "n", "data-ord": "n", style: { ...O, top: 0, left: "50%", marginTop: -5, marginLeft: -5, cursor: "n-resize" } }), m.jsx("div", { "data-dir": "w", "data-ord": "w", style: { ...O, top: "50%", left: 0, marginTop: -5, marginLeft: -5, cursor: "w-resize" } }), m.jsx("div", { "data-dir": "e", "data-ord": "e", style: { ...O, top: "50%", right: 0, marginTop: -5, marginRight: -5, cursor: "e-resize" } }), m.jsx("div", { "data-dir": "se", "data-ord": "se", style: { ...O, bottom: 0, right: 0, marginBottom: -5, marginRight: -5, cursor: "se-resize" } }), m.jsx("div", { "data-dir": "sw", "data-ord": "sw", style: { ...O, bottom: 0, left: 0, marginBottom: -5, marginLeft: -5, cursor: "sw-resize" } }), m.jsx("div", { "data-dir": "nw", "data-ord": "nw", style: { ...O, top: 0, left: 0, marginTop: -5, marginLeft: -5, cursor: "nw-resize" } }), m.jsx("div", { "data-dir": "ne", "data-ord": "ne", style: { ...O, top: 0, right: 0, marginTop: -5, marginRight: -5, cursor: "ne-resize" } })] }), be = ({ area: t, onCropStart: l, showHandles: g, globalAreaStyle: _, customAreaRenderer: v, areaNumber: j }) => { const y = { top: `${t.y}${t.unit}`, left: `${t.x}${t.unit}`, width: `${t.width}${t.unit}`, height: `${t.height}${t.unit}` }; return m.jsxs("div", { style: { position: "absolute", border: "1px dashed rgba(0,0,0,0.5)", outline: "1px dashed rgba(255,255,255,0.5)", cursor: "move", boxSizing: "border-box", touchAction: "none", ...y, ..._, ...t.areaStyle }, onPointerDown: l, "data-wrapper": "wrapper", children: [v ? v({ ...t, areaNumber: j }) : null, g ? m.jsx(xe, {}) : null] }); }, we = ({ areas: t }) => m.jsx("table", { style: { position: "absolute", right: 0, top: 8 }, children: m.jsx("tbody", { children: t.map((l, g) => m.jsxs("tr", { children: [m.jsxs("td", { children: ["x: ", Math.round(l.x)] }), m.jsxs("td", { children: ["y: ", Math.round(l.y)] }), m.jsxs("td", { children: ["width: ", Math.round(l.width)] }), m.jsxs("td", { children: ["height: ", Math.round(l.height)] }), m.jsxs("td", { children: ["unit: ", l.unit] })] }, g)) }) }), pe = (t, l) => t !== null && (!!l(t) || pe(t.parentElement, l)), T = { capture: !0, passive: !1 }, ve = ["e", "w"], je = ["n", "s"], Se = ["nw", "ne", "se", "sw"], ke = ({ maxAreas: t = 1 / 0, unit: l = "pixel", minWidth: g = 0, minHeight: _ = 0, debug: v = !1, children: j, areas: y, onChange: S, maxWidth: P, maxHeight: M, wrapperStyle: L, globalAreaStyle: K, customAreaRenderer: Q, mediaWrapperClassName: D }) => { const Z = se(null), V = se(null), [ee, te] = re(0), [u, Y] = re({ startClientX: 0, startClientY: 0, startAreaX: 0, startAreaY: 0, clientX: 0, clientY: 0, isResize: !1 }), [N, I] = re({ areaChangeIndex: 0, isChanging: !1 }), A = () => { const o = V.current; if (!o) return { x: 0, y: 0, width: 0, height: 0 }; const { x: h, y: d, width: c, height: e } = o.getBoundingClientRect(); return { x: h, y: d, width: c, height: e }; }, G = $((o, h, d) => { const c = h - o.x, e = d - o.y < u.startAreaY; return c < u.startAreaX ? e ? "nw" : "sw" : e ? "ne" : "se"; }, [u]), E = $((o) => { const h = A(); return ae(o, h.width, h.height); }, []), z = $((o, h, d) => { const c = A(), e = E(o), r = h - u.startClientX, n = d - u.startClientY; return e.x = he(u.startAreaX + r, 0, c.width - e.width), e.y = he(u.startAreaY + n, 0, c.height - e.height), e; }, [u, E]), W = $((o, h, d) => { const c = A(), e = G(c, h, d), r = E(o), n = u.ord ? u.ord : e, i = h - u.startClientX, b = d - u.startClientY, s = { unit: "px", x: 0, y: 0, width: 0, height: 0, isChanging: !0, isNew: !1 }; e === "ne" ? (s.x = u.startAreaX, s.width = i, s.height = Math.abs(b), s.y = u.startAreaY - s.height) : e === "se" ? (s.x = u.startAreaX, s.y = u.startAreaY, s.width = i, s.height = b) : e === "sw" ? (s.x = u.startAreaX + i, s.y = u.startAreaY, s.width = Math.abs(i), s.height = b) : e === "nw" && (s.x = u.startAreaX + i, s.width = Math.abs(i), s.height = Math.abs(b), s.y = u.startAreaY + b); const w = function(p, x, R, f, k = 0, C = 0, F = R, H = f) { const a = { ...p }; a.y < 0 && (a.height = Math.max(a.height + a.y, C), a.y = 0), a.x < 0 && (a.width = Math.max(a.width + a.x, k), a.x = 0); const U = R - (a.x + a.width); U < 0 && (a.x = Math.min(a.x, R - k), a.width += U); const oe = f - (a.y + a.height); return oe < 0 && (a.y = Math.min(a.y, f - C), a.height += oe), a.width < k && (x !== "sw" && x !== "nw" || (a.x -= k - a.width), a.width = k), a.height < C && (x !== "nw" && x !== "ne" || (a.y -= C - a.height), a.height = C), a.width > F && (x !== "sw" && x !== "nw" || (a.x -= F - a.width), a.width = F), a.height > H && (x !== "nw" && x !== "ne" || (a.y -= H - a.height), a.height = H), a; }(s, e, c.width, c.height, g, _, P, M); return Se.indexOf(n) > -1 ? (r.x = w.x, r.y = w.y, r.width = w.width, r.height = w.height) : ve.indexOf(n) > -1 ? (r.x = w.x, r.width = w.width) : je.indexOf(n) > -1 && (r.y = w.y, r.height = w.height), r; }, [u, G, E, g, _, P, M]), B = $((o) => { o.preventDefault(), o.stopPropagation(); const { isChanging: h, areaChangeIndex: d } = N; if (!h) return; const c = A(), e = y[d], r = o.clientX, n = o.clientY; let i; if (Y((w) => ({ ...w, clientX: r, clientY: n })), i = u.isResize ? W(e, r, n) : z(e, r, n), s = i, (b = e).width !== s.width || b.height !== s.height || b.x !== s.x || b.y !== s.y || b.unit !== s.unit) { const w = de(i, c.width, c.height, l); S([...y.slice(0, d), { ...w }, ...y.slice(d + 1)]); } var b, s; }, [N, y, u, z, S, l, W]), X = $((o) => { o.preventDefault(), o.stopPropagation(); const { isChanging: h, areaChangeIndex: d } = N; if (h) { I({ isChanging: !1, areaChangeIndex: -1 }), Y({ startClientX: 0, startClientY: 0, startAreaX: 0, startAreaY: 0, clientX: 0, clientY: 0, isResize: !1 }); const c = y[d]; S([...y.slice(0, d), { ...c, isNew: !1, isChanging: !1 }, ...y.slice(d + 1)]); } }, [N, y, S]); return ge(() => (document.addEventListener("pointermove", B, T), document.addEventListener("pointerup", X, T), document.addEventListener("pointercancel", X, T), () => { document.removeEventListener("pointermove", B, T), document.removeEventListener("pointerup", X, T), document.removeEventListener("pointercancel", X, T); }), [B, X]), m.jsxs("div", { ref: Z, style: { position: "relative", display: "inline-block", cursor: "crosshair", boxSizing: "border-box", maxWidth: "100%", touchAction: "none", lineHeight: 0, ...L }, children: [m.jsx("div", { ref: V, onPointerDown: (o) => { const h = o.currentTarget; if (h.dataset.wrapper || h.dataset.direction || pe(h, (b) => { var s; return !!((s = b.dataset) != null && s.wrapper); })) return; o.preventDefault(), o.stopPropagation(); const d = A(), c = o.clientX - d.x, e = o.clientY - d.y, r = { unit: "px", x: c, y: e, width: 0, height: 0, isChanging: !0, isNew: !0 }; Y({ startClientX: o.clientX, startClientY: o.clientY, startAreaX: c, startAreaY: e, clientX: o.clientX, clientY: o.clientY, isResize: !0 }), te(ee + 1); const n = de(r, d.width, d.height, l); let i; y.length < t ? (S(y.concat(n)), i = y.length) : (S([...y.slice(0, t - 1), n]), i = t - 1), I({ areaChangeIndex: i, isChanging: !0 }); }, style: { boxSizing: "border-box" }, className: D, children: j }), y.map((o, h) => m.jsx(be, { area: o, showHandles: !o.isNew, onCropStart: (d) => ((c, e) => { c.preventDefault(), c.stopPropagation(); const r = A(), n = ae(y[e], r.width, r.height), i = c.target.dataset.ord, b = !!i; let s = c.clientX, w = c.clientY, p = n.x, x = n.y; i && (i === "ne" || i == "e" ? (p = n.x, x = n.y + n.height) : i === "se" || i === "s" ? (p = n.x, x = n.y) : i === "sw" || i == "w" ? (p = n.x + n.width, x = n.y) : i !== "nw" && i != "n" || (p = n.x + n.width, x = n.y + n.height), s = p + r.x, w = x + r.y), Y({ startClientX: s, startClientY: w, startAreaX: p, startAreaY: x, clientX: c.clientX, clientY: c.clientY, isResize: b, ord: i }), I({ isChanging: !0, areaChangeIndex: e }); })(d, h), globalAreaStyle: K, customAreaRenderer: Q, areaNumber: h + 1 }, h)), v ? m.jsx(we, { areas: y }) : null] }); }; export { ke as AreaSelector };