reacthub-pixitweenjs 0.2.2 → 0.2.4

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.
Files changed (38) hide show
  1. package/.storybook/{main.js → main.ts} +9 -1
  2. package/.storybook/{preview.jsx → preview.tsx} +3 -7
  3. package/CHANGELOG.md +28 -0
  4. package/README.md +29 -80
  5. package/build-storybook.log +491 -0
  6. package/index.html +1 -1
  7. package/package.json +54 -19
  8. package/src/App.tsx +29 -0
  9. package/src/{stories/PixiImageSprite/PixiImageSprite.stories.js → components/PixiImageSprite/PixiImageSprite.stories.tsx} +25 -8
  10. package/src/components/PixiImageSprite/PixiImageSprite.tsx +346 -0
  11. package/src/components/PixiImageSprite/index.ts +1 -0
  12. package/src/hooks/usePixiTransformer.tsx +168 -0
  13. package/src/index.ts +3 -0
  14. package/src/providers/{GsapPixieContextProvider.jsx → GsapPixieContextProvider.tsx} +27 -24
  15. package/src/providers/index.ts +1 -0
  16. package/src/stories/Introduction.mdx +0 -99
  17. package/src/types/transformation.tsx +13 -0
  18. package/src/utils/AppStateProvider.tsx +70 -0
  19. package/src/utils/AppStateStage.tsx +27 -0
  20. package/src/utils/AppWrapper.tsx +43 -0
  21. package/src/utils/ContextBridge.tsx +25 -0
  22. package/src/{providers/GsapAnim.jsx → utils/GsapAnim.tsx} +35 -4
  23. package/src/utils/PixiStage.tsx +33 -0
  24. package/src/utils/VideoSeekBar.tsx +118 -0
  25. package/src/utils/useDeepEffect.tsx +23 -0
  26. package/src/vite-env.d.ts +1 -0
  27. package/tsconfig.json +37 -0
  28. package/tsconfig.node.json +10 -0
  29. package/{vite.config.js → vite.config.ts} +4 -2
  30. package/vitest.config.ts +11 -0
  31. package/src/App.jsx +0 -35
  32. package/src/index.js +0 -3
  33. package/src/providers/ContextBridge.jsx +0 -67
  34. package/src/providers/VideoSeekBar.jsx +0 -186
  35. package/src/providers/index.js +0 -3
  36. package/src/stories/PixiImageSprite/PixiImageSprite.jsx +0 -318
  37. package/src/stories/PixiImageSprite/index.js +0 -1
  38. /package/src/{main.jsx → main.tsx} +0 -0
package/index.html CHANGED
@@ -8,6 +8,6 @@
8
8
  </head>
9
9
  <body>
10
10
  <div id="root"></div>
11
- <script type="module" src="/src/main.jsx"></script>
11
+ <script type="module" src="/src/main.tsx"></script>
12
12
  </body>
13
13
  </html>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "reacthub-pixitweenjs",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "description": "reacthub-pixitweenjs is a library that provides a powerful combination of React, PixiJS, GSAP, and image manipulation capabilities in a timeline sequence. With this library, you can easily create stunning animations and interactive graphics for your React applications",
5
5
  "author": "khanzzirfan",
6
6
  "type": "module",
@@ -12,19 +12,21 @@
12
12
  "url": "https://github.com/khanzzirfan/reacthub-gsap-pixiez/issues"
13
13
  },
14
14
  "license": "MIT",
15
- "dependencies": {
16
- "react": "^18.2.0",
17
- "react-dom": "^18.2.0"
18
- },
15
+ "dependencies": {},
19
16
  "scripts": {
20
17
  "dev": "vite",
21
- "build": "vite build",
18
+ "build": "tsc && vite build",
19
+ "lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
20
+ "lint:fix": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0 --fix",
21
+ "format": "prettier --write \"src/**/*.{ts,tsx,js,jsx,json,md}\"",
22
22
  "preview": "vite preview",
23
+ "test": "vitest",
23
24
  "storybook": "storybook dev -p 6006",
24
25
  "start": "npm run storybook",
25
26
  "build-storybook": "storybook build",
26
27
  "init-msw": "msw init public/",
27
- "release": "standard-version --release-as patch &&npm publish"
28
+ "release": "standard-version --release-as patch &&npm publish",
29
+ "chromatic": "env-cmd -f .env.dev chromatic"
28
30
  },
