reacthub-pixitweenjs 0.2.3 → 0.2.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.
Files changed (57) hide show
  1. package/.storybook/{main.js → main.ts} +9 -1
  2. package/.storybook/{preview.jsx → preview.tsx} +3 -7
  3. package/CHANGELOG.md +40 -0
  4. package/README.md +21 -2
  5. package/build-storybook.log +94 -0
  6. package/index.html +1 -1
  7. package/package.json +68 -36
  8. package/src/App.tsx +29 -0
  9. package/src/components/PixiAnimatedSprite/PixiAnimatedSprite.tsx +51 -0
  10. package/src/components/PixiAnimatedSprite/index.ts +2 -0
  11. package/src/components/PixiAudioSprite/PixiAudioSprite.stories.tsx +61 -0
  12. package/src/components/PixiAudioSprite/PixiAudioSprite.tsx +212 -0
  13. package/src/components/PixiAudioSprite/index.ts +1 -0
  14. package/src/components/PixiGifSprite/PixiGifSprite.stories.tsx +135 -0
  15. package/src/components/PixiGifSprite/PixiGifSprite.tsx +451 -0
  16. package/src/components/PixiGifSprite/index.ts +2 -0
  17. package/src/{stories/PixiImageSprite/PixiImageSprite.stories.js → components/PixiImageSprite/PixiImageSprite.stories.tsx} +36 -8
  18. package/src/components/PixiImageSprite/PixiImageSprite.tsx +340 -0
  19. package/src/components/PixiImageSprite/index.ts +1 -0
  20. package/src/components/PixiSVGSprite/PixiSvgPathSprite.stories.tsx +137 -0
  21. package/src/components/PixiSVGSprite/PixiSvgPathSprite.tsx +378 -0
  22. package/src/components/PixiSVGSprite/index.ts +1 -0
  23. package/src/components/PixiVideoSprite/PixiVideoSprite.stories.tsx +147 -0
  24. package/src/components/PixiVideoSprite/PixiVideoSprite.tsx +684 -0
  25. package/src/components/PixiVideoSprite/PixiVideoSpriteBackup.txt +755 -0
  26. package/src/components/PixiVideoSprite/index.ts +1 -0
  27. package/src/declare.module.ts +5 -0
  28. package/src/hooks/usePixiTransformer.tsx +168 -0
  29. package/src/index.ts +3 -0
  30. package/src/providers/GsapPixieContextProvider.tsx +251 -0
  31. package/src/providers/index.ts +1 -0
  32. package/src/reacthub-react-bindings.d.ts +27 -0
  33. package/src/types/transformation.tsx +13 -0
  34. package/src/utils/AppStateProvider.tsx +59 -0
  35. package/src/utils/AppStateStage.tsx +27 -0
  36. package/src/utils/AppWrapper.tsx +43 -0
  37. package/src/utils/ContextBridge.tsx +25 -0
  38. package/src/{providers/GsapAnim.jsx → utils/GsapAnim.tsx} +35 -4
  39. package/src/utils/PixiStage.tsx +29 -0
  40. package/src/utils/PixiTransformer.tsx +100 -0
  41. package/src/utils/VideoSeekBar.tsx +129 -0
  42. package/src/utils/useDebounce.tsx +15 -0
  43. package/src/utils/useDeepEffect.tsx +23 -0
  44. package/src/vite-env.d.ts +1 -0
  45. package/tsconfig.json +37 -0
  46. package/tsconfig.node.json +10 -0
  47. package/{vite.config.js → vite.config.ts} +4 -2
  48. package/vitest.config.ts +11 -0
  49. package/src/App.jsx +0 -35
  50. package/src/index.js +0 -3
  51. package/src/providers/ContextBridge.jsx +0 -67
  52. package/src/providers/GsapPixieContextProvider.jsx +0 -162
  53. package/src/providers/VideoSeekBar.jsx +0 -186
  54. package/src/providers/index.js +0 -3
  55. package/src/stories/PixiImageSprite/PixiImageSprite.jsx +0 -318
  56. package/src/stories/PixiImageSprite/index.js +0 -1
  57. /package/src/{main.jsx → main.tsx} +0 -0
