@vnejs/uis.react.sprite 0.1.3 → 0.1.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/package.json CHANGED
@@ -1,32 +1,26 @@
1
1
  {
2
2
  "name": "@vnejs/uis.react.sprite",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "scripts": {
7
- "build": "node ../../../scripts/build-package.mjs",
8
- "publish:major:plugin": "npm run publish:major",
9
- "publish:minor:plugin": "npm run publish:minor",
10
- "publish:patch:plugin": "npm run publish:patch",
11
- "publish:major": "npm run build && npm version major && npm publish --access public",
12
- "publish:minor": "npm run build && npm version minor && npm publish --access public",
13
- "publish:patch": "npm run build && npm version patch && npm publish --access public"
7
+ "build": "npx @vnejs/monorepo package",
8
+ "publish:major:uis:react": "npm run publish:major",
9
+ "publish:minor:uis:react": "npm run publish:minor",
10
+ "publish:patch:uis:react": "npm run publish:patch",
11
+ "publish:major": "npx @vnejs/monorepo publish major --access public",
12
+ "publish:minor": "npx @vnejs/monorepo publish minor --access public",
13
+ "publish:patch": "npx @vnejs/monorepo publish patch --access public"
14
14
  },
15
15
  "peerDependencies": {
16
- "@bem-react/classname": "1.5.12",
17
- "@vnejs/uis.utils": "~0.1.0",
18
- "react": "19.2.4",
19
- "react-dom": "19.2.4",
20
- "@vnejs/uis.react": "~0.1.0"
16
+ "@vnejs/uis.utils": "~0.1.0"
21
17
  },
22
18
  "devDependencies": {
23
- "@vnejs/uis.react": "~0.1.0",
24
- "typescript": "^6.0.3",
25
- "@types/react": "^19.0.10",
26
- "@types/react-dom": "^19.0.4"
19
+ "@vnejs/uis.react": "~0.1.0"
27
20
  },
28
21
  "files": [
29
22
  "dist",
30
- "package.json"
23
+ "src",
24
+ "tsconfig.json"
31
25
  ]
32
26
  }
