anim-3d-obj 2.0.1 → 2.0.4

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.js CHANGED
@@ -1,31 +1,7 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
-
20
- // src/index.ts
21
- var src_exports = {};
22
- __export(src_exports, {
23
- Obj: () => Obj_default
24
- });
25
- module.exports = __toCommonJS(src_exports);
1
+ import * as React from 'react';
2
+ import { jsx, jsxs } from 'react/jsx-runtime';
26
3
 
27
4
  // src/components/Obj.tsx
28
- var import_react = require("react");
29
5
 
30
6
  // src/keyframes.ts
31
7
  function ensureStyleTag() {
@@ -91,142 +67,171 @@ function toAnimationShorthand(cfg) {
91
67
  const play = cfg.animationPlayState ?? "running";
92
68
  return `${name} ${dur} ${timing} ${delay} ${iter} ${dir} ${fill} ${play}`;
93
69
  }
94
-
95
- // src/components/Obj.tsx
96
- var import_obj = require("./obj-PY72GEW6.css");
97
- var import_jsx_runtime = require("react/jsx-runtime");
98
70
  function faceTransform(name, w, h, d) {
99
- const z = d / 2;
71
+ const hw = w / 2;
72
+ const hh = h / 2;
73
+ const hd = d / 2;
100
74
  switch (name) {
101
75
  case "front":
102
- return `translate3d(-50%, -50%, ${z}px)`;
76
+ return `translate(-50%, -50%) translateZ(${hd}px)`;
103
77
  case "back":
104
- return `translate3d(-50%, -50%, ${-z}px) rotateY(180deg)`;
78
+ return `translate(-50%, -50%) rotateY(180deg) translateZ(${hd}px)`;
105
79
  case "left":
106
- return `translate3d(-50%, -50%, 0) rotateY(-90deg) translateZ(${w / 2}px)`;
80
+ return `translate(-50%, -50%) rotateY(-90deg) translateZ(${hw}px)`;
107
81
  case "right":
108
- return `translate3d(-50%, -50%, 0) rotateY(90deg) translateZ(${w / 2}px)`;
82
+ return `translate(-50%, -50%) rotateY(90deg) translateZ(${hw}px)`;
109
83
  case "top":
110
- return `translate3d(-50%, -50%, 0) rotateX(90deg) translateZ(${h / 2}px)`;
84
+ return `translate(-50%, -50%) rotateX(90deg) translateZ(${hh}px)`;
111
85
  case "bottom":
112
- return `translate3d(-50%, -50%, 0) rotateX(-90deg) translateZ(${h / 2}px)`;
113
- // legacy/extraposition near top/bottom, front/back edges
86
+ return `translate(-50%, -50%) rotateX(-90deg) translateZ(${hh}px)`;
87
+ // Legacy names map to angled half-faces
114
88
  case "top_front":
115
- return `translate3d(-50%, -50%, ${z / 2}px) rotateX(75deg)`;
89
+ return `translate(-50%, -50%) rotateX(45deg) translateZ(${hh}px)`;
116
90
  case "top_rear":
117
- return `translate3d(-50%, -50%, ${-z / 2}px) rotateX(105deg)`;
91
+ return `translate(-50%, -50%) rotateX(135deg) translateZ(${hh}px)`;
118
92
  case "bottom_front":
119
- return `translate3d(-50%, -50%, ${z / 2}px) rotateX(-75deg)`;
93
+ return `translate(-50%, -50%) rotateX(-45deg) translateZ(${hh}px)`;
120
94
  case "bottom_rear":
121
- return `translate3d(-50%, -50%, ${-z / 2}px) rotateX(-105deg)`;
95
+ return `translate(-50%, -50%) rotateX(-135deg) translateZ(${hh}px)`;
122
96
  default:
123
- return `translate3d(-50%, -50%, ${z}px)`;
97
+ return `translate(-50%, -50%) translateZ(${hd}px)`;
124
98
  }
125
99
  }
126
- function mergeStyles(inlineCSS, style) {
127
- const out = { ...style ?? {} };
128
- if (inlineCSS) {
129
- inlineCSS.split(";").map((s) => s.trim()).filter(Boolean).forEach((rule) => {
130
- const [k, v] = rule.split(":");
131
- if (!k || !v) return;
132
- const key = k.trim().replace(/-([a-z])/g, (_, c) => c.toUpperCase());
133
- out[key] = v.trim();
134
- });
135
- }
136
- return out;
100
+ function parseCssText(css) {
101
+ if (!css) return {};
102
+ const style = {};
103
+ css.split(";").forEach((rule) => {
104
+ const [prop, ...rest] = rule.split(":");
105
+ if (!prop || rest.length === 0) return;
106
+ const key = prop.trim().replace(/-([a-z])/g, (_, c) => c.toUpperCase());
107
+ style[key] = rest.join(":").trim();
108
+ });
109
+ return style;
137
110
  }
138
- function Face({
139
- w,
140
- h,
141
- d,
142
- face,
143
- global
144
- }) {
145
- const base = (0, import_react.useMemo)(
146
- () => mergeStyles(global?.css, global?.style),
147
- [global]
148
- );
149
- const merged = (0, import_react.useMemo)(
150
- () => ({ ...base, ...mergeStyles(face.css, face.style) }),
151
- [base, face.css, face.style]
152
- );
153
- const content = face.body ?? global?.body ?? null;
154
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
155
- "div",
156
- {
157
- className: `anim3d-face ${face.className ?? ""}`,
158
- style: {
159
- transform: faceTransform(face.name, w, h, d),
160
- ...merged
161
- },
162
- "data-face": face.name,
163
- children: typeof content === "string" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: content }) : content
164
- }
165
- );
111
+ function faceDimensions(name, w, h, d) {
112
+ switch (name) {
113
+ case "left":
114
+ case "right":
115
+ return { width: d, height: h };
116
+ case "top":
117
+ case "bottom":
118
+ case "top_front":
119
+ case "top_rear":
120
+ case "bottom_front":
121
+ case "bottom_rear":
122
+ return { width: w, height: d };
123
+ default:
124
+ return { width: w, height: h };
125
+ }
166
126
  }
