react-rubiks-cube 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +190 -0
- package/dist/cubex.js +586 -0
- package/dist/cubex.umd.cjs +1 -0
- package/package.json +70 -0
- package/src/AutoCubeScene.jsx +190 -0
- package/src/CubeOverlay.jsx +211 -0
- package/src/InteractiveCubeScene.jsx +196 -0
- package/src/RubiksCube.jsx +109 -0
- package/src/index.d.ts +116 -0
- package/src/index.js +11 -0
- package/src/palette.js +48 -0
- package/src/primitives.jsx +66 -0
package/dist/cubex.js
ADDED
|
@@ -0,0 +1,586 @@
|
|
|
1
|
+
import { jsx as l, jsxs as E, Fragment as Z } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo as J, useRef as M, useCallback as B, useState as O, useEffect as j } from "react";
|
|
3
|
+
import { useFrame as ee, useThree as ae, Canvas as te } from "@react-three/fiber";
|
|
4
|
+
import * as A from "three";
|
|
5
|
+
import { Vector3 as U, BoxGeometry as ce } from "three";
|
|
6
|
+
import { createPortal as le } from "react-dom";
|
|
7
|
+
import { OrbitControls as ue } from "@react-three/drei";
|
|
8
|
+
import { AnimatePresence as de, motion as $ } from "framer-motion";
|
|
9
|
+
const I = new U();
|
|
10
|
+
function C(e, t, n, r, f, o) {
|
|
11
|
+
const h = 2 * Math.PI * f / 4, m = Math.max(o - 2 * f, 0), b = Math.PI / 4;
|
|
12
|
+
I.copy(t), I[r] = 0, I.normalize();
|
|
13
|
+
const s = 0.5 * h / (h + m), w = 1 - I.angleTo(e) / b;
|
|
14
|
+
return Math.sign(I[n]) === 1 ? w * s : m / (h + m) + s + s * (1 - w);
|
|
15
|
+
}
|
|
16
|
+
class W extends ce {
|
|
17
|
+
/**
|
|
18
|
+
* Constructs a new rounded box geometry.
|
|
19
|
+
*
|
|
20
|
+
* @param {number} [width=1] - The width. That is, the length of the edges parallel to the X axis.
|
|
21
|
+
* @param {number} [height=1] - The height. That is, the length of the edges parallel to the Y axis.
|
|
22
|
+
* @param {number} [depth=1] - The depth. That is, the length of the edges parallel to the Z axis.
|
|
23
|
+
* @param {number} [segments=2] - Number of segments that form the rounded corners.
|
|
24
|
+
* @param {number} [radius=0.1] - The radius of the rounded corners.
|
|
25
|
+
*/
|
|
26
|
+
constructor(t = 1, n = 1, r = 1, f = 2, o = 0.1) {
|
|
27
|
+
const h = f * 2 + 1;
|
|
28
|
+
if (o = Math.min(t / 2, n / 2, r / 2, o), super(1, 1, 1, h, h, h), this.type = "RoundedBoxGeometry", this.parameters = {
|
|
29
|
+
width: t,
|
|
30
|
+
height: n,
|
|
31
|
+
depth: r,
|
|
32
|
+
segments: f,
|
|
33
|
+
radius: o
|
|
34
|
+
}, h === 1) return;
|
|
35
|
+
const m = this.toNonIndexed();
|
|
36
|
+
this.index = null, this.attributes.position = m.attributes.position, this.attributes.normal = m.attributes.normal, this.attributes.uv = m.attributes.uv;
|
|
37
|
+
const b = new U(), s = new U(), w = new U(t, n, r).divideScalar(2).subScalar(o), d = this.attributes.position.array, g = this.attributes.normal.array, u = this.attributes.uv.array, S = d.length / 6, a = new U(), z = 0.5 / h;
|
|
38
|
+
for (let v = 0, i = 0; v < d.length; v += 3, i += 2)
|
|
39
|
+
switch (b.fromArray(d, v), s.copy(b), s.x -= Math.sign(s.x) * z, s.y -= Math.sign(s.y) * z, s.z -= Math.sign(s.z) * z, s.normalize(), d[v + 0] = w.x * Math.sign(b.x) + s.x * o, d[v + 1] = w.y * Math.sign(b.y) + s.y * o, d[v + 2] = w.z * Math.sign(b.z) + s.z * o, g[v + 0] = s.x, g[v + 1] = s.y, g[v + 2] = s.z, Math.floor(v / S)) {
|
|
40
|
+
case 0:
|
|
41
|
+
a.set(1, 0, 0), u[i + 0] = C(a, s, "z", "y", o, r), u[i + 1] = 1 - C(a, s, "y", "z", o, n);
|
|
42
|
+
break;
|
|
43
|
+
case 1:
|
|
44
|
+
a.set(-1, 0, 0), u[i + 0] = 1 - C(a, s, "z", "y", o, r), u[i + 1] = 1 - C(a, s, "y", "z", o, n);
|
|
45
|
+
break;
|
|
46
|
+
case 2:
|
|
47
|
+
a.set(0, 1, 0), u[i + 0] = 1 - C(a, s, "x", "z", o, t), u[i + 1] = C(a, s, "z", "x", o, r);
|
|
48
|
+
break;
|
|
49
|
+
case 3:
|
|
50
|
+
a.set(0, -1, 0), u[i + 0] = 1 - C(a, s, "x", "z", o, t), u[i + 1] = 1 - C(a, s, "z", "x", o, r);
|
|
51
|
+
break;
|
|
52
|
+
case 4:
|
|
53
|
+
a.set(0, 0, 1), u[i + 0] = 1 - C(a, s, "x", "y", o, t), u[i + 1] = 1 - C(a, s, "y", "x", o, n);
|
|
54
|
+
break;
|
|
55
|
+
case 5:
|
|
56
|
+
a.set(0, 0, -1), u[i + 0] = C(a, s, "x", "y", o, t), u[i + 1] = 1 - C(a, s, "y", "x", o, n);
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Factory method for creating an instance of this class from the given
|
|
62
|
+
* JSON object.
|
|
63
|
+
*
|
|
64
|
+
* @param {Object} data - A JSON object representing the serialized geometry.
|
|
65
|
+
* @returns {RoundedBoxGeometry} A new instance.
|
|
66
|
+
*/
|
|
67
|
+
static fromJSON(t) {
|
|
68
|
+
return new W(
|
|
69
|
+
t.width,
|
|
70
|
+
t.height,
|
|
71
|
+
t.depth,
|
|
72
|
+
t.segments,
|
|
73
|
+
t.radius
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
const Q = {
|
|
78
|
+
right: { color: "#E05C28", roughness: 0.34, metalness: 0 },
|
|
79
|
+
// accent orange
|
|
80
|
+
left: { color: "#00C9A7", roughness: 0.34, metalness: 0 },
|
|
81
|
+
// mint teal
|
|
82
|
+
up: { color: "#EDE3D1", roughness: 0.44, metalness: 0 },
|
|
83
|
+
// ink cream
|
|
84
|
+
down: { color: "#C8963E", roughness: 0.36, metalness: 0 },
|
|
85
|
+
// gold
|
|
86
|
+
front: { color: "#B23E22", roughness: 0.36, metalness: 0 },
|
|
87
|
+
// deep terracotta
|
|
88
|
+
back: { color: "#0B7A6E", roughness: 0.38, metalness: 0 },
|
|
89
|
+
// deep teal
|
|
90
|
+
inner: { color: "#1C1A17", roughness: 0.82, metalness: 0 }
|
|
91
|
+
// dark body
|
|
92
|
+
}, pe = {
|
|
93
|
+
right: { color: "#B71234", roughness: 0.3, metalness: 0 },
|
|
94
|
+
// red
|
|
95
|
+
left: { color: "#FF5800", roughness: 0.3, metalness: 0 },
|
|
96
|
+
// orange
|
|
97
|
+
up: { color: "#FFFFFF", roughness: 0.4, metalness: 0 },
|
|
98
|
+
// white
|
|
99
|
+
down: { color: "#FFD500", roughness: 0.32, metalness: 0 },
|
|
100
|
+
// yellow
|
|
101
|
+
front: { color: "#009B48", roughness: 0.32, metalness: 0 },
|
|
102
|
+
// green
|
|
103
|
+
back: { color: "#0046AD", roughness: 0.32, metalness: 0 },
|
|
104
|
+
// blue
|
|
105
|
+
inner: { color: "#111111", roughness: 0.85, metalness: 0 }
|
|
106
|
+
// black body
|
|
107
|
+
}, re = ["right", "left", "up", "down", "front", "back"];
|
|
108
|
+
function fe(e) {
|
|
109
|
+
if (!e) return Q;
|
|
110
|
+
const t = e.base === "classic" ? pe : Q, n = {};
|
|
111
|
+
for (const r of [...re, "inner"])
|
|
112
|
+
n[r] = { ...t[r], ...e[r] || {} };
|
|
113
|
+
return n;
|
|
114
|
+
}
|
|
115
|
+
const he = new W(0.95, 0.95, 0.95, 4, 0.045), ne = (e) => (e = Math.max(0, Math.min(1, e)), e * e * e * (e * (e * 6 - 15) + 10));
|
|
116
|
+
function oe({ px: e, py: t, pz: n, palette: r }) {
|
|
117
|
+
const f = J(
|
|
118
|
+
() => [e === 1, e === -1, t === 1, t === -1, n === 1, n === -1],
|
|
119
|
+
[e, t, n]
|
|
120
|
+
);
|
|
121
|
+
return /* @__PURE__ */ l("mesh", { position: [e, t, n], geometry: he, children: f.map((o, h) => {
|
|
122
|
+
const m = o ? r[re[h]] : r.inner;
|
|
123
|
+
return /* @__PURE__ */ l(
|
|
124
|
+
"meshStandardMaterial",
|
|
125
|
+
{
|
|
126
|
+
attach: `material-${h}`,
|
|
127
|
+
color: m.color,
|
|
128
|
+
roughness: m.roughness,
|
|
129
|
+
metalness: m.metalness
|
|
130
|
+
},
|
|
131
|
+
h
|
|
132
|
+
);
|
|
133
|
+
}) });
|
|
134
|
+
}
|
|
135
|
+
function ie({ ambient: e = 0.22 }) {
|
|
136
|
+
return /* @__PURE__ */ E(Z, { children: [
|
|
137
|
+
/* @__PURE__ */ l("directionalLight", { position: [5, 8, 4], intensity: 2.4, color: "#fff6ee" }),
|
|
138
|
+
/* @__PURE__ */ l("directionalLight", { position: [-5, -3, -4], intensity: 0.6, color: "#ffe0cf" }),
|
|
139
|
+
/* @__PURE__ */ l("directionalLight", { position: [-4, 6, -6], intensity: 1.5, color: "#cfe4ff" }),
|
|
140
|
+
/* @__PURE__ */ l("ambientLight", { intensity: e }),
|
|
141
|
+
/* @__PURE__ */ l("pointLight", { position: [-1, 1, 5], intensity: 0.85, color: "#fff5ee", distance: 18 })
|
|
142
|
+
] });
|
|
143
|
+
}
|
|
144
|
+
function se() {
|
|
145
|
+
return J(() => {
|
|
146
|
+
const e = [];
|
|
147
|
+
for (let t = -1; t <= 1; t++)
|
|
148
|
+
for (let n = -1; n <= 1; n++)
|
|
149
|
+
for (let r = -1; r <= 1; r++) e.push([t, n, r]);
|
|
150
|
+
return e;
|
|
151
|
+
}, []);
|
|
152
|
+
}
|
|
153
|
+
const V = ["x", "y", "z"], _ = () => Math.random() < 0.5 ? 1 : -1;
|
|
154
|
+
function me(e) {
|
|
155
|
+
for (let t = 0; t < 8; t++) {
|
|
156
|
+
const n = V[Math.random() * 3 | 0], r = [-1, 0, 1][Math.random() * 3 | 0], f = _(), o = Math.random() < 0.82 ? 1 : 2;
|
|
157
|
+
if (!(e && e.axis === n && e.layer === r && e.dir === -f && e.quarter === o))
|
|
158
|
+
return { axis: n, layer: r, dir: f, quarter: o };
|
|
159
|
+
}
|
|
160
|
+
return { axis: "y", layer: 1, dir: 1, quarter: 1 };
|
|
161
|
+
}
|
|
162
|
+
function ye(e, t, n) {
|
|
163
|
+
return n === null ? e : e.filter((r) => {
|
|
164
|
+
const f = r.position[t];
|
|
165
|
+
return n === 0 ? Math.abs(f) < 0.5 : n > 0 ? f > 0.5 : f < -0.5;
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
const Y = new A.Quaternion(), X = new A.Quaternion(), H = new A.Quaternion(), G = new A.Quaternion(), ge = new A.Vector3(0.58, 0.77, -0.27).normalize(), xe = new A.Vector3(-0.41, 0.35, 0.84).normalize(), be = new A.Vector3(0.22, -0.62, 0.75).normalize();
|
|
169
|
+
function ve(e) {
|
|
170
|
+
const t = Math.random();
|
|
171
|
+
if (t < 0.16)
|
|
172
|
+
return { moves: [{ axis: V[Math.random() * 3 | 0], layer: [-1, 0, 1][Math.random() * 3 | 0], dir: _(), quarter: 4 }], record: null };
|
|
173
|
+
if (t < 0.54) {
|
|
174
|
+
const r = V[Math.random() * 3 | 0], f = [-1, 0, 1], o = Math.random() * 3 | 0;
|
|
175
|
+
let h = Math.random() * 3 | 0;
|
|
176
|
+
for (; h === o; ) h = Math.random() * 3 | 0;
|
|
177
|
+
const m = [o, h].map((b) => ({ axis: r, layer: f[b], dir: _(), quarter: Math.random() < 0.25 ? 2 : 1 }));
|
|
178
|
+
return { moves: m, record: m };
|
|
179
|
+
}
|
|
180
|
+
const n = me(e);
|
|
181
|
+
return { moves: [n], record: [n] };
|
|
182
|
+
}
|
|
183
|
+
function K(e, t, n, r) {
|
|
184
|
+
ye(n.children.slice(), r.axis, r.layer).forEach((f) => t.attach(f)), e.ref = t, e.axis = r.axis, e.target = Math.PI / 2 * r.dir * r.quarter, e.elapsed = 0, e.duration = 0.42 * r.quarter + 0.16 + Math.random() * 0.3, e.active = !0;
|
|
185
|
+
}
|
|
186
|
+
function Me({ palette: e, scrollRef: t, scale: n = 0.72, tumble: r = !0, autoplay: f = !0 }) {
|
|
187
|
+
const o = M(), h = M(), m = M(), b = M(), s = M(), w = M(new A.Vector3(0.3, 0.88, 0.36).normalize()), d = M([
|
|
188
|
+
{ active: !1, ref: null, axis: "y", target: 0, elapsed: 0, duration: 0 },
|
|
189
|
+
{ active: !1, ref: null, axis: "y", target: 0, elapsed: 0, duration: 0 }
|
|
190
|
+
]), g = M({ phase: "scramble", history: [], remaining: 7, idle: 1, prevMove: null }), u = se();
|
|
191
|
+
return ee((S, a) => {
|
|
192
|
+
if (!h.current || !o.current || !m.current || !b.current || !s.current) return;
|
|
193
|
+
const z = S.clock.elapsedTime, v = m.current, i = g.current, y = d.current;
|
|
194
|
+
if (r) {
|
|
195
|
+
X.setFromAxisAngle(ge, 0.2 * a), H.setFromAxisAngle(xe, 0.125 * a), G.setFromAxisAngle(be, 0.075 * a), w.current.applyQuaternion(X).applyQuaternion(H).applyQuaternion(G).normalize();
|
|
196
|
+
const x = 0.72 + (Math.sin(z * 0.11) * 0.5 + Math.sin(z * 0.047 + 1.3) * 0.3 + Math.sin(z * 0.19 + 0.6) * 0.18) * 0.34;
|
|
197
|
+
Y.setFromAxisAngle(w.current, x * a), h.current.quaternion.premultiply(Y), h.current.position.y = Math.sin(z * 0.6) * 0.09;
|
|
198
|
+
}
|
|
199
|
+
if (t) {
|
|
200
|
+
const c = t.current || 0, x = 1 - Math.pow(0.05, a);
|
|
201
|
+
o.current.rotation.x = A.MathUtils.lerp(o.current.rotation.x, c * -0.36, x);
|
|
202
|
+
}
|
|
203
|
+
const p = y[0].active || y[1].active;
|
|
204
|
+
if (f && !p && (i.idle -= a, i.idle <= 0)) {
|
|
205
|
+
let c;
|
|
206
|
+
if (i.phase === "scramble") {
|
|
207
|
+
const x = ve(i.prevMove);
|
|
208
|
+
c = x.moves, x.record && i.history.push(x.record), i.history.length >= i.remaining && (i.phase = "solve");
|
|
209
|
+
} else
|
|
210
|
+
c = i.history.pop().map((k) => ({ axis: k.axis, layer: k.layer, dir: -k.dir, quarter: k.quarter }));
|
|
211
|
+
i.prevMove = c[c.length - 1], K(y[0], b.current, v, c[0]), c[1] && K(y[1], s.current, v, c[1]);
|
|
212
|
+
}
|
|
213
|
+
for (const c of y)
|
|
214
|
+
c.active && (c.elapsed = Math.min(c.elapsed + a, c.duration), c.ref.rotation[c.axis] = c.target * ne(c.elapsed / c.duration), c.elapsed >= c.duration && (c.ref.rotation[c.axis] = c.target, c.ref.children.slice().forEach((x) => v.attach(x)), c.ref.rotation.set(0, 0, 0), c.active = !1));
|
|
215
|
+
p && !y[0].active && !y[1].active && (i.phase === "solve" && i.history.length === 0 ? (i.phase = "scramble", i.remaining = 7 + (Math.random() * 6 | 0), i.idle = 1.8 + Math.random() * 1.5) : i.idle = 0.12 + Math.random() * 0.4);
|
|
216
|
+
}), /* @__PURE__ */ l("group", { ref: o, children: /* @__PURE__ */ E("group", { ref: h, scale: [n, n, n], children: [
|
|
217
|
+
/* @__PURE__ */ l("group", { ref: m, children: u.map(([S, a, z]) => /* @__PURE__ */ l(oe, { px: S, py: a, pz: z, palette: e }, `${S + 1}${a + 1}${z + 1}`)) }),
|
|
218
|
+
/* @__PURE__ */ l("group", { ref: b }),
|
|
219
|
+
/* @__PURE__ */ l("group", { ref: s })
|
|
220
|
+
] }) });
|
|
221
|
+
}
|
|
222
|
+
function we(e) {
|
|
223
|
+
return e > 0.5 ? 1 : e < -0.5 ? -1 : 0;
|
|
224
|
+
}
|
|
225
|
+
function ze(e, t, n, r, f) {
|
|
226
|
+
const o = ["x", "y", "z"], h = o.reduce((g, u) => Math.abs(e[u]) > Math.abs(e[g]) ? u : g, "x"), m = o.filter((g) => g !== h), b = Math.sqrt(n * n + r * r);
|
|
227
|
+
if (b < 1) return null;
|
|
228
|
+
const w = m.map((g) => {
|
|
229
|
+
const u = new A.Vector3(g === "x" ? 1 : 0, g === "y" ? 1 : 0, g === "z" ? 1 : 0), a = new A.Vector3().crossVectors(u, e.clone().normalize()).clone().applyMatrix4(f.matrixWorldInverse).normalize(), z = (a.x * n + -a.y * r) / b;
|
|
230
|
+
return { rotAxis: g, dot: z };
|
|
231
|
+
}).reduce((g, u) => Math.abs(g.dot) > Math.abs(u.dot) ? g : u), d = we(t[w.rotAxis]);
|
|
232
|
+
return { axis: w.rotAxis, layer: d, dir: w.dot > 0 ? 1 : -1 };
|
|
233
|
+
}
|
|
234
|
+
function Se({ palette: e, queueRef: t, modeRef: n, autoReturnAfter: r = 4, idleSpin: f = 0.28 }) {
|
|
235
|
+
const o = M(), h = M(), m = M(), b = M({ active: !1, axis: "y", start: 0, target: 0, elapsed: 0, duration: 0.3 }), s = M(null), w = M(0), d = M([]), g = M(0), u = M(!1), { camera: S } = ae(), a = se();
|
|
236
|
+
ee((i, y) => {
|
|
237
|
+
const p = b.current, c = h.current, x = m.current;
|
|
238
|
+
if (!(!c || !x)) {
|
|
239
|
+
if (!p.active && t.current.length > 0) {
|
|
240
|
+
const k = t.current.shift(), { axis: F, layer: D, dir: L } = k;
|
|
241
|
+
u.current || (d.current.push(k), g.current = 0);
|
|
242
|
+
const R = c.children.slice();
|
|
243
|
+
(D === null ? R : R.filter((P) => {
|
|
244
|
+
const q = P.position[F];
|
|
245
|
+
return D === 0 ? Math.abs(q) < 0.5 : D > 0 ? q > 0.5 : q < -0.5;
|
|
246
|
+
})).forEach((P) => x.attach(P)), b.current = { active: !0, axis: F, start: 0, target: Math.PI / 2 * L, elapsed: 0, duration: 0.42 };
|
|
247
|
+
}
|
|
248
|
+
if (p.active) {
|
|
249
|
+
p.elapsed = Math.min(p.elapsed + y, p.duration);
|
|
250
|
+
const k = ne(p.elapsed / p.duration);
|
|
251
|
+
x.rotation[p.axis] = p.start + (p.target - p.start) * k, p.elapsed >= p.duration && (x.rotation[p.axis] = p.target, x.children.slice().forEach((F) => c.attach(F)), x.rotation.set(0, 0, 0), p.active = !1, u.current && t.current.length === 0 && (u.current = !1, d.current = []));
|
|
252
|
+
}
|
|
253
|
+
if (r > 0 && !p.active && t.current.length === 0 && d.current.length > 0 && !u.current && (g.current += y, g.current >= r)) {
|
|
254
|
+
u.current = !0, g.current = 0;
|
|
255
|
+
const k = d.current.slice().reverse().map((F) => ({ ...F, dir: -F.dir }));
|
|
256
|
+
t.current.push(...k);
|
|
257
|
+
}
|
|
258
|
+
f > 0 && !p.active && t.current.length === 0 && o.current && (w.current += y * f, o.current.rotation.y = w.current);
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
const z = B(
|
|
262
|
+
(i) => {
|
|
263
|
+
if (n && n.current !== "move") return;
|
|
264
|
+
i.stopPropagation();
|
|
265
|
+
const y = i.face.normal.clone().transformDirection(i.object.matrixWorld);
|
|
266
|
+
s.current = { startX: i.clientX, startY: i.clientY, normalWorld: y, cubeletPos: i.object.position.clone() };
|
|
267
|
+
},
|
|
268
|
+
[n]
|
|
269
|
+
), v = B(
|
|
270
|
+
(i) => {
|
|
271
|
+
const y = s.current;
|
|
272
|
+
if (!y) return;
|
|
273
|
+
s.current = null;
|
|
274
|
+
const p = i.clientX - y.startX, c = i.clientY - y.startY;
|
|
275
|
+
if (Math.sqrt(p * p + c * c) < 12) return;
|
|
276
|
+
const x = ze(y.normalWorld, y.cubeletPos, p, c, S);
|
|
277
|
+
x && t.current.push(x);
|
|
278
|
+
},
|
|
279
|
+
[S, t]
|
|
280
|
+
);
|
|
281
|
+
return /* @__PURE__ */ E("group", { ref: o, children: [
|
|
282
|
+
/* @__PURE__ */ l("group", { ref: h, onPointerDown: z, onPointerUp: v, children: a.map(([i, y, p]) => /* @__PURE__ */ l(oe, { px: i, py: y, pz: p, palette: e }, `${i + 1}${y + 1}${p + 1}`)) }),
|
|
283
|
+
/* @__PURE__ */ l("group", { ref: m })
|
|
284
|
+
] });
|
|
285
|
+
}
|
|
286
|
+
const N = [
|
|
287
|
+
{
|
|
288
|
+
id: "y",
|
|
289
|
+
label: "Y · Layer",
|
|
290
|
+
accent: "#f59e0b",
|
|
291
|
+
pairs: [
|
|
292
|
+
[{ n: "U", axis: "y", layer: 1, dir: -1 }, { n: "U'", axis: "y", layer: 1, dir: 1 }],
|
|
293
|
+
[{ n: "E", axis: "y", layer: 0, dir: 1 }, { n: "E'", axis: "y", layer: 0, dir: -1 }],
|
|
294
|
+
[{ n: "D", axis: "y", layer: -1, dir: 1 }, { n: "D'", axis: "y", layer: -1, dir: -1 }]
|
|
295
|
+
]
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
id: "x",
|
|
299
|
+
label: "X · Column",
|
|
300
|
+
accent: "#ef4444",
|
|
301
|
+
pairs: [
|
|
302
|
+
[{ n: "R", axis: "x", layer: 1, dir: -1 }, { n: "R'", axis: "x", layer: 1, dir: 1 }],
|
|
303
|
+
[{ n: "M", axis: "x", layer: 0, dir: 1 }, { n: "M'", axis: "x", layer: 0, dir: -1 }],
|
|
304
|
+
[{ n: "L", axis: "x", layer: -1, dir: 1 }, { n: "L'", axis: "x", layer: -1, dir: -1 }]
|
|
305
|
+
]
|
|
306
|
+
},
|
|
307
|
+
{
|
|
308
|
+
id: "z",
|
|
309
|
+
label: "Z · Depth",
|
|
310
|
+
accent: "#22c55e",
|
|
311
|
+
pairs: [
|
|
312
|
+
[{ n: "F", axis: "z", layer: 1, dir: -1 }, { n: "F'", axis: "z", layer: 1, dir: 1 }],
|
|
313
|
+
[{ n: "S", axis: "z", layer: 0, dir: -1 }, { n: "S'", axis: "z", layer: 0, dir: 1 }],
|
|
314
|
+
[{ n: "B", axis: "z", layer: -1, dir: 1 }, { n: "B'", axis: "z", layer: -1, dir: -1 }]
|
|
315
|
+
]
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
id: "rot",
|
|
319
|
+
label: "Rotate · Whole",
|
|
320
|
+
accent: "#a78bfa",
|
|
321
|
+
pairs: [
|
|
322
|
+
[{ n: "x", axis: "x", layer: null, dir: -1 }, { n: "x'", axis: "x", layer: null, dir: 1 }],
|
|
323
|
+
[{ n: "y", axis: "y", layer: null, dir: -1 }, { n: "y'", axis: "y", layer: null, dir: 1 }],
|
|
324
|
+
[{ n: "z", axis: "z", layer: null, dir: -1 }, { n: "z'", axis: "z", layer: null, dir: 1 }]
|
|
325
|
+
]
|
|
326
|
+
}
|
|
327
|
+
];
|
|
328
|
+
function Ee({ label: e, accent: t, onClick: n }) {
|
|
329
|
+
const [r, f] = O(!1), o = e.includes("'");
|
|
330
|
+
return /* @__PURE__ */ l(
|
|
331
|
+
$.button,
|
|
332
|
+
{
|
|
333
|
+
whileTap: { scale: 0.9 },
|
|
334
|
+
onClick: n,
|
|
335
|
+
onMouseEnter: () => f(!0),
|
|
336
|
+
onMouseLeave: () => f(!1),
|
|
337
|
+
style: {
|
|
338
|
+
flex: 1,
|
|
339
|
+
border: `1px solid ${r ? t : "rgba(255,255,255,0.08)"}`,
|
|
340
|
+
background: r ? `${t}22` : "rgba(255,255,255,0.03)",
|
|
341
|
+
color: r ? "#fff" : "rgba(240,235,226,0.65)",
|
|
342
|
+
borderRadius: 6,
|
|
343
|
+
padding: "5px 0",
|
|
344
|
+
fontSize: 11,
|
|
345
|
+
fontWeight: 700,
|
|
346
|
+
cursor: "pointer",
|
|
347
|
+
fontFamily: "'DM Mono', monospace",
|
|
348
|
+
transition: "all 0.12s",
|
|
349
|
+
textAlign: "center",
|
|
350
|
+
letterSpacing: o ? "-0.02em" : "0.04em"
|
|
351
|
+
},
|
|
352
|
+
children: e
|
|
353
|
+
}
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
function ke({ onClose: e, palette: t, accent: n = "#E05C28", cameraPosition: r = [5, 4, 5], fov: f = 34 }) {
|
|
357
|
+
const [o, h] = O("orbit"), m = M("orbit"), b = M([]), s = B((d) => {
|
|
358
|
+
m.current = d, h(d);
|
|
359
|
+
}, []), w = B((d) => b.current.push(d), []);
|
|
360
|
+
return le(
|
|
361
|
+
/* @__PURE__ */ l(de, { children: /* @__PURE__ */ E(
|
|
362
|
+
$.div,
|
|
363
|
+
{
|
|
364
|
+
initial: { opacity: 0 },
|
|
365
|
+
animate: { opacity: 1 },
|
|
366
|
+
exit: { opacity: 0 },
|
|
367
|
+
transition: { duration: 0.2 },
|
|
368
|
+
style: {
|
|
369
|
+
position: "fixed",
|
|
370
|
+
inset: 0,
|
|
371
|
+
zIndex: 9999,
|
|
372
|
+
background: "rgba(7, 6, 5, 0.65)",
|
|
373
|
+
backdropFilter: "blur(20px)",
|
|
374
|
+
display: "flex",
|
|
375
|
+
alignItems: "center",
|
|
376
|
+
justifyContent: "center",
|
|
377
|
+
gap: 28,
|
|
378
|
+
fontFamily: "system-ui, sans-serif"
|
|
379
|
+
},
|
|
380
|
+
onClick: (d) => {
|
|
381
|
+
d.target === d.currentTarget && e();
|
|
382
|
+
},
|
|
383
|
+
children: [
|
|
384
|
+
/* @__PURE__ */ l(
|
|
385
|
+
"button",
|
|
386
|
+
{
|
|
387
|
+
onClick: e,
|
|
388
|
+
"aria-label": "Close",
|
|
389
|
+
style: {
|
|
390
|
+
position: "absolute",
|
|
391
|
+
top: 20,
|
|
392
|
+
right: 22,
|
|
393
|
+
background: "rgba(255,255,255,0.04)",
|
|
394
|
+
border: "1px solid rgba(255,255,255,0.09)",
|
|
395
|
+
color: "rgba(255,255,255,0.35)",
|
|
396
|
+
borderRadius: 9,
|
|
397
|
+
width: 36,
|
|
398
|
+
height: 36,
|
|
399
|
+
fontSize: 18,
|
|
400
|
+
cursor: "pointer",
|
|
401
|
+
display: "flex",
|
|
402
|
+
alignItems: "center",
|
|
403
|
+
justifyContent: "center",
|
|
404
|
+
transition: "all 0.15s"
|
|
405
|
+
},
|
|
406
|
+
children: "×"
|
|
407
|
+
}
|
|
408
|
+
),
|
|
409
|
+
/* @__PURE__ */ l(
|
|
410
|
+
$.div,
|
|
411
|
+
{
|
|
412
|
+
initial: { scale: 0.6, opacity: 0 },
|
|
413
|
+
animate: { scale: 1, opacity: 1 },
|
|
414
|
+
exit: { scale: 0.6, opacity: 0 },
|
|
415
|
+
transition: { type: "spring", damping: 20, stiffness: 180 },
|
|
416
|
+
style: {
|
|
417
|
+
width: "min(460px, 78vw)",
|
|
418
|
+
height: "min(460px, 78vw)",
|
|
419
|
+
flexShrink: 0,
|
|
420
|
+
borderRadius: 20,
|
|
421
|
+
cursor: o === "move" ? "crosshair" : "grab",
|
|
422
|
+
overflow: "hidden"
|
|
423
|
+
},
|
|
424
|
+
children: /* @__PURE__ */ E(te, { flat: !0, camera: { position: r, fov: f }, gl: { antialias: !0, alpha: !0 }, style: { background: "transparent" }, children: [
|
|
425
|
+
/* @__PURE__ */ l(ie, { ambient: 0.4 }),
|
|
426
|
+
/* @__PURE__ */ l(Se, { palette: t, queueRef: b, modeRef: m }),
|
|
427
|
+
/* @__PURE__ */ l(ue, { enabled: o === "orbit", autoRotate: !1, enablePan: !1, enableZoom: !1, dampingFactor: 0.08, enableDamping: !0, rotateSpeed: 0.65 })
|
|
428
|
+
] })
|
|
429
|
+
}
|
|
430
|
+
),
|
|
431
|
+
/* @__PURE__ */ E(
|
|
432
|
+
$.div,
|
|
433
|
+
{
|
|
434
|
+
initial: { x: 44, opacity: 0 },
|
|
435
|
+
animate: { x: 0, opacity: 1 },
|
|
436
|
+
exit: { x: 44, opacity: 0 },
|
|
437
|
+
transition: { type: "spring", damping: 22, stiffness: 180, delay: 0.06 },
|
|
438
|
+
style: {
|
|
439
|
+
width: 196,
|
|
440
|
+
background: "rgba(255,255,255,0.025)",
|
|
441
|
+
border: "1px solid rgba(255,255,255,0.07)",
|
|
442
|
+
borderRadius: 16,
|
|
443
|
+
overflow: "hidden",
|
|
444
|
+
flexShrink: 0
|
|
445
|
+
},
|
|
446
|
+
children: [
|
|
447
|
+
/* @__PURE__ */ E("div", { style: { padding: "14px 14px 10px", borderBottom: "1px solid rgba(255,255,255,0.05)" }, children: [
|
|
448
|
+
/* @__PURE__ */ l("p", { style: { fontSize: 9, fontWeight: 700, letterSpacing: "0.22em", textTransform: "uppercase", color: "rgba(255,255,255,0.22)", marginBottom: 10 }, children: "Controls" }),
|
|
449
|
+
/* @__PURE__ */ l("div", { style: { display: "flex", background: "rgba(0,0,0,0.35)", borderRadius: 9, padding: 3, gap: 2 }, children: [
|
|
450
|
+
{ id: "orbit", icon: "⟳", label: "Orbit" },
|
|
451
|
+
{ id: "move", icon: "✦", label: "Move" }
|
|
452
|
+
].map(({ id: d, icon: g, label: u }) => /* @__PURE__ */ E(
|
|
453
|
+
"button",
|
|
454
|
+
{
|
|
455
|
+
onClick: () => s(d),
|
|
456
|
+
style: {
|
|
457
|
+
flex: 1,
|
|
458
|
+
border: "none",
|
|
459
|
+
borderRadius: 7,
|
|
460
|
+
padding: "6px 0",
|
|
461
|
+
fontSize: 10.5,
|
|
462
|
+
fontWeight: 700,
|
|
463
|
+
cursor: "pointer",
|
|
464
|
+
display: "flex",
|
|
465
|
+
alignItems: "center",
|
|
466
|
+
justifyContent: "center",
|
|
467
|
+
gap: 4,
|
|
468
|
+
transition: "all 0.15s",
|
|
469
|
+
background: o === d ? n : "transparent",
|
|
470
|
+
color: o === d ? "#fff" : "rgba(255,255,255,0.35)"
|
|
471
|
+
},
|
|
472
|
+
children: [
|
|
473
|
+
/* @__PURE__ */ l("span", { style: { fontSize: 11 }, children: g }),
|
|
474
|
+
u
|
|
475
|
+
]
|
|
476
|
+
},
|
|
477
|
+
d
|
|
478
|
+
)) }),
|
|
479
|
+
/* @__PURE__ */ l("p", { style: { marginTop: 8, fontSize: 9.5, lineHeight: 1.45, color: "rgba(255,255,255,0.2)" }, children: o === "orbit" ? "Drag to orbit · buttons to move" : "Swipe a face to rotate · or use buttons" })
|
|
480
|
+
] }),
|
|
481
|
+
N.map(({ id: d, label: g, accent: u, pairs: S }, a) => /* @__PURE__ */ E("div", { style: { borderBottom: a < N.length - 1 ? "1px solid rgba(255,255,255,0.045)" : "none", padding: "8px 10px 9px" }, children: [
|
|
482
|
+
/* @__PURE__ */ E("div", { style: { display: "flex", alignItems: "center", gap: 5, marginBottom: 6 }, children: [
|
|
483
|
+
/* @__PURE__ */ l("span", { style: { width: 5, height: 5, borderRadius: "50%", background: u, flexShrink: 0, opacity: 0.85 } }),
|
|
484
|
+
/* @__PURE__ */ l("span", { style: { fontSize: 9, fontWeight: 700, letterSpacing: "0.16em", textTransform: "uppercase", color: "rgba(255,255,255,0.2)" }, children: g })
|
|
485
|
+
] }),
|
|
486
|
+
/* @__PURE__ */ l("div", { style: { display: "flex", flexDirection: "column", gap: 3 }, children: S.map(([z, v], i) => /* @__PURE__ */ l("div", { style: { display: "flex", gap: 3 }, children: [z, v].map(({ n: y, axis: p, layer: c, dir: x }) => /* @__PURE__ */ l(Ee, { label: y, accent: u, onClick: () => w({ axis: p, layer: c, dir: x }) }, y)) }, i)) })
|
|
487
|
+
] }, d)),
|
|
488
|
+
/* @__PURE__ */ l("div", { style: { padding: "8px 14px 12px", borderTop: "1px solid rgba(255,255,255,0.04)" }, children: /* @__PURE__ */ E("p", { style: { fontSize: 9, color: "rgba(255,255,255,0.15)", lineHeight: 1.5, letterSpacing: "0.04em" }, children: [
|
|
489
|
+
"Notation: prime (′) = counter-clockwise",
|
|
490
|
+
/* @__PURE__ */ l("br", {}),
|
|
491
|
+
"U=Up D=Down R=Right L=Left",
|
|
492
|
+
/* @__PURE__ */ l("br", {}),
|
|
493
|
+
"F=Front B=Back M=Mid E=Eq S=Std",
|
|
494
|
+
/* @__PURE__ */ l("br", {}),
|
|
495
|
+
"x/y/z = whole-cube rotation"
|
|
496
|
+
] }) })
|
|
497
|
+
]
|
|
498
|
+
}
|
|
499
|
+
)
|
|
500
|
+
]
|
|
501
|
+
},
|
|
502
|
+
"cube-overlay"
|
|
503
|
+
) }),
|
|
504
|
+
document.body
|
|
505
|
+
);
|
|
506
|
+
}
|
|
507
|
+
function De({
|
|
508
|
+
size: e = 400,
|
|
509
|
+
height: t,
|
|
510
|
+
palette: n,
|
|
511
|
+
accent: r = "#E05C28",
|
|
512
|
+
autoplay: f = !0,
|
|
513
|
+
tumble: o = !0,
|
|
514
|
+
interactive: h = !0,
|
|
515
|
+
scrollTilt: m = !1,
|
|
516
|
+
scale: b = 0.72,
|
|
517
|
+
cameraPosition: s = [7, 6, 7],
|
|
518
|
+
fov: w = 24,
|
|
519
|
+
background: d = "transparent",
|
|
520
|
+
ambient: g = 0.22,
|
|
521
|
+
className: u,
|
|
522
|
+
style: S,
|
|
523
|
+
onExpand: a,
|
|
524
|
+
...z
|
|
525
|
+
}) {
|
|
526
|
+
const v = M(0), i = M(null), [y, p] = O(!1), c = fe(n), x = typeof e == "number" ? `${e}px` : e, k = t != null ? typeof t == "number" ? `${t}px` : t : x;
|
|
527
|
+
j(() => {
|
|
528
|
+
if (!m) return;
|
|
529
|
+
const L = i.current, R = () => {
|
|
530
|
+
if (!L) return;
|
|
531
|
+
const T = L.getBoundingClientRect(), P = window.innerHeight || 1;
|
|
532
|
+
v.current = Math.max(0, Math.min(1, (P - T.top) / (P + T.height) - 0.1));
|
|
533
|
+
};
|
|
534
|
+
return R(), window.addEventListener("scroll", R, { passive: !0 }), window.addEventListener("resize", R), () => {
|
|
535
|
+
window.removeEventListener("scroll", R), window.removeEventListener("resize", R);
|
|
536
|
+
};
|
|
537
|
+
}, [m]), j(() => {
|
|
538
|
+
if (!y) return;
|
|
539
|
+
const L = window.scrollY;
|
|
540
|
+
document.body.style.position = "fixed", document.body.style.top = `-${L}px`, document.body.style.width = "100%";
|
|
541
|
+
const R = (T) => T.key === "Escape" && p(!1);
|
|
542
|
+
return window.addEventListener("keydown", R), () => {
|
|
543
|
+
document.body.style.position = "", document.body.style.top = "", document.body.style.width = "", window.scrollTo(0, L), window.removeEventListener("keydown", R);
|
|
544
|
+
};
|
|
545
|
+
}, [y]);
|
|
546
|
+
const F = B(() => {
|
|
547
|
+
p(!0), a == null || a();
|
|
548
|
+
}, [a]), D = B(() => p(!1), []);
|
|
549
|
+
return /* @__PURE__ */ E(Z, { children: [
|
|
550
|
+
/* @__PURE__ */ E("div", { ref: i, className: u, style: { position: "relative", width: x, height: k, flexShrink: 0, ...S }, ...z, children: [
|
|
551
|
+
/* @__PURE__ */ E(te, { flat: !0, camera: { position: s, fov: w }, gl: { antialias: !0, alpha: d === "transparent" }, style: { background: d }, children: [
|
|
552
|
+
/* @__PURE__ */ l(ie, { ambient: g }),
|
|
553
|
+
/* @__PURE__ */ l(Me, { palette: c, scrollRef: m ? v : null, scale: b, tumble: o, autoplay: f })
|
|
554
|
+
] }),
|
|
555
|
+
h && /* @__PURE__ */ l(
|
|
556
|
+
"div",
|
|
557
|
+
{
|
|
558
|
+
style: { position: "absolute", inset: 0, cursor: "pointer", zIndex: 1 },
|
|
559
|
+
onClick: F,
|
|
560
|
+
role: "button",
|
|
561
|
+
"aria-label": "Explore cube",
|
|
562
|
+
tabIndex: 0,
|
|
563
|
+
onKeyDown: (L) => L.key === "Enter" && F()
|
|
564
|
+
}
|
|
565
|
+
)
|
|
566
|
+
] }),
|
|
567
|
+
h && y && /* @__PURE__ */ l(ke, { onClose: D, palette: c, accent: r })
|
|
568
|
+
] });
|
|
569
|
+
}
|
|
570
|
+
export {
|
|
571
|
+
Me as AutoCubeScene,
|
|
572
|
+
Q as BRAND_PALETTE,
|
|
573
|
+
pe as CLASSIC_PALETTE,
|
|
574
|
+
he as CUBELET_GEO,
|
|
575
|
+
ke as CubeOverlay,
|
|
576
|
+
oe as Cubelet,
|
|
577
|
+
re as FACE_ORDER,
|
|
578
|
+
Se as InteractiveCubeScene,
|
|
579
|
+
ie as Lights,
|
|
580
|
+
N as MOVE_GROUPS,
|
|
581
|
+
De as RubiksCube,
|
|
582
|
+
De as default,
|
|
583
|
+
fe as resolvePalette,
|
|
584
|
+
ne as smoother,
|
|
585
|
+
se as useCubePositions
|
|
586
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(function(x,r){typeof exports=="object"&&typeof module<"u"?r(exports,require("react/jsx-runtime"),require("react"),require("@react-three/fiber"),require("three"),require("react-dom"),require("@react-three/drei"),require("framer-motion")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react","@react-three/fiber","three","react-dom","@react-three/drei","framer-motion"],r):(x=typeof globalThis<"u"?globalThis:x||self,r(x.Cubex={},x.jsxRuntime,x.React,x.ReactThreeFiber,x.THREE,x.ReactDOM,x.Drei,x.FramerMotion))})(this,function(x,r,d,B,D,ce,le,O){"use strict";function ue(e){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e){for(const n in e)if(n!=="default"){const o=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(t,n,o.get?o:{enumerable:!0,get:()=>e[n]})}}return t.default=e,Object.freeze(t)}const A=ue(D),_=new D.Vector3;function E(e,t,n,o,h,s){const y=2*Math.PI*h/4,b=Math.max(s-2*h,0),M=Math.PI/4;_.copy(t),_[o]=0,_.normalize();const a=.5*y/(y+b),C=1-_.angleTo(e)/M;return Math.sign(_[n])===1?C*a:b/(y+b)+a+a*(1-C)}class V extends D.BoxGeometry{constructor(t=1,n=1,o=1,h=2,s=.1){const y=h*2+1;if(s=Math.min(t/2,n/2,o/2,s),super(1,1,1,y,y,y),this.type="RoundedBoxGeometry",this.parameters={width:t,height:n,depth:o,segments:h,radius:s},y===1)return;const b=this.toNonIndexed();this.index=null,this.attributes.position=b.attributes.position,this.attributes.normal=b.attributes.normal,this.attributes.uv=b.attributes.uv;const M=new D.Vector3,a=new D.Vector3,C=new D.Vector3(t,n,o).divideScalar(2).subScalar(s),f=this.attributes.position.array,m=this.attributes.normal.array,u=this.attributes.uv.array,z=f.length/6,c=new D.Vector3,S=.5/y;for(let w=0,i=0;w<f.length;w+=3,i+=2)switch(M.fromArray(f,w),a.copy(M),a.x-=Math.sign(a.x)*S,a.y-=Math.sign(a.y)*S,a.z-=Math.sign(a.z)*S,a.normalize(),f[w+0]=C.x*Math.sign(M.x)+a.x*s,f[w+1]=C.y*Math.sign(M.y)+a.y*s,f[w+2]=C.z*Math.sign(M.z)+a.z*s,m[w+0]=a.x,m[w+1]=a.y,m[w+2]=a.z,Math.floor(w/z)){case 0:c.set(1,0,0),u[i+0]=E(c,a,"z","y",s,o),u[i+1]=1-E(c,a,"y","z",s,n);break;case 1:c.set(-1,0,0),u[i+0]=1-E(c,a,"z","y",s,o),u[i+1]=1-E(c,a,"y","z",s,n);break;case 2:c.set(0,1,0),u[i+0]=1-E(c,a,"x","z",s,t),u[i+1]=E(c,a,"z","x",s,o);break;case 3:c.set(0,-1,0),u[i+0]=1-E(c,a,"x","z",s,t),u[i+1]=1-E(c,a,"z","x",s,o);break;case 4:c.set(0,0,1),u[i+0]=1-E(c,a,"x","y",s,t),u[i+1]=1-E(c,a,"y","x",s,n);break;case 5:c.set(0,0,-1),u[i+0]=E(c,a,"x","y",s,t),u[i+1]=1-E(c,a,"y","x",s,n);break}}static fromJSON(t){return new V(t.width,t.height,t.depth,t.segments,t.radius)}}const j={right:{color:"#E05C28",roughness:.34,metalness:0},left:{color:"#00C9A7",roughness:.34,metalness:0},up:{color:"#EDE3D1",roughness:.44,metalness:0},down:{color:"#C8963E",roughness:.36,metalness:0},front:{color:"#B23E22",roughness:.36,metalness:0},back:{color:"#0B7A6E",roughness:.38,metalness:0},inner:{color:"#1C1A17",roughness:.82,metalness:0}},R={right:{color:"#B71234",roughness:.3,metalness:0},left:{color:"#FF5800",roughness:.3,metalness:0},up:{color:"#FFFFFF",roughness:.4,metalness:0},down:{color:"#FFD500",roughness:.32,metalness:0},front:{color:"#009B48",roughness:.32,metalness:0},back:{color:"#0046AD",roughness:.32,metalness:0},inner:{color:"#111111",roughness:.85,metalness:0}},U=["right","left","up","down","front","back"];function Z(e){if(!e)return j;const t=e.base==="classic"?R:j,n={};for(const o of[...U,"inner"])n[o]={...t[o],...e[o]||{}};return n}const J=new V(.95,.95,.95,4,.045),$=e=>(e=Math.max(0,Math.min(1,e)),e*e*e*(e*(e*6-15)+10));function W({px:e,py:t,pz:n,palette:o}){const h=d.useMemo(()=>[e===1,e===-1,t===1,t===-1,n===1,n===-1],[e,t,n]);return r.jsx("mesh",{position:[e,t,n],geometry:J,children:h.map((s,y)=>{const b=s?o[U[y]]:o.inner;return r.jsx("meshStandardMaterial",{attach:`material-${y}`,color:b.color,roughness:b.roughness,metalness:b.metalness},y)})})}function Q({ambient:e=.22}){return r.jsxs(r.Fragment,{children:[r.jsx("directionalLight",{position:[5,8,4],intensity:2.4,color:"#fff6ee"}),r.jsx("directionalLight",{position:[-5,-3,-4],intensity:.6,color:"#ffe0cf"}),r.jsx("directionalLight",{position:[-4,6,-6],intensity:1.5,color:"#cfe4ff"}),r.jsx("ambientLight",{intensity:e}),r.jsx("pointLight",{position:[-1,1,5],intensity:.85,color:"#fff5ee",distance:18})]})}function Y(){return d.useMemo(()=>{const e=[];for(let t=-1;t<=1;t++)for(let n=-1;n<=1;n++)for(let o=-1;o<=1;o++)e.push([t,n,o]);return e},[])}const G=["x","y","z"],X=()=>Math.random()<.5?1:-1;function de(e){for(let t=0;t<8;t++){const n=G[Math.random()*3|0],o=[-1,0,1][Math.random()*3|0],h=X(),s=Math.random()<.82?1:2;if(!(e&&e.axis===n&&e.layer===o&&e.dir===-h&&e.quarter===s))return{axis:n,layer:o,dir:h,quarter:s}}return{axis:"y",layer:1,dir:1,quarter:1}}function fe(e,t,n){return n===null?e:e.filter(o=>{const h=o.position[t];return n===0?Math.abs(h)<.5:n>0?h>.5:h<-.5})}const H=new A.Quaternion,ee=new A.Quaternion,te=new A.Quaternion,re=new A.Quaternion,pe=new A.Vector3(.58,.77,-.27).normalize(),he=new A.Vector3(-.41,.35,.84).normalize(),ye=new A.Vector3(.22,-.62,.75).normalize();function be(e){const t=Math.random();if(t<.16)return{moves:[{axis:G[Math.random()*3|0],layer:[-1,0,1][Math.random()*3|0],dir:X(),quarter:4}],record:null};if(t<.54){const o=G[Math.random()*3|0],h=[-1,0,1],s=Math.random()*3|0;let y=Math.random()*3|0;for(;y===s;)y=Math.random()*3|0;const b=[s,y].map(M=>({axis:o,layer:h[M],dir:X(),quarter:Math.random()<.25?2:1}));return{moves:b,record:b}}const n=de(e);return{moves:[n],record:[n]}}function ne(e,t,n,o){fe(n.children.slice(),o.axis,o.layer).forEach(h=>t.attach(h)),e.ref=t,e.axis=o.axis,e.target=Math.PI/2*o.dir*o.quarter,e.elapsed=0,e.duration=.42*o.quarter+.16+Math.random()*.3,e.active=!0}function oe({palette:e,scrollRef:t,scale:n=.72,tumble:o=!0,autoplay:h=!0}){const s=d.useRef(),y=d.useRef(),b=d.useRef(),M=d.useRef(),a=d.useRef(),C=d.useRef(new A.Vector3(.3,.88,.36).normalize()),f=d.useRef([{active:!1,ref:null,axis:"y",target:0,elapsed:0,duration:0},{active:!1,ref:null,axis:"y",target:0,elapsed:0,duration:0}]),m=d.useRef({phase:"scramble",history:[],remaining:7,idle:1,prevMove:null}),u=Y();return B.useFrame((z,c)=>{if(!y.current||!s.current||!b.current||!M.current||!a.current)return;const S=z.clock.elapsedTime,w=b.current,i=m.current,g=f.current;if(o){ee.setFromAxisAngle(pe,.2*c),te.setFromAxisAngle(he,.125*c),re.setFromAxisAngle(ye,.075*c),C.current.applyQuaternion(ee).applyQuaternion(te).applyQuaternion(re).normalize();const v=.72+(Math.sin(S*.11)*.5+Math.sin(S*.047+1.3)*.3+Math.sin(S*.19+.6)*.18)*.34;H.setFromAxisAngle(C.current,v*c),y.current.quaternion.premultiply(H),y.current.position.y=Math.sin(S*.6)*.09}if(t){const l=t.current||0,v=1-Math.pow(.05,c);s.current.rotation.x=A.MathUtils.lerp(s.current.rotation.x,l*-.36,v)}const p=g[0].active||g[1].active;if(h&&!p&&(i.idle-=c,i.idle<=0)){let l;if(i.phase==="scramble"){const v=be(i.prevMove);l=v.moves,v.record&&i.history.push(v.record),i.history.length>=i.remaining&&(i.phase="solve")}else l=i.history.pop().map(k=>({axis:k.axis,layer:k.layer,dir:-k.dir,quarter:k.quarter}));i.prevMove=l[l.length-1],ne(g[0],M.current,w,l[0]),l[1]&&ne(g[1],a.current,w,l[1])}for(const l of g)l.active&&(l.elapsed=Math.min(l.elapsed+c,l.duration),l.ref.rotation[l.axis]=l.target*$(l.elapsed/l.duration),l.elapsed>=l.duration&&(l.ref.rotation[l.axis]=l.target,l.ref.children.slice().forEach(v=>w.attach(v)),l.ref.rotation.set(0,0,0),l.active=!1));p&&!g[0].active&&!g[1].active&&(i.phase==="solve"&&i.history.length===0?(i.phase="scramble",i.remaining=7+(Math.random()*6|0),i.idle=1.8+Math.random()*1.5):i.idle=.12+Math.random()*.4)}),r.jsx("group",{ref:s,children:r.jsxs("group",{ref:y,scale:[n,n,n],children:[r.jsx("group",{ref:b,children:u.map(([z,c,S])=>r.jsx(W,{px:z,py:c,pz:S,palette:e},`${z+1}${c+1}${S+1}`))}),r.jsx("group",{ref:M}),r.jsx("group",{ref:a})]})})}function ge(e){return e>.5?1:e<-.5?-1:0}function me(e,t,n,o,h){const s=["x","y","z"],y=s.reduce((m,u)=>Math.abs(e[u])>Math.abs(e[m])?u:m,"x"),b=s.filter(m=>m!==y),M=Math.sqrt(n*n+o*o);if(M<1)return null;const C=b.map(m=>{const u=new A.Vector3(m==="x"?1:0,m==="y"?1:0,m==="z"?1:0),c=new A.Vector3().crossVectors(u,e.clone().normalize()).clone().applyMatrix4(h.matrixWorldInverse).normalize(),S=(c.x*n+-c.y*o)/M;return{rotAxis:m,dot:S}}).reduce((m,u)=>Math.abs(m.dot)>Math.abs(u.dot)?m:u),f=ge(t[C.rotAxis]);return{axis:C.rotAxis,layer:f,dir:C.dot>0?1:-1}}function se({palette:e,queueRef:t,modeRef:n,autoReturnAfter:o=4,idleSpin:h=.28}){const s=d.useRef(),y=d.useRef(),b=d.useRef(),M=d.useRef({active:!1,axis:"y",start:0,target:0,elapsed:0,duration:.3}),a=d.useRef(null),C=d.useRef(0),f=d.useRef([]),m=d.useRef(0),u=d.useRef(!1),{camera:z}=B.useThree(),c=Y();B.useFrame((i,g)=>{const p=M.current,l=y.current,v=b.current;if(!(!l||!v)){if(!p.active&&t.current.length>0){const k=t.current.shift(),{axis:P,layer:q,dir:L}=k;u.current||(f.current.push(k),m.current=0);const F=l.children.slice();(q===null?F:F.filter(T=>{const K=T.position[P];return q===0?Math.abs(K)<.5:q>0?K>.5:K<-.5})).forEach(T=>v.attach(T)),M.current={active:!0,axis:P,start:0,target:Math.PI/2*L,elapsed:0,duration:.42}}if(p.active){p.elapsed=Math.min(p.elapsed+g,p.duration);const k=$(p.elapsed/p.duration);v.rotation[p.axis]=p.start+(p.target-p.start)*k,p.elapsed>=p.duration&&(v.rotation[p.axis]=p.target,v.children.slice().forEach(P=>l.attach(P)),v.rotation.set(0,0,0),p.active=!1,u.current&&t.current.length===0&&(u.current=!1,f.current=[]))}if(o>0&&!p.active&&t.current.length===0&&f.current.length>0&&!u.current&&(m.current+=g,m.current>=o)){u.current=!0,m.current=0;const k=f.current.slice().reverse().map(P=>({...P,dir:-P.dir}));t.current.push(...k)}h>0&&!p.active&&t.current.length===0&&s.current&&(C.current+=g*h,s.current.rotation.y=C.current)}});const S=d.useCallback(i=>{if(n&&n.current!=="move")return;i.stopPropagation();const g=i.face.normal.clone().transformDirection(i.object.matrixWorld);a.current={startX:i.clientX,startY:i.clientY,normalWorld:g,cubeletPos:i.object.position.clone()}},[n]),w=d.useCallback(i=>{const g=a.current;if(!g)return;a.current=null;const p=i.clientX-g.startX,l=i.clientY-g.startY;if(Math.sqrt(p*p+l*l)<12)return;const v=me(g.normalWorld,g.cubeletPos,p,l,z);v&&t.current.push(v)},[z,t]);return r.jsxs("group",{ref:s,children:[r.jsx("group",{ref:y,onPointerDown:S,onPointerUp:w,children:c.map(([i,g,p])=>r.jsx(W,{px:i,py:g,pz:p,palette:e},`${i+1}${g+1}${p+1}`))}),r.jsx("group",{ref:b})]})}const N=[{id:"y",label:"Y · Layer",accent:"#f59e0b",pairs:[[{n:"U",axis:"y",layer:1,dir:-1},{n:"U'",axis:"y",layer:1,dir:1}],[{n:"E",axis:"y",layer:0,dir:1},{n:"E'",axis:"y",layer:0,dir:-1}],[{n:"D",axis:"y",layer:-1,dir:1},{n:"D'",axis:"y",layer:-1,dir:-1}]]},{id:"x",label:"X · Column",accent:"#ef4444",pairs:[[{n:"R",axis:"x",layer:1,dir:-1},{n:"R'",axis:"x",layer:1,dir:1}],[{n:"M",axis:"x",layer:0,dir:1},{n:"M'",axis:"x",layer:0,dir:-1}],[{n:"L",axis:"x",layer:-1,dir:1},{n:"L'",axis:"x",layer:-1,dir:-1}]]},{id:"z",label:"Z · Depth",accent:"#22c55e",pairs:[[{n:"F",axis:"z",layer:1,dir:-1},{n:"F'",axis:"z",layer:1,dir:1}],[{n:"S",axis:"z",layer:0,dir:-1},{n:"S'",axis:"z",layer:0,dir:1}],[{n:"B",axis:"z",layer:-1,dir:1},{n:"B'",axis:"z",layer:-1,dir:-1}]]},{id:"rot",label:"Rotate · Whole",accent:"#a78bfa",pairs:[[{n:"x",axis:"x",layer:null,dir:-1},{n:"x'",axis:"x",layer:null,dir:1}],[{n:"y",axis:"y",layer:null,dir:-1},{n:"y'",axis:"y",layer:null,dir:1}],[{n:"z",axis:"z",layer:null,dir:-1},{n:"z'",axis:"z",layer:null,dir:1}]]}];function xe({label:e,accent:t,onClick:n}){const[o,h]=d.useState(!1),s=e.includes("'");return r.jsx(O.motion.button,{whileTap:{scale:.9},onClick:n,onMouseEnter:()=>h(!0),onMouseLeave:()=>h(!1),style:{flex:1,border:`1px solid ${o?t:"rgba(255,255,255,0.08)"}`,background:o?`${t}22`:"rgba(255,255,255,0.03)",color:o?"#fff":"rgba(240,235,226,0.65)",borderRadius:6,padding:"5px 0",fontSize:11,fontWeight:700,cursor:"pointer",fontFamily:"'DM Mono', monospace",transition:"all 0.12s",textAlign:"center",letterSpacing:s?"-0.02em":"0.04em"},children:e})}function ie({onClose:e,palette:t,accent:n="#E05C28",cameraPosition:o=[5,4,5],fov:h=34}){const[s,y]=d.useState("orbit"),b=d.useRef("orbit"),M=d.useRef([]),a=d.useCallback(f=>{b.current=f,y(f)},[]),C=d.useCallback(f=>M.current.push(f),[]);return ce.createPortal(r.jsx(O.AnimatePresence,{children:r.jsxs(O.motion.div,{initial:{opacity:0},animate:{opacity:1},exit:{opacity:0},transition:{duration:.2},style:{position:"fixed",inset:0,zIndex:9999,background:"rgba(7, 6, 5, 0.65)",backdropFilter:"blur(20px)",display:"flex",alignItems:"center",justifyContent:"center",gap:28,fontFamily:"system-ui, sans-serif"},onClick:f=>{f.target===f.currentTarget&&e()},children:[r.jsx("button",{onClick:e,"aria-label":"Close",style:{position:"absolute",top:20,right:22,background:"rgba(255,255,255,0.04)",border:"1px solid rgba(255,255,255,0.09)",color:"rgba(255,255,255,0.35)",borderRadius:9,width:36,height:36,fontSize:18,cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",transition:"all 0.15s"},children:"×"}),r.jsx(O.motion.div,{initial:{scale:.6,opacity:0},animate:{scale:1,opacity:1},exit:{scale:.6,opacity:0},transition:{type:"spring",damping:20,stiffness:180},style:{width:"min(460px, 78vw)",height:"min(460px, 78vw)",flexShrink:0,borderRadius:20,cursor:s==="move"?"crosshair":"grab",overflow:"hidden"},children:r.jsxs(B.Canvas,{flat:!0,camera:{position:o,fov:h},gl:{antialias:!0,alpha:!0},style:{background:"transparent"},children:[r.jsx(Q,{ambient:.4}),r.jsx(se,{palette:t,queueRef:M,modeRef:b}),r.jsx(le.OrbitControls,{enabled:s==="orbit",autoRotate:!1,enablePan:!1,enableZoom:!1,dampingFactor:.08,enableDamping:!0,rotateSpeed:.65})]})}),r.jsxs(O.motion.div,{initial:{x:44,opacity:0},animate:{x:0,opacity:1},exit:{x:44,opacity:0},transition:{type:"spring",damping:22,stiffness:180,delay:.06},style:{width:196,background:"rgba(255,255,255,0.025)",border:"1px solid rgba(255,255,255,0.07)",borderRadius:16,overflow:"hidden",flexShrink:0},children:[r.jsxs("div",{style:{padding:"14px 14px 10px",borderBottom:"1px solid rgba(255,255,255,0.05)"},children:[r.jsx("p",{style:{fontSize:9,fontWeight:700,letterSpacing:"0.22em",textTransform:"uppercase",color:"rgba(255,255,255,0.22)",marginBottom:10},children:"Controls"}),r.jsx("div",{style:{display:"flex",background:"rgba(0,0,0,0.35)",borderRadius:9,padding:3,gap:2},children:[{id:"orbit",icon:"⟳",label:"Orbit"},{id:"move",icon:"✦",label:"Move"}].map(({id:f,icon:m,label:u})=>r.jsxs("button",{onClick:()=>a(f),style:{flex:1,border:"none",borderRadius:7,padding:"6px 0",fontSize:10.5,fontWeight:700,cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",gap:4,transition:"all 0.15s",background:s===f?n:"transparent",color:s===f?"#fff":"rgba(255,255,255,0.35)"},children:[r.jsx("span",{style:{fontSize:11},children:m}),u]},f))}),r.jsx("p",{style:{marginTop:8,fontSize:9.5,lineHeight:1.45,color:"rgba(255,255,255,0.2)"},children:s==="orbit"?"Drag to orbit · buttons to move":"Swipe a face to rotate · or use buttons"})]}),N.map(({id:f,label:m,accent:u,pairs:z},c)=>r.jsxs("div",{style:{borderBottom:c<N.length-1?"1px solid rgba(255,255,255,0.045)":"none",padding:"8px 10px 9px"},children:[r.jsxs("div",{style:{display:"flex",alignItems:"center",gap:5,marginBottom:6},children:[r.jsx("span",{style:{width:5,height:5,borderRadius:"50%",background:u,flexShrink:0,opacity:.85}}),r.jsx("span",{style:{fontSize:9,fontWeight:700,letterSpacing:"0.16em",textTransform:"uppercase",color:"rgba(255,255,255,0.2)"},children:m})]}),r.jsx("div",{style:{display:"flex",flexDirection:"column",gap:3},children:z.map(([S,w],i)=>r.jsx("div",{style:{display:"flex",gap:3},children:[S,w].map(({n:g,axis:p,layer:l,dir:v})=>r.jsx(xe,{label:g,accent:u,onClick:()=>C({axis:p,layer:l,dir:v})},g))},i))})]},f)),r.jsx("div",{style:{padding:"8px 14px 12px",borderTop:"1px solid rgba(255,255,255,0.04)"},children:r.jsxs("p",{style:{fontSize:9,color:"rgba(255,255,255,0.15)",lineHeight:1.5,letterSpacing:"0.04em"},children:["Notation: prime (′) = counter-clockwise",r.jsx("br",{}),"U=Up D=Down R=Right L=Left",r.jsx("br",{}),"F=Front B=Back M=Mid E=Eq S=Std",r.jsx("br",{}),"x/y/z = whole-cube rotation"]})})]})]},"cube-overlay")}),document.body)}function ae({size:e=400,height:t,palette:n,accent:o="#E05C28",autoplay:h=!0,tumble:s=!0,interactive:y=!0,scrollTilt:b=!1,scale:M=.72,cameraPosition:a=[7,6,7],fov:C=24,background:f="transparent",ambient:m=.22,className:u,style:z,onExpand:c,...S}){const w=d.useRef(0),i=d.useRef(null),[g,p]=d.useState(!1),l=Z(n),v=typeof e=="number"?`${e}px`:e,k=t!=null?typeof t=="number"?`${t}px`:t:v;d.useEffect(()=>{if(!b)return;const L=i.current,F=()=>{if(!L)return;const I=L.getBoundingClientRect(),T=window.innerHeight||1;w.current=Math.max(0,Math.min(1,(T-I.top)/(T+I.height)-.1))};return F(),window.addEventListener("scroll",F,{passive:!0}),window.addEventListener("resize",F),()=>{window.removeEventListener("scroll",F),window.removeEventListener("resize",F)}},[b]),d.useEffect(()=>{if(!g)return;const L=window.scrollY;document.body.style.position="fixed",document.body.style.top=`-${L}px`,document.body.style.width="100%";const F=I=>I.key==="Escape"&&p(!1);return window.addEventListener("keydown",F),()=>{document.body.style.position="",document.body.style.top="",document.body.style.width="",window.scrollTo(0,L),window.removeEventListener("keydown",F)}},[g]);const P=d.useCallback(()=>{p(!0),c==null||c()},[c]),q=d.useCallback(()=>p(!1),[]);return r.jsxs(r.Fragment,{children:[r.jsxs("div",{ref:i,className:u,style:{position:"relative",width:v,height:k,flexShrink:0,...z},...S,children:[r.jsxs(B.Canvas,{flat:!0,camera:{position:a,fov:C},gl:{antialias:!0,alpha:f==="transparent"},style:{background:f},children:[r.jsx(Q,{ambient:m}),r.jsx(oe,{palette:l,scrollRef:b?w:null,scale:M,tumble:s,autoplay:h})]}),y&&r.jsx("div",{style:{position:"absolute",inset:0,cursor:"pointer",zIndex:1},onClick:P,role:"button","aria-label":"Explore cube",tabIndex:0,onKeyDown:L=>L.key==="Enter"&&P()})]}),y&&g&&r.jsx(ie,{onClose:q,palette:l,accent:o})]})}x.AutoCubeScene=oe,x.BRAND_PALETTE=j,x.CLASSIC_PALETTE=R,x.CUBELET_GEO=J,x.CubeOverlay=ie,x.Cubelet=W,x.FACE_ORDER=U,x.InteractiveCubeScene=se,x.Lights=Q,x.MOVE_GROUPS=N,x.RubiksCube=ae,x.default=ae,x.resolvePalette=Z,x.smoother=$,x.useCubePositions=Y,Object.defineProperties(x,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
|