@sangwonl/pocato-react 0.7.4 → 0.7.5
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 +137 -21
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -10,7 +10,6 @@ import {
|
|
|
10
10
|
import { createPortal } from "react-dom";
|
|
11
11
|
|
|
12
12
|
// src/export-image.ts
|
|
13
|
-
import html2canvas from "html2canvas";
|
|
14
13
|
var MIME_TYPES = {
|
|
15
14
|
png: "image/png",
|
|
16
15
|
webp: "image/webp",
|
|
@@ -21,34 +20,38 @@ async function captureFaceWithEffect(content, effectLayer, effect, options) {
|
|
|
21
20
|
await Promise.all(
|
|
22
21
|
Array.from(content.querySelectorAll("img"), (image) => image.decode?.().catch(() => void 0))
|
|
23
22
|
);
|
|
24
|
-
const
|
|
25
|
-
|
|
23
|
+
const width = content.offsetWidth;
|
|
24
|
+
const height = content.offsetHeight;
|
|
25
|
+
if (!width || !height) {
|
|
26
26
|
throw new Error("Failed to export Pocato image: card face has no size");
|
|
27
27
|
}
|
|
28
28
|
const effectStyle = window.getComputedStyle(effectLayer);
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
height: bounds.height,
|
|
34
|
-
logging: false,
|
|
35
|
-
scale: options.width / bounds.width,
|
|
36
|
-
useCORS: true,
|
|
37
|
-
width: bounds.width,
|
|
38
|
-
onclone: (_document, clonedContent) => {
|
|
39
|
-
clonedContent.style.position = "relative";
|
|
40
|
-
clonedContent.style.inset = "auto";
|
|
41
|
-
clonedContent.style.width = `${bounds.width}px`;
|
|
42
|
-
clonedContent.style.height = `${bounds.height}px`;
|
|
43
|
-
clonedContent.style.transform = "none";
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
const effectImage = await dataUrlToImage(effectDataUrl);
|
|
29
|
+
const [capturedFace, effectImage] = await Promise.all([
|
|
30
|
+
captureHtml(content, width, height, options),
|
|
31
|
+
blobToDataUrl(effect).then(dataUrlToImage)
|
|
32
|
+
]);
|
|
47
33
|
const output = document.createElement("canvas");
|
|
48
34
|
output.width = options.width;
|
|
49
35
|
output.height = options.height;
|
|
50
36
|
const context = output.getContext("2d");
|
|
51
37
|
if (!context) throw new Error("Failed to export Pocato image: canvas context is unavailable");
|
|
38
|
+
const faceStyle = getComputedStyle(content.parentElement ?? content);
|
|
39
|
+
const radius = (value, size) => value.endsWith("%") ? parseFloat(value) * size / 100 : parseFloat(value);
|
|
40
|
+
const corners = [
|
|
41
|
+
faceStyle.borderTopLeftRadius,
|
|
42
|
+
faceStyle.borderTopRightRadius,
|
|
43
|
+
faceStyle.borderBottomRightRadius,
|
|
44
|
+
faceStyle.borderBottomLeftRadius
|
|
45
|
+
].map((value) => {
|
|
46
|
+
const [horizontal, vertical = horizontal] = value.split(/\s+/);
|
|
47
|
+
return {
|
|
48
|
+
x: radius(horizontal, width) * options.width / width,
|
|
49
|
+
y: radius(vertical, height) * options.height / height
|
|
50
|
+
};
|
|
51
|
+
});
|
|
52
|
+
context.beginPath();
|
|
53
|
+
context.roundRect(0, 0, output.width, output.height, corners);
|
|
54
|
+
context.clip();
|
|
52
55
|
context.drawImage(capturedFace, 0, 0, output.width, output.height);
|
|
53
56
|
context.save();
|
|
54
57
|
context.globalAlpha = Number(effectStyle.opacity);
|
|
@@ -58,6 +61,119 @@ async function captureFaceWithEffect(content, effectLayer, effect, options) {
|
|
|
58
61
|
const format = options.format ?? "png";
|
|
59
62
|
return canvasToBlob(output, MIME_TYPES[format], options.quality);
|
|
60
63
|
}
|
|
64
|
+
async function captureHtml(content, width, height, options) {
|
|
65
|
+
const resources = /* @__PURE__ */ new Map();
|
|
66
|
+
const inlineResource = (src) => {
|
|
67
|
+
if (src.startsWith("data:")) return Promise.resolve(src);
|
|
68
|
+
const url = new URL(src, document.baseURI).href;
|
|
69
|
+
let pending = resources.get(url);
|
|
70
|
+
if (!pending) {
|
|
71
|
+
pending = fetch(url).then(async (response) => {
|
|
72
|
+
if (!response.ok) throw new Error(`Failed to export Pocato image: resource returned ${response.status}`);
|
|
73
|
+
return blobToDataUrl(await response.blob());
|
|
74
|
+
});
|
|
75
|
+
resources.set(url, pending);
|
|
76
|
+
}
|
|
77
|
+
return pending;
|
|
78
|
+
};
|
|
79
|
+
const pseudoRules = [];
|
|
80
|
+
let nodeId = 0;
|
|
81
|
+
async function cloneElement(source) {
|
|
82
|
+
const clone2 = source.cloneNode(false);
|
|
83
|
+
const id = String(nodeId++);
|
|
84
|
+
clone2.setAttribute("data-pocato-export-node", id);
|
|
85
|
+
const computed = getComputedStyle(source);
|
|
86
|
+
clone2.setAttribute("style", serializeStyle(computed));
|
|
87
|
+
if (source instanceof HTMLElement && source.children.length === 0 && source.textContent?.trim()) {
|
|
88
|
+
const oneLineHeight = parseFloat(computed.lineHeight) + parseFloat(computed.paddingTop) + parseFloat(computed.paddingBottom);
|
|
89
|
+
if (source.clientHeight <= oneLineHeight + 1 && source.scrollWidth <= source.clientWidth) {
|
|
90
|
+
clone2.style.whiteSpace = "nowrap";
|
|
91
|
+
clone2.style.overflow = "visible";
|
|
92
|
+
clone2.style.textOverflow = "clip";
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
for (const pseudo of ["::before", "::after"]) {
|
|
96
|
+
const style2 = getComputedStyle(source, pseudo);
|
|
97
|
+
if (style2.content !== "none" && style2.content !== "normal") {
|
|
98
|
+
pseudoRules.push(`[data-pocato-export-node="${id}"]${pseudo}{${serializeStyle(style2)}}`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (source instanceof HTMLImageElement) {
|
|
102
|
+
clone2.removeAttribute("srcset");
|
|
103
|
+
clone2.removeAttribute("sizes");
|
|
104
|
+
clone2.removeAttribute("loading");
|
|
105
|
+
const canvas = document.createElement("canvas");
|
|
106
|
+
canvas.width = source.naturalWidth;
|
|
107
|
+
canvas.height = source.naturalHeight;
|
|
108
|
+
const context = canvas.getContext("2d");
|
|
109
|
+
if (!context) throw new Error("Failed to export Pocato image: image canvas is unavailable");
|
|
110
|
+
context.drawImage(source, 0, 0);
|
|
111
|
+
clone2.setAttribute("src", canvas.toDataURL("image/png"));
|
|
112
|
+
}
|
|
113
|
+
for (const child of Array.from(source.childNodes)) {
|
|
114
|
+
clone2.append(child instanceof Element ? await cloneElement(child) : child.cloneNode(true));
|
|
115
|
+
}
|
|
116
|
+
return clone2;
|
|
117
|
+
}
|
|
118
|
+
const [clone, fontCss] = await Promise.all([
|
|
119
|
+
cloneElement(content),
|
|
120
|
+
embedLoadedFonts(inlineResource)
|
|
121
|
+
]);
|
|
122
|
+
Object.assign(clone.style, {
|
|
123
|
+
position: "relative",
|
|
124
|
+
inset: "auto",
|
|
125
|
+
left: "0",
|
|
126
|
+
top: "0",
|
|
127
|
+
margin: "0",
|
|
128
|
+
width: `${width}px`,
|
|
129
|
+
height: `${height}px`,
|
|
130
|
+
transform: "none"
|
|
131
|
+
});
|
|
132
|
+
const style = document.createElement("style");
|
|
133
|
+
style.textContent = `${fontCss}
|
|
134
|
+
${pseudoRules.join("\n")}`;
|
|
135
|
+
clone.prepend(style);
|
|
136
|
+
clone.setAttribute("xmlns", "http://www.w3.org/1999/xhtml");
|
|
137
|
+
const markup = new XMLSerializer().serializeToString(clone);
|
|
138
|
+
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="${options.width}" height="${options.height}" viewBox="0 0 ${width} ${height}"><foreignObject width="100%" height="100%">${markup}</foreignObject></svg>`;
|
|
139
|
+
return dataUrlToImage(`data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`);
|
|
140
|
+
}
|
|
141
|
+
function serializeStyle(style) {
|
|
142
|
+
return Array.from(style, (name) => `${name}:${style.getPropertyValue(name)};`).join("");
|
|
143
|
+
}
|
|
144
|
+
async function embedLoadedFonts(inlineResource) {
|
|
145
|
+
const loaded = [];
|
|
146
|
+
document.fonts?.forEach((font) => {
|
|
147
|
+
if (font.status === "loaded") loaded.push(font);
|
|
148
|
+
});
|
|
149
|
+
const rules = [];
|
|
150
|
+
function collect(sheet) {
|
|
151
|
+
let sheetRules;
|
|
152
|
+
try {
|
|
153
|
+
sheetRules = sheet.cssRules;
|
|
154
|
+
} catch {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
for (const rule of Array.from(sheetRules)) {
|
|
158
|
+
if (rule instanceof CSSFontFaceRule) rules.push(rule);
|
|
159
|
+
else if (rule instanceof CSSImportRule && rule.styleSheet) collect(rule.styleSheet);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
Array.from(document.styleSheets).forEach(collect);
|
|
163
|
+
const normalize = (value) => value.replace(/["'\s]/g, "").toLowerCase();
|
|
164
|
+
const selected = rules.filter((rule) => loaded.some(
|
|
165
|
+
(font) => normalize(font.family) === normalize(rule.style.getPropertyValue("font-family")) && normalize(font.unicodeRange) === normalize(rule.style.getPropertyValue("unicode-range") || "U+0-10FFFF")
|
|
166
|
+
));
|
|
167
|
+
return (await Promise.all(selected.map(async (rule) => {
|
|
168
|
+
let css = rule.cssText;
|
|
169
|
+
const urls = Array.from(css.matchAll(/url\(\s*['"]?([^'"\)]+)['"]?\s*\)/g));
|
|
170
|
+
for (const match of urls) {
|
|
171
|
+
const url = new URL(match[1], rule.parentStyleSheet?.href || document.baseURI).href;
|
|
172
|
+
css = css.replace(match[0], `url("${await inlineResource(url)}")`);
|
|
173
|
+
}
|
|
174
|
+
return css;
|
|
175
|
+
}))).join("\n");
|
|
176
|
+
}
|
|
61
177
|
function blobToDataUrl(blob) {
|
|
62
178
|
return new Promise((resolve, reject) => {
|
|
63
179
|
const reader = new FileReader();
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/PocaCard.tsx","../src/export-image.ts","../src/pocato-client.ts","../src/use-pocato-config.ts"],"sourcesContent":["import {\n forwardRef,\n useEffect,\n useImperativeHandle,\n useLayoutEffect,\n useRef,\n useState,\n type CSSProperties,\n type ForwardedRef,\n type ReactNode,\n} from 'react'\nimport { createPortal } from 'react-dom'\nimport { captureFaceWithEffect } from './export-image'\nimport {\n PocaCard as CorePocaCard,\n type EffectUniformValue,\n type ExportImageOptions,\n type FaceFrameOptions,\n type LayerSource,\n type PocaCardOptions,\n} from '@sangwonl/pocato-core'\nimport { trackCardEvent, type PocaCardConfig, type PocaCardEffectConfig } from './pocato-client'\nimport { usePocatoConfig } from './use-pocato-config'\n\nexport interface PocaCardHandle {\n flip(): void\n wiggle(): void\n reset(): void\n exportImage(options: PocaCardExportImageOptions): Promise<Blob>\n}\n\nexport interface PocaCardExportImageOptions extends ExportImageOptions {\n includeContent?: boolean\n}\n\nexport interface FaceProps {\n shader?: string\n uniforms?: Record<string, EffectUniformValue>\n frame?: FaceFrameOptions\n layers: LayerSource[]\n content?: ReactNode\n}\n\nexport interface PocaCardImagePreview {\n interaction?: 'block' | 'pass-through'\n src?: string\n backgroundColor?: string\n mode?: 'cover' | 'contain'\n blur?: boolean\n render?: never\n}\n\nexport interface PocaCardCustomPreview {\n interaction?: 'block' | 'pass-through'\n render: ReactNode\n}\n\nexport type PocaCardPreview = PocaCardImagePreview | PocaCardCustomPreview\n\ninterface CommonPocaCardProps {\n flippable?: boolean\n initialFlipped?: boolean\n flipSpeed?: number\n interactive?: boolean\n touchAction?: PocaCardOptions['touchAction']\n preventNativeScroll?: PocaCardOptions['preventNativeScroll']\n interactionScrollMode?: PocaCardOptions['interactionScrollMode']\n stopPointerPropagation?: PocaCardOptions['stopPointerPropagation']\n preventPointerDefault?: PocaCardOptions['preventPointerDefault']\n maxTiltDegrees?: number\n onRotate?: (rotate: { x: number; y: number }) => void\n onFlip?: (flipped: boolean) => void\n onReady?: () => void\n onFirstFrame?: () => void\n onError?: (error: Error) => void\n preview?: PocaCardPreview\n error?: ReactNode | ((error: Error) => ReactNode)\n style?: CSSProperties\n className?: string\n}\n\ninterface DirectPocaCardProps extends CommonPocaCardProps {\n front: FaceProps\n back?: FaceProps\n config?: never\n cardId?: never\n publishableKey?: never\n releaseId?: never\n apiBaseUrl?: never\n}\n\ninterface ConfigPocaCardProps extends CommonPocaCardProps {\n config: PocaCardConfig\n front?: Partial<FaceProps>\n back?: Partial<FaceProps>\n cardId?: never\n publishableKey?: never\n releaseId?: never\n apiBaseUrl?: never\n}\n\ninterface ConnectedPocaCardProps extends CommonPocaCardProps {\n cardId: string\n publishableKey: string\n releaseId?: string | null\n apiBaseUrl?: string\n front?: Partial<FaceProps>\n back?: Partial<FaceProps>\n config?: never\n}\n\nexport type PocaCardProps = DirectPocaCardProps | ConfigPocaCardProps | ConnectedPocaCardProps\n\ninterface ResolvedPocaCardProps extends CommonPocaCardProps {\n front: FaceProps\n back?: FaceProps\n}\n\nfunction isConnectedProps(props: PocaCardProps): props is ConnectedPocaCardProps {\n return typeof props.cardId === 'string' && typeof props.publishableKey === 'string'\n}\n\nfunction isConfigProps(props: PocaCardProps): props is ConfigPocaCardProps {\n return 'config' in props && props.config != null\n}\n\nfunction resolveConfigProps(\n config: PocaCardConfig,\n props: ConfigPocaCardProps | ConnectedPocaCardProps,\n): ResolvedPocaCardProps {\n return {\n ...props,\n front: {\n ...config.front,\n shader: config.front.effect?.shader ?? config.front.shader,\n uniforms: config.front.uniforms ?? getEffectUniforms(config.front.effect),\n frame: props.front?.frame ?? config.front.frame,\n content: props.front?.content,\n },\n back: config.back\n ? {\n ...config.back,\n shader: config.back.effect?.shader ?? config.back.shader,\n uniforms: config.back.uniforms ?? getEffectUniforms(config.back.effect),\n frame: props.back?.frame ?? config.back.frame,\n content: props.back?.content,\n }\n : props.back?.layers\n ? props.back as FaceProps\n : undefined,\n flippable: props.flippable ?? config.flippable,\n initialFlipped: props.initialFlipped ?? config.initialFlipped,\n flipSpeed: props.flipSpeed ?? config.flipSpeed,\n preview: props.preview ?? config.preview,\n }\n}\n\nfunction getEffectUniforms(effect?: PocaCardEffectConfig) {\n if (!effect) return undefined\n return Object.fromEntries(\n effect.schema.map((item) => [\n item.uniform,\n effect.params[item.key] ?? item.defaultValue,\n ]),\n )\n}\n\nfunction renderError(errorView: CommonPocaCardProps['error'], error: Error) {\n if (typeof errorView === 'function') return errorView(error)\n return errorView ?? null\n}\n\nfunction renderPreview(preview?: PocaCardPreview) {\n if (!preview) return null\n if ('render' in preview && preview.render) return preview.render\n\n const imagePreview = preview as PocaCardImagePreview\n const backgroundColor = imagePreview.backgroundColor ?? '#f3f4f6'\n return (\n <div\n style={{\n width: '100%',\n height: '100%',\n overflow: 'hidden',\n borderRadius: '2%',\n background: backgroundColor,\n }}\n >\n {imagePreview.src ? (\n <img\n src={imagePreview.src}\n alt=\"\"\n draggable={false}\n style={{\n width: '100%',\n height: '100%',\n objectFit: imagePreview.mode ?? 'cover',\n filter: imagePreview.blur ? 'blur(12px)' : undefined,\n transform: imagePreview.blur ? 'scale(1.04)' : undefined,\n }}\n />\n ) : null}\n </div>\n )\n}\n\nfunction ConnectedPocaCard(\n props: ConnectedPocaCardProps,\n ref: ForwardedRef<PocaCardHandle>,\n) {\n const { config, loading, error } = usePocatoConfig({\n cardId: props.cardId,\n publishableKey: props.publishableKey,\n releaseId: props.releaseId,\n apiBaseUrl: props.apiBaseUrl,\n })\n const readyTracked = useRef(false)\n\n useEffect(() => {\n if (error && !props.error) {\n props.onError?.(error)\n }\n }, [error, props.error, props.onError])\n\n if (error) {\n return renderError(props.error, error)\n }\n\n if (loading || !config) {\n return renderPreview(props.preview)\n }\n\n const resolved = resolveConfigProps(config, {\n ...props,\n onFirstFrame: () => {\n if (!readyTracked.current) {\n readyTracked.current = true\n void trackCardEvent(props.cardId, {\n apiBaseUrl: props.apiBaseUrl,\n publishableKey: props.publishableKey,\n eventType: 'card_ready',\n })\n }\n props.onFirstFrame?.()\n },\n onError: (runtimeError) => {\n void trackCardEvent(props.cardId, {\n apiBaseUrl: props.apiBaseUrl,\n publishableKey: props.publishableKey,\n eventType: 'render_error',\n })\n props.onError?.(runtimeError)\n },\n })\n\n return <PocaCardRenderer props={resolved} refHandle={ref} />\n}\n\nfunction PocaCardRenderer({\n props,\n refHandle,\n}: {\n props: ResolvedPocaCardProps\n refHandle: ForwardedRef<PocaCardHandle>\n}) {\n const containerRef = useRef<HTMLDivElement>(null)\n const cardRef = useRef<CorePocaCard | null>(null)\n const [runtimeReady, setRuntimeReady] = useState(false)\n const [portalTargets, setPortalTargets] = useState<{\n front: HTMLElement | null\n back: HTMLElement | null\n }>({ front: null, back: null })\n const layersMounted = useRef(false)\n\n useLayoutEffect(() => {\n if (!containerRef.current) return\n\n layersMounted.current = false\n setRuntimeReady(false)\n const card = new CorePocaCard(containerRef.current, {\n front: { shader: props.front.shader, uniforms: props.front.uniforms, frame: props.front.frame, layers: props.front.layers },\n back: props.back ? { shader: props.back.shader, uniforms: props.back.uniforms, frame: props.back.frame, layers: props.back.layers } : undefined,\n flippable: props.flippable,\n initialFlipped: props.initialFlipped,\n flipSpeed: props.flipSpeed,\n interactive: props.interactive,\n touchAction: props.touchAction,\n preventNativeScroll: props.preventNativeScroll,\n interactionScrollMode: props.interactionScrollMode,\n stopPointerPropagation: props.stopPointerPropagation,\n preventPointerDefault: props.preventPointerDefault,\n maxTiltDegrees: props.maxTiltDegrees,\n onRotate: props.onRotate,\n })\n\n cardRef.current = card\n setPortalTargets({\n front: card.getFrontContentEl(),\n back: card.getBackContentEl(),\n })\n\n return () => {\n card.destroy()\n cardRef.current = null\n setPortalTargets({ front: null, back: null })\n }\n // Re-create when shader config changes\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [props.front.shader, props.back?.shader])\n\n const frontLayersKey = JSON.stringify(props.front.layers)\n const backLayersKey = JSON.stringify(props.back?.layers)\n useEffect(() => {\n if (!layersMounted.current) {\n layersMounted.current = true\n return\n }\n cardRef.current?.updateOptions({\n front: { layers: props.front.layers },\n back: props.back ? { layers: props.back.layers } : undefined,\n })\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [frontLayersKey, backLayersKey])\n\n useEffect(() => {\n if (props.flipSpeed != null) {\n cardRef.current?.updateOptions({ flipSpeed: props.flipSpeed })\n }\n }, [props.flipSpeed])\n\n const frontUniformsKey = JSON.stringify(props.front.uniforms ?? {})\n const backUniformsKey = JSON.stringify(props.back?.uniforms ?? {})\n useEffect(() => {\n cardRef.current?.updateOptions({\n front: { uniforms: props.front.uniforms },\n back: props.back ? { uniforms: props.back.uniforms } : undefined,\n })\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [frontUniformsKey, backUniformsKey])\n\n const frontFrameKey = JSON.stringify(props.front.frame ?? {})\n const backFrameKey = JSON.stringify(props.back?.frame ?? {})\n useEffect(() => {\n cardRef.current?.updateOptions({\n front: { frame: props.front.frame },\n back: props.back ? { frame: props.back.frame } : undefined,\n })\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [frontFrameKey, backFrameKey])\n\n useEffect(() => {\n const card = cardRef.current\n if (!card) return\n\n const onFlip = props.onFlip\n const onReady = props.onReady\n const onFirstFrame = props.onFirstFrame\n const onError = props.onError\n const handleFirstFrame = () => {\n setRuntimeReady(true)\n onFirstFrame?.()\n }\n\n if (onFlip) card.on('flip', onFlip)\n if (onReady) card.on('ready', onReady)\n card.on('firstFrame', handleFirstFrame)\n if (onError) card.on('error', onError)\n\n return () => {\n if (onFlip) card.off('flip', onFlip)\n if (onReady) card.off('ready', onReady)\n card.off('firstFrame', handleFirstFrame)\n if (onError) card.off('error', onError)\n }\n }, [props.onFlip, props.onReady, props.onFirstFrame, props.onError])\n\n useImperativeHandle(refHandle, () => ({\n flip: () => cardRef.current?.flip(),\n wiggle: () => cardRef.current?.wiggle(),\n reset: () => cardRef.current?.reset(),\n exportImage: async (options) => {\n const card = cardRef.current\n if (!card) {\n return Promise.reject(new Error('Failed to export Pocato image: card is not mounted'))\n }\n\n const { includeContent = false, ...renderOptions } = options\n const effect = await card.exportImage(renderOptions)\n if (!includeContent) return effect\n\n const content = renderOptions.face === 'back' ? portalTargets.back : portalTargets.front\n const face = content?.parentElement\n const effectLayer = face?.firstElementChild\n if (!content || !effectLayer || !['CANVAS', 'IMG'].includes(effectLayer.tagName)) {\n throw new Error('Failed to export Pocato image: card face is not mounted')\n }\n\n return captureFaceWithEffect(content, effectLayer, effect, renderOptions)\n },\n }))\n\n const preview = renderPreview(props.preview)\n const previewPointerEvents: CSSProperties['pointerEvents'] =\n props.preview?.interaction === 'pass-through' ? 'none' : undefined\n\n return (\n <div\n style={{\n ...props.style,\n position: props.style?.position ?? 'relative',\n }}\n className={props.className}\n >\n <div\n ref={containerRef}\n style={{\n position: 'absolute',\n inset: 0,\n }}\n />\n {!runtimeReady && preview ? (\n <div\n aria-hidden=\"true\"\n style={{\n position: 'absolute',\n inset: 0,\n zIndex: 1,\n pointerEvents: previewPointerEvents,\n }}\n >\n {preview}\n </div>\n ) : null}\n {portalTargets.front && props.front.content && createPortal(props.front.content, portalTargets.front)}\n {portalTargets.back && props.back?.content && createPortal(props.back.content, portalTargets.back)}\n </div>\n )\n}\n\nexport const PocaCard = forwardRef<PocaCardHandle, PocaCardProps>(\n (props, ref) => {\n if (isConnectedProps(props)) {\n return ConnectedPocaCard(props, ref)\n }\n\n const resolved = isConfigProps(props) ? resolveConfigProps(props.config, props) : props\n return <PocaCardRenderer props={resolved} refHandle={ref} />\n },\n)\n\nPocaCard.displayName = 'PocaCard'\n","import html2canvas from 'html2canvas'\nimport type { ExportImageOptions } from '@sangwonl/pocato-core'\n\nconst MIME_TYPES: Record<NonNullable<ExportImageOptions['format']>, string> = {\n png: 'image/png',\n webp: 'image/webp',\n jpeg: 'image/jpeg',\n}\n\nexport async function captureFaceWithEffect(\n content: HTMLElement,\n effectLayer: Element,\n effect: Blob,\n options: ExportImageOptions,\n): Promise<Blob> {\n await document.fonts?.ready\n await Promise.all(\n Array.from(content.querySelectorAll('img'), (image) => image.decode?.().catch(() => undefined)),\n )\n\n const bounds = content.getBoundingClientRect()\n if (!bounds.width || !bounds.height) {\n throw new Error('Failed to export Pocato image: card face has no size')\n }\n\n const effectStyle = window.getComputedStyle(effectLayer)\n\n const effectDataUrl = await blobToDataUrl(effect)\n const capturedFace = await html2canvas(content, {\n backgroundColor: null,\n foreignObjectRendering: true,\n height: bounds.height,\n logging: false,\n scale: options.width / bounds.width,\n useCORS: true,\n width: bounds.width,\n onclone: (_document, clonedContent) => {\n clonedContent.style.position = 'relative'\n clonedContent.style.inset = 'auto'\n clonedContent.style.width = `${bounds.width}px`\n clonedContent.style.height = `${bounds.height}px`\n clonedContent.style.transform = 'none'\n },\n })\n const effectImage = await dataUrlToImage(effectDataUrl)\n\n const output = document.createElement('canvas')\n output.width = options.width\n output.height = options.height\n const context = output.getContext('2d')\n if (!context) throw new Error('Failed to export Pocato image: canvas context is unavailable')\n context.drawImage(capturedFace, 0, 0, output.width, output.height)\n context.save()\n context.globalAlpha = Number(effectStyle.opacity)\n context.globalCompositeOperation = effectStyle.mixBlendMode === 'normal'\n ? 'source-over'\n : effectStyle.mixBlendMode as GlobalCompositeOperation\n context.drawImage(effectImage, 0, 0, output.width, output.height)\n context.restore()\n\n const format = options.format ?? 'png'\n return canvasToBlob(output, MIME_TYPES[format], options.quality)\n}\n\nfunction blobToDataUrl(blob: Blob): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader()\n reader.onload = () => {\n if (typeof reader.result === 'string') resolve(reader.result)\n else reject(new Error('Failed to export Pocato image: effect image could not be read'))\n }\n reader.onerror = () => reject(new Error('Failed to export Pocato image: effect image could not be read'))\n reader.readAsDataURL(blob)\n })\n}\n\nfunction dataUrlToImage(src: string): Promise<HTMLImageElement> {\n return new Promise((resolve, reject) => {\n const image = new Image()\n image.onload = () => resolve(image)\n image.onerror = () => reject(new Error('Failed to export Pocato image: effect image could not be decoded'))\n image.src = src\n })\n}\n\nfunction canvasToBlob(canvas: HTMLCanvasElement, type: string, quality?: number): Promise<Blob> {\n return new Promise((resolve, reject) => {\n canvas.toBlob((blob) => {\n if (blob) resolve(blob)\n else reject(new Error('Failed to export Pocato image: image encoding failed'))\n }, type, quality)\n })\n}\n","import type { FaceProps, PocaCardImagePreview } from './PocaCard'\n\nconst DEFAULT_API_BASE_URL = 'https://pocato-api.gamzabaw.workers.dev'\n\nexport type EffectParamValue = string | number | boolean\n\nexport interface EffectParamSchema {\n key: string\n label: string\n uniform: string\n type: 'number' | 'boolean' | 'color' | 'select'\n defaultValue: EffectParamValue\n min?: number\n max?: number\n step?: number\n options?: Array<{ label: string; value: EffectParamValue }>\n}\n\nexport interface PocaCardEffectConfig {\n id: string\n label: string\n shader: string\n minLayers: number\n params: Record<string, EffectParamValue>\n schema: EffectParamSchema[]\n customizedShader?: boolean\n}\n\nexport interface PocaCardFaceConfig extends Omit<FaceProps, 'content'> {\n effect?: PocaCardEffectConfig\n html?: string\n}\n\nexport interface PocaCardConfig {\n preview?: PocaCardImagePreview\n cardSize?: {\n width: number\n height: number\n preset?: string\n }\n front: PocaCardFaceConfig\n back?: PocaCardFaceConfig\n flippable?: boolean\n initialFlipped?: boolean\n flipSpeed?: number\n}\n\nexport interface PublishedConfigResponse {\n cardId: string\n releaseId: string\n config: PocaCardConfig\n}\n\nexport interface PocatoClientOptions {\n apiBaseUrl?: string\n publishableKey: string\n releaseId?: string | null\n}\n\nfunction getApiBaseUrl(apiBaseUrl?: string): string {\n return apiBaseUrl ?? DEFAULT_API_BASE_URL\n}\n\nexport async function fetchPublishedConfig(\n cardId: string,\n options: PocatoClientOptions,\n): Promise<PublishedConfigResponse> {\n const baseUrl = getApiBaseUrl(options.apiBaseUrl)\n const url = new URL(`${baseUrl}/api/v1/public/cards/${cardId}/config`)\n if (options.releaseId) url.searchParams.set('release', options.releaseId)\n const res = await fetch(url.toString(), {\n headers: {\n 'X-Pocato-Key': options.publishableKey,\n },\n })\n\n if (!res.ok) {\n throw new Error(`Failed to load Pocato card config: ${res.status}`)\n }\n\n return res.json()\n}\n\nexport async function trackCardEvent(\n cardId: string,\n options: PocatoClientOptions & { eventType: 'card_ready' | 'render_error' },\n): Promise<void> {\n const baseUrl = getApiBaseUrl(options.apiBaseUrl)\n await fetch(`${baseUrl}/api/v1/public/cards/${cardId}/events`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-Pocato-Key': options.publishableKey,\n },\n body: JSON.stringify({ eventType: options.eventType }),\n keepalive: true,\n }).catch(() => {\n // Usage metering must not break customer rendering.\n })\n}\n","import { useCallback, useEffect, useMemo, useState } from 'react'\nimport {\n fetchPublishedConfig,\n type PocatoClientOptions,\n type PocaCardConfig,\n type PublishedConfigResponse,\n} from './pocato-client'\n\nconst cache = new Map<string, PublishedConfigResponse>()\n\nexport function getPocatoConfigCacheKey(\n apiBaseUrl: string | undefined,\n publishableKey: string,\n cardId: string,\n releaseId?: string | null,\n): string {\n return `${apiBaseUrl ?? ''}:${publishableKey}:${cardId}:${releaseId ?? ''}`\n}\n\nexport interface UsePocatoConfigInput extends PocatoClientOptions {\n cardId: string\n}\n\nexport interface UsePocatoConfigResult {\n data: PublishedConfigResponse | null\n config: PocaCardConfig | null\n loading: boolean\n error: Error | null\n refetch: () => Promise<PublishedConfigResponse | null>\n}\n\nexport function usePocatoConfig(input: UsePocatoConfigInput): UsePocatoConfigResult {\n const cacheKey = useMemo(() => {\n return getPocatoConfigCacheKey(input.apiBaseUrl, input.publishableKey, input.cardId, input.releaseId)\n }, [input.apiBaseUrl, input.publishableKey, input.cardId, input.releaseId])\n\n const [data, setData] = useState<PublishedConfigResponse | null>(() => {\n return cache.get(cacheKey) ?? null\n })\n const [loading, setLoading] = useState(!data)\n const [error, setError] = useState<Error | null>(null)\n\n const load = useCallback(async (options?: { force?: boolean }) => {\n if (!options?.force) {\n const cached = cache.get(cacheKey)\n if (cached) {\n setData(cached)\n setLoading(false)\n setError(null)\n return cached\n }\n }\n\n setData(null)\n setLoading(true)\n setError(null)\n\n try {\n const response = await fetchPublishedConfig(input.cardId, {\n apiBaseUrl: input.apiBaseUrl,\n publishableKey: input.publishableKey,\n releaseId: input.releaseId,\n })\n cache.set(cacheKey, response)\n setData(response)\n setLoading(false)\n return response\n } catch (err) {\n const nextError = err instanceof Error ? err : new Error('Failed to load Pocato config')\n setError(nextError)\n setLoading(false)\n return null\n }\n }, [cacheKey, input.apiBaseUrl, input.cardId, input.publishableKey, input.releaseId])\n\n useEffect(() => {\n let cancelled = false\n const cached = cache.get(cacheKey)\n\n if (cached) {\n setData(cached)\n setLoading(false)\n setError(null)\n return\n }\n\n setData(null)\n setLoading(true)\n setError(null)\n\n fetchPublishedConfig(input.cardId, {\n apiBaseUrl: input.apiBaseUrl,\n publishableKey: input.publishableKey,\n releaseId: input.releaseId,\n })\n .then((response) => {\n if (cancelled) return\n cache.set(cacheKey, response)\n setData(response)\n setLoading(false)\n })\n .catch((err) => {\n if (cancelled) return\n setError(err instanceof Error ? err : new Error('Failed to load Pocato config'))\n setLoading(false)\n })\n\n return () => {\n cancelled = true\n }\n }, [cacheKey, input.apiBaseUrl, input.publishableKey, input.cardId, input.releaseId])\n\n return {\n data,\n config: data?.config ?? null,\n loading,\n error,\n refetch: () => load({ force: true }),\n }\n}\n"],"mappings":"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","names":["useEffect","useState","useEffect","useState"]}
|
|
1
|
+
{"version":3,"sources":["../src/PocaCard.tsx","../src/export-image.ts","../src/pocato-client.ts","../src/use-pocato-config.ts"],"sourcesContent":["import {\n forwardRef,\n useEffect,\n useImperativeHandle,\n useLayoutEffect,\n useRef,\n useState,\n type CSSProperties,\n type ForwardedRef,\n type ReactNode,\n} from 'react'\nimport { createPortal } from 'react-dom'\nimport { captureFaceWithEffect } from './export-image'\nimport {\n PocaCard as CorePocaCard,\n type EffectUniformValue,\n type ExportImageOptions,\n type FaceFrameOptions,\n type LayerSource,\n type PocaCardOptions,\n} from '@sangwonl/pocato-core'\nimport { trackCardEvent, type PocaCardConfig, type PocaCardEffectConfig } from './pocato-client'\nimport { usePocatoConfig } from './use-pocato-config'\n\nexport interface PocaCardHandle {\n flip(): void\n wiggle(): void\n reset(): void\n exportImage(options: PocaCardExportImageOptions): Promise<Blob>\n}\n\nexport interface PocaCardExportImageOptions extends ExportImageOptions {\n includeContent?: boolean\n}\n\nexport interface FaceProps {\n shader?: string\n uniforms?: Record<string, EffectUniformValue>\n frame?: FaceFrameOptions\n layers: LayerSource[]\n content?: ReactNode\n}\n\nexport interface PocaCardImagePreview {\n interaction?: 'block' | 'pass-through'\n src?: string\n backgroundColor?: string\n mode?: 'cover' | 'contain'\n blur?: boolean\n render?: never\n}\n\nexport interface PocaCardCustomPreview {\n interaction?: 'block' | 'pass-through'\n render: ReactNode\n}\n\nexport type PocaCardPreview = PocaCardImagePreview | PocaCardCustomPreview\n\ninterface CommonPocaCardProps {\n flippable?: boolean\n initialFlipped?: boolean\n flipSpeed?: number\n interactive?: boolean\n touchAction?: PocaCardOptions['touchAction']\n preventNativeScroll?: PocaCardOptions['preventNativeScroll']\n interactionScrollMode?: PocaCardOptions['interactionScrollMode']\n stopPointerPropagation?: PocaCardOptions['stopPointerPropagation']\n preventPointerDefault?: PocaCardOptions['preventPointerDefault']\n maxTiltDegrees?: number\n onRotate?: (rotate: { x: number; y: number }) => void\n onFlip?: (flipped: boolean) => void\n onReady?: () => void\n onFirstFrame?: () => void\n onError?: (error: Error) => void\n preview?: PocaCardPreview\n error?: ReactNode | ((error: Error) => ReactNode)\n style?: CSSProperties\n className?: string\n}\n\ninterface DirectPocaCardProps extends CommonPocaCardProps {\n front: FaceProps\n back?: FaceProps\n config?: never\n cardId?: never\n publishableKey?: never\n releaseId?: never\n apiBaseUrl?: never\n}\n\ninterface ConfigPocaCardProps extends CommonPocaCardProps {\n config: PocaCardConfig\n front?: Partial<FaceProps>\n back?: Partial<FaceProps>\n cardId?: never\n publishableKey?: never\n releaseId?: never\n apiBaseUrl?: never\n}\n\ninterface ConnectedPocaCardProps extends CommonPocaCardProps {\n cardId: string\n publishableKey: string\n releaseId?: string | null\n apiBaseUrl?: string\n front?: Partial<FaceProps>\n back?: Partial<FaceProps>\n config?: never\n}\n\nexport type PocaCardProps = DirectPocaCardProps | ConfigPocaCardProps | ConnectedPocaCardProps\n\ninterface ResolvedPocaCardProps extends CommonPocaCardProps {\n front: FaceProps\n back?: FaceProps\n}\n\nfunction isConnectedProps(props: PocaCardProps): props is ConnectedPocaCardProps {\n return typeof props.cardId === 'string' && typeof props.publishableKey === 'string'\n}\n\nfunction isConfigProps(props: PocaCardProps): props is ConfigPocaCardProps {\n return 'config' in props && props.config != null\n}\n\nfunction resolveConfigProps(\n config: PocaCardConfig,\n props: ConfigPocaCardProps | ConnectedPocaCardProps,\n): ResolvedPocaCardProps {\n return {\n ...props,\n front: {\n ...config.front,\n shader: config.front.effect?.shader ?? config.front.shader,\n uniforms: config.front.uniforms ?? getEffectUniforms(config.front.effect),\n frame: props.front?.frame ?? config.front.frame,\n content: props.front?.content,\n },\n back: config.back\n ? {\n ...config.back,\n shader: config.back.effect?.shader ?? config.back.shader,\n uniforms: config.back.uniforms ?? getEffectUniforms(config.back.effect),\n frame: props.back?.frame ?? config.back.frame,\n content: props.back?.content,\n }\n : props.back?.layers\n ? props.back as FaceProps\n : undefined,\n flippable: props.flippable ?? config.flippable,\n initialFlipped: props.initialFlipped ?? config.initialFlipped,\n flipSpeed: props.flipSpeed ?? config.flipSpeed,\n preview: props.preview ?? config.preview,\n }\n}\n\nfunction getEffectUniforms(effect?: PocaCardEffectConfig) {\n if (!effect) return undefined\n return Object.fromEntries(\n effect.schema.map((item) => [\n item.uniform,\n effect.params[item.key] ?? item.defaultValue,\n ]),\n )\n}\n\nfunction renderError(errorView: CommonPocaCardProps['error'], error: Error) {\n if (typeof errorView === 'function') return errorView(error)\n return errorView ?? null\n}\n\nfunction renderPreview(preview?: PocaCardPreview) {\n if (!preview) return null\n if ('render' in preview && preview.render) return preview.render\n\n const imagePreview = preview as PocaCardImagePreview\n const backgroundColor = imagePreview.backgroundColor ?? '#f3f4f6'\n return (\n <div\n style={{\n width: '100%',\n height: '100%',\n overflow: 'hidden',\n borderRadius: '2%',\n background: backgroundColor,\n }}\n >\n {imagePreview.src ? (\n <img\n src={imagePreview.src}\n alt=\"\"\n draggable={false}\n style={{\n width: '100%',\n height: '100%',\n objectFit: imagePreview.mode ?? 'cover',\n filter: imagePreview.blur ? 'blur(12px)' : undefined,\n transform: imagePreview.blur ? 'scale(1.04)' : undefined,\n }}\n />\n ) : null}\n </div>\n )\n}\n\nfunction ConnectedPocaCard(\n props: ConnectedPocaCardProps,\n ref: ForwardedRef<PocaCardHandle>,\n) {\n const { config, loading, error } = usePocatoConfig({\n cardId: props.cardId,\n publishableKey: props.publishableKey,\n releaseId: props.releaseId,\n apiBaseUrl: props.apiBaseUrl,\n })\n const readyTracked = useRef(false)\n\n useEffect(() => {\n if (error && !props.error) {\n props.onError?.(error)\n }\n }, [error, props.error, props.onError])\n\n if (error) {\n return renderError(props.error, error)\n }\n\n if (loading || !config) {\n return renderPreview(props.preview)\n }\n\n const resolved = resolveConfigProps(config, {\n ...props,\n onFirstFrame: () => {\n if (!readyTracked.current) {\n readyTracked.current = true\n void trackCardEvent(props.cardId, {\n apiBaseUrl: props.apiBaseUrl,\n publishableKey: props.publishableKey,\n eventType: 'card_ready',\n })\n }\n props.onFirstFrame?.()\n },\n onError: (runtimeError) => {\n void trackCardEvent(props.cardId, {\n apiBaseUrl: props.apiBaseUrl,\n publishableKey: props.publishableKey,\n eventType: 'render_error',\n })\n props.onError?.(runtimeError)\n },\n })\n\n return <PocaCardRenderer props={resolved} refHandle={ref} />\n}\n\nfunction PocaCardRenderer({\n props,\n refHandle,\n}: {\n props: ResolvedPocaCardProps\n refHandle: ForwardedRef<PocaCardHandle>\n}) {\n const containerRef = useRef<HTMLDivElement>(null)\n const cardRef = useRef<CorePocaCard | null>(null)\n const [runtimeReady, setRuntimeReady] = useState(false)\n const [portalTargets, setPortalTargets] = useState<{\n front: HTMLElement | null\n back: HTMLElement | null\n }>({ front: null, back: null })\n const layersMounted = useRef(false)\n\n useLayoutEffect(() => {\n if (!containerRef.current) return\n\n layersMounted.current = false\n setRuntimeReady(false)\n const card = new CorePocaCard(containerRef.current, {\n front: { shader: props.front.shader, uniforms: props.front.uniforms, frame: props.front.frame, layers: props.front.layers },\n back: props.back ? { shader: props.back.shader, uniforms: props.back.uniforms, frame: props.back.frame, layers: props.back.layers } : undefined,\n flippable: props.flippable,\n initialFlipped: props.initialFlipped,\n flipSpeed: props.flipSpeed,\n interactive: props.interactive,\n touchAction: props.touchAction,\n preventNativeScroll: props.preventNativeScroll,\n interactionScrollMode: props.interactionScrollMode,\n stopPointerPropagation: props.stopPointerPropagation,\n preventPointerDefault: props.preventPointerDefault,\n maxTiltDegrees: props.maxTiltDegrees,\n onRotate: props.onRotate,\n })\n\n cardRef.current = card\n setPortalTargets({\n front: card.getFrontContentEl(),\n back: card.getBackContentEl(),\n })\n\n return () => {\n card.destroy()\n cardRef.current = null\n setPortalTargets({ front: null, back: null })\n }\n // Re-create when shader config changes\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [props.front.shader, props.back?.shader])\n\n const frontLayersKey = JSON.stringify(props.front.layers)\n const backLayersKey = JSON.stringify(props.back?.layers)\n useEffect(() => {\n if (!layersMounted.current) {\n layersMounted.current = true\n return\n }\n cardRef.current?.updateOptions({\n front: { layers: props.front.layers },\n back: props.back ? { layers: props.back.layers } : undefined,\n })\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [frontLayersKey, backLayersKey])\n\n useEffect(() => {\n if (props.flipSpeed != null) {\n cardRef.current?.updateOptions({ flipSpeed: props.flipSpeed })\n }\n }, [props.flipSpeed])\n\n const frontUniformsKey = JSON.stringify(props.front.uniforms ?? {})\n const backUniformsKey = JSON.stringify(props.back?.uniforms ?? {})\n useEffect(() => {\n cardRef.current?.updateOptions({\n front: { uniforms: props.front.uniforms },\n back: props.back ? { uniforms: props.back.uniforms } : undefined,\n })\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [frontUniformsKey, backUniformsKey])\n\n const frontFrameKey = JSON.stringify(props.front.frame ?? {})\n const backFrameKey = JSON.stringify(props.back?.frame ?? {})\n useEffect(() => {\n cardRef.current?.updateOptions({\n front: { frame: props.front.frame },\n back: props.back ? { frame: props.back.frame } : undefined,\n })\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [frontFrameKey, backFrameKey])\n\n useEffect(() => {\n const card = cardRef.current\n if (!card) return\n\n const onFlip = props.onFlip\n const onReady = props.onReady\n const onFirstFrame = props.onFirstFrame\n const onError = props.onError\n const handleFirstFrame = () => {\n setRuntimeReady(true)\n onFirstFrame?.()\n }\n\n if (onFlip) card.on('flip', onFlip)\n if (onReady) card.on('ready', onReady)\n card.on('firstFrame', handleFirstFrame)\n if (onError) card.on('error', onError)\n\n return () => {\n if (onFlip) card.off('flip', onFlip)\n if (onReady) card.off('ready', onReady)\n card.off('firstFrame', handleFirstFrame)\n if (onError) card.off('error', onError)\n }\n }, [props.onFlip, props.onReady, props.onFirstFrame, props.onError])\n\n useImperativeHandle(refHandle, () => ({\n flip: () => cardRef.current?.flip(),\n wiggle: () => cardRef.current?.wiggle(),\n reset: () => cardRef.current?.reset(),\n exportImage: async (options) => {\n const card = cardRef.current\n if (!card) {\n return Promise.reject(new Error('Failed to export Pocato image: card is not mounted'))\n }\n\n const { includeContent = false, ...renderOptions } = options\n const effect = await card.exportImage(renderOptions)\n if (!includeContent) return effect\n\n const content = renderOptions.face === 'back' ? portalTargets.back : portalTargets.front\n const face = content?.parentElement\n const effectLayer = face?.firstElementChild\n if (!content || !effectLayer || !['CANVAS', 'IMG'].includes(effectLayer.tagName)) {\n throw new Error('Failed to export Pocato image: card face is not mounted')\n }\n\n return captureFaceWithEffect(content, effectLayer, effect, renderOptions)\n },\n }))\n\n const preview = renderPreview(props.preview)\n const previewPointerEvents: CSSProperties['pointerEvents'] =\n props.preview?.interaction === 'pass-through' ? 'none' : undefined\n\n return (\n <div\n style={{\n ...props.style,\n position: props.style?.position ?? 'relative',\n }}\n className={props.className}\n >\n <div\n ref={containerRef}\n style={{\n position: 'absolute',\n inset: 0,\n }}\n />\n {!runtimeReady && preview ? (\n <div\n aria-hidden=\"true\"\n style={{\n position: 'absolute',\n inset: 0,\n zIndex: 1,\n pointerEvents: previewPointerEvents,\n }}\n >\n {preview}\n </div>\n ) : null}\n {portalTargets.front && props.front.content && createPortal(props.front.content, portalTargets.front)}\n {portalTargets.back && props.back?.content && createPortal(props.back.content, portalTargets.back)}\n </div>\n )\n}\n\nexport const PocaCard = forwardRef<PocaCardHandle, PocaCardProps>(\n (props, ref) => {\n if (isConnectedProps(props)) {\n return ConnectedPocaCard(props, ref)\n }\n\n const resolved = isConfigProps(props) ? resolveConfigProps(props.config, props) : props\n return <PocaCardRenderer props={resolved} refHandle={ref} />\n },\n)\n\nPocaCard.displayName = 'PocaCard'\n","import type { ExportImageOptions } from '@sangwonl/pocato-core'\n\nconst MIME_TYPES: Record<NonNullable<ExportImageOptions['format']>, string> = {\n png: 'image/png',\n webp: 'image/webp',\n jpeg: 'image/jpeg',\n}\n\nexport async function captureFaceWithEffect(\n content: HTMLElement,\n effectLayer: Element,\n effect: Blob,\n options: ExportImageOptions,\n): Promise<Blob> {\n await document.fonts?.ready\n await Promise.all(\n Array.from(content.querySelectorAll('img'), (image) => image.decode?.().catch(() => undefined)),\n )\n\n const width = content.offsetWidth\n const height = content.offsetHeight\n if (!width || !height) {\n throw new Error('Failed to export Pocato image: card face has no size')\n }\n\n const effectStyle = window.getComputedStyle(effectLayer)\n\n const [capturedFace, effectImage] = await Promise.all([\n captureHtml(content, width, height, options),\n blobToDataUrl(effect).then(dataUrlToImage),\n ])\n\n const output = document.createElement('canvas')\n output.width = options.width\n output.height = options.height\n const context = output.getContext('2d')\n if (!context) throw new Error('Failed to export Pocato image: canvas context is unavailable')\n const faceStyle = getComputedStyle(content.parentElement ?? content)\n const radius = (value: string, size: number) => value.endsWith('%')\n ? parseFloat(value) * size / 100\n : parseFloat(value)\n const corners = [\n faceStyle.borderTopLeftRadius, faceStyle.borderTopRightRadius,\n faceStyle.borderBottomRightRadius, faceStyle.borderBottomLeftRadius,\n ].map((value) => {\n const [horizontal, vertical = horizontal] = value.split(/\\s+/)\n return {\n x: radius(horizontal, width) * options.width / width,\n y: radius(vertical, height) * options.height / height,\n }\n })\n context.beginPath()\n context.roundRect(0, 0, output.width, output.height, corners)\n context.clip()\n context.drawImage(capturedFace, 0, 0, output.width, output.height)\n context.save()\n context.globalAlpha = Number(effectStyle.opacity)\n context.globalCompositeOperation = effectStyle.mixBlendMode === 'normal'\n ? 'source-over'\n : effectStyle.mixBlendMode as GlobalCompositeOperation\n context.drawImage(effectImage, 0, 0, output.width, output.height)\n context.restore()\n\n const format = options.format ?? 'png'\n return canvasToBlob(output, MIME_TYPES[format], options.quality)\n}\n\nasync function captureHtml(\n content: HTMLElement,\n width: number,\n height: number,\n options: ExportImageOptions,\n): Promise<HTMLImageElement> {\n const resources = new Map<string, Promise<string>>()\n const inlineResource = (src: string) => {\n if (src.startsWith('data:')) return Promise.resolve(src)\n const url = new URL(src, document.baseURI).href\n let pending = resources.get(url)\n if (!pending) {\n pending = fetch(url).then(async (response) => {\n if (!response.ok) throw new Error(`Failed to export Pocato image: resource returned ${response.status}`)\n return blobToDataUrl(await response.blob())\n })\n resources.set(url, pending)\n }\n return pending\n }\n const pseudoRules: string[] = []\n let nodeId = 0\n\n async function cloneElement(source: Element): Promise<Element> {\n const clone = source.cloneNode(false) as HTMLElement\n const id = String(nodeId++)\n clone.setAttribute('data-pocato-export-node', id)\n const computed = getComputedStyle(source)\n clone.setAttribute('style', serializeStyle(computed))\n if (source instanceof HTMLElement && source.children.length === 0 && source.textContent?.trim()) {\n const oneLineHeight = parseFloat(computed.lineHeight) + parseFloat(computed.paddingTop) + parseFloat(computed.paddingBottom)\n if (source.clientHeight <= oneLineHeight + 1 && source.scrollWidth <= source.clientWidth) {\n clone.style.whiteSpace = 'nowrap'\n clone.style.overflow = 'visible'\n clone.style.textOverflow = 'clip'\n }\n }\n for (const pseudo of ['::before', '::after']) {\n const style = getComputedStyle(source, pseudo)\n if (style.content !== 'none' && style.content !== 'normal') {\n pseudoRules.push(`[data-pocato-export-node=\"${id}\"]${pseudo}{${serializeStyle(style)}}`)\n }\n }\n if (source instanceof HTMLImageElement) {\n clone.removeAttribute('srcset')\n clone.removeAttribute('sizes')\n clone.removeAttribute('loading')\n // Reuse the decoded image: re-fetching responsive URLs can negotiate JPEG\n // and discard transparency that was present in the live image.\n const canvas = document.createElement('canvas')\n canvas.width = source.naturalWidth\n canvas.height = source.naturalHeight\n const context = canvas.getContext('2d')\n if (!context) throw new Error('Failed to export Pocato image: image canvas is unavailable')\n context.drawImage(source, 0, 0)\n clone.setAttribute('src', canvas.toDataURL('image/png'))\n }\n for (const child of Array.from(source.childNodes)) {\n clone.append(child instanceof Element ? await cloneElement(child) : child.cloneNode(true))\n }\n return clone\n }\n\n // Browser-native HTML rendering preserves transforms, masks, and text metrics.\n const [clone, fontCss] = await Promise.all([\n cloneElement(content) as Promise<HTMLElement>,\n embedLoadedFonts(inlineResource),\n ])\n Object.assign(clone.style, {\n position: 'relative', inset: 'auto', left: '0', top: '0', margin: '0',\n width: `${width}px`, height: `${height}px`, transform: 'none',\n })\n const style = document.createElement('style')\n style.textContent = `${fontCss}\\n${pseudoRules.join('\\n')}`\n clone.prepend(style)\n clone.setAttribute('xmlns', 'http://www.w3.org/1999/xhtml')\n const markup = new XMLSerializer().serializeToString(clone)\n const svg = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${options.width}\" height=\"${options.height}\" viewBox=\"0 0 ${width} ${height}\"><foreignObject width=\"100%\" height=\"100%\">${markup}</foreignObject></svg>`\n return dataUrlToImage(`data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`)\n}\n\nfunction serializeStyle(style: CSSStyleDeclaration): string {\n return Array.from(style, (name) => `${name}:${style.getPropertyValue(name)};`).join('')\n}\n\nasync function embedLoadedFonts(inlineResource: (src: string) => Promise<string>): Promise<string> {\n const loaded: FontFace[] = []\n document.fonts?.forEach((font) => { if (font.status === 'loaded') loaded.push(font) })\n const rules: CSSFontFaceRule[] = []\n function collect(sheet: CSSStyleSheet) {\n let sheetRules: CSSRuleList\n try { sheetRules = sheet.cssRules } catch { return }\n for (const rule of Array.from(sheetRules)) {\n if (rule instanceof CSSFontFaceRule) rules.push(rule)\n else if (rule instanceof CSSImportRule && rule.styleSheet) collect(rule.styleSheet)\n }\n }\n Array.from(document.styleSheets).forEach(collect)\n const normalize = (value: string) => value.replace(/[\"'\\s]/g, '').toLowerCase()\n const selected = rules.filter((rule) => loaded.some((font) =>\n normalize(font.family) === normalize(rule.style.getPropertyValue('font-family')) &&\n normalize(font.unicodeRange) === normalize(rule.style.getPropertyValue('unicode-range') || 'U+0-10FFFF'),\n ))\n return (await Promise.all(selected.map(async (rule) => {\n let css = rule.cssText\n const urls = Array.from(css.matchAll(/url\\(\\s*['\"]?([^'\"\\)]+)['\"]?\\s*\\)/g))\n for (const match of urls) {\n const url = new URL(match[1], rule.parentStyleSheet?.href || document.baseURI).href\n css = css.replace(match[0], `url(\"${await inlineResource(url)}\")`)\n }\n return css\n }))).join('\\n')\n}\n\nfunction blobToDataUrl(blob: Blob): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader()\n reader.onload = () => {\n if (typeof reader.result === 'string') resolve(reader.result)\n else reject(new Error('Failed to export Pocato image: effect image could not be read'))\n }\n reader.onerror = () => reject(new Error('Failed to export Pocato image: effect image could not be read'))\n reader.readAsDataURL(blob)\n })\n}\n\nfunction dataUrlToImage(src: string): Promise<HTMLImageElement> {\n return new Promise((resolve, reject) => {\n const image = new Image()\n image.onload = () => resolve(image)\n image.onerror = () => reject(new Error('Failed to export Pocato image: effect image could not be decoded'))\n image.src = src\n })\n}\n\nfunction canvasToBlob(canvas: HTMLCanvasElement, type: string, quality?: number): Promise<Blob> {\n return new Promise((resolve, reject) => {\n canvas.toBlob((blob) => {\n if (blob) resolve(blob)\n else reject(new Error('Failed to export Pocato image: image encoding failed'))\n }, type, quality)\n })\n}\n","import type { FaceProps, PocaCardImagePreview } from './PocaCard'\n\nconst DEFAULT_API_BASE_URL = 'https://pocato-api.gamzabaw.workers.dev'\n\nexport type EffectParamValue = string | number | boolean\n\nexport interface EffectParamSchema {\n key: string\n label: string\n uniform: string\n type: 'number' | 'boolean' | 'color' | 'select'\n defaultValue: EffectParamValue\n min?: number\n max?: number\n step?: number\n options?: Array<{ label: string; value: EffectParamValue }>\n}\n\nexport interface PocaCardEffectConfig {\n id: string\n label: string\n shader: string\n minLayers: number\n params: Record<string, EffectParamValue>\n schema: EffectParamSchema[]\n customizedShader?: boolean\n}\n\nexport interface PocaCardFaceConfig extends Omit<FaceProps, 'content'> {\n effect?: PocaCardEffectConfig\n html?: string\n}\n\nexport interface PocaCardConfig {\n preview?: PocaCardImagePreview\n cardSize?: {\n width: number\n height: number\n preset?: string\n }\n front: PocaCardFaceConfig\n back?: PocaCardFaceConfig\n flippable?: boolean\n initialFlipped?: boolean\n flipSpeed?: number\n}\n\nexport interface PublishedConfigResponse {\n cardId: string\n releaseId: string\n config: PocaCardConfig\n}\n\nexport interface PocatoClientOptions {\n apiBaseUrl?: string\n publishableKey: string\n releaseId?: string | null\n}\n\nfunction getApiBaseUrl(apiBaseUrl?: string): string {\n return apiBaseUrl ?? DEFAULT_API_BASE_URL\n}\n\nexport async function fetchPublishedConfig(\n cardId: string,\n options: PocatoClientOptions,\n): Promise<PublishedConfigResponse> {\n const baseUrl = getApiBaseUrl(options.apiBaseUrl)\n const url = new URL(`${baseUrl}/api/v1/public/cards/${cardId}/config`)\n if (options.releaseId) url.searchParams.set('release', options.releaseId)\n const res = await fetch(url.toString(), {\n headers: {\n 'X-Pocato-Key': options.publishableKey,\n },\n })\n\n if (!res.ok) {\n throw new Error(`Failed to load Pocato card config: ${res.status}`)\n }\n\n return res.json()\n}\n\nexport async function trackCardEvent(\n cardId: string,\n options: PocatoClientOptions & { eventType: 'card_ready' | 'render_error' },\n): Promise<void> {\n const baseUrl = getApiBaseUrl(options.apiBaseUrl)\n await fetch(`${baseUrl}/api/v1/public/cards/${cardId}/events`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-Pocato-Key': options.publishableKey,\n },\n body: JSON.stringify({ eventType: options.eventType }),\n keepalive: true,\n }).catch(() => {\n // Usage metering must not break customer rendering.\n })\n}\n","import { useCallback, useEffect, useMemo, useState } from 'react'\nimport {\n fetchPublishedConfig,\n type PocatoClientOptions,\n type PocaCardConfig,\n type PublishedConfigResponse,\n} from './pocato-client'\n\nconst cache = new Map<string, PublishedConfigResponse>()\n\nexport function getPocatoConfigCacheKey(\n apiBaseUrl: string | undefined,\n publishableKey: string,\n cardId: string,\n releaseId?: string | null,\n): string {\n return `${apiBaseUrl ?? ''}:${publishableKey}:${cardId}:${releaseId ?? ''}`\n}\n\nexport interface UsePocatoConfigInput extends PocatoClientOptions {\n cardId: string\n}\n\nexport interface UsePocatoConfigResult {\n data: PublishedConfigResponse | null\n config: PocaCardConfig | null\n loading: boolean\n error: Error | null\n refetch: () => Promise<PublishedConfigResponse | null>\n}\n\nexport function usePocatoConfig(input: UsePocatoConfigInput): UsePocatoConfigResult {\n const cacheKey = useMemo(() => {\n return getPocatoConfigCacheKey(input.apiBaseUrl, input.publishableKey, input.cardId, input.releaseId)\n }, [input.apiBaseUrl, input.publishableKey, input.cardId, input.releaseId])\n\n const [data, setData] = useState<PublishedConfigResponse | null>(() => {\n return cache.get(cacheKey) ?? null\n })\n const [loading, setLoading] = useState(!data)\n const [error, setError] = useState<Error | null>(null)\n\n const load = useCallback(async (options?: { force?: boolean }) => {\n if (!options?.force) {\n const cached = cache.get(cacheKey)\n if (cached) {\n setData(cached)\n setLoading(false)\n setError(null)\n return cached\n }\n }\n\n setData(null)\n setLoading(true)\n setError(null)\n\n try {\n const response = await fetchPublishedConfig(input.cardId, {\n apiBaseUrl: input.apiBaseUrl,\n publishableKey: input.publishableKey,\n releaseId: input.releaseId,\n })\n cache.set(cacheKey, response)\n setData(response)\n setLoading(false)\n return response\n } catch (err) {\n const nextError = err instanceof Error ? err : new Error('Failed to load Pocato config')\n setError(nextError)\n setLoading(false)\n return null\n }\n }, [cacheKey, input.apiBaseUrl, input.cardId, input.publishableKey, input.releaseId])\n\n useEffect(() => {\n let cancelled = false\n const cached = cache.get(cacheKey)\n\n if (cached) {\n setData(cached)\n setLoading(false)\n setError(null)\n return\n }\n\n setData(null)\n setLoading(true)\n setError(null)\n\n fetchPublishedConfig(input.cardId, {\n apiBaseUrl: input.apiBaseUrl,\n publishableKey: input.publishableKey,\n releaseId: input.releaseId,\n })\n .then((response) => {\n if (cancelled) return\n cache.set(cacheKey, response)\n setData(response)\n setLoading(false)\n })\n .catch((err) => {\n if (cancelled) return\n setError(err instanceof Error ? err : new Error('Failed to load Pocato config'))\n setLoading(false)\n })\n\n return () => {\n cancelled = true\n }\n }, [cacheKey, input.apiBaseUrl, input.publishableKey, input.cardId, input.releaseId])\n\n return {\n data,\n config: data?.config ?? null,\n loading,\n error,\n refetch: () => load({ force: true }),\n }\n}\n"],"mappings":"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","names":["useEffect","useState","clone","style","useEffect","useState"]}
|