paperlab 0.5.0 → 0.5.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 +4 -2
- package/dist/{chunk-6IADJZX5.js → chunk-HRXQTJFS.js} +45 -28
- package/dist/chunk-HRXQTJFS.js.map +1 -0
- package/dist/index.cjs +107 -90
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/stage.cjs +254 -231
- package/dist/stage.cjs.map +1 -1
- package/dist/stage.js +13 -5
- package/dist/stage.js.map +1 -1
- package/package.json +3 -3
- package/dist/chunk-6IADJZX5.js.map +0 -1
package/dist/stage.cjs
CHANGED
|
@@ -52,8 +52,8 @@ module.exports = __toCommonJS(stage_exports);
|
|
|
52
52
|
|
|
53
53
|
// src/stage/PaperStage.tsx
|
|
54
54
|
var THREE22 = __toESM(require("three"), 1);
|
|
55
|
-
var
|
|
56
|
-
var
|
|
55
|
+
var import_fiber11 = require("@react-three/fiber");
|
|
56
|
+
var import_react24 = require("react");
|
|
57
57
|
var import_zod29 = require("zod");
|
|
58
58
|
|
|
59
59
|
// src/a11y/index.tsx
|
|
@@ -275,8 +275,8 @@ function contentText(config) {
|
|
|
275
275
|
// src/PaperField.tsx
|
|
276
276
|
var THREE16 = __toESM(require("three"), 1);
|
|
277
277
|
var import_gsap5 = require("gsap");
|
|
278
|
-
var
|
|
279
|
-
var
|
|
278
|
+
var import_fiber7 = require("@react-three/fiber");
|
|
279
|
+
var import_react17 = require("react");
|
|
280
280
|
|
|
281
281
|
// src/config/schema.ts
|
|
282
282
|
var import_zod14 = require("zod");
|
|
@@ -2110,9 +2110,24 @@ function paintBackdrop(backdrop, width, height, image) {
|
|
|
2110
2110
|
return texture;
|
|
2111
2111
|
}
|
|
2112
2112
|
|
|
2113
|
+
// src/scene/release.tsx
|
|
2114
|
+
var import_fiber3 = require("@react-three/fiber");
|
|
2115
|
+
var import_react4 = require("react");
|
|
2116
|
+
function ReleaseContextOnUnmount() {
|
|
2117
|
+
const gl = (0, import_fiber3.useThree)((s) => s.gl);
|
|
2118
|
+
(0, import_react4.useEffect)(
|
|
2119
|
+
() => () => {
|
|
2120
|
+
gl.forceContextLoss();
|
|
2121
|
+
gl.dispose();
|
|
2122
|
+
},
|
|
2123
|
+
[gl]
|
|
2124
|
+
);
|
|
2125
|
+
return null;
|
|
2126
|
+
}
|
|
2127
|
+
|
|
2113
2128
|
// src/field/dropZones.tsx
|
|
2114
2129
|
var THREE4 = __toESM(require("three"), 1);
|
|
2115
|
-
var
|
|
2130
|
+
var import_react5 = require("react");
|
|
2116
2131
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
2117
2132
|
var DropZoneRegistry = class {
|
|
2118
2133
|
zones = /* @__PURE__ */ new Map();
|
|
@@ -2151,7 +2166,7 @@ var DropZoneRegistry = class {
|
|
|
2151
2166
|
for (const fn of this.listeners) fn();
|
|
2152
2167
|
}
|
|
2153
2168
|
};
|
|
2154
|
-
var DropZoneContext = (0,
|
|
2169
|
+
var DropZoneContext = (0, import_react5.createContext)(null);
|
|
2155
2170
|
var globCache = /* @__PURE__ */ new Map();
|
|
2156
2171
|
var globRegExp = (glob) => {
|
|
2157
2172
|
let re = globCache.get(glob);
|
|
@@ -2167,17 +2182,17 @@ function zoneAccepts(zone, name) {
|
|
|
2167
2182
|
}
|
|
2168
2183
|
var zoneContains = (zone, x, y) => Math.abs(x - zone.bounds.position[0]) <= zone.bounds.size[0] / 2 && Math.abs(y - zone.bounds.position[1]) <= zone.bounds.size[1] / 2;
|
|
2169
2184
|
function DropZoneVisual({ registry: registry4, config }) {
|
|
2170
|
-
(0,
|
|
2185
|
+
(0, import_react5.useSyncExternalStore)(registry4.subscribe, registry4.getVersion, registry4.getVersion);
|
|
2171
2186
|
const hovered = registry4.hovered === config.id;
|
|
2172
2187
|
const style = config.highlight ?? "glow";
|
|
2173
2188
|
const [w, h] = config.bounds.size;
|
|
2174
|
-
const edges = (0,
|
|
2189
|
+
const edges = (0, import_react5.useMemo)(() => {
|
|
2175
2190
|
const plane = new THREE4.PlaneGeometry(w, h);
|
|
2176
2191
|
const geo = new THREE4.EdgesGeometry(plane);
|
|
2177
2192
|
plane.dispose();
|
|
2178
2193
|
return geo;
|
|
2179
2194
|
}, [w, h]);
|
|
2180
|
-
(0,
|
|
2195
|
+
(0, import_react5.useEffect)(() => () => edges.dispose(), [edges]);
|
|
2181
2196
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("group", { position: config.bounds.position, children: [
|
|
2182
2197
|
style !== "outline" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("mesh", { children: [
|
|
2183
2198
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("planeGeometry", { args: [w, h] }),
|
|
@@ -2198,8 +2213,8 @@ function DropZoneVisual({ registry: registry4, config }) {
|
|
|
2198
2213
|
// src/PaperMesh.tsx
|
|
2199
2214
|
var THREE11 = __toESM(require("three"), 1);
|
|
2200
2215
|
var import_gsap2 = require("gsap");
|
|
2201
|
-
var
|
|
2202
|
-
var
|
|
2216
|
+
var import_fiber4 = require("@react-three/fiber");
|
|
2217
|
+
var import_react11 = require("react");
|
|
2203
2218
|
|
|
2204
2219
|
// src/config/serialize.ts
|
|
2205
2220
|
function parsePreset(input) {
|
|
@@ -2262,9 +2277,9 @@ function computeSheetNormals(geometry) {
|
|
|
2262
2277
|
}
|
|
2263
2278
|
|
|
2264
2279
|
// src/core/stable.ts
|
|
2265
|
-
var
|
|
2280
|
+
var import_react6 = require("react");
|
|
2266
2281
|
function useStable(value) {
|
|
2267
|
-
const held = (0,
|
|
2282
|
+
const held = (0, import_react6.useRef)(value);
|
|
2268
2283
|
if (!deepEqual(held.current, value)) held.current = value;
|
|
2269
2284
|
return held.current;
|
|
2270
2285
|
}
|
|
@@ -2580,7 +2595,7 @@ function listPresets() {
|
|
|
2580
2595
|
|
|
2581
2596
|
// src/content/texture.ts
|
|
2582
2597
|
var THREE6 = __toESM(require("three"), 1);
|
|
2583
|
-
var
|
|
2598
|
+
var import_react7 = require("react");
|
|
2584
2599
|
|
|
2585
2600
|
// src/content/type.ts
|
|
2586
2601
|
function wrapLines(ctx, text, maxWidth, font) {
|
|
@@ -2869,9 +2884,9 @@ function makeTexture(canvas) {
|
|
|
2869
2884
|
return tex;
|
|
2870
2885
|
}
|
|
2871
2886
|
function useContentTexture(content, sheet2, stock) {
|
|
2872
|
-
const [texture, setTexture] = (0,
|
|
2887
|
+
const [texture, setTexture] = (0, import_react7.useState)(null);
|
|
2873
2888
|
const key = JSON.stringify({ content: content ?? null, w: sheet2.width, h: sheet2.height, stock: stock.id });
|
|
2874
|
-
(0,
|
|
2889
|
+
(0, import_react7.useEffect)(() => {
|
|
2875
2890
|
let disposed = false;
|
|
2876
2891
|
let tex = null;
|
|
2877
2892
|
if (!content) {
|
|
@@ -3840,7 +3855,7 @@ var ClothSim = class {
|
|
|
3840
3855
|
|
|
3841
3856
|
// src/surface/PaperMaterial.tsx
|
|
3842
3857
|
var THREE10 = __toESM(require("three"), 1);
|
|
3843
|
-
var
|
|
3858
|
+
var import_react9 = require("react");
|
|
3844
3859
|
var import_three_custom_shader_material = __toESM(require("three-custom-shader-material"), 1);
|
|
3845
3860
|
|
|
3846
3861
|
// src/surface/compose.ts
|
|
@@ -4213,14 +4228,14 @@ function padPositions(positions) {
|
|
|
4213
4228
|
}
|
|
4214
4229
|
|
|
4215
4230
|
// src/scene/rig.tsx
|
|
4216
|
-
var
|
|
4231
|
+
var import_react8 = require("react");
|
|
4217
4232
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
4218
|
-
var LightRigContext = (0,
|
|
4233
|
+
var LightRigContext = (0, import_react8.createContext)(null);
|
|
4219
4234
|
function LightRig({ rig, children }) {
|
|
4220
4235
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(LightRigContext.Provider, { value: rig, children });
|
|
4221
4236
|
}
|
|
4222
4237
|
function useLightRig(own) {
|
|
4223
|
-
return (0,
|
|
4238
|
+
return (0, import_react8.useContext)(LightRigContext) ?? getLightingPreset(own);
|
|
4224
4239
|
}
|
|
4225
4240
|
|
|
4226
4241
|
// src/surface/PaperMaterial.tsx
|
|
@@ -4246,8 +4261,8 @@ function PaperMaterial({
|
|
|
4246
4261
|
sheet2,
|
|
4247
4262
|
rig
|
|
4248
4263
|
);
|
|
4249
|
-
const bound = (0,
|
|
4250
|
-
(0,
|
|
4264
|
+
const bound = (0, import_react9.useMemo)(() => composed.uniforms, [composed.structureKey]);
|
|
4265
|
+
(0, import_react9.useEffect)(() => {
|
|
4251
4266
|
for (const [key, uniform] of Object.entries(composed.uniforms)) {
|
|
4252
4267
|
if (!bound[key] || key === "uFrontMap" || key === "uBackMap") continue;
|
|
4253
4268
|
if (bound[key].value instanceof THREE10.Color && uniform.value instanceof THREE10.Color) {
|
|
@@ -4258,7 +4273,7 @@ function PaperMaterial({
|
|
|
4258
4273
|
}
|
|
4259
4274
|
}
|
|
4260
4275
|
});
|
|
4261
|
-
(0,
|
|
4276
|
+
(0, import_react9.useEffect)(() => {
|
|
4262
4277
|
if (bound.uFrontMap) bound.uFrontMap.value = texture;
|
|
4263
4278
|
if (bound.uBackMap) bound.uBackMap.value = backTexture ?? null;
|
|
4264
4279
|
}, [bound, texture, backTexture]);
|
|
@@ -4292,7 +4307,7 @@ function quantizeProgress(p, duration, fps = ON_TWOS_FPS) {
|
|
|
4292
4307
|
}
|
|
4293
4308
|
|
|
4294
4309
|
// src/states/usePaperStates.ts
|
|
4295
|
-
var
|
|
4310
|
+
var import_react10 = require("react");
|
|
4296
4311
|
|
|
4297
4312
|
// src/states/machine.ts
|
|
4298
4313
|
var import_gsap = require("gsap");
|
|
@@ -4519,15 +4534,15 @@ var PaperStateMachine = class {
|
|
|
4519
4534
|
// src/states/usePaperStates.ts
|
|
4520
4535
|
function usePaperStates(config, enabled, instant, onAction, onStateChange) {
|
|
4521
4536
|
const live = enabled && Boolean(config.states);
|
|
4522
|
-
const key = (0,
|
|
4523
|
-
const onActionRef = (0,
|
|
4537
|
+
const key = (0, import_react10.useMemo)(() => JSON.stringify(config), [config]);
|
|
4538
|
+
const onActionRef = (0, import_react10.useRef)(onAction);
|
|
4524
4539
|
onActionRef.current = onAction;
|
|
4525
|
-
const onStateChangeRef = (0,
|
|
4540
|
+
const onStateChangeRef = (0, import_react10.useRef)(onStateChange);
|
|
4526
4541
|
onStateChangeRef.current = onStateChange;
|
|
4527
|
-
const machineRef = (0,
|
|
4528
|
-
const lastStateRef = (0,
|
|
4529
|
-
const [animated, setAnimated] = (0,
|
|
4530
|
-
(0,
|
|
4542
|
+
const machineRef = (0, import_react10.useRef)(null);
|
|
4543
|
+
const lastStateRef = (0, import_react10.useRef)("rest");
|
|
4544
|
+
const [animated, setAnimated] = (0, import_react10.useState)(null);
|
|
4545
|
+
(0, import_react10.useEffect)(() => {
|
|
4531
4546
|
if (!live) {
|
|
4532
4547
|
machineRef.current?.dispose();
|
|
4533
4548
|
machineRef.current = null;
|
|
@@ -4554,7 +4569,7 @@ function usePaperStates(config, enabled, instant, onAction, onStateChange) {
|
|
|
4554
4569
|
lastStateRef.current = machine.state;
|
|
4555
4570
|
setAnimated({ config: machine.structuralConfig(), state: machine.state });
|
|
4556
4571
|
}, [key, live, instant]);
|
|
4557
|
-
(0,
|
|
4572
|
+
(0, import_react10.useEffect)(
|
|
4558
4573
|
() => () => {
|
|
4559
4574
|
machineRef.current?.dispose();
|
|
4560
4575
|
machineRef.current = null;
|
|
@@ -4586,7 +4601,7 @@ function configInputs(props) {
|
|
|
4586
4601
|
}
|
|
4587
4602
|
function useResolvedConfig(props) {
|
|
4588
4603
|
const inputs = useStable(configInputs(props));
|
|
4589
|
-
return (0,
|
|
4604
|
+
return (0, import_react11.useMemo)(() => resolveConfig(props), [inputs]);
|
|
4590
4605
|
}
|
|
4591
4606
|
function resolveConfig(props) {
|
|
4592
4607
|
const base = props.preset ? typeof props.preset === "string" ? getPreset(props.preset) : parsePreset(props.preset) : paperConfigSchema.parse({});
|
|
@@ -4610,7 +4625,7 @@ var planeNormal = new THREE11.Vector3();
|
|
|
4610
4625
|
var anchorScratch = new THREE11.Vector3();
|
|
4611
4626
|
var worldScratch = new THREE11.Vector3();
|
|
4612
4627
|
var quatScratch = new THREE11.Quaternion();
|
|
4613
|
-
var PaperMesh = (0,
|
|
4628
|
+
var PaperMesh = (0, import_react11.forwardRef)(function PaperMesh2(props, ref) {
|
|
4614
4629
|
const resolved = useResolvedConfig(props);
|
|
4615
4630
|
const reduced = usePrefersReducedMotion(props.reducedMotion);
|
|
4616
4631
|
const statesLive = Boolean(resolved.states) && props.stateTriggers !== false;
|
|
@@ -4620,33 +4635,33 @@ var PaperMesh = (0, import_react10.forwardRef)(function PaperMesh2(props, ref) {
|
|
|
4620
4635
|
state: machineState
|
|
4621
4636
|
} = usePaperStates(resolved, statesLive, reduced, props.onStateAction, props.onStateChange);
|
|
4622
4637
|
const behavior = config.behavior ? getBehavior(config.behavior.type) : null;
|
|
4623
|
-
const machineRef = (0,
|
|
4638
|
+
const machineRef = (0, import_react11.useRef)(null);
|
|
4624
4639
|
machineRef.current = machine;
|
|
4625
|
-
const resolvedRef = (0,
|
|
4640
|
+
const resolvedRef = (0, import_react11.useRef)(resolved);
|
|
4626
4641
|
resolvedRef.current = resolved;
|
|
4627
4642
|
const isCloth = !reduced && typeof config.physics === "object";
|
|
4628
4643
|
const idle = !reduced && typeof config.physics === "string" && config.physics !== "none" ? getIdlePreset(config.physics) : null;
|
|
4629
|
-
const meshRef = (0,
|
|
4630
|
-
const groupRef = (0,
|
|
4631
|
-
const handleRefs = (0,
|
|
4632
|
-
const overridesRef = (0,
|
|
4633
|
-
const dirtyRef = (0,
|
|
4634
|
-
const playingRef = (0,
|
|
4635
|
-
const tweenRef = (0,
|
|
4636
|
-
const draggingRef = (0,
|
|
4637
|
-
const configRef = (0,
|
|
4644
|
+
const meshRef = (0, import_react11.useRef)(null);
|
|
4645
|
+
const groupRef = (0, import_react11.useRef)(null);
|
|
4646
|
+
const handleRefs = (0, import_react11.useRef)([]);
|
|
4647
|
+
const overridesRef = (0, import_react11.useRef)({});
|
|
4648
|
+
const dirtyRef = (0, import_react11.useRef)(true);
|
|
4649
|
+
const playingRef = (0, import_react11.useRef)(false);
|
|
4650
|
+
const tweenRef = (0, import_react11.useRef)(null);
|
|
4651
|
+
const draggingRef = (0, import_react11.useRef)(null);
|
|
4652
|
+
const configRef = (0, import_react11.useRef)(config);
|
|
4638
4653
|
configRef.current = config;
|
|
4639
|
-
const controls = (0,
|
|
4640
|
-
const camera = (0,
|
|
4654
|
+
const controls = (0, import_fiber4.useThree)((s) => s.controls);
|
|
4655
|
+
const camera = (0, import_fiber4.useThree)((s) => s.camera);
|
|
4641
4656
|
const behaviorKey = JSON.stringify(config.behavior ?? null);
|
|
4642
4657
|
const deformersKey = JSON.stringify(config.deformers ?? null);
|
|
4643
4658
|
const sheetKey = JSON.stringify(config.sheet);
|
|
4644
4659
|
const physicsKey = JSON.stringify(config.physics);
|
|
4645
|
-
(0,
|
|
4660
|
+
(0, import_react11.useEffect)(() => {
|
|
4646
4661
|
if (!draggingRef.current && !playingRef.current) overridesRef.current = {};
|
|
4647
4662
|
dirtyRef.current = true;
|
|
4648
4663
|
}, [behaviorKey, deformersKey, sheetKey, physicsKey]);
|
|
4649
|
-
const { minSegments, autoSegments, animatedStack } = (0,
|
|
4664
|
+
const { minSegments, autoSegments, animatedStack } = (0, import_react11.useMemo)(() => {
|
|
4650
4665
|
const cfg = configRef.current;
|
|
4651
4666
|
const probe2 = buildStack(cfg, {});
|
|
4652
4667
|
if (!probe2) {
|
|
@@ -4675,18 +4690,18 @@ var PaperMesh = (0, import_react10.forwardRef)(function PaperMesh2(props, ref) {
|
|
|
4675
4690
|
animatedStack: animated
|
|
4676
4691
|
};
|
|
4677
4692
|
}, [behaviorKey, deformersKey, physicsKey]);
|
|
4678
|
-
const geometry = (0,
|
|
4693
|
+
const geometry = (0, import_react11.useMemo)(() => {
|
|
4679
4694
|
if (!isCloth) return createSheetGeometry(config.sheet, minSegments, autoSegments);
|
|
4680
4695
|
const [sx, sy] = resolveSegments(config.sheet, 2);
|
|
4681
4696
|
const capped = Math.min(Math.max(sx, sy), CLOTH_MAX_SEGMENTS);
|
|
4682
4697
|
return new THREE11.PlaneGeometry(config.sheet.width, config.sheet.height, capped, capped);
|
|
4683
4698
|
}, [sheetKey, minSegments, autoSegments, isCloth]);
|
|
4684
|
-
(0,
|
|
4685
|
-
const basePositions = (0,
|
|
4699
|
+
(0, import_react11.useEffect)(() => () => geometry.dispose(), [geometry]);
|
|
4700
|
+
const basePositions = (0, import_react11.useMemo)(
|
|
4686
4701
|
() => Float32Array.from(geometry.attributes.position.array),
|
|
4687
4702
|
[geometry]
|
|
4688
4703
|
);
|
|
4689
|
-
const sim = (0,
|
|
4704
|
+
const sim = (0, import_react11.useMemo)(() => {
|
|
4690
4705
|
if (!isCloth) return null;
|
|
4691
4706
|
const cloth = configRef.current.physics;
|
|
4692
4707
|
const cols = geometry.parameters.widthSegments + 1;
|
|
@@ -4739,7 +4754,7 @@ var PaperMesh = (0, import_react10.forwardRef)(function PaperMesh2(props, ref) {
|
|
|
4739
4754
|
playingRef.current = false;
|
|
4740
4755
|
tweenRef.current?.pause();
|
|
4741
4756
|
};
|
|
4742
|
-
(0,
|
|
4757
|
+
(0, import_react11.useEffect)(() => {
|
|
4743
4758
|
if (props.autoplay && !reduced) play();
|
|
4744
4759
|
return () => {
|
|
4745
4760
|
tweenRef.current?.kill();
|
|
@@ -4755,7 +4770,7 @@ var PaperMesh = (0, import_react10.forwardRef)(function PaperMesh2(props, ref) {
|
|
|
4755
4770
|
behavior: { ...cfg.behavior, ...overridesRef.current }
|
|
4756
4771
|
});
|
|
4757
4772
|
};
|
|
4758
|
-
(0,
|
|
4773
|
+
(0, import_react11.useImperativeHandle)(ref, () => ({
|
|
4759
4774
|
play,
|
|
4760
4775
|
pause,
|
|
4761
4776
|
get playing() {
|
|
@@ -4792,8 +4807,8 @@ var PaperMesh = (0, import_react10.forwardRef)(function PaperMesh2(props, ref) {
|
|
|
4792
4807
|
placeProgrammatic: () => machineRef.current?.placeProgrammatic() ?? false,
|
|
4793
4808
|
returnProgrammatic: () => machineRef.current?.returnProgrammatic() ?? false
|
|
4794
4809
|
}));
|
|
4795
|
-
const idlePose = (0,
|
|
4796
|
-
(0,
|
|
4810
|
+
const idlePose = (0, import_react11.useRef)({ position: [0, 0, 0], rotation: [0, 0, 0] });
|
|
4811
|
+
(0, import_fiber4.useFrame)(({ clock }, delta) => {
|
|
4797
4812
|
const cfg = liveConfig();
|
|
4798
4813
|
const now = reduced ? 0 : cfg.onTwos ? quantizeTime(clock.elapsedTime) : clock.elapsedTime;
|
|
4799
4814
|
const hasBehaviorTransform = Boolean(behavior?.transform && cfg.behavior);
|
|
@@ -4878,7 +4893,7 @@ var PaperMesh = (0, import_react10.forwardRef)(function PaperMesh2(props, ref) {
|
|
|
4878
4893
|
const p = overridesRef.current[behavior.progressParam];
|
|
4879
4894
|
if (typeof p === "number") props.onProgress?.(p);
|
|
4880
4895
|
};
|
|
4881
|
-
const grabAnchor = (0,
|
|
4896
|
+
const grabAnchor = (0, import_react11.useRef)(new THREE11.Vector3());
|
|
4882
4897
|
const clothDown = (e) => {
|
|
4883
4898
|
if (!isCloth || !sim || !props.interactive || !groupRef.current) return;
|
|
4884
4899
|
e.stopPropagation();
|
|
@@ -5094,22 +5109,22 @@ function resolveFieldSlotConfig(slot, fallback, index, layoutId, layoutOptions)
|
|
|
5094
5109
|
// src/field/fieldGroup.tsx
|
|
5095
5110
|
var THREE13 = __toESM(require("three"), 1);
|
|
5096
5111
|
var import_gsap3 = require("gsap");
|
|
5097
|
-
var
|
|
5098
|
-
var
|
|
5112
|
+
var import_fiber5 = require("@react-three/fiber");
|
|
5113
|
+
var import_react13 = require("react");
|
|
5099
5114
|
var import_three_custom_shader_material2 = __toESM(require("three-custom-shader-material"), 1);
|
|
5100
5115
|
|
|
5101
5116
|
// src/content/atlas.ts
|
|
5102
5117
|
var THREE12 = __toESM(require("three"), 1);
|
|
5103
|
-
var
|
|
5118
|
+
var import_react12 = require("react");
|
|
5104
5119
|
var MAX_ATLAS = 4096;
|
|
5105
5120
|
function atlasGrid(count, aspect = 1) {
|
|
5106
5121
|
const cols = Math.max(1, Math.min(count, Math.ceil(Math.sqrt(count * Math.max(aspect, 0.01)))));
|
|
5107
5122
|
return { cols, rows: Math.max(1, Math.ceil(count / cols)) };
|
|
5108
5123
|
}
|
|
5109
5124
|
function useContentAtlas(contents, sheet2, stock) {
|
|
5110
|
-
const [atlas, setAtlas] = (0,
|
|
5125
|
+
const [atlas, setAtlas] = (0, import_react12.useState)(null);
|
|
5111
5126
|
const stableContents = useStable(contents);
|
|
5112
|
-
(0,
|
|
5127
|
+
(0, import_react12.useEffect)(() => {
|
|
5113
5128
|
let disposed = false;
|
|
5114
5129
|
const aspect = sheet2.height / sheet2.width;
|
|
5115
5130
|
const { cols, rows } = atlasGrid(contents.length, aspect);
|
|
@@ -5839,11 +5854,11 @@ function FieldGroup({
|
|
|
5839
5854
|
const stock = getStock(config.stock);
|
|
5840
5855
|
const rig = useLightRig(config.scene.lighting);
|
|
5841
5856
|
const behavior = config.behavior && !config.deformers ? getBehavior(config.behavior.type) : null;
|
|
5842
|
-
const progressRef = (0,
|
|
5857
|
+
const progressRef = (0, import_react13.useRef)(
|
|
5843
5858
|
behavior ? config.behavior[behavior.progressParam] : 0
|
|
5844
5859
|
);
|
|
5845
5860
|
const buildStackAt = (progress) => fieldShapeStack(config, progress);
|
|
5846
|
-
const initialStack = (0,
|
|
5861
|
+
const initialStack = (0, import_react13.useMemo)(
|
|
5847
5862
|
() => buildStackAt(progressRef.current),
|
|
5848
5863
|
[
|
|
5849
5864
|
JSON.stringify(config.behavior ?? null),
|
|
@@ -5852,7 +5867,7 @@ function FieldGroup({
|
|
|
5852
5867
|
]
|
|
5853
5868
|
);
|
|
5854
5869
|
const structureKey = initialStack.map((i) => i.type).join("|");
|
|
5855
|
-
const geometry = (0,
|
|
5870
|
+
const geometry = (0, import_react13.useMemo)(() => {
|
|
5856
5871
|
const floor = stackMinSegments(initialStack, config.sheet);
|
|
5857
5872
|
const want = [0, 0];
|
|
5858
5873
|
for (const p of PROGRESS_SAMPLES2) {
|
|
@@ -5886,9 +5901,9 @@ function FieldGroup({
|
|
|
5886
5901
|
geo.setAttribute("aBias", new THREE13.InstancedBufferAttribute(bias, 1));
|
|
5887
5902
|
return geo;
|
|
5888
5903
|
}, [JSON.stringify(config.sheet), structureKey, count, autoCeiling]);
|
|
5889
|
-
(0,
|
|
5904
|
+
(0, import_react13.useEffect)(() => () => geometry.dispose(), [geometry]);
|
|
5890
5905
|
const atlas = useContentAtlas(contents, config.sheet, stock);
|
|
5891
|
-
const shader = (0,
|
|
5906
|
+
const shader = (0, import_react13.useMemo)(() => {
|
|
5892
5907
|
const composed = buildDisplacementGLSL(initialStack, config.sheet);
|
|
5893
5908
|
const uniforms = {};
|
|
5894
5909
|
for (const [name, value] of Object.entries(composed.uniforms)) {
|
|
@@ -5917,19 +5932,19 @@ function FieldGroup({
|
|
|
5917
5932
|
config.surface.showThrough,
|
|
5918
5933
|
config.surface.translucency
|
|
5919
5934
|
]);
|
|
5920
|
-
(0,
|
|
5935
|
+
(0, import_react13.useEffect)(() => {
|
|
5921
5936
|
const values = translucencyValues(config.surface.translucency ?? stock.translucency, rig);
|
|
5922
5937
|
shader.uniforms.uTranslucency.value = values.translucency;
|
|
5923
5938
|
shader.uniforms.uBackLightDir.value.copy(values.direction);
|
|
5924
5939
|
shader.uniforms.uBackLightColor.value.copy(values.color);
|
|
5925
5940
|
shader.uniforms.uAmbientTransmission.value = values.ambient;
|
|
5926
5941
|
}, [shader, rig, config.surface.translucency, stock.translucency]);
|
|
5927
|
-
(0,
|
|
5942
|
+
(0, import_react13.useEffect)(() => {
|
|
5928
5943
|
if (!atlas) return;
|
|
5929
5944
|
shader.uniforms.uAtlas.value = atlas.texture;
|
|
5930
5945
|
shader.uniforms.uAtlasGrid.value.set(atlas.cols, atlas.rows);
|
|
5931
5946
|
}, [atlas, shader]);
|
|
5932
|
-
(0,
|
|
5947
|
+
(0, import_react13.useEffect)(() => {
|
|
5933
5948
|
if (!behavior || shared.reduced) return;
|
|
5934
5949
|
const state = { p: progressRef.current };
|
|
5935
5950
|
const tween = import_gsap3.gsap.to(state, {
|
|
@@ -5946,8 +5961,8 @@ function FieldGroup({
|
|
|
5946
5961
|
tween.kill();
|
|
5947
5962
|
};
|
|
5948
5963
|
}, [structureKey, shared.reduced]);
|
|
5949
|
-
const meshRef = (0,
|
|
5950
|
-
(0,
|
|
5964
|
+
const meshRef = (0, import_react13.useRef)(null);
|
|
5965
|
+
(0, import_fiber5.useFrame)(({ clock }) => {
|
|
5951
5966
|
const mesh = meshRef.current;
|
|
5952
5967
|
if (!mesh) return;
|
|
5953
5968
|
const elapsed = clock.elapsedTime - Math.max(shared.mountTimeRef.current, 0);
|
|
@@ -6094,7 +6109,7 @@ var easeInOut = (t) => t < 0.5 ? 2 * t * t : 1 - (-2 * t + 2) ** 2 / 2;
|
|
|
6094
6109
|
|
|
6095
6110
|
// src/field/backingSheet.tsx
|
|
6096
6111
|
var THREE14 = __toESM(require("three"), 1);
|
|
6097
|
-
var
|
|
6112
|
+
var import_react14 = require("react");
|
|
6098
6113
|
|
|
6099
6114
|
// src/content/backing.ts
|
|
6100
6115
|
function silhouetteRects(o, count) {
|
|
@@ -6167,7 +6182,7 @@ function BackingSheet({
|
|
|
6167
6182
|
removed
|
|
6168
6183
|
}) {
|
|
6169
6184
|
const { width, height } = sheetBackingSize(options);
|
|
6170
|
-
const canvas = (0,
|
|
6185
|
+
const canvas = (0, import_react14.useMemo)(() => {
|
|
6171
6186
|
if (typeof document === "undefined") return null;
|
|
6172
6187
|
const c = document.createElement("canvas");
|
|
6173
6188
|
const scale = Math.min(1024, Math.round(360 * Math.max(width, height))) / Math.max(width, height);
|
|
@@ -6175,14 +6190,14 @@ function BackingSheet({
|
|
|
6175
6190
|
c.height = Math.max(2, Math.round(height * scale));
|
|
6176
6191
|
return c;
|
|
6177
6192
|
}, [width, height]);
|
|
6178
|
-
const texture = (0,
|
|
6193
|
+
const texture = (0, import_react14.useMemo)(() => canvas ? new THREE14.CanvasTexture(canvas) : null, [canvas]);
|
|
6179
6194
|
const removedKey = [...removed].sort((a, b) => a - b).join(",");
|
|
6180
|
-
(0,
|
|
6195
|
+
(0, import_react14.useEffect)(() => {
|
|
6181
6196
|
if (!canvas || !texture) return;
|
|
6182
6197
|
drawBacking(canvas, { options, count, tint: BACKING_TINT, removed });
|
|
6183
6198
|
texture.needsUpdate = true;
|
|
6184
6199
|
}, [canvas, texture, JSON.stringify(options), count, removedKey]);
|
|
6185
|
-
(0,
|
|
6200
|
+
(0, import_react14.useEffect)(() => () => texture?.dispose(), [texture]);
|
|
6186
6201
|
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("mesh", { receiveShadow: true, children: [
|
|
6187
6202
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("planeGeometry", { args: [width, height] }),
|
|
6188
6203
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("meshStandardMaterial", { map: texture, color: "#ffffff", roughness: 0.92, metalness: 0 })
|
|
@@ -6192,8 +6207,8 @@ function BackingSheet({
|
|
|
6192
6207
|
// src/field/interactiveField.tsx
|
|
6193
6208
|
var THREE15 = __toESM(require("three"), 1);
|
|
6194
6209
|
var import_gsap4 = require("gsap");
|
|
6195
|
-
var
|
|
6196
|
-
var
|
|
6210
|
+
var import_fiber6 = require("@react-three/fiber");
|
|
6211
|
+
var import_react15 = require("react");
|
|
6197
6212
|
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
6198
6213
|
var PICK_BEHAVIORS = /* @__PURE__ */ new Set(["peel", "carry"]);
|
|
6199
6214
|
function InteractiveField(props) {
|
|
@@ -6201,15 +6216,15 @@ function InteractiveField(props) {
|
|
|
6201
6216
|
const total = papers.length;
|
|
6202
6217
|
const layout = getLayout(layoutId);
|
|
6203
6218
|
const reduced = usePrefersReducedMotion(props.reducedMotion);
|
|
6204
|
-
const contextRegistry = (0,
|
|
6205
|
-
const registry4 = (0,
|
|
6206
|
-
const camera = (0,
|
|
6207
|
-
const gl = (0,
|
|
6208
|
-
const controls = (0,
|
|
6209
|
-
const [removed, setRemoved] = (0,
|
|
6210
|
-
const [slotPatches, setSlotPatches] = (0,
|
|
6211
|
-
const [slotStates, setSlotStates] = (0,
|
|
6212
|
-
const slotConfigs = (0,
|
|
6219
|
+
const contextRegistry = (0, import_react15.useContext)(DropZoneContext);
|
|
6220
|
+
const registry4 = (0, import_react15.useMemo)(() => contextRegistry ?? new DropZoneRegistry(), [contextRegistry]);
|
|
6221
|
+
const camera = (0, import_fiber6.useThree)((s) => s.camera);
|
|
6222
|
+
const gl = (0, import_fiber6.useThree)((s) => s.gl);
|
|
6223
|
+
const controls = (0, import_fiber6.useThree)((s) => s.controls);
|
|
6224
|
+
const [removed, setRemoved] = (0, import_react15.useState)(EMPTY_SET);
|
|
6225
|
+
const [slotPatches, setSlotPatches] = (0, import_react15.useState)({});
|
|
6226
|
+
const [slotStates, setSlotStates] = (0, import_react15.useState)({});
|
|
6227
|
+
const slotConfigs = (0, import_react15.useMemo)(
|
|
6213
6228
|
() => papers.map((slot, i) => {
|
|
6214
6229
|
const config = resolveFieldSlotConfig(slot, fallback, i, layoutId, layoutOptions);
|
|
6215
6230
|
const patch = slotPatches[i];
|
|
@@ -6223,14 +6238,14 @@ function InteractiveField(props) {
|
|
|
6223
6238
|
slotPatches
|
|
6224
6239
|
]
|
|
6225
6240
|
);
|
|
6226
|
-
const poses = (0,
|
|
6241
|
+
const poses = (0, import_react15.useMemo)(
|
|
6227
6242
|
() => slotConfigs.map((_, i) => layout.pose(i, total, layoutOptions, 0, props.sheet)),
|
|
6228
6243
|
[layoutId, JSON.stringify(layoutOptions), total, props.sheet.width, props.sheet.height]
|
|
6229
6244
|
);
|
|
6230
|
-
const groupRefs = (0,
|
|
6231
|
-
const handleRefs = (0,
|
|
6232
|
-
const pressRef = (0,
|
|
6233
|
-
const carriedRef = (0,
|
|
6245
|
+
const groupRefs = (0, import_react15.useRef)([]);
|
|
6246
|
+
const handleRefs = (0, import_react15.useRef)([]);
|
|
6247
|
+
const pressRef = (0, import_react15.useRef)(null);
|
|
6248
|
+
const carriedRef = (0, import_react15.useRef)(null);
|
|
6234
6249
|
const zonesLive = () => [...props.zones ?? [], ...registry4.list()];
|
|
6235
6250
|
const slotName = (i) => {
|
|
6236
6251
|
const preset = papers[i]?.preset ?? fallback;
|
|
@@ -6243,10 +6258,10 @@ function InteractiveField(props) {
|
|
|
6243
6258
|
}
|
|
6244
6259
|
props.onSlotStateChange?.(i, state);
|
|
6245
6260
|
};
|
|
6246
|
-
const raycaster = (0,
|
|
6247
|
-
const planeScratch = (0,
|
|
6248
|
-
const pointScratch = (0,
|
|
6249
|
-
const ndcScratch = (0,
|
|
6261
|
+
const raycaster = (0, import_react15.useMemo)(() => new THREE15.Raycaster(), []);
|
|
6262
|
+
const planeScratch = (0, import_react15.useMemo)(() => new THREE15.Plane(new THREE15.Vector3(0, 0, 1), 0), []);
|
|
6263
|
+
const pointScratch = (0, import_react15.useMemo)(() => new THREE15.Vector3(), []);
|
|
6264
|
+
const ndcScratch = (0, import_react15.useMemo)(() => new THREE15.Vector2(), []);
|
|
6250
6265
|
const planePoint = (clientX, clientY, planeZ) => {
|
|
6251
6266
|
const rect = gl.domElement.getBoundingClientRect();
|
|
6252
6267
|
ndcScratch.set(
|
|
@@ -6376,7 +6391,7 @@ function InteractiveField(props) {
|
|
|
6376
6391
|
import_gsap4.gsap.to(group.rotation, { x: home.rotation[0], y: home.rotation[1], z: home.rotation[2], duration });
|
|
6377
6392
|
import_gsap4.gsap.to(group.scale, { x: home.scale, y: home.scale, z: home.scale, duration: duration * 0.5 });
|
|
6378
6393
|
};
|
|
6379
|
-
const onPointerMoveRef = (0,
|
|
6394
|
+
const onPointerMoveRef = (0, import_react15.useRef)(() => {
|
|
6380
6395
|
});
|
|
6381
6396
|
onPointerMoveRef.current = (e) => {
|
|
6382
6397
|
const press = pressRef.current;
|
|
@@ -6400,7 +6415,7 @@ function InteractiveField(props) {
|
|
|
6400
6415
|
pick(slot, hit[0], hit[1], pointerId);
|
|
6401
6416
|
}
|
|
6402
6417
|
};
|
|
6403
|
-
const onPointerUpRef = (0,
|
|
6418
|
+
const onPointerUpRef = (0, import_react15.useRef)(() => {
|
|
6404
6419
|
});
|
|
6405
6420
|
onPointerUpRef.current = (e) => {
|
|
6406
6421
|
pressRef.current = null;
|
|
@@ -6414,7 +6429,7 @@ function InteractiveField(props) {
|
|
|
6414
6429
|
if (zone) settleInto(carried, zone);
|
|
6415
6430
|
else returnHome(carried);
|
|
6416
6431
|
};
|
|
6417
|
-
(0,
|
|
6432
|
+
(0, import_react15.useEffect)(() => {
|
|
6418
6433
|
const move = (e) => onPointerMoveRef.current(e);
|
|
6419
6434
|
const up = (e) => onPointerUpRef.current(e);
|
|
6420
6435
|
window.addEventListener("pointermove", move);
|
|
@@ -6424,7 +6439,7 @@ function InteractiveField(props) {
|
|
|
6424
6439
|
window.removeEventListener("pointerup", up);
|
|
6425
6440
|
};
|
|
6426
6441
|
}, []);
|
|
6427
|
-
(0,
|
|
6442
|
+
(0, import_fiber6.useFrame)((_, delta) => {
|
|
6428
6443
|
const carried = carriedRef.current;
|
|
6429
6444
|
if (!carried || carried.settling) return;
|
|
6430
6445
|
const group = groupRefs.current[carried.slot];
|
|
@@ -6462,7 +6477,7 @@ function InteractiveField(props) {
|
|
|
6462
6477
|
group.scale.x += (targetScale - group.scale.x) * 0.15;
|
|
6463
6478
|
group.scale.y = group.scale.z = group.scale.x;
|
|
6464
6479
|
});
|
|
6465
|
-
const a11yImplRef = (0,
|
|
6480
|
+
const a11yImplRef = (0, import_react15.useRef)(null);
|
|
6466
6481
|
a11yImplRef.current = {
|
|
6467
6482
|
pick: (slot) => {
|
|
6468
6483
|
const home = poses[slot];
|
|
@@ -6487,7 +6502,7 @@ function InteractiveField(props) {
|
|
|
6487
6502
|
zoneIds: () => zonesLive().map((z30) => z30.id),
|
|
6488
6503
|
slotState: (slot) => slotStates[slot] ?? "rest"
|
|
6489
6504
|
};
|
|
6490
|
-
(0,
|
|
6505
|
+
(0, import_react15.useEffect)(() => {
|
|
6491
6506
|
const ref = props.a11yRef;
|
|
6492
6507
|
if (!ref) return;
|
|
6493
6508
|
ref.current = {
|
|
@@ -6540,7 +6555,7 @@ function InteractiveField(props) {
|
|
|
6540
6555
|
}
|
|
6541
6556
|
|
|
6542
6557
|
// src/field/keyboardMirror.tsx
|
|
6543
|
-
var
|
|
6558
|
+
var import_react16 = require("react");
|
|
6544
6559
|
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
6545
6560
|
function fieldKeyboardStep(carry2, slot, key, controller) {
|
|
6546
6561
|
if (!carry2) {
|
|
@@ -6586,7 +6601,7 @@ function FieldKeyboardMirror({
|
|
|
6586
6601
|
papers,
|
|
6587
6602
|
controller
|
|
6588
6603
|
}) {
|
|
6589
|
-
const [carrying, setCarrying] = (0,
|
|
6604
|
+
const [carrying, setCarrying] = (0, import_react16.useState)(null);
|
|
6590
6605
|
const paperLabel = (slot, i) => {
|
|
6591
6606
|
try {
|
|
6592
6607
|
const config = resolveConfig({ preset: slot.preset });
|
|
@@ -6689,16 +6704,16 @@ function fitCamera(layout, n, options, sheet2, fovDeg, aspect, margin = 1.06) {
|
|
|
6689
6704
|
|
|
6690
6705
|
// src/PaperField.tsx
|
|
6691
6706
|
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
6692
|
-
var PaperFieldMesh = (0,
|
|
6707
|
+
var PaperFieldMesh = (0, import_react17.forwardRef)(
|
|
6693
6708
|
function PaperFieldMesh2(props, ref) {
|
|
6694
6709
|
const reduced = usePrefersReducedMotion(props.reducedMotion);
|
|
6695
|
-
const papers = (0,
|
|
6710
|
+
const papers = (0, import_react17.useMemo)(
|
|
6696
6711
|
() => effectiveFieldPapers(props.papers, props.images),
|
|
6697
6712
|
[props.papers, props.images]
|
|
6698
6713
|
);
|
|
6699
6714
|
const stablePapers = useStable(papers);
|
|
6700
6715
|
const stablePreset = useStable(props.preset ?? null);
|
|
6701
|
-
const groups = (0,
|
|
6716
|
+
const groups = (0, import_react17.useMemo)(
|
|
6702
6717
|
() => groupFieldPapers(stablePapers, stablePreset ?? void 0),
|
|
6703
6718
|
[stablePapers, stablePreset]
|
|
6704
6719
|
);
|
|
@@ -6707,22 +6722,22 @@ var PaperFieldMesh = (0, import_react16.forwardRef)(
|
|
|
6707
6722
|
const layout = getLayout(layoutId);
|
|
6708
6723
|
const firstSheet = groups[0]?.config.sheet;
|
|
6709
6724
|
const stableLayoutOptions = useStable(props.layoutOptions ?? {});
|
|
6710
|
-
const layoutOptions = (0,
|
|
6725
|
+
const layoutOptions = (0, import_react17.useMemo)(
|
|
6711
6726
|
// Sheet grids size their cells from the papers themselves — gutter is
|
|
6712
6727
|
// then literally the spacing between stamps (explicit cell dims win).
|
|
6713
6728
|
() => resolveLayoutOptions(layoutId, layout, stableLayoutOptions, firstSheet),
|
|
6714
6729
|
[layoutId, stableLayoutOptions, firstSheet?.width, firstSheet?.height]
|
|
6715
6730
|
);
|
|
6716
|
-
const phaseRef = (0,
|
|
6717
|
-
const dragVelRef = (0,
|
|
6718
|
-
const mountTimeRef = (0,
|
|
6719
|
-
const morphRef = (0,
|
|
6720
|
-
const prevLayout = (0,
|
|
6721
|
-
const gl = (0,
|
|
6731
|
+
const phaseRef = (0, import_react17.useRef)(0);
|
|
6732
|
+
const dragVelRef = (0, import_react17.useRef)(0);
|
|
6733
|
+
const mountTimeRef = (0, import_react17.useRef)(-1);
|
|
6734
|
+
const morphRef = (0, import_react17.useRef)({ from: null, t: 1 });
|
|
6735
|
+
const prevLayout = (0, import_react17.useRef)({ id: layoutId, options: layoutOptions });
|
|
6736
|
+
const gl = (0, import_fiber7.useThree)((s) => s.gl);
|
|
6722
6737
|
const driver = reduced ? "none" : props.motion?.driver ?? "autoplay";
|
|
6723
6738
|
const speed = props.motion?.speed ?? 0.5;
|
|
6724
6739
|
const entranceType = reduced ? "none" : props.entrance?.type ?? "rise";
|
|
6725
|
-
(0,
|
|
6740
|
+
(0, import_react17.useEffect)(() => {
|
|
6726
6741
|
const prev = prevLayout.current;
|
|
6727
6742
|
if (prev.id !== layoutId || JSON.stringify(prev.options) !== JSON.stringify(layoutOptions)) {
|
|
6728
6743
|
morphRef.current = { from: prev, t: 0 };
|
|
@@ -6730,7 +6745,7 @@ var PaperFieldMesh = (0, import_react16.forwardRef)(
|
|
|
6730
6745
|
prevLayout.current = { id: layoutId, options: layoutOptions };
|
|
6731
6746
|
}
|
|
6732
6747
|
}, [layoutId, layoutOptions]);
|
|
6733
|
-
(0,
|
|
6748
|
+
(0, import_react17.useEffect)(() => {
|
|
6734
6749
|
if (driver !== "drag") return;
|
|
6735
6750
|
const el = gl.domElement;
|
|
6736
6751
|
let lastX = null;
|
|
@@ -6756,7 +6771,7 @@ var PaperFieldMesh = (0, import_react16.forwardRef)(
|
|
|
6756
6771
|
window.removeEventListener("pointerup", up);
|
|
6757
6772
|
};
|
|
6758
6773
|
}, [driver, gl]);
|
|
6759
|
-
(0,
|
|
6774
|
+
(0, import_fiber7.useFrame)(({ clock }, delta) => {
|
|
6760
6775
|
if (mountTimeRef.current < 0) mountTimeRef.current = clock.elapsedTime;
|
|
6761
6776
|
if (driver === "autoplay") phaseRef.current += delta * speed * 0.02;
|
|
6762
6777
|
if (driver === "drag") {
|
|
@@ -6814,14 +6829,14 @@ var PaperFieldMesh = (0, import_react16.forwardRef)(
|
|
|
6814
6829
|
}
|
|
6815
6830
|
);
|
|
6816
6831
|
function FitCamera(meshProps) {
|
|
6817
|
-
const camera = (0,
|
|
6818
|
-
const width = (0,
|
|
6819
|
-
const height = (0,
|
|
6832
|
+
const camera = (0, import_fiber7.useThree)((s) => s.camera);
|
|
6833
|
+
const width = (0, import_fiber7.useThree)((s) => s.size.width);
|
|
6834
|
+
const height = (0, import_fiber7.useThree)((s) => s.size.height);
|
|
6820
6835
|
const papersProp = useStable(meshProps.papers ?? null);
|
|
6821
6836
|
const imagesProp = useStable(meshProps.images ?? null);
|
|
6822
6837
|
const presetProp = useStable(meshProps.preset ?? null);
|
|
6823
6838
|
const optionsProp = useStable(meshProps.layoutOptions ?? {});
|
|
6824
|
-
const field = (0,
|
|
6839
|
+
const field = (0, import_react17.useMemo)(() => {
|
|
6825
6840
|
const papers = effectiveFieldPapers(papersProp ?? void 0, imagesProp ?? void 0);
|
|
6826
6841
|
const layoutId = meshProps.layout ?? "ring";
|
|
6827
6842
|
const layout = getLayout(layoutId);
|
|
@@ -6829,7 +6844,7 @@ function FitCamera(meshProps) {
|
|
|
6829
6844
|
const options = resolveLayoutOptions(layoutId, layout, optionsProp, sheet2);
|
|
6830
6845
|
return { layout, n: papers.length, options, sheet: sheet2 ?? DEFAULT_SHEET };
|
|
6831
6846
|
}, [papersProp, imagesProp, presetProp, meshProps.layout, optionsProp]);
|
|
6832
|
-
(0,
|
|
6847
|
+
(0, import_react17.useEffect)(() => {
|
|
6833
6848
|
if (!(camera instanceof THREE16.PerspectiveCamera)) return;
|
|
6834
6849
|
const { position, target } = fitCamera(
|
|
6835
6850
|
field.layout,
|
|
@@ -6845,27 +6860,28 @@ function FitCamera(meshProps) {
|
|
|
6845
6860
|
}, [camera, width, height, field]);
|
|
6846
6861
|
return null;
|
|
6847
6862
|
}
|
|
6848
|
-
var PaperField = (0,
|
|
6863
|
+
var PaperField = (0, import_react17.forwardRef)(function PaperField2({ children, className, style, scene, ...meshProps }, ref) {
|
|
6849
6864
|
const rig = sceneSchema.parse(scene ?? {});
|
|
6850
|
-
const registry4 = (0,
|
|
6851
|
-
const a11yRef = (0,
|
|
6852
|
-
const papers = (0,
|
|
6865
|
+
const registry4 = (0, import_react17.useMemo)(() => new DropZoneRegistry(), []);
|
|
6866
|
+
const a11yRef = (0, import_react17.useRef)(null);
|
|
6867
|
+
const papers = (0, import_react17.useMemo)(
|
|
6853
6868
|
() => effectiveFieldPapers(meshProps.papers, meshProps.images),
|
|
6854
6869
|
[meshProps.papers, meshProps.images]
|
|
6855
6870
|
);
|
|
6856
6871
|
const stablePapers = useStable(papers);
|
|
6857
6872
|
const stablePreset = useStable(meshProps.preset ?? null);
|
|
6858
|
-
const interactive = (0,
|
|
6873
|
+
const interactive = (0, import_react17.useMemo)(
|
|
6859
6874
|
() => fieldIsInteractive(stablePapers, stablePreset ?? void 0, meshProps.interactive),
|
|
6860
6875
|
[stablePapers, stablePreset, meshProps.interactive]
|
|
6861
6876
|
);
|
|
6862
6877
|
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className, style: { width: "100%", height: "100%", ...style }, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(DropZoneContext.Provider, { value: registry4, children: [
|
|
6863
|
-
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
6878
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_fiber7.Canvas, { shadows: true, camera: { position: [0, 0.6, 5.2], fov: 45 }, dpr: [1, 2], children: [
|
|
6864
6879
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(FitCamera, { ...meshProps }),
|
|
6865
6880
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(PaperBackdrop, { backdrop: rig.backdrop }),
|
|
6866
6881
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(PaperLighting, { preset: rig.lighting, light: rig.light, floor: -2.4, scale: 14 }),
|
|
6867
6882
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(PaperFieldMesh, { ref, a11yControllerRef: a11yRef, ...meshProps }),
|
|
6868
|
-
children
|
|
6883
|
+
children,
|
|
6884
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ReleaseContextOnUnmount, {})
|
|
6869
6885
|
] }),
|
|
6870
6886
|
interactive && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(FieldKeyboardMirror, { papers, controller: a11yRef })
|
|
6871
6887
|
] }) });
|
|
@@ -6962,13 +6978,13 @@ function stageCamera(path, walked, scale, options) {
|
|
|
6962
6978
|
|
|
6963
6979
|
// src/stage/Figure.tsx
|
|
6964
6980
|
var THREE18 = __toESM(require("three"), 1);
|
|
6965
|
-
var
|
|
6966
|
-
var
|
|
6981
|
+
var import_react19 = require("react");
|
|
6982
|
+
var import_fiber9 = require("@react-three/fiber");
|
|
6967
6983
|
|
|
6968
6984
|
// src/stage/RiggedFigure.tsx
|
|
6969
6985
|
var import_drei2 = require("@react-three/drei");
|
|
6970
|
-
var
|
|
6971
|
-
var
|
|
6986
|
+
var import_fiber8 = require("@react-three/fiber");
|
|
6987
|
+
var import_react18 = require("react");
|
|
6972
6988
|
var THREE17 = __toESM(require("three"), 1);
|
|
6973
6989
|
var import_SkeletonUtils = require("three/examples/jsm/utils/SkeletonUtils.js");
|
|
6974
6990
|
|
|
@@ -7144,7 +7160,7 @@ function placeFigure(path, distance, o) {
|
|
|
7144
7160
|
|
|
7145
7161
|
// src/stage/RiggedFigure.tsx
|
|
7146
7162
|
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
7147
|
-
var ModelBoundary = class extends
|
|
7163
|
+
var ModelBoundary = class extends import_react18.Component {
|
|
7148
7164
|
state = { failed: false };
|
|
7149
7165
|
static getDerivedStateFromError() {
|
|
7150
7166
|
return { failed: true };
|
|
@@ -7158,14 +7174,14 @@ var ModelBoundary = class extends import_react17.Component {
|
|
|
7158
7174
|
};
|
|
7159
7175
|
function Rigged({ url, options, distance, frozen }) {
|
|
7160
7176
|
const gltf = (0, import_drei2.useGLTF)(url);
|
|
7161
|
-
const scene = (0,
|
|
7177
|
+
const scene = (0, import_react18.useMemo)(() => (0, import_SkeletonUtils.clone)(gltf.scene), [gltf.scene]);
|
|
7162
7178
|
const silhouette = options.finish === "silhouette";
|
|
7163
|
-
const material = (0,
|
|
7179
|
+
const material = (0, import_react18.useMemo)(
|
|
7164
7180
|
() => silhouette ? new THREE17.MeshBasicMaterial({ color: options.color, toneMapped: false }) : null,
|
|
7165
7181
|
[silhouette, options.color]
|
|
7166
7182
|
);
|
|
7167
|
-
(0,
|
|
7168
|
-
const scale = (0,
|
|
7183
|
+
(0, import_react18.useEffect)(() => () => material?.dispose(), [material]);
|
|
7184
|
+
const scale = (0, import_react18.useMemo)(() => {
|
|
7169
7185
|
scene.traverse((child) => {
|
|
7170
7186
|
const mesh = child;
|
|
7171
7187
|
if (!mesh.isMesh) return;
|
|
@@ -7179,13 +7195,13 @@ function Rigged({ url, options, distance, frozen }) {
|
|
|
7179
7195
|
const height = box.max.y - box.min.y;
|
|
7180
7196
|
return height > 0 ? options.height / height : 1;
|
|
7181
7197
|
}, [scene, material, silhouette, options.height]);
|
|
7182
|
-
const mixer = (0,
|
|
7183
|
-
const clip = (0,
|
|
7198
|
+
const mixer = (0, import_react18.useMemo)(() => new THREE17.AnimationMixer(scene), [scene]);
|
|
7199
|
+
const clip = (0, import_react18.useMemo)(() => {
|
|
7184
7200
|
const names = gltf.animations.map((a) => a.name);
|
|
7185
7201
|
const wanted = frozen ? pickStillClip(names) : pickClip(names, isRunning(options));
|
|
7186
7202
|
return gltf.animations.find((a) => a.name === wanted) ?? gltf.animations[0];
|
|
7187
7203
|
}, [gltf.animations, options, frozen]);
|
|
7188
|
-
(0,
|
|
7204
|
+
(0, import_react18.useEffect)(() => {
|
|
7189
7205
|
if (!clip) return;
|
|
7190
7206
|
mixer.clipAction(clip).play();
|
|
7191
7207
|
return () => {
|
|
@@ -7193,7 +7209,7 @@ function Rigged({ url, options, distance, frozen }) {
|
|
|
7193
7209
|
mixer.uncacheClip(clip);
|
|
7194
7210
|
};
|
|
7195
7211
|
}, [mixer, clip]);
|
|
7196
|
-
(0,
|
|
7212
|
+
(0, import_fiber8.useFrame)(() => {
|
|
7197
7213
|
if (!clip) return;
|
|
7198
7214
|
mixer.setTime(frozen ? 0 : clipTimeFor(distance.current, options, clip.duration));
|
|
7199
7215
|
});
|
|
@@ -7212,29 +7228,29 @@ function Segment({ length, radius, material }) {
|
|
|
7212
7228
|
function Figure({ path, figure, distance, distanceRef, walkLength, frozen }) {
|
|
7213
7229
|
const reducedMotion = usePrefersReducedMotion();
|
|
7214
7230
|
const still = frozen ?? reducedMotion;
|
|
7215
|
-
const options = (0,
|
|
7216
|
-
const walk = (0,
|
|
7217
|
-
const root = (0,
|
|
7218
|
-
const walkedRef = (0,
|
|
7219
|
-
const hips = (0,
|
|
7220
|
-
const chest = (0,
|
|
7221
|
-
const legL = (0,
|
|
7222
|
-
const legR = (0,
|
|
7223
|
-
const kneeL = (0,
|
|
7224
|
-
const kneeR = (0,
|
|
7225
|
-
const armL = (0,
|
|
7226
|
-
const armR = (0,
|
|
7227
|
-
const elbowL = (0,
|
|
7228
|
-
const elbowR = (0,
|
|
7229
|
-
const material = (0,
|
|
7231
|
+
const options = (0, import_react19.useMemo)(() => figureSchema.parse(figure ?? {}), [figure]);
|
|
7232
|
+
const walk = (0, import_react19.useMemo)(() => getWalkPath(walkPathSchema.parse(path ?? {})), [path]);
|
|
7233
|
+
const root = (0, import_react19.useRef)(null);
|
|
7234
|
+
const walkedRef = (0, import_react19.useRef)(0);
|
|
7235
|
+
const hips = (0, import_react19.useRef)(null);
|
|
7236
|
+
const chest = (0, import_react19.useRef)(null);
|
|
7237
|
+
const legL = (0, import_react19.useRef)(null);
|
|
7238
|
+
const legR = (0, import_react19.useRef)(null);
|
|
7239
|
+
const kneeL = (0, import_react19.useRef)(null);
|
|
7240
|
+
const kneeR = (0, import_react19.useRef)(null);
|
|
7241
|
+
const armL = (0, import_react19.useRef)(null);
|
|
7242
|
+
const armR = (0, import_react19.useRef)(null);
|
|
7243
|
+
const elbowL = (0, import_react19.useRef)(null);
|
|
7244
|
+
const elbowR = (0, import_react19.useRef)(null);
|
|
7245
|
+
const material = (0, import_react19.useMemo)(
|
|
7230
7246
|
() => new THREE18.MeshBasicMaterial({ color: options.color, toneMapped: false }),
|
|
7231
7247
|
[options.color]
|
|
7232
7248
|
);
|
|
7233
|
-
(0,
|
|
7249
|
+
(0, import_react19.useEffect)(() => () => material.dispose(), [material]);
|
|
7234
7250
|
const h = options.height;
|
|
7235
7251
|
const p = PROPORTIONS;
|
|
7236
7252
|
const torso = (p.shoulder - p.hip) * h;
|
|
7237
|
-
(0,
|
|
7253
|
+
(0, import_fiber9.useFrame)((state) => {
|
|
7238
7254
|
const walked = distanceRef !== void 0 ? distanceRef.current * (walkLength ?? walk.length) : distance ?? (still ? 0 : state.clock.elapsedTime * options.speed);
|
|
7239
7255
|
walkedRef.current = walked;
|
|
7240
7256
|
const { position, yaw, pose } = placeFigure(walk, walked, options);
|
|
@@ -7289,7 +7305,7 @@ function Figure({ path, figure, distance, distanceRef, walkLength, frozen }) {
|
|
|
7289
7305
|
// The capsules are both the fallback and the thing being replaced, so
|
|
7290
7306
|
// a model that is still downloading shows a walking figure rather than
|
|
7291
7307
|
// a hole, and one that never arrives leaves the stage as it was.
|
|
7292
|
-
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
7308
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react19.Suspense, { fallback: capsules, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
7293
7309
|
RiggedFigure,
|
|
7294
7310
|
{
|
|
7295
7311
|
url: options.model,
|
|
@@ -7304,7 +7320,7 @@ function Figure({ path, figure, distance, distanceRef, walkLength, frozen }) {
|
|
|
7304
7320
|
|
|
7305
7321
|
// src/stage/Surround.tsx
|
|
7306
7322
|
var THREE19 = __toESM(require("three"), 1);
|
|
7307
|
-
var
|
|
7323
|
+
var import_react20 = require("react");
|
|
7308
7324
|
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
7309
7325
|
function makeSkyTexture(sky) {
|
|
7310
7326
|
const canvas = document.createElement("canvas");
|
|
@@ -7359,8 +7375,8 @@ function Source({
|
|
|
7359
7375
|
color,
|
|
7360
7376
|
intensity = SOURCE_INTENSITY
|
|
7361
7377
|
}) {
|
|
7362
|
-
const texture = (0,
|
|
7363
|
-
(0,
|
|
7378
|
+
const texture = (0, import_react20.useMemo)(() => makeGlowTexture(color), [color]);
|
|
7379
|
+
(0, import_react20.useEffect)(() => () => texture.dispose(), [texture]);
|
|
7364
7380
|
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("mesh", { position, rotation: [0, yaw, 0], children: [
|
|
7365
7381
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("planeGeometry", { args: [size * 2.4, size * 1.8] }),
|
|
7366
7382
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
@@ -7377,8 +7393,8 @@ function Source({
|
|
|
7377
7393
|
}
|
|
7378
7394
|
function Surround({ radius, sky }) {
|
|
7379
7395
|
const { zenith, horizon, ground } = sky;
|
|
7380
|
-
const texture = (0,
|
|
7381
|
-
(0,
|
|
7396
|
+
const texture = (0, import_react20.useMemo)(() => makeSkyTexture({ zenith, horizon, ground }), [zenith, horizon, ground]);
|
|
7397
|
+
(0, import_react20.useEffect)(() => () => texture.dispose(), [texture]);
|
|
7382
7398
|
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("mesh", { children: [
|
|
7383
7399
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("sphereGeometry", { args: [radius, 32, 24] }),
|
|
7384
7400
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("meshBasicMaterial", { map: texture, side: THREE19.BackSide, fog: false })
|
|
@@ -7387,7 +7403,7 @@ function Surround({ radius, sky }) {
|
|
|
7387
7403
|
|
|
7388
7404
|
// src/stage/Room.tsx
|
|
7389
7405
|
var THREE20 = __toESM(require("three"), 1);
|
|
7390
|
-
var
|
|
7406
|
+
var import_react21 = require("react");
|
|
7391
7407
|
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
7392
7408
|
function makeFloorTexture(color, repeats) {
|
|
7393
7409
|
const size = 256;
|
|
@@ -7419,8 +7435,8 @@ function Floor({
|
|
|
7419
7435
|
slab
|
|
7420
7436
|
}) {
|
|
7421
7437
|
const repeats = slab > 0 ? Math.max(1, Math.round(size / slab)) : 0;
|
|
7422
|
-
const texture = (0,
|
|
7423
|
-
(0,
|
|
7438
|
+
const texture = (0, import_react21.useMemo)(() => repeats > 0 ? makeFloorTexture(color, repeats) : null, [color, repeats]);
|
|
7439
|
+
(0, import_react21.useEffect)(() => () => texture?.dispose(), [texture]);
|
|
7424
7440
|
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("mesh", { rotation: [-Math.PI / 2, 0, 0], receiveShadow: true, children: [
|
|
7425
7441
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("planeGeometry", { args: [size, size] }),
|
|
7426
7442
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("meshStandardMaterial", { map: texture, color: texture ? "#ffffff" : color, roughness: 1 })
|
|
@@ -7440,7 +7456,7 @@ function Columns({
|
|
|
7440
7456
|
offset,
|
|
7441
7457
|
color
|
|
7442
7458
|
}) {
|
|
7443
|
-
const placements = (0,
|
|
7459
|
+
const placements = (0, import_react21.useMemo)(() => {
|
|
7444
7460
|
if (!(spacing > 0) || !(path.length > 0)) return [];
|
|
7445
7461
|
const bays = Math.max(1, Math.round(path.length / spacing));
|
|
7446
7462
|
const out = [];
|
|
@@ -7456,12 +7472,12 @@ function Columns({
|
|
|
7456
7472
|
}
|
|
7457
7473
|
return out;
|
|
7458
7474
|
}, [path, spacing, offset]);
|
|
7459
|
-
const shaft = (0,
|
|
7460
|
-
const base = (0,
|
|
7461
|
-
const capital = (0,
|
|
7475
|
+
const shaft = (0, import_react21.useRef)(null);
|
|
7476
|
+
const base = (0, import_react21.useRef)(null);
|
|
7477
|
+
const capital = (0, import_react21.useRef)(null);
|
|
7462
7478
|
const plate = width * 1.45;
|
|
7463
7479
|
const plateHeight = width * 0.24;
|
|
7464
|
-
(0,
|
|
7480
|
+
(0, import_react21.useEffect)(() => {
|
|
7465
7481
|
const m = new THREE20.Matrix4();
|
|
7466
7482
|
const q = new THREE20.Quaternion();
|
|
7467
7483
|
const scale = new THREE20.Vector3(1, 1, 1);
|
|
@@ -7505,7 +7521,7 @@ function Doorway({
|
|
|
7505
7521
|
color,
|
|
7506
7522
|
extent
|
|
7507
7523
|
}) {
|
|
7508
|
-
const geometry = (0,
|
|
7524
|
+
const geometry = (0, import_react21.useMemo)(() => {
|
|
7509
7525
|
const w = size * 2.4 * opening;
|
|
7510
7526
|
const h = size * 1.8 * opening;
|
|
7511
7527
|
const shape = new THREE20.Shape();
|
|
@@ -7523,8 +7539,8 @@ function Doorway({
|
|
|
7523
7539
|
shape.holes.push(hole);
|
|
7524
7540
|
return new THREE20.ShapeGeometry(shape);
|
|
7525
7541
|
}, [size, opening, extent]);
|
|
7526
|
-
(0,
|
|
7527
|
-
const stood = (0,
|
|
7542
|
+
(0, import_react21.useEffect)(() => () => geometry.dispose(), [geometry]);
|
|
7543
|
+
const stood = (0, import_react21.useMemo)(
|
|
7528
7544
|
() => [position[0] + Math.sin(yaw) * NUDGE, position[1], position[2] + Math.cos(yaw) * NUDGE],
|
|
7529
7545
|
[position, yaw]
|
|
7530
7546
|
);
|
|
@@ -7533,7 +7549,7 @@ function Doorway({
|
|
|
7533
7549
|
|
|
7534
7550
|
// src/stage/Suspension.tsx
|
|
7535
7551
|
var THREE21 = __toESM(require("three"), 1);
|
|
7536
|
-
var
|
|
7552
|
+
var import_react22 = require("react");
|
|
7537
7553
|
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
7538
7554
|
var euler = (pose) => new THREE21.Euler(pose.rotation[0], pose.rotation[1], pose.rotation[2]);
|
|
7539
7555
|
function rodLength(sheet2, pose) {
|
|
@@ -7557,13 +7573,13 @@ function Suspension({
|
|
|
7557
7573
|
type,
|
|
7558
7574
|
hardware
|
|
7559
7575
|
}) {
|
|
7560
|
-
const poses = (0,
|
|
7576
|
+
const poses = (0, import_react22.useMemo)(() => {
|
|
7561
7577
|
const entry = getLayout(layout);
|
|
7562
7578
|
if (!entry) return [];
|
|
7563
7579
|
const options = entry.optionsSchema.parse(layoutOptions);
|
|
7564
7580
|
return Array.from({ length: count }, (_, i) => entry.pose(i, count, options, 0, sheet2));
|
|
7565
7581
|
}, [layout, layoutOptions, count, sheet2]);
|
|
7566
|
-
const geometry = (0,
|
|
7582
|
+
const geometry = (0, import_react22.useMemo)(() => {
|
|
7567
7583
|
const points = [];
|
|
7568
7584
|
const end = new THREE21.Vector3();
|
|
7569
7585
|
for (const pose of poses) {
|
|
@@ -7583,17 +7599,17 @@ function Suspension({
|
|
|
7583
7599
|
g.setAttribute("position", new THREE21.Float32BufferAttribute(points, 3));
|
|
7584
7600
|
return g;
|
|
7585
7601
|
}, [poses, paperHeight, ceiling, type, sheet2]);
|
|
7586
|
-
(0,
|
|
7587
|
-
const clipRef = (0,
|
|
7588
|
-
const rodRef = (0,
|
|
7589
|
-
const rodGeometry = (0,
|
|
7602
|
+
(0, import_react22.useEffect)(() => () => geometry.dispose(), [geometry]);
|
|
7603
|
+
const clipRef = (0, import_react22.useRef)(null);
|
|
7604
|
+
const rodRef = (0, import_react22.useRef)(null);
|
|
7605
|
+
const rodGeometry = (0, import_react22.useMemo)(() => {
|
|
7590
7606
|
const r = sheet2.width * 0.018;
|
|
7591
7607
|
const g = new THREE21.CylinderGeometry(r, r, sheet2.width * 1.22, 8);
|
|
7592
7608
|
g.rotateZ(Math.PI / 2);
|
|
7593
7609
|
return g;
|
|
7594
7610
|
}, [sheet2.width]);
|
|
7595
|
-
(0,
|
|
7596
|
-
(0,
|
|
7611
|
+
(0, import_react22.useEffect)(() => () => rodGeometry.dispose(), [rodGeometry]);
|
|
7612
|
+
(0, import_react22.useEffect)(() => {
|
|
7597
7613
|
const m = new THREE21.Matrix4();
|
|
7598
7614
|
const q = new THREE21.Quaternion();
|
|
7599
7615
|
const at = new THREE21.Vector3();
|
|
@@ -7984,8 +8000,8 @@ function travelBetween(from, to, t, closed) {
|
|
|
7984
8000
|
}
|
|
7985
8001
|
|
|
7986
8002
|
// src/stage/useWalk.ts
|
|
7987
|
-
var
|
|
7988
|
-
var
|
|
8003
|
+
var import_react23 = require("react");
|
|
8004
|
+
var import_fiber10 = require("@react-three/fiber");
|
|
7989
8005
|
function useWalk({
|
|
7990
8006
|
path,
|
|
7991
8007
|
motion,
|
|
@@ -7995,15 +8011,15 @@ function useWalk({
|
|
|
7995
8011
|
reduced,
|
|
7996
8012
|
onProgress
|
|
7997
8013
|
}) {
|
|
7998
|
-
const gl = (0,
|
|
7999
|
-
const walk = (0,
|
|
8000
|
-
const velocity = (0,
|
|
8001
|
-
const dragged = (0,
|
|
8002
|
-
const travel = (0,
|
|
8014
|
+
const gl = (0, import_fiber10.useThree)((s) => s.gl);
|
|
8015
|
+
const walk = (0, import_react23.useRef)(progress ?? 0);
|
|
8016
|
+
const velocity = (0, import_react23.useRef)(0);
|
|
8017
|
+
const dragged = (0, import_react23.useRef)(false);
|
|
8018
|
+
const travel = (0, import_react23.useRef)(null);
|
|
8003
8019
|
const controlled = progress !== void 0;
|
|
8004
8020
|
const interactive = !controlled && motion.driver === "drag";
|
|
8005
|
-
const engaged = (0,
|
|
8006
|
-
const travelTo = (0,
|
|
8021
|
+
const engaged = (0, import_react23.useRef)(false);
|
|
8022
|
+
const travelTo = (0, import_react23.useCallback)(
|
|
8007
8023
|
(target) => {
|
|
8008
8024
|
engaged.current = true;
|
|
8009
8025
|
velocity.current = 0;
|
|
@@ -8017,14 +8033,14 @@ function useWalk({
|
|
|
8017
8033
|
},
|
|
8018
8034
|
[path.closed, reduced]
|
|
8019
8035
|
);
|
|
8020
|
-
const step = (0,
|
|
8036
|
+
const step = (0, import_react23.useCallback)(
|
|
8021
8037
|
(direction) => {
|
|
8022
8038
|
const from = travel.current?.to ?? walk.current;
|
|
8023
8039
|
travelTo(nextStop(stops, from, direction, path.closed));
|
|
8024
8040
|
},
|
|
8025
8041
|
[stops, path.closed, travelTo]
|
|
8026
8042
|
);
|
|
8027
|
-
(0,
|
|
8043
|
+
(0, import_react23.useEffect)(() => {
|
|
8028
8044
|
if (controlled) {
|
|
8029
8045
|
walk.current = progress;
|
|
8030
8046
|
travel.current = null;
|
|
@@ -8032,7 +8048,7 @@ function useWalk({
|
|
|
8032
8048
|
}
|
|
8033
8049
|
}, [controlled, progress]);
|
|
8034
8050
|
const canvas = gl.domElement;
|
|
8035
|
-
(0,
|
|
8051
|
+
(0, import_react23.useEffect)(() => {
|
|
8036
8052
|
if (!interactive) return;
|
|
8037
8053
|
const hadTabIndex = canvas.hasAttribute("tabindex");
|
|
8038
8054
|
if (!hadTabIndex) canvas.tabIndex = 0;
|
|
@@ -8123,8 +8139,8 @@ function useWalk({
|
|
|
8123
8139
|
if (!hadLabel) canvas.removeAttribute("aria-label");
|
|
8124
8140
|
};
|
|
8125
8141
|
}, [canvas, interactive, motion.speed, motion.capture, path.closed, step, travelTo, stops]);
|
|
8126
|
-
const reported = (0,
|
|
8127
|
-
(0,
|
|
8142
|
+
const reported = (0, import_react23.useRef)(-1);
|
|
8143
|
+
(0, import_fiber10.useFrame)((_, delta) => {
|
|
8128
8144
|
if (onProgress && Math.abs(walk.current - reported.current) > 1e-4) {
|
|
8129
8145
|
reported.current = walk.current;
|
|
8130
8146
|
onProgress(walk.current);
|
|
@@ -8150,7 +8166,7 @@ function useWalk({
|
|
|
8150
8166
|
if (!path.closed && (walk.current <= 0 || walk.current >= 1)) velocity.current = 0;
|
|
8151
8167
|
}
|
|
8152
8168
|
});
|
|
8153
|
-
return (0,
|
|
8169
|
+
return (0, import_react23.useMemo)(() => ({ walk, travelTo, step, dragged }), [travelTo, step]);
|
|
8154
8170
|
}
|
|
8155
8171
|
|
|
8156
8172
|
// src/stage/quality.ts
|
|
@@ -8270,13 +8286,13 @@ function ShotRig({
|
|
|
8270
8286
|
paperHeight,
|
|
8271
8287
|
walk
|
|
8272
8288
|
}) {
|
|
8273
|
-
const camera = (0,
|
|
8274
|
-
const path = (0,
|
|
8275
|
-
const scale = (0,
|
|
8289
|
+
const camera = (0, import_fiber11.useThree)((s) => s.camera);
|
|
8290
|
+
const path = (0, import_react24.useMemo)(() => getWalkPath(stage.path), [stage.path]);
|
|
8291
|
+
const scale = (0, import_react24.useMemo)(
|
|
8276
8292
|
() => ({ figure: stage.figure.height, paper: paperHeight }),
|
|
8277
8293
|
[stage.figure.height, paperHeight]
|
|
8278
8294
|
);
|
|
8279
|
-
(0,
|
|
8295
|
+
(0, import_fiber11.useFrame)(() => {
|
|
8280
8296
|
const { position, target } = stageCamera(path, walk.current * path.length, scale, stage.shot);
|
|
8281
8297
|
camera.position.set(position[0], position[1], position[2]);
|
|
8282
8298
|
camera.lookAt(target[0], target[1], target[2]);
|
|
@@ -8284,17 +8300,17 @@ function ShotRig({
|
|
|
8284
8300
|
return null;
|
|
8285
8301
|
}
|
|
8286
8302
|
function QualityWatch({ tier, onChange }) {
|
|
8287
|
-
const samples = (0,
|
|
8288
|
-
const settle2 = (0,
|
|
8289
|
-
const window2 = (0,
|
|
8290
|
-
const failed = (0,
|
|
8291
|
-
const settled = (0,
|
|
8303
|
+
const samples = (0, import_react24.useRef)([]);
|
|
8304
|
+
const settle2 = (0, import_react24.useRef)(SETTLE_FRAMES);
|
|
8305
|
+
const window2 = (0, import_react24.useRef)(FIRST_WINDOW);
|
|
8306
|
+
const failed = (0, import_react24.useRef)(null);
|
|
8307
|
+
const settled = (0, import_react24.useCallback)((next) => {
|
|
8292
8308
|
samples.current = [];
|
|
8293
8309
|
settle2.current = SETTLE_FRAMES;
|
|
8294
8310
|
window2.current = STEADY_WINDOW;
|
|
8295
8311
|
return next;
|
|
8296
8312
|
}, []);
|
|
8297
|
-
(0,
|
|
8313
|
+
(0, import_fiber11.useFrame)((_, delta) => {
|
|
8298
8314
|
if (settle2.current > 0) {
|
|
8299
8315
|
settle2.current -= 1;
|
|
8300
8316
|
return;
|
|
@@ -8331,41 +8347,41 @@ function PaperStageScene({
|
|
|
8331
8347
|
reducedMotion
|
|
8332
8348
|
}) {
|
|
8333
8349
|
const still = usePrefersReducedMotion(reducedMotion);
|
|
8334
|
-
const [tier, setTier] = (0,
|
|
8335
|
-
(0,
|
|
8350
|
+
const [tier, setTier] = (0, import_react24.useState)(quality === "auto" ? INITIAL_TIER : quality);
|
|
8351
|
+
(0, import_react24.useEffect)(() => {
|
|
8336
8352
|
if (quality !== "auto") setTier(quality);
|
|
8337
8353
|
}, [quality]);
|
|
8338
|
-
const reportQuality = (0,
|
|
8339
|
-
(0,
|
|
8354
|
+
const reportQuality = (0, import_react24.useRef)(onQualityChange);
|
|
8355
|
+
(0, import_react24.useEffect)(() => {
|
|
8340
8356
|
reportQuality.current = onQualityChange;
|
|
8341
8357
|
});
|
|
8342
|
-
(0,
|
|
8358
|
+
(0, import_react24.useEffect)(() => {
|
|
8343
8359
|
reportQuality.current?.(tier);
|
|
8344
8360
|
}, [tier]);
|
|
8345
8361
|
const settings = quality === "auto" ? qualityTiers[tier] : qualityFor(quality);
|
|
8346
8362
|
const stageKey = JSON.stringify(stageInput ?? {});
|
|
8347
|
-
const stage = (0,
|
|
8348
|
-
const path = (0,
|
|
8349
|
-
const rig = (0,
|
|
8363
|
+
const stage = (0, import_react24.useMemo)(() => stageSchema.parse(stageInput ?? {}), [stageKey]);
|
|
8364
|
+
const path = (0, import_react24.useMemo)(() => getWalkPath(stage.path), [stage.path]);
|
|
8365
|
+
const rig = (0, import_react24.useMemo)(() => {
|
|
8350
8366
|
const resolved = resolveLighting(stage.lighting, stage.light);
|
|
8351
8367
|
return {
|
|
8352
8368
|
...resolved,
|
|
8353
8369
|
sky: { zenith: stage.source.zenith, horizon: stage.source.color, ground: stage.ground.color }
|
|
8354
8370
|
};
|
|
8355
8371
|
}, [stage.lighting, stage.light, stage.source.zenith, stage.source.color, stage.ground.color]);
|
|
8356
|
-
const sheetDims = (0,
|
|
8372
|
+
const sheetDims = (0, import_react24.useMemo)(() => {
|
|
8357
8373
|
const { width, height } = resolveConfig({ preset: preset ?? BANNER }).sheet;
|
|
8358
8374
|
return { width, height };
|
|
8359
8375
|
}, [preset]);
|
|
8360
8376
|
const paperHeight = sheetDims.height;
|
|
8361
8377
|
const paperWidth = sheetDims.width;
|
|
8362
8378
|
const paper = preset ?? BANNER;
|
|
8363
|
-
const resolvedLayoutOptions = (0,
|
|
8379
|
+
const resolvedLayoutOptions = (0, import_react24.useMemo)(() => {
|
|
8364
8380
|
const schema = getLayout(layout).optionsSchema;
|
|
8365
8381
|
const takesPath = schema instanceof import_zod29.z.ZodObject && "path" in schema.shape;
|
|
8366
8382
|
return takesPath ? { ...layoutOptions, path: stage.path } : layoutOptions;
|
|
8367
8383
|
}, [layout, layoutOptions, stage.path]);
|
|
8368
|
-
const slots = (0,
|
|
8384
|
+
const slots = (0, import_react24.useMemo)(() => {
|
|
8369
8385
|
if (papers) return papers;
|
|
8370
8386
|
if (images) return void 0;
|
|
8371
8387
|
if (text !== void 0) {
|
|
@@ -8403,7 +8419,7 @@ function PaperStageScene({
|
|
|
8403
8419
|
}, [papers, images, text, count, sheetDims]);
|
|
8404
8420
|
const drive = stageMotionSchema.parse(motion ?? {});
|
|
8405
8421
|
const slotCount = slots?.length ?? images?.length ?? count;
|
|
8406
|
-
const stops = (0,
|
|
8422
|
+
const stops = (0, import_react24.useMemo)(() => {
|
|
8407
8423
|
const spec = getLayout(layout);
|
|
8408
8424
|
const placed = spec.walkStops?.(slotCount, spec.optionsSchema.parse(resolvedLayoutOptions ?? {}));
|
|
8409
8425
|
if (placed && placed.length > 0) return placed;
|
|
@@ -8418,11 +8434,11 @@ function PaperStageScene({
|
|
|
8418
8434
|
reduced: still,
|
|
8419
8435
|
onProgress
|
|
8420
8436
|
});
|
|
8421
|
-
const surroundRadius = (0,
|
|
8437
|
+
const surroundRadius = (0, import_react24.useMemo)(
|
|
8422
8438
|
() => Math.max(path.length * 1.6, paperHeight * 9),
|
|
8423
8439
|
[path.length, paperHeight]
|
|
8424
8440
|
);
|
|
8425
|
-
const source = (0,
|
|
8441
|
+
const source = (0, import_react24.useMemo)(() => {
|
|
8426
8442
|
const [x, z30] = walkPoint(path, path.length + stage.source.beyond);
|
|
8427
8443
|
const [tx, tz] = path.tangentAt(1);
|
|
8428
8444
|
const size = paperHeight * stage.source.spread;
|
|
@@ -8525,7 +8541,7 @@ function PaperStageScene({
|
|
|
8525
8541
|
function PaperStage({ children, className, style, ...sceneProps }) {
|
|
8526
8542
|
const dpr = qualityFor(sceneProps.quality ?? "auto").dpr;
|
|
8527
8543
|
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className, style: { width: "100%", height: "100%", ...style }, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
8528
|
-
|
|
8544
|
+
import_fiber11.Canvas,
|
|
8529
8545
|
{
|
|
8530
8546
|
shadows: true,
|
|
8531
8547
|
dpr: [1, dpr],
|
|
@@ -8535,7 +8551,8 @@ function PaperStage({ children, className, style, ...sceneProps }) {
|
|
|
8535
8551
|
},
|
|
8536
8552
|
children: [
|
|
8537
8553
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(PaperStageScene, { ...sceneProps }),
|
|
8538
|
-
children
|
|
8554
|
+
children,
|
|
8555
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ReleaseContextOnUnmount, {})
|
|
8539
8556
|
]
|
|
8540
8557
|
}
|
|
8541
8558
|
) });
|
|
@@ -8964,7 +8981,11 @@ function describeStage(input) {
|
|
|
8964
8981
|
);
|
|
8965
8982
|
const moved = Object.entries(stage.light).filter(([, value]) => value !== void 0).map(([key]) => key);
|
|
8966
8983
|
if (moved.length > 0) parts.push(`with its ${moved.join(", ")} set by hand`);
|
|
8967
|
-
if (input.scroll)
|
|
8984
|
+
if (input.scroll) {
|
|
8985
|
+
parts.push(
|
|
8986
|
+
stage.showFigure ? "and scrolling the page walks the figure deeper into it" : "and scrolling the page carries the camera deeper into it"
|
|
8987
|
+
);
|
|
8988
|
+
}
|
|
8968
8989
|
return parts.join(", ");
|
|
8969
8990
|
}
|
|
8970
8991
|
function exportableImages(images) {
|
|
@@ -9005,6 +9026,7 @@ const banner = ${stringifyStage(diffConfig(paperConfigSchema.parse(input.paper))
|
|
|
9005
9026
|
const textConst = input.text?.trim() ? `
|
|
9006
9027
|
|
|
9007
9028
|
const text = ${JSON.stringify(input.text)}` : "";
|
|
9029
|
+
const scrolls = stageSchema.parse(input.stage).showFigure ? "walk the figure" : "move the camera";
|
|
9008
9030
|
const images = input.images?.length ? exportableImages(input.images) : null;
|
|
9009
9031
|
const imagesConst = images ? `
|
|
9010
9032
|
${images.substituted ? "\n// Your uploaded pictures cannot travel in a snippet \u2014 these are\n// placeholders in the same order. Point them at your own files." : ""}
|
|
@@ -9031,7 +9053,7 @@ export function ${name}() {
|
|
|
9031
9053
|
const ref = useRef<HTMLDivElement>(null)
|
|
9032
9054
|
const [progress, setProgress] = useState(0)
|
|
9033
9055
|
|
|
9034
|
-
// Scroll the section,
|
|
9056
|
+
// Scroll the section, ${scrolls}. The stage is pinned for the height
|
|
9035
9057
|
// of the section, so the page scrolling past it IS the walk.
|
|
9036
9058
|
useEffect(() => {
|
|
9037
9059
|
const el = ref.current
|
|
@@ -9068,7 +9090,8 @@ function buildStageAgentPayload(input) {
|
|
|
9068
9090
|
heights of scroll and pins the canvas inside that. Drop it into the page
|
|
9069
9091
|
flow as a section; do NOT wrap it in a fixed-height container.` : `4. Sizing: the component fills its parent container. Place it where I ask;
|
|
9070
9092
|
give the parent an explicit height.`;
|
|
9071
|
-
|
|
9093
|
+
const subject = stageSchema.parse(input.stage).showFigure ? "paper as architecture, with a figure walking through it" : "paper as architecture, banners hung along a walk you move through";
|
|
9094
|
+
return `Integrate a Paperlab stage \u2014 ${subject} \u2014 into this project. (paperlab agent-payload v${AGENT_PAYLOAD_VERSION})
|
|
9072
9095
|
|
|
9073
9096
|
1. Install the dependencies:
|
|
9074
9097
|
|