UNPKG

react-wheel-menu

Version:

React components & hooks for building a radial wheel menu

491 lines (490 loc) 8.9 kB
import { useState as w, useCallback as O, useEffect as D, createContext as N, useContext as T } from "react"; import { useRect as x } from "react-use-rect"; import { jsx as f } from "react/jsx-runtime"; import { clsx as d } from "clsx"; function y(t) { if (typeof t == "number") return t; if (t.endsWith("deg")) return m(t, "deg"); if (t.endsWith("grad")) return m(t, "grad") * 0.9; if (t.endsWith("rad")) return m(t, "rad") * 180 / Math.PI; if (t.endsWith("turn")) return m(t, "turn") * 360; if (t.endsWith("%")) return m(t, "%") * 360 / 100; throw new Error(`angle must have a unit in [${Y}], but was: ${t}`); } const F = [ "deg", "grad", "rad", "turn", "%" ], Y = F.join(", "); function m(t, e) { return Number(t.substring(0, t.length - e.length)); } function b(t, e) { return t === 0 ? 0 : t === e ? t : (t % e + e) % e; } const M = 360; function g(t) { return b(t, M); } function j(t, e, n, s) { const r = n - t, o = s - e; return Math.atan2(o, r); } function W(t) { const e = t.x + t.width / 2, n = t.y + t.height / 2; return [e, n]; } function B(t) { const [e, n] = w(null), s = O((a) => { n(W(a)); }, []), [r, o] = x(s, t); return { midpoint: e, setElement: r, revalidate: o }; } function R() { const [t, e] = w(0), [n, s] = w(0); return D(() => { if (!(typeof window > "u")) { let r = function(o) { e(o.x), s(o.y); }; return window.addEventListener("mousemove", r), function() { window.removeEventListener("mousemove", r); }; } }, []), [t, n]; } function kt() { const t = R(), { midpoint: e, setElement: n } = B(); if (e === null) return { ref: n, angle: null }; { const [s, r] = e, [o, a] = t; return { ref: n, angle: j(s, r, o, a) }; } } const Ut = [ "start", "center", "end" ], X = "center", S = 0, _t = [ "downwards", "upwards", "inwards", "outwards", "clockwise", "counterclockwise" ], $ = "downwards"; function J(t, e) { switch (e) { case "downwards": return -t; case "upwards": return 180 - t; case "inwards": return 0; case "outwards": return 180; case "clockwise": return 270; case "counterclockwise": return 90; } } function G(t, e = $, n = S, s) { const r = K(n), o = z(e, t), a = [ r, o ]; return s !== void 0 && a.push(s), a.filter(q).join(" "); } function K(t) { return t === 0 || t === "" ? "" : `translateY(${V(t)})`; } function z(t, e) { const n = J(e, t); return n === 0 ? "" : `rotate(${n}deg)`; } function V(t, e = "px") { return typeof t == "number" ? `${t}${e}` : t; } function q(t) { return t.length > 0; } const L = { from: 0, to: 0, magnitude: 0 }, A = N(L); function P() { return T(A); } const I = { angle: 0 }, k = N(I); function H() { return T(k); } function Q() { const t = P(), e = H(); return t !== L ? Z(t) : e !== I ? e.angle : 0; } function Z(t) { const { from: e, magnitude: n } = t; return e + n / 2; } function tt(t) { const { className: e, style: n, orient: s = $, justify: r = X, offset: o = S } = t, a = Q(), c = d( e, "wheel-label", `wheel-label--${r}` ), u = { ...n, transform: G(a, s, o, n?.transform) }; return { className: c, style: u }; } function vt(t) { const { as: e = "span", className: n, style: s, orient: r, justify: o, offset: a, ...c } = t, u = tt({ className: n, style: s, orient: r, justify: o, offset: a }); return /* @__PURE__ */ f( e, { ...u, ...c } ); } const Ct = [ "horizontal", "vertical" ], et = "vertical", Ot = [ "start", "center", "end" ], nt = "center", st = "translateX(-50%)", rt = "translateY(50%)"; function ot(t, e) { if (t === 0) return e; { const n = at(t), s = ct(t), r = [ st, n, s, rt ]; return e !== void 0 && r.push(e), r.filter(ut).join(" "); } } function at(t) { const e = -(t - 90); return e === 0 ? "" : `skew(${e}deg)`; } function ct(t) { const e = 90 - t / 2; return e === 0 ? "" : `rotate(${e}deg)`; } function ut(t) { return t.length > 0; } function it(t) { const { className: e, style: n, direction: s = et, justify: r = nt } = t, { magnitude: o } = P(), a = d( e, "wheel-layout", `wheel-layout--${s}`, `wheel-layout--${r}` ), c = { ...n, transform: ot(o, n?.transform) }; return { className: a, style: c }; } function Dt(t) { const { as: e = "span", className: n, style: s, direction: r, justify: o, ...a } = t, c = it({ className: n, style: s, direction: r, justify: o }); return /* @__PURE__ */ f( e, { ...c, ...a } ); } function lt(t, e) { const { from: n, magnitude: s, gapBefore: r, gapAfter: o } = t, a = ft(n, s), c = mt(s), u = dt(r, o), i = [ a, c, u ]; return e !== void 0 && i.push(e), i.filter(pt).join(" "); } function ft(t, e) { const n = t + e - 90; return n === 0 ? "" : `rotate(${n}deg)`; } function mt(t) { const e = t - 90; return e === 0 ? "" : `skew(${e}deg)`; } function dt(t, e) { if (t !== void 0 && e !== void 0) { const n = p(t), s = p(e); return `translate(${n}, -${s})`; } else return t !== void 0 ? `translateX(${p(t)})` : e !== void 0 ? `translateY(-${p(e)})` : ""; } function p(t, e = "px") { return typeof t == "number" ? `${t}${e}` : t; } function pt(t) { return t.length > 0; } function gt(t) { const { className: e, style: n, from: s, to: r, gapBefore: o, gapAfter: a } = t, c = y(s), u = y(r), i = g(c), l = g(u), h = g(u - c), _ = Math.min(150, h), E = { from: i, to: l, magnitude: _, gapBefore: o, gapAfter: a }, v = d( e, "wheel-segment" ), C = { ...n, transform: lt(E, n?.transform) }; return { state: E, className: v, style: C }; } function xt(t) { const { as: e = "div", className: n, style: s, from: r, to: o, gapBefore: a, gapAfter: c, children: u, ...i } = t, { state: l, ...h } = gt({ className: n, style: s, from: r, to: o, gapBefore: a, gapAfter: c }); return /* @__PURE__ */ f(e, { ...h, ...i, children: /* @__PURE__ */ f(A.Provider, { value: l, children: u }) }); } const ht = "center", U = 0; function wt(t, e = U, n) { const s = yt(t), r = Et(e), o = [ s, r ]; return n !== void 0 && o.push(n), o.filter(Tt).join(" "); } function yt(t) { return t === 0 ? "" : `rotate(${t}deg)`; } function Et(t) { return t === 0 || t === "" ? "" : `translateY(${Nt(t)})`; } function Nt(t, e = "px") { return typeof t == "number" ? `${t}${e}` : t; } function Tt(t) { return t.length > 0; } function St(t) { const { className: e, style: n, angle: s, align: r = ht, offset: o = U } = t, a = y(s), c = g(a), u = { angle: c }, i = d( e, "wheel-spoke", `wheel-spoke--${r}` ), l = { ...n, transform: wt(c, o, n?.transform) }; return { state: u, className: i, style: l }; } function Ft(t) { const { as: e = "span", className: n, style: s, angle: r, align: o, offset: a, children: c, ...u } = t, { state: i, ...l } = St({ className: n, style: s, angle: r, align: o, offset: a }); return /* @__PURE__ */ f(e, { ...l, ...u, children: /* @__PURE__ */ f(k.Provider, { value: i, children: c }) }); } function $t(t) { const { className: e } = t; return { className: d( e, "wheel" ) }; } function Yt(t) { const { as: e = "div", className: n, ...s } = t, r = $t({ className: n }); return /* @__PURE__ */ f( e, { ...r, ...s } ); } export { X as DEFAULT_LABEL_JUSTIFICATION, S as DEFAULT_LABEL_OFFSET, $ as DEFAULT_LABEL_ORIENTATION, et as DEFAULT_LAYOUT_DIRECTION, nt as DEFAULT_LAYOUT_JUSTIFICATION, ht as DEFAULT_SPOKE_ALIGNMENT, U as DEFAULT_SPOKE_OFFSET, L as DefaultSegmentState, I as DefaultSpokeState, Ut as LABEL_JUSTIFICATIONS, _t as LABEL_ORIENTATIONS, Ct as LAYOUT_DIRECTIONS, Ot as LAYOUT_JUSTIFICATIONS, vt as Label, Dt as Layout, xt as Segment, A as SegmentStateContext, Ft as Spoke, k as SpokeStateContext, Yt as Wheel, y as angleToDegrees, g as moduloDegrees, j as radiansBetween, J as rotateLabel, G as transformLabel, ot as transformLayout, lt as transformSegment, wt as transformSpoke, kt as useElementToMouseAngle, tt as useLabel, it as useLayout, gt as useSegment, P as useSegmentState, St as useSpoke, H as useSpokeState, $t as useWheel };