anim-3d-obj 2.0.5 → 2.0.7

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 CHANGED
@@ -120,39 +120,38 @@ function faceTransform3D(name, w, h, d) {
120
120
  return `translate(-50%, -50%) translateZ(${hd}px)`;
121
121
  }
122
122
  }
123
- function faceTransformFlat(name, w, _h, d) {
124
- const total = 2 * d + 2 * w;
125
- const halfTotal = total / 2;
123
+ function faceTransformFlat(name, w, h, d) {
124
+ const total = 2 * w + 2 * d;
125
+ const half = total / 2;
126
126
  let cx;
127
127
  switch (name) {
128
- case "left":
129
- cx = d / 2;
130
- break;
131
128
  case "front":
132
- cx = d + w / 2;
129
+ cx = w / 2;
133
130
  break;
134
131
  case "right":
135
- cx = d + w + d / 2;
132
+ cx = w + d / 2;
136
133
  break;
137
134
  case "back":
138
- cx = d + w + d + w / 2;
135
+ cx = w + d + w / 2;
136
+ break;
137
+ case "left":
138
+ cx = w + d + w + d / 2;
139
139
  break;
140
140
  case "top":
141
141
  case "top_front":
142
142
  case "top_rear":
143
- cx = d + w / 2;
144
- return `translate(-50%, -50%) translateX(${cx - halfTotal}px) translateY(-${_h}px)`;
143
+ cx = w / 2;
144
+ return `translate(-50%, -50%) translateX(${cx - half}px) translateY(-${h}px)`;
145
145
  case "bottom":
146
146
  case "bottom_front":
147
147
  case "bottom_rear":
148
- cx = d + w / 2;
149
- return `translate(-50%, -50%) translateX(${cx - halfTotal}px) translateY(${_h}px)`;
148
+ cx = w / 2;
149
+ return `translate(-50%, -50%) translateX(${cx - half}px) translateY(${h}px)`;
150
150
  default:
151
- cx = d + w / 2;
151
+ cx = w / 2;
152
152
  break;
153
153
  }
154
- const offsetX = cx - halfTotal;
155
- return `translate(-50%, -50%) translateX(${offsetX}px)`;
154
+ return `translate(-50%, -50%) translateX(${cx - half}px)`;
156
155
  }
157
156
  function parseCssText(css) {
158
157
  if (!css) return {};
@@ -181,6 +180,41 @@ function faceDimensions(name, w, h, d) {
181
180
  return { width: w, height: h };
182
181
  }
183
182
  }
183
+ function faceAppearance(face, globalDef) {
184
+ const globalStyle = parseCssText(globalDef?.css);
185
+ const faceInlineStyle = parseCssText(face.css);
186
+ const style = {
187
+ ...globalStyle,
188
+ ...globalDef?.style ?? {},
189
+ ...faceInlineStyle,
190
+ ...face.style ?? {}
191
+ };
192
+ const className = ["anim3d-face", face.className].filter(Boolean).join(" ");
193
+ const body = face.body ?? globalDef?.body ?? null;
194
+ return { style, className, body };
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
+ }
184
218
  var DEFAULT_FACE_NAMES = [
185
219
  "front",
186
220
  "back",
@@ -189,6 +223,18 @@ var DEFAULT_FACE_NAMES = [
189
223
  "top",
190
224
  "bottom"
191
225
  ];
226
+ var STAGGER_ORDER = [
227
+ "front",
228
+ "right",
229
+ "back",
230
+ "left",
231
+ "top",
232
+ "bottom",
233
+ "top_front",
234
+ "top_rear",
235
+ "bottom_front",
236
+ "bottom_rear"
237
+ ];
192
238
  var Obj = React__namespace.memo(
193
239
  ({
194
240
  width = 160,
@@ -203,45 +249,217 @@ var Obj = React__namespace.memo(
203
249
  showCenterDiv = false,
204
250
  flat = false,
205
251
  transitionDuration = 1,
252
+ oneAtATime = false,
253
+ remainJoined = false,
254
+ sheen = false,
206
255
  className,
207
256
  style
208
257
  }) => {
209
- const w = typeof width === "number" ? width : parseFloat(width);
210
- const h = typeof height === "number" ? height : parseFloat(height);
211
- const d = typeof depth === "number" ? depth : parseFloat(depth);
258
+ const w = typeof width === "number" ? width : parseFloat(String(width));
259
+ const h = typeof height === "number" ? height : parseFloat(String(height));
260
+ const d = typeof depth === "number" ? depth : parseFloat(String(depth));
212
261
  const animation1 = toAnimationShorthand(anim1) ?? void 0;
213
262
  const animation2 = toAnimationShorthand(anim2) ?? void 0;
214
263
  const faceList = faces && faces.length > 0 ? faces : DEFAULT_FACE_NAMES.map((name) => ({ name }));
215
- const transitionCss = `transform ${transitionDuration}s ease-in-out`;
216
- const renderFace = (face, i) => {
264
+ const transitionCss = (delay = 0) => `transform ${transitionDuration}s ease-in-out ${delay}s`;
265
+ const sheenDur = anim1?.duration ?? 6;
266
+ const renderStandard = () => faceList.map((face, i) => {
217
267
  const dims = faceDimensions(face.name, w, h, d);
218
268
  const transform = flat ? faceTransformFlat(face.name, w, h, d) : faceTransform3D(face.name, w, h, d);
219
- const globalStyle = parseCssText(globalDef?.css);
220
- const faceInlineStyle = parseCssText(face.css);
221
- const mergedStyle = {
222
- ...globalStyle,
223
- ...globalDef?.style ?? {},
224
- ...faceInlineStyle,
225
- ...face.style ?? {},
226
- width: dims.width,
227
- height: dims.height,
228
- transform,
229
- transition: transitionCss
230
- };
231
- const body = face.body ?? globalDef?.body ?? null;
232
- const faceClassName = [
233
- "anim3d-face",
234
- face.className
235
- ].filter(Boolean).join(" ");
236
- return /* @__PURE__ */ jsxRuntime.jsx(
269
+ const {
270
+ style: fStyle,
271
+ className: fCls,
272
+ body
273
+ } = faceAppearance(face, globalDef);
274
+ const idx = STAGGER_ORDER.indexOf(face.name);
275
+ const delay = oneAtATime ? (idx >= 0 ? idx : i) * transitionDuration : 0;
276
+ return /* @__PURE__ */ jsxRuntime.jsxs(
237
277
  "div",
238
278
  {
239
- className: faceClassName,
240
- style: mergedStyle,
241
- children: body
279
+ className: fCls,
280
+ style: {
281
+ ...fStyle,
282
+ width: dims.width,
283
+ height: dims.height,
284
+ transform,
285
+ transition: transitionCss(delay)
286
+ },
287
+ children: [
288
+ body,
289
+ sheen && sheenOverlay(face.name, sheenDur, flat)
290
+ ]
242
291
  },
243
292
  face.name + "-" + i
244
293
  );
294
+ });
295
+ const renderJoined = () => {
296
+ const findFace = (n) => faceList.find((f) => f.name === n);
297
+ const frontFace = findFace("front");
298
+ const rightFace = findFace("right");
299
+ const backFace = findFace("back");
300
+ const leftFace = findFace("left");
301
+ const sideNames = /* @__PURE__ */ new Set([
302
+ "front",
303
+ "right",
304
+ "back",
305
+ "left"
306
+ ]);
307
+ const otherFaces = faceList.filter(
308
+ (f) => !sideNames.has(f.name)
309
+ );
310
+ const step = oneAtATime ? transitionDuration : 0;
311
+ const renderFaceEl = (face, dims, extra, key) => {
312
+ if (!face) return null;
313
+ const {
314
+ style: fStyle,
315
+ className: fCls,
316
+ body
317
+ } = faceAppearance(face, globalDef);
318
+ return /* @__PURE__ */ jsxRuntime.jsxs(
319
+ "div",
320
+ {
321
+ className: fCls,
322
+ style: {
323
+ ...fStyle,
324
+ width: dims.width,
325
+ height: dims.height,
326
+ display: "flex",
327
+ alignItems: "center",
328
+ justifyContent: "center",
329
+ boxSizing: "border-box",
330
+ ...extra
331
+ },
332
+ children: [
333
+ body,
334
+ sheen && sheenOverlay(face.name, sheenDur, flat)
335
+ ]
336
+ },
337
+ key
338
+ );
339
+ };
340
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
341
+ renderFaceEl(
342
+ frontFace,
343
+ { width: w, height: h },
344
+ {
345
+ position: "absolute",
346
+ left: "50%",
347
+ top: "50%",
348
+ transform: flat ? "translate(-50%, -50%)" : `translate(-50%, -50%) translateZ(${d / 2}px)`,
349
+ transition: transitionCss(0)
350
+ },
351
+ "front-j"
352
+ ),
353
+ /* @__PURE__ */ jsxRuntime.jsxs(
354
+ "div",
355
+ {
356
+ style: {
357
+ position: "absolute",
358
+ left: `calc(50% + ${w / 2}px)`,
359
+ top: "50%",
360
+ width: 0,
361
+ height: 0,
362
+ transformOrigin: "0 0",
363
+ transformStyle: "preserve-3d",
364
+ transform: flat ? "none" : `translateZ(${d / 2}px) rotateY(90deg)`,
365
+ transition: transitionCss(step)
366
+ },
367
+ children: [
368
+ renderFaceEl(
369
+ rightFace,
370
+ { width: d, height: h },
371
+ {
372
+ position: "absolute",
373
+ left: 0,
374
+ top: 0,
375
+ transform: "translateY(-50%)"
376
+ },
377
+ "right-j"
378
+ ),
379
+ /* @__PURE__ */ jsxRuntime.jsxs(
380
+ "div",
381
+ {
382
+ style: {
383
+ position: "absolute",
384
+ left: d,
385
+ top: 0,
386
+ width: 0,
387
+ height: 0,
388
+ transformOrigin: "0 0",
389
+ transformStyle: "preserve-3d",
390
+ transform: flat ? "none" : "rotateY(90deg)",
391
+ transition: transitionCss(step * 2)
392
+ },
393
+ children: [
394
+ renderFaceEl(
395
+ backFace,
396
+ { width: w, height: h },
397
+ {
398
+ position: "absolute",
399
+ left: 0,
400
+ top: 0,
401
+ transform: "translateY(-50%)"
402
+ },
403
+ "back-j"
404
+ ),
405
+ /* @__PURE__ */ jsxRuntime.jsx(
406
+ "div",
407
+ {
408
+ style: {
409
+ position: "absolute",
410
+ left: w,
411
+ top: 0,
412
+ width: 0,
413
+ height: 0,
414
+ transformOrigin: "0 0",
415
+ transformStyle: "preserve-3d",
416
+ transform: flat ? "none" : "rotateY(90deg)",
417
+ transition: transitionCss(step * 3)
418
+ },
419
+ children: renderFaceEl(
420
+ leftFace,
421
+ { width: d, height: h },
422
+ {
423
+ position: "absolute",
424
+ left: 0,
425
+ top: 0,
426
+ transform: "translateY(-50%)"
427
+ },
428
+ "left-j"
429
+ )
430
+ }
431
+ )
432
+ ]
433
+ }
434
+ )
435
+ ]
436
+ }
437
+ ),
438
+ otherFaces.map((face, i) => {
439
+ const dims = faceDimensions(face.name, w, h, d);
440
+ const xform = flat ? faceTransformFlat(face.name, w, h, d) : faceTransform3D(face.name, w, h, d);
441
+ const {
442
+ style: fStyle,
443
+ className: fCls,
444
+ body
445
+ } = faceAppearance(face, globalDef);
446
+ return /* @__PURE__ */ jsxRuntime.jsx(
447
+ "div",
448
+ {
449
+ className: fCls,
450
+ style: {
451
+ ...fStyle,
452
+ width: dims.width,
453
+ height: dims.height,
454
+ transform: xform,
455
+ transition: transitionCss(0)
456
+ },
457
+ children: body
458
+ },
459
+ face.name + "-o-" + i
460
+ );
461
+ })
462
+ ] });
245
463
  };
246
464
  const cssVars = {
247
465
  "--obj-w": w + "px",
@@ -253,7 +471,7 @@ var Obj = React__namespace.memo(
253
471
  {
254
472
  className: ["anim3d-stage", className].filter(Boolean).join(" "),
255
473
  style: {
256
- perspective: flat ? "none" : perspective,
474
+ perspective,
257
475
  perspectiveOrigin,
258
476
  ...cssVars,
259
477
  ...style
@@ -269,7 +487,7 @@ var Obj = React__namespace.memo(
269
487
  ...cssVars,
270
488
  animation: flat ? "none" : animation1,
271
489
  transformStyle: "preserve-3d",
272
- transition: transitionCss
490
+ transition: transitionCss()
273
491
  },
274
492
  children: /* @__PURE__ */ jsxRuntime.jsxs(
275
493
  "div",
@@ -279,11 +497,11 @@ var Obj = React__namespace.memo(
279
497
  ...cssVars,
280
498
  animation: flat ? "none" : animation2,
281
499
  transformStyle: "preserve-3d",
282
- transition: transitionCss
500
+ transition: transitionCss()
283
501
  },
284
502
  children: [
285
503
  showCenterDiv && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "anim3d-center" }),
286
- faceList.map(renderFace)
504
+ remainJoined ? renderJoined() : renderStandard()
287
505
  ]
288
506
  }
289
507
  )
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/keyframes.ts","../src/components/Obj.tsx"],"names":["React","jsx","jsxs"],"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/* Layout order: … | left | front | right | back | … */\n/* Centered on the midpoint of the full row. */\n/* ------------------------------------------------------------------ */\n\n/** Ordered face names for the flat row (left-to-right) */\nconst FLAT_ORDER: FaceName[] = [\"left\", \"front\", \"right\", \"back\"];\n\n/**\n * Returns the flat-layout transform for a face.\n *\n * Side faces (left, right) have a rendered width of `d` (depth).\n * Front/back faces have a rendered width of `w`.\n * Row order: left(d) | front(w) | right(d) | back(w)\n * Total row width = 2d + 2w. We centre the row on 0.\n */\nfunction faceTransformFlat(\n name: string,\n w: number,\n _h: number,\n d: number\n): string {\n // Total row width\n const total = 2 * d + 2 * w;\n const halfTotal = total / 2;\n\n // Cumulative left-edge x positions (relative to row start = 0)\n // left : 0 width d\n // front : d width w\n // right : d + w width d\n // back : d + w + d width w\n let cx: number; // centre-x of this face in the row\n\n switch (name as FaceName) {\n case \"left\":\n cx = d / 2;\n break;\n case \"front\":\n cx = d + w / 2;\n break;\n case \"right\":\n cx = d + w + d / 2;\n break;\n case \"back\":\n cx = d + w + d + w / 2;\n break;\n case \"top\":\n case \"top_front\":\n case \"top_rear\":\n // Top faces slide upward out of the way\n cx = d + w / 2;\n return `translate(-50%, -50%) translateX(${cx - halfTotal}px) translateY(-${_h}px)`;\n case \"bottom\":\n case \"bottom_front\":\n case \"bottom_rear\":\n cx = d + w / 2;\n return `translate(-50%, -50%) translateX(${cx - halfTotal}px) translateY(${_h}px)`;\n default:\n cx = d + w / 2;\n break;\n }\n\n // Shift so the row is centred on x=0\n const offsetX = cx - halfTotal;\n return `translate(-50%, -50%) translateX(${offsetX}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/* 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/* 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 className,\n style,\n }) => {\n const w = typeof width === \"number\" ? width : parseFloat(width);\n const h = typeof height === \"number\" ? height : parseFloat(height);\n const d = typeof depth === \"number\" ? depth : parseFloat(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 = `transform ${transitionDuration}s ease-in-out`;\n\n // Merge global defaults into each face\n const renderFace = (face: FaceDef, i: number) => {\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 globalStyle = parseCssText(globalDef?.css);\n const faceInlineStyle = parseCssText(face.css);\n\n const mergedStyle: React.CSSProperties = {\n ...globalStyle,\n ...(globalDef?.style ?? {}),\n ...faceInlineStyle,\n ...(face.style ?? {}),\n width: dims.width,\n height: dims.height,\n transform,\n transition: transitionCss,\n };\n\n const body = face.body ?? globalDef?.body ?? null;\n const faceClassName = [\n \"anim3d-face\",\n face.className,\n ]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <div\n key={face.name + \"-\" + i}\n className={faceClassName}\n style={mergedStyle}\n >\n {body}\n </div>\n );\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].filter(Boolean).join(\" \")}\n style={{\n perspective: flat ? \"none\" : 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 && <div className=\"anim3d-center\" />}\n {faceList.map(renderFace)}\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":["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"]}
package/dist/index.css CHANGED
@@ -32,4 +32,47 @@
32
32
  backface-visibility: visible;
33
33
  box-sizing: border-box;
34
34
  }
35
+ .anim3d-sheen {
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 {
62
+ 0% {
63
+ transform: translateX(-100%);
64
+ opacity: 0;
65
+ }
66
+ 2% {
67
+ opacity: 1;
68
+ }
69
+ 14% {
70
+ transform: translateX(350%);
71
+ opacity: 0;
72
+ }
73
+ 14.1%, 100% {
74
+ opacity: 0;
75
+ transform: translateX(-100%);
76
+ }
77
+ }
35
78
  /*# sourceMappingURL=index.css.map */
@@ -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"],"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;","names":[]}
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/* ---- Sheen overlay ---- */\n\n.anim3d-sheen {\n position: absolute;\n inset: 0;\n overflow: hidden;\n pointer-events: none;\n z-index: 1;\n}\n\n.anim3d-sheen-bar {\n position: absolute;\n top: 0;\n left: 0;\n width: 40%;\n height: 100%;\n background: linear-gradient(\n 105deg,\n transparent 20%,\n rgba(255, 255, 255, 0.35) 45%,\n rgba(255, 255, 255, 0.5) 50%,\n rgba(255, 255, 255, 0.35) 55%,\n transparent 80%\n );\n opacity: 0;\n transform: translateX(-100%);\n animation: anim3d-sheen-sweep var(--sheen-dur, 6s) linear infinite;\n animation-delay: var(--sheen-delay, 0s);\n}\n\n@keyframes anim3d-sheen-sweep {\n 0% {\n transform: translateX(-100%);\n opacity: 0;\n }\n 2% {\n opacity: 1;\n }\n 14% {\n transform: translateX(350%);\n opacity: 0;\n }\n 14.1%,\n 100% {\n opacity: 0;\n transform: translateX(-100%);\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,CAAC;AACE,YAAU;AACV,SAAO;AACP,YAAU;AACV,kBAAgB;AAChB,WAAS;AACZ;AAEA,CAAC;AACE,YAAU;AACV,OAAK;AACL,QAAM;AACN,SAAO;AACP,UAAQ;AACR;AAAA,IAAY;AAAA,MACT,MAAM;AAAA,MACN,YAAY,GAAG;AAAA,MACf,KAAK,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,GAAG;AAAA,MAC7B,KAAK,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,GAAG;AAAA,MAC5B,KAAK,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,GAAG;AAAA,MAC7B,YAAY;AAEf,WAAS;AACT,aAAW,WAAW;AACtB,aAAW,mBAAmB,IAAI,WAAW,EAAE,IAAI,OAAO;AAC1D,mBAAiB,IAAI,aAAa,EAAE;AACvC;AAEA,WAJc;AAKX;AACG,eAAW,WAAW;AACtB,aAAS;AACZ;AACA;AACG,aAAS;AACZ;AACA;AACG,eAAW,WAAW;AACtB,aAAS;AACZ;AACA;AAEG,aAAS;AACT,eAAW,WAAW;AACzB;AACH;","names":[]}
package/dist/index.d.mts CHANGED
@@ -46,6 +46,15 @@ type ObjProps = {
46
46
  flat?: boolean;
47
47
  /** Seconds for the fold/unfold transition (default 1) */
48
48
  transitionDuration?: number;
49
+ /** When true, faces unfold one at a time with staggered delays */
50
+ oneAtATime?: boolean;
51
+ /** When true, connected edges stay joined during unfold (front→right→back chain).
52
+ * The left–front edge is the break point. */
53
+ remainJoined?: boolean;
54
+ /** When true, a light-sheen sweeps across each face the moment it
55
+ * rotates away from being face-on to the viewer.
56
+ * Requires a Y-axis rotation animation (anim1) to function. */
57
+ sheen?: boolean;
49
58
  className?: string;
50
59
  style?: CSSProperties;
51
60
  };
package/dist/index.d.ts CHANGED
@@ -46,6 +46,15 @@ type ObjProps = {
46
46
  flat?: boolean;
47
47
  /** Seconds for the fold/unfold transition (default 1) */
48
48
  transitionDuration?: number;
49
+ /** When true, faces unfold one at a time with staggered delays */
50
+ oneAtATime?: boolean;
51
+ /** When true, connected edges stay joined during unfold (front→right→back chain).
52
+ * The left–front edge is the break point. */
53
+ remainJoined?: boolean;
54
+ /** When true, a light-sheen sweeps across each face the moment it
55
+ * rotates away from being face-on to the viewer.
56
+ * Requires a Y-axis rotation animation (anim1) to function. */
57
+ sheen?: boolean;
49
58
  className?: string;
50
59
  style?: CSSProperties;
51
60
  };
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
3
3
 
4
4
  // src/components/Obj.tsx
5
5
 
@@ -96,39 +96,38 @@ function faceTransform3D(name, w, h, d) {
96
96
  return `translate(-50%, -50%) translateZ(${hd}px)`;
97
97
  }
98
98
  }
99
- function faceTransformFlat(name, w, _h, d) {
100
- const total = 2 * d + 2 * w;
101
- const halfTotal = total / 2;
99
+ function faceTransformFlat(name, w, h, d) {
100
+ const total = 2 * w + 2 * d;
101
+ const half = total / 2;
102
102
  let cx;
103
103
  switch (name) {
104
- case "left":
105
- cx = d / 2;
106
- break;
107
104
  case "front":
108
- cx = d + w / 2;
105
+ cx = w / 2;
109
106
  break;
110
107
  case "right":
111
- cx = d + w + d / 2;
108
+ cx = w + d / 2;
112
109
  break;
113
110
  case "back":
114
- cx = d + w + d + w / 2;
111
+ cx = w + d + w / 2;
112
+ break;
113
+ case "left":
114
+ cx = w + d + w + d / 2;
115
115
  break;
116
116
  case "top":
117
117
  case "top_front":
118
118
  case "top_rear":
119
- cx = d + w / 2;
120
- return `translate(-50%, -50%) translateX(${cx - halfTotal}px) translateY(-${_h}px)`;
119
+ cx = w / 2;
120
+ return `translate(-50%, -50%) translateX(${cx - half}px) translateY(-${h}px)`;
121
121
  case "bottom":
122
122
  case "bottom_front":
123
123
  case "bottom_rear":
124
- cx = d + w / 2;
125
- return `translate(-50%, -50%) translateX(${cx - halfTotal}px) translateY(${_h}px)`;
124
+ cx = w / 2;
125
+ return `translate(-50%, -50%) translateX(${cx - half}px) translateY(${h}px)`;
126
126
  default:
127
- cx = d + w / 2;
127
+ cx = w / 2;
128
128
  break;
129
129
  }
130
- const offsetX = cx - halfTotal;
131
- return `translate(-50%, -50%) translateX(${offsetX}px)`;
130
+ return `translate(-50%, -50%) translateX(${cx - half}px)`;
132
131
  }
133
132
  function parseCssText(css) {
134
133
  if (!css) return {};
@@ -157,6 +156,41 @@ function faceDimensions(name, w, h, d) {
157
156
  return { width: w, height: h };
158
157
  }
159
158
  }
159
+ function faceAppearance(face, globalDef) {
160
+ const globalStyle = parseCssText(globalDef?.css);
161
+ const faceInlineStyle = parseCssText(face.css);
162
+ const style = {
163
+ ...globalStyle,
164
+ ...globalDef?.style ?? {},
165
+ ...faceInlineStyle,
166
+ ...face.style ?? {}
167
+ };
168
+ const className = ["anim3d-face", face.className].filter(Boolean).join(" ");
169
+ const body = face.body ?? globalDef?.body ?? null;
170
+ return { style, className, body };
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
+ }
160
194
  var DEFAULT_FACE_NAMES = [
161
195
  "front",
162
196
  "back",
@@ -165,6 +199,18 @@ var DEFAULT_FACE_NAMES = [
165
199
  "top",
166
200
  "bottom"
167
201
  ];
202
+ var STAGGER_ORDER = [
203
+ "front",
204
+ "right",
205
+ "back",
206
+ "left",
207
+ "top",
208
+ "bottom",
209
+ "top_front",
210
+ "top_rear",
211
+ "bottom_front",
212
+ "bottom_rear"
213
+ ];
168
214
  var Obj = React.memo(
169
215
  ({
170
216
  width = 160,
@@ -179,45 +225,217 @@ var Obj = React.memo(
179
225
  showCenterDiv = false,
180
226
  flat = false,
181
227
  transitionDuration = 1,
228
+ oneAtATime = false,
229
+ remainJoined = false,
230
+ sheen = false,
182
231
  className,
183
232
  style
184
233
  }) => {
185
- const w = typeof width === "number" ? width : parseFloat(width);
186
- const h = typeof height === "number" ? height : parseFloat(height);
187
- const d = typeof depth === "number" ? depth : parseFloat(depth);
234
+ const w = typeof width === "number" ? width : parseFloat(String(width));
235
+ const h = typeof height === "number" ? height : parseFloat(String(height));
236
+ const d = typeof depth === "number" ? depth : parseFloat(String(depth));
188
237
  const animation1 = toAnimationShorthand(anim1) ?? void 0;
189
238
  const animation2 = toAnimationShorthand(anim2) ?? void 0;
190
239
  const faceList = faces && faces.length > 0 ? faces : DEFAULT_FACE_NAMES.map((name) => ({ name }));
191
- const transitionCss = `transform ${transitionDuration}s ease-in-out`;
192
- const renderFace = (face, i) => {
240
+ const transitionCss = (delay = 0) => `transform ${transitionDuration}s ease-in-out ${delay}s`;
241
+ const sheenDur = anim1?.duration ?? 6;
242
+ const renderStandard = () => faceList.map((face, i) => {
193
243
  const dims = faceDimensions(face.name, w, h, d);
194
244
  const transform = flat ? faceTransformFlat(face.name, w, h, d) : faceTransform3D(face.name, w, h, d);
195
- const globalStyle = parseCssText(globalDef?.css);
196
- const faceInlineStyle = parseCssText(face.css);
197
- const mergedStyle = {
198
- ...globalStyle,
199
- ...globalDef?.style ?? {},
200
- ...faceInlineStyle,
201
- ...face.style ?? {},
202
- width: dims.width,
203
- height: dims.height,
204
- transform,
205
- transition: transitionCss
206
- };
207
- const body = face.body ?? globalDef?.body ?? null;
208
- const faceClassName = [
209
- "anim3d-face",
210
- face.className
211
- ].filter(Boolean).join(" ");
212
- return /* @__PURE__ */ jsx(
245
+ const {
246
+ style: fStyle,
247
+ className: fCls,
248
+ body
249
+ } = faceAppearance(face, globalDef);
250
+ const idx = STAGGER_ORDER.indexOf(face.name);
251
+ const delay = oneAtATime ? (idx >= 0 ? idx : i) * transitionDuration : 0;
252
+ return /* @__PURE__ */ jsxs(
213
253
  "div",
214
254
  {
215
- className: faceClassName,
216
- style: mergedStyle,
217
- children: body
255
+ className: fCls,
256
+ style: {
257
+ ...fStyle,
258
+ width: dims.width,
259
+ height: dims.height,
260
+ transform,
261
+ transition: transitionCss(delay)
262
+ },
263
+ children: [
264
+ body,
265
+ sheen && sheenOverlay(face.name, sheenDur, flat)
266
+ ]
218
267
  },
219
268
  face.name + "-" + i
220
269
  );
270
+ });
271
+ const renderJoined = () => {
272
+ const findFace = (n) => faceList.find((f) => f.name === n);
273
+ const frontFace = findFace("front");
274
+ const rightFace = findFace("right");
275
+ const backFace = findFace("back");
276
+ const leftFace = findFace("left");
277
+ const sideNames = /* @__PURE__ */ new Set([
278
+ "front",
279
+ "right",
280
+ "back",
281
+ "left"
282
+ ]);
283
+ const otherFaces = faceList.filter(
284
+ (f) => !sideNames.has(f.name)
285
+ );
286
+ const step = oneAtATime ? transitionDuration : 0;
287
+ const renderFaceEl = (face, dims, extra, key) => {
288
+ if (!face) return null;
289
+ const {
290
+ style: fStyle,
291
+ className: fCls,
292
+ body
293
+ } = faceAppearance(face, globalDef);
294
+ return /* @__PURE__ */ jsxs(
295
+ "div",
296
+ {
297
+ className: fCls,
298
+ style: {
299
+ ...fStyle,
300
+ width: dims.width,
301
+ height: dims.height,
302
+ display: "flex",
303
+ alignItems: "center",
304
+ justifyContent: "center",
305
+ boxSizing: "border-box",
306
+ ...extra
307
+ },
308
+ children: [
309
+ body,
310
+ sheen && sheenOverlay(face.name, sheenDur, flat)
311
+ ]
312
+ },
313
+ key
314
+ );
315
+ };
316
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
317
+ renderFaceEl(
318
+ frontFace,
319
+ { width: w, height: h },
320
+ {
321
+ position: "absolute",
322
+ left: "50%",
323
+ top: "50%",
324
+ transform: flat ? "translate(-50%, -50%)" : `translate(-50%, -50%) translateZ(${d / 2}px)`,
325
+ transition: transitionCss(0)
326
+ },
327
+ "front-j"
328
+ ),
329
+ /* @__PURE__ */ jsxs(
330
+ "div",
331
+ {
332
+ style: {
333
+ position: "absolute",
334
+ left: `calc(50% + ${w / 2}px)`,
335
+ top: "50%",
336
+ width: 0,
337
+ height: 0,
338
+ transformOrigin: "0 0",
339
+ transformStyle: "preserve-3d",
340
+ transform: flat ? "none" : `translateZ(${d / 2}px) rotateY(90deg)`,
341
+ transition: transitionCss(step)
342
+ },
343
+ children: [
344
+ renderFaceEl(
345
+ rightFace,
346
+ { width: d, height: h },
347
+ {
348
+ position: "absolute",
349
+ left: 0,
350
+ top: 0,
351
+ transform: "translateY(-50%)"
352
+ },
353
+ "right-j"
354
+ ),
355
+ /* @__PURE__ */ jsxs(
356
+ "div",
357
+ {
358
+ style: {
359
+ position: "absolute",
360
+ left: d,
361
+ top: 0,
362
+ width: 0,
363
+ height: 0,
364
+ transformOrigin: "0 0",
365
+ transformStyle: "preserve-3d",
366
+ transform: flat ? "none" : "rotateY(90deg)",
367
+ transition: transitionCss(step * 2)
368
+ },
369
+ children: [
370
+ renderFaceEl(
371
+ backFace,
372
+ { width: w, height: h },
373
+ {
374
+ position: "absolute",
375
+ left: 0,
376
+ top: 0,
377
+ transform: "translateY(-50%)"
378
+ },
379
+ "back-j"
380
+ ),
381
+ /* @__PURE__ */ jsx(
382
+ "div",
383
+ {
384
+ style: {
385
+ position: "absolute",
386
+ left: w,
387
+ top: 0,
388
+ width: 0,
389
+ height: 0,
390
+ transformOrigin: "0 0",
391
+ transformStyle: "preserve-3d",
392
+ transform: flat ? "none" : "rotateY(90deg)",
393
+ transition: transitionCss(step * 3)
394
+ },
395
+ children: renderFaceEl(
396
+ leftFace,
397
+ { width: d, height: h },
398
+ {
399
+ position: "absolute",
400
+ left: 0,
401
+ top: 0,
402
+ transform: "translateY(-50%)"
403
+ },
404
+ "left-j"
405
+ )
406
+ }
407
+ )
408
+ ]
409
+ }
410
+ )
411
+ ]
412
+ }
413
+ ),
414
+ otherFaces.map((face, i) => {
415
+ const dims = faceDimensions(face.name, w, h, d);
416
+ const xform = flat ? faceTransformFlat(face.name, w, h, d) : faceTransform3D(face.name, w, h, d);
417
+ const {
418
+ style: fStyle,
419
+ className: fCls,
420
+ body
421
+ } = faceAppearance(face, globalDef);
422
+ return /* @__PURE__ */ jsx(
423
+ "div",
424
+ {
425
+ className: fCls,
426
+ style: {
427
+ ...fStyle,
428
+ width: dims.width,
429
+ height: dims.height,
430
+ transform: xform,
431
+ transition: transitionCss(0)
432
+ },
433
+ children: body
434
+ },
435
+ face.name + "-o-" + i
436
+ );
437
+ })
438
+ ] });
221
439
  };
222
440
  const cssVars = {
223
441
  "--obj-w": w + "px",
@@ -229,7 +447,7 @@ var Obj = React.memo(
229
447
  {
230
448
  className: ["anim3d-stage", className].filter(Boolean).join(" "),
231
449
  style: {
232
- perspective: flat ? "none" : perspective,
450
+ perspective,
233
451
  perspectiveOrigin,
234
452
  ...cssVars,
235
453
  ...style
@@ -245,7 +463,7 @@ var Obj = React.memo(
245
463
  ...cssVars,
246
464
  animation: flat ? "none" : animation1,
247
465
  transformStyle: "preserve-3d",
248
- transition: transitionCss
466
+ transition: transitionCss()
249
467
  },
250
468
  children: /* @__PURE__ */ jsxs(
251
469
  "div",
@@ -255,11 +473,11 @@ var Obj = React.memo(
255
473
  ...cssVars,
256
474
  animation: flat ? "none" : animation2,
257
475
  transformStyle: "preserve-3d",
258
- transition: transitionCss
476
+ transition: transitionCss()
259
477
  },
260
478
  children: [
261
479
  showCenterDiv && /* @__PURE__ */ jsx("div", { className: "anim3d-center" }),
262
- faceList.map(renderFace)
480
+ remainJoined ? renderJoined() : renderStandard()
263
481
  ]
264
482
  }
265
483
  )
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/* Layout order: … | left | front | right | back | … */\n/* Centered on the midpoint of the full row. */\n/* ------------------------------------------------------------------ */\n\n/** Ordered face names for the flat row (left-to-right) */\nconst FLAT_ORDER: FaceName[] = [\"left\", \"front\", \"right\", \"back\"];\n\n/**\n * Returns the flat-layout transform for a face.\n *\n * Side faces (left, right) have a rendered width of `d` (depth).\n * Front/back faces have a rendered width of `w`.\n * Row order: left(d) | front(w) | right(d) | back(w)\n * Total row width = 2d + 2w. We centre the row on 0.\n */\nfunction faceTransformFlat(\n name: string,\n w: number,\n _h: number,\n d: number\n): string {\n // Total row width\n const total = 2 * d + 2 * w;\n const halfTotal = total / 2;\n\n // Cumulative left-edge x positions (relative to row start = 0)\n // left : 0 width d\n // front : d width w\n // right : d + w width d\n // back : d + w + d width w\n let cx: number; // centre-x of this face in the row\n\n switch (name as FaceName) {\n case \"left\":\n cx = d / 2;\n break;\n case \"front\":\n cx = d + w / 2;\n break;\n case \"right\":\n cx = d + w + d / 2;\n break;\n case \"back\":\n cx = d + w + d + w / 2;\n break;\n case \"top\":\n case \"top_front\":\n case \"top_rear\":\n // Top faces slide upward out of the way\n cx = d + w / 2;\n return `translate(-50%, -50%) translateX(${cx - halfTotal}px) translateY(-${_h}px)`;\n case \"bottom\":\n case \"bottom_front\":\n case \"bottom_rear\":\n cx = d + w / 2;\n return `translate(-50%, -50%) translateX(${cx - halfTotal}px) translateY(${_h}px)`;\n default:\n cx = d + w / 2;\n break;\n }\n\n // Shift so the row is centred on x=0\n const offsetX = cx - halfTotal;\n return `translate(-50%, -50%) translateX(${offsetX}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/* 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/* 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 className,\n style,\n }) => {\n const w = typeof width === \"number\" ? width : parseFloat(width);\n const h = typeof height === \"number\" ? height : parseFloat(height);\n const d = typeof depth === \"number\" ? depth : parseFloat(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 = `transform ${transitionDuration}s ease-in-out`;\n\n // Merge global defaults into each face\n const renderFace = (face: FaceDef, i: number) => {\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 globalStyle = parseCssText(globalDef?.css);\n const faceInlineStyle = parseCssText(face.css);\n\n const mergedStyle: React.CSSProperties = {\n ...globalStyle,\n ...(globalDef?.style ?? {}),\n ...faceInlineStyle,\n ...(face.style ?? {}),\n width: dims.width,\n height: dims.height,\n transform,\n transition: transitionCss,\n };\n\n const body = face.body ?? globalDef?.body ?? null;\n const faceClassName = [\n \"anim3d-face\",\n face.className,\n ]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <div\n key={face.name + \"-\" + i}\n className={faceClassName}\n style={mergedStyle}\n >\n {body}\n </div>\n );\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].filter(Boolean).join(\" \")}\n style={{\n perspective: flat ? \"none\" : 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 && <div className=\"anim3d-center\" />}\n {faceList.map(renderFace)}\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 // 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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "anim-3d-obj",
3
- "version": "2.0.5",
3
+ "version": "2.0.7",
4
4
  "description": "Configurable 3D object with animated rotations and face content",
5
5
  "license": "MIT",
6
6
  "author": "mdnelles",