UNPKG

solid-contextmenu

Version:

Add contextmenu to your solid app with ease

326 lines (325 loc) 11.2 kB
import { createComponent as k, Portal as Q, mergeProps as U, spread as I, effect as M, className as P, template as W, delegateEvents as X, insert as N } from "solid-js/web"; import { createSignal as D, children as Z, mergeProps as F, createComputed as S, untrack as Y, batch as ee, createContext as te, useContext as ne, splitProps as O, onCleanup as R, createMemo as E, Show as p } from "solid-js"; var g = /* @__PURE__ */ ((e) => (e.menu = "solid-contextmenu", e.submenu = "solid-contextmenu solid-contextmenu__submenu", e.submenuArrow = "solid-contextmenu__submenu-arrow", e.submenuOpen = "solid-contextmenu__submenu--is-open", e.separator = "solid-contextmenu__separator", e.item = "solid-contextmenu__item", e.itemDisabled = "solid-contextmenu__item--disabled", e.itemContent = "solid-contextmenu__item__content", e.theme = "solid-contextmenu__theme--", e.animationWillEnter = "solid-contextmenu__will-enter--", e.animationWillLeave = "solid-contextmenu__will-leave--", e))(g || {}), ie = /* @__PURE__ */ ((e) => (e[e.HIDE_ALL = 0] = "HIDE_ALL", e))(ie || {}); const _e = { light: "light", dark: "dark" }, ge = { fade: "fade", flip: "flip", scale: "scale", slide: "slide" }; function j(e) { requestAnimationFrame(() => { requestAnimationFrame(e); }); } const se = (e) => { let t, s = !0; const [i, f] = D(), [A, w] = D(), x = Z(() => e.children), h = e.name || "s"; e = F({ name: h, enterActiveClass: h + "-enter-active", enterClass: h + "-enter", enterToClass: h + "-enter-to", exitActiveClass: h + "-exit-active", exitClass: h + "-exit", exitToClass: h + "-exit-to" }, e); const { onBeforeEnter: b, onEnter: a, onAfterEnter: $, onBeforeExit: m, onExit: C, onAfterExit: r } = e; function y(n, o) { if (!s || e.appear) { let l = function(u) { n && (!u || u.target === n) && (n.removeEventListener("transitionend", l), n.removeEventListener("animationend", l), n.classList.remove(..._), n.classList.remove(...d), ee(() => { i() !== n && f(n), A() === n && w(void 0); }), $ && $(n), e.mode === "inout" && v(n, o)); }; const c = e.enterClass.split(" "), _ = e.enterActiveClass.split(" "), d = e.enterToClass.split(" "); b && b(n), n.classList.add(...c), n.classList.add(..._), j(() => { n.classList.remove(...c), n.classList.add(...d), a && a(n, () => l()), (!a || a.length < 2) && (n.addEventListener("transitionend", l), n.addEventListener("animationend", l)); }); } o && !e.mode ? w(n) : f(n); } function v(n, o) { const c = e.exitClass.split(" "), _ = e.exitActiveClass.split(" "), d = e.exitToClass.split(" "); if (!o.parentNode) return l(); m && m(o), o.classList.add(...c), o.classList.add(..._), j(() => { o.classList.remove(...c), o.classList.add(...d); }), C && C(o, () => l()), (!C || C.length < 2) && (o.addEventListener("transitionend", l), o.addEventListener("animationend", l)); function l(u) { (!u || u.target === o) && (o.removeEventListener("transitionend", l), o.removeEventListener("animationend", l), o.classList.remove(..._), o.classList.remove(...d), i() === o && f(void 0), r && r(o), e.mode === "outin" && y(n, o)); } } return S((n) => { for (t = x(); typeof t == "function"; ) t = t(); return Y(() => (t && t !== n && (e.mode !== "outin" ? y(t, n) : s && f(t)), n && n !== t && e.mode !== "inout" && v(t, n), s = !1, t)); }), [i, A]; }; function oe(e) { return { all: e = e || /* @__PURE__ */ new Map(), on: function(t, s) { var i = e.get(t); i ? i.push(s) : e.set(t, [s]); }, off: function(t, s) { var i = e.get(t); i && (s ? i.splice(i.indexOf(s) >>> 0, 1) : e.set(t, [])); }, emit: function(t, s) { var i = e.get(t); i && i.slice().map(function(f) { f(s); }), (i = e.get("*")) && i.slice().map(function(f) { f(t, s); }); } }; } const L = oe(), G = te(), J = () => ne(G); function K(e) { var t, s, i = ""; if (typeof e == "string" || typeof e == "number") i += e; else if (typeof e == "object") if (Array.isArray(e)) for (t = 0; t < e.length; t++) e[t] && (s = K(e[t])) && (i && (i += " "), i += s); else for (t in e) e[t] && (i && (i += " "), i += t); return i; } function z() { for (var e, t, s = 0, i = ""; s < arguments.length; ) (e = arguments[s++]) && (t = K(e)) && (i && (i += " "), i += t); return i; } const re = /* @__PURE__ */ W("<div></div>", 2), T = (e, t, s) => e + t <= s ? e : e < t ? s - t : e - t, de = (e, t) => { const s = { width: window.innerWidth, height: window.innerHeight }; return { x: T(e.x, t.width, s.width), y: T(e.y, t.height, s.height) }; }, we = (e) => { const [t, s] = O(e, ["id", "theme", "animation", "onShown", "onHidden"]), [i, f] = D(!1), [A, w] = D({ x: 0, y: 0 }); let x; const [h, b] = D(); L.on("show", (r) => { r.id === t.id && (r.event.preventDefault(), b(r.props), f(!0), w(r.position ?? de({ x: r.event.clientX, y: r.event.clientY }, { width: x.offsetWidth, height: x.offsetHeight }))); }); const a = () => { L.emit("hide", t.id), f(!1); }, $ = F({ shown: i, animation: "scale", hide: a, props: h }, t); L.on("hideAll", () => { a(); }), R(() => { L.off("show"), L.off("hideAll"); }); const m = E(() => { let r = ""; return t.animation && (r = `solid-contextmenu-${t.animation}`), console.log(r), r; }), C = E(() => ({ enterActiveClass: m() + "-enter-active", exitActiveClass: m() + "-exit-active" })); return k(G.Provider, { value: $, get children() { return k(Q, { get children() { return k(se, U(C, { get children() { return k(p, { get when() { return i(); }, get children() { const r = re.cloneNode(!0), y = x; return typeof y == "function" ? y(r) : x = r, ae(r, () => a()), I(r, s, !1, !1), M((v) => { const n = z(g.menu, s.class, { [`${g.theme}${t.theme}`]: t.theme }), o = A().x + "px", c = A().y + "px"; return n !== v._v$ && P(r, v._v$ = n), o !== v._v$2 && r.style.setProperty("left", v._v$2 = o), c !== v._v$3 && r.style.setProperty("top", v._v$3 = c), v; }, { _v$: void 0, _v$2: void 0, _v$3: void 0 }), r; } }); } })); } }); } }); }; function ae(e, t) { const s = (i) => !e.contains(i.target) && t()?.(); document.body.addEventListener("click", s), R(() => document.body.removeEventListener("click", s)); } function le(e) { return typeof e == "function"; } function B(e, t) { return le(e) ? e(t) : e; } const ce = /* @__PURE__ */ W("<div><div></div></div>", 4), xe = (e) => { const [t, s] = O(e, ["hidden", "disabled", "onClick", "data", "children"]), i = F({ hidden: !1, disabled: !1 }, t), { props: f, hide: A } = J(), w = E(() => ({ props: f(), data: e.data })), x = E(() => B(i.disabled, w())), h = E(() => B(i.hidden, w())), b = (a) => { x() || (e.onClick?.({ event: a, ...w() }), A()); }; return k(p, { get when() { return !h(); }, get children() { const a = ce.cloneNode(!0), $ = a.firstChild; return a.$$click = b, I(a, s, !1, !0), N($, () => t.children), M((m) => { const C = z(g.item, { [g.itemDisabled]: x() }), r = g.itemContent; return C !== m._v$ && P(a, m._v$ = C), r !== m._v$2 && P($, m._v$2 = r), m; }, { _v$: void 0, _v$2: void 0 }), a; } }); }; X(["click"]); const ue = /* @__PURE__ */ W("<div></div>", 2), $e = () => (() => { const e = ue.cloneNode(!0); return M(() => P(e, g.separator)), e; })(), fe = /* @__PURE__ */ W("<div></div>", 2), he = /* @__PURE__ */ W("<div><div><span></span></div></div>", 6), Ce = (e) => { const [t, s] = O(e, ["arrow", "children", "disabled", "hidden", "label", "class"]), i = F({ arrow: "\u25B6\uFE0F", disabled: !1, hidden: !1 }, t), { props: f, id: A } = J(), w = E(() => ({ props: f() })), x = E(() => B(i.disabled, w())), h = E(() => B(i.hidden, w())); let b, a; const [$, m] = D({ x: 0, y: 0 }), C = () => { const n = b.getBoundingClientRect(), o = a.getBoundingClientRect(), c = { width: window.innerWidth, height: window.innerHeight }; let _ = n.right; _ + o.width > c.width && (n.left - o.width > 0 ? _ = n.left - o.width : _ = c.width - o.width); let d = n.top; d + o.height > c.height && (n.bottom - o.height > 0 ? d = n.bottom - o.height : d = c.height - o.height), m({ x: _, y: d }), console.log($()); }, [r, y] = D(!1), v = () => { y(!0), C(); }; return L.on("hide", (n) => { n === A && y(!1); }), R(() => { L.off("hide"); }), k(p, { get when() { return !h(); }, get children() { const n = he.cloneNode(!0), o = n.firstChild, c = o.firstChild; n.$$click = () => r() ? y(!1) : v(), n.addEventListener("mouseleave", () => y(!1)), n.addEventListener("mouseenter", () => v()), I(n, s, !1, !0); const _ = b; return typeof _ == "function" ? _(o) : b = o, N(o, () => i.label, c), N(c, () => i.arrow), N(n, k(p, { get when() { return r(); }, get children() { const d = fe.cloneNode(!0), l = a; return typeof l == "function" ? l(d) : a = d, N(d, () => i.children), M((u) => { const H = g.submenu, V = $().x + "px", q = $().y + "px"; return H !== u._v$ && P(d, u._v$ = H), V !== u._v$2 && d.style.setProperty("left", u._v$2 = V), q !== u._v$3 && d.style.setProperty("top", u._v$3 = q), u; }, { _v$: void 0, _v$2: void 0, _v$3: void 0 }), d; } }), null), M((d) => { const l = z(g.item, t.class, { [g.itemDisabled]: x() }), u = g.itemContent, H = g.submenuArrow; return l !== d._v$4 && P(n, d._v$4 = l), u !== d._v$5 && P(o, d._v$5 = u), H !== d._v$6 && P(c, d._v$6 = H), d; }, { _v$4: void 0, _v$5: void 0, _v$6: void 0 }), n; } }); }; X(["click"]); const be = (e) => ({ show: (t, s) => { process.env.NODE_ENV === "development" && !e?.id && !s?.id && console.error( "You need to provide an id when initializing the hook `useContextMenu({ id: 'your id' })` or when you display the menu `show(e, { id: 'your id' })`. The later is used to override the one defined during initialization." ), L.emit("show", { id: s?.id || e?.id, props: s?.props || e?.props, event: t, position: s?.position }); }, hideAll: () => { L.emit("hideAll"); } }); export { ie as EVENT, xe as Item, we as Menu, g as STYLE, $e as Separator, Ce as Submenu, ge as animation, _e as theme, be as useContextMenu };