@walrosproject/ui 0.4.0 → 0.4.1

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 CHANGED
@@ -8,7 +8,7 @@ npm install @walrosproject/ui
8
8
 
9
9
  ## Cambio de tema completo
10
10
 
11
- `WalrosThemeTransition` une la entrada negra con la silueta de la morsa, el glitch visual y el sonido de walros.org. El portal acelera durante **900 ms** con la curva `power2.in`; el glitch dura **1.500 ms**; el tema cambia a los **610 ms** y el audio se detiene al concluir los **1.500 ms**. La imagen del logo se precarga y la pantalla permanece negra mientras termina de cargar, como en la portada.
11
+ `WalrosThemeTransition` muestra exclusivamente el glitch visual de walros.org: bandas, destellos y sacudida de la página, sin silueta ni logo. El glitch dura **1.500 ms**; el tema cambia a los **610 ms** y el audio se detiene al concluir los **1.500 ms**. La entrada de la página es un componente independiente.
12
12
 
13
13
  ```tsx
14
14
  import {
@@ -48,13 +48,13 @@ const theme = useWalrosTheme({
48
48
 
49
49
  ## Portal de entrada
50
50
 
51
- El componente completo muestra el logo cromado bajo la máscara negra y calcula el punto de partida con sus proporciones visibles:
51
+ `WalrosPortalTransition` muestra la morsa cromada **debajo** de la máscara negra y la acerca al centro mientras se abre el portal. Dura **900 ms** y no espera a que se descargue la imagen para iniciar; el logo desaparece antes de que se revele la página.
52
52
 
53
53
  ```tsx
54
54
  <WalrosPortalTransition storageMode="always" />
55
55
  ```
56
56
 
57
- `storageMode` acepta `always`, `session` y `once`. La duración predeterminada es **900 ms**. Para usar el modelo 3D real de walros.org como fondo, renderízalo en tu escena y pasa sus límites proyectados a `Walros3DPortalTransition`:
57
+ `storageMode` acepta `always`, `session` y `once`. Para usar el modelo 3D real de walros.org como fondo, renderízalo en tu escena y pasa sus límites proyectados a `Walros3DPortalTransition`:
58
58
 
59
59
  ```tsx
60
60
  <Walros3DPortalTransition
package/dist/index.d.ts CHANGED
@@ -1,18 +1,6 @@
1
1
  import * as react from 'react';
2
2
  import { ImgHTMLAttributes, CSSProperties, RefObject } from 'react';
3
3
 