29
31
  "devDependencies": {
30
32
  "@chakra-ui/icons": "^2.0.15",
@@ -45,17 +47,39 @@
45
47
  "@pixi/react": "7.0.0",
46
48
  "@pixi/sound": "^4.3.1",
47
49
  "@react-gifs/tools": "^0.1.2",
48
- "@storybook/addon-essentials": "^7.0.6",
49
- "@storybook/addon-interactions": "^7.0.6",
50
- "@storybook/addon-links": "^7.0.6",
51
- "@storybook/blocks": "^7.0.6",
50
+ "@storybook/addon-essentials": "^7.1.0",
51
+ "@storybook/addon-interactions": "^7.1.0",
52
+ "@storybook/addon-links": "^7.1.0",
53
+ "@storybook/addon-onboarding": "^1.0.7",
54
+ "@storybook/addon-styling": "^1.3.4",
55
+ "@storybook/blocks": "^7.1.0",
56
+ "@storybook/builder-vite": "^7.1.0",
57
+ "@storybook/react": "^7.1.0",
58
+ "@storybook/react-vite": "^7.1.0",
59
+ "@storybook/testing-library": "^0.2.0",
60
+ "@testing-library/dom": "^9.3.1",
61
+ "@testing-library/jest-dom": "^5.17.0",
62
+ "@testing-library/react": "^14.0.0",
63
+ "@types/dotenv": "^8.2.0",
64
+ "@types/react": "^18.2.15",
65
+ "@types/react-dom": "^18.2.7",
66
+ "@typescript-eslint/eslint-plugin": "^5.62.0",
67
+ "@typescript-eslint/parser": "^5.62.0",
68
+ "@vitejs/plugin-react": "^4.0.3",
69
+ "@vitejs/plugin-react-swc": "^3.3.2",
52
70
  "@storybook/jest": "^0.1.0",
53
- "@storybook/react": "^7.0.6",
54
- "@storybook/react-vite": "^7.0.6",
55
- "@storybook/testing-library": "^0.0.14-next.2",
56
- "@types/react": "^18.0.28",
57
- "@types/react-dom": "^18.0.11",
58
- "@vitejs/plugin-react": "^3.1.0",
71
+ "jsdom": "^21.1.2",
72
+ "eslint": "^8.45.0",
73
+ "eslint-config-airbnb": "^19.0.4",
74
+ "eslint-config-airbnb-typescript": "^17.1.0",
75
+ "eslint-plugin-react-hooks": "^4.6.0",
76
+ "eslint-plugin-react-refresh": "^0.3.5",
77
+ "eslint-plugin-storybook": "^0.6.12",
78
+ "react-fast-compare": "^3.2.0",
79
+ "chromatic": "^6.7.3",
80
+ "debug": "^4.3.4",
81
+ "dotenv": "^16.0.1",
82
+ "env-cmd": "^10.1.0",
59
83
  "framer-motion": "^8.4.0",
60
84
  "gsap": "3.11.5",
61
85
  "lodash": "4.17.21",
@@ -67,9 +91,20 @@
67
91
  "prop-types": "^15.8.1",
68
92
  "react-custom-events": "^1.1.1",
69
93
  "react-gsap": "^3.2.1",
70
- "storybook": "^7.0.6",
94
+ "react": "^18.2.0",
95
+ "react-dom": "^18.2.0",
71
96
  "storybook-react-context": "^0.6.0",
72
97
  "standard-version": "^9.5.0",
73
- "vite": "^4.2.0"
98
+ "storybook": "^7.1.0",
99
+ "stylelint": "^15.10.2",
100
+ "stylelint-config-prettier": "^9.0.5",
101
+ "stylelint-config-recommended-scss": "^11.0.0",
102
+ "stylelint-config-standard": "^33.0.0",
103
+ "typescript": "^5.1.6",
104
+ "typescript-plugin-css-modules": "^5.0.1",
105
+ "vite": "^4.4.4",
106
+ "vite-plugin-environment": "^1.1.3",
107
+ "vite-plugin-stylelint": "^4.3.0",
108
+ "vitest": "^0.30.1"
74
109
  }