@@ -0,0 +1,93 @@
1
+ import { useCallback, useEffect, useMemo, useState } from "react";
2
+
3
+ import { renderWithVneWrap, DEFAULT_ARGS, ARGS } from "@vnejs/uis.react";
4
+
5
+ import { Sprite } from "@vnejs/uis.react";
6
+
7
+ export const Common = {
8
+ args: {
9
+ ...DEFAULT_ARGS,
10
+
11
+ transition: 500,
12
+
13
+ isPose1: false,
14
+ isPose2: false,
15
+ },
16
+ };
17
+
18
+ const BOX_PROPS = { top: "100%", left: "50%", scale: 1, translateX: -50, translateY: -100, transition: 0 };
19
+ const SPRITE_PREFIX = "./speaker/original-4k/co";
20
+
21
+ export default {
22
+ title: "Base/Sprite/Change",
23
+ render: renderWithVneWrap(({ isPose1, isPose2, transition }) => {
24
+ const [spriteTransition, setSpriteTransition] = useState(0);
25
+ const [spriteType, setSpriteType] = useState(1);
26
+
27
+ const setNewSpriteType = useCallback(
28
+ (cond, transition, newType) => {
29
+ if (!cond) return;
30
+
31
+ setSpriteTransition(0);
32
+
33
+ requestAnimationFrame(() => {
34
+ setSpriteTransition(transition);
35
+ setSpriteType(newType);
36
+ setTimeout(() => setSpriteTransition(0), transition);
37
+ });
38
+ },
39
+ [setSpriteTransition, setSpriteType],
40
+ );
41
+
42
+ useEffect(() => setNewSpriteType(isPose1, transition, 1), [isPose1, transition, setNewSpriteType]);
43
+ useEffect(() => setNewSpriteType(isPose2, transition, 2), [isPose2, transition, setNewSpriteType]);
44
+
45
+ const [spritePose, spriteWear, spriteHair, spriteEmotion] = useMemo(() => {
46
+ if (spriteType === 1) return ["default", "laboratory_suit", "normal", "default"];
47
+ return ["hand_on_shoulder_spead_legs", "medical_shirt", "wild_hair", "anger"];
48
+ }, [spriteType]);
49
+
50
+ const parts = useMemo(
51
+ () => [
52
+ { src: `${SPRITE_PREFIX}/${spritePose}/hair_back/${spriteHair}.png` },
53
+ { src: `${SPRITE_PREFIX}/${spritePose}/index.png` },
54
+ {
55
+ src: [
56
+ { url: `${SPRITE_PREFIX}/${spritePose}/eyes/${spriteEmotion}/opened.png`, duration: 3000, randomDuration: 1000, transition: 500 },
57
+ { url: `${SPRITE_PREFIX}/${spritePose}/eyes/${spriteEmotion}/closed.png`, duration: 100, randomDuration: 50, transition: 200 },
58
+ { url: `${SPRITE_PREFIX}/${spritePose}/eyes/${spriteEmotion}/opened.png`, duration: 500, randomDuration: 500, transition: 500 },
59
+ { url: `${SPRITE_PREFIX}/${spritePose}/eyes/${spriteEmotion}/closed.png`, duration: 100, randomDuration: 50, transition: 200 },
60
+ ],
61
+ isSwitchDisabled: false,
62
+ },
63
+ { src: `${SPRITE_PREFIX}/${spritePose}/hair_front/${spriteHair}.png` },
64
+ {
65
+ src: [
66
+ { url: `${SPRITE_PREFIX}/${spritePose}/mouth/${spriteEmotion}/closed.png`, duration: 100, transition: 200 },
67
+ { url: `${SPRITE_PREFIX}/${spritePose}/mouth/${spriteEmotion}/opened.png`, duration: 100, transition: 200 },
68
+ ],
69
+ isSwitchDisabled: true,
70
+ },
71
+ { src: `${SPRITE_PREFIX}/${spritePose}/wear/${spriteWear}.png` },
72
+ ],
73
+ [spritePose, spriteWear, spriteHair, spriteEmotion],
74
+ );
75
+ const indexSrc = useMemo(() => `${SPRITE_PREFIX}/${spritePose}/index.png`, [spritePose]);
76
+
77
+ const partsProps = useMemo(() => ({ transition: spriteTransition }), [spriteTransition]);
78
+
79
+ return (
80
+ <Sprite
81
+ boxProps={BOX_PROPS}
82
+ partsProps={partsProps}
83
+ parts={parts}
84
+ indexSrc={indexSrc}
85
+ />
86
+ );
87
+ }),
88
+ argTypes: {
89
+ ...ARGS,
90
+
91
+ transition: { control: { type: "number", min: 0, max: 1000, step: 50 } },
92
+ },
93
+ };
@@ -0,0 +1,112 @@
1
+ import { useMemo } from "react";
2
+
3
+ import { renderWithVneWrap, ARGS, DEFAULT_ARGS } from "@vnejs/uis.react";
4
+
5
+ import { Sprite } from "@vnejs/uis.react";
6
+
7
+ export const Common = {
8
+ args: {
9
+ ...DEFAULT_ARGS,
10
+
11
+ spritePose: "default",
12
+ spriteWear: "laboratory_suit",
13
+ spriteHair: "normal",
14
+ spriteIsBlinking: false,
15
+ spriteIsSpeaking: false,
16
+
17
+ boxTransition: 0,
18
+ partsTransition: 0,
19
+
20
+ top: 100,
21
+ left: 50,
22
+ scale: 1,
23
+ translateX: -50,
24
+ translateY: -100,
25
+ },
26
+ };
27
+
28
+ export default {
29
+ title: "Base/Sprite/Default",
30
+ render: renderWithVneWrap(
31
+ ({
32
+ translateX,
33
+ translateY,
34
+ top,
35
+ left,
36
+ scale,
37
+ boxTransition,
38
+ partsTransition,
39
+
40
+ spriteIsBlinking,
41
+ spriteIsSpeaking,
42
+ spritePose,
43
+ spriteHair,
44
+ spriteWear,
45
+ }) => {
46
+ const parts = useMemo(
47
+ () => [
48
+ { src: `./speaker/original-4k/co/${spritePose}/hair_back/${spriteHair}.png` },
49
+ { src: `./speaker/original-4k/co/${spritePose}/index.png` },
50
+ {
51
+ src: [
52
+ { url: `./speaker/original-4k/co/${spritePose}/eyes/default/opened.png`, duration: 3000, randomDuration: 1000, transition: 300 },
53
+ { url: `./speaker/original-4k/co/${spritePose}/eyes/default/closed.png`, duration: 100, randomDuration: 0, transition: 100 },
54
+ { url: `./speaker/original-4k/co/${spritePose}/eyes/default/opened.png`, duration: 500, randomDuration: 500, transition: 300 },
55
+ { url: `./speaker/original-4k/co/${spritePose}/eyes/default/closed.png`, duration: 100, randomDuration: 0, transition: 100 },
56
+ ],
57
+ isSwitchDisabled: !spriteIsBlinking,
58
+ },
59
+ { src: `./speaker/original-4k/co/${spritePose}/hair_front/${spriteHair}.png` },
60
+ {
61
+ src: [
62
+ { url: `./speaker/original-4k/co/${spritePose}/mouth/default/closed.png`, duration: 100, transition: 200 },
63
+ { url: `./speaker/original-4k/co/${spritePose}/mouth/default/opened.png`, duration: 100, transition: 200 },
64
+ ],
65
+ isSwitchDisabled: !spriteIsSpeaking,
66
+ },
67
+ { src: `./speaker/original-4k/co/${spritePose}/wear/${spriteWear}.png` },
68
+ ],
69
+ [spriteIsBlinking, spriteIsSpeaking, spritePose, spriteWear, spriteHair],
70
+ );
71
+ const indexSrc = useMemo(() => `./speaker/original-4k/co/${spritePose}/index.png`, [spritePose]);
72
+
73
+ const boxProps = useMemo(
74
+ () => ({ top: `${top}%`, left: `${left}%`, scale, translateX, translateY, transition: boxTransition }),
75
+ [top, left, scale, translateX, translateY, boxTransition],
76
+ );
77
+
78
+ const partsProps = useMemo(() => ({ transition: partsTransition }), [partsTransition]);
79
+
80
+ return (
81
+ <Sprite
82
+ boxProps={boxProps}
83
+ partsProps={partsProps}
84
+ parts={parts}
85
+ indexSrc={indexSrc}
86
+ />
87
+ );
88
+ },
89
+ ),
90
+ argTypes: {
91
+ // engine
92
+ ...ARGS,
93
+
94
+ spritePose: {
95
+ control: { type: "select" },
96
+ options: ["default", "hand_on_shoulder_spead_legs", "head_to_shoulders"],
97
+ },
98
+ spriteWear: { control: { type: "select" }, options: ["laboratory_suit", "costume", "medical_shirt"] },
99
+ spriteHair: { control: { type: "select" }, options: ["normal", "wild_hair"] },
100
+
101
+ // Sprite
102
+ partsTransition: { control: { type: "number", min: 0, max: 1000, step: 50 } },
103
+
104
+ // PositionBox
105
+ boxTransition: { control: { type: "number", min: 0, max: 1000, step: 50 } },
106
+ top: { control: { type: "number", min: 0, max: 100, step: 5 } },
107
+ left: { control: { type: "number", min: 0, max: 100, step: 5 } },
108
+ scale: { control: { type: "number", min: 0.1, max: 2, step: 0.1 } },
109
+ translateX: { control: { type: "number", min: -100, max: 100, step: 1 } },
110
+ translateY: { control: { type: "number", min: -100, max: 100, step: 1 } },
111
+ },
112
+ };
@@ -0,0 +1,125 @@
1
+ import { useEffect, useMemo, useState } from "react";
2
+
3
+ import { renderWithVneWrap, VneWrap } from "@vnejs/uis.react";
4
+
5
+ import { Sprite } from "@vnejs/uis.react";
6
+
7
+ const LEFT_X = 480 * 2;
8
+ const RIGHT_X = 480 * 6;
9
+
10
+ export const Common = {
11
+ args: {
12
+ ...VneWrap.DEFAULT_ARGS,
13
+
14
+ transition: 500,
15
+
16
+ isHideRight: false,
17
+ isShowLeft: false,
18
+ isPose: false,
19
+ },
20
+ };
21
+
22
+ export default {
23
+ title: "Base/Sprite/Move",
24
+ render: renderWithVneWrap(({ isHideRight, isShowLeft, isPose, transition }) => {
25
+ const [boxTransition, setBoxTransition] = useState(0);
26
+ const [boxOpacity, setBoxOpacity] = useState(1);
27
+ const [boxTranslateXShift, setBoxTranslateXShift] = useState(0);
28
+
29
+ const [boxX, setBoxX] = useState(LEFT_X);
30
+
31
+ useEffect(() => {
32
+ if (!isHideRight) return;
33
+
34
+ setBoxTransition(0);
35
+ setBoxTranslateXShift(0);
36
+ setBoxOpacity(1);
37
+
38
+ requestAnimationFrame(() => {
39
+ setBoxTransition(transition);
40
+ setBoxTranslateXShift(25);
41
+ setBoxOpacity(0);
42
+
43
+ setTimeout(() => {
44
+ setBoxTransition(0);
45
+ }, transition);
46
+ });
47
+ }, [isHideRight, transition]);
48
+
49
+ useEffect(() => {
50
+ if (!isShowLeft) return;
51
+
52
+ setBoxTransition(0);
53
+ setBoxTranslateXShift(-25);
54
+ setBoxOpacity(0);
55
+
56
+ requestAnimationFrame(() => {
57
+ setBoxTransition(transition);
58
+ setBoxTranslateXShift(0);
59
+ setBoxOpacity(1);
60
+
61
+ setTimeout(() => {
62
+ setBoxTransition(0);
63
+ }, transition);
64
+ });
65
+ }, [isShowLeft, transition]);
66
+
67
+ const spritePose = useMemo(() => (isPose ? "default" : "hand_on_shoulder_spead_legs"), [isPose]);
68
+
69
+ useEffect(() => setBoxX(isPose ? LEFT_X : RIGHT_X), [isPose]);
70
+
71
+ const parts = useMemo(
72
+ () => [
73
+ { src: `./speaker/original-4k/co/${spritePose}/hair_back/normal.png` },
74
+ { src: `./speaker/original-4k/co/${spritePose}/index.png` },
75
+ {
76
+ src: [
77
+ { url: `./speaker/original-4k/co/${spritePose}/eyes/default/opened.png`, duration: 3000, randomDuration: 1000, transition: 300 },
78
+ { url: `./speaker/original-4k/co/${spritePose}/eyes/default/closed.png`, duration: 100, randomDuration: 0, transition: 100 },
79
+ { url: `./speaker/original-4k/co/${spritePose}/eyes/default/opened.png`, duration: 500, randomDuration: 500, transition: 300 },
80
+ { url: `./speaker/original-4k/co/${spritePose}/eyes/default/closed.png`, duration: 100, randomDuration: 0, transition: 100 },
81
+ ],
82
+ isSwitchDisabled: false,
83
+ },
84
+ { src: `./speaker/original-4k/co/${spritePose}/hair_front/normal.png` },
85
+ {
86
+ src: [
87
+ { url: `./speaker/original-4k/co/${spritePose}/mouth/default/closed.png`, duration: 100, transition: 200 },
88
+ { url: `./speaker/original-4k/co/${spritePose}/mouth/default/opened.png`, duration: 100, transition: 200 },
89
+ ],
90
+ isSwitchDisabled: true,
91
+ },
92
+ { src: `./speaker/original-4k/co/${spritePose}/wear/medical_shirt.png` },
93
+ ],
94
+ [spritePose],
95
+ );
96
+ const indexSrc = useMemo(() => `./speaker/original-4k/co/${spritePose}/index.png`, [spritePose]);
97
+
98
+ const boxProps = useMemo(
99
+ () => ({
100
+ top: 2160,
101
+ left: boxX,
102
+ scale: 1,
103
+ translateX: -50 + boxTranslateXShift,
104
+ translateY: -100,
105
+ transition: boxTransition,
106
+ opacity: boxOpacity,
107
+ }),
108
+ [boxTransition, boxTranslateXShift, boxOpacity, boxX],
109
+ );
110
+
111
+ return (
112
+ <Sprite
113
+ boxProps={boxProps}
114
+ parts={parts}
115
+ indexSrc={indexSrc}
116
+ />
117
+ );
118
+ }),
119
+ argTypes: {
120
+ // engine
121
+ ...VneWrap.ARGS,
122
+
123
+ transition: { control: { type: "number", min: 0, max: 1000, step: 50 } },
124
+ },
125
+ };
package/src/Sprite.tsx ADDED
@@ -0,0 +1,31 @@
1
+ import { useMemo } from "react";
2
+ import { Image, PositionBox } from "@vnejs/uis.react";
3
+
4
+ const POSE_STYLE: Record<string, any> = { opacity: 0, visibility: "hidden" };
5
+
6
+ export const Sprite = ({ parts = [], indexSrc = "", boxProps = {}, partsProps = {}, transition = null, transitionBox = null }) => {
7
+ const realBoxProps = useMemo(() => {
8
+ const result: Record<string, any> = { ...boxProps };
9
+
10
+ if (transitionBox !== null) result.transition = transitionBox;
11
+
12
+ return result;
13
+ }, [boxProps, transitionBox]);
14
+
15
+ return (
16
+ <PositionBox {...realBoxProps}>
17
+ {parts.map((props, i) => (
18
+ <Image
19
+ key={i}
20
+ {...props}
21
+ {...partsProps}
22
+ transition={transition}
23
+ />
24
+ ))}
25
+ <img
26
+ src={indexSrc}
27
+ style={POSE_STYLE}
28
+ />
29
+ </PositionBox>
30
+ );
31
+ };
package/src/index.ts ADDED
@@ -0,0 +1 @@
1
+ export * from "./Sprite";
package/tsconfig.json ADDED
@@ -0,0 +1,18 @@
1
+ {
2
+ "extends": "../../../tsconfig.react.base.json",
3
+ "compilerOptions": {
4
+ "outDir": "dist",
5
+ "rootDir": "src"
6
+ },
7
+ "include": [
8
+ "src/**/*.ts",
9
+ "src/**/*.tsx",
10
+ "../../../globals.d.ts",
11
+ "../../../peer-modules.d.ts"
12
+ ],
13
+ "exclude": [
14
+ "dist",
15
+ "node_modules",
16
+ "src/**/*.stories.tsx"
17
+ ]
18
+ }