@@ -0,0 +1,451 @@
1
+ import * as React from "react";
2
+ import { useContext, useEffect, useRef, useState } from "react";
3
+ // @ts-ignore
4
+ import map from "lodash/map";
5
+ // @ts-ignore
6
+ import PropTypes from "prop-types";
7
+ import { GsapPixieContext } from "../../providers/GsapPixieContextProvider";
8
+ import { Container, useApp, withFilters, Graphics } from "@pixi/react";
9
+ import { AdjustmentFilter } from "@pixi/filter-adjustment";
10
+ import * as PIXI from "pixi.js";
11
+ import gsap from "gsap";
12
+ import { useWorkerParser, usePlayerState } from "@react-gifs/tools";
13
+ import PixiTransformer from "../../utils/PixiTransformer";
14
+
15
+ // @ts-ignore
16
+ import isEmpty from "lodash/isEmpty";
17
+ import { getAnimByName } from "../../utils/GsapAnim";
18
+ import { TransformationEnd } from "../../types/transformation";
19
+ import { PixiAnimatedSprite } from "../PixiAnimatedSprite";
20
+
21
+ type PixiGifSpriteProps = {
22
+ uniqueId: string;
23
+ src: string;
24
+ startAt: number;
25
+ endAt: number;
26
+ initialAlpha: number;
27
+ locked: boolean;
28
+ loop: boolean;
29
+ transformation: {
30
+ x: number;
31
+ y: number;
32
+ width: number;
33
+ height: number;
34
+ anchor: number;
35
+ rotation?: number;
36
+ alpha?: number;
37
+ scale?: number | [number, number];
38
+ tint?: number;
39
+ blendMode?: number;
40
+ animation?: string;
41
+ colorCorrection?: {
42
+ enabled?: boolean;
43
+ temperature?: number;
44
+ hue?: number;
45
+ contrast?: number;
46
+ saturation?: number;
47
+ exposure?: number;
48
+ reset?: boolean;
49
+ sharpness?: number;
50
+ value?: number;
51
+ levels?: number;
52
+ luminance?: number;
53
+ enhance?: number;
54
+ blurRadius?: number;
55
+ red?: number;
56
+ green?: number;
57
+ blue?: number;
58
+ alpha?: number;
59
+ scaleInput?: number;
60
+ };
61
+ effect?: string;
62
+ };
63
+ pointerdown?: () => void;
64
+ pointerup?: () => void;
65
+ mousedown?: () => void;
66
+ mouseup?: () => void;
67
+ pointerover?: () => void;
68
+ mouseover?: () => void;
69
+ mouseout?: () => void;
70
+ pointerout?: () => void;
71
+ applyTransformer?: boolean;
72
+ onAnchorTransformationEnd?: (endData: any) => void;
73
+ };
74
+
75
+ type EffectFunc = () => void;
76
+ type Deps = ReadonlyArray<unknown>;
77
+
78
+ const Filters = withFilters(Container, {
79
+ blur: PIXI.filters.BlurFilter,
80
+ adjust: AdjustmentFilter,
81
+ matrix: PIXI.filters.ColorMatrixFilter,
82
+ });
83
+
84
+ /** filter config */
85
+ const config = {
86
+ dot: {
87
+ scale: 1,
88
+ angle: 5,
89
+ },
90
+ blur: {
91
+ blur: 0,
92
+ quality: 4,
93
+ },
94
+ };
95
+
96
+ /** CYAN Filters */
97
+ const CYAN = [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0];
98
+
99
+ const initialState = {
100
+ isPlaying: false,
101
+ progress: 0,
102
+ speed: 1,
103
+ isMuted: false,
104
+ isWaiting: false,
105
+ loaded: false,
106
+ size: { width: 50, height: 50 },
107
+ play: false,
108
+ current: false,
109
+ };
110
+
111
+ /**
112
+ * PixiGifSprite Component is used to render gif image
113
+ * @param props Gif Sprite props
114
+ * @returns
115
+ */
116
+ const PixiGifSprite: React.FC<PixiGifSpriteProps> = (props) => {
117
+ //// State
118
+ const [gifFrame, setGifFrame] = React.useState<PIXI.Texture[]>([]);
119
+ const [gifDuration, setGifDuration] = React.useState<number>(0);
120
+ const [gifFrameObject, setGifFrameObject] = React.useState<
121
+ PIXI.FrameObject[]
122
+ >([]);
123
+ const [currentFrame, setCurrentFrame] = useState<number>(0);
124
+ const [isComplete, setIsComplete] = useState<boolean>(false);
125
+
126
+ const [isDragging, setIsDragging] = useState(false);
127
+ const [isMouseOverTransformer, setIsMouseOverTransformer] = useState(false);
128
+
129
+ const [gifState, update] = usePlayerState({ autoPlay: false });
130
+ const graphicRef = React.useRef<PIXI.Graphics>(null);
131
+ const gifStatusRef = React.useRef(false);
132
+
133
+ console.log("allProps", props);
134
+ //// Refs
135
+ const animatedSpriteRef = useRef<PIXI.AnimatedSprite>(null);
136
+ const containerRef = useRef<PIXI.Container>(null);
137
+ const parentNode = useRef<PIXI.Container>(null);
138
+ const imgGroupRef = useRef<PIXI.Container>(null);
139
+ const transformerRef = useRef<PIXI.Container>(null);
140
+
141
+ //// Context
142
+ const { tl, play: tlPlay } = useContext(GsapPixieContext);
143
+
144
+ /// 1001
145
+ console.log("contxt Values", tl);
146
+ console.log("gifState", gifState, gifDuration);
147
+ const {
148
+ index,
149
+ frames: gifFrames,
150
+ delays: gifDelays,
151
+ length,
152
+ loaded,
153
+ } = gifState;
154
+
155
+ const {
156
+ uniqueId,
157
+ src,
158
+ startAt,
159
+ endAt,
160
+ initialAlpha,
161
+ locked,
162
+ loop,
163
+ transformation: {
164
+ width = 0,
165
+ height = 0,
166
+ x,
167
+ y,
168
+ rotation = 0,
169
+ scale,
170
+ anchor,
171
+ animation,
172
+ colorCorrection,
173
+ effect,
174
+ },
175
+ pointerdown,
176
+ pointerup,
177
+ mousedown,
178
+ mouseup,
179
+ pointerover,
180
+ mouseover,
181
+ mouseout,
182
+ pointerout,
183
+ applyTransformer,
184
+ onAnchorTransformationEnd,
185
+ ...restProps
186
+ } = props;
187
+
188
+ // color corrections
189
+ const {
190
+ enabled = false,
191
+ temperature = 1,
192
+ hue = 1,
193
+ contrast = 1,
194
+ saturation = 1,
195
+ exposure = 1,
196
+ reset,
197
+ sharpness = 1,
198
+ value = 0,
199
+ levels = 1,
200
+ luminance = 0,
201
+ enhance = 0,
202
+ blurRadius = 0,
203
+ red = 150,
204
+ green = 150,
205
+ blue = 150,
206
+ alpha = 1,
207
+ scaleInput = 1,
208
+ } = colorCorrection || {};
209
+
210
+ const app = useApp();
211
+
212
+ /** adjustment filter */
213
+ const adjustments = {
214
+ brightness: exposure,
215
+ contrast,
216
+ saturation,
217
+ alpha,
218
+ };
219
+
220
+ // load and parse gif
221
+ useWorkerParser(src, update);
222
+
223
+ // updates current index
224
+ // usePlayback(gifState, () => update(({ index }) => ({ index: index + 1 })));
225
+
226
+ // transformer to handle sprite transformation
227
+ const handleOnTransformEnd = React.useCallback(
228
+ (endData: TransformationEnd) => {
229
+ console.log("changeEnd", endData);
230
+ if (onAnchorTransformationEnd) {
231
+ onAnchorTransformationEnd(endData);
232
+ }
233
+ },
234
+ []
235
+ );
236
+
237
+ React.useEffect(() => {
238
+ if (!isEmpty(gifFrames)) {
239
+ // app.stage.addChild(frames);
240
+ /// load textues
241
+ const texturedFrames = map(gifFrames, (eachFrame: ImageData) => {
242
+ const { data, width, height } = eachFrame;
243
+ const dataEx = new Uint8Array(data);
244
+ return PIXI.Texture.fromBuffer(dataEx, width, height);
245
+ });
246
+
247
+ const frameObj = texturedFrames.map(
248
+ (eachFrame: PIXI.Texture, index: number) => {
249
+ return {
250
+ texture: eachFrame,
251
+ time: gifDelays[index],
252
+ };
253
+ }
254
+ );
255
+
256
+ setGifFrame(texturedFrames);
257
+ setGifFrameObject(frameObj);
258
+ let duration = 0;
259
+ gifDelays.forEach((delay) => {
260
+ duration += delay * 10;
261
+ });
262
+ setGifDuration(duration);
263
+ }
264
+ }, [gifFrames, gifDelays]);
265
+
266
+ /** Gsap Start and Stop Events */
267
+ const gsapOnStart = (startAt: number) => {
268
+ if (animatedSpriteRef.current) {
269
+ animatedSpriteRef.current.gotoAndPlay(startAt || 0);
270
+ }
271
+ };
272
+
273
+ const gsapOnPause = (startAt: number) => {
274
+ // console.log(`gsap onStart ${droptype} id`, refId);
275
+ // console.log(elementRefs.current[refId]);
276
+ if (animatedSpriteRef.current) {
277
+ animatedSpriteRef.current.stop();
278
+ }
279
+ };
280
+
281
+ const gsapOnComplete = () => {
282
+ if (animatedSpriteRef.current) {
283
+ animatedSpriteRef.current.stop();
284
+ // animatedSpriteRef.current.gotoAndStop(0);
285
+ }
286
+ };
287
+
288
+ const onInterrupt = () => {
289
+ // console.log('interrupting', refId);
290
+ };
291
+
292
+ const onUpdate = () => {
293
+ // console.log('timeline paused', ctxTimeLine.paused());
294
+ // if (animatedSpriteRef.current) {
295
+ // animatedSpriteRef.current.play();
296
+ // dispatchState({
297
+ // play: play,
298
+ // });
299
+ // }
300
+ };
301
+
302
+ const handleComplete = () => {
303
+ setIsComplete(true);
304
+ // if (onComplete) {
305
+ // onComplete();
306
+ // }
307
+ };
308
+
309
+ useEffect(() => {
310
+ let ctx = gsap.context(() => {});
311
+ if (containerRef.current && tl.current) {
312
+ const data = {
313
+ duration: Number(endAt) - Number(startAt),
314
+ onStart: gsapOnStart,
315
+ onComplete: gsapOnComplete,
316
+ onStartParams: [startAt],
317
+ onCompleteParams: [],
318
+ onInterrupt: onInterrupt,
319
+ onUpdate: onUpdate,
320
+ onUpdateParams: [],
321
+ };
322
+
323
+ const ease = getAnimByName(animation || "None");
324
+ ctx = gsap.context(() => {
325
+ if (!isEmpty(ease.from)) {
326
+ tl.current
327
+ .from(containerRef.current, { ...ease.from }, startAt)
328
+ .to(imgGroupRef.current, { alpha: 1, duration: 0.2 }, startAt)
329
+ .from(imgGroupRef.current, { ...data }, startAt)
330
+ .to(containerRef.current, { alpha: 0, duration: 0.2 }, endAt - 0.2);
331
+ } else if (!isEmpty(ease.to)) {
332
+ tl.current
333
+ .to(
334
+ containerRef.current,
335
+ { alpha: 1, duration: 0.2, ...ease.to },
336
+ startAt
337
+ )
338
+ .from(imgGroupRef.current, { ...data }, startAt)
339
+ .to(containerRef.current, { alpha: 0, duration: 0.2 }, endAt - 0.2);
340
+ } else if (!isEmpty(ease.fromTo)) {
341
+ tl.current
342
+ .fromTo(
343
+ containerRef.current,
344
+ ease.fromTo?.from,
345
+ ease.fromTo?.to,
346
+ startAt
347
+ )
348
+ .from(imgGroupRef.current, { ...data }, startAt)
349
+ .to(containerRef.current, { alpha: 0, duration: 0.2 }, endAt - 0.2);
350
+ } else {
351
+ tl.current
352
+ .to(containerRef.current, { alpha: 1, duration: 0.01 }, startAt)
353
+ .from(imgGroupRef.current, { ...data }, startAt)
354
+ .to(
355
+ containerRef.current,
356
+ { alpha: 0, duration: 0.1 },
357
+ Number(endAt) - Number(0.1)
358
+ );
359
+ }
360
+ });
361
+ }
362
+ return () => ctx.revert(); // cleanup!
363
+ }, [animation, startAt, endAt]);
364
+
365
+ /** handle on tranformer onchange */
366
+ const handleOnTransformChange = React.useCallback(() => {
367
+ setIsDragging(true);
368
+ }, []);
369
+
370
+ app.ticker.add((delta) => {
371
+ if (graphicRef.current) {
372
+ graphicRef.current.rotation += 0.01 * delta;
373
+ graphicRef.current
374
+ .clear()
375
+ .lineStyle(4, 0xffffff, 1)
376
+ .moveTo(40, 0)
377
+ .arc(0, 0, 40, 0, Math.PI * 2 * 0.6, false);
378
+ }
379
+ });
380
+
381
+ const draw = React.useCallback((g: PIXI.Graphics) => {
382
+ g.clear();
383
+ }, []);
384
+
385
+ return (
386
+ // @ts-ignore
387
+ <Container ref={parentNode}>
388
+ {/* @ts-ignore */}
389
+ <Container
390
+ ref={containerRef}
391
+ alpha={initialAlpha}
392
+ position={[x, y]}
393
+ pivot={[x, y]}
394
+ width={width}
395
+ height={height}
396
+ >
397
+ {/* @ts-ignore */}
398
+ <Container ref={imgGroupRef}>
399
+ {!loaded && (
400
+ // @ts-ignore
401
+ <Container anchor={0.5} position={[width / 2, height / 2]}>
402
+ <Graphics x={x} y={y} ref={graphicRef} draw={draw} />
403
+ </Container>
404
+ )}
405
+ {gifFrame && gifFrame.length > 0 && (
406
+ <PixiAnimatedSprite
407
+ x={x}
408
+ y={y}
409
+ width={width}
410
+ height={height}
411
+ rotation={rotation}
412
+ animationSpeed={1}
413
+ loop={loop}
414
+ isPlaying={!!tlPlay}
415
+ // @ts-ignore
416
+ textures={gifFrameObject}
417
+ onComplete={handleComplete}
418
+ onFrameChange={(currentFrame: number) =>
419
+ setCurrentFrame(currentFrame)
420
+ }
421
+ anchor={0.5}
422
+ {...(!locked &&
423
+ !isDragging && {
424
+ interactive: true,
425
+ buttonMode: true,
426
+ pointerdown: pointerdown,
427
+ pointerover: pointerover,
428
+ pointerout: pointerout,
429
+ })}
430
+ forwardRef={animatedSpriteRef}
431
+ scale={scale}
432
+ />
433
+ )}
434
+ </Container>
435
+ </Container>
436
+ {applyTransformer && (
437
+ <PixiTransformer
438
+ pixiTransformerRef={transformerRef}
439
+ imageRef={containerRef}
440
+ isMounted={loaded}
441
+ transformCommit={handleOnTransformEnd}
442
+ transformChange={handleOnTransformChange}
443
+ mouseoverEvent={setIsMouseOverTransformer}
444
+ uniqueId={uniqueId}
445
+ />
446
+ )}
447
+ </Container>
448
+ );
449
+ };
450
+
451
+ export default PixiGifSprite;
@@ -0,0 +1,2 @@
1
+ export { default as PixiGifSprite } from "./PixiGifSprite";
2
+ export * from "./PixiGifSprite";
@@ -1,13 +1,17 @@
1
- import { PixiImageSprite } from "./PixiImageSprite";
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { PixiImageSprite } from ".";
3
+ import { AppStateContextProvider } from "../../utils/AppStateProvider";
4
+
2
5
  // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction
