@sangwonl/pocato-react 0.3.0 → 0.4.1

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 CHANGED
@@ -2,6 +2,31 @@ import * as react from 'react';
2
2
  import { ReactNode, CSSProperties } from 'react';
3
3
  import { LayerSource } from '@sangwonl/pocato-core';
4
4
 
5
+ interface PocaCardFaceConfig extends Omit<FaceProps, 'content'> {
6
+ html?: string;
7
+ }
8
+ interface PocaCardConfig {
9
+ cardSize?: {
10
+ width: number;
11
+ height: number;
12
+ preset?: string;
13
+ };
14
+ front: PocaCardFaceConfig;
15
+ back?: PocaCardFaceConfig;
16
+ flippable?: boolean;
17
+ initialFlipped?: boolean;
18
+ flipSpeed?: number;
19
+ }
20
+ interface PublishedConfigResponse {
21
+ cardId: string;
22
+ releaseId: string;
23
+ config: PocaCardConfig;
24
+ }
25
+ interface PocatoClientOptions {
26
+ apiBaseUrl?: string;
27
+ publishableKey: string;
28
+ }
29
+
5
30
  interface PocaCardHandle {
6
31
  flip(): void;
7
32
  wiggle(): void;
@@ -12,18 +37,55 @@ interface FaceProps {
12
37
  layers: LayerSource[];
13
38
  content?: ReactNode;
14
39
  }
15
- interface PocaCardProps {
16
- front: FaceProps;
17
- back?: FaceProps;
40
+ interface CommonPocaCardProps {
18
41
  flippable?: boolean;
19
42
  initialFlipped?: boolean;
20
43
  flipSpeed?: number;
21
44
  onFlip?: (flipped: boolean) => void;
22
45
  onReady?: () => void;
23
46
  onError?: (error: Error) => void;
47
+ loadingFallback?: ReactNode;
48
+ errorFallback?: ReactNode | ((error: Error) => ReactNode);
24
49
  style?: CSSProperties;
25
50
  className?: string;
26
51
  }
52
+ interface DirectPocaCardProps extends CommonPocaCardProps {
53
+ front: FaceProps;
54
+ back?: FaceProps;
55
+ config?: never;
56
+ cardId?: never;
57
+ publishableKey?: never;
58
+ apiBaseUrl?: never;
59
+ }
60
+ interface ConfigPocaCardProps extends CommonPocaCardProps {
61
+ config: PocaCardConfig;
62
+ front?: Partial<FaceProps>;
63
+ back?: Partial<FaceProps>;
64
+ cardId?: never;
65
+ publishableKey?: never;
66
+ apiBaseUrl?: never;
67
+ }
68
+ interface ConnectedPocaCardProps extends CommonPocaCardProps {
69
+ cardId: string;
70
+ publishableKey: string;
71
+ apiBaseUrl?: string;
72
+ front?: Partial<FaceProps>;
73
+ back?: Partial<FaceProps>;
74
+ config?: never;
75
+ }
76
+ type PocaCardProps = DirectPocaCardProps | ConfigPocaCardProps | ConnectedPocaCardProps;
27
77
  declare const PocaCard: react.ForwardRefExoticComponent<PocaCardProps & react.RefAttributes<PocaCardHandle>>;
28
78
 
29
- export { type FaceProps, PocaCard, type PocaCardHandle, type PocaCardProps };
79
+ interface UsePocatoConfigInput extends PocatoClientOptions {
80
+ cardId: string;
81
+ }
82
+ interface UsePocatoConfigResult {
83
+ data: PublishedConfigResponse | null;
84
+ config: PocaCardConfig | null;
85
+ loading: boolean;
86
+ error: Error | null;
87
+ refetch: () => Promise<PublishedConfigResponse | null>;
88
+ }
89
+ declare function usePocatoConfig(input: UsePocatoConfigInput): UsePocatoConfigResult;
90
+
91
+ export { type FaceProps, PocaCard, type PocaCardConfig, type PocaCardFaceConfig, type PocaCardHandle, type PocaCardProps, type PublishedConfigResponse, type UsePocatoConfigInput, type UsePocatoConfigResult, usePocatoConfig };
package/dist/index.js CHANGED
@@ -1,95 +1,289 @@
1
1
  // src/PocaCard.tsx
2
2
  import {
3
3
  forwardRef,
4
- useEffect,
4
+ useEffect as useEffect2,
5
5
  useImperativeHandle,
6
6
  useRef,
7
- useState
7
+ useState as useState2
8
8
  } from "react";
9
9
  import { createPortal } from "react-dom";
10
10
  import {
11
11
  PocaCard as CorePocaCard
12
12
  } from "@sangwonl/pocato-core";
13
- import { jsxs } from "react/jsx-runtime";
14
- var PocaCard = forwardRef(
15
- (props, ref) => {
16
- const containerRef = useRef(null);
17
- const cardRef = useRef(null);
18
- const [portalTargets, setPortalTargets] = useState({ front: null, back: null });
19
- useEffect(() => {
20
- if (!containerRef.current) return;
21
- const card = new CorePocaCard(containerRef.current, {
22
- front: { shader: props.front.shader, layers: props.front.layers },
23
- back: props.back ? { shader: props.back.shader, layers: props.back.layers } : void 0,
24
- flippable: props.flippable,
25
- initialFlipped: props.initialFlipped,
26
- flipSpeed: props.flipSpeed
27
- });
28
- cardRef.current = card;
29
- setPortalTargets({
30
- front: card.getFrontContentEl(),
31
- back: card.getBackContentEl()
32
- });
33
- return () => {
34
- card.destroy();
35
- cardRef.current = null;
36
- setPortalTargets({ front: null, back: null });
37
- };
38
- }, [props.front.shader, props.back?.shader]);
39
- const frontLayersKey = JSON.stringify(props.front.layers);
40
- const backLayersKey = JSON.stringify(props.back?.layers);
41
- const layersMounted = useRef(false);
42
- useEffect(() => {
43
- if (!layersMounted.current) {
44
- layersMounted.current = true;
45
- return;
13
+
14
+ // src/pocato-client.ts
15
+ var DEFAULT_API_BASE_URL = "https://pocato-api.gamzabaw.workers.dev";
16
+ function getApiBaseUrl(apiBaseUrl) {
17
+ return apiBaseUrl ?? DEFAULT_API_BASE_URL;
18
+ }
19
+ async function fetchPublishedConfig(cardId, options) {
20
+ const baseUrl = getApiBaseUrl(options.apiBaseUrl);
21
+ const res = await fetch(`${baseUrl}/api/v1/public/cards/${cardId}/config`, {
22
+ headers: {
23
+ "X-Pocato-Key": options.publishableKey
24
+ }
25
+ });
26
+ if (!res.ok) {
27
+ throw new Error(`Failed to load Pocato card config: ${res.status}`);
28
+ }
29
+ return res.json();
30
+ }
31
+ async function trackCardEvent(cardId, options) {
32
+ const baseUrl = getApiBaseUrl(options.apiBaseUrl);
33
+ await fetch(`${baseUrl}/api/v1/public/cards/${cardId}/events`, {
34
+ method: "POST",
35
+ headers: {
36
+ "Content-Type": "application/json",
37
+ "X-Pocato-Key": options.publishableKey
38
+ },
39
+ body: JSON.stringify({ eventType: options.eventType }),
40
+ keepalive: true
41
+ }).catch(() => {
42
+ });
43
+ }
44
+
45
+ // src/use-pocato-config.ts
46
+ import { useCallback, useEffect, useMemo, useState } from "react";
47
+ var cache = /* @__PURE__ */ new Map();
48
+ function getPocatoConfigCacheKey(apiBaseUrl, publishableKey, cardId) {
49
+ return `${apiBaseUrl ?? ""}:${publishableKey}:${cardId}`;
50
+ }
51
+ function usePocatoConfig(input) {
52
+ const cacheKey = useMemo(() => {
53
+ return getPocatoConfigCacheKey(input.apiBaseUrl, input.publishableKey, input.cardId);
54
+ }, [input.apiBaseUrl, input.publishableKey, input.cardId]);
55
+ const [data, setData] = useState(() => {
56
+ return cache.get(cacheKey) ?? null;
57
+ });
58
+ const [loading, setLoading] = useState(!data);
59
+ const [error, setError] = useState(null);
60
+ const load = useCallback(async (options) => {
61
+ if (!options?.force) {
62
+ const cached = cache.get(cacheKey);
63
+ if (cached) {
64
+ setData(cached);
65
+ setLoading(false);
66
+ setError(null);
67
+ return cached;
46
68
  }
47
- cardRef.current?.updateOptions({
48
- front: { layers: props.front.layers },
49
- back: props.back ? { layers: props.back.layers } : void 0
69
+ }
70
+ setData(null);
71
+ setLoading(true);
72
+ setError(null);
73
+ try {
74
+ const response = await fetchPublishedConfig(input.cardId, {
75
+ apiBaseUrl: input.apiBaseUrl,
76
+ publishableKey: input.publishableKey
50
77
  });
51
- }, [frontLayersKey, backLayersKey]);
52
- useEffect(() => {
53
- if (props.flipSpeed != null) {
54
- cardRef.current?.updateOptions({ flipSpeed: props.flipSpeed });
55
- }
56
- }, [props.flipSpeed]);
57
- useEffect(() => {
58
- const card = cardRef.current;
59
- if (!card) return;
60
- const onFlip = props.onFlip;
61
- const onReady = props.onReady;
62
- const onError = props.onError;
63
- if (onFlip) card.on("flip", onFlip);
64
- if (onReady) card.on("ready", onReady);
65
- if (onError) card.on("error", onError);
66
- return () => {
67
- if (onFlip) card.off("flip", onFlip);
68
- if (onReady) card.off("ready", onReady);
69
- if (onError) card.off("error", onError);
70
- };
71
- }, [props.onFlip, props.onReady, props.onError]);
72
- useImperativeHandle(ref, () => ({
73
- flip: () => cardRef.current?.flip(),
74
- wiggle: () => cardRef.current?.wiggle(),
75
- reset: () => cardRef.current?.reset()
76
- }));
77
- return /* @__PURE__ */ jsxs(
78
- "div",
79
- {
80
- ref: containerRef,
81
- style: props.style,
82
- className: props.className,
83
- children: [
84
- portalTargets.front && props.front.content && createPortal(props.front.content, portalTargets.front),
85
- portalTargets.back && props.back?.content && createPortal(props.back.content, portalTargets.back)
86
- ]
78
+ cache.set(cacheKey, response);
79
+ setData(response);
80
+ setLoading(false);
81
+ return response;
82
+ } catch (err) {
83
+ const nextError = err instanceof Error ? err : new Error("Failed to load Pocato config");
84
+ setError(nextError);
85
+ setLoading(false);
86
+ return null;
87
+ }
88
+ }, [cacheKey, input.apiBaseUrl, input.cardId, input.publishableKey]);
89
+ useEffect(() => {
90
+ let cancelled = false;
91
+ const cached = cache.get(cacheKey);
92
+ if (cached) {
93
+ setData(cached);
94
+ setLoading(false);
95
+ setError(null);
96
+ return;
97
+ }
98
+ setData(null);
99
+ setLoading(true);
100
+ setError(null);
101
+ fetchPublishedConfig(input.cardId, {
102
+ apiBaseUrl: input.apiBaseUrl,
103
+ publishableKey: input.publishableKey
104
+ }).then((response) => {
105
+ if (cancelled) return;
106
+ cache.set(cacheKey, response);
107
+ setData(response);
108
+ setLoading(false);
109
+ }).catch((err) => {
110
+ if (cancelled) return;
111
+ setError(err instanceof Error ? err : new Error("Failed to load Pocato config"));
112
+ setLoading(false);
113
+ });
114
+ return () => {
115
+ cancelled = true;
116
+ };
117
+ }, [cacheKey, input.apiBaseUrl, input.publishableKey, input.cardId]);
118
+ return {
119
+ data,
120
+ config: data?.config ?? null,
121
+ loading,
122
+ error,
123
+ refetch: () => load({ force: true })
124
+ };
125
+ }
126
+
127
+ // src/PocaCard.tsx
128
+ import { jsx, jsxs } from "react/jsx-runtime";
129
+ function isConnectedProps(props) {
130
+ return typeof props.cardId === "string" && typeof props.publishableKey === "string";
131
+ }
132
+ function isConfigProps(props) {
133
+ return "config" in props && props.config != null;
134
+ }
135
+ function resolveConfigProps(config, props) {
136
+ return {
137
+ ...props,
138
+ front: {
139
+ ...config.front,
140
+ content: props.front?.content
141
+ },
142
+ back: config.back ? {
143
+ ...config.back,
144
+ content: props.back?.content
145
+ } : props.back?.layers ? props.back : void 0,
146
+ flippable: props.flippable ?? config.flippable,
147
+ initialFlipped: props.initialFlipped ?? config.initialFlipped,
148
+ flipSpeed: props.flipSpeed ?? config.flipSpeed
149
+ };
150
+ }
151
+ function renderErrorFallback(errorFallback, error) {
152
+ if (typeof errorFallback === "function") return errorFallback(error);
153
+ return errorFallback ?? null;
154
+ }
155
+ function ConnectedPocaCard(props, ref) {
156
+ const { config, loading, error } = usePocatoConfig({
157
+ cardId: props.cardId,
158
+ publishableKey: props.publishableKey,
159
+ apiBaseUrl: props.apiBaseUrl
160
+ });
161
+ const readyTracked = useRef(false);
162
+ useEffect2(() => {
163
+ if (error && !props.errorFallback) {
164
+ props.onError?.(error);
165
+ }
166
+ }, [error, props.errorFallback, props.onError]);
167
+ if (error) {
168
+ return renderErrorFallback(props.errorFallback, error);
169
+ }
170
+ if (loading || !config) {
171
+ return props.loadingFallback ?? null;
172
+ }
173
+ const resolved = resolveConfigProps(config, {
174
+ ...props,
175
+ onReady: () => {
176
+ if (!readyTracked.current) {
177
+ readyTracked.current = true;
178
+ void trackCardEvent(props.cardId, {
179
+ apiBaseUrl: props.apiBaseUrl,
180
+ publishableKey: props.publishableKey,
181
+ eventType: "card_ready"
182
+ });
87
183
  }
88
- );
184
+ props.onReady?.();
185
+ },
186
+ onError: (runtimeError) => {
187
+ void trackCardEvent(props.cardId, {
188
+ apiBaseUrl: props.apiBaseUrl,
189
+ publishableKey: props.publishableKey,
190
+ eventType: "render_error"
191
+ });
192
+ props.onError?.(runtimeError);
193
+ }
194
+ });
195
+ return /* @__PURE__ */ jsx(PocaCardRenderer, { props: resolved, refHandle: ref });
196
+ }
197
+ function PocaCardRenderer({
198
+ props,
199
+ refHandle
200
+ }) {
201
+ const containerRef = useRef(null);
202
+ const cardRef = useRef(null);
203
+ const [portalTargets, setPortalTargets] = useState2({ front: null, back: null });
204
+ useEffect2(() => {
205
+ if (!containerRef.current) return;
206
+ 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,
209
+ flippable: props.flippable,
210
+ initialFlipped: props.initialFlipped,
211
+ flipSpeed: props.flipSpeed
212
+ });
213
+ cardRef.current = card;
214
+ setPortalTargets({
215
+ front: card.getFrontContentEl(),
216
+ back: card.getBackContentEl()
217
+ });
218
+ return () => {
219
+ card.destroy();
220
+ cardRef.current = null;
221
+ setPortalTargets({ front: null, back: null });
222
+ };
223
+ }, [props.front.shader, props.back?.shader]);
224
+ const frontLayersKey = JSON.stringify(props.front.layers);
225
+ const backLayersKey = JSON.stringify(props.back?.layers);
226
+ const layersMounted = useRef(false);
227
+ useEffect2(() => {
228
+ if (!layersMounted.current) {
229
+ layersMounted.current = true;
230
+ return;
231
+ }
232
+ cardRef.current?.updateOptions({
233
+ front: { layers: props.front.layers },
234
+ back: props.back ? { layers: props.back.layers } : void 0
235
+ });
236
+ }, [frontLayersKey, backLayersKey]);
237
+ useEffect2(() => {
238
+ if (props.flipSpeed != null) {
239
+ cardRef.current?.updateOptions({ flipSpeed: props.flipSpeed });
240
+ }
241
+ }, [props.flipSpeed]);
242
+ useEffect2(() => {
243
+ const card = cardRef.current;
244
+ if (!card) return;
245
+ const onFlip = props.onFlip;
246
+ const onReady = props.onReady;
247
+ const onError = props.onError;
248
+ if (onFlip) card.on("flip", onFlip);
249
+ if (onReady) card.on("ready", onReady);
250
+ if (onError) card.on("error", onError);
251
+ return () => {
252
+ if (onFlip) card.off("flip", onFlip);
253
+ if (onReady) card.off("ready", onReady);
254
+ if (onError) card.off("error", onError);
255
+ };
256
+ }, [props.onFlip, props.onReady, props.onError]);
257
+ useImperativeHandle(refHandle, () => ({
258
+ flip: () => cardRef.current?.flip(),
259
+ wiggle: () => cardRef.current?.wiggle(),
260
+ reset: () => cardRef.current?.reset()
261
+ }));
262
+ return /* @__PURE__ */ jsxs(
263
+ "div",
264
+ {
265
+ ref: containerRef,
266
+ style: props.style,
267
+ className: props.className,
268
+ children: [
269
+ portalTargets.front && props.front.content && createPortal(props.front.content, portalTargets.front),
270
+ portalTargets.back && props.back?.content && createPortal(props.back.content, portalTargets.back)
271
+ ]
272
+ }
273
+ );
274
+ }
275
+ var PocaCard = forwardRef(
276
+ (props, ref) => {
277
+ if (isConnectedProps(props)) {
278
+ return ConnectedPocaCard(props, ref);
279
+ }
280
+ const resolved = isConfigProps(props) ? resolveConfigProps(props.config, props) : props;
281
+ return /* @__PURE__ */ jsx(PocaCardRenderer, { props: resolved, refHandle: ref });
89
282
  }
90
283
  );
91
284
  PocaCard.displayName = "PocaCard";
92
285
  export {
93
- PocaCard
286
+ PocaCard,
287
+ usePocatoConfig
94
288
  };
95
289
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/PocaCard.tsx"],"sourcesContent":["import {\n forwardRef,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n type CSSProperties,\n type ReactNode,\n} from 'react'\nimport { createPortal } from 'react-dom'\nimport {\n PocaCard as CorePocaCard,\n type PocaCardOptions,\n type LayerSource,\n} from '@sangwonl/pocato-core'\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\nexport interface PocaCardProps {\n front: FaceProps\n back?: FaceProps\n flippable?: boolean\n initialFlipped?: boolean\n flipSpeed?: number\n onFlip?: (flipped: boolean) => void\n onReady?: () => void\n onError?: (error: Error) => void\n style?: CSSProperties\n className?: string\n}\n\nexport const PocaCard = forwardRef<PocaCardHandle, PocaCardProps>(\n (props, ref) => {\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 // Create/destroy core instance\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 // Sync layers (JSON.stringify for shallow comparison of small plain objects)\n // Skip initial mount — constructor already loads layers\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 // Sync flipSpeed\n useEffect(() => {\n if (props.flipSpeed != null) {\n cardRef.current?.updateOptions({ flipSpeed: props.flipSpeed })\n }\n }, [props.flipSpeed])\n\n // Bind events\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 // Expose imperative handle\n useImperativeHandle(ref, () => ({\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)\n\nPocaCard.displayName = 'PocaCard'\n"],"mappings":"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","names":[]}
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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sangwonl/pocato-react",
3
- "version": "0.3.0",
3
+ "version": "0.4.1",
4
4
  "author": "Sangwon Lee <gamzabaw@gmail.com>",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -25,7 +25,7 @@
25
25
  "dev": "tsup --watch"
26
26
  },
27
27
  "dependencies": {
28
- "@sangwonl/pocato-core": "0.3.0"
28
+ "@sangwonl/pocato-core": "0.4.1"
29
29
  },
30
30
  "peerDependencies": {
31
31
  "react": "^18.0.0 || ^19.0.0",