@walrosproject/ui 0.3.4 → 0.4.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/README.md +42 -233
- package/dist/assets/walros-logo-3d.glb +0 -0
- package/dist/index.d.ts +37 -2
- package/dist/index.js +508 -352
- package/dist/index.js.map +1 -1
- package/dist/model.d.ts +4 -0
- package/dist/model.js +6 -0
- package/dist/model.js.map +1 -0
- package/package.json +6 -1
package/dist/index.js
CHANGED
|
@@ -1,296 +1,6 @@
|
|
|
1
1
|
// src/components/WalrosPortalTransition.tsx
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
useId,
|
|
5
|
-
useLayoutEffect,
|
|
6
|
-
useRef,
|
|
7
|
-
useState
|
|
8
|
-
} from "react";
|
|
9
|
-
import { gsap } from "gsap";
|
|
10
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
11
|
-
var SILHOUETTE_VIEWBOX = 1254;
|
|
12
|
-
var FOCUS_X = 626;
|
|
13
|
-
var FOCUS_Y = 333;
|
|
14
|
-
var PORTAL_RADIUS = 190;
|
|
15
|
-
var WALROS_PORTAL_SILHOUETTE_URL = "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgICAgdmlld0JveD0iMCAwIDEyNTQgMTI1NCIKICAgICB3aWR0aD0iMTI1NCIgaGVpZ2h0PSIxMjU0IgogICAgIHJvbGU9ImltZyIgYXJpYS1sYWJlbD0iU2lsdWV0YSBXYWxyT1MiPgogIDxnIGZpbGw9IiMwMDAwMDAiPgogICAgPHBhdGggZD0iTSAyNDQuMDAgMzU0LjAwIEMgMjQwLjUwIDM3Ny42NywgMjQwLjE3IDQxMy42NywgMjQyLjAwIDQzNC4wMCBDIDI0My44MyA0NTQuMzMsIDI0OS41MCA0NjQuNTAsIDI1NS4wMCA0NzYuMDAgQyAyNjAuNTAgNDg3LjUwLCAyNjguNTAgNDk2LjAwLCAyNzUuMDAgNTAzLjAwIEMgMjgxLjUwIDUxMC4wMCwgMjg3LjE3IDUxMy42NywgMjk0LjAwIDUxOC4wMCBDIDMwMC44MyA1MjIuMzMsIDMwNi4wMCA1MjUuNjcsIDMxNi4wMCA1MjkuMDAgQyAzMjYuMDAgNTMyLjMzLCAzMzYuMzMgNTM2LjY3LCAzNTQuMDAgNTM4LjAwIEMgMzcxLjY3IDUzOS4zMywgMzk3LjgzIDU0MC44MywgNDIyLjAwIDUzNy4wMCBDIDQ0Ni4xNyA1MzMuMTcsIDQ3NC4xNyA1MjUuMzMsIDQ5OS4wMCA1MTUuMDAgQyA1MjMuODMgNTA0LjY3LCA1NTAuMDAgNDg5LjMzLCA1NzEuMDAgNDc1LjAwIEMgNTkyLjAwIDQ2MC42NywgNjE1LjAwIDQzNi41MCwgNjI1LjAwIDQyOS4wMCBDIDYzNS4wMCA0MjEuNTAsIDYyMy42NyA0MjQuMDAsIDYzMS4wMCA0MzAuMDAgQyA2MzguMzMgNDM2LjAwLCA2NTYuNjcgNDU0LjgzLCA2NjkuMDAgNDY1LjAwIEMgNjgxLjMzIDQ3NS4xNywgNjkwLjAwIDQ4Mi4xNywgNzA1LjAwIDQ5MS4wMCBDIDcyMC4wMCA0OTkuODMsIDc0My42NyA1MTEuNTAsIDc1OS4wMCA1MTguMDAgQyA3NzQuMzMgNTI0LjUwLCA3ODQuMDAgNTI2LjgzLCA3OTcuMDAgNTMwLjAwIEMgODEwLjAwIDUzMy4xNywgODIwLjAwIDUzNS44MywgODM3LjAwIDUzNy4wMCBDIDg1NC4wMCA1MzguMTcsIDg4MS4xNyA1MzkuMDAsIDg5OS4wMCA1MzcuMDAgQyA5MTYuODMgNTM1LjAwLCA5MzIuMDAgNTMwLjAwLCA5NDQuMDAgNTI1LjAwIEMgOTU2LjAwIDUyMC4wMCwgOTYyLjAwIDUxNi4xNywgOTcxLjAwIDUwNy4wMCBDIDk4MC4wMCA0OTcuODMsIDk5MS42NyA0ODIuODMsIDk5OC4wMCA0NzAuMDAgQyAxMDA0LjMzIDQ1Ny4xNywgMTAwNy4xNyA0NDYuMzMsIDEwMDkuMDAgNDMwLjAwIEMgMTAxMC44MyA0MTMuNjcsIDEwMTAuODMgMzkwLjUwLCAxMDA5LjAwIDM3Mi4wMCBDIDEwMDcuMTcgMzUzLjUwLCAxMDAzLjgzIDMzNy4xNywgOTk4LjAwIDMxOS4wMCBDIDk5Mi4xNyAzMDAuODMsIDk4My42NyAyODAuMTcsIDk3NC4wMCAyNjMuMDAgQyA5NjQuMzMgMjQ1LjgzLCA5NTIuMDAgMjI5LjY3LCA5NDAuMDAgMjE2LjAwIEMgOTI4LjAwIDIwMi4zMywgOTE3LjE3IDE5Mi4wMCwgOTAyLjAwIDE4MS4wMCBDIDg4Ni44MyAxNzAuMDAsIDg2Ni41MCAxNTguMTcsIDg0OS4wMCAxNTAuMDAgQyA4MzEuNTAgMTQxLjgzLCA4MTYuNjcgMTM3LjAwLCA3OTcuMDAgMTMyLjAwIEMgNzc3LjMzIDEyNy4wMCwgNzU2LjY3IDEyMi44MywgNzMxLjAwIDEyMC4wMCBDIDcwNS4zMyAxMTcuMTcsIDY3My42NyAxMTUuMzMsIDY0My4wMCAxMTUuMDAgQyA2MTIuMzMgMTE0LjY3LCA1NzUuNjcgMTE1LjY3LCA1NDcuMDAgMTE4LjAwIEMgNTE4LjMzIDEyMC4zMywgNDk2LjE3IDEyMy4wMCwgNDcxLjAwIDEyOS4wMCBDIDQ0NS44MyAxMzUuMDAsIDQxOC4zMyAxNDMuNTAsIDM5Ni4wMCAxNTQuMDAgQyAzNzMuNjcgMTY0LjUwLCAzNTMuNTAgMTc4LjUwLCAzMzcuMDAgMTkyLjAwIEMgMzIwLjUwIDIwNS41MCwgMzA5LjMzIDIxOC4zMywgMjk3LjAwIDIzNS4wMCBDIDI4NC42NyAyNTEuNjcsIDI3MS44MyAyNzIuMTcsIDI2My4wMCAyOTIuMDAgQyAyNTQuMTcgMzExLjgzLCAyNDcuNTAgMzMwLjMzLCAyNDQuMDAgMzU0LjAwIFoiLz48cGF0aCBkPSJNIDI4OS4wMCA1MzYuMDAgQyAyODMuMTcgNTM1LjUwLCAyODQuODMgNTMzLjAwLCAyODQuMDAgNTQ0LjAwIEMgMjgzLjE3IDU1NS4wMCwgMjgyLjY3IDU3OC42NywgMjg0LjAwIDYwMi4wMCBDIDI4NS4zMyA2MjUuMzMsIDI4Ny4wMCA2NTEuODMsIDI5Mi4wMCA2ODQuMDAgQyAyOTcuMDAgNzE2LjE3LCAzMDYuMzMgNzYzLjUwLCAzMTQuMDAgNzk1LjAwIEMgMzIxLjY3IDgyNi41MCwgMzI4LjY3IDg0Ny4xNywgMzM4LjAwIDg3My4wMCBDIDM0Ny4zMyA4OTguODMsIDM1Ny4wMCA5MjMuNjcsIDM3MC4wMCA5NTAuMDAgQyAzODMuMDAgOTc2LjMzLCAzOTkuNjcgMTAwNi4wMCwgNDE2LjAwIDEwMzEuMDAgQyA0MzIuMzMgMTA1Ni4wMCwgNDU1LjMzIDEwODQuNTAsIDQ2OC4wMCAxMTAwLjAwIEMgNDgwLjY3IDExMTUuNTAsIDQ4Ni4xNyAxMTE5LjMzLCA0OTIuMDAgMTEyNC4wMCBDIDQ5Ny44MyAxMTI4LjY3LCA1MDAuNjcgMTEyNy42NywgNTAzLjAwIDExMjguMDAgQyA1MDUuMzMgMTEyOC4zMywgNTA1LjUwIDExMjcuNTAsIDUwNi4wMCAxMTI2LjAwIEMgNTA2LjUwIDExMjQuNTAsIDUxMC4zMyAxMTMyLjAwLCA1MDYuMDAgMTExOS4wMCBDIDUwMS42NyAxMTA2LjAwLCA0ODguMTcgMTA3My44MywgNDgwLjAwIDEwNDguMDAgQyA0NzEuODMgMTAyMi4xNywgNDYyLjY3IDk4Ny42NywgNDU3LjAwIDk2NC4wMCBDIDQ1MS4zMyA5NDAuMzMsIDQ0OS4xNyA5MjcuMzMsIDQ0Ni4wMCA5MDYuMDAgQyA0NDIuODMgODg0LjY3LCA0MzkuNTAgODY1LjAwLCA0MzguMDAgODM2LjAwIEMgNDM2LjUwIDgwNy4wMCwgNDM2LjUwIDc1OC4zMywgNDM3LjAwIDczMi4wMCBDIDQzNy41MCA3MDUuNjcsIDQzOS4wMCA2OTYuMzMsIDQ0MS4wMCA2NzguMDAgQyA0NDMuMDAgNjU5LjY3LCA0NDQuODMgNjQ0LjAwLCA0NDkuMDAgNjIyLjAwIEMgNDUzLjE3IDYwMC4wMCwgNDY0LjUwIDU1OS4wMCwgNDY2LjAwIDU0Ni4wMCBDIDQ2Ny41MCA1MzMuMDAsIDQ2OC42NyA1NDIuNTAsIDQ1OC4wMCA1NDQuMDAgQyA0NDcuMzMgNTQ1LjUwLCA0MTguMzMgNTUzLjE3LCA0MDIuMDAgNTU1LjAwIEMgMzg1LjY3IDU1Ni44MywgMzczLjgzIDU1Ni4zMywgMzYwLjAwIDU1NS4wMCBDIDM0Ni4xNyA1NTMuNjcsIDMzMC44MyA1NTAuMTcsIDMxOS4wMCA1NDcuMDAgQyAzMDcuMTcgNTQzLjgzLCAyOTQuODMgNTM2LjUwLCAyODkuMDAgNTM2LjAwIFoiLz48cGF0aCBkPSJNIDk2MS4wMCA1MzcuMDAgQyA5NDguNTAgNTM5LjE3LCA5MDcuODMgNTUyLjAwLCA4ODkuMDAgNTU1LjAwIEMgODcwLjE3IDU1OC4wMCwgODY0LjE3IDU1Ny4wMCwgODQ4LjAwIDU1NS4wMCBDIDgzMS44MyA1NTMuMDAsIDgwMi44MyA1NDUuMDAsIDc5Mi4wMCA1NDMuMDAgQyA3ODEuMTcgNTQxLjAwLCA3ODQuODMgNTQyLjUwLCA3ODMuMDAgNTQzLjAwIEMgNzgxLjE3IDU0My41MCwgNzc4LjY3IDUzMy44MywgNzgxLjAwIDU0Ni4wMCBDIDc4My4zMyA1NTguMTcsIDc5Mi42NyA1OTIuMzMsIDc5Ny4wMCA2MTYuMDAgQyA4MDEuMzMgNjM5LjY3LCA4MDQuODMgNjY4LjgzLCA4MDcuMDAgNjg4LjAwIEMgODA5LjE3IDcwNy4xNywgODA5LjY3IDcwOS4wMCwgODEwLjAwIDczMS4wMCBDIDgxMC4zMyA3NTMuMDAsIDgxMC41MCA3OTIuODMsIDgwOS4wMCA4MjAuMDAgQyA4MDcuNTAgODQ3LjE3LCA4MDQuNTAgODcwLjUwLCA4MDEuMDAgODk0LjAwIEMgNzk3LjUwIDkxNy41MCwgNzk0LjAwIDkzNi4xNywgNzg4LjAwIDk2MS4wMCBDIDc4Mi4wMCA5ODUuODMsIDc3My41MCAxMDE2LjY3LCA3NjUuMDAgMTA0My4wMCBDIDc1Ni41MCAxMDY5LjMzLCA3NDEuMzMgMTEwNC44MywgNzM3LjAwIDExMTkuMDAgQyA3MzIuNjcgMTEzMy4xNywgNzM2LjY3IDExMjcuMTcsIDczOS4wMCAxMTI4LjAwIEMgNzQxLjMzIDExMjguODMsIDc0NS44MyAxMTI3LjgzLCA3NTEuMDAgMTEyNC4wMCBDIDc1Ni4xNyAxMTIwLjE3LCA3NTcuMzMgMTEyMC41MCwgNzcwLjAwIDExMDUuMDAgQyA3ODIuNjcgMTA4OS41MCwgODExLjMzIDEwNTMuNTAsIDgyNy4wMCAxMDMxLjAwIEMgODQyLjY3IDEwMDguNTAsIDg1MS4xNyA5OTUuMDAsIDg2NC4wMCA5NzAuMDAgQyA4NzYuODMgOTQ1LjAwLCA4OTIuODMgOTEwLjAwLCA5MDQuMDAgODgxLjAwIEMgOTE1LjE3IDg1Mi4wMCwgOTIzLjAwIDgyNi42NywgOTMxLjAwIDc5Ni4wMCBDIDkzOS4wMCA3NjUuMzMsIDk0Ni42NyA3MjguNjcsIDk1Mi4wMCA2OTcuMDAgQyA5NTcuMzMgNjY1LjMzLCA5NjEuMDAgNjMxLjgzLCA5NjMuMDAgNjA2LjAwIEMgOTY1LjAwIDU4MC4xNywgOTY0LjMzIDU1My41MCwgOTY0LjAwIDU0Mi4wMCBDIDk2My42NyA1MzAuNTAsIDk3My41MCA1MzQuODMsIDk2MS4wMCA1MzcuMDAgWiIvPgogIDwvZz4KPC9zdmc+Cg==";
|
|
16
|
-
function getStorage(mode) {
|
|
17
|
-
if (typeof window === "undefined") return null;
|
|
18
|
-
try {
|
|
19
|
-
const storage = mode === "session" ? window.sessionStorage : window.localStorage;
|
|
20
|
-
const testKey = "__walros_portal_test__";
|
|
21
|
-
storage.setItem(testKey, "1");
|
|
22
|
-
storage.removeItem(testKey);
|
|
23
|
-
return storage;
|
|
24
|
-
} catch {
|
|
25
|
-
return null;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
function shouldRunTransition(enabled, storageMode, storageKey) {
|
|
29
|
-
if (!enabled) return false;
|
|
30
|
-
if (storageMode === "always") return true;
|
|
31
|
-
if (typeof window === "undefined") return false;
|
|
32
|
-
const storage = getStorage(storageMode);
|
|
33
|
-
if (!storage) return true;
|
|
34
|
-
try {
|
|
35
|
-
return storage.getItem(storageKey) == null;
|
|
36
|
-
} catch {
|
|
37
|
-
return true;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
function WalrosPortalTransition({
|
|
41
|
-
duration = 900,
|
|
42
|
-
onComplete,
|
|
43
|
-
backgroundColor = "#000000",
|
|
44
|
-
enabled = true,
|
|
45
|
-
storageMode = "always",
|
|
46
|
-
storageKey = "walros-portal-seen",
|
|
47
|
-
zIndex = 9999
|
|
48
|
-
}) {
|
|
49
|
-
const [shouldRun] = useState(
|
|
50
|
-
() => shouldRunTransition(enabled, storageMode, storageKey)
|
|
51
|
-
);
|
|
52
|
-
const [visible, setVisible] = useState(shouldRun);
|
|
53
|
-
const [size, setSize] = useState({ w: 0, h: 0 });
|
|
54
|
-
const overlayRef = useRef(null);
|
|
55
|
-
const maskScaleRef = useRef(null);
|
|
56
|
-
const completedRef = useRef(false);
|
|
57
|
-
const startedRef = useRef(false);
|
|
58
|
-
const rafRef = useRef(null);
|
|
59
|
-
const timelineRef = useRef(null);
|
|
60
|
-
const previousOverflowRef = useRef("");
|
|
61
|
-
const uid = useId().replace(/[:]/g, "_");
|
|
62
|
-
const maskId = `walros-portal-mask-${uid}`;
|
|
63
|
-
useEffect(() => {
|
|
64
|
-
if (!visible) return;
|
|
65
|
-
const element = overlayRef.current;
|
|
66
|
-
if (!element) return;
|
|
67
|
-
const measure = () => {
|
|
68
|
-
const rect = element.getBoundingClientRect();
|
|
69
|
-
setSize(
|
|
70
|
-
(previous) => previous.w === rect.width && previous.h === rect.height ? previous : { w: rect.width, h: rect.height }
|
|
71
|
-
);
|
|
72
|
-
};
|
|
73
|
-
measure();
|
|
74
|
-
const observer = typeof ResizeObserver !== "undefined" ? new ResizeObserver(measure) : null;
|
|
75
|
-
observer?.observe(element);
|
|
76
|
-
window.addEventListener("resize", measure);
|
|
77
|
-
return () => {
|
|
78
|
-
observer?.disconnect();
|
|
79
|
-
window.removeEventListener("resize", measure);
|
|
80
|
-
};
|
|
81
|
-
}, [visible]);
|
|
82
|
-
useLayoutEffect(() => {
|
|
83
|
-
if (!enabled) {
|
|
84
|
-
setVisible(false);
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
if (!visible) return;
|
|
88
|
-
if (completedRef.current || startedRef.current) return;
|
|
89
|
-
if (size.w <= 0 || size.h <= 0) return;
|
|
90
|
-
const overlay = overlayRef.current;
|
|
91
|
-
const maskScale = maskScaleRef.current;
|
|
92
|
-
if (!overlay || !maskScale) return;
|
|
93
|
-
startedRef.current = true;
|
|
94
|
-
previousOverflowRef.current = document.body.style.overflow;
|
|
95
|
-
document.body.style.overflow = "hidden";
|
|
96
|
-
const finish = () => {
|
|
97
|
-
if (completedRef.current) return;
|
|
98
|
-
completedRef.current = true;
|
|
99
|
-
document.body.style.overflow = previousOverflowRef.current;
|
|
100
|
-
if (storageMode !== "always") {
|
|
101
|
-
const storage = getStorage(storageMode);
|
|
102
|
-
try {
|
|
103
|
-
storage?.setItem(storageKey, "1");
|
|
104
|
-
} catch {
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
setVisible(false);
|
|
108
|
-
onComplete?.();
|
|
109
|
-
};
|
|
110
|
-
const reducedMotion = window.matchMedia(
|
|
111
|
-
"(prefers-reduced-motion: reduce)"
|
|
112
|
-
).matches;
|
|
113
|
-
if (reducedMotion) {
|
|
114
|
-
const timeline = gsap.timeline({ onComplete: finish });
|
|
115
|
-
timelineRef.current = timeline;
|
|
116
|
-
timeline.to(overlay, {
|
|
117
|
-
opacity: 0,
|
|
118
|
-
duration: 0.15,
|
|
119
|
-
ease: "power1.out"
|
|
120
|
-
});
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
rafRef.current = requestAnimationFrame(() => {
|
|
124
|
-
rafRef.current = null;
|
|
125
|
-
const halfDiagonal = Math.sqrt(size.w * size.w + size.h * size.h) / 2;
|
|
126
|
-
const initialPixels2 = Math.min(
|
|
127
|
-
180,
|
|
128
|
-
Math.max(120, size.w * 0.12)
|
|
129
|
-
);
|
|
130
|
-
const initialScale2 = initialPixels2 / SILHOUETTE_VIEWBOX;
|
|
131
|
-
const finalScale = (halfDiagonal + 80) / PORTAL_RADIUS * 1.15;
|
|
132
|
-
gsap.set(maskScale, {
|
|
133
|
-
svgOrigin: "0 0",
|
|
134
|
-
scale: initialScale2
|
|
135
|
-
});
|
|
136
|
-
gsap.set(overlay, { opacity: 1 });
|
|
137
|
-
const totalSeconds = duration / 1e3;
|
|
138
|
-
const timeline = gsap.timeline({ onComplete: finish });
|
|
139
|
-
timelineRef.current = timeline;
|
|
140
|
-
timeline.to(
|
|
141
|
-
maskScale,
|
|
142
|
-
{
|
|
143
|
-
scale: initialScale2 * 1.4,
|
|
144
|
-
duration: totalSeconds * 0.15,
|
|
145
|
-
ease: "power2.out"
|
|
146
|
-
},
|
|
147
|
-
0
|
|
148
|
-
);
|
|
149
|
-
timeline.to(
|
|
150
|
-
maskScale,
|
|
151
|
-
{
|
|
152
|
-
scale: finalScale,
|
|
153
|
-
duration: totalSeconds * 0.85,
|
|
154
|
-
ease: "power2.in"
|
|
155
|
-
},
|
|
156
|
-
totalSeconds * 0.15
|
|
157
|
-
);
|
|
158
|
-
timeline.to(
|
|
159
|
-
overlay,
|
|
160
|
-
{
|
|
161
|
-
opacity: 0,
|
|
162
|
-
duration: totalSeconds * 0.1,
|
|
163
|
-
ease: "power2.out"
|
|
164
|
-
},
|
|
165
|
-
totalSeconds * 0.9
|
|
166
|
-
);
|
|
167
|
-
});
|
|
168
|
-
}, [
|
|
169
|
-
duration,
|
|
170
|
-
enabled,
|
|
171
|
-
onComplete,
|
|
172
|
-
size,
|
|
173
|
-
storageKey,
|
|
174
|
-
storageMode,
|
|
175
|
-
visible
|
|
176
|
-
]);
|
|
177
|
-
useEffect(() => {
|
|
178
|
-
return () => {
|
|
179
|
-
if (rafRef.current !== null) {
|
|
180
|
-
cancelAnimationFrame(rafRef.current);
|
|
181
|
-
}
|
|
182
|
-
timelineRef.current?.kill();
|
|
183
|
-
if (startedRef.current && !completedRef.current) {
|
|
184
|
-
document.body.style.overflow = previousOverflowRef.current;
|
|
185
|
-
}
|
|
186
|
-
};
|
|
187
|
-
}, []);
|
|
188
|
-
if (!shouldRun || !visible) return null;
|
|
189
|
-
const { w, h } = size;
|
|
190
|
-
const ready = w > 0 && h > 0;
|
|
191
|
-
const viewportCenterX = w / 2;
|
|
192
|
-
const viewportCenterY = h / 2;
|
|
193
|
-
const initialPixels = Math.min(
|
|
194
|
-
180,
|
|
195
|
-
Math.max(120, w * 0.12)
|
|
196
|
-
);
|
|
197
|
-
const initialScale = initialPixels / SILHOUETTE_VIEWBOX;
|
|
198
|
-
const visualCenter = SILHOUETTE_VIEWBOX / 2;
|
|
199
|
-
const initialOffsetX = (visualCenter - FOCUS_X) * initialScale;
|
|
200
|
-
const initialOffsetY = (visualCenter - FOCUS_Y) * initialScale;
|
|
201
|
-
const portalCenterX = viewportCenterX - initialOffsetX;
|
|
202
|
-
const portalCenterY = viewportCenterY - initialOffsetY;
|
|
203
|
-
return /* @__PURE__ */ jsx(
|
|
204
|
-
"div",
|
|
205
|
-
{
|
|
206
|
-
ref: overlayRef,
|
|
207
|
-
"aria-hidden": "true",
|
|
208
|
-
style: {
|
|
209
|
-
position: "fixed",
|
|
210
|
-
inset: 0,
|
|
211
|
-
width: "100vw",
|
|
212
|
-
height: "100dvh",
|
|
213
|
-
zIndex,
|
|
214
|
-
pointerEvents: "none",
|
|
215
|
-
overflow: "hidden",
|
|
216
|
-
backgroundColor: ready ? "transparent" : backgroundColor
|
|
217
|
-
},
|
|
218
|
-
children: ready && /* @__PURE__ */ jsxs(
|
|
219
|
-
"svg",
|
|
220
|
-
{
|
|
221
|
-
width: "100%",
|
|
222
|
-
height: "100%",
|
|
223
|
-
viewBox: `0 0 ${w} ${h}`,
|
|
224
|
-
preserveAspectRatio: "none",
|
|
225
|
-
style: {
|
|
226
|
-
position: "absolute",
|
|
227
|
-
inset: 0,
|
|
228
|
-
display: "block"
|
|
229
|
-
},
|
|
230
|
-
children: [
|
|
231
|
-
/* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs(
|
|
232
|
-
"mask",
|
|
233
|
-
{
|
|
234
|
-
id: maskId,
|
|
235
|
-
maskUnits: "userSpaceOnUse",
|
|
236
|
-
x: "0",
|
|
237
|
-
y: "0",
|
|
238
|
-
width: w,
|
|
239
|
-
height: h,
|
|
240
|
-
children: [
|
|
241
|
-
/* @__PURE__ */ jsx(
|
|
242
|
-
"rect",
|
|
243
|
-
{
|
|
244
|
-
x: "0",
|
|
245
|
-
y: "0",
|
|
246
|
-
width: w,
|
|
247
|
-
height: h,
|
|
248
|
-
fill: "white"
|
|
249
|
-
}
|
|
250
|
-
),
|
|
251
|
-
/* @__PURE__ */ jsx(
|
|
252
|
-
"g",
|
|
253
|
-
{
|
|
254
|
-
transform: `translate(${portalCenterX} ${portalCenterY})`,
|
|
255
|
-
children: /* @__PURE__ */ jsx(
|
|
256
|
-
"g",
|
|
257
|
-
{
|
|
258
|
-
ref: maskScaleRef,
|
|
259
|
-
transform: `scale(${initialScale})`,
|
|
260
|
-
children: /* @__PURE__ */ jsx(
|
|
261
|
-
"image",
|
|
262
|
-
{
|
|
263
|
-
href: WALROS_PORTAL_SILHOUETTE_URL,
|
|
264
|
-
x: -FOCUS_X,
|
|
265
|
-
y: -FOCUS_Y,
|
|
266
|
-
width: SILHOUETTE_VIEWBOX,
|
|
267
|
-
height: SILHOUETTE_VIEWBOX
|
|
268
|
-
}
|
|
269
|
-
)
|
|
270
|
-
}
|
|
271
|
-
)
|
|
272
|
-
}
|
|
273
|
-
)
|
|
274
|
-
]
|
|
275
|
-
}
|
|
276
|
-
) }),
|
|
277
|
-
/* @__PURE__ */ jsx(
|
|
278
|
-
"rect",
|
|
279
|
-
{
|
|
280
|
-
x: "0",
|
|
281
|
-
y: "0",
|
|
282
|
-
width: w,
|
|
283
|
-
height: h,
|
|
284
|
-
fill: backgroundColor,
|
|
285
|
-
mask: `url(#${maskId})`
|
|
286
|
-
}
|
|
287
|
-
)
|
|
288
|
-
]
|
|
289
|
-
}
|
|
290
|
-
)
|
|
291
|
-
}
|
|
292
|
-
);
|
|
293
|
-
}
|
|
2
|
+
import { useState as useState4 } from "react";
|
|
3
|
+
import { createPortal as createPortal2 } from "react-dom";
|
|
294
4
|
|
|
295
5
|
// src/assets.ts
|
|
296
6
|
var walrosPortalSilhouetteUrl = new URL(
|
|
@@ -314,46 +24,133 @@ var walrosThemeGlitchSoundUrl = new URL(
|
|
|
314
24
|
import.meta.url
|
|
315
25
|
).href;
|
|
316
26
|
|
|
317
|
-
// src/components/
|
|
318
|
-
import {
|
|
319
|
-
|
|
320
|
-
alt = "WalrOS",
|
|
321
|
-
draggable = false,
|
|
322
|
-
...props
|
|
323
|
-
}) {
|
|
324
|
-
return /* @__PURE__ */ jsx2(
|
|
325
|
-
"img",
|
|
326
|
-
{
|
|
327
|
-
src: walrosLogoChromeUrl,
|
|
328
|
-
alt,
|
|
329
|
-
draggable,
|
|
330
|
-
...props
|
|
331
|
-
}
|
|
332
|
-
);
|
|
333
|
-
}
|
|
27
|
+
// src/components/WalrosThemeTransition.tsx
|
|
28
|
+
import { useEffect as useEffect2, useLayoutEffect as useLayoutEffect3, useRef as useRef2, useState as useState3 } from "react";
|
|
29
|
+
import { createPortal } from "react-dom";
|
|
334
30
|
|
|
335
|
-
// src/components/
|
|
336
|
-
import {
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
31
|
+
// src/components/Walros3DPortalTransition.tsx
|
|
32
|
+
import { useEffect, useId, useLayoutEffect, useRef, useState } from "react";
|
|
33
|
+
import gsap from "gsap";
|
|
34
|
+
|
|
35
|
+
// src/portalSilhouette.ts
|
|
36
|
+
var walrosPortalPaths = [
|
|
37
|
+
"M 244.00 354.00 C 240.50 377.67, 240.17 413.67, 242.00 434.00 C 243.83 454.33, 249.50 464.50, 255.00 476.00 C 260.50 487.50, 268.50 496.00, 275.00 503.00 C 281.50 510.00, 287.17 513.67, 294.00 518.00 C 300.83 522.33, 306.00 525.67, 316.00 529.00 C 326.00 532.33, 336.33 536.67, 354.00 538.00 C 371.67 539.33, 397.83 540.83, 422.00 537.00 C 446.17 533.17, 474.17 525.33, 499.00 515.00 C 523.83 504.67, 550.00 489.33, 571.00 475.00 C 592.00 460.67, 615.00 436.50, 625.00 429.00 C 635.00 421.50, 623.67 424.00, 631.00 430.00 C 638.33 436.00, 656.67 454.83, 669.00 465.00 C 681.33 475.17, 690.00 482.17, 705.00 491.00 C 720.00 499.83, 743.67 511.50, 759.00 518.00 C 774.33 524.50, 784.00 526.83, 797.00 530.00 C 810.00 533.17, 820.00 535.83, 837.00 537.00 C 854.00 538.17, 881.17 539.00, 899.00 537.00 C 916.83 535.00, 932.00 530.00, 944.00 525.00 C 956.00 520.00, 962.00 516.17, 971.00 507.00 C 980.00 497.83, 991.67 482.83, 998.00 470.00 C 1004.33 457.17, 1007.17 446.33, 1009.00 430.00 C 1010.83 413.67, 1010.83 390.50, 1009.00 372.00 C 1007.17 353.50, 1003.83 337.17, 998.00 319.00 C 992.17 300.83, 983.67 280.17, 974.00 263.00 C 964.33 245.83, 952.00 229.67, 940.00 216.00 C 928.00 202.33, 917.17 192.00, 902.00 181.00 C 886.83 170.00, 866.50 158.17, 849.00 150.00 C 831.50 141.83, 816.67 137.00, 797.00 132.00 C 777.33 127.00, 756.67 122.83, 731.00 120.00 C 705.33 117.17, 673.67 115.33, 643.00 115.00 C 612.33 114.67, 575.67 115.67, 547.00 118.00 C 518.33 120.33, 496.17 123.00, 471.00 129.00 C 445.83 135.00, 418.33 143.50, 396.00 154.00 C 373.67 164.50, 353.50 178.50, 337.00 192.00 C 320.50 205.50, 309.33 218.33, 297.00 235.00 C 284.67 251.67, 271.83 272.17, 263.00 292.00 C 254.17 311.83, 247.50 330.33, 244.00 354.00 Z",
|
|
38
|
+
"M 289.00 536.00 C 283.17 535.50, 284.83 533.00, 284.00 544.00 C 283.17 555.00, 282.67 578.67, 284.00 602.00 C 285.33 625.33, 287.00 651.83, 292.00 684.00 C 297.00 716.17, 306.33 763.50, 314.00 795.00 C 321.67 826.50, 328.67 847.17, 338.00 873.00 C 347.33 898.83, 357.00 923.67, 370.00 950.00 C 383.00 976.33, 399.67 1006.00, 416.00 1031.00 C 432.33 1056.00, 455.33 1084.50, 468.00 1100.00 C 480.67 1115.50, 486.17 1119.33, 492.00 1124.00 C 497.83 1128.67, 500.67 1127.67, 503.00 1128.00 C 505.33 1128.33, 505.50 1127.50, 506.00 1126.00 C 506.50 1124.50, 510.33 1132.00, 506.00 1119.00 C 501.67 1106.00, 488.17 1073.83, 480.00 1048.00 C 471.83 1022.17, 462.67 987.67, 457.00 964.00 C 451.33 940.33, 449.17 927.33, 446.00 906.00 C 442.83 884.67, 439.50 865.00, 438.00 836.00 C 436.50 807.00, 436.50 758.33, 437.00 732.00 C 437.50 705.67, 439.00 696.33, 441.00 678.00 C 443.00 659.67, 444.83 644.00, 449.00 622.00 C 453.17 600.00, 464.50 559.00, 466.00 546.00 C 467.50 533.00, 468.67 542.50, 458.00 544.00 C 447.33 545.50, 418.33 553.17, 402.00 555.00 C 385.67 556.83, 373.83 556.33, 360.00 555.00 C 346.17 553.67, 330.83 550.17, 319.00 547.00 C 307.17 543.83, 294.83 536.50, 289.00 536.00 Z",
|
|
39
|
+
"M 961.00 537.00 C 948.50 539.17, 907.83 552.00, 889.00 555.00 C 870.17 558.00, 864.17 557.00, 848.00 555.00 C 831.83 553.00, 802.83 545.00, 792.00 543.00 C 781.17 541.00, 784.83 542.50, 783.00 543.00 C 781.17 543.50, 778.67 533.83, 781.00 546.00 C 783.33 558.17, 792.67 592.33, 797.00 616.00 C 801.33 639.67, 804.83 668.83, 807.00 688.00 C 809.17 707.17, 809.67 709.00, 810.00 731.00 C 810.33 753.00, 810.50 792.83, 809.00 820.00 C 807.50 847.17, 804.50 870.50, 801.00 894.00 C 797.50 917.50, 794.00 936.17, 788.00 961.00 C 782.00 985.83, 773.50 1016.67, 765.00 1043.00 C 756.50 1069.33, 741.33 1104.83, 737.00 1119.00 C 732.67 1133.17, 736.67 1127.17, 739.00 1128.00 C 741.33 1128.83, 745.83 1127.83, 751.00 1124.00 C 756.17 1120.17, 757.33 1120.50, 770.00 1105.00 C 782.67 1089.50, 811.33 1053.50, 827.00 1031.00 C 842.67 1008.50, 851.17 995.00, 864.00 970.00 C 876.83 945.00, 892.83 910.00, 904.00 881.00 C 915.17 852.00, 923.00 826.67, 931.00 796.00 C 939.00 765.33, 946.67 728.67, 952.00 697.00 C 957.33 665.33, 961.00 631.83, 963.00 606.00 C 965.00 580.17, 964.33 553.50, 964.00 542.00 C 963.67 530.50, 973.50 534.83, 961.00 537.00 Z"
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
// src/components/Walros3DPortalTransition.tsx
|
|
43
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
44
|
+
var FOCUS_X = 626;
|
|
45
|
+
var FOCUS_Y = 333;
|
|
46
|
+
var VISIBLE_LEFT = 244;
|
|
47
|
+
var VISIBLE_RIGHT = 1010;
|
|
48
|
+
var VISIBLE_TOP = 115;
|
|
49
|
+
var VISIBLE_BOTTOM = 1128;
|
|
50
|
+
var PORTAL_RADIUS = 190;
|
|
51
|
+
function Walros3DPortalTransition({
|
|
52
|
+
origin,
|
|
53
|
+
onComplete,
|
|
54
|
+
duration = 900,
|
|
55
|
+
backgroundColor = "#000",
|
|
56
|
+
zIndex = 10001,
|
|
57
|
+
lockScroll = true
|
|
342
58
|
}) {
|
|
343
|
-
const
|
|
344
|
-
|
|
345
|
-
"
|
|
59
|
+
const [visible, setVisible] = useState(true);
|
|
60
|
+
const [viewport, setViewport] = useState(() => ({
|
|
61
|
+
width: typeof window === "undefined" ? 0 : window.innerWidth,
|
|
62
|
+
height: typeof window === "undefined" ? 0 : window.innerHeight
|
|
63
|
+
}));
|
|
64
|
+
const overlay = useRef(null);
|
|
65
|
+
const portal = useRef(null);
|
|
66
|
+
const completeRef = useRef(onComplete);
|
|
67
|
+
completeRef.current = onComplete;
|
|
68
|
+
const maskId = `walros-3d-portal-${useId().replace(/:/g, "_")}`;
|
|
69
|
+
useEffect(() => {
|
|
70
|
+
const updateViewport = () => setViewport({ width: window.innerWidth, height: window.innerHeight });
|
|
71
|
+
window.addEventListener("resize", updateViewport);
|
|
72
|
+
return () => window.removeEventListener("resize", updateViewport);
|
|
73
|
+
}, []);
|
|
74
|
+
useLayoutEffect(() => {
|
|
75
|
+
if (!visible || viewport.width <= 0 || viewport.height <= 0 || !overlay.current || !portal.current) return;
|
|
76
|
+
const previousOverflow = document.body.style.overflow;
|
|
77
|
+
if (lockScroll) document.body.style.overflow = "hidden";
|
|
78
|
+
const visibleWidth = VISIBLE_RIGHT - VISIBLE_LEFT;
|
|
79
|
+
const visibleHeight = VISIBLE_BOTTOM - VISIBLE_TOP;
|
|
80
|
+
const visualCenterX = (VISIBLE_LEFT + VISIBLE_RIGHT) / 2;
|
|
81
|
+
const visualCenterY = (VISIBLE_TOP + VISIBLE_BOTTOM) / 2;
|
|
82
|
+
const initialScale = Math.min(origin.width / visibleWidth, origin.height / visibleHeight) * 0.985;
|
|
83
|
+
const initialX = origin.centerX - (visualCenterX - FOCUS_X) * initialScale;
|
|
84
|
+
const initialY = origin.centerY - (visualCenterY - FOCUS_Y) * initialScale;
|
|
85
|
+
const targetX = viewport.width / 2 - (visualCenterX - FOCUS_X) * initialScale;
|
|
86
|
+
const targetY = viewport.height / 2 - (visualCenterY - FOCUS_Y) * initialScale;
|
|
87
|
+
const diagonal = Math.hypot(viewport.width, viewport.height) / 2;
|
|
88
|
+
const finalScale = (diagonal + 80) / PORTAL_RADIUS * 1.15;
|
|
89
|
+
const total = duration / 1e3;
|
|
90
|
+
gsap.set(portal.current, {
|
|
91
|
+
x: initialX,
|
|
92
|
+
y: initialY,
|
|
93
|
+
scale: initialScale,
|
|
94
|
+
svgOrigin: "0 0"
|
|
95
|
+
});
|
|
96
|
+
gsap.set(overlay.current, { opacity: 1 });
|
|
97
|
+
const finish = () => {
|
|
98
|
+
if (lockScroll) document.body.style.overflow = previousOverflow;
|
|
99
|
+
setVisible(false);
|
|
100
|
+
completeRef.current?.();
|
|
101
|
+
};
|
|
102
|
+
const reducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
103
|
+
const timeline = gsap.timeline({ onComplete: finish });
|
|
104
|
+
if (reducedMotion) {
|
|
105
|
+
timeline.to(overlay.current, { opacity: 0, duration: 0.15, ease: "power1.out" });
|
|
106
|
+
} else {
|
|
107
|
+
timeline.to(portal.current, {
|
|
108
|
+
x: targetX,
|
|
109
|
+
y: targetY,
|
|
110
|
+
scale: finalScale,
|
|
111
|
+
duration: total,
|
|
112
|
+
ease: "power2.in"
|
|
113
|
+
}).to(overlay.current, {
|
|
114
|
+
opacity: 0,
|
|
115
|
+
duration: total * 0.1,
|
|
116
|
+
ease: "power2.out"
|
|
117
|
+
}, total * 0.9);
|
|
118
|
+
}
|
|
119
|
+
return () => {
|
|
120
|
+
timeline.kill();
|
|
121
|
+
if (lockScroll) document.body.style.overflow = previousOverflow;
|
|
122
|
+
};
|
|
123
|
+
}, [duration, lockScroll, origin, viewport, visible]);
|
|
124
|
+
if (!visible) return null;
|
|
125
|
+
return /* @__PURE__ */ jsx(
|
|
126
|
+
"div",
|
|
346
127
|
{
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
128
|
+
ref: overlay,
|
|
129
|
+
className: "walros-3d-portal",
|
|
130
|
+
style: {
|
|
131
|
+
position: "fixed",
|
|
132
|
+
inset: 0,
|
|
133
|
+
width: "100vw",
|
|
134
|
+
height: "100dvh",
|
|
135
|
+
overflow: "hidden",
|
|
136
|
+
pointerEvents: "none",
|
|
137
|
+
zIndex,
|
|
138
|
+
backgroundColor: viewport.width > 0 && viewport.height > 0 ? "transparent" : backgroundColor
|
|
139
|
+
},
|
|
140
|
+
"aria-hidden": "true",
|
|
141
|
+
children: /* @__PURE__ */ jsxs("svg", { width: "100%", height: "100%", viewBox: `0 0 ${viewport.width} ${viewport.height}`, preserveAspectRatio: "none", style: { display: "block" }, children: [
|
|
142
|
+
/* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs("mask", { id: maskId, maskUnits: "userSpaceOnUse", x: "0", y: "0", width: viewport.width, height: viewport.height, children: [
|
|
143
|
+
/* @__PURE__ */ jsx("rect", { width: viewport.width, height: viewport.height, fill: "white" }),
|
|
144
|
+
/* @__PURE__ */ jsx("g", { ref: portal, children: /* @__PURE__ */ jsx("g", { transform: `translate(${-FOCUS_X} ${-FOCUS_Y})`, fill: "black", children: walrosPortalPaths.map((path, index) => /* @__PURE__ */ jsx("path", { d: path }, index)) }) })
|
|
145
|
+
] }) }),
|
|
146
|
+
/* @__PURE__ */ jsx("rect", { width: viewport.width, height: viewport.height, fill: backgroundColor, mask: `url(#${maskId})` })
|
|
147
|
+
] })
|
|
351
148
|
}
|
|
352
149
|
);
|
|
353
150
|
}
|
|
354
151
|
|
|
355
152
|
// src/components/WalrosThemeGlitch.tsx
|
|
356
|
-
import { Fragment, jsx as
|
|
153
|
+
import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
357
154
|
var GLITCH_STYLES = `
|
|
358
155
|
.walros-theme-glitch-root {
|
|
359
156
|
position: fixed;
|
|
@@ -371,7 +168,6 @@ var GLITCH_STYLES = `
|
|
|
371
168
|
content: "";
|
|
372
169
|
position: absolute;
|
|
373
170
|
inset: 0;
|
|
374
|
-
mix-blend-mode: screen;
|
|
375
171
|
}
|
|
376
172
|
.walros-theme-glitch-root::before {
|
|
377
173
|
background: rgba(0, 0, 0, .82);
|
|
@@ -501,7 +297,7 @@ function WalrosThemeGlitch({
|
|
|
501
297
|
style
|
|
502
298
|
}) {
|
|
503
299
|
return /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
504
|
-
/* @__PURE__ */
|
|
300
|
+
/* @__PURE__ */ jsx2("style", { children: GLITCH_STYLES }),
|
|
505
301
|
active ? /* @__PURE__ */ jsxs2(
|
|
506
302
|
"div",
|
|
507
303
|
{
|
|
@@ -509,22 +305,374 @@ function WalrosThemeGlitch({
|
|
|
509
305
|
style: { zIndex, ...style },
|
|
510
306
|
"aria-hidden": "true",
|
|
511
307
|
children: [
|
|
512
|
-
/* @__PURE__ */
|
|
513
|
-
/* @__PURE__ */
|
|
514
|
-
/* @__PURE__ */
|
|
515
|
-
/* @__PURE__ */
|
|
308
|
+
/* @__PURE__ */ jsx2("span", { className: "walros-theme-glitch-band" }),
|
|
309
|
+
/* @__PURE__ */ jsx2("span", { className: "walros-theme-glitch-band" }),
|
|
310
|
+
/* @__PURE__ */ jsx2("span", { className: "walros-theme-glitch-band" }),
|
|
311
|
+
/* @__PURE__ */ jsx2("span", { className: "walros-theme-glitch-band" })
|
|
516
312
|
]
|
|
517
313
|
}
|
|
518
314
|
) : null
|
|
519
315
|
] });
|
|
520
316
|
}
|
|
521
317
|
|
|
318
|
+
// src/components/useOverlayHost.ts
|
|
319
|
+
import { useLayoutEffect as useLayoutEffect2, useState as useState2 } from "react";
|
|
320
|
+
function useOverlayHost(zIndex) {
|
|
321
|
+
const [host] = useState2(
|
|
322
|
+
() => typeof document === "undefined" ? null : document.createElement("div")
|
|
323
|
+
);
|
|
324
|
+
useLayoutEffect2(() => {
|
|
325
|
+
if (!host) return;
|
|
326
|
+
host.dataset.walrosOverlayRoot = "";
|
|
327
|
+
host.style.position = "fixed";
|
|
328
|
+
host.style.inset = "0";
|
|
329
|
+
host.style.pointerEvents = "none";
|
|
330
|
+
document.documentElement.appendChild(host);
|
|
331
|
+
return () => host.remove();
|
|
332
|
+
}, [host]);
|
|
333
|
+
useLayoutEffect2(() => {
|
|
334
|
+
if (host) host.style.zIndex = String(zIndex);
|
|
335
|
+
}, [host, zIndex]);
|
|
336
|
+
return host;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// src/components/WalrosThemeTransition.tsx
|
|
340
|
+
import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
341
|
+
var IMAGE_SIZE = "clamp(90px, 11vw, 150px)";
|
|
342
|
+
var IMAGE_WIDTH = 1254;
|
|
343
|
+
var VISIBLE_LEFT2 = 244;
|
|
344
|
+
var VISIBLE_RIGHT2 = 1010;
|
|
345
|
+
var VISIBLE_TOP2 = 115;
|
|
346
|
+
var VISIBLE_BOTTOM2 = 1128;
|
|
347
|
+
function WalrosPortalScene({
|
|
348
|
+
logoUrl,
|
|
349
|
+
portalDuration,
|
|
350
|
+
zIndex,
|
|
351
|
+
backgroundColor = "#000",
|
|
352
|
+
onComplete,
|
|
353
|
+
lockScroll = false
|
|
354
|
+
}) {
|
|
355
|
+
const logoRef = useRef2(null);
|
|
356
|
+
const [origin, setOrigin] = useState3(null);
|
|
357
|
+
const [portalComplete, setPortalComplete] = useState3(false);
|
|
358
|
+
const measureLogo = () => {
|
|
359
|
+
const image = logoRef.current;
|
|
360
|
+
if (!image) return;
|
|
361
|
+
const rect = image.getBoundingClientRect();
|
|
362
|
+
const scale = rect.width / IMAGE_WIDTH;
|
|
363
|
+
setOrigin({
|
|
364
|
+
centerX: rect.left + (VISIBLE_LEFT2 + VISIBLE_RIGHT2) / 2 * scale,
|
|
365
|
+
centerY: rect.top + (VISIBLE_TOP2 + VISIBLE_BOTTOM2) / 2 * scale,
|
|
366
|
+
width: (VISIBLE_RIGHT2 - VISIBLE_LEFT2) * scale,
|
|
367
|
+
height: (VISIBLE_BOTTOM2 - VISIBLE_TOP2) * scale
|
|
368
|
+
});
|
|
369
|
+
};
|
|
370
|
+
useLayoutEffect3(() => {
|
|
371
|
+
const image = logoRef.current;
|
|
372
|
+
if (image?.complete) measureLogo();
|
|
373
|
+
}, []);
|
|
374
|
+
return /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
375
|
+
!portalComplete && /* @__PURE__ */ jsx3(
|
|
376
|
+
"img",
|
|
377
|
+
{
|
|
378
|
+
ref: logoRef,
|
|
379
|
+
src: logoUrl,
|
|
380
|
+
onLoad: measureLogo,
|
|
381
|
+
onError: measureLogo,
|
|
382
|
+
alt: "",
|
|
383
|
+
"aria-hidden": "true",
|
|
384
|
+
style: {
|
|
385
|
+
position: "fixed",
|
|
386
|
+
left: "50%",
|
|
387
|
+
top: "45%",
|
|
388
|
+
width: IMAGE_SIZE,
|
|
389
|
+
height: IMAGE_SIZE,
|
|
390
|
+
transform: "translate(-50%, -50%)",
|
|
391
|
+
objectFit: "contain",
|
|
392
|
+
zIndex,
|
|
393
|
+
pointerEvents: "none"
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
),
|
|
397
|
+
!portalComplete && !origin && /* @__PURE__ */ jsx3("div", { style: { position: "fixed", inset: 0, zIndex: zIndex + 1, background: backgroundColor, pointerEvents: "none" }, "aria-hidden": "true" }),
|
|
398
|
+
!portalComplete && origin && /* @__PURE__ */ jsx3(
|
|
399
|
+
Walros3DPortalTransition,
|
|
400
|
+
{
|
|
401
|
+
origin,
|
|
402
|
+
duration: portalDuration,
|
|
403
|
+
zIndex: zIndex + 1,
|
|
404
|
+
backgroundColor,
|
|
405
|
+
lockScroll,
|
|
406
|
+
onComplete: () => {
|
|
407
|
+
setPortalComplete(true);
|
|
408
|
+
onComplete?.();
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
)
|
|
412
|
+
] });
|
|
413
|
+
}
|
|
414
|
+
function WalrosThemeTransition({
|
|
415
|
+
active,
|
|
416
|
+
portalDuration = 900,
|
|
417
|
+
logoUrl = walrosLogoChromeUrl,
|
|
418
|
+
zIndex = 1e4
|
|
419
|
+
}) {
|
|
420
|
+
const host = useOverlayHost(zIndex);
|
|
421
|
+
useEffect2(() => {
|
|
422
|
+
if (typeof window === "undefined") return;
|
|
423
|
+
const logo = new Image();
|
|
424
|
+
logo.src = logoUrl;
|
|
425
|
+
}, [logoUrl]);
|
|
426
|
+
if (!host) return null;
|
|
427
|
+
return createPortal(
|
|
428
|
+
/* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
429
|
+
active && /* @__PURE__ */ jsx3(WalrosPortalScene, { logoUrl, portalDuration, zIndex }),
|
|
430
|
+
/* @__PURE__ */ jsx3(WalrosThemeGlitch, { active, zIndex: zIndex + 2 })
|
|
431
|
+
] }),
|
|
432
|
+
host
|
|
433
|
+
);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
// src/components/WalrosPortalTransition.tsx
|
|
437
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
438
|
+
function getStorage(mode) {
|
|
439
|
+
if (typeof window === "undefined") return null;
|
|
440
|
+
try {
|
|
441
|
+
return mode === "session" ? window.sessionStorage : window.localStorage;
|
|
442
|
+
} catch {
|
|
443
|
+
return null;
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
function shouldRun(enabled, mode, key) {
|
|
447
|
+
if (!enabled) return false;
|
|
448
|
+
if (mode === "always") return true;
|
|
449
|
+
try {
|
|
450
|
+
return getStorage(mode)?.getItem(key) == null;
|
|
451
|
+
} catch {
|
|
452
|
+
return true;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
function WalrosPortalTransition({
|
|
456
|
+
duration = 900,
|
|
457
|
+
onComplete,
|
|
458
|
+
backgroundColor = "#000",
|
|
459
|
+
enabled = true,
|
|
460
|
+
storageMode = "always",
|
|
461
|
+
storageKey = "walros-portal-seen",
|
|
462
|
+
zIndex = 1e4
|
|
463
|
+
}) {
|
|
464
|
+
const [run] = useState4(() => shouldRun(enabled, storageMode, storageKey));
|
|
465
|
+
const [complete, setComplete] = useState4(false);
|
|
466
|
+
const host = useOverlayHost(zIndex);
|
|
467
|
+
if (!host || !enabled || !run || complete) return null;
|
|
468
|
+
return createPortal2(
|
|
469
|
+
/* @__PURE__ */ jsx4(
|
|
470
|
+
WalrosPortalScene,
|
|
471
|
+
{
|
|
472
|
+
logoUrl: walrosLogoChromeUrl,
|
|
473
|
+
portalDuration: duration,
|
|
474
|
+
backgroundColor,
|
|
475
|
+
zIndex,
|
|
476
|
+
lockScroll: true,
|
|
477
|
+
onComplete: () => {
|
|
478
|
+
if (storageMode !== "always") {
|
|
479
|
+
try {
|
|
480
|
+
getStorage(storageMode)?.setItem(storageKey, "1");
|
|
481
|
+
} catch {
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
setComplete(true);
|
|
485
|
+
onComplete?.();
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
),
|
|
489
|
+
host
|
|
490
|
+
);
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
// src/components/DirectionalCursor.tsx
|
|
494
|
+
import { useEffect as useEffect3, useRef as useRef3 } from "react";
|
|
495
|
+
import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
496
|
+
var DESKTOP_CURSOR_QUERY = "(min-width: 1024px) and (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference)";
|
|
497
|
+
var CURSOR_STYLES = `
|
|
498
|
+
.directional-cursor { position: fixed; top: 0; left: 0; z-index: 9999; width: 20px; height: 22px; opacity: 0; pointer-events: none; contain: layout style; will-change: transform; transition: opacity 100ms linear; }
|
|
499
|
+
.directional-cursor.is-visible { opacity: 1; }
|
|
500
|
+
.directional-cursor-shape { width: 20px; height: 22px; transform-origin: center center; will-change: transform; }
|
|
501
|
+
.directional-cursor svg { display: block; width: 20px; height: 22px; }
|
|
502
|
+
@media (min-width: 1024px) and (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {
|
|
503
|
+
html.has-directional-cursor, html.has-directional-cursor body, html.has-directional-cursor body * { cursor: none !important; }
|
|
504
|
+
html.has-directional-cursor :is(a, button, [role="button"], [onclick], .clickable, [data-clickable], input[type="button"], input[type="submit"], input[type="reset"], label[for]),
|
|
505
|
+
html.has-directional-cursor :is(a, button, [role="button"], [onclick], .clickable, [data-clickable], input[type="button"], input[type="submit"], input[type="reset"], label[for]) * { cursor: pointer !important; }
|
|
506
|
+
html.has-directional-cursor :is(input, textarea, select, [contenteditable="true"]) { cursor: text !important; }
|
|
507
|
+
}
|
|
508
|
+
`;
|
|
509
|
+
function DirectionalCursor() {
|
|
510
|
+
const positionLayer = useRef3(null);
|
|
511
|
+
const directionLayer = useRef3(null);
|
|
512
|
+
useEffect3(() => {
|
|
513
|
+
const position = positionLayer.current;
|
|
514
|
+
const direction = directionLayer.current;
|
|
515
|
+
if (!position || !direction) return;
|
|
516
|
+
const media = window.matchMedia(DESKTOP_CURSOR_QUERY);
|
|
517
|
+
let active = false;
|
|
518
|
+
let frame = 0;
|
|
519
|
+
let moveFrame = 0;
|
|
520
|
+
let scaleTimer = 0;
|
|
521
|
+
let latestEvent = null;
|
|
522
|
+
let currentX = window.innerWidth / 2;
|
|
523
|
+
let currentY = -60;
|
|
524
|
+
let targetX = currentX;
|
|
525
|
+
let targetY = currentY;
|
|
526
|
+
let currentAngle = 0;
|
|
527
|
+
let targetAngle = 0;
|
|
528
|
+
let hasAngle = false;
|
|
529
|
+
let currentScale = 1;
|
|
530
|
+
let targetScale = 1;
|
|
531
|
+
let lastX = currentX;
|
|
532
|
+
let lastY = 0;
|
|
533
|
+
const render = () => {
|
|
534
|
+
currentX += (targetX - currentX) * 0.4;
|
|
535
|
+
currentY += (targetY - currentY) * 0.4;
|
|
536
|
+
const angleDelta = (targetAngle - currentAngle + 540) % 360 - 180;
|
|
537
|
+
currentAngle += angleDelta * 0.24;
|
|
538
|
+
currentScale += (targetScale - currentScale) * 0.24;
|
|
539
|
+
position.style.transform = `translate3d(${currentX}px, ${currentY}px, 0)`;
|
|
540
|
+
direction.style.transform = `translate(-50%, -50%) rotate(${currentAngle}deg) scale(${currentScale})`;
|
|
541
|
+
const unsettled = Math.abs(targetX - currentX) > 0.08 || Math.abs(targetY - currentY) > 0.08 || Math.abs(angleDelta) > 0.08 || Math.abs(targetScale - currentScale) > 2e-3;
|
|
542
|
+
frame = unsettled ? window.requestAnimationFrame(render) : 0;
|
|
543
|
+
};
|
|
544
|
+
const requestRender = () => {
|
|
545
|
+
if (!frame) frame = window.requestAnimationFrame(render);
|
|
546
|
+
};
|
|
547
|
+
const processMove = () => {
|
|
548
|
+
moveFrame = 0;
|
|
549
|
+
const event = latestEvent;
|
|
550
|
+
if (!event) return;
|
|
551
|
+
const deltaX = event.clientX - lastX;
|
|
552
|
+
const deltaY = event.clientY - lastY;
|
|
553
|
+
const distance = Math.hypot(deltaX, deltaY);
|
|
554
|
+
targetX = event.clientX;
|
|
555
|
+
targetY = event.clientY;
|
|
556
|
+
position.classList.add("is-visible");
|
|
557
|
+
if (distance > 1.25) {
|
|
558
|
+
const rawAngle = Math.atan2(deltaY, deltaX) * (180 / Math.PI) + 90;
|
|
559
|
+
const normalizedAngle = (rawAngle % 360 + 360) % 360;
|
|
560
|
+
if (!hasAngle) {
|
|
561
|
+
targetAngle = normalizedAngle;
|
|
562
|
+
currentAngle = normalizedAngle;
|
|
563
|
+
hasAngle = true;
|
|
564
|
+
} else {
|
|
565
|
+
targetAngle = normalizedAngle;
|
|
566
|
+
}
|
|
567
|
+
targetScale = 0.92;
|
|
568
|
+
window.clearTimeout(scaleTimer);
|
|
569
|
+
scaleTimer = window.setTimeout(() => {
|
|
570
|
+
targetScale = 1;
|
|
571
|
+
requestRender();
|
|
572
|
+
}, 130);
|
|
573
|
+
}
|
|
574
|
+
lastX = event.clientX;
|
|
575
|
+
lastY = event.clientY;
|
|
576
|
+
requestRender();
|
|
577
|
+
};
|
|
578
|
+
const handleMouseMove = (event) => {
|
|
579
|
+
latestEvent = event;
|
|
580
|
+
if (!moveFrame) moveFrame = window.requestAnimationFrame(processMove);
|
|
581
|
+
};
|
|
582
|
+
const activate = () => {
|
|
583
|
+
if (active) return;
|
|
584
|
+
active = true;
|
|
585
|
+
document.documentElement.classList.add("has-directional-cursor");
|
|
586
|
+
window.addEventListener("mousemove", handleMouseMove, { passive: true });
|
|
587
|
+
};
|
|
588
|
+
const deactivate = () => {
|
|
589
|
+
if (!active) return;
|
|
590
|
+
active = false;
|
|
591
|
+
document.documentElement.classList.remove("has-directional-cursor");
|
|
592
|
+
position.classList.remove("is-visible");
|
|
593
|
+
window.removeEventListener("mousemove", handleMouseMove);
|
|
594
|
+
window.cancelAnimationFrame(frame);
|
|
595
|
+
window.cancelAnimationFrame(moveFrame);
|
|
596
|
+
window.clearTimeout(scaleTimer);
|
|
597
|
+
frame = 0;
|
|
598
|
+
moveFrame = 0;
|
|
599
|
+
};
|
|
600
|
+
const sync = () => {
|
|
601
|
+
if (media.matches) activate();
|
|
602
|
+
else deactivate();
|
|
603
|
+
};
|
|
604
|
+
media.addEventListener("change", sync);
|
|
605
|
+
sync();
|
|
606
|
+
return () => {
|
|
607
|
+
media.removeEventListener("change", sync);
|
|
608
|
+
deactivate();
|
|
609
|
+
};
|
|
610
|
+
}, []);
|
|
611
|
+
return /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
612
|
+
/* @__PURE__ */ jsx5("style", { children: CURSOR_STYLES }),
|
|
613
|
+
/* @__PURE__ */ jsx5("div", { ref: positionLayer, className: "directional-cursor", "aria-hidden": "true", children: /* @__PURE__ */ jsx5("div", { ref: directionLayer, className: "directional-cursor-shape", children: /* @__PURE__ */ jsxs4("svg", { width: "50", height: "54", viewBox: "0 0 50 54", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
|
|
614
|
+
/* @__PURE__ */ jsxs4("g", { filter: "url(#walros-cursor-shadow)", children: [
|
|
615
|
+
/* @__PURE__ */ jsx5("path", { d: "M42.6817 41.1495L27.5103 6.79925C26.7269 5.02557 24.2082 5.02558 23.3927 6.79925L7.59814 41.1495C6.75833 42.9759 8.52712 44.8902 10.4125 44.1954L24.3757 39.0496C24.8829 38.8627 25.4385 38.8627 25.9422 39.0496L39.8121 44.1954C41.6849 44.8902 43.4884 42.9759 42.6817 41.1495Z", fill: "black" }),
|
|
616
|
+
/* @__PURE__ */ jsx5("path", { d: "M43.7146 40.6933L28.5431 6.34306C27.3556 3.65428 23.5772 3.69516 22.3668 6.32755L6.57226 40.6778C5.3134 43.4156 7.97238 46.298 10.803 45.2549L24.7662 40.109C25.0221 40.0147 25.2999 40.0156 25.5494 40.1082L39.4193 45.254C42.2261 46.2953 44.9254 43.4347 43.7146 40.6933Z", stroke: "white", strokeWidth: "2.25825" })
|
|
617
|
+
] }),
|
|
618
|
+
/* @__PURE__ */ jsx5("defs", { children: /* @__PURE__ */ jsxs4("filter", { id: "walros-cursor-shadow", x: "0.602397", y: "0.952444", width: "49.0584", height: "52.428", filterUnits: "userSpaceOnUse", colorInterpolationFilters: "sRGB", children: [
|
|
619
|
+
/* @__PURE__ */ jsx5("feFlood", { floodOpacity: "0", result: "BackgroundImageFix" }),
|
|
620
|
+
/* @__PURE__ */ jsx5("feColorMatrix", { in: "SourceAlpha", type: "matrix", values: "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0", result: "hardAlpha" }),
|
|
621
|
+
/* @__PURE__ */ jsx5("feOffset", { dy: "2.25825" }),
|
|
622
|
+
/* @__PURE__ */ jsx5("feGaussianBlur", { stdDeviation: "2.25825" }),
|
|
623
|
+
/* @__PURE__ */ jsx5("feComposite", { in2: "hardAlpha", operator: "out" }),
|
|
624
|
+
/* @__PURE__ */ jsx5("feColorMatrix", { type: "matrix", values: "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.08 0" }),
|
|
625
|
+
/* @__PURE__ */ jsx5("feBlend", { mode: "normal", in2: "BackgroundImageFix", result: "effect1_dropShadow" }),
|
|
626
|
+
/* @__PURE__ */ jsx5("feBlend", { mode: "normal", in: "SourceGraphic", in2: "effect1_dropShadow", result: "shape" })
|
|
627
|
+
] }) })
|
|
628
|
+
] }) }) })
|
|
629
|
+
] });
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
// src/components/WalrosLogo.tsx
|
|
633
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
634
|
+
function WalrosLogo({
|
|
635
|
+
alt = "WalrOS",
|
|
636
|
+
draggable = false,
|
|
637
|
+
...props
|
|
638
|
+
}) {
|
|
639
|
+
return /* @__PURE__ */ jsx6(
|
|
640
|
+
"img",
|
|
641
|
+
{
|
|
642
|
+
src: walrosLogoChromeUrl,
|
|
643
|
+
alt,
|
|
644
|
+
draggable,
|
|
645
|
+
...props
|
|
646
|
+
}
|
|
647
|
+
);
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
// src/components/WalrosWordmark.tsx
|
|
651
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
652
|
+
function WalrosWordmark({
|
|
653
|
+
variant = "light",
|
|
654
|
+
alt = "WalrOS",
|
|
655
|
+
draggable = false,
|
|
656
|
+
...props
|
|
657
|
+
}) {
|
|
658
|
+
const src = variant === "dark" ? walrosWordmarkDarkUrl : walrosWordmarkLightUrl;
|
|
659
|
+
return /* @__PURE__ */ jsx7(
|
|
660
|
+
"img",
|
|
661
|
+
{
|
|
662
|
+
src,
|
|
663
|
+
alt,
|
|
664
|
+
draggable,
|
|
665
|
+
...props
|
|
666
|
+
}
|
|
667
|
+
);
|
|
668
|
+
}
|
|
669
|
+
|
|
522
670
|
// src/hooks/useWalrosTheme.ts
|
|
523
671
|
import {
|
|
524
672
|
useCallback,
|
|
525
|
-
useEffect as
|
|
526
|
-
useRef as
|
|
527
|
-
useState as
|
|
673
|
+
useEffect as useEffect4,
|
|
674
|
+
useRef as useRef4,
|
|
675
|
+
useState as useState5
|
|
528
676
|
} from "react";
|
|
529
677
|
var GLITCH_BASE_CLASS = "walros-theme-glitch-page";
|
|
530
678
|
var GLITCH_BODY_CLASS = "walros-theme-glitch-page--body";
|
|
@@ -571,25 +719,25 @@ function useWalrosTheme({
|
|
|
571
719
|
lockScroll,
|
|
572
720
|
onAfterUnlock
|
|
573
721
|
} = {}) {
|
|
574
|
-
const [theme, setThemeState] =
|
|
722
|
+
const [theme, setThemeState] = useState5(
|
|
575
723
|
() => readInitialTheme(storageKey, defaultTheme, useSystemPreference)
|
|
576
724
|
);
|
|
577
|
-
const [mounted, setMounted] =
|
|
578
|
-
const [glitching, setGlitching] =
|
|
579
|
-
const themeRef =
|
|
580
|
-
const glitchingRef =
|
|
581
|
-
const swapTimerRef =
|
|
582
|
-
const cleanupTimerRef =
|
|
583
|
-
const applyThemeRef =
|
|
584
|
-
const modeRef =
|
|
585
|
-
const shakeTargetsRef =
|
|
586
|
-
const lockScrollRef =
|
|
587
|
-
const onAfterUnlockRef =
|
|
588
|
-
const activeTargetsRef =
|
|
589
|
-
const viewportLockRef =
|
|
590
|
-
const soundRef =
|
|
591
|
-
const soundUrlRef =
|
|
592
|
-
const soundVolumeRef =
|
|
725
|
+
const [mounted, setMounted] = useState5(false);
|
|
726
|
+
const [glitching, setGlitching] = useState5(false);
|
|
727
|
+
const themeRef = useRef4(theme);
|
|
728
|
+
const glitchingRef = useRef4(false);
|
|
729
|
+
const swapTimerRef = useRef4(null);
|
|
730
|
+
const cleanupTimerRef = useRef4(null);
|
|
731
|
+
const applyThemeRef = useRef4(applyTheme);
|
|
732
|
+
const modeRef = useRef4(mode);
|
|
733
|
+
const shakeTargetsRef = useRef4(shakeTargets);
|
|
734
|
+
const lockScrollRef = useRef4(lockScroll);
|
|
735
|
+
const onAfterUnlockRef = useRef4(onAfterUnlock);
|
|
736
|
+
const activeTargetsRef = useRef4([]);
|
|
737
|
+
const viewportLockRef = useRef4(null);
|
|
738
|
+
const soundRef = useRef4(null);
|
|
739
|
+
const soundUrlRef = useRef4(soundUrl);
|
|
740
|
+
const soundVolumeRef = useRef4(soundVolume);
|
|
593
741
|
themeRef.current = theme;
|
|
594
742
|
applyThemeRef.current = applyTheme;
|
|
595
743
|
modeRef.current = mode;
|
|
@@ -626,7 +774,7 @@ function useWalrosTheme({
|
|
|
626
774
|
},
|
|
627
775
|
[storageKey]
|
|
628
776
|
);
|
|
629
|
-
|
|
777
|
+
useEffect4(() => {
|
|
630
778
|
const initialTheme = readInitialTheme(
|
|
631
779
|
storageKey,
|
|
632
780
|
defaultTheme,
|
|
@@ -708,6 +856,10 @@ function useWalrosTheme({
|
|
|
708
856
|
activeTargetsRef.current = [];
|
|
709
857
|
}, []);
|
|
710
858
|
const finishGlitch = useCallback(() => {
|
|
859
|
+
if (soundRef.current) {
|
|
860
|
+
soundRef.current.pause();
|
|
861
|
+
soundRef.current.currentTime = 0;
|
|
862
|
+
}
|
|
711
863
|
removeShakeClasses();
|
|
712
864
|
unlockViewport(true);
|
|
713
865
|
glitchingRef.current = false;
|
|
@@ -757,12 +909,13 @@ function useWalrosTheme({
|
|
|
757
909
|
finishGlitch();
|
|
758
910
|
}, effectiveDuration);
|
|
759
911
|
}, [finishGlitch, lockViewport, persistTheme, playThemeSound, swapDelay, totalDuration]);
|
|
760
|
-
|
|
912
|
+
useEffect4(() => {
|
|
761
913
|
return () => {
|
|
762
914
|
clearTimers();
|
|
763
915
|
removeShakeClasses();
|
|
764
916
|
unlockViewport(false);
|
|
765
917
|
soundRef.current?.pause();
|
|
918
|
+
if (soundRef.current) soundRef.current.currentTime = 0;
|
|
766
919
|
soundRef.current = null;
|
|
767
920
|
};
|
|
768
921
|
}, [clearTimers, removeShakeClasses, unlockViewport]);
|
|
@@ -776,9 +929,12 @@ function useWalrosTheme({
|
|
|
776
929
|
};
|
|
777
930
|
}
|
|
778
931
|
export {
|
|
932
|
+
DirectionalCursor,
|
|
933
|
+
Walros3DPortalTransition,
|
|
779
934
|
WalrosLogo,
|
|
780
935
|
WalrosPortalTransition,
|
|
781
936
|
WalrosThemeGlitch,
|
|
937
|
+
WalrosThemeTransition,
|
|
782
938
|
WalrosWordmark,
|
|
783
939
|
useWalrosTheme,
|
|
784
940
|
walrosLogoChromeUrl,
|