anim-3d-obj 2.0.7 → 2.0.8
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/dist/index.cjs +50 -44
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +16 -37
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +50 -44
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -193,28 +193,6 @@ function faceAppearance(face, globalDef) {
|
|
|
193
193
|
const body = face.body ?? globalDef?.body ?? null;
|
|
194
194
|
return { style, className, body };
|
|
195
195
|
}
|
|
196
|
-
var Y_FACE_OFFSET = {
|
|
197
|
-
front: 0,
|
|
198
|
-
right: 0.25,
|
|
199
|
-
back: 0.5,
|
|
200
|
-
left: 0.75
|
|
201
|
-
};
|
|
202
|
-
function sheenOverlay(faceName, animDuration, isFlat) {
|
|
203
|
-
if (isFlat) return null;
|
|
204
|
-
const offset = Y_FACE_OFFSET[faceName];
|
|
205
|
-
if (offset === void 0) return null;
|
|
206
|
-
const delay = offset * animDuration;
|
|
207
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "anim3d-sheen", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
208
|
-
"div",
|
|
209
|
-
{
|
|
210
|
-
className: "anim3d-sheen-bar",
|
|
211
|
-
style: {
|
|
212
|
-
"--sheen-dur": animDuration + "s",
|
|
213
|
-
"--sheen-delay": delay + "s"
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
) });
|
|
217
|
-
}
|
|
218
196
|
var DEFAULT_FACE_NAMES = [
|
|
219
197
|
"front",
|
|
220
198
|
"back",
|
|
@@ -251,7 +229,7 @@ var Obj = React__namespace.memo(
|
|
|
251
229
|
transitionDuration = 1,
|
|
252
230
|
oneAtATime = false,
|
|
253
231
|
remainJoined = false,
|
|
254
|
-
|
|
232
|
+
ytilt = false,
|
|
255
233
|
className,
|
|
256
234
|
style
|
|
257
235
|
}) => {
|
|
@@ -262,7 +240,32 @@ var Obj = React__namespace.memo(
|
|
|
262
240
|
const animation2 = toAnimationShorthand(anim2) ?? void 0;
|
|
263
241
|
const faceList = faces && faces.length > 0 ? faces : DEFAULT_FACE_NAMES.map((name) => ({ name }));
|
|
264
242
|
const transitionCss = (delay = 0) => `transform ${transitionDuration}s ease-in-out ${delay}s`;
|
|
265
|
-
const
|
|
243
|
+
const tiltCount = React__namespace.useRef(0);
|
|
244
|
+
const prevFlat = React__namespace.useRef(flat);
|
|
245
|
+
const [tiltAnim, setTiltAnim] = React__namespace.useState(void 0);
|
|
246
|
+
React__namespace.useEffect(() => {
|
|
247
|
+
if (flat !== prevFlat.current) {
|
|
248
|
+
prevFlat.current = flat;
|
|
249
|
+
if (ytilt) {
|
|
250
|
+
tiltCount.current += 1;
|
|
251
|
+
const sideCount = faceList.filter(
|
|
252
|
+
(f) => ["front", "right", "back", "left"].includes(
|
|
253
|
+
f.name
|
|
254
|
+
)
|
|
255
|
+
).length;
|
|
256
|
+
const totalDur = oneAtATime ? transitionDuration * sideCount : transitionDuration;
|
|
257
|
+
const name = tiltCount.current % 2 === 0 ? "anim3d-ytilt-a" : "anim3d-ytilt-b";
|
|
258
|
+
setTiltAnim(
|
|
259
|
+
`${name} ${totalDur}s ease-in-out 1 forwards`
|
|
260
|
+
);
|
|
261
|
+
const timer = setTimeout(
|
|
262
|
+
() => setTiltAnim(void 0),
|
|
263
|
+
totalDur * 1e3 + 50
|
|
264
|
+
);
|
|
265
|
+
return () => clearTimeout(timer);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}, [flat, ytilt, transitionDuration, oneAtATime, faceList]);
|
|
266
269
|
const renderStandard = () => faceList.map((face, i) => {
|
|
267
270
|
const dims = faceDimensions(face.name, w, h, d);
|
|
268
271
|
const transform = flat ? faceTransformFlat(face.name, w, h, d) : faceTransform3D(face.name, w, h, d);
|
|
@@ -273,7 +276,7 @@ var Obj = React__namespace.memo(
|
|
|
273
276
|
} = faceAppearance(face, globalDef);
|
|
274
277
|
const idx = STAGGER_ORDER.indexOf(face.name);
|
|
275
278
|
const delay = oneAtATime ? (idx >= 0 ? idx : i) * transitionDuration : 0;
|
|
276
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
279
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
277
280
|
"div",
|
|
278
281
|
{
|
|
279
282
|
className: fCls,
|
|
@@ -284,10 +287,7 @@ var Obj = React__namespace.memo(
|
|
|
284
287
|
transform,
|
|
285
288
|
transition: transitionCss(delay)
|
|
286
289
|
},
|
|
287
|
-
children:
|
|
288
|
-
body,
|
|
289
|
-
sheen && sheenOverlay(face.name, sheenDur, flat)
|
|
290
|
-
]
|
|
290
|
+
children: body
|
|
291
291
|
},
|
|
292
292
|
face.name + "-" + i
|
|
293
293
|
);
|
|
@@ -315,7 +315,7 @@ var Obj = React__namespace.memo(
|
|
|
315
315
|
className: fCls,
|
|
316
316
|
body
|
|
317
317
|
} = faceAppearance(face, globalDef);
|
|
318
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
318
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
319
319
|
"div",
|
|
320
320
|
{
|
|
321
321
|
className: fCls,
|
|
@@ -329,10 +329,7 @@ var Obj = React__namespace.memo(
|
|
|
329
329
|
boxSizing: "border-box",
|
|
330
330
|
...extra
|
|
331
331
|
},
|
|
332
|
-
children:
|
|
333
|
-
body,
|
|
334
|
-
sheen && sheenOverlay(face.name, sheenDur, flat)
|
|
335
|
-
]
|
|
332
|
+
children: body
|
|
336
333
|
},
|
|
337
334
|
key
|
|
338
335
|
);
|
|
@@ -482,27 +479,36 @@ var Obj = React__namespace.memo(
|
|
|
482
479
|
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
483
480
|
"div",
|
|
484
481
|
{
|
|
485
|
-
className: "anim3d-wrapper",
|
|
486
482
|
style: {
|
|
487
|
-
...cssVars,
|
|
488
|
-
animation: flat ? "none" : animation1,
|
|
489
483
|
transformStyle: "preserve-3d",
|
|
490
|
-
|
|
484
|
+
animation: tiltAnim
|
|
491
485
|
},
|
|
492
|
-
children: /* @__PURE__ */ jsxRuntime.
|
|
486
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
493
487
|
"div",
|
|
494
488
|
{
|
|
495
489
|
className: "anim3d-wrapper",
|
|
496
490
|
style: {
|
|
497
491
|
...cssVars,
|
|
498
|
-
animation: flat ? "none" :
|
|
492
|
+
animation: flat ? "none" : animation1,
|
|
499
493
|
transformStyle: "preserve-3d",
|
|
500
494
|
transition: transitionCss()
|
|
501
495
|
},
|
|
502
|
-
children:
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
496
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
497
|
+
"div",
|
|
498
|
+
{
|
|
499
|
+
className: "anim3d-wrapper",
|
|
500
|
+
style: {
|
|
501
|
+
...cssVars,
|
|
502
|
+
animation: flat ? "none" : animation2,
|
|
503
|
+
transformStyle: "preserve-3d",
|
|
504
|
+
transition: transitionCss()
|
|
505
|
+
},
|
|
506
|
+
children: [
|
|
507
|
+
showCenterDiv && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "anim3d-center" }),
|
|
508
|
+
remainJoined ? renderJoined() : renderStandard()
|
|
509
|
+
]
|
|
510
|
+
}
|
|
511
|
+
)
|
|
506
512
|
}
|
|
507
513
|
)
|
|
508
514
|
}
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/keyframes.ts","../src/components/Obj.tsx"],"names":["jsx","React","jsxs","Fragment"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { AnimationConfig } from \"./types\";\n\n/** Create (or reuse) a <style> tag for dynamic keyframes */\nfunction ensureStyleTag(): HTMLStyleElement {\n let tag = document.getElementById(\n \"anim3d-keyframes\"\n ) as HTMLStyleElement | null;\n if (!tag) {\n tag = document.createElement(\"style\");\n tag.id = \"anim3d-keyframes\";\n document.head.appendChild(tag);\n }\n return tag;\n}\n\nfunction inject(css: string) {\n if (typeof document === \"undefined\") return; // SSR\n const tag = ensureStyleTag();\n tag.appendChild(document.createTextNode(css));\n}\n\n/** Keyframes text for built-ins */\nfunction builtInKeyframes(name: string, cfg: AnimationConfig) {\n const hi = cfg.degreesHi ?? 15;\n const lo = cfg.degreesLow ?? -15;\n switch (name) {\n case \"Y360\":\n return `@keyframes Y360 { from { transform: rotateY(0deg) } to { transform: rotateY(360deg) } }`;\n case \"X360\":\n return `@keyframes X360 { from { transform: rotateX(0deg) } to { transform: rotateX(360deg) } }`;\n case \"Z360\":\n return `@keyframes Z360 { from { transform: rotateZ(0deg) } to { transform: rotateZ(360deg) } }`;\n case \"rockY\":\n return `@keyframes rockY { 0%{ transform: rotateY(${lo}deg) } 50%{ transform: rotateY(${hi}deg) } 100%{ transform: rotateY(${lo}deg) } }`;\n case \"rockX\":\n return `@keyframes rockX { 0%{ transform: rotateX(${lo}deg) } 50%{ transform: rotateX(${hi}deg) } 100%{ transform: rotateX(${lo}deg) } }`;\n default:\n // Custom names: let authors supply their own @keyframes in global CSS with that name.\n return \"\";\n }\n}\n\n/** Returns a concrete animation-name and ensures keyframes exist (for built-ins) */\nexport function resolveAnimation(cfg?: AnimationConfig): string | null {\n if (!cfg) return null;\n const name = cfg.name;\n const builtIn = builtInKeyframes(name, cfg);\n if (builtIn) {\n // Ensure single injection per built-in name\n const marker = `/*kf-${name}*/`;\n if (typeof document !== \"undefined\") {\n const tag = ensureStyleTag();\n if (!tag.innerHTML.includes(marker)) {\n inject(`${builtIn}\\n${marker}`);\n }\n }\n return name; // use built-in name as animation-name\n }\n // custom: use author-provided @keyframes by name\n return name;\n}\n\n/** Build the full CSS animation shorthand from a config and resolved name */\nexport function toAnimationShorthand(cfg?: AnimationConfig): string | null {\n const name = resolveAnimation(cfg);\n if (!cfg || !name) return null;\n const dur = (cfg.duration ?? 10) + \"s\";\n const delay = (cfg.delay ?? 0) + \"s\";\n const iter = cfg.iterationCount ?? \"infinite\";\n const dir = cfg.direction ?? \"normal\";\n const timing = cfg.timing ?? \"linear\";\n const fill = cfg.fillMode ?? \"forwards\";\n const play = cfg.animationPlayState ?? \"running\";\n // name duration timing delay iteration-count direction fill-mode play-state\n return `${name} ${dur} ${timing} ${delay} ${iter} ${dir} ${fill} ${play}`;\n}\n","import * as React from \"react\";\nimport type {\n ObjProps,\n FaceDef,\n FaceName,\n GlobalDef,\n} from \"../types\";\nimport { toAnimationShorthand } from \"../keyframes\";\nimport \"../styles/obj.css\";\n\n// Re-export the canonical ObjProps from types.ts\nexport type { ObjProps } from \"../types\";\n\n/* ------------------------------------------------------------------ */\n/* Face transform — 3D cuboid positions */\n/* ------------------------------------------------------------------ */\n\nfunction faceTransform3D(\n name: string,\n w: number,\n h: number,\n d: number\n): string {\n const hw = w / 2;\n const hh = h / 2;\n const hd = d / 2;\n\n switch (name as FaceName) {\n case \"front\":\n return `translate(-50%, -50%) translateZ(${hd}px)`;\n case \"back\":\n return `translate(-50%, -50%) rotateY(180deg) translateZ(${hd}px)`;\n case \"left\":\n return `translate(-50%, -50%) rotateY(-90deg) translateZ(${hw}px)`;\n case \"right\":\n return `translate(-50%, -50%) rotateY(90deg) translateZ(${hw}px)`;\n case \"top\":\n return `translate(-50%, -50%) rotateX(90deg) translateZ(${hh}px)`;\n case \"bottom\":\n return `translate(-50%, -50%) rotateX(-90deg) translateZ(${hh}px)`;\n case \"top_front\":\n return `translate(-50%, -50%) rotateX(45deg) translateZ(${hh}px)`;\n case \"top_rear\":\n return `translate(-50%, -50%) rotateX(135deg) translateZ(${hh}px)`;\n case \"bottom_front\":\n return `translate(-50%, -50%) rotateX(-45deg) translateZ(${hh}px)`;\n case \"bottom_rear\":\n return `translate(-50%, -50%) rotateX(-135deg) translateZ(${hh}px)`;\n default:\n return `translate(-50%, -50%) translateZ(${hd}px)`;\n }\n}\n\n/* ------------------------------------------------------------------ */\n/* Face transform — flat (unfolded) positions */\n/* */\n/* Flat order: front | right | back | left */\n/* Centred on the midpoint of the full row. */\n/* ------------------------------------------------------------------ */\n\nfunction faceTransformFlat(\n name: string,\n w: number,\n h: number,\n d: number\n): string {\n // Row layout (left to right): front(w) | right(d) | back(w) | left(d)\n // Total width = 2w + 2d. Centre of row at (w + d).\n const total = 2 * w + 2 * d;\n const half = total / 2;\n\n let cx: number;\n\n switch (name as FaceName) {\n case \"front\":\n cx = w / 2;\n break;\n case \"right\":\n cx = w + d / 2;\n break;\n case \"back\":\n cx = w + d + w / 2;\n break;\n case \"left\":\n cx = w + d + w + d / 2;\n break;\n case \"top\":\n case \"top_front\":\n case \"top_rear\":\n cx = w / 2;\n return `translate(-50%, -50%) translateX(${cx - half}px) translateY(-${h}px)`;\n case \"bottom\":\n case \"bottom_front\":\n case \"bottom_rear\":\n cx = w / 2;\n return `translate(-50%, -50%) translateX(${cx - half}px) translateY(${h}px)`;\n default:\n cx = w / 2;\n break;\n }\n\n return `translate(-50%, -50%) translateX(${cx - half}px)`;\n}\n\n/* ------------------------------------------------------------------ */\n/* Parse a legacy CSS text string into a CSSProperties object */\n/* ------------------------------------------------------------------ */\n\nfunction parseCssText(css?: string): React.CSSProperties {\n if (!css) return {};\n const style: Record<string, string> = {};\n css.split(\";\").forEach((rule) => {\n const [prop, ...rest] = rule.split(\":\");\n if (!prop || rest.length === 0) return;\n const key = prop\n .trim()\n .replace(/-([a-z])/g, (_, c) => c.toUpperCase());\n style[key] = rest.join(\":\").trim();\n });\n return style as React.CSSProperties;\n}\n\n/* ------------------------------------------------------------------ */\n/* Resolve face dimensions for non-standard faces */\n/* ------------------------------------------------------------------ */\n\nfunction faceDimensions(\n name: string,\n w: number,\n h: number,\n d: number\n): { width: number; height: number } {\n switch (name as FaceName) {\n case \"left\":\n case \"right\":\n return { width: d, height: h };\n case \"top\":\n case \"bottom\":\n case \"top_front\":\n case \"top_rear\":\n case \"bottom_front\":\n case \"bottom_rear\":\n return { width: w, height: d };\n default:\n return { width: w, height: h };\n }\n}\n\n/* ------------------------------------------------------------------ */\n/* Build appearance style for a face (colours, borders, etc.) */\n/* Does NOT include position / transform / size. */\n/* ------------------------------------------------------------------ */\n\nfunction faceAppearance(\n face: FaceDef,\n globalDef?: GlobalDef\n): {\n style: React.CSSProperties;\n className: string;\n body: React.ReactNode;\n} {\n const globalStyle = parseCssText(globalDef?.css);\n const faceInlineStyle = parseCssText(face.css);\n\n const style: React.CSSProperties = {\n ...globalStyle,\n ...(globalDef?.style ?? {}),\n ...faceInlineStyle,\n ...(face.style ?? {}),\n };\n\n const className = [\"anim3d-face\", face.className]\n .filter(Boolean)\n .join(\" \");\n\n const body = face.body ?? globalDef?.body ?? null;\n\n return { style, className, body };\n}\n\n/* ------------------------------------------------------------------ */\n/* Sheen overlay — sweeps across each face as it leaves face-on */\n/* ------------------------------------------------------------------ */\n\n/** Fraction of rotation cycle at which each face is face-on (Y-axis) */\nconst Y_FACE_OFFSET: Record<string, number> = {\n front: 0,\n right: 0.25,\n back: 0.5,\n left: 0.75,\n};\n\nfunction sheenOverlay(\n faceName: string,\n animDuration: number,\n isFlat: boolean\n): React.ReactNode {\n if (isFlat) return null;\n const offset = Y_FACE_OFFSET[faceName];\n if (offset === undefined) return null; // no sheen for top/bottom etc.\n const delay = offset * animDuration;\n\n return (\n <div className=\"anim3d-sheen\">\n <div\n className=\"anim3d-sheen-bar\"\n style={{\n \"--sheen-dur\": animDuration + \"s\",\n \"--sheen-delay\": delay + \"s\",\n } as React.CSSProperties}\n />\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Default 6-sided cube when no faces are provided */\n/* ------------------------------------------------------------------ */\n\nconst DEFAULT_FACE_NAMES: FaceName[] = [\n \"front\",\n \"back\",\n \"left\",\n \"right\",\n \"top\",\n \"bottom\",\n];\n\n/* ------------------------------------------------------------------ */\n/* Stagger order for oneAtATime (standard mode) */\n/* ------------------------------------------------------------------ */\n\nconst STAGGER_ORDER: string[] = [\n \"front\",\n \"right\",\n \"back\",\n \"left\",\n \"top\",\n \"bottom\",\n \"top_front\",\n \"top_rear\",\n \"bottom_front\",\n \"bottom_rear\",\n];\n\n/* ------------------------------------------------------------------ */\n/* Component */\n/* ------------------------------------------------------------------ */\n\nexport const Obj: React.FC<ObjProps> = React.memo(\n ({\n width = 160,\n height = 160,\n depth = 150,\n perspective = 600,\n perspectiveOrigin = \"50% 50%\",\n faces,\n global: globalDef,\n anim1,\n anim2,\n showCenterDiv = false,\n flat = false,\n transitionDuration = 1,\n oneAtATime = false,\n remainJoined = false,\n sheen = false,\n className,\n style,\n }) => {\n const w =\n typeof width === \"number\" ? width : parseFloat(String(width));\n const h =\n typeof height === \"number\" ? height : parseFloat(String(height));\n const d =\n typeof depth === \"number\" ? depth : parseFloat(String(depth));\n\n // Resolve animation shorthands\n const animation1 = toAnimationShorthand(anim1) ?? undefined;\n const animation2 = toAnimationShorthand(anim2) ?? undefined;\n\n // Determine which faces to render\n const faceList: FaceDef[] =\n faces && faces.length > 0\n ? faces\n : DEFAULT_FACE_NAMES.map((name) => ({ name }));\n\n const transitionCss = (delay = 0) =>\n `transform ${transitionDuration}s ease-in-out ${delay}s`;\n\n // Duration for sheen (synced to anim1 rotation cycle)\n const sheenDur = anim1?.duration ?? 6;\n\n /* ============================================================ */\n /* Standard rendering (no remainJoined) */\n /* ============================================================ */\n\n const renderStandard = () =>\n faceList.map((face, i) => {\n const dims = faceDimensions(face.name, w, h, d);\n const transform = flat\n ? faceTransformFlat(face.name, w, h, d)\n : faceTransform3D(face.name, w, h, d);\n\n const {\n style: fStyle,\n className: fCls,\n body,\n } = faceAppearance(face, globalDef);\n\n const idx = STAGGER_ORDER.indexOf(face.name);\n const delay = oneAtATime\n ? (idx >= 0 ? idx : i) * transitionDuration\n : 0;\n\n return (\n <div\n key={face.name + \"-\" + i}\n className={fCls}\n style={{\n ...fStyle,\n width: dims.width,\n height: dims.height,\n transform,\n transition: transitionCss(delay),\n }}\n >\n {body}\n {sheen && sheenOverlay(face.name, sheenDur, flat)}\n </div>\n );\n });\n\n /* ============================================================ */\n /* Joined rendering — nested hinge structure */\n /* */\n /* Chain: front → right → back (hinged at shared edges) */\n /* Left is independent (the break‑point). */\n /* */\n /* Flat order: front | right | back | left (left on far right) */\n /* ============================================================ */\n\n const renderJoined = () => {\n const findFace = (n: string) =>\n faceList.find((f) => f.name === n);\n\n const frontFace = findFace(\"front\");\n const rightFace = findFace(\"right\");\n const backFace = findFace(\"back\");\n const leftFace = findFace(\"left\");\n\n const sideNames = new Set([\n \"front\",\n \"right\",\n \"back\",\n \"left\",\n ]);\n const otherFaces = faceList.filter(\n (f) => !sideNames.has(f.name)\n );\n\n const step = oneAtATime ? transitionDuration : 0;\n\n /* Helper: render a single face element with merged styles */\n const renderFaceEl = (\n face: FaceDef | undefined,\n dims: { width: number; height: number },\n extra: React.CSSProperties,\n key: string\n ) => {\n if (!face) return null;\n const {\n style: fStyle,\n className: fCls,\n body,\n } = faceAppearance(face, globalDef);\n return (\n <div\n key={key}\n className={fCls}\n style={{\n ...fStyle,\n width: dims.width,\n height: dims.height,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n boxSizing: \"border-box\",\n ...extra,\n }}\n >\n {body}\n {sheen &&\n sheenOverlay(face.name, sheenDur, flat)}\n </div>\n );\n };\n\n return (\n <>\n {/* ---- Front face (anchor) ---- */}\n {renderFaceEl(\n frontFace,\n { width: w, height: h },\n {\n position: \"absolute\",\n left: \"50%\",\n top: \"50%\",\n transform: flat\n ? \"translate(-50%, -50%)\"\n : `translate(-50%, -50%) translateZ(${d / 2}px)`,\n transition: transitionCss(0),\n },\n \"front-j\"\n )}\n\n {/* ---- Right hinge (pivots at front's right edge) ---- */}\n <div\n style={{\n position: \"absolute\",\n left: `calc(50% + ${w / 2}px)`,\n top: \"50%\",\n width: 0,\n height: 0,\n transformOrigin: \"0 0\",\n transformStyle: \"preserve-3d\",\n transform: flat\n ? \"none\"\n : `translateZ(${d / 2}px) rotateY(90deg)`,\n transition: transitionCss(step),\n }}\n >\n {/* Right face */}\n {renderFaceEl(\n rightFace,\n { width: d, height: h },\n {\n position: \"absolute\",\n left: 0,\n top: 0,\n transform: \"translateY(-50%)\",\n },\n \"right-j\"\n )}\n\n {/* ---- Back hinge (pivots at right's far edge) ---- */}\n <div\n style={{\n position: \"absolute\",\n left: d,\n top: 0,\n width: 0,\n height: 0,\n transformOrigin: \"0 0\",\n transformStyle: \"preserve-3d\",\n transform: flat\n ? \"none\"\n : \"rotateY(90deg)\",\n transition: transitionCss(step * 2),\n }}\n >\n {/* Back face */}\n {renderFaceEl(\n backFace,\n { width: w, height: h },\n {\n position: \"absolute\",\n left: 0,\n top: 0,\n transform: \"translateY(-50%)\",\n },\n \"back-j\"\n )}\n\n {/* ---- Left hinge (pivots at back's far edge) ---- */}\n <div\n style={{\n position: \"absolute\",\n left: w,\n top: 0,\n width: 0,\n height: 0,\n transformOrigin: \"0 0\",\n transformStyle: \"preserve-3d\",\n transform: flat\n ? \"none\"\n : \"rotateY(90deg)\",\n transition: transitionCss(step * 3),\n }}\n >\n {/* Left face */}\n {renderFaceEl(\n leftFace,\n { width: d, height: h },\n {\n position: \"absolute\",\n left: 0,\n top: 0,\n transform: \"translateY(-50%)\",\n },\n \"left-j\"\n )}\n </div>\n </div>\n </div>\n\n {/* ---- Non-side faces (top, bottom, etc.) ---- */}\n {otherFaces.map((face, i) => {\n const dims = faceDimensions(face.name, w, h, d);\n const xform = flat\n ? faceTransformFlat(face.name, w, h, d)\n : faceTransform3D(face.name, w, h, d);\n const {\n style: fStyle,\n className: fCls,\n body,\n } = faceAppearance(face, globalDef);\n return (\n <div\n key={face.name + \"-o-\" + i}\n className={fCls}\n style={{\n ...fStyle,\n width: dims.width,\n height: dims.height,\n transform: xform,\n transition: transitionCss(0),\n }}\n >\n {body}\n </div>\n );\n })}\n </>\n );\n };\n\n /* ============================================================ */\n /* Render tree */\n /* ============================================================ */\n\n const cssVars = {\n \"--obj-w\": w + \"px\",\n \"--obj-h\": h + \"px\",\n \"--obj-d\": d + \"px\",\n } as React.CSSProperties;\n\n return (\n <div\n className={[\"anim3d-stage\", className]\n .filter(Boolean)\n .join(\" \")}\n style={{\n perspective,\n perspectiveOrigin,\n ...cssVars,\n ...style,\n }}\n data-anim-3d-obj\n role=\"img\"\n aria-label=\"3D object\"\n >\n {/* Outer animation wrapper (anim1) */}\n <div\n className=\"anim3d-wrapper\"\n style={{\n ...cssVars,\n animation: flat ? \"none\" : animation1,\n transformStyle: \"preserve-3d\",\n transition: transitionCss(),\n }}\n >\n {/* Inner animation wrapper (anim2) */}\n <div\n className=\"anim3d-wrapper\"\n style={{\n ...cssVars,\n animation: flat ? \"none\" : animation2,\n transformStyle: \"preserve-3d\",\n transition: transitionCss(),\n }}\n >\n {showCenterDiv && (\n <div className=\"anim3d-center\" />\n )}\n {remainJoined\n ? renderJoined()\n : renderStandard()}\n </div>\n </div>\n </div>\n );\n }\n);\n\nObj.displayName = \"Obj\";\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/keyframes.ts","../src/components/Obj.tsx"],"names":["React","jsx","jsxs","Fragment"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { AnimationConfig } from \"./types\";\n\n/** Create (or reuse) a <style> tag for dynamic keyframes */\nfunction ensureStyleTag(): HTMLStyleElement {\n let tag = document.getElementById(\n \"anim3d-keyframes\"\n ) as HTMLStyleElement | null;\n if (!tag) {\n tag = document.createElement(\"style\");\n tag.id = \"anim3d-keyframes\";\n document.head.appendChild(tag);\n }\n return tag;\n}\n\nfunction inject(css: string) {\n if (typeof document === \"undefined\") return; // SSR\n const tag = ensureStyleTag();\n tag.appendChild(document.createTextNode(css));\n}\n\n/** Keyframes text for built-ins */\nfunction builtInKeyframes(name: string, cfg: AnimationConfig) {\n const hi = cfg.degreesHi ?? 15;\n const lo = cfg.degreesLow ?? -15;\n switch (name) {\n case \"Y360\":\n return `@keyframes Y360 { from { transform: rotateY(0deg) } to { transform: rotateY(360deg) } }`;\n case \"X360\":\n return `@keyframes X360 { from { transform: rotateX(0deg) } to { transform: rotateX(360deg) } }`;\n case \"Z360\":\n return `@keyframes Z360 { from { transform: rotateZ(0deg) } to { transform: rotateZ(360deg) } }`;\n case \"rockY\":\n return `@keyframes rockY { 0%{ transform: rotateY(${lo}deg) } 50%{ transform: rotateY(${hi}deg) } 100%{ transform: rotateY(${lo}deg) } }`;\n case \"rockX\":\n return `@keyframes rockX { 0%{ transform: rotateX(${lo}deg) } 50%{ transform: rotateX(${hi}deg) } 100%{ transform: rotateX(${lo}deg) } }`;\n default:\n // Custom names: let authors supply their own @keyframes in global CSS with that name.\n return \"\";\n }\n}\n\n/** Returns a concrete animation-name and ensures keyframes exist (for built-ins) */\nexport function resolveAnimation(cfg?: AnimationConfig): string | null {\n if (!cfg) return null;\n const name = cfg.name;\n const builtIn = builtInKeyframes(name, cfg);\n if (builtIn) {\n // Ensure single injection per built-in name\n const marker = `/*kf-${name}*/`;\n if (typeof document !== \"undefined\") {\n const tag = ensureStyleTag();\n if (!tag.innerHTML.includes(marker)) {\n inject(`${builtIn}\\n${marker}`);\n }\n }\n return name; // use built-in name as animation-name\n }\n // custom: use author-provided @keyframes by name\n return name;\n}\n\n/** Build the full CSS animation shorthand from a config and resolved name */\nexport function toAnimationShorthand(cfg?: AnimationConfig): string | null {\n const name = resolveAnimation(cfg);\n if (!cfg || !name) return null;\n const dur = (cfg.duration ?? 10) + \"s\";\n const delay = (cfg.delay ?? 0) + \"s\";\n const iter = cfg.iterationCount ?? \"infinite\";\n const dir = cfg.direction ?? \"normal\";\n const timing = cfg.timing ?? \"linear\";\n const fill = cfg.fillMode ?? \"forwards\";\n const play = cfg.animationPlayState ?? \"running\";\n // name duration timing delay iteration-count direction fill-mode play-state\n return `${name} ${dur} ${timing} ${delay} ${iter} ${dir} ${fill} ${play}`;\n}\n","import * as React from \"react\";\nimport type {\n ObjProps,\n FaceDef,\n FaceName,\n GlobalDef,\n} from \"../types\";\nimport { toAnimationShorthand } from \"../keyframes\";\nimport \"../styles/obj.css\";\n\n// Re-export the canonical ObjProps from types.ts\nexport type { ObjProps } from \"../types\";\n\n/* ------------------------------------------------------------------ */\n/* Face transform — 3D cuboid positions */\n/* ------------------------------------------------------------------ */\n\nfunction faceTransform3D(\n name: string,\n w: number,\n h: number,\n d: number\n): string {\n const hw = w / 2;\n const hh = h / 2;\n const hd = d / 2;\n\n switch (name as FaceName) {\n case \"front\":\n return `translate(-50%, -50%) translateZ(${hd}px)`;\n case \"back\":\n return `translate(-50%, -50%) rotateY(180deg) translateZ(${hd}px)`;\n case \"left\":\n return `translate(-50%, -50%) rotateY(-90deg) translateZ(${hw}px)`;\n case \"right\":\n return `translate(-50%, -50%) rotateY(90deg) translateZ(${hw}px)`;\n case \"top\":\n return `translate(-50%, -50%) rotateX(90deg) translateZ(${hh}px)`;\n case \"bottom\":\n return `translate(-50%, -50%) rotateX(-90deg) translateZ(${hh}px)`;\n case \"top_front\":\n return `translate(-50%, -50%) rotateX(45deg) translateZ(${hh}px)`;\n case \"top_rear\":\n return `translate(-50%, -50%) rotateX(135deg) translateZ(${hh}px)`;\n case \"bottom_front\":\n return `translate(-50%, -50%) rotateX(-45deg) translateZ(${hh}px)`;\n case \"bottom_rear\":\n return `translate(-50%, -50%) rotateX(-135deg) translateZ(${hh}px)`;\n default:\n return `translate(-50%, -50%) translateZ(${hd}px)`;\n }\n}\n\n/* ------------------------------------------------------------------ */\n/* Face transform — flat (unfolded) positions */\n/* */\n/* Flat order: front | right | back | left */\n/* Centred on the midpoint of the full row. */\n/* ------------------------------------------------------------------ */\n\nfunction faceTransformFlat(\n name: string,\n w: number,\n h: number,\n d: number\n): string {\n const total = 2 * w + 2 * d;\n const half = total / 2;\n\n let cx: number;\n\n switch (name as FaceName) {\n case \"front\":\n cx = w / 2;\n break;\n case \"right\":\n cx = w + d / 2;\n break;\n case \"back\":\n cx = w + d + w / 2;\n break;\n case \"left\":\n cx = w + d + w + d / 2;\n break;\n case \"top\":\n case \"top_front\":\n case \"top_rear\":\n cx = w / 2;\n return `translate(-50%, -50%) translateX(${cx - half}px) translateY(-${h}px)`;\n case \"bottom\":\n case \"bottom_front\":\n case \"bottom_rear\":\n cx = w / 2;\n return `translate(-50%, -50%) translateX(${cx - half}px) translateY(${h}px)`;\n default:\n cx = w / 2;\n break;\n }\n\n return `translate(-50%, -50%) translateX(${cx - half}px)`;\n}\n\n/* ------------------------------------------------------------------ */\n/* Parse a legacy CSS text string into a CSSProperties object */\n/* ------------------------------------------------------------------ */\n\nfunction parseCssText(css?: string): React.CSSProperties {\n if (!css) return {};\n const style: Record<string, string> = {};\n css.split(\";\").forEach((rule) => {\n const [prop, ...rest] = rule.split(\":\");\n if (!prop || rest.length === 0) return;\n const key = prop\n .trim()\n .replace(/-([a-z])/g, (_, c) => c.toUpperCase());\n style[key] = rest.join(\":\").trim();\n });\n return style as React.CSSProperties;\n}\n\n/* ------------------------------------------------------------------ */\n/* Resolve face dimensions for non-standard faces */\n/* ------------------------------------------------------------------ */\n\nfunction faceDimensions(\n name: string,\n w: number,\n h: number,\n d: number\n): { width: number; height: number } {\n switch (name as FaceName) {\n case \"left\":\n case \"right\":\n return { width: d, height: h };\n case \"top\":\n case \"bottom\":\n case \"top_front\":\n case \"top_rear\":\n case \"bottom_front\":\n case \"bottom_rear\":\n return { width: w, height: d };\n default:\n return { width: w, height: h };\n }\n}\n\n/* ------------------------------------------------------------------ */\n/* Build appearance style for a face (colours, borders, etc.) */\n/* Does NOT include position / transform / size. */\n/* ------------------------------------------------------------------ */\n\nfunction faceAppearance(\n face: FaceDef,\n globalDef?: GlobalDef\n): {\n style: React.CSSProperties;\n className: string;\n body: React.ReactNode;\n} {\n const globalStyle = parseCssText(globalDef?.css);\n const faceInlineStyle = parseCssText(face.css);\n\n const style: React.CSSProperties = {\n ...globalStyle,\n ...(globalDef?.style ?? {}),\n ...faceInlineStyle,\n ...(face.style ?? {}),\n };\n\n const className = [\"anim3d-face\", face.className]\n .filter(Boolean)\n .join(\" \");\n\n const body = face.body ?? globalDef?.body ?? null;\n\n return { style, className, body };\n}\n\n/* ------------------------------------------------------------------ */\n/* Default 6-sided cube when no faces are provided */\n/* ------------------------------------------------------------------ */\n\nconst DEFAULT_FACE_NAMES: FaceName[] = [\n \"front\",\n \"back\",\n \"left\",\n \"right\",\n \"top\",\n \"bottom\",\n];\n\n/* ------------------------------------------------------------------ */\n/* Stagger order for oneAtATime (standard mode) */\n/* ------------------------------------------------------------------ */\n\nconst STAGGER_ORDER: string[] = [\n \"front\",\n \"right\",\n \"back\",\n \"left\",\n \"top\",\n \"bottom\",\n \"top_front\",\n \"top_rear\",\n \"bottom_front\",\n \"bottom_rear\",\n];\n\n/* ------------------------------------------------------------------ */\n/* Component */\n/* ------------------------------------------------------------------ */\n\nexport const Obj: React.FC<ObjProps> = React.memo(\n ({\n width = 160,\n height = 160,\n depth = 150,\n perspective = 600,\n perspectiveOrigin = \"50% 50%\",\n faces,\n global: globalDef,\n anim1,\n anim2,\n showCenterDiv = false,\n flat = false,\n transitionDuration = 1,\n oneAtATime = false,\n remainJoined = false,\n ytilt = false,\n className,\n style,\n }) => {\n const w =\n typeof width === \"number\" ? width : parseFloat(String(width));\n const h =\n typeof height === \"number\" ? height : parseFloat(String(height));\n const d =\n typeof depth === \"number\" ? depth : parseFloat(String(depth));\n\n // Resolve animation shorthands\n const animation1 = toAnimationShorthand(anim1) ?? undefined;\n const animation2 = toAnimationShorthand(anim2) ?? undefined;\n\n // Determine which faces to render\n const faceList: FaceDef[] =\n faces && faces.length > 0\n ? faces\n : DEFAULT_FACE_NAMES.map((name) => ({ name }));\n\n const transitionCss = (delay = 0) =>\n `transform ${transitionDuration}s ease-in-out ${delay}s`;\n\n /* ============================================================ */\n /* Y-tilt — fire a one-shot rotateX(0→45→0) each time */\n /* flat changes. We alternate between two identical keyframe */\n /* names (a/b) so the browser re-triggers the animation. */\n /* ============================================================ */\n\n const tiltCount = React.useRef(0);\n const prevFlat = React.useRef(flat);\n const [tiltAnim, setTiltAnim] = React.useState<\n string | undefined\n >(undefined);\n\n React.useEffect(() => {\n if (flat !== prevFlat.current) {\n prevFlat.current = flat;\n if (ytilt) {\n tiltCount.current += 1;\n const sideCount = faceList.filter((f) =>\n [\"front\", \"right\", \"back\", \"left\"].includes(\n f.name\n )\n ).length;\n const totalDur = oneAtATime\n ? transitionDuration * sideCount\n : transitionDuration;\n const name =\n tiltCount.current % 2 === 0\n ? \"anim3d-ytilt-a\"\n : \"anim3d-ytilt-b\";\n setTiltAnim(\n `${name} ${totalDur}s ease-in-out 1 forwards`\n );\n // Clear animation after it completes so it can re-trigger\n const timer = setTimeout(\n () => setTiltAnim(undefined),\n totalDur * 1000 + 50\n );\n return () => clearTimeout(timer);\n }\n }\n }, [flat, ytilt, transitionDuration, oneAtATime, faceList]);\n\n /* ============================================================ */\n /* Standard rendering (no remainJoined) */\n /* ============================================================ */\n\n const renderStandard = () =>\n faceList.map((face, i) => {\n const dims = faceDimensions(face.name, w, h, d);\n const transform = flat\n ? faceTransformFlat(face.name, w, h, d)\n : faceTransform3D(face.name, w, h, d);\n\n const {\n style: fStyle,\n className: fCls,\n body,\n } = faceAppearance(face, globalDef);\n\n const idx = STAGGER_ORDER.indexOf(face.name);\n const delay = oneAtATime\n ? (idx >= 0 ? idx : i) * transitionDuration\n : 0;\n\n return (\n <div\n key={face.name + \"-\" + i}\n className={fCls}\n style={{\n ...fStyle,\n width: dims.width,\n height: dims.height,\n transform,\n transition: transitionCss(delay),\n }}\n >\n {body}\n </div>\n );\n });\n\n /* ============================================================ */\n /* Joined rendering — nested hinge structure */\n /* */\n /* Chain: front → right → back → left (hinged at shared edges) */\n /* The left–front edge is the break‑point. */\n /* */\n /* Flat order: front | right | back | left (left on far right) */\n /* ============================================================ */\n\n const renderJoined = () => {\n const findFace = (n: string) =>\n faceList.find((f) => f.name === n);\n\n const frontFace = findFace(\"front\");\n const rightFace = findFace(\"right\");\n const backFace = findFace(\"back\");\n const leftFace = findFace(\"left\");\n\n const sideNames = new Set([\n \"front\",\n \"right\",\n \"back\",\n \"left\",\n ]);\n const otherFaces = faceList.filter(\n (f) => !sideNames.has(f.name)\n );\n\n const step = oneAtATime ? transitionDuration : 0;\n\n /* Helper: render a single face element with merged styles */\n const renderFaceEl = (\n face: FaceDef | undefined,\n dims: { width: number; height: number },\n extra: React.CSSProperties,\n key: string\n ) => {\n if (!face) return null;\n const {\n style: fStyle,\n className: fCls,\n body,\n } = faceAppearance(face, globalDef);\n return (\n <div\n key={key}\n className={fCls}\n style={{\n ...fStyle,\n width: dims.width,\n height: dims.height,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n boxSizing: \"border-box\",\n ...extra,\n }}\n >\n {body}\n </div>\n );\n };\n\n return (\n <>\n {/* ---- Front face (anchor) ---- */}\n {renderFaceEl(\n frontFace,\n { width: w, height: h },\n {\n position: \"absolute\",\n left: \"50%\",\n top: \"50%\",\n transform: flat\n ? \"translate(-50%, -50%)\"\n : `translate(-50%, -50%) translateZ(${d / 2}px)`,\n transition: transitionCss(0),\n },\n \"front-j\"\n )}\n\n {/* ---- Right hinge (pivots at front's right edge) ---- */}\n <div\n style={{\n position: \"absolute\",\n left: `calc(50% + ${w / 2}px)`,\n top: \"50%\",\n width: 0,\n height: 0,\n transformOrigin: \"0 0\",\n transformStyle: \"preserve-3d\",\n transform: flat\n ? \"none\"\n : `translateZ(${d / 2}px) rotateY(90deg)`,\n transition: transitionCss(step),\n }}\n >\n {/* Right face */}\n {renderFaceEl(\n rightFace,\n { width: d, height: h },\n {\n position: \"absolute\",\n left: 0,\n top: 0,\n transform: \"translateY(-50%)\",\n },\n \"right-j\"\n )}\n\n {/* ---- Back hinge (pivots at right's far edge) ---- */}\n <div\n style={{\n position: \"absolute\",\n left: d,\n top: 0,\n width: 0,\n height: 0,\n transformOrigin: \"0 0\",\n transformStyle: \"preserve-3d\",\n transform: flat\n ? \"none\"\n : \"rotateY(90deg)\",\n transition: transitionCss(step * 2),\n }}\n >\n {/* Back face */}\n {renderFaceEl(\n backFace,\n { width: w, height: h },\n {\n position: \"absolute\",\n left: 0,\n top: 0,\n transform: \"translateY(-50%)\",\n },\n \"back-j\"\n )}\n\n {/* ---- Left hinge (pivots at back's far edge) ---- */}\n <div\n style={{\n position: \"absolute\",\n left: w,\n top: 0,\n width: 0,\n height: 0,\n transformOrigin: \"0 0\",\n transformStyle: \"preserve-3d\",\n transform: flat\n ? \"none\"\n : \"rotateY(90deg)\",\n transition: transitionCss(step * 3),\n }}\n >\n {/* Left face */}\n {renderFaceEl(\n leftFace,\n { width: d, height: h },\n {\n position: \"absolute\",\n left: 0,\n top: 0,\n transform: \"translateY(-50%)\",\n },\n \"left-j\"\n )}\n </div>\n </div>\n </div>\n\n {/* ---- Non-side faces (top, bottom, etc.) ---- */}\n {otherFaces.map((face, i) => {\n const dims = faceDimensions(face.name, w, h, d);\n const xform = flat\n ? faceTransformFlat(face.name, w, h, d)\n : faceTransform3D(face.name, w, h, d);\n const {\n style: fStyle,\n className: fCls,\n body,\n } = faceAppearance(face, globalDef);\n return (\n <div\n key={face.name + \"-o-\" + i}\n className={fCls}\n style={{\n ...fStyle,\n width: dims.width,\n height: dims.height,\n transform: xform,\n transition: transitionCss(0),\n }}\n >\n {body}\n </div>\n );\n })}\n </>\n );\n };\n\n /* ============================================================ */\n /* Render tree */\n /* ============================================================ */\n\n const cssVars = {\n \"--obj-w\": w + \"px\",\n \"--obj-h\": h + \"px\",\n \"--obj-d\": d + \"px\",\n } as React.CSSProperties;\n\n return (\n <div\n className={[\"anim3d-stage\", className]\n .filter(Boolean)\n .join(\" \")}\n style={{\n perspective,\n perspectiveOrigin,\n ...cssVars,\n ...style,\n }}\n data-anim-3d-obj\n role=\"img\"\n aria-label=\"3D object\"\n >\n {/* Y-tilt wrapper — sits between stage and anim wrappers */}\n <div\n style={{\n transformStyle: \"preserve-3d\",\n animation: tiltAnim,\n }}\n >\n {/* Outer animation wrapper (anim1) */}\n <div\n className=\"anim3d-wrapper\"\n style={{\n ...cssVars,\n animation: flat ? \"none\" : animation1,\n transformStyle: \"preserve-3d\",\n transition: transitionCss(),\n }}\n >\n {/* Inner animation wrapper (anim2) */}\n <div\n className=\"anim3d-wrapper\"\n style={{\n ...cssVars,\n animation: flat ? \"none\" : animation2,\n transformStyle: \"preserve-3d\",\n transition: transitionCss(),\n }}\n >\n {showCenterDiv && (\n <div className=\"anim3d-center\" />\n )}\n {remainJoined\n ? renderJoined()\n : renderStandard()}\n </div>\n </div>\n </div>\n </div>\n );\n }\n);\n\nObj.displayName = \"Obj\";\n"]}
|
package/dist/index.css
CHANGED
|
@@ -32,47 +32,26 @@
|
|
|
32
32
|
backface-visibility: visible;
|
|
33
33
|
box-sizing: border-box;
|
|
34
34
|
}
|
|
35
|
-
|
|
36
|
-
position: absolute;
|
|
37
|
-
inset: 0;
|
|
38
|
-
overflow: hidden;
|
|
39
|
-
pointer-events: none;
|
|
40
|
-
z-index: 1;
|
|
41
|
-
}
|
|
42
|
-
.anim3d-sheen-bar {
|
|
43
|
-
position: absolute;
|
|
44
|
-
top: 0;
|
|
45
|
-
left: 0;
|
|
46
|
-
width: 40%;
|
|
47
|
-
height: 100%;
|
|
48
|
-
background:
|
|
49
|
-
linear-gradient(
|
|
50
|
-
105deg,
|
|
51
|
-
transparent 20%,
|
|
52
|
-
rgba(255, 255, 255, 0.35) 45%,
|
|
53
|
-
rgba(255, 255, 255, 0.5) 50%,
|
|
54
|
-
rgba(255, 255, 255, 0.35) 55%,
|
|
55
|
-
transparent 80%);
|
|
56
|
-
opacity: 0;
|
|
57
|
-
transform: translateX(-100%);
|
|
58
|
-
animation: anim3d-sheen-sweep var(--sheen-dur, 6s) linear infinite;
|
|
59
|
-
animation-delay: var(--sheen-delay, 0s);
|
|
60
|
-
}
|
|
61
|
-
@keyframes anim3d-sheen-sweep {
|
|
35
|
+
@keyframes anim3d-ytilt-a {
|
|
62
36
|
0% {
|
|
63
|
-
transform:
|
|
64
|
-
opacity: 0;
|
|
37
|
+
transform: rotateX(0deg);
|
|
65
38
|
}
|
|
66
|
-
|
|
67
|
-
|
|
39
|
+
50% {
|
|
40
|
+
transform: rotateX(45deg);
|
|
41
|
+
}
|
|
42
|
+
100% {
|
|
43
|
+
transform: rotateX(0deg);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
@keyframes anim3d-ytilt-b {
|
|
47
|
+
0% {
|
|
48
|
+
transform: rotateX(0deg);
|
|
68
49
|
}
|
|
69
|
-
|
|
70
|
-
transform:
|
|
71
|
-
opacity: 0;
|
|
50
|
+
50% {
|
|
51
|
+
transform: rotateX(45deg);
|
|
72
52
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
transform: translateX(-100%);
|
|
53
|
+
100% {
|
|
54
|
+
transform: rotateX(0deg);
|
|
76
55
|
}
|
|
77
56
|
}
|
|
78
57
|
/*# sourceMappingURL=index.css.map */
|
package/dist/index.css.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/styles/obj.css"],"sourcesContent":[".anim3d-stage {\n position: relative;\n width: max-content;\n height: max-content;\n /* perspective is set inline via props */\n}\n\n.anim3d-wrapper {\n position: relative;\n transform-style: preserve-3d;\n width: var(--obj-w, 160px);\n height: var(--obj-h, 160px);\n}\n\n.anim3d-center {\n position: absolute;\n left: 50%;\n top: 50%;\n width: 2px;\n height: 2px;\n background: #f00;\n transform: translate(-50%, -50%);\n z-index: 10;\n pointer-events: none;\n}\n\n.anim3d-face {\n position: absolute;\n left: 50%;\n top: 50%;\n transform-style: preserve-3d;\n display: flex;\n align-items: center;\n justify-content: center;\n backface-visibility: visible;\n box-sizing: border-box;\n /* width/height/transform set inline per face */\n}\n\n/* ----
|
|
1
|
+
{"version":3,"sources":["../src/styles/obj.css"],"sourcesContent":[".anim3d-stage {\n position: relative;\n width: max-content;\n height: max-content;\n /* perspective is set inline via props */\n}\n\n.anim3d-wrapper {\n position: relative;\n transform-style: preserve-3d;\n width: var(--obj-w, 160px);\n height: var(--obj-h, 160px);\n}\n\n.anim3d-center {\n position: absolute;\n left: 50%;\n top: 50%;\n width: 2px;\n height: 2px;\n background: #f00;\n transform: translate(-50%, -50%);\n z-index: 10;\n pointer-events: none;\n}\n\n.anim3d-face {\n position: absolute;\n left: 50%;\n top: 50%;\n transform-style: preserve-3d;\n display: flex;\n align-items: center;\n justify-content: center;\n backface-visibility: visible;\n box-sizing: border-box;\n /* width/height/transform set inline per face */\n}\n\n/* ---- Y-tilt: tips forward 45° during fold/unfold, then returns ---- */\n\n@keyframes anim3d-ytilt-a {\n 0% {\n transform: rotateX(0deg);\n }\n 50% {\n transform: rotateX(45deg);\n }\n 100% {\n transform: rotateX(0deg);\n }\n}\n\n@keyframes anim3d-ytilt-b {\n 0% {\n transform: rotateX(0deg);\n }\n 50% {\n transform: rotateX(45deg);\n }\n 100% {\n transform: rotateX(0deg);\n }\n}\n"],"mappings":";AAAA,CAAC;AACE,YAAU;AACV,SAAO;AACP,UAAQ;AAEX;AAEA,CAAC;AACE,YAAU;AACV,mBAAiB;AACjB,SAAO,IAAI,OAAO,EAAE;AACpB,UAAQ,IAAI,OAAO,EAAE;AACxB;AAEA,CAAC;AACE,YAAU;AACV,QAAM;AACN,OAAK;AACL,SAAO;AACP,UAAQ;AACR,cAAY;AACZ,aAAW,UAAU,IAAI,EAAE;AAC3B,WAAS;AACT,kBAAgB;AACnB;AAEA,CAAC;AACE,YAAU;AACV,QAAM;AACN,OAAK;AACL,mBAAiB;AACjB,WAAS;AACT,eAAa;AACb,mBAAiB;AACjB,uBAAqB;AACrB,cAAY;AAEf;AAIA,WAAW;AACR;AACG,eAAW,QAAQ;AACtB;AACA;AACG,eAAW,QAAQ;AACtB;AACA;AACG,eAAW,QAAQ;AACtB;AACH;AAEA,WAAW;AACR;AACG,eAAW,QAAQ;AACtB;AACA;AACG,eAAW,QAAQ;AACtB;AACA;AACG,eAAW,QAAQ;AACtB;AACH;","names":[]}
|
package/dist/index.d.mts
CHANGED
|
@@ -51,10 +51,10 @@ type ObjProps = {
|
|
|
51
51
|
/** When true, connected edges stay joined during unfold (front→right→back chain).
|
|
52
52
|
* The left–front edge is the break point. */
|
|
53
53
|
remainJoined?: boolean;
|
|
54
|
-
/** When true,
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
|
|
54
|
+
/** When true, the object tilts 45° on the X-axis (tips forward) during
|
|
55
|
+
* a fold/unfold transition, then returns to 0° when the transition
|
|
56
|
+
* completes. Only active while flat is changing. */
|
|
57
|
+
ytilt?: boolean;
|
|
58
58
|
className?: string;
|
|
59
59
|
style?: CSSProperties;
|
|
60
60
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -51,10 +51,10 @@ type ObjProps = {
|
|
|
51
51
|
/** When true, connected edges stay joined during unfold (front→right→back chain).
|
|
52
52
|
* The left–front edge is the break point. */
|
|
53
53
|
remainJoined?: boolean;
|
|
54
|
-
/** When true,
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
|
|
54
|
+
/** When true, the object tilts 45° on the X-axis (tips forward) during
|
|
55
|
+
* a fold/unfold transition, then returns to 0° when the transition
|
|
56
|
+
* completes. Only active while flat is changing. */
|
|
57
|
+
ytilt?: boolean;
|
|
58
58
|
className?: string;
|
|
59
59
|
style?: CSSProperties;
|
|
60
60
|
};
|
package/dist/index.js
CHANGED
|
@@ -169,28 +169,6 @@ function faceAppearance(face, globalDef) {
|
|
|
169
169
|
const body = face.body ?? globalDef?.body ?? null;
|
|
170
170
|
return { style, className, body };
|
|
171
171
|
}
|
|
172
|
-
var Y_FACE_OFFSET = {
|
|
173
|
-
front: 0,
|
|
174
|
-
right: 0.25,
|
|
175
|
-
back: 0.5,
|
|
176
|
-
left: 0.75
|
|
177
|
-
};
|
|
178
|
-
function sheenOverlay(faceName, animDuration, isFlat) {
|
|
179
|
-
if (isFlat) return null;
|
|
180
|
-
const offset = Y_FACE_OFFSET[faceName];
|
|
181
|
-
if (offset === void 0) return null;
|
|
182
|
-
const delay = offset * animDuration;
|
|
183
|
-
return /* @__PURE__ */ jsx("div", { className: "anim3d-sheen", children: /* @__PURE__ */ jsx(
|
|
184
|
-
"div",
|
|
185
|
-
{
|
|
186
|
-
className: "anim3d-sheen-bar",
|
|
187
|
-
style: {
|
|
188
|
-
"--sheen-dur": animDuration + "s",
|
|
189
|
-
"--sheen-delay": delay + "s"
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
) });
|
|
193
|
-
}
|
|
194
172
|
var DEFAULT_FACE_NAMES = [
|
|
195
173
|
"front",
|
|
196
174
|
"back",
|
|
@@ -227,7 +205,7 @@ var Obj = React.memo(
|
|
|
227
205
|
transitionDuration = 1,
|
|
228
206
|
oneAtATime = false,
|
|
229
207
|
remainJoined = false,
|
|
230
|
-
|
|
208
|
+
ytilt = false,
|
|
231
209
|
className,
|
|
232
210
|
style
|
|
233
211
|
}) => {
|
|
@@ -238,7 +216,32 @@ var Obj = React.memo(
|
|
|
238
216
|
const animation2 = toAnimationShorthand(anim2) ?? void 0;
|
|
239
217
|
const faceList = faces && faces.length > 0 ? faces : DEFAULT_FACE_NAMES.map((name) => ({ name }));
|
|
240
218
|
const transitionCss = (delay = 0) => `transform ${transitionDuration}s ease-in-out ${delay}s`;
|
|
241
|
-
const
|
|
219
|
+
const tiltCount = React.useRef(0);
|
|
220
|
+
const prevFlat = React.useRef(flat);
|
|
221
|
+
const [tiltAnim, setTiltAnim] = React.useState(void 0);
|
|
222
|
+
React.useEffect(() => {
|
|
223
|
+
if (flat !== prevFlat.current) {
|
|
224
|
+
prevFlat.current = flat;
|
|
225
|
+
if (ytilt) {
|
|
226
|
+
tiltCount.current += 1;
|
|
227
|
+
const sideCount = faceList.filter(
|
|
228
|
+
(f) => ["front", "right", "back", "left"].includes(
|
|
229
|
+
f.name
|
|
230
|
+
)
|
|
231
|
+
).length;
|
|
232
|
+
const totalDur = oneAtATime ? transitionDuration * sideCount : transitionDuration;
|
|
233
|
+
const name = tiltCount.current % 2 === 0 ? "anim3d-ytilt-a" : "anim3d-ytilt-b";
|
|
234
|
+
setTiltAnim(
|
|
235
|
+
`${name} ${totalDur}s ease-in-out 1 forwards`
|
|
236
|
+
);
|
|
237
|
+
const timer = setTimeout(
|
|
238
|
+
() => setTiltAnim(void 0),
|
|
239
|
+
totalDur * 1e3 + 50
|
|
240
|
+
);
|
|
241
|
+
return () => clearTimeout(timer);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}, [flat, ytilt, transitionDuration, oneAtATime, faceList]);
|
|
242
245
|
const renderStandard = () => faceList.map((face, i) => {
|
|
243
246
|
const dims = faceDimensions(face.name, w, h, d);
|
|
244
247
|
const transform = flat ? faceTransformFlat(face.name, w, h, d) : faceTransform3D(face.name, w, h, d);
|
|
@@ -249,7 +252,7 @@ var Obj = React.memo(
|
|
|
249
252
|
} = faceAppearance(face, globalDef);
|
|
250
253
|
const idx = STAGGER_ORDER.indexOf(face.name);
|
|
251
254
|
const delay = oneAtATime ? (idx >= 0 ? idx : i) * transitionDuration : 0;
|
|
252
|
-
return /* @__PURE__ */
|
|
255
|
+
return /* @__PURE__ */ jsx(
|
|
253
256
|
"div",
|
|
254
257
|
{
|
|
255
258
|
className: fCls,
|
|
@@ -260,10 +263,7 @@ var Obj = React.memo(
|
|
|
260
263
|
transform,
|
|
261
264
|
transition: transitionCss(delay)
|
|
262
265
|
},
|
|
263
|
-
children:
|
|
264
|
-
body,
|
|
265
|
-
sheen && sheenOverlay(face.name, sheenDur, flat)
|
|
266
|
-
]
|
|
266
|
+
children: body
|
|
267
267
|
},
|
|
268
268
|
face.name + "-" + i
|
|
269
269
|
);
|
|
@@ -291,7 +291,7 @@ var Obj = React.memo(
|
|
|
291
291
|
className: fCls,
|
|
292
292
|
body
|
|
293
293
|
} = faceAppearance(face, globalDef);
|
|
294
|
-
return /* @__PURE__ */
|
|
294
|
+
return /* @__PURE__ */ jsx(
|
|
295
295
|
"div",
|
|
296
296
|
{
|
|
297
297
|
className: fCls,
|
|
@@ -305,10 +305,7 @@ var Obj = React.memo(
|
|
|
305
305
|
boxSizing: "border-box",
|
|
306
306
|
...extra
|
|
307
307
|
},
|
|
308
|
-
children:
|
|
309
|
-
body,
|
|
310
|
-
sheen && sheenOverlay(face.name, sheenDur, flat)
|
|
311
|
-
]
|
|
308
|
+
children: body
|
|
312
309
|
},
|
|
313
310
|
key
|
|
314
311
|
);
|
|
@@ -458,27 +455,36 @@ var Obj = React.memo(
|
|
|
458
455
|
children: /* @__PURE__ */ jsx(
|
|
459
456
|
"div",
|
|
460
457
|
{
|
|
461
|
-
className: "anim3d-wrapper",
|
|
462
458
|
style: {
|
|
463
|
-
...cssVars,
|
|
464
|
-
animation: flat ? "none" : animation1,
|
|
465
459
|
transformStyle: "preserve-3d",
|
|
466
|
-
|
|
460
|
+
animation: tiltAnim
|
|
467
461
|
},
|
|
468
|
-
children: /* @__PURE__ */
|
|
462
|
+
children: /* @__PURE__ */ jsx(
|
|
469
463
|
"div",
|
|
470
464
|
{
|
|
471
465
|
className: "anim3d-wrapper",
|
|
472
466
|
style: {
|
|
473
467
|
...cssVars,
|
|
474
|
-
animation: flat ? "none" :
|
|
468
|
+
animation: flat ? "none" : animation1,
|
|
475
469
|
transformStyle: "preserve-3d",
|
|
476
470
|
transition: transitionCss()
|
|
477
471
|
},
|
|
478
|
-
children:
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
472
|
+
children: /* @__PURE__ */ jsxs(
|
|
473
|
+
"div",
|
|
474
|
+
{
|
|
475
|
+
className: "anim3d-wrapper",
|
|
476
|
+
style: {
|
|
477
|
+
...cssVars,
|
|
478
|
+
animation: flat ? "none" : animation2,
|
|
479
|
+
transformStyle: "preserve-3d",
|
|
480
|
+
transition: transitionCss()
|
|
481
|
+
},
|
|
482
|
+
children: [
|
|
483
|
+
showCenterDiv && /* @__PURE__ */ jsx("div", { className: "anim3d-center" }),
|
|
484
|
+
remainJoined ? renderJoined() : renderStandard()
|
|
485
|
+
]
|
|
486
|
+
}
|
|
487
|
+
)
|
|
482
488
|
}
|
|
483
489
|
)
|
|
484
490
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/keyframes.ts","../src/components/Obj.tsx"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { AnimationConfig } from \"./types\";\n\n/** Create (or reuse) a <style> tag for dynamic keyframes */\nfunction ensureStyleTag(): HTMLStyleElement {\n let tag = document.getElementById(\n \"anim3d-keyframes\"\n ) as HTMLStyleElement | null;\n if (!tag) {\n tag = document.createElement(\"style\");\n tag.id = \"anim3d-keyframes\";\n document.head.appendChild(tag);\n }\n return tag;\n}\n\nfunction inject(css: string) {\n if (typeof document === \"undefined\") return; // SSR\n const tag = ensureStyleTag();\n tag.appendChild(document.createTextNode(css));\n}\n\n/** Keyframes text for built-ins */\nfunction builtInKeyframes(name: string, cfg: AnimationConfig) {\n const hi = cfg.degreesHi ?? 15;\n const lo = cfg.degreesLow ?? -15;\n switch (name) {\n case \"Y360\":\n return `@keyframes Y360 { from { transform: rotateY(0deg) } to { transform: rotateY(360deg) } }`;\n case \"X360\":\n return `@keyframes X360 { from { transform: rotateX(0deg) } to { transform: rotateX(360deg) } }`;\n case \"Z360\":\n return `@keyframes Z360 { from { transform: rotateZ(0deg) } to { transform: rotateZ(360deg) } }`;\n case \"rockY\":\n return `@keyframes rockY { 0%{ transform: rotateY(${lo}deg) } 50%{ transform: rotateY(${hi}deg) } 100%{ transform: rotateY(${lo}deg) } }`;\n case \"rockX\":\n return `@keyframes rockX { 0%{ transform: rotateX(${lo}deg) } 50%{ transform: rotateX(${hi}deg) } 100%{ transform: rotateX(${lo}deg) } }`;\n default:\n // Custom names: let authors supply their own @keyframes in global CSS with that name.\n return \"\";\n }\n}\n\n/** Returns a concrete animation-name and ensures keyframes exist (for built-ins) */\nexport function resolveAnimation(cfg?: AnimationConfig): string | null {\n if (!cfg) return null;\n const name = cfg.name;\n const builtIn = builtInKeyframes(name, cfg);\n if (builtIn) {\n // Ensure single injection per built-in name\n const marker = `/*kf-${name}*/`;\n if (typeof document !== \"undefined\") {\n const tag = ensureStyleTag();\n if (!tag.innerHTML.includes(marker)) {\n inject(`${builtIn}\\n${marker}`);\n }\n }\n return name; // use built-in name as animation-name\n }\n // custom: use author-provided @keyframes by name\n return name;\n}\n\n/** Build the full CSS animation shorthand from a config and resolved name */\nexport function toAnimationShorthand(cfg?: AnimationConfig): string | null {\n const name = resolveAnimation(cfg);\n if (!cfg || !name) return null;\n const dur = (cfg.duration ?? 10) + \"s\";\n const delay = (cfg.delay ?? 0) + \"s\";\n const iter = cfg.iterationCount ?? \"infinite\";\n const dir = cfg.direction ?? \"normal\";\n const timing = cfg.timing ?? \"linear\";\n const fill = cfg.fillMode ?? \"forwards\";\n const play = cfg.animationPlayState ?? \"running\";\n // name duration timing delay iteration-count direction fill-mode play-state\n return `${name} ${dur} ${timing} ${delay} ${iter} ${dir} ${fill} ${play}`;\n}\n","import * as React from \"react\";\nimport type {\n ObjProps,\n FaceDef,\n FaceName,\n GlobalDef,\n} from \"../types\";\nimport { toAnimationShorthand } from \"../keyframes\";\nimport \"../styles/obj.css\";\n\n// Re-export the canonical ObjProps from types.ts\nexport type { ObjProps } from \"../types\";\n\n/* ------------------------------------------------------------------ */\n/* Face transform — 3D cuboid positions */\n/* ------------------------------------------------------------------ */\n\nfunction faceTransform3D(\n name: string,\n w: number,\n h: number,\n d: number\n): string {\n const hw = w / 2;\n const hh = h / 2;\n const hd = d / 2;\n\n switch (name as FaceName) {\n case \"front\":\n return `translate(-50%, -50%) translateZ(${hd}px)`;\n case \"back\":\n return `translate(-50%, -50%) rotateY(180deg) translateZ(${hd}px)`;\n case \"left\":\n return `translate(-50%, -50%) rotateY(-90deg) translateZ(${hw}px)`;\n case \"right\":\n return `translate(-50%, -50%) rotateY(90deg) translateZ(${hw}px)`;\n case \"top\":\n return `translate(-50%, -50%) rotateX(90deg) translateZ(${hh}px)`;\n case \"bottom\":\n return `translate(-50%, -50%) rotateX(-90deg) translateZ(${hh}px)`;\n case \"top_front\":\n return `translate(-50%, -50%) rotateX(45deg) translateZ(${hh}px)`;\n case \"top_rear\":\n return `translate(-50%, -50%) rotateX(135deg) translateZ(${hh}px)`;\n case \"bottom_front\":\n return `translate(-50%, -50%) rotateX(-45deg) translateZ(${hh}px)`;\n case \"bottom_rear\":\n return `translate(-50%, -50%) rotateX(-135deg) translateZ(${hh}px)`;\n default:\n return `translate(-50%, -50%) translateZ(${hd}px)`;\n }\n}\n\n/* ------------------------------------------------------------------ */\n/* Face transform — flat (unfolded) positions */\n/* */\n/* Flat order: front | right | back | left */\n/* Centred on the midpoint of the full row. */\n/* ------------------------------------------------------------------ */\n\nfunction faceTransformFlat(\n name: string,\n w: number,\n h: number,\n d: number\n): string {\n // Row layout (left to right): front(w) | right(d) | back(w) | left(d)\n // Total width = 2w + 2d. Centre of row at (w + d).\n const total = 2 * w + 2 * d;\n const half = total / 2;\n\n let cx: number;\n\n switch (name as FaceName) {\n case \"front\":\n cx = w / 2;\n break;\n case \"right\":\n cx = w + d / 2;\n break;\n case \"back\":\n cx = w + d + w / 2;\n break;\n case \"left\":\n cx = w + d + w + d / 2;\n break;\n case \"top\":\n case \"top_front\":\n case \"top_rear\":\n cx = w / 2;\n return `translate(-50%, -50%) translateX(${cx - half}px) translateY(-${h}px)`;\n case \"bottom\":\n case \"bottom_front\":\n case \"bottom_rear\":\n cx = w / 2;\n return `translate(-50%, -50%) translateX(${cx - half}px) translateY(${h}px)`;\n default:\n cx = w / 2;\n break;\n }\n\n return `translate(-50%, -50%) translateX(${cx - half}px)`;\n}\n\n/* ------------------------------------------------------------------ */\n/* Parse a legacy CSS text string into a CSSProperties object */\n/* ------------------------------------------------------------------ */\n\nfunction parseCssText(css?: string): React.CSSProperties {\n if (!css) return {};\n const style: Record<string, string> = {};\n css.split(\";\").forEach((rule) => {\n const [prop, ...rest] = rule.split(\":\");\n if (!prop || rest.length === 0) return;\n const key = prop\n .trim()\n .replace(/-([a-z])/g, (_, c) => c.toUpperCase());\n style[key] = rest.join(\":\").trim();\n });\n return style as React.CSSProperties;\n}\n\n/* ------------------------------------------------------------------ */\n/* Resolve face dimensions for non-standard faces */\n/* ------------------------------------------------------------------ */\n\nfunction faceDimensions(\n name: string,\n w: number,\n h: number,\n d: number\n): { width: number; height: number } {\n switch (name as FaceName) {\n case \"left\":\n case \"right\":\n return { width: d, height: h };\n case \"top\":\n case \"bottom\":\n case \"top_front\":\n case \"top_rear\":\n case \"bottom_front\":\n case \"bottom_rear\":\n return { width: w, height: d };\n default:\n return { width: w, height: h };\n }\n}\n\n/* ------------------------------------------------------------------ */\n/* Build appearance style for a face (colours, borders, etc.) */\n/* Does NOT include position / transform / size. */\n/* ------------------------------------------------------------------ */\n\nfunction faceAppearance(\n face: FaceDef,\n globalDef?: GlobalDef\n): {\n style: React.CSSProperties;\n className: string;\n body: React.ReactNode;\n} {\n const globalStyle = parseCssText(globalDef?.css);\n const faceInlineStyle = parseCssText(face.css);\n\n const style: React.CSSProperties = {\n ...globalStyle,\n ...(globalDef?.style ?? {}),\n ...faceInlineStyle,\n ...(face.style ?? {}),\n };\n\n const className = [\"anim3d-face\", face.className]\n .filter(Boolean)\n .join(\" \");\n\n const body = face.body ?? globalDef?.body ?? null;\n\n return { style, className, body };\n}\n\n/* ------------------------------------------------------------------ */\n/* Sheen overlay — sweeps across each face as it leaves face-on */\n/* ------------------------------------------------------------------ */\n\n/** Fraction of rotation cycle at which each face is face-on (Y-axis) */\nconst Y_FACE_OFFSET: Record<string, number> = {\n front: 0,\n right: 0.25,\n back: 0.5,\n left: 0.75,\n};\n\nfunction sheenOverlay(\n faceName: string,\n animDuration: number,\n isFlat: boolean\n): React.ReactNode {\n if (isFlat) return null;\n const offset = Y_FACE_OFFSET[faceName];\n if (offset === undefined) return null; // no sheen for top/bottom etc.\n const delay = offset * animDuration;\n\n return (\n <div className=\"anim3d-sheen\">\n <div\n className=\"anim3d-sheen-bar\"\n style={{\n \"--sheen-dur\": animDuration + \"s\",\n \"--sheen-delay\": delay + \"s\",\n } as React.CSSProperties}\n />\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Default 6-sided cube when no faces are provided */\n/* ------------------------------------------------------------------ */\n\nconst DEFAULT_FACE_NAMES: FaceName[] = [\n \"front\",\n \"back\",\n \"left\",\n \"right\",\n \"top\",\n \"bottom\",\n];\n\n/* ------------------------------------------------------------------ */\n/* Stagger order for oneAtATime (standard mode) */\n/* ------------------------------------------------------------------ */\n\nconst STAGGER_ORDER: string[] = [\n \"front\",\n \"right\",\n \"back\",\n \"left\",\n \"top\",\n \"bottom\",\n \"top_front\",\n \"top_rear\",\n \"bottom_front\",\n \"bottom_rear\",\n];\n\n/* ------------------------------------------------------------------ */\n/* Component */\n/* ------------------------------------------------------------------ */\n\nexport const Obj: React.FC<ObjProps> = React.memo(\n ({\n width = 160,\n height = 160,\n depth = 150,\n perspective = 600,\n perspectiveOrigin = \"50% 50%\",\n faces,\n global: globalDef,\n anim1,\n anim2,\n showCenterDiv = false,\n flat = false,\n transitionDuration = 1,\n oneAtATime = false,\n remainJoined = false,\n sheen = false,\n className,\n style,\n }) => {\n const w =\n typeof width === \"number\" ? width : parseFloat(String(width));\n const h =\n typeof height === \"number\" ? height : parseFloat(String(height));\n const d =\n typeof depth === \"number\" ? depth : parseFloat(String(depth));\n\n // Resolve animation shorthands\n const animation1 = toAnimationShorthand(anim1) ?? undefined;\n const animation2 = toAnimationShorthand(anim2) ?? undefined;\n\n // Determine which faces to render\n const faceList: FaceDef[] =\n faces && faces.length > 0\n ? faces\n : DEFAULT_FACE_NAMES.map((name) => ({ name }));\n\n const transitionCss = (delay = 0) =>\n `transform ${transitionDuration}s ease-in-out ${delay}s`;\n\n // Duration for sheen (synced to anim1 rotation cycle)\n const sheenDur = anim1?.duration ?? 6;\n\n /* ============================================================ */\n /* Standard rendering (no remainJoined) */\n /* ============================================================ */\n\n const renderStandard = () =>\n faceList.map((face, i) => {\n const dims = faceDimensions(face.name, w, h, d);\n const transform = flat\n ? faceTransformFlat(face.name, w, h, d)\n : faceTransform3D(face.name, w, h, d);\n\n const {\n style: fStyle,\n className: fCls,\n body,\n } = faceAppearance(face, globalDef);\n\n const idx = STAGGER_ORDER.indexOf(face.name);\n const delay = oneAtATime\n ? (idx >= 0 ? idx : i) * transitionDuration\n : 0;\n\n return (\n <div\n key={face.name + \"-\" + i}\n className={fCls}\n style={{\n ...fStyle,\n width: dims.width,\n height: dims.height,\n transform,\n transition: transitionCss(delay),\n }}\n >\n {body}\n {sheen && sheenOverlay(face.name, sheenDur, flat)}\n </div>\n );\n });\n\n /* ============================================================ */\n /* Joined rendering — nested hinge structure */\n /* */\n /* Chain: front → right → back (hinged at shared edges) */\n /* Left is independent (the break‑point). */\n /* */\n /* Flat order: front | right | back | left (left on far right) */\n /* ============================================================ */\n\n const renderJoined = () => {\n const findFace = (n: string) =>\n faceList.find((f) => f.name === n);\n\n const frontFace = findFace(\"front\");\n const rightFace = findFace(\"right\");\n const backFace = findFace(\"back\");\n const leftFace = findFace(\"left\");\n\n const sideNames = new Set([\n \"front\",\n \"right\",\n \"back\",\n \"left\",\n ]);\n const otherFaces = faceList.filter(\n (f) => !sideNames.has(f.name)\n );\n\n const step = oneAtATime ? transitionDuration : 0;\n\n /* Helper: render a single face element with merged styles */\n const renderFaceEl = (\n face: FaceDef | undefined,\n dims: { width: number; height: number },\n extra: React.CSSProperties,\n key: string\n ) => {\n if (!face) return null;\n const {\n style: fStyle,\n className: fCls,\n body,\n } = faceAppearance(face, globalDef);\n return (\n <div\n key={key}\n className={fCls}\n style={{\n ...fStyle,\n width: dims.width,\n height: dims.height,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n boxSizing: \"border-box\",\n ...extra,\n }}\n >\n {body}\n {sheen &&\n sheenOverlay(face.name, sheenDur, flat)}\n </div>\n );\n };\n\n return (\n <>\n {/* ---- Front face (anchor) ---- */}\n {renderFaceEl(\n frontFace,\n { width: w, height: h },\n {\n position: \"absolute\",\n left: \"50%\",\n top: \"50%\",\n transform: flat\n ? \"translate(-50%, -50%)\"\n : `translate(-50%, -50%) translateZ(${d / 2}px)`,\n transition: transitionCss(0),\n },\n \"front-j\"\n )}\n\n {/* ---- Right hinge (pivots at front's right edge) ---- */}\n <div\n style={{\n position: \"absolute\",\n left: `calc(50% + ${w / 2}px)`,\n top: \"50%\",\n width: 0,\n height: 0,\n transformOrigin: \"0 0\",\n transformStyle: \"preserve-3d\",\n transform: flat\n ? \"none\"\n : `translateZ(${d / 2}px) rotateY(90deg)`,\n transition: transitionCss(step),\n }}\n >\n {/* Right face */}\n {renderFaceEl(\n rightFace,\n { width: d, height: h },\n {\n position: \"absolute\",\n left: 0,\n top: 0,\n transform: \"translateY(-50%)\",\n },\n \"right-j\"\n )}\n\n {/* ---- Back hinge (pivots at right's far edge) ---- */}\n <div\n style={{\n position: \"absolute\",\n left: d,\n top: 0,\n width: 0,\n height: 0,\n transformOrigin: \"0 0\",\n transformStyle: \"preserve-3d\",\n transform: flat\n ? \"none\"\n : \"rotateY(90deg)\",\n transition: transitionCss(step * 2),\n }}\n >\n {/* Back face */}\n {renderFaceEl(\n backFace,\n { width: w, height: h },\n {\n position: \"absolute\",\n left: 0,\n top: 0,\n transform: \"translateY(-50%)\",\n },\n \"back-j\"\n )}\n\n {/* ---- Left hinge (pivots at back's far edge) ---- */}\n <div\n style={{\n position: \"absolute\",\n left: w,\n top: 0,\n width: 0,\n height: 0,\n transformOrigin: \"0 0\",\n transformStyle: \"preserve-3d\",\n transform: flat\n ? \"none\"\n : \"rotateY(90deg)\",\n transition: transitionCss(step * 3),\n }}\n >\n {/* Left face */}\n {renderFaceEl(\n leftFace,\n { width: d, height: h },\n {\n position: \"absolute\",\n left: 0,\n top: 0,\n transform: \"translateY(-50%)\",\n },\n \"left-j\"\n )}\n </div>\n </div>\n </div>\n\n {/* ---- Non-side faces (top, bottom, etc.) ---- */}\n {otherFaces.map((face, i) => {\n const dims = faceDimensions(face.name, w, h, d);\n const xform = flat\n ? faceTransformFlat(face.name, w, h, d)\n : faceTransform3D(face.name, w, h, d);\n const {\n style: fStyle,\n className: fCls,\n body,\n } = faceAppearance(face, globalDef);\n return (\n <div\n key={face.name + \"-o-\" + i}\n className={fCls}\n style={{\n ...fStyle,\n width: dims.width,\n height: dims.height,\n transform: xform,\n transition: transitionCss(0),\n }}\n >\n {body}\n </div>\n );\n })}\n </>\n );\n };\n\n /* ============================================================ */\n /* Render tree */\n /* ============================================================ */\n\n const cssVars = {\n \"--obj-w\": w + \"px\",\n \"--obj-h\": h + \"px\",\n \"--obj-d\": d + \"px\",\n } as React.CSSProperties;\n\n return (\n <div\n className={[\"anim3d-stage\", className]\n .filter(Boolean)\n .join(\" \")}\n style={{\n perspective,\n perspectiveOrigin,\n ...cssVars,\n ...style,\n }}\n data-anim-3d-obj\n role=\"img\"\n aria-label=\"3D object\"\n >\n {/* Outer animation wrapper (anim1) */}\n <div\n className=\"anim3d-wrapper\"\n style={{\n ...cssVars,\n animation: flat ? \"none\" : animation1,\n transformStyle: \"preserve-3d\",\n transition: transitionCss(),\n }}\n >\n {/* Inner animation wrapper (anim2) */}\n <div\n className=\"anim3d-wrapper\"\n style={{\n ...cssVars,\n animation: flat ? \"none\" : animation2,\n transformStyle: \"preserve-3d\",\n transition: transitionCss(),\n }}\n >\n {showCenterDiv && (\n <div className=\"anim3d-center\" />\n )}\n {remainJoined\n ? renderJoined()\n : renderStandard()}\n </div>\n </div>\n </div>\n );\n }\n);\n\nObj.displayName = \"Obj\";\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/keyframes.ts","../src/components/Obj.tsx"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { AnimationConfig } from \"./types\";\n\n/** Create (or reuse) a <style> tag for dynamic keyframes */\nfunction ensureStyleTag(): HTMLStyleElement {\n let tag = document.getElementById(\n \"anim3d-keyframes\"\n ) as HTMLStyleElement | null;\n if (!tag) {\n tag = document.createElement(\"style\");\n tag.id = \"anim3d-keyframes\";\n document.head.appendChild(tag);\n }\n return tag;\n}\n\nfunction inject(css: string) {\n if (typeof document === \"undefined\") return; // SSR\n const tag = ensureStyleTag();\n tag.appendChild(document.createTextNode(css));\n}\n\n/** Keyframes text for built-ins */\nfunction builtInKeyframes(name: string, cfg: AnimationConfig) {\n const hi = cfg.degreesHi ?? 15;\n const lo = cfg.degreesLow ?? -15;\n switch (name) {\n case \"Y360\":\n return `@keyframes Y360 { from { transform: rotateY(0deg) } to { transform: rotateY(360deg) } }`;\n case \"X360\":\n return `@keyframes X360 { from { transform: rotateX(0deg) } to { transform: rotateX(360deg) } }`;\n case \"Z360\":\n return `@keyframes Z360 { from { transform: rotateZ(0deg) } to { transform: rotateZ(360deg) } }`;\n case \"rockY\":\n return `@keyframes rockY { 0%{ transform: rotateY(${lo}deg) } 50%{ transform: rotateY(${hi}deg) } 100%{ transform: rotateY(${lo}deg) } }`;\n case \"rockX\":\n return `@keyframes rockX { 0%{ transform: rotateX(${lo}deg) } 50%{ transform: rotateX(${hi}deg) } 100%{ transform: rotateX(${lo}deg) } }`;\n default:\n // Custom names: let authors supply their own @keyframes in global CSS with that name.\n return \"\";\n }\n}\n\n/** Returns a concrete animation-name and ensures keyframes exist (for built-ins) */\nexport function resolveAnimation(cfg?: AnimationConfig): string | null {\n if (!cfg) return null;\n const name = cfg.name;\n const builtIn = builtInKeyframes(name, cfg);\n if (builtIn) {\n // Ensure single injection per built-in name\n const marker = `/*kf-${name}*/`;\n if (typeof document !== \"undefined\") {\n const tag = ensureStyleTag();\n if (!tag.innerHTML.includes(marker)) {\n inject(`${builtIn}\\n${marker}`);\n }\n }\n return name; // use built-in name as animation-name\n }\n // custom: use author-provided @keyframes by name\n return name;\n}\n\n/** Build the full CSS animation shorthand from a config and resolved name */\nexport function toAnimationShorthand(cfg?: AnimationConfig): string | null {\n const name = resolveAnimation(cfg);\n if (!cfg || !name) return null;\n const dur = (cfg.duration ?? 10) + \"s\";\n const delay = (cfg.delay ?? 0) + \"s\";\n const iter = cfg.iterationCount ?? \"infinite\";\n const dir = cfg.direction ?? \"normal\";\n const timing = cfg.timing ?? \"linear\";\n const fill = cfg.fillMode ?? \"forwards\";\n const play = cfg.animationPlayState ?? \"running\";\n // name duration timing delay iteration-count direction fill-mode play-state\n return `${name} ${dur} ${timing} ${delay} ${iter} ${dir} ${fill} ${play}`;\n}\n","import * as React from \"react\";\nimport type {\n ObjProps,\n FaceDef,\n FaceName,\n GlobalDef,\n} from \"../types\";\nimport { toAnimationShorthand } from \"../keyframes\";\nimport \"../styles/obj.css\";\n\n// Re-export the canonical ObjProps from types.ts\nexport type { ObjProps } from \"../types\";\n\n/* ------------------------------------------------------------------ */\n/* Face transform — 3D cuboid positions */\n/* ------------------------------------------------------------------ */\n\nfunction faceTransform3D(\n name: string,\n w: number,\n h: number,\n d: number\n): string {\n const hw = w / 2;\n const hh = h / 2;\n const hd = d / 2;\n\n switch (name as FaceName) {\n case \"front\":\n return `translate(-50%, -50%) translateZ(${hd}px)`;\n case \"back\":\n return `translate(-50%, -50%) rotateY(180deg) translateZ(${hd}px)`;\n case \"left\":\n return `translate(-50%, -50%) rotateY(-90deg) translateZ(${hw}px)`;\n case \"right\":\n return `translate(-50%, -50%) rotateY(90deg) translateZ(${hw}px)`;\n case \"top\":\n return `translate(-50%, -50%) rotateX(90deg) translateZ(${hh}px)`;\n case \"bottom\":\n return `translate(-50%, -50%) rotateX(-90deg) translateZ(${hh}px)`;\n case \"top_front\":\n return `translate(-50%, -50%) rotateX(45deg) translateZ(${hh}px)`;\n case \"top_rear\":\n return `translate(-50%, -50%) rotateX(135deg) translateZ(${hh}px)`;\n case \"bottom_front\":\n return `translate(-50%, -50%) rotateX(-45deg) translateZ(${hh}px)`;\n case \"bottom_rear\":\n return `translate(-50%, -50%) rotateX(-135deg) translateZ(${hh}px)`;\n default:\n return `translate(-50%, -50%) translateZ(${hd}px)`;\n }\n}\n\n/* ------------------------------------------------------------------ */\n/* Face transform — flat (unfolded) positions */\n/* */\n/* Flat order: front | right | back | left */\n/* Centred on the midpoint of the full row. */\n/* ------------------------------------------------------------------ */\n\nfunction faceTransformFlat(\n name: string,\n w: number,\n h: number,\n d: number\n): string {\n const total = 2 * w + 2 * d;\n const half = total / 2;\n\n let cx: number;\n\n switch (name as FaceName) {\n case \"front\":\n cx = w / 2;\n break;\n case \"right\":\n cx = w + d / 2;\n break;\n case \"back\":\n cx = w + d + w / 2;\n break;\n case \"left\":\n cx = w + d + w + d / 2;\n break;\n case \"top\":\n case \"top_front\":\n case \"top_rear\":\n cx = w / 2;\n return `translate(-50%, -50%) translateX(${cx - half}px) translateY(-${h}px)`;\n case \"bottom\":\n case \"bottom_front\":\n case \"bottom_rear\":\n cx = w / 2;\n return `translate(-50%, -50%) translateX(${cx - half}px) translateY(${h}px)`;\n default:\n cx = w / 2;\n break;\n }\n\n return `translate(-50%, -50%) translateX(${cx - half}px)`;\n}\n\n/* ------------------------------------------------------------------ */\n/* Parse a legacy CSS text string into a CSSProperties object */\n/* ------------------------------------------------------------------ */\n\nfunction parseCssText(css?: string): React.CSSProperties {\n if (!css) return {};\n const style: Record<string, string> = {};\n css.split(\";\").forEach((rule) => {\n const [prop, ...rest] = rule.split(\":\");\n if (!prop || rest.length === 0) return;\n const key = prop\n .trim()\n .replace(/-([a-z])/g, (_, c) => c.toUpperCase());\n style[key] = rest.join(\":\").trim();\n });\n return style as React.CSSProperties;\n}\n\n/* ------------------------------------------------------------------ */\n/* Resolve face dimensions for non-standard faces */\n/* ------------------------------------------------------------------ */\n\nfunction faceDimensions(\n name: string,\n w: number,\n h: number,\n d: number\n): { width: number; height: number } {\n switch (name as FaceName) {\n case \"left\":\n case \"right\":\n return { width: d, height: h };\n case \"top\":\n case \"bottom\":\n case \"top_front\":\n case \"top_rear\":\n case \"bottom_front\":\n case \"bottom_rear\":\n return { width: w, height: d };\n default:\n return { width: w, height: h };\n }\n}\n\n/* ------------------------------------------------------------------ */\n/* Build appearance style for a face (colours, borders, etc.) */\n/* Does NOT include position / transform / size. */\n/* ------------------------------------------------------------------ */\n\nfunction faceAppearance(\n face: FaceDef,\n globalDef?: GlobalDef\n): {\n style: React.CSSProperties;\n className: string;\n body: React.ReactNode;\n} {\n const globalStyle = parseCssText(globalDef?.css);\n const faceInlineStyle = parseCssText(face.css);\n\n const style: React.CSSProperties = {\n ...globalStyle,\n ...(globalDef?.style ?? {}),\n ...faceInlineStyle,\n ...(face.style ?? {}),\n };\n\n const className = [\"anim3d-face\", face.className]\n .filter(Boolean)\n .join(\" \");\n\n const body = face.body ?? globalDef?.body ?? null;\n\n return { style, className, body };\n}\n\n/* ------------------------------------------------------------------ */\n/* Default 6-sided cube when no faces are provided */\n/* ------------------------------------------------------------------ */\n\nconst DEFAULT_FACE_NAMES: FaceName[] = [\n \"front\",\n \"back\",\n \"left\",\n \"right\",\n \"top\",\n \"bottom\",\n];\n\n/* ------------------------------------------------------------------ */\n/* Stagger order for oneAtATime (standard mode) */\n/* ------------------------------------------------------------------ */\n\nconst STAGGER_ORDER: string[] = [\n \"front\",\n \"right\",\n \"back\",\n \"left\",\n \"top\",\n \"bottom\",\n \"top_front\",\n \"top_rear\",\n \"bottom_front\",\n \"bottom_rear\",\n];\n\n/* ------------------------------------------------------------------ */\n/* Component */\n/* ------------------------------------------------------------------ */\n\nexport const Obj: React.FC<ObjProps> = React.memo(\n ({\n width = 160,\n height = 160,\n depth = 150,\n perspective = 600,\n perspectiveOrigin = \"50% 50%\",\n faces,\n global: globalDef,\n anim1,\n anim2,\n showCenterDiv = false,\n flat = false,\n transitionDuration = 1,\n oneAtATime = false,\n remainJoined = false,\n ytilt = false,\n className,\n style,\n }) => {\n const w =\n typeof width === \"number\" ? width : parseFloat(String(width));\n const h =\n typeof height === \"number\" ? height : parseFloat(String(height));\n const d =\n typeof depth === \"number\" ? depth : parseFloat(String(depth));\n\n // Resolve animation shorthands\n const animation1 = toAnimationShorthand(anim1) ?? undefined;\n const animation2 = toAnimationShorthand(anim2) ?? undefined;\n\n // Determine which faces to render\n const faceList: FaceDef[] =\n faces && faces.length > 0\n ? faces\n : DEFAULT_FACE_NAMES.map((name) => ({ name }));\n\n const transitionCss = (delay = 0) =>\n `transform ${transitionDuration}s ease-in-out ${delay}s`;\n\n /* ============================================================ */\n /* Y-tilt — fire a one-shot rotateX(0→45→0) each time */\n /* flat changes. We alternate between two identical keyframe */\n /* names (a/b) so the browser re-triggers the animation. */\n /* ============================================================ */\n\n const tiltCount = React.useRef(0);\n const prevFlat = React.useRef(flat);\n const [tiltAnim, setTiltAnim] = React.useState<\n string | undefined\n >(undefined);\n\n React.useEffect(() => {\n if (flat !== prevFlat.current) {\n prevFlat.current = flat;\n if (ytilt) {\n tiltCount.current += 1;\n const sideCount = faceList.filter((f) =>\n [\"front\", \"right\", \"back\", \"left\"].includes(\n f.name\n )\n ).length;\n const totalDur = oneAtATime\n ? transitionDuration * sideCount\n : transitionDuration;\n const name =\n tiltCount.current % 2 === 0\n ? \"anim3d-ytilt-a\"\n : \"anim3d-ytilt-b\";\n setTiltAnim(\n `${name} ${totalDur}s ease-in-out 1 forwards`\n );\n // Clear animation after it completes so it can re-trigger\n const timer = setTimeout(\n () => setTiltAnim(undefined),\n totalDur * 1000 + 50\n );\n return () => clearTimeout(timer);\n }\n }\n }, [flat, ytilt, transitionDuration, oneAtATime, faceList]);\n\n /* ============================================================ */\n /* Standard rendering (no remainJoined) */\n /* ============================================================ */\n\n const renderStandard = () =>\n faceList.map((face, i) => {\n const dims = faceDimensions(face.name, w, h, d);\n const transform = flat\n ? faceTransformFlat(face.name, w, h, d)\n : faceTransform3D(face.name, w, h, d);\n\n const {\n style: fStyle,\n className: fCls,\n body,\n } = faceAppearance(face, globalDef);\n\n const idx = STAGGER_ORDER.indexOf(face.name);\n const delay = oneAtATime\n ? (idx >= 0 ? idx : i) * transitionDuration\n : 0;\n\n return (\n <div\n key={face.name + \"-\" + i}\n className={fCls}\n style={{\n ...fStyle,\n width: dims.width,\n height: dims.height,\n transform,\n transition: transitionCss(delay),\n }}\n >\n {body}\n </div>\n );\n });\n\n /* ============================================================ */\n /* Joined rendering — nested hinge structure */\n /* */\n /* Chain: front → right → back → left (hinged at shared edges) */\n /* The left–front edge is the break‑point. */\n /* */\n /* Flat order: front | right | back | left (left on far right) */\n /* ============================================================ */\n\n const renderJoined = () => {\n const findFace = (n: string) =>\n faceList.find((f) => f.name === n);\n\n const frontFace = findFace(\"front\");\n const rightFace = findFace(\"right\");\n const backFace = findFace(\"back\");\n const leftFace = findFace(\"left\");\n\n const sideNames = new Set([\n \"front\",\n \"right\",\n \"back\",\n \"left\",\n ]);\n const otherFaces = faceList.filter(\n (f) => !sideNames.has(f.name)\n );\n\n const step = oneAtATime ? transitionDuration : 0;\n\n /* Helper: render a single face element with merged styles */\n const renderFaceEl = (\n face: FaceDef | undefined,\n dims: { width: number; height: number },\n extra: React.CSSProperties,\n key: string\n ) => {\n if (!face) return null;\n const {\n style: fStyle,\n className: fCls,\n body,\n } = faceAppearance(face, globalDef);\n return (\n <div\n key={key}\n className={fCls}\n style={{\n ...fStyle,\n width: dims.width,\n height: dims.height,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n boxSizing: \"border-box\",\n ...extra,\n }}\n >\n {body}\n </div>\n );\n };\n\n return (\n <>\n {/* ---- Front face (anchor) ---- */}\n {renderFaceEl(\n frontFace,\n { width: w, height: h },\n {\n position: \"absolute\",\n left: \"50%\",\n top: \"50%\",\n transform: flat\n ? \"translate(-50%, -50%)\"\n : `translate(-50%, -50%) translateZ(${d / 2}px)`,\n transition: transitionCss(0),\n },\n \"front-j\"\n )}\n\n {/* ---- Right hinge (pivots at front's right edge) ---- */}\n <div\n style={{\n position: \"absolute\",\n left: `calc(50% + ${w / 2}px)`,\n top: \"50%\",\n width: 0,\n height: 0,\n transformOrigin: \"0 0\",\n transformStyle: \"preserve-3d\",\n transform: flat\n ? \"none\"\n : `translateZ(${d / 2}px) rotateY(90deg)`,\n transition: transitionCss(step),\n }}\n >\n {/* Right face */}\n {renderFaceEl(\n rightFace,\n { width: d, height: h },\n {\n position: \"absolute\",\n left: 0,\n top: 0,\n transform: \"translateY(-50%)\",\n },\n \"right-j\"\n )}\n\n {/* ---- Back hinge (pivots at right's far edge) ---- */}\n <div\n style={{\n position: \"absolute\",\n left: d,\n top: 0,\n width: 0,\n height: 0,\n transformOrigin: \"0 0\",\n transformStyle: \"preserve-3d\",\n transform: flat\n ? \"none\"\n : \"rotateY(90deg)\",\n transition: transitionCss(step * 2),\n }}\n >\n {/* Back face */}\n {renderFaceEl(\n backFace,\n { width: w, height: h },\n {\n position: \"absolute\",\n left: 0,\n top: 0,\n transform: \"translateY(-50%)\",\n },\n \"back-j\"\n )}\n\n {/* ---- Left hinge (pivots at back's far edge) ---- */}\n <div\n style={{\n position: \"absolute\",\n left: w,\n top: 0,\n width: 0,\n height: 0,\n transformOrigin: \"0 0\",\n transformStyle: \"preserve-3d\",\n transform: flat\n ? \"none\"\n : \"rotateY(90deg)\",\n transition: transitionCss(step * 3),\n }}\n >\n {/* Left face */}\n {renderFaceEl(\n leftFace,\n { width: d, height: h },\n {\n position: \"absolute\",\n left: 0,\n top: 0,\n transform: \"translateY(-50%)\",\n },\n \"left-j\"\n )}\n </div>\n </div>\n </div>\n\n {/* ---- Non-side faces (top, bottom, etc.) ---- */}\n {otherFaces.map((face, i) => {\n const dims = faceDimensions(face.name, w, h, d);\n const xform = flat\n ? faceTransformFlat(face.name, w, h, d)\n : faceTransform3D(face.name, w, h, d);\n const {\n style: fStyle,\n className: fCls,\n body,\n } = faceAppearance(face, globalDef);\n return (\n <div\n key={face.name + \"-o-\" + i}\n className={fCls}\n style={{\n ...fStyle,\n width: dims.width,\n height: dims.height,\n transform: xform,\n transition: transitionCss(0),\n }}\n >\n {body}\n </div>\n );\n })}\n </>\n );\n };\n\n /* ============================================================ */\n /* Render tree */\n /* ============================================================ */\n\n const cssVars = {\n \"--obj-w\": w + \"px\",\n \"--obj-h\": h + \"px\",\n \"--obj-d\": d + \"px\",\n } as React.CSSProperties;\n\n return (\n <div\n className={[\"anim3d-stage\", className]\n .filter(Boolean)\n .join(\" \")}\n style={{\n perspective,\n perspectiveOrigin,\n ...cssVars,\n ...style,\n }}\n data-anim-3d-obj\n role=\"img\"\n aria-label=\"3D object\"\n >\n {/* Y-tilt wrapper — sits between stage and anim wrappers */}\n <div\n style={{\n transformStyle: \"preserve-3d\",\n animation: tiltAnim,\n }}\n >\n {/* Outer animation wrapper (anim1) */}\n <div\n className=\"anim3d-wrapper\"\n style={{\n ...cssVars,\n animation: flat ? \"none\" : animation1,\n transformStyle: \"preserve-3d\",\n transition: transitionCss(),\n }}\n >\n {/* Inner animation wrapper (anim2) */}\n <div\n className=\"anim3d-wrapper\"\n style={{\n ...cssVars,\n animation: flat ? \"none\" : animation2,\n transformStyle: \"preserve-3d\",\n transition: transitionCss(),\n }}\n >\n {showCenterDiv && (\n <div className=\"anim3d-center\" />\n )}\n {remainJoined\n ? renderJoined()\n : renderStandard()}\n </div>\n </div>\n </div>\n </div>\n );\n }\n);\n\nObj.displayName = \"Obj\";\n"]}
|