4
- type WalrosPortalTransitionProps = {
5
- duration?: number;
6
- onComplete?: () => void;
7
- backgroundColor?: string;
8
- enabled?: boolean;
9
- storageMode?: "always" | "session" | "once";
10
- storageKey?: string;
11
- zIndex?: number;
12
- };
13
- /** Exact walros.org black portal, including its chrome logo and 900 ms curve. */
14
- declare function WalrosPortalTransition({ duration, onComplete, backgroundColor, enabled, storageMode, storageKey, zIndex, }: WalrosPortalTransitionProps): react.ReactPortal | null;
15
-
16
4
  type PortalOrigin = {
17
5
  centerX: number;
18
6
  centerY: number;
@@ -26,24 +14,38 @@ type Walros3DPortalTransitionProps = {
26
14
  backgroundColor?: string;
27
15
  zIndex?: number;
28
16
  lockScroll?: boolean;
17
+ /** An optional image that follows the portal exactly and fades before reveal. */
18
+ logoUrl?: string | false;
19
+ };
20
+ declare function Walros3DPortalTransition({ origin, onComplete, duration, backgroundColor, zIndex, lockScroll, logoUrl, }: Walros3DPortalTransitionProps): react.JSX.Element | null;
21
+
22
+ type WalrosPortalTransitionProps = {
23
+ duration?: number;
24
+ onComplete?: () => void;
25
+ backgroundColor?: string;
26
+ enabled?: boolean;
27
+ storageMode?: "always" | "session" | "once";
28
+ storageKey?: string;
29
+ zIndex?: number;
30
+ /** Projected bounds of an existing 3D logo, as on walros.org. */
31
+ origin?: PortalOrigin;
32
+ /** Intro logo shown beneath the black mask; set false when using an existing 3D logo. */
33
+ logoUrl?: string | false;
29
34
  };
30
- declare function Walros3DPortalTransition({ origin, onComplete, duration, backgroundColor, zIndex, lockScroll, }: Walros3DPortalTransitionProps): react.JSX.Element | null;
35
+ /** 900 ms walros.org entrance, with the logo confined below its black mask. */
36
+ declare function WalrosPortalTransition({ duration, onComplete, backgroundColor, enabled, storageMode, storageKey, zIndex, origin, logoUrl, }: WalrosPortalTransitionProps): react.ReactPortal | null;
31
37
 
32
38
  type WalrosThemeTransitionProps = {
33
39
  /** Pass the `glitching` value returned by `useWalrosTheme`. */
34
40
  active: boolean;
35
- /** The walros.org portal takes 900 ms. */
41
+ /** @deprecated The theme change has no portal; retained for source compatibility. */
36
42
  portalDuration?: number;
37
- /** The same chrome logo used under the portal on walros.org. */
43
+ /** @deprecated The theme change has no logo; retained for source compatibility. */
38
44
  logoUrl?: string;
39
45
  zIndex?: number;
40
46
  };
41
- /**
42
- * A ready-to-use walros.org theme transition. The portal runs for 900 ms,
43
- * while the matching glitch and sound from useWalrosTheme run for 1,500 ms.
44
- * Mount once near the app root and pass `active={glitching}`.
45
- */
46
- declare function WalrosThemeTransition({ active, portalDuration, logoUrl, zIndex, }: WalrosThemeTransitionProps): react.ReactPortal | null;
47
+ /** The walros.org theme effect is a shake and glitch, without an intro logo. */
48
+ declare function WalrosThemeTransition({ active, zIndex, }: WalrosThemeTransitionProps): react.ReactPortal | null;
47
49
 
48
50
  declare function DirectionalCursor(): react.JSX.Element;
49
51
 
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // src/components/WalrosPortalTransition.tsx
2
- import { useState as useState4 } from "react";
3
- import { createPortal as createPortal2 } from "react-dom";
2
+ import { useState as useState3 } from "react";
3
+ import { createPortal } from "react-dom";
4
4
 
5
5
  // src/assets.ts
6
6
  var walrosPortalSilhouetteUrl = new URL(
@@ -24,10 +24,6 @@ var walrosThemeGlitchSoundUrl = new URL(
24
24
  import.meta.url
25
25
  ).href;
26
26
 
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";
30
-
31
27
  // src/components/Walros3DPortalTransition.tsx
32
28
  import { useEffect, useId, useLayoutEffect, useRef, useState } from "react";
33
29
  import gsap from "gsap";
@@ -54,7 +50,8 @@ function Walros3DPortalTransition({
54
50
  duration = 900,
55
51
  backgroundColor = "#000",
56
52
  zIndex = 10001,
57
- lockScroll = true
53
+ lockScroll = true,
54
+ logoUrl = false
58
55
  }) {
59
56
  const [visible, setVisible] = useState(true);
60
57
  const [viewport, setViewport] = useState(() => ({
@@ -63,6 +60,7 @@ function Walros3DPortalTransition({
63
60
  }));
64
61
  const overlay = useRef(null);
65
62
  const portal = useRef(null);
63
+ const logo = useRef(null);
66
64
  const completeRef = useRef(onComplete);
67
65
  completeRef.current = onComplete;
68
66
  const maskId = `walros-3d-portal-${useId().replace(/:/g, "_")}`;
@@ -82,10 +80,10 @@ function Walros3DPortalTransition({
82
80
  const initialScale = Math.min(origin.width / visibleWidth, origin.height / visibleHeight) * 0.985;
83
81
  const initialX = origin.centerX - (visualCenterX - FOCUS_X) * initialScale;
84
82
  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
83
  const diagonal = Math.hypot(viewport.width, viewport.height) / 2;
88
84
  const finalScale = (diagonal + 80) / PORTAL_RADIUS * 1.15;
85
+ const targetX = viewport.width / 2 - (visualCenterX - FOCUS_X) * finalScale;
86
+ const targetY = viewport.height / 2 - (visualCenterY - FOCUS_Y) * finalScale;
89
87
  const total = duration / 1e3;
90
88
  gsap.set(portal.current, {
91
89
  x: initialX,
@@ -93,6 +91,15 @@ function Walros3DPortalTransition({
93
91
  scale: initialScale,
94
92
  svgOrigin: "0 0"
95
93
  });
94
+ if (logo.current) {
95
+ gsap.set(logo.current, {
96
+ x: initialX,
97
+ y: initialY,
98
+ scale: initialScale,
99
+ opacity: 1,
100
+ svgOrigin: "0 0"
101
+ });
102
+ }
96
103
  gsap.set(overlay.current, { opacity: 1 });
97
104
  const finish = () => {
98
105
  if (lockScroll) document.body.style.overflow = previousOverflow;
@@ -104,13 +111,21 @@ function Walros3DPortalTransition({
104
111
  if (reducedMotion) {
105
112
  timeline.to(overlay.current, { opacity: 0, duration: 0.15, ease: "power1.out" });
106
113
  } else {
107
- timeline.to(portal.current, {
114
+ timeline.to([portal.current, logo.current].filter(Boolean), {
108
115
  x: targetX,
109
116
  y: targetY,
110
117
  scale: finalScale,
111
118
  duration: total,
112
119
  ease: "power2.in"
113
- }).to(overlay.current, {
120
+ });
121
+ if (logo.current) {
122
+ timeline.to(logo.current, {
123
+ opacity: 0,
124
+ duration: total * 0.18,
125
+ ease: "power1.out"
126
+ }, total * 0.7);
127
+ }
128
+ timeline.to(overlay.current, {
114
129
  opacity: 0,
115
130
  duration: total * 0.1,
116
131
  ease: "power2.out"
@@ -143,14 +158,116 @@ function Walros3DPortalTransition({
143
158
  /* @__PURE__ */ jsx("rect", { width: viewport.width, height: viewport.height, fill: "white" }),
144
159
  /* @__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
160
  ] }) }),
161
+ logoUrl && /* @__PURE__ */ jsx("g", { ref: logo, children: /* @__PURE__ */ jsx("image", { href: logoUrl, x: -FOCUS_X, y: -FOCUS_Y, width: "1254", height: "1254" }) }),
146
162
  /* @__PURE__ */ jsx("rect", { width: viewport.width, height: viewport.height, fill: backgroundColor, mask: `url(#${maskId})` })
147
163
  ] })
148
164
  }
149
165
  );
150
166
  }
151
167
 
168
+ // src/components/useOverlayHost.ts
169
+ import { useLayoutEffect as useLayoutEffect2, useState as useState2 } from "react";
170
+ function useOverlayHost(zIndex) {
171
+ const [host] = useState2(
172
+ () => typeof document === "undefined" ? null : document.createElement("div")
173
+ );
174
+ useLayoutEffect2(() => {
175
+ if (!host) return;
176
+ host.dataset.walrosOverlayRoot = "";
177
+ host.style.position = "fixed";
178
+ host.style.inset = "0";
179
+ host.style.pointerEvents = "none";
180
+ document.documentElement.appendChild(host);
181
+ return () => host.remove();
182
+ }, [host]);
183
+ useLayoutEffect2(() => {
184
+ if (host) host.style.zIndex = String(zIndex);
185
+ }, [host, zIndex]);
186
+ return host;
187
+ }
188
+
189
+ // src/components/WalrosPortalTransition.tsx
190
+ import { jsx as jsx2 } from "react/jsx-runtime";
191
+ var IMAGE_SIZE = (width) => Math.min(150, Math.max(90, width * 0.11));
192
+ var IMAGE_WIDTH = 1254;
193
+ var VISIBLE_LEFT2 = 244;
194
+ var VISIBLE_RIGHT2 = 1010;
195
+ var VISIBLE_TOP2 = 115;
196
+ var VISIBLE_BOTTOM2 = 1128;
197
+ function defaultOrigin() {
198
+ if (typeof window === "undefined") return { centerX: 0, centerY: 0, width: 70, height: 90 };
199
+ const size = IMAGE_SIZE(window.innerWidth);
200
+ return {
201
+ centerX: window.innerWidth / 2,
202
+ centerY: window.innerHeight * 0.45 + ((VISIBLE_TOP2 + VISIBLE_BOTTOM2) / 2 - IMAGE_WIDTH / 2) / IMAGE_WIDTH * size,
203
+ width: (VISIBLE_RIGHT2 - VISIBLE_LEFT2) / IMAGE_WIDTH * size,
204
+ height: (VISIBLE_BOTTOM2 - VISIBLE_TOP2) / IMAGE_WIDTH * size
205
+ };
206
+ }
207
+ function getStorage(mode) {
208
+ if (typeof window === "undefined") return null;
209
+ try {
210
+ return mode === "session" ? window.sessionStorage : window.localStorage;
211
+ } catch {
212
+ return null;
213
+ }
214
+ }
215
+ function shouldRun(enabled, mode, key) {
216
+ if (!enabled) return false;
217
+ if (mode === "always") return true;
218
+ try {
219
+ return getStorage(mode)?.getItem(key) == null;
220
+ } catch {
221
+ return true;
222
+ }
223
+ }
224
+ function WalrosPortalTransition({
225
+ duration = 900,
226
+ onComplete,
227
+ backgroundColor = "#000",
228
+ enabled = true,
229
+ storageMode = "always",
230
+ storageKey = "walros-portal-seen",
231
+ zIndex = 1e4,
232
+ origin,
233
+ logoUrl = walrosLogoChromeUrl
234
+ }) {
235
+ const [run] = useState3(() => shouldRun(enabled, storageMode, storageKey));
236
+ const [complete, setComplete] = useState3(false);
237
+ const [initialOrigin] = useState3(() => origin ?? defaultOrigin());
238
+ const host = useOverlayHost(zIndex);
239
+ if (!host || !enabled || !run || complete) return null;
240
+ return createPortal(
241
+ /* @__PURE__ */ jsx2(
242
+ Walros3DPortalTransition,
243
+ {
244
+ origin: initialOrigin,
245
+ logoUrl,
246
+ duration,
247
+ backgroundColor,
248
+ zIndex: 1,
249
+ lockScroll: true,
250
+ onComplete: () => {
251
+ if (storageMode !== "always") {
252
+ try {
253
+ getStorage(storageMode)?.setItem(storageKey, "1");
254
+ } catch {
255
+ }
256
+ }
257
+ setComplete(true);
258
+ onComplete?.();
259
+ }
260
+ }
261
+ ),
262
+ host
263
+ );
264
+ }
265
+
266
+ // src/components/WalrosThemeTransition.tsx
267
+ import { createPortal as createPortal2 } from "react-dom";
268
+
152
269
  // src/components/WalrosThemeGlitch.tsx
153
- import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
270
+ import { Fragment, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
154
271
  var GLITCH_STYLES = `
155
272
  .walros-theme-glitch-root {
156
273
  position: fixed;
@@ -297,7 +414,7 @@ function WalrosThemeGlitch({
297
414
  style
298
415
  }) {
299
416
  return /* @__PURE__ */ jsxs2(Fragment, { children: [
300
- /* @__PURE__ */ jsx2("style", { children: GLITCH_STYLES }),
417
+ /* @__PURE__ */ jsx3("style", { children: GLITCH_STYLES }),
301
418
  active ? /* @__PURE__ */ jsxs2(
302
419
  "div",
303
420
  {
@@ -305,194 +422,33 @@ function WalrosThemeGlitch({
305
422
  style: { zIndex, ...style },
306
423
  "aria-hidden": "true",
307
424
  children: [
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" })
425
+ /* @__PURE__ */ jsx3("span", { className: "walros-theme-glitch-band" }),
426
+ /* @__PURE__ */ jsx3("span", { className: "walros-theme-glitch-band" }),
427
+ /* @__PURE__ */ jsx3("span", { className: "walros-theme-glitch-band" }),
428
+ /* @__PURE__ */ jsx3("span", { className: "walros-theme-glitch-band" })
312
429
  ]
313
430
  }
314
431
  ) : null
315
432
  ] });
316
433
  }
317
434
 
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
435
  // 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
- }
436
+ import { jsx as jsx4 } from "react/jsx-runtime";
414
437
  function WalrosThemeTransition({
415
438
  active,
416
- portalDuration = 900,
417
- logoUrl = walrosLogoChromeUrl,
418
439
  zIndex = 1e4
419
440
  }) {
420
441
  const host = useOverlayHost(zIndex);
421
- useEffect2(() => {
422
- if (typeof window === "undefined") return;
423
- const logo = new Image();
424
- logo.src = logoUrl;
425
- }, [logoUrl]);
426
442
  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
443
  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
- ),
444
+ /* @__PURE__ */ jsx4(WalrosThemeGlitch, { active, zIndex: 1 }),
489
445
  host
490
446
  );
491
447
  }
492
448
 
493
449
  // 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";
450
+ import { useEffect as useEffect2, useRef as useRef2 } from "react";
451
+ import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
496
452
  var DESKTOP_CURSOR_QUERY = "(min-width: 1024px) and (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference)";
497
453
  var CURSOR_STYLES = `
498
454
  .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; }
@@ -507,9 +463,9 @@ var CURSOR_STYLES = `
507
463
  }
508
464
  `;
509
465
  function DirectionalCursor() {
510
- const positionLayer = useRef3(null);
511
- const directionLayer = useRef3(null);
512
- useEffect3(() => {
466
+ const positionLayer = useRef2(null);
467
+ const directionLayer = useRef2(null);
468
+ useEffect2(() => {
513
469
  const position = positionLayer.current;
514
470
  const direction = directionLayer.current;
515
471
  if (!position || !direction) return;
@@ -608,14 +564,14 @@ function DirectionalCursor() {
608
564
  deactivate();
609
565
  };
610
566
  }, []);
611
- return /* @__PURE__ */ jsxs4(Fragment3, { children: [
567
+ return /* @__PURE__ */ jsxs3(Fragment2, { children: [
612
568
  /* @__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: [
569
+ /* @__PURE__ */ jsx5("div", { ref: positionLayer, className: "directional-cursor", "aria-hidden": "true", children: /* @__PURE__ */ jsx5("div", { ref: directionLayer, className: "directional-cursor-shape", children: /* @__PURE__ */ jsxs3("svg", { width: "50", height: "54", viewBox: "0 0 50 54", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
570
+ /* @__PURE__ */ jsxs3("g", { filter: "url(#walros-cursor-shadow)", children: [
615
571
  /* @__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
572
  /* @__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
573
  ] }),
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: [
574
+ /* @__PURE__ */ jsx5("defs", { children: /* @__PURE__ */ jsxs3("filter", { id: "walros-cursor-shadow", x: "0.602397", y: "0.952444", width: "49.0584", height: "52.428", filterUnits: "userSpaceOnUse", colorInterpolationFilters: "sRGB", children: [
619
575
  /* @__PURE__ */ jsx5("feFlood", { floodOpacity: "0", result: "BackgroundImageFix" }),
620
576
  /* @__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
577
  /* @__PURE__ */ jsx5("feOffset", { dy: "2.25825" }),
@@ -670,9 +626,9 @@ function WalrosWordmark({
670
626
  // src/hooks/useWalrosTheme.ts
671
627
  import {
672
628
  useCallback,
673
- useEffect as useEffect4,
674
- useRef as useRef4,
675
- useState as useState5
629
+ useEffect as useEffect3,
630
+ useRef as useRef3,
631
+ useState as useState4
676
632
  } from "react";
677
633
  var GLITCH_BASE_CLASS = "walros-theme-glitch-page";
678
634
  var GLITCH_BODY_CLASS = "walros-theme-glitch-page--body";
@@ -719,25 +675,25 @@ function useWalrosTheme({
719
675
  lockScroll,
720
676
  onAfterUnlock
721
677
  } = {}) {
722
- const [theme, setThemeState] = useState5(
678
+ const [theme, setThemeState] = useState4(
723
679
  () => readInitialTheme(storageKey, defaultTheme, useSystemPreference)
724
680
  );
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);
681
+ const [mounted, setMounted] = useState4(false);
682
+ const [glitching, setGlitching] = useState4(false);
683
+ const themeRef = useRef3(theme);
684
+ const glitchingRef = useRef3(false);
685
+ const swapTimerRef = useRef3(null);
686
+ const cleanupTimerRef = useRef3(null);
687
+ const applyThemeRef = useRef3(applyTheme);
688
+ const modeRef = useRef3(mode);
689
+ const shakeTargetsRef = useRef3(shakeTargets);
690
+ const lockScrollRef = useRef3(lockScroll);
691
+ const onAfterUnlockRef = useRef3(onAfterUnlock);
692
+ const activeTargetsRef = useRef3([]);
693
+ const viewportLockRef = useRef3(null);
694
+ const soundRef = useRef3(null);
695
+ const soundUrlRef = useRef3(soundUrl);
696
+ const soundVolumeRef = useRef3(soundVolume);
741
697
  themeRef.current = theme;
742
698
  applyThemeRef.current = applyTheme;
743
699
  modeRef.current = mode;
@@ -774,7 +730,7 @@ function useWalrosTheme({
774
730
  },
775
731
  [storageKey]
776
732
  );
777
- useEffect4(() => {
733
+ useEffect3(() => {
778
734
  const initialTheme = readInitialTheme(
779
735
  storageKey,
780
736
  defaultTheme,
@@ -909,7 +865,7 @@ function useWalrosTheme({
909
865
  finishGlitch();
910
866
  }, effectiveDuration);
911
867
  }, [finishGlitch, lockViewport, persistTheme, playThemeSound, swapDelay, totalDuration]);
912
- useEffect4(() => {
868
+ useEffect3(() => {
913
869
  return () => {
914
870
  clearTimers();
915
871
  removeShakeClasses();
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/WalrosPortalTransition.tsx","../src/assets.ts","../src/components/WalrosThemeTransition.tsx","../src/components/Walros3DPortalTransition.tsx","../src/portalSilhouette.ts","../src/components/WalrosThemeGlitch.tsx","../src/components/useOverlayHost.ts","../src/components/DirectionalCursor.tsx","../src/components/WalrosLogo.tsx","../src/components/WalrosWordmark.tsx","../src/hooks/useWalrosTheme.ts"],"sourcesContent":["import { useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { walrosLogoChromeUrl } from \"../assets\";\nimport { WalrosPortalScene } from \"./WalrosThemeTransition\";\nimport { useOverlayHost } from \"./useOverlayHost\";\n\nexport type WalrosPortalTransitionProps = {\n duration?: number;\n onComplete?: () => void;\n backgroundColor?: string;\n enabled?: boolean;\n storageMode?: \"always\" | \"session\" | \"once\";\n storageKey?: string;\n zIndex?: number;\n};\n\nfunction getStorage(mode: \"session\" | \"once\"): Storage | null {\n if (typeof window === \"undefined\") return null;\n try {\n return mode === \"session\" ? window.sessionStorage : window.localStorage;\n } catch {\n return null;\n }\n}\n\nfunction shouldRun(enabled: boolean, mode: \"always\" | \"session\" | \"once\", key: string) {\n if (!enabled) return false;\n if (mode === \"always\") return true;\n try {\n return getStorage(mode)?.getItem(key) == null;\n } catch {\n return true;\n }\n}\n\n/** Exact walros.org black portal, including its chrome logo and 900 ms curve. */\nexport function WalrosPortalTransition({\n duration = 900,\n onComplete,\n backgroundColor = \"#000\",\n enabled = true,\n storageMode = \"always\",\n storageKey = \"walros-portal-seen\",\n zIndex = 10000,\n}: WalrosPortalTransitionProps) {\n const [run] = useState(() => shouldRun(enabled, storageMode, storageKey));\n const [complete, setComplete] = useState(false);\n const host = useOverlayHost(zIndex);\n\n if (!host || !enabled || !run || complete) return null;\n\n return createPortal(\n <WalrosPortalScene\n logoUrl={walrosLogoChromeUrl}\n portalDuration={duration}\n backgroundColor={backgroundColor}\n zIndex={zIndex}\n lockScroll\n onComplete={() => {\n if (storageMode !== \"always\") {\n try { getStorage(storageMode)?.setItem(storageKey, \"1\"); } catch { /* Storage is optional. */ }\n }\n setComplete(true);\n onComplete?.();\n }}\n />,\n host,\n );\n}\n\nexport default WalrosPortalTransition;\n","export const walrosPortalSilhouetteUrl = new URL(\n \"./assets/walros-portal-silhouette.svg\",\n import.meta.url,\n).href;\n\nexport const walrosLogoChromeUrl = new URL(\n \"./assets/walros-logo-chrome.png\",\n import.meta.url,\n).href;\n\nexport const walrosWordmarkLightUrl = new URL(\n \"./assets/walros-wordmark-light.png\",\n import.meta.url,\n).href;\n\nexport const walrosWordmarkDarkUrl = new URL(\n \"./assets/walros-wordmark-dark.png\",\n import.meta.url,\n).href;\n\nexport const walrosThemeGlitchSoundUrl = new URL(\n \"./assets/walros-theme-glitch.mp3\",\n import.meta.url,\n).href;\n","import { useEffect, useLayoutEffect, useRef, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { walrosLogoChromeUrl } from \"../assets\";\nimport { Walros3DPortalTransition, type PortalOrigin } from \"./Walros3DPortalTransition\";\nimport { WalrosThemeGlitch } from \"./WalrosThemeGlitch\";\nimport { useOverlayHost } from \"./useOverlayHost\";\n\nexport type WalrosThemeTransitionProps = {\n /** Pass the `glitching` value returned by `useWalrosTheme`. */\n active: boolean;\n /** The walros.org portal takes 900 ms. */\n portalDuration?: number;\n /** The same chrome logo used under the portal on walros.org. */\n logoUrl?: string;\n zIndex?: number;\n};\n\nconst IMAGE_SIZE = \"clamp(90px, 11vw, 150px)\";\nconst IMAGE_WIDTH = 1254;\nconst VISIBLE_LEFT = 244;\nconst VISIBLE_RIGHT = 1010;\nconst VISIBLE_TOP = 115;\nconst VISIBLE_BOTTOM = 1128;\n\nexport type WalrosPortalSceneProps = {\n logoUrl: string;\n portalDuration: number;\n zIndex: number;\n backgroundColor?: string;\n onComplete?: () => void;\n lockScroll?: boolean;\n};\n\nexport function WalrosPortalScene({\n logoUrl,\n portalDuration,\n zIndex,\n backgroundColor = \"#000\",\n onComplete,\n lockScroll = false,\n}: WalrosPortalSceneProps) {\n const logoRef = useRef<HTMLImageElement>(null);\n const [origin, setOrigin] = useState<PortalOrigin | null>(null);\n const [portalComplete, setPortalComplete] = useState(false);\n\n const measureLogo = () => {\n const image = logoRef.current;\n if (!image) return;\n const rect = image.getBoundingClientRect();\n const scale = rect.width / IMAGE_WIDTH;\n setOrigin({\n centerX: rect.left + ((VISIBLE_LEFT + VISIBLE_RIGHT) / 2) * scale,\n centerY: rect.top + ((VISIBLE_TOP + VISIBLE_BOTTOM) / 2) * scale,\n width: (VISIBLE_RIGHT - VISIBLE_LEFT) * scale,\n height: (VISIBLE_BOTTOM - VISIBLE_TOP) * scale,\n });\n };\n\n useLayoutEffect(() => {\n const image = logoRef.current;\n if (image?.complete) measureLogo();\n }, []);\n\n return (\n <>\n {!portalComplete && (\n <img\n ref={logoRef}\n src={logoUrl}\n onLoad={measureLogo}\n onError={measureLogo}\n alt=\"\"\n aria-hidden=\"true\"\n style={{\n position: \"fixed\",\n left: \"50%\",\n top: \"45%\",\n width: IMAGE_SIZE,\n height: IMAGE_SIZE,\n transform: \"translate(-50%, -50%)\",\n objectFit: \"contain\",\n zIndex,\n pointerEvents: \"none\",\n }}\n />\n )}\n {!portalComplete && !origin && (\n <div style={{ position: \"fixed\", inset: 0, zIndex: zIndex + 1, background: backgroundColor, pointerEvents: \"none\" }} aria-hidden=\"true\" />\n )}\n {!portalComplete && origin && (\n <Walros3DPortalTransition\n origin={origin}\n duration={portalDuration}\n zIndex={zIndex + 1}\n backgroundColor={backgroundColor}\n lockScroll={lockScroll}\n onComplete={() => { setPortalComplete(true); onComplete?.(); }}\n />\n )}\n </>\n );\n}\n\n/**\n * A ready-to-use walros.org theme transition. The portal runs for 900 ms,\n * while the matching glitch and sound from useWalrosTheme run for 1,500 ms.\n * Mount once near the app root and pass `active={glitching}`.\n */\nexport function WalrosThemeTransition({\n active,\n portalDuration = 900,\n logoUrl = walrosLogoChromeUrl,\n zIndex = 10000,\n}: WalrosThemeTransitionProps) {\n const host = useOverlayHost(zIndex);\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n const logo = new Image();\n logo.src = logoUrl;\n }, [logoUrl]);\n\n if (!host) return null;\n\n return createPortal(\n <>\n {active && <WalrosPortalScene logoUrl={logoUrl} portalDuration={portalDuration} zIndex={zIndex} />}\n <WalrosThemeGlitch active={active} zIndex={zIndex + 2} />\n </>,\n host,\n );\n}\n","import { useEffect, useId, useLayoutEffect, useRef, useState } from \"react\";\nimport gsap from \"gsap\";\nimport { walrosPortalPaths } from \"../portalSilhouette\";\n\r\nexport type PortalOrigin = {\r\n centerX: number;\r\n centerY: number;\r\n width: number;\r\n height: number;\r\n};\r\n\r\nexport type Walros3DPortalTransitionProps = {\n origin: PortalOrigin;\n onComplete?: () => void;\n duration?: number;\n backgroundColor?: string;\n zIndex?: number;\n lockScroll?: boolean;\n};\n\r\nconst FOCUS_X = 626;\r\nconst FOCUS_Y = 333;\r\nconst VISIBLE_LEFT = 244;\r\nconst VISIBLE_RIGHT = 1010;\r\nconst VISIBLE_TOP = 115;\r\nconst VISIBLE_BOTTOM = 1128;\r\nconst PORTAL_RADIUS = 190;\r\n\r\nexport function Walros3DPortalTransition({\n origin,\n onComplete,\n duration = 900,\n backgroundColor = \"#000\",\n zIndex = 10001,\n lockScroll = true,\n}: Walros3DPortalTransitionProps) {\n const [visible, setVisible] = useState(true);\n const [viewport, setViewport] = useState(() => ({\n width: typeof window === \"undefined\" ? 0 : window.innerWidth,\n height: typeof window === \"undefined\" ? 0 : window.innerHeight,\n }));\n const overlay = useRef<HTMLDivElement>(null);\n const portal = useRef<SVGGElement>(null);\n const completeRef = useRef(onComplete);\n completeRef.current = onComplete;\n const maskId = `walros-3d-portal-${useId().replace(/:/g, \"_\")}`;\n\r\n useEffect(() => {\r\n const updateViewport = () => setViewport({ width: window.innerWidth, height: window.innerHeight });\r\n window.addEventListener(\"resize\", updateViewport);\r\n return () => window.removeEventListener(\"resize\", updateViewport);\r\n }, []);\r\n\r\n useLayoutEffect(() => {\n if (!visible || viewport.width <= 0 || viewport.height <= 0 || !overlay.current || !portal.current) return;\n const previousOverflow = document.body.style.overflow;\n if (lockScroll) document.body.style.overflow = \"hidden\";\n\r\n const visibleWidth = VISIBLE_RIGHT - VISIBLE_LEFT;\r\n const visibleHeight = VISIBLE_BOTTOM - VISIBLE_TOP;\r\n const visualCenterX = (VISIBLE_LEFT + VISIBLE_RIGHT) / 2;\r\n const visualCenterY = (VISIBLE_TOP + VISIBLE_BOTTOM) / 2;\r\n // Let the black mask overlap the projected GLB by roughly one pixel. This\r\n // removes the pale halo without visibly cropping the chrome silhouette.\r\n const initialScale = Math.min(origin.width / visibleWidth, origin.height / visibleHeight) * .985;\r\n const initialX = origin.centerX - (visualCenterX - FOCUS_X) * initialScale;\r\n const initialY = origin.centerY - (visualCenterY - FOCUS_Y) * initialScale;\r\n const targetX = viewport.width / 2 - (visualCenterX - FOCUS_X) * initialScale;\r\n const targetY = viewport.height / 2 - (visualCenterY - FOCUS_Y) * initialScale;\r\n const diagonal = Math.hypot(viewport.width, viewport.height) / 2;\r\n const finalScale = ((diagonal + 80) / PORTAL_RADIUS) * 1.15;\r\n const total = duration / 1000;\r\n\r\n gsap.set(portal.current, {\r\n x: initialX,\r\n y: initialY,\r\n scale: initialScale,\r\n svgOrigin: \"0 0\",\r\n });\r\n gsap.set(overlay.current, { opacity: 1 });\r\n\r\n const finish = () => {\r\n if (lockScroll) document.body.style.overflow = previousOverflow;\n setVisible(false);\n completeRef.current?.();\n };\r\n const reducedMotion = window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\r\n const timeline = gsap.timeline({ onComplete: finish });\r\n if (reducedMotion) {\r\n timeline.to(overlay.current, { opacity: 0, duration: 0.15, ease: \"power1.out\" });\r\n } else {\r\n timeline\r\n .to(portal.current, {\r\n x: targetX,\r\n y: targetY,\r\n scale: finalScale,\r\n duration: total,\r\n ease: \"power2.in\",\r\n })\r\n .to(overlay.current, {\r\n opacity: 0,\r\n duration: total * 0.1,\r\n ease: \"power2.out\",\r\n }, total * 0.9);\r\n }\r\n\r\n return () => {\r\n timeline.kill();\r\n if (lockScroll) document.body.style.overflow = previousOverflow;\n };\n }, [duration, lockScroll, origin, viewport, visible]);\n\n if (!visible) return null;\n\r\n return (\r\n <div\r\n ref={overlay}\r\n className=\"walros-3d-portal\"\n style={{\n position: \"fixed\",\n inset: 0,\n width: \"100vw\",\n height: \"100dvh\",\n overflow: \"hidden\",\n pointerEvents: \"none\",\n zIndex,\n backgroundColor: viewport.width > 0 && viewport.height > 0 ? \"transparent\" : backgroundColor,\n }}\n aria-hidden=\"true\"\r\n >\r\n <svg width=\"100%\" height=\"100%\" viewBox={`0 0 ${viewport.width} ${viewport.height}`} preserveAspectRatio=\"none\" style={{ display: \"block\" }}>\n <defs>\r\n <mask id={maskId} maskUnits=\"userSpaceOnUse\" x=\"0\" y=\"0\" width={viewport.width} height={viewport.height}>\r\n <rect width={viewport.width} height={viewport.height} fill=\"white\" />\r\n <g ref={portal}>\r\n <g transform={`translate(${-FOCUS_X} ${-FOCUS_Y})`} fill=\"black\">\r\n {walrosPortalPaths.map((path, index) => <path d={path} key={index} />)}\n </g>\r\n </g>\r\n </mask>\r\n </defs>\r\n <rect width={viewport.width} height={viewport.height} fill={backgroundColor} mask={`url(#${maskId})`} />\n </svg>\r\n </div>\r\n );\r\n}\r\n","/* Exact silhouette used by the walros.org portal mask. */\r\nexport const walrosPortalPaths = [\r\n \"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\",\r\n \"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\",\r\n \"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\",\r\n] as const;\r\n","import type { CSSProperties } from \"react\";\n\nexport type WalrosThemeGlitchProps = {\n active: boolean;\n zIndex?: number;\n className?: string;\n style?: CSSProperties;\n};\n\nconst GLITCH_STYLES = `\n.walros-theme-glitch-root {\n position: fixed;\n inset: 0;\n z-index: 9998;\n pointer-events: none;\n overflow: hidden;\n visibility: hidden;\n}\n.walros-theme-glitch-root.is-active {\n visibility: visible;\n}\n.walros-theme-glitch-root::before,\n.walros-theme-glitch-root::after {\n content: \"\";\n position: absolute;\n inset: 0;\n}\n.walros-theme-glitch-root::before {\n background: rgba(0, 0, 0, .82);\n mix-blend-mode: normal;\n animation: walros-glitch-flash 1500ms steps(1, end) both;\n}\n.walros-theme-glitch-root::after {\n background: repeating-linear-gradient(0deg, transparent 0 3px, rgba(255,255,255,.09) 3px 4px);\n animation: walros-glitch-scan 90ms steps(2, end) 16 both;\n}\n.walros-theme-glitch-band {\n position: absolute;\n left: -12%;\n width: 124%;\n opacity: 0;\n}\n.walros-theme-glitch-band:nth-child(1) { top: 12%; height: 4%; background: #eaf6ff; animation: walros-glitch-band-a 1500ms steps(1, end) both; }\n.walros-theme-glitch-band:nth-child(2) { top: 36%; height: 11%; background: #020407; animation: walros-glitch-band-b 1500ms steps(1, end) both; }\n.walros-theme-glitch-band:nth-child(3) { top: 62%; height: 2%; background: #7faddb; animation: walros-glitch-band-c 1500ms steps(1, end) both; }\n.walros-theme-glitch-band:nth-child(4) { top: 79%; height: 8%; background: #f4f6f5; animation: walros-glitch-band-d 1500ms steps(1, end) both; }\n\n@keyframes walros-glitch-scan {\n 0% { transform: translateY(-2px); opacity: .25; }\n 50% { transform: translateY(2px); opacity: .08; }\n 100% { transform: translateY(0); opacity: .2; }\n}\n@keyframes walros-glitch-flash {\n 0%, 17%, 22%, 34%, 39%, 54%, 59%, 73%, 78%, 100% { opacity: 0; }\n 18%, 21% { opacity: .18; }\n 35%, 38% { opacity: .48; }\n 55%, 58% { opacity: .82; }\n 74%, 77% { opacity: .22; }\n}\n@keyframes walros-glitch-band-a {\n 0%, 8%, 18%, 42%, 51%, 73%, 82%, 100% { opacity: 0; transform: translateX(0); }\n 9%, 17% { opacity: .55; transform: translateX(-7%); }\n 43%, 50% { opacity: .82; transform: translateX(10%); }\n 74%, 81% { opacity: .32; transform: translateX(-4%); }\n}\n@keyframes walros-glitch-band-b {\n 0%, 20%, 27%, 46%, 55%, 64%, 71%, 100% { opacity: 0; transform: translateX(0); }\n 21%, 26% { opacity: .72; transform: translateX(9%); }\n 47%, 54% { opacity: .9; transform: translateX(-6%); }\n 65%, 70% { opacity: .5; transform: translateX(4%); }\n}\n@keyframes walros-glitch-band-c {\n 0%, 13%, 23%, 39%, 48%, 67%, 76%, 100% { opacity: 0; transform: translateX(0); }\n 14%, 22% { opacity: .9; transform: translateX(5%); }\n 40%, 47% { opacity: .65; transform: translateX(-11%); }\n 68%, 75% { opacity: .75; transform: translateX(8%); }\n}\n@keyframes walros-glitch-band-d {\n 0%, 29%, 38%, 57%, 65%, 85%, 93%, 100% { opacity: 0; transform: translateX(0); }\n 30%, 37% { opacity: .42; transform: translateX(-8%); }\n 58%, 64% { opacity: .7; transform: translateX(7%); }\n 86%, 92% { opacity: .25; transform: translateX(-3%); }\n}\n\n.walros-theme-glitch-lock {\n overscroll-behavior: none;\n}\n\n.walros-theme-glitch-page {\n will-change: transform, filter;\n}\n\n/* Comportamiento original de WalrOS Forum para páginas normales. */\n.walros-theme-glitch-page--body {\n animation: walros-glitch-page-body 1500ms steps(1, end) both;\n}\n\n@keyframes walros-glitch-page-body {\n 0%, 6%, 18%, 31%, 49%, 68%, 82%, 100% { transform: translate3d(0,0,0) scale(1); filter: none; }\n 7% { transform: translate3d(-18px,4px,0) scale(1.012); filter: contrast(1.5) saturate(.45); }\n 19% { transform: translate3d(26px,-7px,0) scale(1.02) skewX(-1.2deg); filter: contrast(1.9) saturate(1.6); }\n 32% { transform: translate3d(-9px,11px,0) scale(1.03); filter: invert(.12) contrast(2); }\n 50%, 57% { transform: translate3d(34px,-3px,0) scale(1.025); filter: grayscale(1) contrast(2.3); }\n 69% { transform: translate3d(-24px,5px,0) scale(1.016); filter: contrast(1.7) saturate(.2); }\n 83% { transform: translate3d(8px,-2px,0) scale(1.006); filter: contrast(1.35); }\n}\n\n/*\n * Modo seguro para parallax/sticky/ScrollTrigger.\n * El shake se aplica a una capa estable del viewport, nunca al scroll real.\n * El pequeño overscan evita descubrir bordes al desplazar la escena.\n */\n.walros-theme-glitch-page--viewport {\n transform-origin: 50% var(--walros-glitch-origin-y, 50%);\n animation: walros-glitch-page-viewport 1500ms steps(1, end) both;\n}\n\n@keyframes walros-glitch-page-viewport {\n 0%, 6%, 18%, 31%, 49%, 68%, 82%, 100% { transform: translate3d(0,0,0) scale(1.012); filter: none; }\n 7% { transform: translate3d(-18px,4px,0) scale(1.012); filter: contrast(1.5) saturate(.45); }\n 19% { transform: translate3d(26px,-7px,0) scale(1.02) skewX(-1.2deg); filter: contrast(1.9) saturate(1.6); }\n 32% { transform: translate3d(-9px,11px,0) scale(1.03); filter: invert(.12) contrast(2); }\n 50%, 57% { transform: translate3d(34px,-3px,0) scale(1.025); filter: grayscale(1) contrast(2.3); }\n 69% { transform: translate3d(-24px,5px,0) scale(1.016); filter: contrast(1.7) saturate(.2); }\n 83% { transform: translate3d(8px,-2px,0) scale(1.006); filter: contrast(1.35); }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .walros-theme-glitch-root::before,\n .walros-theme-glitch-root::after {\n animation: walros-glitch-reduced 150ms ease-out forwards;\n }\n\n .walros-theme-glitch-band {\n animation: none !important;\n }\n\n .walros-theme-glitch-page--body,\n .walros-theme-glitch-page--viewport {\n animation: none;\n }\n\n @keyframes walros-glitch-reduced {\n from { opacity: 0.35; }\n to { opacity: 0; }\n }\n}\n`;\n\nexport function WalrosThemeGlitch({\n active,\n zIndex = 9998,\n className,\n style,\n}: WalrosThemeGlitchProps) {\n return (\n <>\n <style>{GLITCH_STYLES}</style>\n {active ? (\n <div\n className={[\"walros-theme-glitch-root\", \"is-active\", className]\n .filter(Boolean)\n .join(\" \")}\n style={{ zIndex, ...style }}\n aria-hidden=\"true\"\n >\n <span className=\"walros-theme-glitch-band\" />\n <span className=\"walros-theme-glitch-band\" />\n <span className=\"walros-theme-glitch-band\" />\n <span className=\"walros-theme-glitch-band\" />\n </div>\n ) : null}\n </>\n );\n}\n\nexport default WalrosThemeGlitch;\n","import { useLayoutEffect, useState } from \"react\";\n\n/** Keep fixed overlays outside an animated body, which would otherwise\n * become their containing block and displace the portal during the glitch. */\nexport function useOverlayHost(zIndex: number) {\n const [host] = useState<HTMLDivElement | null>(() =>\n typeof document === \"undefined\" ? null : document.createElement(\"div\"),\n );\n\n useLayoutEffect(() => {\n if (!host) return;\n host.dataset.walrosOverlayRoot = \"\";\n host.style.position = \"fixed\";\n host.style.inset = \"0\";\n host.style.pointerEvents = \"none\";\n document.documentElement.appendChild(host);\n return () => host.remove();\n }, [host]);\n\n useLayoutEffect(() => {\n if (host) host.style.zIndex = String(zIndex);\n }, [host, zIndex]);\n\n return host;\n}\n","import { useEffect, useRef } from \"react\";\r\n\r\nconst DESKTOP_CURSOR_QUERY = \"(min-width: 1024px) and (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference)\";\n\nconst CURSOR_STYLES = `\n.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; }\n.directional-cursor.is-visible { opacity: 1; }\n.directional-cursor-shape { width: 20px; height: 22px; transform-origin: center center; will-change: transform; }\n.directional-cursor svg { display: block; width: 20px; height: 22px; }\n@media (min-width: 1024px) and (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {\n html.has-directional-cursor, html.has-directional-cursor body, html.has-directional-cursor body * { cursor: none !important; }\n html.has-directional-cursor :is(a, button, [role=\"button\"], [onclick], .clickable, [data-clickable], input[type=\"button\"], input[type=\"submit\"], input[type=\"reset\"], label[for]),\n 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; }\n html.has-directional-cursor :is(input, textarea, select, [contenteditable=\"true\"]) { cursor: text !important; }\n}\n`;\n\r\nexport function DirectionalCursor() {\r\n const positionLayer = useRef<HTMLDivElement>(null);\r\n const directionLayer = useRef<HTMLDivElement>(null);\r\n\r\n useEffect(() => {\r\n const position = positionLayer.current;\r\n const direction = directionLayer.current;\r\n if (!position || !direction) return;\r\n\r\n const media = window.matchMedia(DESKTOP_CURSOR_QUERY);\r\n let active = false;\r\n let frame = 0;\r\n let moveFrame = 0;\r\n let scaleTimer = 0;\r\n let latestEvent: MouseEvent | null = null;\r\n let currentX = window.innerWidth / 2;\r\n let currentY = -60;\r\n let targetX = currentX;\r\n let targetY = currentY;\r\n let currentAngle = 0;\r\n let targetAngle = 0;\r\n let hasAngle = false;\r\n let currentScale = 1;\r\n let targetScale = 1;\r\n let lastX = currentX;\r\n let lastY = 0;\r\n\r\n const render = () => {\r\n currentX += (targetX - currentX) * 0.4;\r\n currentY += (targetY - currentY) * 0.4;\r\n const angleDelta = ((targetAngle - currentAngle + 540) % 360) - 180;\r\n currentAngle += angleDelta * 0.24;\r\n currentScale += (targetScale - currentScale) * 0.24;\r\n\r\n position.style.transform = `translate3d(${currentX}px, ${currentY}px, 0)`;\r\n direction.style.transform = `translate(-50%, -50%) rotate(${currentAngle}deg) scale(${currentScale})`;\r\n\r\n const unsettled = Math.abs(targetX - currentX) > 0.08\r\n || Math.abs(targetY - currentY) > 0.08\r\n || Math.abs(angleDelta) > 0.08\r\n || Math.abs(targetScale - currentScale) > 0.002;\r\n frame = unsettled ? window.requestAnimationFrame(render) : 0;\r\n };\r\n\r\n const requestRender = () => {\r\n if (!frame) frame = window.requestAnimationFrame(render);\r\n };\r\n\r\n const processMove = () => {\r\n moveFrame = 0;\r\n const event = latestEvent;\r\n if (!event) return;\r\n const deltaX = event.clientX - lastX;\r\n const deltaY = event.clientY - lastY;\r\n const distance = Math.hypot(deltaX, deltaY);\r\n targetX = event.clientX;\r\n targetY = event.clientY;\r\n position.classList.add(\"is-visible\");\r\n\r\n if (distance > 1.25) {\r\n const rawAngle = Math.atan2(deltaY, deltaX) * (180 / Math.PI) + 90;\r\n const normalizedAngle = (rawAngle % 360 + 360) % 360;\r\n if (!hasAngle) {\r\n targetAngle = normalizedAngle;\r\n currentAngle = normalizedAngle;\r\n hasAngle = true;\r\n } else {\r\n targetAngle = normalizedAngle;\r\n }\r\n\r\n targetScale = 0.92;\r\n window.clearTimeout(scaleTimer);\r\n scaleTimer = window.setTimeout(() => {\r\n targetScale = 1;\r\n requestRender();\r\n }, 130);\r\n }\r\n\r\n lastX = event.clientX;\r\n lastY = event.clientY;\r\n requestRender();\r\n };\r\n\r\n const handleMouseMove = (event: MouseEvent) => {\r\n latestEvent = event;\r\n if (!moveFrame) moveFrame = window.requestAnimationFrame(processMove);\r\n };\r\n\r\n const activate = () => {\r\n if (active) return;\r\n active = true;\r\n document.documentElement.classList.add(\"has-directional-cursor\");\r\n window.addEventListener(\"mousemove\", handleMouseMove, { passive: true });\r\n };\r\n\r\n const deactivate = () => {\r\n if (!active) return;\r\n active = false;\r\n document.documentElement.classList.remove(\"has-directional-cursor\");\r\n position.classList.remove(\"is-visible\");\r\n window.removeEventListener(\"mousemove\", handleMouseMove);\r\n window.cancelAnimationFrame(frame);\r\n window.cancelAnimationFrame(moveFrame);\r\n window.clearTimeout(scaleTimer);\r\n frame = 0;\r\n moveFrame = 0;\r\n };\r\n\r\n const sync = () => {\r\n if (media.matches) activate();\r\n else deactivate();\r\n };\r\n media.addEventListener(\"change\", sync);\r\n sync();\r\n\r\n return () => {\r\n media.removeEventListener(\"change\", sync);\r\n deactivate();\r\n };\r\n }, []);\r\n\r\n return (\n <><style>{CURSOR_STYLES}</style><div ref={positionLayer} className=\"directional-cursor\" aria-hidden=\"true\">\n <div ref={directionLayer} className=\"directional-cursor-shape\">\r\n <svg width=\"50\" height=\"54\" viewBox=\"0 0 50 54\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <g filter=\"url(#walros-cursor-shadow)\">\r\n <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\" />\r\n <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\" />\r\n </g>\r\n <defs>\r\n <filter id=\"walros-cursor-shadow\" x=\"0.602397\" y=\"0.952444\" width=\"49.0584\" height=\"52.428\" filterUnits=\"userSpaceOnUse\" colorInterpolationFilters=\"sRGB\">\r\n <feFlood floodOpacity=\"0\" result=\"BackgroundImageFix\" />\r\n <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\" />\r\n <feOffset dy=\"2.25825\" />\r\n <feGaussianBlur stdDeviation=\"2.25825\" />\r\n <feComposite in2=\"hardAlpha\" operator=\"out\" />\r\n <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\" />\r\n <feBlend mode=\"normal\" in2=\"BackgroundImageFix\" result=\"effect1_dropShadow\" />\r\n <feBlend mode=\"normal\" in=\"SourceGraphic\" in2=\"effect1_dropShadow\" result=\"shape\" />\r\n </filter>\r\n </defs>\r\n </svg>\r\n </div>\r\n </div></>\n );\n}\n","import type { ImgHTMLAttributes } from \"react\";\nimport { walrosLogoChromeUrl } from \"../assets\";\n\nexport type WalrosLogoProps = Omit<\n ImgHTMLAttributes<HTMLImageElement>,\n \"src\"\n>;\n\nexport function WalrosLogo({\n alt = \"WalrOS\",\n draggable = false,\n ...props\n}: WalrosLogoProps) {\n return (\n <img\n src={walrosLogoChromeUrl}\n alt={alt}\n draggable={draggable}\n {...props}\n />\n );\n}\n\nexport default WalrosLogo;\n","import type { ImgHTMLAttributes } from \"react\";\nimport {\n walrosWordmarkDarkUrl,\n walrosWordmarkLightUrl,\n} from \"../assets\";\n\nexport type WalrosWordmarkProps = Omit<\n ImgHTMLAttributes<HTMLImageElement>,\n \"src\"\n> & {\n variant?: \"light\" | \"dark\";\n};\n\nexport function WalrosWordmark({\n variant = \"light\",\n alt = \"WalrOS\",\n draggable = false,\n ...props\n}: WalrosWordmarkProps) {\n const src =\n variant === \"dark\"\n ? walrosWordmarkDarkUrl\n : walrosWordmarkLightUrl;\n\n return (\n <img\n src={src}\n alt={alt}\n draggable={draggable}\n {...props}\n />\n );\n}\n\nexport default WalrosWordmark;\n","import {\n useCallback,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport type { RefObject } from \"react\";\nimport { walrosThemeGlitchSoundUrl } from \"../assets\";\n\nexport type WalrosTheme = \"light\" | \"dark\";\nexport type WalrosThemeMode = \"body\" | \"viewport\";\n\nexport type WalrosThemeShakeTarget =\n | HTMLElement\n | RefObject<HTMLElement | null>\n | null\n | undefined;\n\nexport type UseWalrosThemeOptions = {\n storageKey?: string;\n defaultTheme?: WalrosTheme;\n useSystemPreference?: boolean;\n swapDelay?: number;\n totalDuration?: number;\n /** Set to false to disable audio, or provide a custom sound URL. */\n soundUrl?: string | false;\n /** Playback volume from 0 to 1. Defaults to the WalrOS site mix. */\n soundVolume?: number;\n applyTheme?: (theme: WalrosTheme) => void;\n\n /**\n * `body` reproduce el comportamiento original de WalrOS Forum.\n * `viewport` bloquea el scroll y sacude solo los elementos indicados,\n * recomendado para parallax, sticky y GSAP ScrollTrigger.\n */\n mode?: WalrosThemeMode;\n\n /** Elementos que recibirán el shake cuando mode=\"viewport\". */\n shakeTargets?: readonly WalrosThemeShakeTarget[];\n\n /**\n * En modo viewport se activa por defecto. Mantiene scrollX/scrollY estables\n * con requestAnimationFrame sin usar position: fixed en el body.\n */\n lockScroll?: boolean;\n\n /** Se ejecuta después de restaurar el scroll; útil para ScrollTrigger.update(). */\n onAfterUnlock?: () => void;\n};\n\nexport type UseWalrosThemeResult = {\n theme: WalrosTheme;\n isDark: boolean;\n mounted: boolean;\n glitching: boolean;\n toggleTheme: () => void;\n setTheme: (theme: WalrosTheme) => void;\n};\n\ntype ViewportLockState = {\n scrollX: number;\n scrollY: number;\n rafId: number;\n active: boolean;\n bodyOverflow: string;\n htmlOverflow: string;\n htmlOverscrollBehavior: string;\n};\n\nconst GLITCH_BASE_CLASS = \"walros-theme-glitch-page\";\nconst GLITCH_BODY_CLASS = \"walros-theme-glitch-page--body\";\nconst GLITCH_VIEWPORT_CLASS = \"walros-theme-glitch-page--viewport\";\nconst GLITCH_LOCK_CLASS = \"walros-theme-glitch-lock\";\n\nfunction defaultApplyTheme(theme: WalrosTheme) {\n if (typeof document === \"undefined\") return;\n\n const root = document.documentElement;\n root.classList.toggle(\"dark\", theme === \"dark\");\n root.style.colorScheme = theme;\n}\n\nfunction readInitialTheme(\n storageKey: string,\n defaultTheme: WalrosTheme,\n useSystemPreference: boolean,\n): WalrosTheme {\n if (typeof window === \"undefined\") return defaultTheme;\n\n try {\n const stored = window.localStorage.getItem(storageKey);\n if (stored === \"light\" || stored === \"dark\") return stored;\n } catch {\n // localStorage puede estar bloqueado en modo privado.\n }\n\n if (\n useSystemPreference &&\n window.matchMedia?.(\"(prefers-color-scheme: dark)\").matches\n ) {\n return \"dark\";\n }\n\n return defaultTheme;\n}\n\nfunction resolveShakeTargets(\n targets: readonly WalrosThemeShakeTarget[],\n): HTMLElement[] {\n const resolved = new Set<HTMLElement>();\n\n for (const target of targets) {\n if (!target) continue;\n\n const element =\n typeof target === \"object\" && \"current\" in target\n ? target.current\n : target;\n\n if (element) resolved.add(element);\n }\n\n return [...resolved];\n}\n\nexport function useWalrosTheme({\n storageKey = \"walros-theme\",\n defaultTheme = \"light\",\n useSystemPreference = false,\n swapDelay = 610,\n totalDuration = 1500,\n soundUrl = walrosThemeGlitchSoundUrl,\n soundVolume = 0.52,\n applyTheme = defaultApplyTheme,\n mode = \"body\",\n shakeTargets = [],\n lockScroll,\n onAfterUnlock,\n}: UseWalrosThemeOptions = {}): UseWalrosThemeResult {\n const [theme, setThemeState] = useState<WalrosTheme>(() =>\n readInitialTheme(storageKey, defaultTheme, useSystemPreference),\n );\n const [mounted, setMounted] = useState(false);\n const [glitching, setGlitching] = useState(false);\n\n const themeRef = useRef(theme);\n const glitchingRef = useRef(false);\n const swapTimerRef = useRef<number | null>(null);\n const cleanupTimerRef = useRef<number | null>(null);\n const applyThemeRef = useRef(applyTheme);\n const modeRef = useRef(mode);\n const shakeTargetsRef = useRef(shakeTargets);\n const lockScrollRef = useRef(lockScroll);\n const onAfterUnlockRef = useRef(onAfterUnlock);\n const activeTargetsRef = useRef<HTMLElement[]>([]);\n const viewportLockRef = useRef<ViewportLockState | null>(null);\n const soundRef = useRef<HTMLAudioElement | null>(null);\n const soundUrlRef = useRef(soundUrl);\n const soundVolumeRef = useRef(soundVolume);\n\n themeRef.current = theme;\n applyThemeRef.current = applyTheme;\n modeRef.current = mode;\n shakeTargetsRef.current = shakeTargets;\n lockScrollRef.current = lockScroll;\n onAfterUnlockRef.current = onAfterUnlock;\n soundUrlRef.current = soundUrl;\n soundVolumeRef.current = soundVolume;\n\n const playThemeSound = useCallback(() => {\n if (typeof window === \"undefined\" || !soundUrlRef.current) return;\n\n try {\n if (!soundRef.current || soundRef.current.src !== new URL(soundUrlRef.current, document.baseURI).href) {\n soundRef.current?.pause();\n soundRef.current = new Audio(soundUrlRef.current);\n soundRef.current.preload = \"auto\";\n }\n const audio = soundRef.current;\n audio.volume = Math.max(0, Math.min(1, soundVolumeRef.current));\n audio.currentTime = 0;\n void audio.play().catch(() => {\n // Browsers may block sound; the theme animation still continues.\n });\n } catch {\n // Audio support is optional and must not block the theme change.\n }\n }, []);\n\n const persistTheme = useCallback(\n (nextTheme: WalrosTheme) => {\n applyThemeRef.current(nextTheme);\n setThemeState(nextTheme);\n themeRef.current = nextTheme;\n\n try {\n window.localStorage.setItem(storageKey, nextTheme);\n } catch {\n // El cambio debe funcionar aunque localStorage falle.\n }\n },\n [storageKey],\n );\n\n useEffect(() => {\n const initialTheme = readInitialTheme(\n storageKey,\n defaultTheme,\n useSystemPreference,\n );\n\n themeRef.current = initialTheme;\n setThemeState(initialTheme);\n applyThemeRef.current(initialTheme);\n setMounted(true);\n }, [defaultTheme, storageKey, useSystemPreference]);\n\n const clearTimers = useCallback(() => {\n if (swapTimerRef.current !== null) {\n window.clearTimeout(swapTimerRef.current);\n swapTimerRef.current = null;\n }\n\n if (cleanupTimerRef.current !== null) {\n window.clearTimeout(cleanupTimerRef.current);\n cleanupTimerRef.current = null;\n }\n }, []);\n\n const lockViewport = useCallback(() => {\n if (\n typeof window === \"undefined\" ||\n typeof document === \"undefined\" ||\n viewportLockRef.current\n ) {\n return;\n }\n\n const body = document.body;\n const html = document.documentElement;\n const lockState: ViewportLockState = {\n scrollX: window.scrollX,\n scrollY: window.scrollY,\n rafId: 0,\n active: true,\n bodyOverflow: body.style.overflow,\n htmlOverflow: html.style.overflow,\n htmlOverscrollBehavior: html.style.overscrollBehavior,\n };\n\n viewportLockRef.current = lockState;\n\n const keepScrollStable = () => {\n if (!lockState.active) return;\n window.scrollTo(lockState.scrollX, lockState.scrollY);\n lockState.rafId = window.requestAnimationFrame(keepScrollStable);\n };\n\n html.classList.add(GLITCH_LOCK_CLASS);\n html.style.overflow = \"hidden\";\n html.style.overscrollBehavior = \"none\";\n body.style.overflow = \"hidden\";\n lockState.rafId = window.requestAnimationFrame(keepScrollStable);\n }, []);\n\n const unlockViewport = useCallback((runCallback: boolean) => {\n if (typeof window === \"undefined\" || typeof document === \"undefined\") {\n return;\n }\n\n const lockState = viewportLockRef.current;\n if (!lockState) return;\n\n lockState.active = false;\n window.cancelAnimationFrame(lockState.rafId);\n\n const body = document.body;\n const html = document.documentElement;\n body.style.overflow = lockState.bodyOverflow;\n html.style.overflow = lockState.htmlOverflow;\n html.style.overscrollBehavior = lockState.htmlOverscrollBehavior;\n html.classList.remove(GLITCH_LOCK_CLASS);\n\n viewportLockRef.current = null;\n window.scrollTo(lockState.scrollX, lockState.scrollY);\n\n if (runCallback) {\n window.requestAnimationFrame(() => {\n onAfterUnlockRef.current?.();\n });\n }\n }, []);\n\n const removeShakeClasses = useCallback(() => {\n for (const target of activeTargetsRef.current) {\n target.classList.remove(\n GLITCH_BASE_CLASS,\n GLITCH_BODY_CLASS,\n GLITCH_VIEWPORT_CLASS,\n );\n target.style.removeProperty(\"--walros-glitch-origin-y\");\n }\n\n activeTargetsRef.current = [];\n }, []);\n\n const finishGlitch = useCallback(() => {\n if (soundRef.current) {\n soundRef.current.pause();\n soundRef.current.currentTime = 0;\n }\n removeShakeClasses();\n unlockViewport(true);\n glitchingRef.current = false;\n setGlitching(false);\n }, [removeShakeClasses, unlockViewport]);\n\n const setTheme = useCallback(\n (nextTheme: WalrosTheme) => {\n if (glitchingRef.current) return;\n persistTheme(nextTheme);\n },\n [persistTheme],\n );\n\n const toggleTheme = useCallback(() => {\n if (\n typeof window === \"undefined\" ||\n typeof document === \"undefined\" ||\n glitchingRef.current\n ) {\n return;\n }\n\n playThemeSound();\n\n const currentMode = modeRef.current;\n const shouldLockScroll =\n lockScrollRef.current ?? currentMode === \"viewport\";\n\n if (currentMode === \"viewport\" && shouldLockScroll) {\n lockViewport();\n }\n\n const targets =\n currentMode === \"body\"\n ? [document.body]\n : resolveShakeTargets(shakeTargetsRef.current);\n\n const modeClass =\n currentMode === \"body\"\n ? GLITCH_BODY_CLASS\n : GLITCH_VIEWPORT_CLASS;\n\n for (const target of targets) {\n target.style.setProperty(\n \"--walros-glitch-origin-y\",\n currentMode === \"body\"\n ? `${window.scrollY + window.innerHeight / 2}px`\n : \"50%\",\n );\n target.classList.add(GLITCH_BASE_CLASS, modeClass);\n }\n\n activeTargetsRef.current = targets;\n glitchingRef.current = true;\n setGlitching(true);\n\n const reducedMotion = window.matchMedia?.(\n \"(prefers-reduced-motion: reduce)\",\n ).matches;\n\n const nextTheme: WalrosTheme =\n themeRef.current === \"dark\" ? \"light\" : \"dark\";\n\n const effectiveSwapDelay = reducedMotion\n ? 75\n : Math.max(0, swapDelay);\n const effectiveDuration = reducedMotion\n ? 150\n : Math.max(effectiveSwapDelay, totalDuration);\n\n swapTimerRef.current = window.setTimeout(() => {\n persistTheme(nextTheme);\n swapTimerRef.current = null;\n }, effectiveSwapDelay);\n\n cleanupTimerRef.current = window.setTimeout(() => {\n cleanupTimerRef.current = null;\n finishGlitch();\n }, effectiveDuration);\n }, [finishGlitch, lockViewport, persistTheme, playThemeSound, swapDelay, totalDuration]);\n\n useEffect(() => {\n return () => {\n clearTimers();\n removeShakeClasses();\n unlockViewport(false);\n soundRef.current?.pause();\n if (soundRef.current) soundRef.current.currentTime = 0;\n soundRef.current = null;\n };\n }, [clearTimers, removeShakeClasses, unlockViewport]);\n\n return {\n theme,\n isDark: theme === \"dark\",\n mounted,\n glitching,\n toggleTheme,\n setTheme,\n };\n}\n\nexport default useWalrosTheme;\n"],"mappings":"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","names":["useState","createPortal","useEffect","useLayoutEffect","useRef","useState","jsx","jsxs","useLayoutEffect","useState","Fragment","jsx","jsxs","VISIBLE_LEFT","VISIBLE_RIGHT","VISIBLE_TOP","VISIBLE_BOTTOM","useRef","useState","useLayoutEffect","useEffect","jsx","useState","createPortal","useEffect","useRef","Fragment","jsx","jsxs","jsx","jsx","useEffect","useRef","useState","useState","useRef","useEffect"]}
1
+ {"version":3,"sources":["../src/components/WalrosPortalTransition.tsx","../src/assets.ts","../src/components/Walros3DPortalTransition.tsx","../src/portalSilhouette.ts","../src/components/useOverlayHost.ts","../src/components/WalrosThemeTransition.tsx","../src/components/WalrosThemeGlitch.tsx","../src/components/DirectionalCursor.tsx","../src/components/WalrosLogo.tsx","../src/components/WalrosWordmark.tsx","../src/hooks/useWalrosTheme.ts"],"sourcesContent":["import { useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { walrosLogoChromeUrl } from \"../assets\";\nimport { Walros3DPortalTransition, type PortalOrigin } from \"./Walros3DPortalTransition\";\nimport { useOverlayHost } from \"./useOverlayHost\";\n\nexport type WalrosPortalTransitionProps = {\n duration?: number;\n onComplete?: () => void;\n backgroundColor?: string;\n enabled?: boolean;\n storageMode?: \"always\" | \"session\" | \"once\";\n storageKey?: string;\n zIndex?: number;\n /** Projected bounds of an existing 3D logo, as on walros.org. */\n origin?: PortalOrigin;\n /** Intro logo shown beneath the black mask; set false when using an existing 3D logo. */\n logoUrl?: string | false;\n};\n\nconst IMAGE_SIZE = (width: number) => Math.min(150, Math.max(90, width * .11));\nconst IMAGE_WIDTH = 1254;\nconst VISIBLE_LEFT = 244;\nconst VISIBLE_RIGHT = 1010;\nconst VISIBLE_TOP = 115;\nconst VISIBLE_BOTTOM = 1128;\n\nfunction defaultOrigin(): PortalOrigin {\n if (typeof window === \"undefined\") return { centerX: 0, centerY: 0, width: 70, height: 90 };\n const size = IMAGE_SIZE(window.innerWidth);\n return {\n centerX: window.innerWidth / 2,\n centerY: window.innerHeight * .45 + (((VISIBLE_TOP + VISIBLE_BOTTOM) / 2 - IMAGE_WIDTH / 2) / IMAGE_WIDTH) * size,\n width: ((VISIBLE_RIGHT - VISIBLE_LEFT) / IMAGE_WIDTH) * size,\n height: ((VISIBLE_BOTTOM - VISIBLE_TOP) / IMAGE_WIDTH) * size,\n };\n}\n\nfunction getStorage(mode: \"session\" | \"once\"): Storage | null {\n if (typeof window === \"undefined\") return null;\n try {\n return mode === \"session\" ? window.sessionStorage : window.localStorage;\n } catch {\n return null;\n }\n}\n\nfunction shouldRun(enabled: boolean, mode: \"always\" | \"session\" | \"once\", key: string) {\n if (!enabled) return false;\n if (mode === \"always\") return true;\n try {\n return getStorage(mode)?.getItem(key) == null;\n } catch {\n return true;\n }\n}\n\n/** 900 ms walros.org entrance, with the logo confined below its black mask. */\nexport function WalrosPortalTransition({\n duration = 900,\n onComplete,\n backgroundColor = \"#000\",\n enabled = true,\n storageMode = \"always\",\n storageKey = \"walros-portal-seen\",\n zIndex = 10000,\n origin,\n logoUrl = walrosLogoChromeUrl,\n}: WalrosPortalTransitionProps) {\n const [run] = useState(() => shouldRun(enabled, storageMode, storageKey));\n const [complete, setComplete] = useState(false);\n const [initialOrigin] = useState(() => origin ?? defaultOrigin());\n const host = useOverlayHost(zIndex);\n\n if (!host || !enabled || !run || complete) return null;\n\n return createPortal(\n <Walros3DPortalTransition\n origin={initialOrigin}\n logoUrl={logoUrl}\n duration={duration}\n backgroundColor={backgroundColor}\n zIndex={1}\n lockScroll\n onComplete={() => {\n if (storageMode !== \"always\") {\n try { getStorage(storageMode)?.setItem(storageKey, \"1\"); } catch { /* Storage is optional. */ }\n }\n setComplete(true);\n onComplete?.();\n }}\n />,\n host,\n );\n}\n\nexport default WalrosPortalTransition;\n","export const walrosPortalSilhouetteUrl = new URL(\n \"./assets/walros-portal-silhouette.svg\",\n import.meta.url,\n).href;\n\nexport const walrosLogoChromeUrl = new URL(\n \"./assets/walros-logo-chrome.png\",\n import.meta.url,\n).href;\n\nexport const walrosWordmarkLightUrl = new URL(\n \"./assets/walros-wordmark-light.png\",\n import.meta.url,\n).href;\n\nexport const walrosWordmarkDarkUrl = new URL(\n \"./assets/walros-wordmark-dark.png\",\n import.meta.url,\n).href;\n\nexport const walrosThemeGlitchSoundUrl = new URL(\n \"./assets/walros-theme-glitch.mp3\",\n import.meta.url,\n).href;\n","import { useEffect, useId, useLayoutEffect, useRef, useState } from \"react\";\nimport gsap from \"gsap\";\nimport { walrosPortalPaths } from \"../portalSilhouette\";\n\r\nexport type PortalOrigin = {\r\n centerX: number;\r\n centerY: number;\r\n width: number;\r\n height: number;\r\n};\r\n\r\nexport type Walros3DPortalTransitionProps = {\n origin: PortalOrigin;\n onComplete?: () => void;\n duration?: number;\n backgroundColor?: string;\n zIndex?: number;\n lockScroll?: boolean;\n /** An optional image that follows the portal exactly and fades before reveal. */\n logoUrl?: string | false;\n};\n\r\nconst FOCUS_X = 626;\r\nconst FOCUS_Y = 333;\r\nconst VISIBLE_LEFT = 244;\r\nconst VISIBLE_RIGHT = 1010;\r\nconst VISIBLE_TOP = 115;\r\nconst VISIBLE_BOTTOM = 1128;\r\nconst PORTAL_RADIUS = 190;\r\n\r\nexport function Walros3DPortalTransition({\n origin,\n onComplete,\n duration = 900,\n backgroundColor = \"#000\",\n zIndex = 10001,\n lockScroll = true,\n logoUrl = false,\n}: Walros3DPortalTransitionProps) {\n const [visible, setVisible] = useState(true);\n const [viewport, setViewport] = useState(() => ({\n width: typeof window === \"undefined\" ? 0 : window.innerWidth,\n height: typeof window === \"undefined\" ? 0 : window.innerHeight,\n }));\n const overlay = useRef<HTMLDivElement>(null);\n const portal = useRef<SVGGElement>(null);\n const logo = useRef<SVGGElement>(null);\n const completeRef = useRef(onComplete);\n completeRef.current = onComplete;\n const maskId = `walros-3d-portal-${useId().replace(/:/g, \"_\")}`;\n\r\n useEffect(() => {\r\n const updateViewport = () => setViewport({ width: window.innerWidth, height: window.innerHeight });\r\n window.addEventListener(\"resize\", updateViewport);\r\n return () => window.removeEventListener(\"resize\", updateViewport);\r\n }, []);\r\n\r\n useLayoutEffect(() => {\n if (!visible || viewport.width <= 0 || viewport.height <= 0 || !overlay.current || !portal.current) return;\n const previousOverflow = document.body.style.overflow;\n if (lockScroll) document.body.style.overflow = \"hidden\";\n\r\n const visibleWidth = VISIBLE_RIGHT - VISIBLE_LEFT;\r\n const visibleHeight = VISIBLE_BOTTOM - VISIBLE_TOP;\r\n const visualCenterX = (VISIBLE_LEFT + VISIBLE_RIGHT) / 2;\r\n const visualCenterY = (VISIBLE_TOP + VISIBLE_BOTTOM) / 2;\r\n // Let the black mask overlap the projected GLB by roughly one pixel. This\r\n // removes the pale halo without visibly cropping the chrome silhouette.\r\n const initialScale = Math.min(origin.width / visibleWidth, origin.height / visibleHeight) * .985;\r\n const initialX = origin.centerX - (visualCenterX - FOCUS_X) * initialScale;\r\n const initialY = origin.centerY - (visualCenterY - FOCUS_Y) * initialScale;\r\n const diagonal = Math.hypot(viewport.width, viewport.height) / 2;\n const finalScale = ((diagonal + 80) / PORTAL_RADIUS) * 1.15;\n // The visible silhouette, rather than the SVG transform origin, must\n // remain centred as the portal grows.\n const targetX = viewport.width / 2 - (visualCenterX - FOCUS_X) * finalScale;\n const targetY = viewport.height / 2 - (visualCenterY - FOCUS_Y) * finalScale;\n const total = duration / 1000;\r\n\r\n gsap.set(portal.current, {\n x: initialX,\n y: initialY,\n scale: initialScale,\n svgOrigin: \"0 0\",\n });\n if (logo.current) {\n gsap.set(logo.current, {\n x: initialX,\n y: initialY,\n scale: initialScale,\n opacity: 1,\n svgOrigin: \"0 0\",\n });\n }\n gsap.set(overlay.current, { opacity: 1 });\n\r\n const finish = () => {\r\n if (lockScroll) document.body.style.overflow = previousOverflow;\n setVisible(false);\n completeRef.current?.();\n };\r\n const reducedMotion = window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\r\n const timeline = gsap.timeline({ onComplete: finish });\r\n if (reducedMotion) {\r\n timeline.to(overlay.current, { opacity: 0, duration: 0.15, ease: \"power1.out\" });\n } else {\n timeline\n .to([portal.current, logo.current].filter(Boolean), {\n x: targetX,\n y: targetY,\n scale: finalScale,\n duration: total,\n ease: \"power2.in\",\n });\n if (logo.current) {\n timeline.to(logo.current, {\n opacity: 0,\n duration: total * .18,\n ease: \"power1.out\",\n }, total * .7);\n }\n timeline\n .to(overlay.current, {\n opacity: 0,\r\n duration: total * 0.1,\r\n ease: \"power2.out\",\r\n }, total * 0.9);\r\n }\r\n\r\n return () => {\r\n timeline.kill();\r\n if (lockScroll) document.body.style.overflow = previousOverflow;\n };\n }, [duration, lockScroll, origin, viewport, visible]);\n\n if (!visible) return null;\n\r\n return (\r\n <div\r\n ref={overlay}\r\n className=\"walros-3d-portal\"\n style={{\n position: \"fixed\",\n inset: 0,\n width: \"100vw\",\n height: \"100dvh\",\n overflow: \"hidden\",\n pointerEvents: \"none\",\n zIndex,\n backgroundColor: viewport.width > 0 && viewport.height > 0 ? \"transparent\" : backgroundColor,\n }}\n aria-hidden=\"true\"\r\n >\r\n <svg width=\"100%\" height=\"100%\" viewBox={`0 0 ${viewport.width} ${viewport.height}`} preserveAspectRatio=\"none\" style={{ display: \"block\" }}>\n <defs>\r\n <mask id={maskId} maskUnits=\"userSpaceOnUse\" x=\"0\" y=\"0\" width={viewport.width} height={viewport.height}>\r\n <rect width={viewport.width} height={viewport.height} fill=\"white\" />\r\n <g ref={portal}>\r\n <g transform={`translate(${-FOCUS_X} ${-FOCUS_Y})`} fill=\"black\">\r\n {walrosPortalPaths.map((path, index) => <path d={path} key={index} />)}\n </g>\r\n </g>\r\n </mask>\r\n </defs>\n {logoUrl && (\n <g ref={logo}>\n <image href={logoUrl} x={-FOCUS_X} y={-FOCUS_Y} width=\"1254\" height=\"1254\" />\n </g>\n )}\n <rect width={viewport.width} height={viewport.height} fill={backgroundColor} mask={`url(#${maskId})`} />\n </svg>\r\n </div>\r\n );\r\n}\r\n","/* Exact silhouette used by the walros.org portal mask. */\r\nexport const walrosPortalPaths = [\r\n \"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\",\r\n \"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\",\r\n \"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\",\r\n] as const;\r\n","import { useLayoutEffect, useState } from \"react\";\n\n/** Keep fixed overlays outside an animated body, which would otherwise\n * become their containing block and displace the portal during the glitch. */\nexport function useOverlayHost(zIndex: number) {\n const [host] = useState<HTMLDivElement | null>(() =>\n typeof document === \"undefined\" ? null : document.createElement(\"div\"),\n );\n\n useLayoutEffect(() => {\n if (!host) return;\n host.dataset.walrosOverlayRoot = \"\";\n host.style.position = \"fixed\";\n host.style.inset = \"0\";\n host.style.pointerEvents = \"none\";\n document.documentElement.appendChild(host);\n return () => host.remove();\n }, [host]);\n\n useLayoutEffect(() => {\n if (host) host.style.zIndex = String(zIndex);\n }, [host, zIndex]);\n\n return host;\n}\n","import { createPortal } from \"react-dom\";\nimport { WalrosThemeGlitch } from \"./WalrosThemeGlitch\";\nimport { useOverlayHost } from \"./useOverlayHost\";\n\nexport type WalrosThemeTransitionProps = {\n /** Pass the `glitching` value returned by `useWalrosTheme`. */\n active: boolean;\n /** @deprecated The theme change has no portal; retained for source compatibility. */\n portalDuration?: number;\n /** @deprecated The theme change has no logo; retained for source compatibility. */\n logoUrl?: string;\n zIndex?: number;\n};\n\n/** The walros.org theme effect is a shake and glitch, without an intro logo. */\nexport function WalrosThemeTransition({\n active,\n zIndex = 10000,\n}: WalrosThemeTransitionProps) {\n const host = useOverlayHost(zIndex);\n if (!host) return null;\n\n return createPortal(\n <WalrosThemeGlitch active={active} zIndex={1} />,\n host,\n );\n}\n","import type { CSSProperties } from \"react\";\n\nexport type WalrosThemeGlitchProps = {\n active: boolean;\n zIndex?: number;\n className?: string;\n style?: CSSProperties;\n};\n\nconst GLITCH_STYLES = `\n.walros-theme-glitch-root {\n position: fixed;\n inset: 0;\n z-index: 9998;\n pointer-events: none;\n overflow: hidden;\n visibility: hidden;\n}\n.walros-theme-glitch-root.is-active {\n visibility: visible;\n}\n.walros-theme-glitch-root::before,\n.walros-theme-glitch-root::after {\n content: \"\";\n position: absolute;\n inset: 0;\n}\n.walros-theme-glitch-root::before {\n background: rgba(0, 0, 0, .82);\n mix-blend-mode: normal;\n animation: walros-glitch-flash 1500ms steps(1, end) both;\n}\n.walros-theme-glitch-root::after {\n background: repeating-linear-gradient(0deg, transparent 0 3px, rgba(255,255,255,.09) 3px 4px);\n animation: walros-glitch-scan 90ms steps(2, end) 16 both;\n}\n.walros-theme-glitch-band {\n position: absolute;\n left: -12%;\n width: 124%;\n opacity: 0;\n}\n.walros-theme-glitch-band:nth-child(1) { top: 12%; height: 4%; background: #eaf6ff; animation: walros-glitch-band-a 1500ms steps(1, end) both; }\n.walros-theme-glitch-band:nth-child(2) { top: 36%; height: 11%; background: #020407; animation: walros-glitch-band-b 1500ms steps(1, end) both; }\n.walros-theme-glitch-band:nth-child(3) { top: 62%; height: 2%; background: #7faddb; animation: walros-glitch-band-c 1500ms steps(1, end) both; }\n.walros-theme-glitch-band:nth-child(4) { top: 79%; height: 8%; background: #f4f6f5; animation: walros-glitch-band-d 1500ms steps(1, end) both; }\n\n@keyframes walros-glitch-scan {\n 0% { transform: translateY(-2px); opacity: .25; }\n 50% { transform: translateY(2px); opacity: .08; }\n 100% { transform: translateY(0); opacity: .2; }\n}\n@keyframes walros-glitch-flash {\n 0%, 17%, 22%, 34%, 39%, 54%, 59%, 73%, 78%, 100% { opacity: 0; }\n 18%, 21% { opacity: .18; }\n 35%, 38% { opacity: .48; }\n 55%, 58% { opacity: .82; }\n 74%, 77% { opacity: .22; }\n}\n@keyframes walros-glitch-band-a {\n 0%, 8%, 18%, 42%, 51%, 73%, 82%, 100% { opacity: 0; transform: translateX(0); }\n 9%, 17% { opacity: .55; transform: translateX(-7%); }\n 43%, 50% { opacity: .82; transform: translateX(10%); }\n 74%, 81% { opacity: .32; transform: translateX(-4%); }\n}\n@keyframes walros-glitch-band-b {\n 0%, 20%, 27%, 46%, 55%, 64%, 71%, 100% { opacity: 0; transform: translateX(0); }\n 21%, 26% { opacity: .72; transform: translateX(9%); }\n 47%, 54% { opacity: .9; transform: translateX(-6%); }\n 65%, 70% { opacity: .5; transform: translateX(4%); }\n}\n@keyframes walros-glitch-band-c {\n 0%, 13%, 23%, 39%, 48%, 67%, 76%, 100% { opacity: 0; transform: translateX(0); }\n 14%, 22% { opacity: .9; transform: translateX(5%); }\n 40%, 47% { opacity: .65; transform: translateX(-11%); }\n 68%, 75% { opacity: .75; transform: translateX(8%); }\n}\n@keyframes walros-glitch-band-d {\n 0%, 29%, 38%, 57%, 65%, 85%, 93%, 100% { opacity: 0; transform: translateX(0); }\n 30%, 37% { opacity: .42; transform: translateX(-8%); }\n 58%, 64% { opacity: .7; transform: translateX(7%); }\n 86%, 92% { opacity: .25; transform: translateX(-3%); }\n}\n\n.walros-theme-glitch-lock {\n overscroll-behavior: none;\n}\n\n.walros-theme-glitch-page {\n will-change: transform, filter;\n}\n\n/* Comportamiento original de WalrOS Forum para páginas normales. */\n.walros-theme-glitch-page--body {\n animation: walros-glitch-page-body 1500ms steps(1, end) both;\n}\n\n@keyframes walros-glitch-page-body {\n 0%, 6%, 18%, 31%, 49%, 68%, 82%, 100% { transform: translate3d(0,0,0) scale(1); filter: none; }\n 7% { transform: translate3d(-18px,4px,0) scale(1.012); filter: contrast(1.5) saturate(.45); }\n 19% { transform: translate3d(26px,-7px,0) scale(1.02) skewX(-1.2deg); filter: contrast(1.9) saturate(1.6); }\n 32% { transform: translate3d(-9px,11px,0) scale(1.03); filter: invert(.12) contrast(2); }\n 50%, 57% { transform: translate3d(34px,-3px,0) scale(1.025); filter: grayscale(1) contrast(2.3); }\n 69% { transform: translate3d(-24px,5px,0) scale(1.016); filter: contrast(1.7) saturate(.2); }\n 83% { transform: translate3d(8px,-2px,0) scale(1.006); filter: contrast(1.35); }\n}\n\n/*\n * Modo seguro para parallax/sticky/ScrollTrigger.\n * El shake se aplica a una capa estable del viewport, nunca al scroll real.\n * El pequeño overscan evita descubrir bordes al desplazar la escena.\n */\n.walros-theme-glitch-page--viewport {\n transform-origin: 50% var(--walros-glitch-origin-y, 50%);\n animation: walros-glitch-page-viewport 1500ms steps(1, end) both;\n}\n\n@keyframes walros-glitch-page-viewport {\n 0%, 6%, 18%, 31%, 49%, 68%, 82%, 100% { transform: translate3d(0,0,0) scale(1.012); filter: none; }\n 7% { transform: translate3d(-18px,4px,0) scale(1.012); filter: contrast(1.5) saturate(.45); }\n 19% { transform: translate3d(26px,-7px,0) scale(1.02) skewX(-1.2deg); filter: contrast(1.9) saturate(1.6); }\n 32% { transform: translate3d(-9px,11px,0) scale(1.03); filter: invert(.12) contrast(2); }\n 50%, 57% { transform: translate3d(34px,-3px,0) scale(1.025); filter: grayscale(1) contrast(2.3); }\n 69% { transform: translate3d(-24px,5px,0) scale(1.016); filter: contrast(1.7) saturate(.2); }\n 83% { transform: translate3d(8px,-2px,0) scale(1.006); filter: contrast(1.35); }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .walros-theme-glitch-root::before,\n .walros-theme-glitch-root::after {\n animation: walros-glitch-reduced 150ms ease-out forwards;\n }\n\n .walros-theme-glitch-band {\n animation: none !important;\n }\n\n .walros-theme-glitch-page--body,\n .walros-theme-glitch-page--viewport {\n animation: none;\n }\n\n @keyframes walros-glitch-reduced {\n from { opacity: 0.35; }\n to { opacity: 0; }\n }\n}\n`;\n\nexport function WalrosThemeGlitch({\n active,\n zIndex = 9998,\n className,\n style,\n}: WalrosThemeGlitchProps) {\n return (\n <>\n <style>{GLITCH_STYLES}</style>\n {active ? (\n <div\n className={[\"walros-theme-glitch-root\", \"is-active\", className]\n .filter(Boolean)\n .join(\" \")}\n style={{ zIndex, ...style }}\n aria-hidden=\"true\"\n >\n <span className=\"walros-theme-glitch-band\" />\n <span className=\"walros-theme-glitch-band\" />\n <span className=\"walros-theme-glitch-band\" />\n <span className=\"walros-theme-glitch-band\" />\n </div>\n ) : null}\n </>\n );\n}\n\nexport default WalrosThemeGlitch;\n","import { useEffect, useRef } from \"react\";\r\n\r\nconst DESKTOP_CURSOR_QUERY = \"(min-width: 1024px) and (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference)\";\n\nconst CURSOR_STYLES = `\n.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; }\n.directional-cursor.is-visible { opacity: 1; }\n.directional-cursor-shape { width: 20px; height: 22px; transform-origin: center center; will-change: transform; }\n.directional-cursor svg { display: block; width: 20px; height: 22px; }\n@media (min-width: 1024px) and (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {\n html.has-directional-cursor, html.has-directional-cursor body, html.has-directional-cursor body * { cursor: none !important; }\n html.has-directional-cursor :is(a, button, [role=\"button\"], [onclick], .clickable, [data-clickable], input[type=\"button\"], input[type=\"submit\"], input[type=\"reset\"], label[for]),\n 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; }\n html.has-directional-cursor :is(input, textarea, select, [contenteditable=\"true\"]) { cursor: text !important; }\n}\n`;\n\r\nexport function DirectionalCursor() {\r\n const positionLayer = useRef<HTMLDivElement>(null);\r\n const directionLayer = useRef<HTMLDivElement>(null);\r\n\r\n useEffect(() => {\r\n const position = positionLayer.current;\r\n const direction = directionLayer.current;\r\n if (!position || !direction) return;\r\n\r\n const media = window.matchMedia(DESKTOP_CURSOR_QUERY);\r\n let active = false;\r\n let frame = 0;\r\n let moveFrame = 0;\r\n let scaleTimer = 0;\r\n let latestEvent: MouseEvent | null = null;\r\n let currentX = window.innerWidth / 2;\r\n let currentY = -60;\r\n let targetX = currentX;\r\n let targetY = currentY;\r\n let currentAngle = 0;\r\n let targetAngle = 0;\r\n let hasAngle = false;\r\n let currentScale = 1;\r\n let targetScale = 1;\r\n let lastX = currentX;\r\n let lastY = 0;\r\n\r\n const render = () => {\r\n currentX += (targetX - currentX) * 0.4;\r\n currentY += (targetY - currentY) * 0.4;\r\n const angleDelta = ((targetAngle - currentAngle + 540) % 360) - 180;\r\n currentAngle += angleDelta * 0.24;\r\n currentScale += (targetScale - currentScale) * 0.24;\r\n\r\n position.style.transform = `translate3d(${currentX}px, ${currentY}px, 0)`;\r\n direction.style.transform = `translate(-50%, -50%) rotate(${currentAngle}deg) scale(${currentScale})`;\r\n\r\n const unsettled = Math.abs(targetX - currentX) > 0.08\r\n || Math.abs(targetY - currentY) > 0.08\r\n || Math.abs(angleDelta) > 0.08\r\n || Math.abs(targetScale - currentScale) > 0.002;\r\n frame = unsettled ? window.requestAnimationFrame(render) : 0;\r\n };\r\n\r\n const requestRender = () => {\r\n if (!frame) frame = window.requestAnimationFrame(render);\r\n };\r\n\r\n const processMove = () => {\r\n moveFrame = 0;\r\n const event = latestEvent;\r\n if (!event) return;\r\n const deltaX = event.clientX - lastX;\r\n const deltaY = event.clientY - lastY;\r\n const distance = Math.hypot(deltaX, deltaY);\r\n targetX = event.clientX;\r\n targetY = event.clientY;\r\n position.classList.add(\"is-visible\");\r\n\r\n if (distance > 1.25) {\r\n const rawAngle = Math.atan2(deltaY, deltaX) * (180 / Math.PI) + 90;\r\n const normalizedAngle = (rawAngle % 360 + 360) % 360;\r\n if (!hasAngle) {\r\n targetAngle = normalizedAngle;\r\n currentAngle = normalizedAngle;\r\n hasAngle = true;\r\n } else {\r\n targetAngle = normalizedAngle;\r\n }\r\n\r\n targetScale = 0.92;\r\n window.clearTimeout(scaleTimer);\r\n scaleTimer = window.setTimeout(() => {\r\n targetScale = 1;\r\n requestRender();\r\n }, 130);\r\n }\r\n\r\n lastX = event.clientX;\r\n lastY = event.clientY;\r\n requestRender();\r\n };\r\n\r\n const handleMouseMove = (event: MouseEvent) => {\r\n latestEvent = event;\r\n if (!moveFrame) moveFrame = window.requestAnimationFrame(processMove);\r\n };\r\n\r\n const activate = () => {\r\n if (active) return;\r\n active = true;\r\n document.documentElement.classList.add(\"has-directional-cursor\");\r\n window.addEventListener(\"mousemove\", handleMouseMove, { passive: true });\r\n };\r\n\r\n const deactivate = () => {\r\n if (!active) return;\r\n active = false;\r\n document.documentElement.classList.remove(\"has-directional-cursor\");\r\n position.classList.remove(\"is-visible\");\r\n window.removeEventListener(\"mousemove\", handleMouseMove);\r\n window.cancelAnimationFrame(frame);\r\n window.cancelAnimationFrame(moveFrame);\r\n window.clearTimeout(scaleTimer);\r\n frame = 0;\r\n moveFrame = 0;\r\n };\r\n\r\n const sync = () => {\r\n if (media.matches) activate();\r\n else deactivate();\r\n };\r\n media.addEventListener(\"change\", sync);\r\n sync();\r\n\r\n return () => {\r\n media.removeEventListener(\"change\", sync);\r\n deactivate();\r\n };\r\n }, []);\r\n\r\n return (\n <><style>{CURSOR_STYLES}</style><div ref={positionLayer} className=\"directional-cursor\" aria-hidden=\"true\">\n <div ref={directionLayer} className=\"directional-cursor-shape\">\r\n <svg width=\"50\" height=\"54\" viewBox=\"0 0 50 54\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <g filter=\"url(#walros-cursor-shadow)\">\r\n <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\" />\r\n <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\" />\r\n </g>\r\n <defs>\r\n <filter id=\"walros-cursor-shadow\" x=\"0.602397\" y=\"0.952444\" width=\"49.0584\" height=\"52.428\" filterUnits=\"userSpaceOnUse\" colorInterpolationFilters=\"sRGB\">\r\n <feFlood floodOpacity=\"0\" result=\"BackgroundImageFix\" />\r\n <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\" />\r\n <feOffset dy=\"2.25825\" />\r\n <feGaussianBlur stdDeviation=\"2.25825\" />\r\n <feComposite in2=\"hardAlpha\" operator=\"out\" />\r\n <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\" />\r\n <feBlend mode=\"normal\" in2=\"BackgroundImageFix\" result=\"effect1_dropShadow\" />\r\n <feBlend mode=\"normal\" in=\"SourceGraphic\" in2=\"effect1_dropShadow\" result=\"shape\" />\r\n </filter>\r\n </defs>\r\n </svg>\r\n </div>\r\n </div></>\n );\n}\n","import type { ImgHTMLAttributes } from \"react\";\nimport { walrosLogoChromeUrl } from \"../assets\";\n\nexport type WalrosLogoProps = Omit<\n ImgHTMLAttributes<HTMLImageElement>,\n \"src\"\n>;\n\nexport function WalrosLogo({\n alt = \"WalrOS\",\n draggable = false,\n ...props\n}: WalrosLogoProps) {\n return (\n <img\n src={walrosLogoChromeUrl}\n alt={alt}\n draggable={draggable}\n {...props}\n />\n );\n}\n\nexport default WalrosLogo;\n","import type { ImgHTMLAttributes } from \"react\";\nimport {\n walrosWordmarkDarkUrl,\n walrosWordmarkLightUrl,\n} from \"../assets\";\n\nexport type WalrosWordmarkProps = Omit<\n ImgHTMLAttributes<HTMLImageElement>,\n \"src\"\n> & {\n variant?: \"light\" | \"dark\";\n};\n\nexport function WalrosWordmark({\n variant = \"light\",\n alt = \"WalrOS\",\n draggable = false,\n ...props\n}: WalrosWordmarkProps) {\n const src =\n variant === \"dark\"\n ? walrosWordmarkDarkUrl\n : walrosWordmarkLightUrl;\n\n return (\n <img\n src={src}\n alt={alt}\n draggable={draggable}\n {...props}\n />\n );\n}\n\nexport default WalrosWordmark;\n","import {\n useCallback,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport type { RefObject } from \"react\";\nimport { walrosThemeGlitchSoundUrl } from \"../assets\";\n\nexport type WalrosTheme = \"light\" | \"dark\";\nexport type WalrosThemeMode = \"body\" | \"viewport\";\n\nexport type WalrosThemeShakeTarget =\n | HTMLElement\n | RefObject<HTMLElement | null>\n | null\n | undefined;\n\nexport type UseWalrosThemeOptions = {\n storageKey?: string;\n defaultTheme?: WalrosTheme;\n useSystemPreference?: boolean;\n swapDelay?: number;\n totalDuration?: number;\n /** Set to false to disable audio, or provide a custom sound URL. */\n soundUrl?: string | false;\n /** Playback volume from 0 to 1. Defaults to the WalrOS site mix. */\n soundVolume?: number;\n applyTheme?: (theme: WalrosTheme) => void;\n\n /**\n * `body` reproduce el comportamiento original de WalrOS Forum.\n * `viewport` bloquea el scroll y sacude solo los elementos indicados,\n * recomendado para parallax, sticky y GSAP ScrollTrigger.\n */\n mode?: WalrosThemeMode;\n\n /** Elementos que recibirán el shake cuando mode=\"viewport\". */\n shakeTargets?: readonly WalrosThemeShakeTarget[];\n\n /**\n * En modo viewport se activa por defecto. Mantiene scrollX/scrollY estables\n * con requestAnimationFrame sin usar position: fixed en el body.\n */\n lockScroll?: boolean;\n\n /** Se ejecuta después de restaurar el scroll; útil para ScrollTrigger.update(). */\n onAfterUnlock?: () => void;\n};\n\nexport type UseWalrosThemeResult = {\n theme: WalrosTheme;\n isDark: boolean;\n mounted: boolean;\n glitching: boolean;\n toggleTheme: () => void;\n setTheme: (theme: WalrosTheme) => void;\n};\n\ntype ViewportLockState = {\n scrollX: number;\n scrollY: number;\n rafId: number;\n active: boolean;\n bodyOverflow: string;\n htmlOverflow: string;\n htmlOverscrollBehavior: string;\n};\n\nconst GLITCH_BASE_CLASS = \"walros-theme-glitch-page\";\nconst GLITCH_BODY_CLASS = \"walros-theme-glitch-page--body\";\nconst GLITCH_VIEWPORT_CLASS = \"walros-theme-glitch-page--viewport\";\nconst GLITCH_LOCK_CLASS = \"walros-theme-glitch-lock\";\n\nfunction defaultApplyTheme(theme: WalrosTheme) {\n if (typeof document === \"undefined\") return;\n\n const root = document.documentElement;\n root.classList.toggle(\"dark\", theme === \"dark\");\n root.style.colorScheme = theme;\n}\n\nfunction readInitialTheme(\n storageKey: string,\n defaultTheme: WalrosTheme,\n useSystemPreference: boolean,\n): WalrosTheme {\n if (typeof window === \"undefined\") return defaultTheme;\n\n try {\n const stored = window.localStorage.getItem(storageKey);\n if (stored === \"light\" || stored === \"dark\") return stored;\n } catch {\n // localStorage puede estar bloqueado en modo privado.\n }\n\n if (\n useSystemPreference &&\n window.matchMedia?.(\"(prefers-color-scheme: dark)\").matches\n ) {\n return \"dark\";\n }\n\n return defaultTheme;\n}\n\nfunction resolveShakeTargets(\n targets: readonly WalrosThemeShakeTarget[],\n): HTMLElement[] {\n const resolved = new Set<HTMLElement>();\n\n for (const target of targets) {\n if (!target) continue;\n\n const element =\n typeof target === \"object\" && \"current\" in target\n ? target.current\n : target;\n\n if (element) resolved.add(element);\n }\n\n return [...resolved];\n}\n\nexport function useWalrosTheme({\n storageKey = \"walros-theme\",\n defaultTheme = \"light\",\n useSystemPreference = false,\n swapDelay = 610,\n totalDuration = 1500,\n soundUrl = walrosThemeGlitchSoundUrl,\n soundVolume = 0.52,\n applyTheme = defaultApplyTheme,\n mode = \"body\",\n shakeTargets = [],\n lockScroll,\n onAfterUnlock,\n}: UseWalrosThemeOptions = {}): UseWalrosThemeResult {\n const [theme, setThemeState] = useState<WalrosTheme>(() =>\n readInitialTheme(storageKey, defaultTheme, useSystemPreference),\n );\n const [mounted, setMounted] = useState(false);\n const [glitching, setGlitching] = useState(false);\n\n const themeRef = useRef(theme);\n const glitchingRef = useRef(false);\n const swapTimerRef = useRef<number | null>(null);\n const cleanupTimerRef = useRef<number | null>(null);\n const applyThemeRef = useRef(applyTheme);\n const modeRef = useRef(mode);\n const shakeTargetsRef = useRef(shakeTargets);\n const lockScrollRef = useRef(lockScroll);\n const onAfterUnlockRef = useRef(onAfterUnlock);\n const activeTargetsRef = useRef<HTMLElement[]>([]);\n const viewportLockRef = useRef<ViewportLockState | null>(null);\n const soundRef = useRef<HTMLAudioElement | null>(null);\n const soundUrlRef = useRef(soundUrl);\n const soundVolumeRef = useRef(soundVolume);\n\n themeRef.current = theme;\n applyThemeRef.current = applyTheme;\n modeRef.current = mode;\n shakeTargetsRef.current = shakeTargets;\n lockScrollRef.current = lockScroll;\n onAfterUnlockRef.current = onAfterUnlock;\n soundUrlRef.current = soundUrl;\n soundVolumeRef.current = soundVolume;\n\n const playThemeSound = useCallback(() => {\n if (typeof window === \"undefined\" || !soundUrlRef.current) return;\n\n try {\n if (!soundRef.current || soundRef.current.src !== new URL(soundUrlRef.current, document.baseURI).href) {\n soundRef.current?.pause();\n soundRef.current = new Audio(soundUrlRef.current);\n soundRef.current.preload = \"auto\";\n }\n const audio = soundRef.current;\n audio.volume = Math.max(0, Math.min(1, soundVolumeRef.current));\n audio.currentTime = 0;\n void audio.play().catch(() => {\n // Browsers may block sound; the theme animation still continues.\n });\n } catch {\n // Audio support is optional and must not block the theme change.\n }\n }, []);\n\n const persistTheme = useCallback(\n (nextTheme: WalrosTheme) => {\n applyThemeRef.current(nextTheme);\n setThemeState(nextTheme);\n themeRef.current = nextTheme;\n\n try {\n window.localStorage.setItem(storageKey, nextTheme);\n } catch {\n // El cambio debe funcionar aunque localStorage falle.\n }\n },\n [storageKey],\n );\n\n useEffect(() => {\n const initialTheme = readInitialTheme(\n storageKey,\n defaultTheme,\n useSystemPreference,\n );\n\n themeRef.current = initialTheme;\n setThemeState(initialTheme);\n applyThemeRef.current(initialTheme);\n setMounted(true);\n }, [defaultTheme, storageKey, useSystemPreference]);\n\n const clearTimers = useCallback(() => {\n if (swapTimerRef.current !== null) {\n window.clearTimeout(swapTimerRef.current);\n swapTimerRef.current = null;\n }\n\n if (cleanupTimerRef.current !== null) {\n window.clearTimeout(cleanupTimerRef.current);\n cleanupTimerRef.current = null;\n }\n }, []);\n\n const lockViewport = useCallback(() => {\n if (\n typeof window === \"undefined\" ||\n typeof document === \"undefined\" ||\n viewportLockRef.current\n ) {\n return;\n }\n\n const body = document.body;\n const html = document.documentElement;\n const lockState: ViewportLockState = {\n scrollX: window.scrollX,\n scrollY: window.scrollY,\n rafId: 0,\n active: true,\n bodyOverflow: body.style.overflow,\n htmlOverflow: html.style.overflow,\n htmlOverscrollBehavior: html.style.overscrollBehavior,\n };\n\n viewportLockRef.current = lockState;\n\n const keepScrollStable = () => {\n if (!lockState.active) return;\n window.scrollTo(lockState.scrollX, lockState.scrollY);\n lockState.rafId = window.requestAnimationFrame(keepScrollStable);\n };\n\n html.classList.add(GLITCH_LOCK_CLASS);\n html.style.overflow = \"hidden\";\n html.style.overscrollBehavior = \"none\";\n body.style.overflow = \"hidden\";\n lockState.rafId = window.requestAnimationFrame(keepScrollStable);\n }, []);\n\n const unlockViewport = useCallback((runCallback: boolean) => {\n if (typeof window === \"undefined\" || typeof document === \"undefined\") {\n return;\n }\n\n const lockState = viewportLockRef.current;\n if (!lockState) return;\n\n lockState.active = false;\n window.cancelAnimationFrame(lockState.rafId);\n\n const body = document.body;\n const html = document.documentElement;\n body.style.overflow = lockState.bodyOverflow;\n html.style.overflow = lockState.htmlOverflow;\n html.style.overscrollBehavior = lockState.htmlOverscrollBehavior;\n html.classList.remove(GLITCH_LOCK_CLASS);\n\n viewportLockRef.current = null;\n window.scrollTo(lockState.scrollX, lockState.scrollY);\n\n if (runCallback) {\n window.requestAnimationFrame(() => {\n onAfterUnlockRef.current?.();\n });\n }\n }, []);\n\n const removeShakeClasses = useCallback(() => {\n for (const target of activeTargetsRef.current) {\n target.classList.remove(\n GLITCH_BASE_CLASS,\n GLITCH_BODY_CLASS,\n GLITCH_VIEWPORT_CLASS,\n );\n target.style.removeProperty(\"--walros-glitch-origin-y\");\n }\n\n activeTargetsRef.current = [];\n }, []);\n\n const finishGlitch = useCallback(() => {\n if (soundRef.current) {\n soundRef.current.pause();\n soundRef.current.currentTime = 0;\n }\n removeShakeClasses();\n unlockViewport(true);\n glitchingRef.current = false;\n setGlitching(false);\n }, [removeShakeClasses, unlockViewport]);\n\n const setTheme = useCallback(\n (nextTheme: WalrosTheme) => {\n if (glitchingRef.current) return;\n persistTheme(nextTheme);\n },\n [persistTheme],\n );\n\n const toggleTheme = useCallback(() => {\n if (\n typeof window === \"undefined\" ||\n typeof document === \"undefined\" ||\n glitchingRef.current\n ) {\n return;\n }\n\n playThemeSound();\n\n const currentMode = modeRef.current;\n const shouldLockScroll =\n lockScrollRef.current ?? currentMode === \"viewport\";\n\n if (currentMode === \"viewport\" && shouldLockScroll) {\n lockViewport();\n }\n\n const targets =\n currentMode === \"body\"\n ? [document.body]\n : resolveShakeTargets(shakeTargetsRef.current);\n\n const modeClass =\n currentMode === \"body\"\n ? GLITCH_BODY_CLASS\n : GLITCH_VIEWPORT_CLASS;\n\n for (const target of targets) {\n target.style.setProperty(\n \"--walros-glitch-origin-y\",\n currentMode === \"body\"\n ? `${window.scrollY + window.innerHeight / 2}px`\n : \"50%\",\n );\n target.classList.add(GLITCH_BASE_CLASS, modeClass);\n }\n\n activeTargetsRef.current = targets;\n glitchingRef.current = true;\n setGlitching(true);\n\n const reducedMotion = window.matchMedia?.(\n \"(prefers-reduced-motion: reduce)\",\n ).matches;\n\n const nextTheme: WalrosTheme =\n themeRef.current === \"dark\" ? \"light\" : \"dark\";\n\n const effectiveSwapDelay = reducedMotion\n ? 75\n : Math.max(0, swapDelay);\n const effectiveDuration = reducedMotion\n ? 150\n : Math.max(effectiveSwapDelay, totalDuration);\n\n swapTimerRef.current = window.setTimeout(() => {\n persistTheme(nextTheme);\n swapTimerRef.current = null;\n }, effectiveSwapDelay);\n\n cleanupTimerRef.current = window.setTimeout(() => {\n cleanupTimerRef.current = null;\n finishGlitch();\n }, effectiveDuration);\n }, [finishGlitch, lockViewport, persistTheme, playThemeSound, swapDelay, totalDuration]);\n\n useEffect(() => {\n return () => {\n clearTimers();\n removeShakeClasses();\n unlockViewport(false);\n soundRef.current?.pause();\n if (soundRef.current) soundRef.current.currentTime = 0;\n soundRef.current = null;\n };\n }, [clearTimers, removeShakeClasses, unlockViewport]);\n\n return {\n theme,\n isDark: theme === \"dark\",\n mounted,\n glitching,\n toggleTheme,\n setTheme,\n };\n}\n\nexport default useWalrosTheme;\n"],"mappings":"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","names":["useState","useLayoutEffect","useState","jsx","VISIBLE_LEFT","VISIBLE_RIGHT","VISIBLE_TOP","VISIBLE_BOTTOM","useState","createPortal","jsx","jsxs","jsx","createPortal","useEffect","useRef","Fragment","jsx","jsxs","jsx","jsx","useEffect","useRef","useState","useState","useRef","useEffect"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@walrosproject/ui",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "Componentes, transiciones y recursos visuales oficiales del ecosistema WalrOS.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",