167
- var Obj = ({
168
- width = 160,
169
- height = 160,
170
- depth = 150,
171
- perspective = 500,
172
- perspectiveOrigin = "50% 50%",
173
- faces = [
174
- { name: "front", body: "FRONT" },
175
- { name: "back", body: "BACK" },
176
- { name: "left", body: "LEFT" },
177
- { name: "right", body: "RIGHT" },
178
- { name: "top", body: "TOP" },
179
- { name: "bottom", body: "BOTTOM" }
180
- ],
181
- global,
182
- anim1,
183
- anim2,
184
- showCenterDiv = false,
185
- className,
186
- style
187
- }) => {
188
- const resolvedAnim1 = toAnimationShorthand(anim1);
189
- const resolvedAnim2 = toAnimationShorthand(anim2);
190
- const animation = [resolvedAnim1, resolvedAnim2].filter(Boolean).join(", ");
191
- const stageStyle = {
192
- perspective: `${perspective}px`,
193
- perspectiveOrigin
194
- };
195
- const wrapperStyle = {
196
- // consumed by CSS var
197
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
198
- // @ts-ignore
199
- "--obj-w": `${width}px`,
200
- "--obj-h": `${height}px`,
201
- width,
202
- height,
203
- "animation": animation || void 0
204
- };
205
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
206
- "div",
207
- {
208
- className: `anim3d-stage ${className ?? ""}`,
209
- style: { ...stageStyle, ...style },
210
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "anim3d-wrapper", style: wrapperStyle, children: [
211
- showCenterDiv && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "anim3d-center" }),
212
- faces.map((f, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
213
- Face,
127
+ var DEFAULT_FACE_NAMES = [
128
+ "front",
129
+ "back",
130
+ "left",
131
+ "right",
132
+ "top",
133
+ "bottom"
134
+ ];
135
+ var Obj = React.memo(
136
+ ({
137
+ width = 160,
138
+ height = 160,
139
+ depth = 150,
140
+ perspective = 600,
141
+ perspectiveOrigin = "50% 50%",
142
+ faces,
143
+ global: globalDef,
144
+ anim1,
145
+ anim2,
146
+ showCenterDiv = false,
147
+ className,
148
+ style
149
+ }) => {
150
+ const w = typeof width === "number" ? width : parseFloat(width);
151
+ const h = typeof height === "number" ? height : parseFloat(height);
152
+ const d = typeof depth === "number" ? depth : parseFloat(depth);
153
+ const animation1 = toAnimationShorthand(anim1) ?? void 0;
154
+ const animation2 = toAnimationShorthand(anim2) ?? void 0;
155
+ const faceList = faces && faces.length > 0 ? faces : DEFAULT_FACE_NAMES.map((name) => ({ name }));
156
+ const renderFace = (face, i) => {
157
+ const dims = faceDimensions(face.name, w, h, d);
158
+ const transform = faceTransform(face.name, w, h, d);
159
+ const globalStyle = parseCssText(globalDef?.css);
160
+ const faceInlineStyle = parseCssText(face.css);
161
+ const mergedStyle = {
162
+ ...globalStyle,
163
+ ...globalDef?.style ?? {},
164
+ ...faceInlineStyle,
165
+ ...face.style ?? {},
166
+ width: dims.width,
167
+ height: dims.height,
168
+ transform
169
+ };
170
+ const body = face.body ?? globalDef?.body ?? null;
171
+ const faceClassName = [
172
+ "anim3d-face",
173
+ face.className
174
+ ].filter(Boolean).join(" ");
175
+ return /* @__PURE__ */ jsx(
176
+ "div",
177
+ {
178
+ className: faceClassName,
179
+ style: mergedStyle,
180
+ children: body
181
+ },
182
+ face.name + "-" + i
183
+ );
184
+ };
185
+ const cssVars = {
186
+ "--obj-w": w + "px",
187
+ "--obj-h": h + "px",
188
+ "--obj-d": d + "px"
189
+ };
190
+ return /* @__PURE__ */ jsx(
191
+ "div",
192
+ {
193
+ className: ["anim3d-stage", className].filter(Boolean).join(" "),
194
+ style: {
195
+ perspective,
196
+ perspectiveOrigin,
197
+ ...cssVars,
198
+ ...style
199
+ },
200
+ "data-anim-3d-obj": true,
201
+ role: "img",
202
+ "aria-label": "3D object",
203
+ children: /* @__PURE__ */ jsx(
204
+ "div",
214
205
  {
215
- w: width,
216
- h: height,
217
- d: depth,
218
- face: f,
219
- global
220
- },
221
- `${f.name}-${i}`
222
- ))
223
- ] })
224
- }
225
- );
226
- };
227
- var Obj_default = Obj;
228
- // Annotate the CommonJS export names for ESM import in node:
229
- 0 && (module.exports = {
230
- Obj
231
- });
206
+ className: "anim3d-wrapper",
207
+ style: {
208
+ ...cssVars,
209
+ animation: animation1,
210
+ transformStyle: "preserve-3d"
211
+ },
212
+ children: /* @__PURE__ */ jsxs(
213
+ "div",
214
+ {
215
+ className: "anim3d-wrapper",
216
+ style: {
217
+ ...cssVars,
218
+ animation: animation2,
219
+ transformStyle: "preserve-3d"
220
+ },
221
+ children: [
222
+ showCenterDiv && /* @__PURE__ */ jsx("div", { className: "anim3d-center" }),
223
+ faceList.map(renderFace)
224
+ ]
225
+ }
226
+ )
227
+ }
228
+ )
229
+ }
230
+ );
231
+ }
232
+ );
233
+ Obj.displayName = "Obj";
234
+
235
+ export { Obj, Obj as default, resolveAnimation, toAnimationShorthand };
236
+ //# sourceMappingURL=index.js.map
232
237
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/components/Obj.tsx","../src/keyframes.ts"],"sourcesContent":["export { default as Obj } from \"./components/Obj\";\nexport type {\n ObjProps,\n FaceDef,\n GlobalDef,\n AnimationConfig,\n FaceName,\n BuiltInAnimName,\n} from \"./types\";\n","import React, { useMemo } from \"react\";\nimport type { CSSProperties, ReactNode } from \"react\";\nimport { FaceDef, GlobalDef, ObjProps, FaceName } from \"../types\";\nimport { toAnimationShorthand } from \"../keyframes\";\nimport \"../styles/obj.css\";\n\n/** Map face name -> transform so it sits on a rectangular prism */\nfunction faceTransform(name: string, w: number, h: number, d: number): string {\n const z = d / 2;\n switch (name as FaceName) {\n case \"front\":\n return `translate3d(-50%, -50%, ${z}px)`;\n case \"back\":\n return `translate3d(-50%, -50%, ${-z}px) rotateY(180deg)`;\n case \"left\":\n return `translate3d(-50%, -50%, 0) rotateY(-90deg) translateZ(${\n w / 2\n }px)`;\n case \"right\":\n return `translate3d(-50%, -50%, 0) rotateY(90deg) translateZ(${\n w / 2\n }px)`;\n case \"top\":\n return `translate3d(-50%, -50%, 0) rotateX(90deg) translateZ(${\n h / 2\n }px)`;\n case \"bottom\":\n return `translate3d(-50%, -50%, 0) rotateX(-90deg) translateZ(${\n h / 2\n }px)`;\n // legacy/extra – position near top/bottom, front/back edges\n case \"top_front\":\n return `translate3d(-50%, -50%, ${z / 2}px) rotateX(75deg)`;\n case \"top_rear\":\n return `translate3d(-50%, -50%, ${-z / 2}px) rotateX(105deg)`;\n case \"bottom_front\":\n return `translate3d(-50%, -50%, ${z / 2}px) rotateX(-75deg)`;\n case \"bottom_rear\":\n return `translate3d(-50%, -50%, ${-z / 2}px) rotateX(-105deg)`;\n default:\n return `translate3d(-50%, -50%, ${z}px)`;\n }\n}\n\n/** Merge legacy CSS string + style object */\nfunction mergeStyles(inlineCSS?: string, style?: CSSProperties): CSSProperties {\n const out: CSSProperties = { ...(style ?? {}) };\n if (inlineCSS) {\n // naive parser: split by ;, then key:value\n inlineCSS\n .split(\";\")\n .map((s) => s.trim())\n .filter(Boolean)\n .forEach((rule) => {\n const [k, v] = rule.split(\":\");\n if (!k || !v) return;\n const key = k\n .trim()\n .replace(/-([a-z])/g, (_, c) => c.toUpperCase());\n (out as any)[key] = v.trim();\n });\n }\n return out;\n}\n\nfunction Face({\n w,\n h,\n d,\n face,\n global,\n}: {\n w: number;\n h: number;\n d: number;\n face: FaceDef;\n global?: GlobalDef;\n}) {\n const base = useMemo(\n () => mergeStyles(global?.css, global?.style),\n [global]\n );\n const merged = useMemo(\n () => ({ ...base, ...mergeStyles(face.css, face.style) }),\n [base, face.css, face.style]\n );\n\n const content: ReactNode = face.body ?? global?.body ?? null;\n\n return (\n <div\n className={`anim3d-face ${face.className ?? \"\"}`}\n style={{\n transform: faceTransform(face.name, w, h, d),\n ...merged,\n }}\n data-face={face.name}\n >\n {typeof content === \"string\" ? <span>{content}</span> : content}\n </div>\n );\n}\n\nconst Obj: React.FC<ObjProps> = ({\n width = 160,\n height = 160,\n depth = 150,\n perspective = 500,\n perspectiveOrigin = \"50% 50%\",\n faces = [\n { name: \"front\", body: \"FRONT\" },\n { name: \"back\", body: \"BACK\" },\n { name: \"left\", body: \"LEFT\" },\n { name: \"right\", body: \"RIGHT\" },\n { name: \"top\", body: \"TOP\" },\n { name: \"bottom\", body: \"BOTTOM\" },\n ],\n global,\n anim1,\n anim2,\n showCenterDiv = false,\n className,\n style,\n}) => {\n const resolvedAnim1 = toAnimationShorthand(anim1);\n const resolvedAnim2 = toAnimationShorthand(anim2);\n const animation = [resolvedAnim1, resolvedAnim2].filter(Boolean).join(\", \");\n\n const stageStyle: CSSProperties = {\n perspective: `${perspective}px`,\n perspectiveOrigin,\n };\n\n const wrapperStyle: CSSProperties = {\n // consumed by CSS var\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n \"--obj-w\": `${width}px`,\n \"--obj-h\": `${height}px`,\n width,\n height,\n \"animation\": animation || undefined,\n };\n\n return (\n <div\n className={`anim3d-stage ${className ?? \"\"}`}\n style={{ ...stageStyle, ...style }}\n >\n <div className='anim3d-wrapper' style={wrapperStyle as any}>\n {showCenterDiv && <div className='anim3d-center' />}\n {faces.map((f, i) => (\n <Face\n key={`${f.name}-${i}`}\n w={width}\n h={height}\n d={depth}\n face={f}\n global={global}\n />\n ))}\n </div>\n </div>\n );\n};\n\nexport default Obj;\nexport { Obj };\n","import type { AnimationConfig } from \"./types\";\n\nlet counter = 0;\nconst uid = () => (++counter).toString(36);\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"],"mappings":"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","names":[]}
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 map */\n/* ------------------------------------------------------------------ */\n\nfunction faceTransform(\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 // Legacy names – map to angled half-faces\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/* 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 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 // 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 = faceTransform(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 };\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,\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: animation1,\n transformStyle: \"preserve-3d\",\n }}\n >\n {/* Inner animation wrapper (anim2) */}\n <div\n className=\"anim3d-wrapper\"\n style={{\n ...cssVars,\n animation: animation2,\n transformStyle: \"preserve-3d\",\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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "anim-3d-obj",
3
- "version": "2.0.1",
3
+ "version": "2.0.4",
4
4
  "description": "Configurable 3D object with animated rotations and face content",
5
5
  "license": "MIT",
6
6
  "author": "mdnelles",
@@ -8,39 +8,36 @@
8
8
  "dist/**/*.css",
9
9
  "src/styles/obj.css"
10
10
  ],
