paperlab 0.5.0 → 0.5.2
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 +258 -234
- package/dist/stage.cjs.map +1 -1
- package/dist/stage.js +17 -8
- package/dist/stage.js.map +1 -1
- package/package.json +3 -3
- package/dist/chunk-6IADJZX5.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -107,8 +107,8 @@ __export(index_exports, {
|
|
|
107
107
|
module.exports = __toCommonJS(index_exports);
|
|
108
108
|
|
|
109
109
|
// src/Paper.tsx
|
|
110
|
-
var
|
|
111
|
-
var
|
|
110
|
+
var import_fiber5 = require("@react-three/fiber");
|
|
111
|
+
var import_react11 = require("react");
|
|
112
112
|
|
|
113
113
|
// src/PaperMesh.tsx
|
|
114
114
|
var THREE7 = __toESM(require("three"), 1);
|
|
@@ -5090,13 +5090,28 @@ function paintBackdrop(backdrop, width, height, image) {
|
|
|
5090
5090
|
return texture;
|
|
5091
5091
|
}
|
|
5092
5092
|
|
|
5093
|
+
// src/scene/release.tsx
|
|
5094
|
+
var import_fiber4 = require("@react-three/fiber");
|
|
5095
|
+
var import_react10 = require("react");
|
|
5096
|
+
function ReleaseContextOnUnmount() {
|
|
5097
|
+
const gl = (0, import_fiber4.useThree)((s) => s.gl);
|
|
5098
|
+
(0, import_react10.useEffect)(
|
|
5099
|
+
() => () => {
|
|
5100
|
+
gl.forceContextLoss();
|
|
5101
|
+
gl.dispose();
|
|
5102
|
+
},
|
|
5103
|
+
[gl]
|
|
5104
|
+
);
|
|
5105
|
+
return null;
|
|
5106
|
+
}
|
|
5107
|
+
|
|
5093
5108
|
// src/Paper.tsx
|
|
5094
5109
|
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
5095
|
-
var Paper = (0,
|
|
5110
|
+
var Paper = (0, import_react11.forwardRef)(function Paper2({ children, className, style, ...meshProps }, ref) {
|
|
5096
5111
|
const config = useResolvedConfig(meshProps);
|
|
5097
|
-
const webgl = (0,
|
|
5112
|
+
const webgl = (0, import_react11.useMemo)(() => typeof window === "undefined" ? true : supportsWebGL(), []);
|
|
5098
5113
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className, style: { width: "100%", height: "100%", ...style }, children: [
|
|
5099
|
-
webgl ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
5114
|
+
webgl ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_fiber5.Canvas, { shadows: true, camera: { position: [0, 0.35, 2.4], fov: 40 }, dpr: [1, 2], children: [
|
|
5100
5115
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PaperBackdrop, { backdrop: config.scene.backdrop }),
|
|
5101
5116
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
5102
5117
|
PaperLighting,
|
|
@@ -5109,7 +5124,8 @@ var Paper = (0, import_react10.forwardRef)(function Paper2({ children, className
|
|
|
5109
5124
|
}
|
|
5110
5125
|
),
|
|
5111
5126
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PaperMesh, { ref, ...meshProps }),
|
|
5112
|
-
children
|
|
5127
|
+
children,
|
|
5128
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ReleaseContextOnUnmount, {})
|
|
5113
5129
|
] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PaperFallback, { config }),
|
|
5114
5130
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PaperMirror, { config })
|
|
5115
5131
|
] });
|
|
@@ -5118,12 +5134,12 @@ var Paper = (0, import_react10.forwardRef)(function Paper2({ children, className
|
|
|
5118
5134
|
// src/PaperField.tsx
|
|
5119
5135
|
var THREE16 = __toESM(require("three"), 1);
|
|
5120
5136
|
var import_gsap5 = require("gsap");
|
|
5121
|
-
var
|
|
5122
|
-
var
|
|
5137
|
+
var import_fiber8 = require("@react-three/fiber");
|
|
5138
|
+
var import_react18 = require("react");
|
|
5123
5139
|
|
|
5124
5140
|
// src/field/dropZones.tsx
|
|
5125
5141
|
var THREE11 = __toESM(require("three"), 1);
|
|
5126
|
-
var
|
|
5142
|
+
var import_react12 = require("react");
|
|
5127
5143
|
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
5128
5144
|
var DropZoneRegistry = class {
|
|
5129
5145
|
zones = /* @__PURE__ */ new Map();
|
|
@@ -5162,7 +5178,7 @@ var DropZoneRegistry = class {
|
|
|
5162
5178
|
for (const fn of this.listeners) fn();
|
|
5163
5179
|
}
|
|
5164
5180
|
};
|
|
5165
|
-
var DropZoneContext = (0,
|
|
5181
|
+
var DropZoneContext = (0, import_react12.createContext)(null);
|
|
5166
5182
|
var globCache = /* @__PURE__ */ new Map();
|
|
5167
5183
|
var globRegExp = (glob) => {
|
|
5168
5184
|
let re = globCache.get(glob);
|
|
@@ -5178,13 +5194,13 @@ function zoneAccepts(zone, name) {
|
|
|
5178
5194
|
}
|
|
5179
5195
|
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;
|
|
5180
5196
|
function DropZone(props) {
|
|
5181
|
-
const registry4 = (0,
|
|
5197
|
+
const registry4 = (0, import_react12.useContext)(DropZoneContext);
|
|
5182
5198
|
const { id, accept, bounds, highlight = "glow", onPlace } = props;
|
|
5183
|
-
const place = (0,
|
|
5184
|
-
(0,
|
|
5199
|
+
const place = (0, import_react12.useRef)(onPlace);
|
|
5200
|
+
(0, import_react12.useEffect)(() => {
|
|
5185
5201
|
place.current = onPlace;
|
|
5186
5202
|
}, [onPlace]);
|
|
5187
|
-
(0,
|
|
5203
|
+
(0, import_react12.useEffect)(() => {
|
|
5188
5204
|
if (!registry4) return;
|
|
5189
5205
|
return registry4.register({
|
|
5190
5206
|
id,
|
|
@@ -5198,17 +5214,17 @@ function DropZone(props) {
|
|
|
5198
5214
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(DropZoneVisual, { registry: registry4, config: { id, accept, bounds, highlight } });
|
|
5199
5215
|
}
|
|
5200
5216
|
function DropZoneVisual({ registry: registry4, config }) {
|
|
5201
|
-
(0,
|
|
5217
|
+
(0, import_react12.useSyncExternalStore)(registry4.subscribe, registry4.getVersion, registry4.getVersion);
|
|
5202
5218
|
const hovered = registry4.hovered === config.id;
|
|
5203
5219
|
const style = config.highlight ?? "glow";
|
|
5204
5220
|
const [w, h] = config.bounds.size;
|
|
5205
|
-
const edges = (0,
|
|
5221
|
+
const edges = (0, import_react12.useMemo)(() => {
|
|
5206
5222
|
const plane = new THREE11.PlaneGeometry(w, h);
|
|
5207
5223
|
const geo = new THREE11.EdgesGeometry(plane);
|
|
5208
5224
|
plane.dispose();
|
|
5209
5225
|
return geo;
|
|
5210
5226
|
}, [w, h]);
|
|
5211
|
-
(0,
|
|
5227
|
+
(0, import_react12.useEffect)(() => () => edges.dispose(), [edges]);
|
|
5212
5228
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("group", { position: config.bounds.position, children: [
|
|
5213
5229
|
style !== "outline" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("mesh", { children: [
|
|
5214
5230
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("planeGeometry", { args: [w, h] }),
|
|
@@ -5332,22 +5348,22 @@ function resolveFieldSlotConfig(slot, fallback, index, layoutId, layoutOptions)
|
|
|
5332
5348
|
// src/field/fieldGroup.tsx
|
|
5333
5349
|
var THREE13 = __toESM(require("three"), 1);
|
|
5334
5350
|
var import_gsap3 = require("gsap");
|
|
5335
|
-
var
|
|
5336
|
-
var
|
|
5351
|
+
var import_fiber6 = require("@react-three/fiber");
|
|
5352
|
+
var import_react14 = require("react");
|
|
5337
5353
|
var import_three_custom_shader_material2 = __toESM(require("three-custom-shader-material"), 1);
|
|
5338
5354
|
|
|
5339
5355
|
// src/content/atlas.ts
|
|
5340
5356
|
var THREE12 = __toESM(require("three"), 1);
|
|
5341
|
-
var
|
|
5357
|
+
var import_react13 = require("react");
|
|
5342
5358
|
var MAX_ATLAS = 4096;
|
|
5343
5359
|
function atlasGrid(count, aspect = 1) {
|
|
5344
5360
|
const cols = Math.max(1, Math.min(count, Math.ceil(Math.sqrt(count * Math.max(aspect, 0.01)))));
|
|
5345
5361
|
return { cols, rows: Math.max(1, Math.ceil(count / cols)) };
|
|
5346
5362
|
}
|
|
5347
5363
|
function useContentAtlas(contents, sheet2, stock) {
|
|
5348
|
-
const [atlas, setAtlas] = (0,
|
|
5364
|
+
const [atlas, setAtlas] = (0, import_react13.useState)(null);
|
|
5349
5365
|
const stableContents = useStable(contents);
|
|
5350
|
-
(0,
|
|
5366
|
+
(0, import_react13.useEffect)(() => {
|
|
5351
5367
|
let disposed = false;
|
|
5352
5368
|
const aspect = sheet2.height / sheet2.width;
|
|
5353
5369
|
const { cols, rows } = atlasGrid(contents.length, aspect);
|
|
@@ -6080,11 +6096,11 @@ function FieldGroup({
|
|
|
6080
6096
|
const stock = getStock(config.stock);
|
|
6081
6097
|
const rig = useLightRig(config.scene.lighting);
|
|
6082
6098
|
const behavior = config.behavior && !config.deformers ? getBehavior(config.behavior.type) : null;
|
|
6083
|
-
const progressRef = (0,
|
|
6099
|
+
const progressRef = (0, import_react14.useRef)(
|
|
6084
6100
|
behavior ? config.behavior[behavior.progressParam] : 0
|
|
6085
6101
|
);
|
|
6086
6102
|
const buildStackAt = (progress) => fieldShapeStack(config, progress);
|
|
6087
|
-
const initialStack = (0,
|
|
6103
|
+
const initialStack = (0, import_react14.useMemo)(
|
|
6088
6104
|
() => buildStackAt(progressRef.current),
|
|
6089
6105
|
[
|
|
6090
6106
|
JSON.stringify(config.behavior ?? null),
|
|
@@ -6093,7 +6109,7 @@ function FieldGroup({
|
|
|
6093
6109
|
]
|
|
6094
6110
|
);
|
|
6095
6111
|
const structureKey = initialStack.map((i) => i.type).join("|");
|
|
6096
|
-
const geometry = (0,
|
|
6112
|
+
const geometry = (0, import_react14.useMemo)(() => {
|
|
6097
6113
|
const floor = stackMinSegments(initialStack, config.sheet);
|
|
6098
6114
|
const want = [0, 0];
|
|
6099
6115
|
for (const p of PROGRESS_SAMPLES2) {
|
|
@@ -6127,9 +6143,9 @@ function FieldGroup({
|
|
|
6127
6143
|
geo.setAttribute("aBias", new THREE13.InstancedBufferAttribute(bias, 1));
|
|
6128
6144
|
return geo;
|
|
6129
6145
|
}, [JSON.stringify(config.sheet), structureKey, count, autoCeiling]);
|
|
6130
|
-
(0,
|
|
6146
|
+
(0, import_react14.useEffect)(() => () => geometry.dispose(), [geometry]);
|
|
6131
6147
|
const atlas = useContentAtlas(contents, config.sheet, stock);
|
|
6132
|
-
const shader = (0,
|
|
6148
|
+
const shader = (0, import_react14.useMemo)(() => {
|
|
6133
6149
|
const composed = buildDisplacementGLSL(initialStack, config.sheet);
|
|
6134
6150
|
const uniforms = {};
|
|
6135
6151
|
for (const [name, value] of Object.entries(composed.uniforms)) {
|
|
@@ -6158,19 +6174,19 @@ function FieldGroup({
|
|
|
6158
6174
|
config.surface.showThrough,
|
|
6159
6175
|
config.surface.translucency
|
|
6160
6176
|
]);
|
|
6161
|
-
(0,
|
|
6177
|
+
(0, import_react14.useEffect)(() => {
|
|
6162
6178
|
const values = translucencyValues(config.surface.translucency ?? stock.translucency, rig);
|
|
6163
6179
|
shader.uniforms.uTranslucency.value = values.translucency;
|
|
6164
6180
|
shader.uniforms.uBackLightDir.value.copy(values.direction);
|
|
6165
6181
|
shader.uniforms.uBackLightColor.value.copy(values.color);
|
|
6166
6182
|
shader.uniforms.uAmbientTransmission.value = values.ambient;
|
|
6167
6183
|
}, [shader, rig, config.surface.translucency, stock.translucency]);
|
|
6168
|
-
(0,
|
|
6184
|
+
(0, import_react14.useEffect)(() => {
|
|
6169
6185
|
if (!atlas) return;
|
|
6170
6186
|
shader.uniforms.uAtlas.value = atlas.texture;
|
|
6171
6187
|
shader.uniforms.uAtlasGrid.value.set(atlas.cols, atlas.rows);
|
|
6172
6188
|
}, [atlas, shader]);
|
|
6173
|
-
(0,
|
|
6189
|
+
(0, import_react14.useEffect)(() => {
|
|
6174
6190
|
if (!behavior || shared.reduced) return;
|
|
6175
6191
|
const state = { p: progressRef.current };
|
|
6176
6192
|
const tween = import_gsap3.gsap.to(state, {
|
|
@@ -6187,8 +6203,8 @@ function FieldGroup({
|
|
|
6187
6203
|
tween.kill();
|
|
6188
6204
|
};
|
|
6189
6205
|
}, [structureKey, shared.reduced]);
|
|
6190
|
-
const meshRef = (0,
|
|
6191
|
-
(0,
|
|
6206
|
+
const meshRef = (0, import_react14.useRef)(null);
|
|
6207
|
+
(0, import_fiber6.useFrame)(({ clock }) => {
|
|
6192
6208
|
const mesh = meshRef.current;
|
|
6193
6209
|
if (!mesh) return;
|
|
6194
6210
|
const elapsed = clock.elapsedTime - Math.max(shared.mountTimeRef.current, 0);
|
|
@@ -6335,7 +6351,7 @@ var easeInOut = (t) => t < 0.5 ? 2 * t * t : 1 - (-2 * t + 2) ** 2 / 2;
|
|
|
6335
6351
|
|
|
6336
6352
|
// src/field/backingSheet.tsx
|
|
6337
6353
|
var THREE14 = __toESM(require("three"), 1);
|
|
6338
|
-
var
|
|
6354
|
+
var import_react15 = require("react");
|
|
6339
6355
|
|
|
6340
6356
|
// src/content/backing.ts
|
|
6341
6357
|
function silhouetteRects(o, count) {
|
|
@@ -6408,7 +6424,7 @@ function BackingSheet({
|
|
|
6408
6424
|
removed
|
|
6409
6425
|
}) {
|
|
6410
6426
|
const { width, height } = sheetBackingSize(options);
|
|
6411
|
-
const canvas = (0,
|
|
6427
|
+
const canvas = (0, import_react15.useMemo)(() => {
|
|
6412
6428
|
if (typeof document === "undefined") return null;
|
|
6413
6429
|
const c = document.createElement("canvas");
|
|
6414
6430
|
const scale = Math.min(1024, Math.round(360 * Math.max(width, height))) / Math.max(width, height);
|
|
@@ -6416,14 +6432,14 @@ function BackingSheet({
|
|
|
6416
6432
|
c.height = Math.max(2, Math.round(height * scale));
|
|
6417
6433
|
return c;
|
|
6418
6434
|
}, [width, height]);
|
|
6419
|
-
const texture = (0,
|
|
6435
|
+
const texture = (0, import_react15.useMemo)(() => canvas ? new THREE14.CanvasTexture(canvas) : null, [canvas]);
|
|
6420
6436
|
const removedKey = [...removed].sort((a, b) => a - b).join(",");
|
|
6421
|
-
(0,
|
|
6437
|
+
(0, import_react15.useEffect)(() => {
|
|
6422
6438
|
if (!canvas || !texture) return;
|
|
6423
6439
|
drawBacking(canvas, { options, count, tint: BACKING_TINT, removed });
|
|
6424
6440
|
texture.needsUpdate = true;
|
|
6425
6441
|
}, [canvas, texture, JSON.stringify(options), count, removedKey]);
|
|
6426
|
-
(0,
|
|
6442
|
+
(0, import_react15.useEffect)(() => () => texture?.dispose(), [texture]);
|
|
6427
6443
|
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("mesh", { receiveShadow: true, children: [
|
|
6428
6444
|
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("planeGeometry", { args: [width, height] }),
|
|
6429
6445
|
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("meshStandardMaterial", { map: texture, color: "#ffffff", roughness: 0.92, metalness: 0 })
|
|
@@ -6433,8 +6449,8 @@ function BackingSheet({
|
|
|
6433
6449
|
// src/field/interactiveField.tsx
|
|
6434
6450
|
var THREE15 = __toESM(require("three"), 1);
|
|
6435
6451
|
var import_gsap4 = require("gsap");
|
|
6436
|
-
var
|
|
6437
|
-
var
|
|
6452
|
+
var import_fiber7 = require("@react-three/fiber");
|
|
6453
|
+
var import_react16 = require("react");
|
|
6438
6454
|
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
6439
6455
|
var PICK_BEHAVIORS = /* @__PURE__ */ new Set(["peel", "carry"]);
|
|
6440
6456
|
function InteractiveField(props) {
|
|
@@ -6442,15 +6458,15 @@ function InteractiveField(props) {
|
|
|
6442
6458
|
const total = papers.length;
|
|
6443
6459
|
const layout = getLayout(layoutId);
|
|
6444
6460
|
const reduced = usePrefersReducedMotion(props.reducedMotion);
|
|
6445
|
-
const contextRegistry = (0,
|
|
6446
|
-
const registry4 = (0,
|
|
6447
|
-
const camera = (0,
|
|
6448
|
-
const gl = (0,
|
|
6449
|
-
const controls = (0,
|
|
6450
|
-
const [removed, setRemoved] = (0,
|
|
6451
|
-
const [slotPatches, setSlotPatches] = (0,
|
|
6452
|
-
const [slotStates, setSlotStates] = (0,
|
|
6453
|
-
const slotConfigs = (0,
|
|
6461
|
+
const contextRegistry = (0, import_react16.useContext)(DropZoneContext);
|
|
6462
|
+
const registry4 = (0, import_react16.useMemo)(() => contextRegistry ?? new DropZoneRegistry(), [contextRegistry]);
|
|
6463
|
+
const camera = (0, import_fiber7.useThree)((s) => s.camera);
|
|
6464
|
+
const gl = (0, import_fiber7.useThree)((s) => s.gl);
|
|
6465
|
+
const controls = (0, import_fiber7.useThree)((s) => s.controls);
|
|
6466
|
+
const [removed, setRemoved] = (0, import_react16.useState)(EMPTY_SET);
|
|
6467
|
+
const [slotPatches, setSlotPatches] = (0, import_react16.useState)({});
|
|
6468
|
+
const [slotStates, setSlotStates] = (0, import_react16.useState)({});
|
|
6469
|
+
const slotConfigs = (0, import_react16.useMemo)(
|
|
6454
6470
|
() => papers.map((slot, i) => {
|
|
6455
6471
|
const config = resolveFieldSlotConfig(slot, fallback, i, layoutId, layoutOptions);
|
|
6456
6472
|
const patch = slotPatches[i];
|
|
@@ -6464,14 +6480,14 @@ function InteractiveField(props) {
|
|
|
6464
6480
|
slotPatches
|
|
6465
6481
|
]
|
|
6466
6482
|
);
|
|
6467
|
-
const poses = (0,
|
|
6483
|
+
const poses = (0, import_react16.useMemo)(
|
|
6468
6484
|
() => slotConfigs.map((_, i) => layout.pose(i, total, layoutOptions, 0, props.sheet)),
|
|
6469
6485
|
[layoutId, JSON.stringify(layoutOptions), total, props.sheet.width, props.sheet.height]
|
|
6470
6486
|
);
|
|
6471
|
-
const groupRefs = (0,
|
|
6472
|
-
const handleRefs = (0,
|
|
6473
|
-
const pressRef = (0,
|
|
6474
|
-
const carriedRef = (0,
|
|
6487
|
+
const groupRefs = (0, import_react16.useRef)([]);
|
|
6488
|
+
const handleRefs = (0, import_react16.useRef)([]);
|
|
6489
|
+
const pressRef = (0, import_react16.useRef)(null);
|
|
6490
|
+
const carriedRef = (0, import_react16.useRef)(null);
|
|
6475
6491
|
const zonesLive = () => [...props.zones ?? [], ...registry4.list()];
|
|
6476
6492
|
const slotName = (i) => {
|
|
6477
6493
|
const preset = papers[i]?.preset ?? fallback;
|
|
@@ -6484,10 +6500,10 @@ function InteractiveField(props) {
|
|
|
6484
6500
|
}
|
|
6485
6501
|
props.onSlotStateChange?.(i, state);
|
|
6486
6502
|
};
|
|
6487
|
-
const raycaster = (0,
|
|
6488
|
-
const planeScratch = (0,
|
|
6489
|
-
const pointScratch = (0,
|
|
6490
|
-
const ndcScratch = (0,
|
|
6503
|
+
const raycaster = (0, import_react16.useMemo)(() => new THREE15.Raycaster(), []);
|
|
6504
|
+
const planeScratch = (0, import_react16.useMemo)(() => new THREE15.Plane(new THREE15.Vector3(0, 0, 1), 0), []);
|
|
6505
|
+
const pointScratch = (0, import_react16.useMemo)(() => new THREE15.Vector3(), []);
|
|
6506
|
+
const ndcScratch = (0, import_react16.useMemo)(() => new THREE15.Vector2(), []);
|
|
6491
6507
|
const planePoint = (clientX, clientY, planeZ) => {
|
|
6492
6508
|
const rect = gl.domElement.getBoundingClientRect();
|
|
6493
6509
|
ndcScratch.set(
|
|
@@ -6617,7 +6633,7 @@ function InteractiveField(props) {
|
|
|
6617
6633
|
import_gsap4.gsap.to(group.rotation, { x: home.rotation[0], y: home.rotation[1], z: home.rotation[2], duration });
|
|
6618
6634
|
import_gsap4.gsap.to(group.scale, { x: home.scale, y: home.scale, z: home.scale, duration: duration * 0.5 });
|
|
6619
6635
|
};
|
|
6620
|
-
const onPointerMoveRef = (0,
|
|
6636
|
+
const onPointerMoveRef = (0, import_react16.useRef)(() => {
|
|
6621
6637
|
});
|
|
6622
6638
|
onPointerMoveRef.current = (e) => {
|
|
6623
6639
|
const press = pressRef.current;
|
|
@@ -6641,7 +6657,7 @@ function InteractiveField(props) {
|
|
|
6641
6657
|
pick(slot, hit[0], hit[1], pointerId);
|
|
6642
6658
|
}
|
|
6643
6659
|
};
|
|
6644
|
-
const onPointerUpRef = (0,
|
|
6660
|
+
const onPointerUpRef = (0, import_react16.useRef)(() => {
|
|
6645
6661
|
});
|
|
6646
6662
|
onPointerUpRef.current = (e) => {
|
|
6647
6663
|
pressRef.current = null;
|
|
@@ -6655,7 +6671,7 @@ function InteractiveField(props) {
|
|
|
6655
6671
|
if (zone) settleInto(carried, zone);
|
|
6656
6672
|
else returnHome(carried);
|
|
6657
6673
|
};
|
|
6658
|
-
(0,
|
|
6674
|
+
(0, import_react16.useEffect)(() => {
|
|
6659
6675
|
const move = (e) => onPointerMoveRef.current(e);
|
|
6660
6676
|
const up = (e) => onPointerUpRef.current(e);
|
|
6661
6677
|
window.addEventListener("pointermove", move);
|
|
@@ -6665,7 +6681,7 @@ function InteractiveField(props) {
|
|
|
6665
6681
|
window.removeEventListener("pointerup", up);
|
|
6666
6682
|
};
|
|
6667
6683
|
}, []);
|
|
6668
|
-
(0,
|
|
6684
|
+
(0, import_fiber7.useFrame)((_, delta) => {
|
|
6669
6685
|
const carried = carriedRef.current;
|
|
6670
6686
|
if (!carried || carried.settling) return;
|
|
6671
6687
|
const group = groupRefs.current[carried.slot];
|
|
@@ -6703,7 +6719,7 @@ function InteractiveField(props) {
|
|
|
6703
6719
|
group.scale.x += (targetScale - group.scale.x) * 0.15;
|
|
6704
6720
|
group.scale.y = group.scale.z = group.scale.x;
|
|
6705
6721
|
});
|
|
6706
|
-
const a11yImplRef = (0,
|
|
6722
|
+
const a11yImplRef = (0, import_react16.useRef)(null);
|
|
6707
6723
|
a11yImplRef.current = {
|
|
6708
6724
|
pick: (slot) => {
|
|
6709
6725
|
const home = poses[slot];
|
|
@@ -6728,7 +6744,7 @@ function InteractiveField(props) {
|
|
|
6728
6744
|
zoneIds: () => zonesLive().map((z25) => z25.id),
|
|
6729
6745
|
slotState: (slot) => slotStates[slot] ?? "rest"
|
|
6730
6746
|
};
|
|
6731
|
-
(0,
|
|
6747
|
+
(0, import_react16.useEffect)(() => {
|
|
6732
6748
|
const ref = props.a11yRef;
|
|
6733
6749
|
if (!ref) return;
|
|
6734
6750
|
ref.current = {
|
|
@@ -6781,7 +6797,7 @@ function InteractiveField(props) {
|
|
|
6781
6797
|
}
|
|
6782
6798
|
|
|
6783
6799
|
// src/field/keyboardMirror.tsx
|
|
6784
|
-
var
|
|
6800
|
+
var import_react17 = require("react");
|
|
6785
6801
|
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
6786
6802
|
function fieldKeyboardStep(carry2, slot, key, controller) {
|
|
6787
6803
|
if (!carry2) {
|
|
@@ -6827,7 +6843,7 @@ function FieldKeyboardMirror({
|
|
|
6827
6843
|
papers,
|
|
6828
6844
|
controller
|
|
6829
6845
|
}) {
|
|
6830
|
-
const [carrying, setCarrying] = (0,
|
|
6846
|
+
const [carrying, setCarrying] = (0, import_react17.useState)(null);
|
|
6831
6847
|
const paperLabel = (slot, i) => {
|
|
6832
6848
|
try {
|
|
6833
6849
|
const config = resolveConfig({ preset: slot.preset });
|
|
@@ -6930,16 +6946,16 @@ function fitCamera(layout, n, options, sheet2, fovDeg, aspect, margin = 1.06) {
|
|
|
6930
6946
|
|
|
6931
6947
|
// src/PaperField.tsx
|
|
6932
6948
|
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
6933
|
-
var PaperFieldMesh = (0,
|
|
6949
|
+
var PaperFieldMesh = (0, import_react18.forwardRef)(
|
|
6934
6950
|
function PaperFieldMesh2(props, ref) {
|
|
6935
6951
|
const reduced = usePrefersReducedMotion(props.reducedMotion);
|
|
6936
|
-
const papers = (0,
|
|
6952
|
+
const papers = (0, import_react18.useMemo)(
|
|
6937
6953
|
() => effectiveFieldPapers(props.papers, props.images),
|
|
6938
6954
|
[props.papers, props.images]
|
|
6939
6955
|
);
|
|
6940
6956
|
const stablePapers = useStable(papers);
|
|
6941
6957
|
const stablePreset = useStable(props.preset ?? null);
|
|
6942
|
-
const groups = (0,
|
|
6958
|
+
const groups = (0, import_react18.useMemo)(
|
|
6943
6959
|
() => groupFieldPapers(stablePapers, stablePreset ?? void 0),
|
|
6944
6960
|
[stablePapers, stablePreset]
|
|
6945
6961
|
);
|
|
@@ -6948,22 +6964,22 @@ var PaperFieldMesh = (0, import_react17.forwardRef)(
|
|
|
6948
6964
|
const layout = getLayout(layoutId);
|
|
6949
6965
|
const firstSheet = groups[0]?.config.sheet;
|
|
6950
6966
|
const stableLayoutOptions = useStable(props.layoutOptions ?? {});
|
|
6951
|
-
const layoutOptions = (0,
|
|
6967
|
+
const layoutOptions = (0, import_react18.useMemo)(
|
|
6952
6968
|
// Sheet grids size their cells from the papers themselves — gutter is
|
|
6953
6969
|
// then literally the spacing between stamps (explicit cell dims win).
|
|
6954
6970
|
() => resolveLayoutOptions(layoutId, layout, stableLayoutOptions, firstSheet),
|
|
6955
6971
|
[layoutId, stableLayoutOptions, firstSheet?.width, firstSheet?.height]
|
|
6956
6972
|
);
|
|
6957
|
-
const phaseRef = (0,
|
|
6958
|
-
const dragVelRef = (0,
|
|
6959
|
-
const mountTimeRef = (0,
|
|
6960
|
-
const morphRef = (0,
|
|
6961
|
-
const prevLayout = (0,
|
|
6962
|
-
const gl = (0,
|
|
6973
|
+
const phaseRef = (0, import_react18.useRef)(0);
|
|
6974
|
+
const dragVelRef = (0, import_react18.useRef)(0);
|
|
6975
|
+
const mountTimeRef = (0, import_react18.useRef)(-1);
|
|
6976
|
+
const morphRef = (0, import_react18.useRef)({ from: null, t: 1 });
|
|
6977
|
+
const prevLayout = (0, import_react18.useRef)({ id: layoutId, options: layoutOptions });
|
|
6978
|
+
const gl = (0, import_fiber8.useThree)((s) => s.gl);
|
|
6963
6979
|
const driver = reduced ? "none" : props.motion?.driver ?? "autoplay";
|
|
6964
6980
|
const speed = props.motion?.speed ?? 0.5;
|
|
6965
6981
|
const entranceType = reduced ? "none" : props.entrance?.type ?? "rise";
|
|
6966
|
-
(0,
|
|
6982
|
+
(0, import_react18.useEffect)(() => {
|
|
6967
6983
|
const prev = prevLayout.current;
|
|
6968
6984
|
if (prev.id !== layoutId || JSON.stringify(prev.options) !== JSON.stringify(layoutOptions)) {
|
|
6969
6985
|
morphRef.current = { from: prev, t: 0 };
|
|
@@ -6971,7 +6987,7 @@ var PaperFieldMesh = (0, import_react17.forwardRef)(
|
|
|
6971
6987
|
prevLayout.current = { id: layoutId, options: layoutOptions };
|
|
6972
6988
|
}
|
|
6973
6989
|
}, [layoutId, layoutOptions]);
|
|
6974
|
-
(0,
|
|
6990
|
+
(0, import_react18.useEffect)(() => {
|
|
6975
6991
|
if (driver !== "drag") return;
|
|
6976
6992
|
const el = gl.domElement;
|
|
6977
6993
|
let lastX = null;
|
|
@@ -6997,7 +7013,7 @@ var PaperFieldMesh = (0, import_react17.forwardRef)(
|
|
|
6997
7013
|
window.removeEventListener("pointerup", up);
|
|
6998
7014
|
};
|
|
6999
7015
|
}, [driver, gl]);
|
|
7000
|
-
(0,
|
|
7016
|
+
(0, import_fiber8.useFrame)(({ clock }, delta) => {
|
|
7001
7017
|
if (mountTimeRef.current < 0) mountTimeRef.current = clock.elapsedTime;
|
|
7002
7018
|
if (driver === "autoplay") phaseRef.current += delta * speed * 0.02;
|
|
7003
7019
|
if (driver === "drag") {
|
|
@@ -7055,14 +7071,14 @@ var PaperFieldMesh = (0, import_react17.forwardRef)(
|
|
|
7055
7071
|
}
|
|
7056
7072
|
);
|
|
7057
7073
|
function FitCamera(meshProps) {
|
|
7058
|
-
const camera = (0,
|
|
7059
|
-
const width = (0,
|
|
7060
|
-
const height = (0,
|
|
7074
|
+
const camera = (0, import_fiber8.useThree)((s) => s.camera);
|
|
7075
|
+
const width = (0, import_fiber8.useThree)((s) => s.size.width);
|
|
7076
|
+
const height = (0, import_fiber8.useThree)((s) => s.size.height);
|
|
7061
7077
|
const papersProp = useStable(meshProps.papers ?? null);
|
|
7062
7078
|
const imagesProp = useStable(meshProps.images ?? null);
|
|
7063
7079
|
const presetProp = useStable(meshProps.preset ?? null);
|
|
7064
7080
|
const optionsProp = useStable(meshProps.layoutOptions ?? {});
|
|
7065
|
-
const field = (0,
|
|
7081
|
+
const field = (0, import_react18.useMemo)(() => {
|
|
7066
7082
|
const papers = effectiveFieldPapers(papersProp ?? void 0, imagesProp ?? void 0);
|
|
7067
7083
|
const layoutId = meshProps.layout ?? "ring";
|
|
7068
7084
|
const layout = getLayout(layoutId);
|
|
@@ -7070,7 +7086,7 @@ function FitCamera(meshProps) {
|
|
|
7070
7086
|
const options = resolveLayoutOptions(layoutId, layout, optionsProp, sheet2);
|
|
7071
7087
|
return { layout, n: papers.length, options, sheet: sheet2 ?? DEFAULT_SHEET };
|
|
7072
7088
|
}, [papersProp, imagesProp, presetProp, meshProps.layout, optionsProp]);
|
|
7073
|
-
(0,
|
|
7089
|
+
(0, import_react18.useEffect)(() => {
|
|
7074
7090
|
if (!(camera instanceof THREE16.PerspectiveCamera)) return;
|
|
7075
7091
|
const { position, target } = fitCamera(
|
|
7076
7092
|
field.layout,
|
|
@@ -7086,27 +7102,28 @@ function FitCamera(meshProps) {
|
|
|
7086
7102
|
}, [camera, width, height, field]);
|
|
7087
7103
|
return null;
|
|
7088
7104
|
}
|
|
7089
|
-
var PaperField = (0,
|
|
7105
|
+
var PaperField = (0, import_react18.forwardRef)(function PaperField2({ children, className, style, scene, ...meshProps }, ref) {
|
|
7090
7106
|
const rig = sceneSchema.parse(scene ?? {});
|
|
7091
|
-
const registry4 = (0,
|
|
7092
|
-
const a11yRef = (0,
|
|
7093
|
-
const papers = (0,
|
|
7107
|
+
const registry4 = (0, import_react18.useMemo)(() => new DropZoneRegistry(), []);
|
|
7108
|
+
const a11yRef = (0, import_react18.useRef)(null);
|
|
7109
|
+
const papers = (0, import_react18.useMemo)(
|
|
7094
7110
|
() => effectiveFieldPapers(meshProps.papers, meshProps.images),
|
|
7095
7111
|
[meshProps.papers, meshProps.images]
|
|
7096
7112
|
);
|
|
7097
7113
|
const stablePapers = useStable(papers);
|
|
7098
7114
|
const stablePreset = useStable(meshProps.preset ?? null);
|
|
7099
|
-
const interactive = (0,
|
|
7115
|
+
const interactive = (0, import_react18.useMemo)(
|
|
7100
7116
|
() => fieldIsInteractive(stablePapers, stablePreset ?? void 0, meshProps.interactive),
|
|
7101
7117
|
[stablePapers, stablePreset, meshProps.interactive]
|
|
7102
7118
|
);
|
|
7103
7119
|
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className, style: { width: "100%", height: "100%", ...style }, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(DropZoneContext.Provider, { value: registry4, children: [
|
|
7104
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
7120
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_fiber8.Canvas, { shadows: true, camera: { position: [0, 0.6, 5.2], fov: 45 }, dpr: [1, 2], children: [
|
|
7105
7121
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(FitCamera, { ...meshProps }),
|
|
7106
7122
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(PaperBackdrop, { backdrop: rig.backdrop }),
|
|
7107
7123
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(PaperLighting, { preset: rig.lighting, light: rig.light, floor: -2.4, scale: 14 }),
|
|
7108
7124
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(PaperFieldMesh, { ref, a11yControllerRef: a11yRef, ...meshProps }),
|
|
7109
|
-
children
|
|
7125
|
+
children,
|
|
7126
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ReleaseContextOnUnmount, {})
|
|
7110
7127
|
] }),
|
|
7111
7128
|
interactive && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(FieldKeyboardMirror, { papers, controller: a11yRef })
|
|
7112
7129
|
] }) });
|