@sangwonl/pocato-react 0.2.1 → 0.3.0

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
@@ -1,24 +1,23 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode, CSSProperties } from 'react';
3
- import { PocaCardOptions } from '@sangwonl/pocato-core';
3
+ import { LayerSource } from '@sangwonl/pocato-core';
4
4
 
5
5
  interface PocaCardHandle {
6
6
  flip(): void;
7
7
  wiggle(): void;
8
8
  reset(): void;
9
9
  }
10
+ interface FaceProps {
11
+ shader?: string;
12
+ layers: LayerSource[];
13
+ content?: ReactNode;
14
+ }
10
15
  interface PocaCardProps {
11
- type: PocaCardOptions['type'];
12
- baseImage: string;
13
- popupImage?: string;
14
- maskImage?: string;
15
- backImage?: string;
16
+ front: FaceProps;
17
+ back?: FaceProps;
16
18
  flippable?: boolean;
17
19
  initialFlipped?: boolean;
18
20
  flipSpeed?: number;
19
- customShader?: string;
20
- frontContent?: ReactNode;
21
- backContent?: ReactNode;
22
21
  onFlip?: (flipped: boolean) => void;
23
22
  onReady?: () => void;
24
23
  onError?: (error: Error) => void;
@@ -27,4 +26,4 @@ interface PocaCardProps {
27
26
  }
28
27
  declare const PocaCard: react.ForwardRefExoticComponent<PocaCardProps & react.RefAttributes<PocaCardHandle>>;
29
28
 
30
- export { PocaCard, type PocaCardHandle, type PocaCardProps };
29
+ export { type FaceProps, PocaCard, type PocaCardHandle, type PocaCardProps };
package/dist/index.js CHANGED
@@ -7,7 +7,9 @@ import {
7
7
  useState
8
8
  } from "react";
9
9
  import { createPortal } from "react-dom";
10
- import { PocaCard as CorePocaCard } from "@sangwonl/pocato-core";
10
+ import {
11
+ PocaCard as CorePocaCard
12
+ } from "@sangwonl/pocato-core";
11
13
  import { jsxs } from "react/jsx-runtime";
12
14
  var PocaCard = forwardRef(
13
15
  (props, ref) => {
@@ -17,15 +19,11 @@ var PocaCard = forwardRef(
17
19
  useEffect(() => {
18
20
  if (!containerRef.current) return;
19
21
  const card = new CorePocaCard(containerRef.current, {
20
- type: props.type,
21
- baseImage: props.baseImage,
22
- popupImage: props.popupImage,
23
- maskImage: props.maskImage,
24
- backImage: props.backImage,
22
+ front: { shader: props.front.shader, layers: props.front.layers },
23
+ back: props.back ? { shader: props.back.shader, layers: props.back.layers } : void 0,
25
24
  flippable: props.flippable,
26
25
  initialFlipped: props.initialFlipped,
27
- flipSpeed: props.flipSpeed,
28
- customShader: props.customShader
26
+ flipSpeed: props.flipSpeed
29
27
  });
30
28
  cardRef.current = card;
31
29
  setPortalTargets({
@@ -37,24 +35,25 @@ var PocaCard = forwardRef(
37
35
  cardRef.current = null;
38
36
  setPortalTargets({ front: null, back: null });
39
37
  };
40
- }, [props.type]);
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);
41
42
  useEffect(() => {
43
+ if (!layersMounted.current) {
44
+ layersMounted.current = true;
45
+ return;
46
+ }
42
47
  cardRef.current?.updateOptions({
43
- baseImage: props.baseImage,
44
- popupImage: props.popupImage,
45
- maskImage: props.maskImage
48
+ front: { layers: props.front.layers },
49
+ back: props.back ? { layers: props.back.layers } : void 0
46
50
  });
47
- }, [props.baseImage, props.popupImage, props.maskImage]);
51
+ }, [frontLayersKey, backLayersKey]);
48
52
  useEffect(() => {
49
53
  if (props.flipSpeed != null) {
50
54
  cardRef.current?.updateOptions({ flipSpeed: props.flipSpeed });
51
55
  }
52
56
  }, [props.flipSpeed]);
53
- useEffect(() => {
54
- if (props.customShader) {
55
- cardRef.current?.updateOptions({ customShader: props.customShader });
56
- }
57
- }, [props.customShader]);
58
57
  useEffect(() => {
59
58
  const card = cardRef.current;
60
59
  if (!card) return;
@@ -82,8 +81,8 @@ var PocaCard = forwardRef(
82
81
  style: props.style,
83
82
  className: props.className,
84
83
  children: [
85
- portalTargets.front && props.frontContent && createPortal(props.frontContent, portalTargets.front),
86
- portalTargets.back && props.backContent && createPortal(props.backContent, portalTargets.back)
84
+ portalTargets.front && props.front.content && createPortal(props.front.content, portalTargets.front),
85
+ portalTargets.back && props.back?.content && createPortal(props.back.content, portalTargets.back)
87
86
  ]
88
87
  }
89
88
  );
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 { PocaCard as CorePocaCard, type PocaCardOptions } from '@sangwonl/pocato-core'\n\nexport interface PocaCardHandle {\n flip(): void\n wiggle(): void\n reset(): void\n}\n\nexport interface PocaCardProps {\n type: PocaCardOptions['type']\n baseImage: string\n popupImage?: string\n maskImage?: string\n backImage?: string\n flippable?: boolean\n initialFlipped?: boolean\n flipSpeed?: number\n customShader?: string\n frontContent?: ReactNode\n backContent?: ReactNode\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 type: props.type,\n baseImage: props.baseImage,\n popupImage: props.popupImage,\n maskImage: props.maskImage,\n backImage: props.backImage,\n flippable: props.flippable,\n initialFlipped: props.initialFlipped,\n flipSpeed: props.flipSpeed,\n customShader: props.customShader,\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 only when type changes (major config change)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [props.type])\n\n // Sync image options\n useEffect(() => {\n cardRef.current?.updateOptions({\n baseImage: props.baseImage,\n popupImage: props.popupImage,\n maskImage: props.maskImage,\n })\n }, [props.baseImage, props.popupImage, props.maskImage])\n\n // Sync flipSpeed\n useEffect(() => {\n if (props.flipSpeed != null) {\n cardRef.current?.updateOptions({ flipSpeed: props.flipSpeed })\n }\n }, [props.flipSpeed])\n\n // Sync custom shader\n useEffect(() => {\n if (props.customShader) {\n cardRef.current?.updateOptions({ customShader: props.customShader })\n }\n }, [props.customShader])\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.frontContent && createPortal(props.frontContent, portalTargets.front)}\n {portalTargets.back && props.backContent && createPortal(props.backContent, 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"],"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":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sangwonl/pocato-react",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
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.2.1"
28
+ "@sangwonl/pocato-core": "0.3.0"
29
29
  },
30
30
  "peerDependencies": {
31
31
  "react": "^18.0.0 || ^19.0.0",