11
- "module": "dist/esm/index.js",
12
- "main": "dist/cjs/index.cjs",
13
- "types": "dist/esm/index.d.ts",
11
+ "main": "dist/index.cjs",
12
+ "module": "dist/index.js",
13
+ "types": "dist/index.d.ts",
14
14
  "exports": {
15
15
  ".": {
16
- "import": "./dist/esm/index.js",
17
- "require": "./dist/cjs/index.cjs",
18
- "types": "./dist/esm/index.d.ts"
19
- },
20
- "./components/Obj": {
21
- "import": "./dist/esm/components/Obj.js",
22
- "require": "./dist/cjs/components/Obj.cjs",
23
- "types": "./dist/esm/components/Obj.d.ts"
24
- },
25
- "./dist/cjs/components/Obj": "./dist/cjs/components/Obj.cjs"
16
+ "types": "./dist/index.d.ts",
17
+ "import": "./dist/index.js",
18
+ "require": "./dist/index.cjs",
19
+ "default": "./dist/index.js"
20
+ }
26
21
  },
27
22
  "files": [
28
- "dist"
23
+ "dist",
24
+ "README.md",
25
+ "LICENSE"
29
26
  ],
30
- "scripts": {
31
- "build": "tsup",
32
- "clean": "rm -rf dist",
33
- "dev": "tsup --watch",
34
- "prepublishOnly": "npm run clean && npm run build"
35
- },
36
27
  "peerDependencies": {
37
- "react": ">=17 || >=18",
38
- "react-dom": ">=17 || >=18"
28
+ "react": ">=17 || >=18 || >=19",
29
+ "react-dom": ">=17 || >=18 || >=19"
39
30
  },
