@sangwonl/pocato-react 0.4.1 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +30 -1
- package/dist/index.js +36 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,33 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode, CSSProperties } from 'react';
|
|
3
|
-
import { LayerSource } from '@sangwonl/pocato-core';
|
|
3
|
+
import { EffectUniformValue, FaceFrameOptions, LayerSource } from '@sangwonl/pocato-core';
|
|
4
4
|
|
|
5
|
+
type EffectParamValue = string | number | boolean;
|
|
6
|
+
interface EffectParamSchema {
|
|
7
|
+
key: string;
|
|
8
|
+
label: string;
|
|
9
|
+
uniform: string;
|
|
10
|
+
type: 'number' | 'boolean' | 'color' | 'select';
|
|
11
|
+
defaultValue: EffectParamValue;
|
|
12
|
+
min?: number;
|
|
13
|
+
max?: number;
|
|
14
|
+
step?: number;
|
|
15
|
+
options?: Array<{
|
|
16
|
+
label: string;
|
|
17
|
+
value: EffectParamValue;
|
|
18
|
+
}>;
|
|
19
|
+
}
|
|
20
|
+
interface PocaCardEffectConfig {
|
|
21
|
+
id: string;
|
|
22
|
+
label: string;
|
|
23
|
+
shader: string;
|
|
24
|
+
minLayers: number;
|
|
25
|
+
params: Record<string, EffectParamValue>;
|
|
26
|
+
schema: EffectParamSchema[];
|
|
27
|
+
customizedShader?: boolean;
|
|
28
|
+
}
|
|
5
29
|
interface PocaCardFaceConfig extends Omit<FaceProps, 'content'> {
|
|
30
|
+
effect?: PocaCardEffectConfig;
|
|
6
31
|
html?: string;
|
|
7
32
|
}
|
|
8
33
|
interface PocaCardConfig {
|
|
@@ -34,6 +59,8 @@ interface PocaCardHandle {
|
|
|
34
59
|
}
|
|
35
60
|
interface FaceProps {
|
|
36
61
|
shader?: string;
|
|
62
|
+
uniforms?: Record<string, EffectUniformValue>;
|
|
63
|
+
frame?: FaceFrameOptions;
|
|
37
64
|
layers: LayerSource[];
|
|
38
65
|
content?: ReactNode;
|
|
39
66
|
}
|
|
@@ -41,6 +68,8 @@ interface CommonPocaCardProps {
|
|
|
41
68
|
flippable?: boolean;
|
|
42
69
|
initialFlipped?: boolean;
|
|
43
70
|
flipSpeed?: number;
|
|
71
|
+
interactive?: boolean;
|
|
72
|
+
preventTouchScroll?: boolean;
|
|
44
73
|
onFlip?: (flipped: boolean) => void;
|
|
45
74
|
onReady?: () => void;
|
|
46
75
|
onError?: (error: Error) => void;
|
package/dist/index.js
CHANGED
|
@@ -137,10 +137,16 @@ function resolveConfigProps(config, props) {
|
|
|
137
137
|
...props,
|
|
138
138
|
front: {
|
|
139
139
|
...config.front,
|
|
140
|
+
shader: config.front.effect?.shader ?? config.front.shader,
|
|
141
|
+
uniforms: config.front.uniforms ?? getEffectUniforms(config.front.effect),
|
|
142
|
+
frame: props.front?.frame ?? config.front.frame,
|
|
140
143
|
content: props.front?.content
|
|
141
144
|
},
|
|
142
145
|
back: config.back ? {
|
|
143
146
|
...config.back,
|
|
147
|
+
shader: config.back.effect?.shader ?? config.back.shader,
|
|
148
|
+
uniforms: config.back.uniforms ?? getEffectUniforms(config.back.effect),
|
|
149
|
+
frame: props.back?.frame ?? config.back.frame,
|
|
144
150
|
content: props.back?.content
|
|
145
151
|
} : props.back?.layers ? props.back : void 0,
|
|
146
152
|
flippable: props.flippable ?? config.flippable,
|
|
@@ -148,6 +154,15 @@ function resolveConfigProps(config, props) {
|
|
|
148
154
|
flipSpeed: props.flipSpeed ?? config.flipSpeed
|
|
149
155
|
};
|
|
150
156
|
}
|
|
157
|
+
function getEffectUniforms(effect) {
|
|
158
|
+
if (!effect) return void 0;
|
|
159
|
+
return Object.fromEntries(
|
|
160
|
+
effect.schema.map((item) => [
|
|
161
|
+
item.uniform,
|
|
162
|
+
effect.params[item.key] ?? item.defaultValue
|
|
163
|
+
])
|
|
164
|
+
);
|
|
165
|
+
}
|
|
151
166
|
function renderErrorFallback(errorFallback, error) {
|
|
152
167
|
if (typeof errorFallback === "function") return errorFallback(error);
|
|
153
168
|
return errorFallback ?? null;
|
|
@@ -204,11 +219,13 @@ function PocaCardRenderer({
|
|
|
204
219
|
useEffect2(() => {
|
|
205
220
|
if (!containerRef.current) return;
|
|
206
221
|
const card = new CorePocaCard(containerRef.current, {
|
|
207
|
-
front: { shader: props.front.shader, layers: props.front.layers },
|
|
208
|
-
back: props.back ? { shader: props.back.shader, layers: props.back.layers } : void 0,
|
|
222
|
+
front: { shader: props.front.shader, uniforms: props.front.uniforms, frame: props.front.frame, layers: props.front.layers },
|
|
223
|
+
back: props.back ? { shader: props.back.shader, uniforms: props.back.uniforms, frame: props.back.frame, layers: props.back.layers } : void 0,
|
|
209
224
|
flippable: props.flippable,
|
|
210
225
|
initialFlipped: props.initialFlipped,
|
|
211
|
-
flipSpeed: props.flipSpeed
|
|
226
|
+
flipSpeed: props.flipSpeed,
|
|
227
|
+
interactive: props.interactive,
|
|
228
|
+
preventTouchScroll: props.preventTouchScroll
|
|
212
229
|
});
|
|
213
230
|
cardRef.current = card;
|
|
214
231
|
setPortalTargets({
|
|
@@ -239,6 +256,22 @@ function PocaCardRenderer({
|
|
|
239
256
|
cardRef.current?.updateOptions({ flipSpeed: props.flipSpeed });
|
|
240
257
|
}
|
|
241
258
|
}, [props.flipSpeed]);
|
|
259
|
+
const frontUniformsKey = JSON.stringify(props.front.uniforms ?? {});
|
|
260
|
+
const backUniformsKey = JSON.stringify(props.back?.uniforms ?? {});
|
|
261
|
+
useEffect2(() => {
|
|
262
|
+
cardRef.current?.updateOptions({
|
|
263
|
+
front: { uniforms: props.front.uniforms },
|
|
264
|
+
back: props.back ? { uniforms: props.back.uniforms } : void 0
|
|
265
|
+
});
|
|
266
|
+
}, [frontUniformsKey, backUniformsKey]);
|
|
267
|
+
const frontFrameKey = JSON.stringify(props.front.frame ?? {});
|
|
268
|
+
const backFrameKey = JSON.stringify(props.back?.frame ?? {});
|
|
269
|
+
useEffect2(() => {
|
|
270
|
+
cardRef.current?.updateOptions({
|
|
271
|
+
front: { frame: props.front.frame },
|
|
272
|
+
back: props.back ? { frame: props.back.frame } : void 0
|
|
273
|
+
});
|
|
274
|
+
}, [frontFrameKey, backFrameKey]);
|
|
242
275
|
useEffect2(() => {
|
|
243
276
|
const card = cardRef.current;
|
|
244
277
|
if (!card) return;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/PocaCard.tsx","../src/pocato-client.ts","../src/use-pocato-config.ts"],"sourcesContent":["import {\n forwardRef,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n type CSSProperties,\n type ForwardedRef,\n type ReactNode,\n} from 'react'\nimport { createPortal } from 'react-dom'\nimport {\n PocaCard as CorePocaCard,\n type LayerSource,\n} from '@sangwonl/pocato-core'\nimport { trackCardEvent, type PocaCardConfig } from './pocato-client'\nimport { usePocatoConfig } from './use-pocato-config'\n\nexport interface PocaCardHandle {\n flip(): void\n wiggle(): void\n reset(): void\n}\n\nexport interface FaceProps {\n shader?: string\n layers: LayerSource[]\n content?: ReactNode\n}\n\ninterface CommonPocaCardProps {\n flippable?: boolean\n initialFlipped?: boolean\n flipSpeed?: number\n onFlip?: (flipped: boolean) => void\n onReady?: () => void\n onError?: (error: Error) => void\n loadingFallback?: ReactNode\n errorFallback?: 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 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 apiBaseUrl?: never\n}\n\ninterface ConnectedPocaCardProps extends CommonPocaCardProps {\n cardId: string\n publishableKey: string\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 content: props.front?.content,\n },\n back: config.back\n ? {\n ...config.back,\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 }\n}\n\nfunction renderErrorFallback(errorFallback: CommonPocaCardProps['errorFallback'], error: Error) {\n if (typeof errorFallback === 'function') return errorFallback(error)\n return errorFallback ?? null\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 apiBaseUrl: props.apiBaseUrl,\n })\n const readyTracked = useRef(false)\n\n useEffect(() => {\n if (error && !props.errorFallback) {\n props.onError?.(error)\n }\n }, [error, props.errorFallback, props.onError])\n\n if (error) {\n return renderErrorFallback(props.errorFallback, error)\n }\n\n if (loading || !config) {\n return props.loadingFallback ?? null\n }\n\n const resolved = resolveConfigProps(config, {\n ...props,\n onReady: () => {\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.onReady?.()\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 [portalTargets, setPortalTargets] = useState<{\n front: HTMLElement | null\n back: HTMLElement | null\n }>({ front: null, back: null })\n\n useEffect(() => {\n if (!containerRef.current) return\n\n const card = new CorePocaCard(containerRef.current, {\n front: { shader: props.front.shader, layers: props.front.layers },\n back: props.back ? { shader: props.back.shader, layers: props.back.layers } : undefined,\n flippable: props.flippable,\n initialFlipped: props.initialFlipped,\n flipSpeed: props.flipSpeed,\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 const layersMounted = useRef(false)\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 useEffect(() => {\n const card = cardRef.current\n if (!card) return\n\n const onFlip = props.onFlip\n const onReady = props.onReady\n const onError = props.onError\n\n if (onFlip) card.on('flip', onFlip)\n if (onReady) card.on('ready', onReady)\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 if (onError) card.off('error', onError)\n }\n }, [props.onFlip, props.onReady, props.onError])\n\n useImperativeHandle(refHandle, () => ({\n flip: () => cardRef.current?.flip(),\n wiggle: () => cardRef.current?.wiggle(),\n reset: () => cardRef.current?.reset(),\n }))\n\n return (\n <div\n ref={containerRef}\n style={props.style}\n className={props.className}\n >\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 { FaceProps } from './PocaCard'\n\nconst DEFAULT_API_BASE_URL = 'https://pocato-api.gamzabaw.workers.dev'\n\nexport interface PocaCardFaceConfig extends Omit<FaceProps, 'content'> {\n html?: string\n}\n\nexport interface PocaCardConfig {\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}\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 res = await fetch(`${baseUrl}/api/v1/public/cards/${cardId}/config`, {\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): string {\n return `${apiBaseUrl ?? ''}:${publishableKey}:${cardId}`\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)\n }, [input.apiBaseUrl, input.publishableKey, input.cardId])\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 })\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])\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 })\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])\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/pocato-client.ts","../src/use-pocato-config.ts"],"sourcesContent":["import {\n forwardRef,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n type CSSProperties,\n type ForwardedRef,\n type ReactNode,\n} from 'react'\nimport { createPortal } from 'react-dom'\nimport {\n PocaCard as CorePocaCard,\n type EffectUniformValue,\n type FaceFrameOptions,\n type LayerSource,\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}\n\nexport interface FaceProps {\n shader?: string\n uniforms?: Record<string, EffectUniformValue>\n frame?: FaceFrameOptions\n layers: LayerSource[]\n content?: ReactNode\n}\n\ninterface CommonPocaCardProps {\n flippable?: boolean\n initialFlipped?: boolean\n flipSpeed?: number\n interactive?: boolean\n preventTouchScroll?: boolean\n onFlip?: (flipped: boolean) => void\n onReady?: () => void\n onError?: (error: Error) => void\n loadingFallback?: ReactNode\n errorFallback?: 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 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 apiBaseUrl?: never\n}\n\ninterface ConnectedPocaCardProps extends CommonPocaCardProps {\n cardId: string\n publishableKey: string\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 }\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 renderErrorFallback(errorFallback: CommonPocaCardProps['errorFallback'], error: Error) {\n if (typeof errorFallback === 'function') return errorFallback(error)\n return errorFallback ?? null\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 apiBaseUrl: props.apiBaseUrl,\n })\n const readyTracked = useRef(false)\n\n useEffect(() => {\n if (error && !props.errorFallback) {\n props.onError?.(error)\n }\n }, [error, props.errorFallback, props.onError])\n\n if (error) {\n return renderErrorFallback(props.errorFallback, error)\n }\n\n if (loading || !config) {\n return props.loadingFallback ?? null\n }\n\n const resolved = resolveConfigProps(config, {\n ...props,\n onReady: () => {\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.onReady?.()\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 [portalTargets, setPortalTargets] = useState<{\n front: HTMLElement | null\n back: HTMLElement | null\n }>({ front: null, back: null })\n\n useEffect(() => {\n if (!containerRef.current) return\n\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 preventTouchScroll: props.preventTouchScroll,\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 const layersMounted = useRef(false)\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 onError = props.onError\n\n if (onFlip) card.on('flip', onFlip)\n if (onReady) card.on('ready', onReady)\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 if (onError) card.off('error', onError)\n }\n }, [props.onFlip, props.onReady, props.onError])\n\n useImperativeHandle(refHandle, () => ({\n flip: () => cardRef.current?.flip(),\n wiggle: () => cardRef.current?.wiggle(),\n reset: () => cardRef.current?.reset(),\n }))\n\n return (\n <div\n ref={containerRef}\n style={props.style}\n className={props.className}\n >\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 { FaceProps } 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 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}\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 res = await fetch(`${baseUrl}/api/v1/public/cards/${cardId}/config`, {\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): string {\n return `${apiBaseUrl ?? ''}:${publishableKey}:${cardId}`\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)\n }, [input.apiBaseUrl, input.publishableKey, input.cardId])\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 })\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])\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 })\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])\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"]}
|