3
- export default {
6
+ const meta = {
4
7
  title: "Components/ImageSprite",
5
8
  component: PixiImageSprite,
9
+
6
10
  tags: ["autodocs"],
7
11
  argTypes: {
8
- backgroundColor: {
9
- control: "color",
10
- description: "background color for the application stage",
12
+ uniqueId: {
13
+ control: "text",
14
+ description: "uniqueId of the sprite",
11
15
  },
12
16
  src: {
13
17
  control: "text",
@@ -55,12 +59,30 @@ export default {
55
59
  max: 1,
56
60
  description: "sprite initial alpha value (default 1)",
57
61
  },
62
+ onAnchorTransformationEnd: {
63
+ action: "onAnchorTransformationEnd",
64
+ description:
65
+ "on transforamtion end the event is fire callback with latest sprite transformation properties.",
66
+ },
67
+ pointerdown: {
68
+ action: "pointerdown",
69
+ description: "pointerdown event",
70
+ },
58
71
  },
59
- };
72
+ } satisfies Meta<typeof PixiImageSprite>;
73
+
74
+ export default meta;
75
+ type Story = StoryObj<typeof meta>;
60
76
 
61
77
  // More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args
62
- export const Normal = {
78
+ export const Normal: Story = {
79
+ render: (args: any) => (
80
+ <AppStateContextProvider {...args}>
81
+ <PixiImageSprite {...args} />
82
+ </AppStateContextProvider>
83
+ ),
63
84
  args: {
85
+ uniqueId: "surya001", // uniqueId of the sprite
64
86
  src: "https://assets.codepen.io/693612/surya.svg",
65
87
  transformation: {
66
88
  x: 100,
@@ -82,8 +104,14 @@ export const Normal = {
82
104
  },
83
105
  };
84
106
 
85
- export const FadeIn = {
107
+ export const FadeIn: Story = {
108
+ render: (args: any) => (
109
+ <AppStateContextProvider {...args}>
110
+ <PixiImageSprite {...args} />
111
+ </AppStateContextProvider>
112
+ ),
86
113
  args: {
114
+ uniqueId: "surya002", // uniqueId of the sprite
87
115
  src: "https://assets.codepen.io/693612/surya.svg",
88
116
  transformation: {
89
117
  x: 100,