40
31
  "devDependencies": {
41
- "@types/react": "^18.3.3",
42
- "@types/react-dom": "^18.3.0",
32
+ "@types/react": "^19.0.0",
33
+ "@types/react-dom": "^19.0.0",
43
34
  "tsup": "^8.5.0",
44
- "typescript": "^5.9.2"
35
+ "typescript": "^5.4.0"
36
+ },
37
+ "scripts": {
38
+ "clean": "rm -rf dist",
39
+ "build": "tsup",
40
+ "dev": "tsup --watch",
41
+ "prepublishOnly": "npm run clean && npm run build"
45
42
  }
46
43
  }
@@ -1,50 +0,0 @@
1
- import React, { CSSProperties, ReactNode } from 'react';
2
-
3
- type AnimationDirection = "normal" | "reverse" | "alternate" | "alternate-reverse";
4
- type AnimationFill = "none" | "forwards" | "backwards" | "both";
5
- type AnimationPlayState = "running" | "paused";
6
- type TimingFn = "linear" | "ease" | "ease-in" | "ease-out" | "ease-in-out" | string;
7
- type BuiltInAnimName = "Y360" | "X360" | "Z360" | "rockY" | "rockX";
8
- type AnimationConfig = {
9
- name: BuiltInAnimName | string;
10
- degreesHi?: number;
11
- degreesLow?: number;
12
- duration?: number;
13
- delay?: number;
14
- iterationCount?: number | "infinite";
15
- direction?: AnimationDirection;
16
- timing?: TimingFn;
17
- fillMode?: AnimationFill;
18
- animationPlayState?: AnimationPlayState;
19
- };
20
- type FaceName = "front" | "back" | "left" | "right" | "top" | "bottom" | "top_rear" | "top_front" | "bottom_rear" | "bottom_front";
21
- type FaceDef = {
22
- name: FaceName | string;
23
- css?: string;
24
- style?: CSSProperties;
25
- body?: ReactNode | string;
26
- className?: string;
27
- };
28
- type GlobalDef = {
29
- css?: string;
30
- style?: CSSProperties;
31
- body?: ReactNode | string;
32
- };
33
- type ObjProps = {
34
- width?: number;
35
- height?: number;
36
- depth?: number;
37
- perspective?: number;
38
- perspectiveOrigin?: string;
39
- faces?: FaceDef[];
40
- global?: GlobalDef;
41
- anim1?: AnimationConfig;
42
- anim2?: AnimationConfig;
43
- showCenterDiv?: boolean;
44
- className?: string;
45
- style?: CSSProperties;
46
- };
47
-
48
- declare const Obj: React.FC<ObjProps>;
49
-
50
- export { type AnimationConfig as A, type BuiltInAnimName as B, type FaceDef as F, type GlobalDef as G, type ObjProps as O, Obj, type FaceName as a, Obj as default };
@@ -1,50 +0,0 @@
1
- import React, { CSSProperties, ReactNode } from 'react';
2
-
3
- type AnimationDirection = "normal" | "reverse" | "alternate" | "alternate-reverse";
4
- type AnimationFill = "none" | "forwards" | "backwards" | "both";
5
- type AnimationPlayState = "running" | "paused";
6
- type TimingFn = "linear" | "ease" | "ease-in" | "ease-out" | "ease-in-out" | string;
7
- type BuiltInAnimName = "Y360" | "X360" | "Z360" | "rockY" | "rockX";
8
- type AnimationConfig = {
9
- name: BuiltInAnimName | string;
10
- degreesHi?: number;
11
- degreesLow?: number;
12
- duration?: number;
13
- delay?: number;
14
- iterationCount?: number | "infinite";
15
- direction?: AnimationDirection;
16
- timing?: TimingFn;
17
- fillMode?: AnimationFill;
18
- animationPlayState?: AnimationPlayState;
19
- };
20
- type FaceName = "front" | "back" | "left" | "right" | "top" | "bottom" | "top_rear" | "top_front" | "bottom_rear" | "bottom_front";
21
- type FaceDef = {
22
- name: FaceName | string;
23
- css?: string;
24
- style?: CSSProperties;
25
- body?: ReactNode | string;
26
- className?: string;
27
- };
28
- type GlobalDef = {
29
- css?: string;
30
- style?: CSSProperties;
31
- body?: ReactNode | string;
32
- };
33
- type ObjProps = {
34
- width?: number;
35
- height?: number;
36
- depth?: number;
37
- perspective?: number;
38
- perspectiveOrigin?: string;
39
- faces?: FaceDef[];
40
- global?: GlobalDef;
41
- anim1?: AnimationConfig;
42
- anim2?: AnimationConfig;
43
- showCenterDiv?: boolean;
44
- className?: string;
45
- style?: CSSProperties;
46
- };
47
-
48
- declare const Obj: React.FC<ObjProps>;
49
-
50
- export { type AnimationConfig as A, type BuiltInAnimName as B, type FaceDef as F, type GlobalDef as G, type ObjProps as O, Obj, type FaceName as a, Obj as default };