75
110
  }
package/src/App.tsx ADDED
@@ -0,0 +1,29 @@
1
+ import { useState } from "react";
2
+ import "./App.css";
3
+
4
+ function App() {
5
+ const [count, setCount] = useState(0);
6
+
7
+ return (
8
+ <div className="App">
9
+ <div>
10
+ <a href="https://vitejs.dev" target="_blank"></a>
11
+ <a href="https://reactjs.org" target="_blank"></a>
12
+ </div>
13
+ <h1>Vite + React</h1>
14
+ <div className="card">
15
+ <button onClick={() => setCount((count) => count + 1)}>
16
+ count is {count}
17
+ </button>
18
+ <p>
19
+ Edit <code>src/App.jsx</code> and save to test HMR
20
+ </p>
21
+ </div>
22
+ <p className="read-the-docs">
23
+ Click on the Vite and React logos to learn more
24
+ </p>
25
+ </div>
26
+ );
27
+ }
28
+
29
+ export default App;
@@ -1,13 +1,16 @@
1
- import { PixiImageSprite } from "./PixiImageSprite";
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { PixiImageSprite } from ".";
3
+
2
4
  // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction
3
- export default {
5
+ const meta = {
4
6
  title: "Components/ImageSprite",
5
7
  component: PixiImageSprite,
8
+
6
9
  tags: ["autodocs"],
7
10
  argTypes: {
8
- backgroundColor: {
9
- control: "color",
10
- description: "background color for the application stage",
11
+ uniqueId: {
12
+ control: "text",
13
+ description: "uniqueId of the sprite",
11
14
  },
12
15
  src: {
13
16
  control: "text",
@@ -55,12 +58,25 @@ export default {
55
58
  max: 1,
56
59
  description: "sprite initial alpha value (default 1)",
57
60
  },
61
+ onAnchorTransformationEnd: {
62
+ action: "onAnchorTransformationEnd",
63
+ description:
64
+ "on transforamtion end the event is fire callback with latest sprite transformation properties.",
65
+ },
66
+ pointerdown: {
67
+ action: "pointerdown",
68
+ description: "pointerdown event",
69
+ },
58
70
  },
59
- };
71
+ } satisfies Meta<typeof PixiImageSprite>;
72
+
73
+ export default meta;
74
+ type Story = StoryObj<typeof meta>;
60
75
 
61
76
  // More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args
62
- export const Normal = {
77
+ export const Normal: Story = {
63
78
  args: {
79
+ uniqueId: "surya001", // uniqueId of the sprite
64
80
  src: "https://assets.codepen.io/693612/surya.svg",
65
81
  transformation: {
66
82
  x: 100,
@@ -82,8 +98,9 @@ export const Normal = {
82
98
  },
83
99
  };
84
100
 
85
- export const FadeIn = {
101
+ export const FadeIn: Story = {
86
102
  args: {
103
+ uniqueId: "surya002", // uniqueId of the sprite
87
104
  src: "https://assets.codepen.io/693612/surya.svg",
88
105
  transformation: {
89
106
  x: 100,
@@ -0,0 +1,346 @@
1
+ import * as React from "react";
2
+ import { useContext, useEffect, useRef, useState } from "react";
3
+ // @ts-ignore
4
+ import PropTypes from "prop-types";
5
+ import { GsapPixieContext } from "../../providers/GsapPixieContextProvider";
6
+ import { Sprite, Container, useApp, withFilters } from "@pixi/react";
7
+ import { AdjustmentFilter } from "@pixi/filter-adjustment";
8
+ import * as PIXI from "pixi.js";
9
+ import gsap from "gsap";
10
+ // @ts-ignore
11
+ import isEmpty from "lodash/isEmpty";
12
+ import { getAnimByName } from "../../utils/GsapAnim";
13
+ import { usePixiTransformer } from "../../hooks/usePixiTransformer";
14
+ import { TransformationEnd } from "../../types/transformation";
15
+
16
+ type PixiImageSpriteProps = {
17
+ uniqueId: string;
18
+ src: string;
19
+ startAt: number;
20
+ endAt: number;
21
+ initialAlpha: number;
22
+ transformation: {
23
+ x: number;
24
+ y: number;
25
+ width: number;
26
+ height: number;
27
+ anchor: number;
28
+ rotation?: number;
29
+ alpha?: number;
30
+ scale?: number | [number, number];
31
+ tint?: number;
32
+ blendMode?: number;
33
+ animation?: string;
34
+ colorCorrection?: {
35
+ enabled?: boolean;
36
+ temperature?: number;
37
+ hue?: number;
38
+ contrast?: number;
39
+ saturation?: number;
40
+ exposure?: number;
41
+ reset?: boolean;
42
+ sharpness?: number;
43
+ value?: number;
44
+ levels?: number;
45
+ luminance?: number;
46
+ enhance?: number;
47
+ blurRadius?: number;
48
+ red?: number;
49
+ green?: number;
50
+ blue?: number;
51
+ alpha?: number;
52
+ scaleInput?: number;
53
+ };
54
+ effect?: string;
55
+ };
56
+ pointerdown?: () => void;
57
+ pointerup?: () => void;
58
+ mousedown?: () => void;
59
+ mouseup?: () => void;
60
+ pointerover?: () => void;
61
+ mouseover?: () => void;
62
+ mouseout?: () => void;
63
+ applyTransformer?: boolean;
64
+ onAnchorTransformationEnd?: (endData: any) => void;
65
+ };
66
+
67
+ type EffectFunc = () => void;
68
+ type Deps = ReadonlyArray<unknown>;
69
+
70
+ const Filters = withFilters(Container, {
71
+ blur: PIXI.filters.BlurFilter,
72
+ adjust: AdjustmentFilter,
73
+ matrix: PIXI.filters.ColorMatrixFilter,
74
+ });
75
+
76
+ /** filter config */
77
+ const config = {
78
+ dot: {
79
+ scale: 1,
80
+ angle: 5,
81
+ },
82
+ blur: {
83
+ blur: 0,
84
+ quality: 4,
85
+ },
86
+ };
87
+
88
+ /** CYAN Filters */
89
+ const CYAN = [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0];
90
+
91
+ const PixiImageSprite: React.FC<PixiImageSpriteProps> = (props) => {
92
+ //// State
93
+ const [transform, setTransform] = useState({
94
+ x: 0,
95
+ y: 0,
96
+ width: 80,
97
+ height: 80,
98
+ rotate: 0,
99
+ });
100
+ const [isTransformerDragging, setIsTransformerDragging] = useState(false);
101
+ const [isMouseOverTransformer, setIsMouseOverTransformer] = useState(false);
102
+
103
+ console.log("allProps", props);
104
+ //// Refs
105
+ const imageRef = useRef<PIXI.Sprite>(null);
106
+ const containerRef = useRef<PIXI.Container>(null);
107
+ const parentNode = useRef<PIXI.Container>(null);
108
+ const imgGroupRef = useRef<PIXI.Container>(null);
109
+
110
+ //// Context
111
+ const { tl } = useContext(GsapPixieContext);
112
+
113
+ /// 1001
114
+ console.log("contxt Values", tl);
115
+ const {
116
+ uniqueId,
117
+ src,
118
+ startAt,
119
+ endAt,
120
+ initialAlpha,
121
+ transformation: {
122
+ x,
123
+ y,
124
+ width,
125
+ height,
126
+ anchor,
127
+ animation,
128
+ colorCorrection,
129
+ effect,
130
+ },
131
+ pointerdown,
132
+ pointerup,
133
+ mousedown,
134
+ mouseup,
135
+ pointerover,
136
+ mouseover,
137
+ mouseout,
138
+ applyTransformer,
139
+ onAnchorTransformationEnd,
140
+ ...restProps
141
+ } = props;
142
+
143
+ // color corrections
144
+ const {
145
+ enabled = false,
146
+ temperature = 1,
147
+ hue = 1,
148
+ contrast = 1,
149
+ saturation = 1,
150
+ exposure = 1,
151
+ reset,
152
+ sharpness = 1,
153
+ value = 0,
154
+ levels = 1,
155
+ luminance = 0,
156
+ enhance = 0,
157
+ blurRadius = 0,
158
+ red = 150,
159
+ green = 150,
160
+ blue = 150,
161
+ alpha = 1,
162
+ scaleInput = 1,
163
+ } = colorCorrection || {};
164
+
165
+ const app = useApp();
166
+ const PixiTransformer = useRef<any>(null);
167
+
168
+ /** adjustment filter */
169
+ const adjustments = {
170
+ brightness: exposure,
171
+ contrast,
172
+ saturation,
173
+ alpha,
174
+ };
175
+
176
+ // transformer to handle sprite transformation
177
+ const handleOnTransformEnd = React.useCallback(
178
+ (endData: TransformationEnd) => {
179
+ console.log("changeEnd", endData);
180
+ if (onAnchorTransformationEnd) {
181
+ onAnchorTransformationEnd(endData);
182
+ }
183
+ },
184
+ [],
185
+ );
186
+
187
+ // initialize usePixiTransformer hook
188
+ const { handleTransformer, removeTransformer, isDragging } =
189
+ usePixiTransformer({
190
+ uniqueId,
191
+ onTransformEnd: handleOnTransformEnd,
192
+ events: {},
193
+ mouseoverEvent: setIsMouseOverTransformer,
194
+ setDragging: setIsTransformerDragging,
195
+ });
196
+
197
+ useEffect(() => {
198
+ let ctx = gsap.context(() => {});
199
+ if (containerRef.current && tl.current) {
200
+ const data = {
201
+ duration: Number(endAt) - Number(startAt),
202
+ };
203
+
204
+ const ease = getAnimByName(animation || "None");
205
+ ctx = gsap.context(() => {
206
+ if (!isEmpty(ease.from)) {
207
+ tl.current
208
+ .from(containerRef.current, { ...ease.from }, startAt)
209
+ .to(imgGroupRef.current, { alpha: 1, duration: 0.2 }, startAt)
210
+ .from(imgGroupRef.current, { ...data }, startAt)
211
+ .to(containerRef.current, { alpha: 0, duration: 0.2 }, endAt - 0.2);
212
+ } else if (!isEmpty(ease.to)) {
213
+ tl.current
214
+ .to(
215
+ containerRef.current,
216
+ { alpha: 1, duration: 0.2, ...ease.to },
217
+ startAt,
218
+ )
219
+ .from(imgGroupRef.current, { ...data }, startAt)
220
+ .to(containerRef.current, { alpha: 0, duration: 0.2 }, endAt - 0.2);
221
+ } else if (!isEmpty(ease.fromTo)) {
222
+ tl.current
223
+ .fromTo(
224
+ containerRef.current,
225
+ ease.fromTo?.from,
226
+ ease.fromTo?.to,
227
+ startAt,
228
+ )
229
+ .from(imgGroupRef.current, { ...data }, startAt)
230
+ .to(containerRef.current, { alpha: 0, duration: 0.2 }, endAt - 0.2);
231
+ } else {
232
+ tl.current
233
+ .to(containerRef.current, { alpha: 1, duration: 0.01 }, startAt)
234
+ .from(imgGroupRef.current, { ...data }, startAt)
235
+ .to(
236
+ containerRef.current,
237
+ { alpha: 0, duration: 0.1 },
238
+ Number(endAt) - Number(0.1),
239
+ );
240
+ }
241
+ });
242
+ }
243
+ return () => ctx.revert(); // cleanup!
244
+ }, [animation, startAt, endAt]);
245
+
246
+ useEffect(() => {
247
+ setIsTransformerDragging(isDragging);
248
+ }, [isDragging]);
249
+
250
+ // apply transformer in use effect hook based on prop applyTransformer
251
+ useEffect(() => {
252
+ if (applyTransformer && containerRef.current && parentNode.current) {
253
+ handleTransformer(containerRef.current, parentNode.current);
254
+ }
255
+ return () => {
256
+ removeTransformer();
257
+ };
258
+ }, [removeTransformer, handleTransformer, applyTransformer]);
259
+
260
+ return (
261
+ // @ts-ignore
262
+ <Container ref={parentNode}>
263
+ {/* @ts-ignore */}
264
+ <Container
265
+ ref={containerRef}
266
+ alpha={initialAlpha}
267
+ position={[x, y]}
268
+ pivot={[x, y]}
269
+ width={width}
270
+ height={height}
271
+ >
272
+ {colorCorrection && colorCorrection.enabled ? (
273
+ <Filters
274
+ scale={1}
275
+ blur={{ blur: blurRadius, quality: 4 }}
276
+ adjust={adjustments}
277
+ apply={({ matrix }: { matrix: any }) => {
278
+ if (effect === "BlackAndWhite") {
279
+ matrix.desaturate();
280
+ } else if (effect === "Sepia") {
281
+ matrix.sepia();
282
+ } else if (effect === "RetroVintage") {
283
+ matrix.negative();
284
+ } else if (effect === "NightVision") {
285
+ matrix.negative();
286
+ } else if (effect === "Normal") {
287
+ matrix.reset();
288
+ }
289
+ }}
290
+ matrix={{
291
+ enabled: true,
292
+ // @ts-ignore
293
+ matrix: CYAN,
294
+ }}
295
+ >
296
+ {/* @ts-ignore */}
297
+ <Container ref={imgGroupRef}>
298
+ <Sprite
299
+ image={src}
300
+ width={width}
301
+ height={height}
302
+ anchor={anchor}
303
+ ref={imageRef}
304
+ x={x}
305
+ y={y}
306
+ // @ts-ignore
307
+ interactive={true}
308
+ pointerdown={pointerdown}
309
+ pointerup={pointerup}
310
+ pointerover={pointerover}
311
+ mousedown={mousedown}
312
+ mouseup={mouseup}
313
+ mouseover={mouseover}
314
+ mouseout={mouseout}
315
+ />
316
+ </Container>
317
+ </Filters>
318
+ ) : (
319
+ // @ts-ignore
320
+ <Container ref={imgGroupRef}>
321
+ <Sprite
322
+ image={src}
323
+ width={width}
324
+ height={height}
325
+ anchor={anchor}
326
+ ref={imageRef}
327
+ x={x}
328
+ y={y}
329
+ // @ts-ignore
330
+ interactive={true}
331
+ pointerdown={pointerdown}
332
+ pointerup={pointerup}
333
+ pointerover={pointerover}
334
+ mousedown={mousedown}
335
+ mouseup={mouseup}
336
+ mouseover={mouseover}
337
+ mouseout={mouseout}
338
+ />
339
+ </Container>
340
+ )}
341
+ </Container>
342
+ </Container>
343
+ );
344
+ };
345
+
346
+ export default PixiImageSprite;
@@ -0,0 +1 @@
1
+ export { default as PixiImageSprite } from "./PixiImageSprite";