react-wheel-menu
Version:
React components & hooks for building a radial wheel menu
491 lines (490 loc) • 8.9 kB
JavaScript
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
};