Source identity
| Field | Recorded value |
|---|---|
| Source type | GitHub source |
| Original record | Janady13/thatdeveloperguy-website / app/experience/ItServicesSceneShell.tsx |
| Date | Not specified in source |
| Repository | Janady13/thatdeveloperguy-website |
| Revision | 2bea2ebdff0e34494bff597d4fa9c8422a0c3a94 |
| Branch | main |
| Path or archive member | app/experience/ItServicesSceneShell.tsx |
| Original SHA-256 | 600557311329d6cb5fa5df1acec06ca040fc323ad073c3e7d81045493be634da |
| Git blob SHA | ddcce78dce250ce90a81f21533dfa9762e16fe56 |
| Reading-copy SHA-256 | 600557311329d6cb5fa5df1acec06ca040fc323ad073c3e7d81045493be634da |
Recovered source transcript
Download complete source text ↓109 lines · 4.2 KB
import { lazy, Suspense, useEffect, useState, type CSSProperties } from 'react';
import type { CompiledPage } from '../../src/contracts/page';
import type { SceneRecord } from '../../src/contracts/scene';
import { HotspotOverlay } from './HotspotOverlay';
import { ItServicesEnvironment } from './ItServicesEnvironment';
import { useMotionPreference } from './MotionPreferenceControl';
import { probeRenderer } from './renderer-capability';
import { sceneAspect } from './scene-coordinate-map';
import { useSceneNavigation } from './useSceneNavigation';
import '../styles/it-services-rive.css';
const ItServicesRiveCanvas = lazy(() => import('./ItServicesRiveCanvas.client'));
const ROUTE_TRANSITION_MS = 760;
/** Dedicated full-viewport IT Services room, isolated from the concurrently authored lobby shell. */
export function ItServicesSceneShell({ scene, page }: { scene: SceneRecord; page: CompiledPage }) {
const [mounted, setMounted] = useState(false);
const [renderer, setRenderer] = useState('pending');
const [nativeReady, setNativeReady] = useState(false);
const [nativeFailed, setNativeFailed] = useState(false);
const [focus, setFocus] = useState<string | null>(null);
const [motion] = useMotionPreference();
const [pointer, setPointer] = useState({ x: 0.5, y: 0.5, active: false });
useEffect(() => {
setMounted(true);
const verdict = probeRenderer();
setRenderer(verdict.ok ? verdict.renderer : verdict.reason);
}, []);
const { hotspots, activate, leaving, leavingTarget } = useSceneNavigation({
hotspots: scene.hotspots,
pageId: page.id,
motion,
transitionMs: ROUTE_TRANSITION_MS,
onRouteStart: hotspot => setFocus(hotspot.id),
});
const hardware = mounted && !/^no |^software/i.test(renderer) && renderer !== 'pending';
const showNative = Boolean(hardware && motion && scene.rive && !nativeFailed);
const planeStyle = {
aspectRatio: sceneAspect(scene.canvas),
'--scene-w': scene.canvas.width,
'--scene-h': scene.canvas.height,
'--pointer-x': pointer.x,
'--pointer-y': pointer.y,
} as CSSProperties;
return (
<section
className={`scene scene-it-services${nativeReady ? ' scene-live scene-native-ready' : ''}${leaving ? ' scene-leaving' : ''}`}
aria-label={`${page.heading} room`}
data-scene="it-services"
data-focus={focus ?? ''}
data-motion={motion ? 'on' : 'reduced'}
data-renderer={renderer}
data-native={nativeReady ? 'ready' : nativeFailed ? 'failed' : showNative ? 'loading' : 'fallback'}
data-leaving-target={leavingTarget ?? ''}
onPointerMove={event => {
const rect = event.currentTarget.getBoundingClientRect();
setPointer({
x: Math.max(0, Math.min(1, (event.clientX - rect.left) / rect.width)),
y: Math.max(0, Math.min(1, (event.clientY - rect.top) / rect.height)),
active: true,
});
}}
onPointerLeave={() => setPointer(current => ({ ...current, active: false }))}
>
<div className="scene-plane" style={planeStyle}>
<img
className="scene-poster"
src={scene.poster}
alt={scene.posterAlt}
width={scene.canvas.width}
height={scene.canvas.height}
decoding="async"
fetchPriority="high"
{...({ elementtiming: 'it-services-poster' } as Record<string, string>)}
/>
{showNative && (
<Suspense fallback={null}>
<ItServicesRiveCanvas
asset={scene.rive!}
focus={focus}
onReady={() => setNativeReady(true)}
onError={() => { setNativeFailed(true); setNativeReady(false); }}
/>
</Suspense>
)}
{!nativeReady && (
<ItServicesEnvironment
focus={focus}
motion={motion}
pointer={pointer}
sceneState={!motion ? 'paused' : leaving ? 'transition' : focus ? 'focus' : 'idle'}
/>
)}
<HotspotOverlay
label={page.heading}
canvas={scene.canvas}
hotspots={hotspots}
onFocus={id => { if (!leaving) setFocus(id); }}
onActivate={activate}
/>
</div>
</section>
);
}