reacthub-pixitweenjs 0.2.5 → 0.2.6

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.
@@ -0,0 +1,540 @@
1
+ import * as React from "react";
2
+ import { useContext, useEffect, useRef, useState } from "react";
3
+ import { Container, withFilters, Text } from "@pixi/react";
4
+ import { AdjustmentFilter } from "@pixi/filter-adjustment";
5
+ import * as PIXI from "pixi.js";
6
+ import gsap from "gsap";
7
+ import Quill from "quill";
8
+ import "quill/dist/quill.snow.css";
9
+ // @ts-ignore
10
+ import PropTypes from "prop-types";
11
+ // @ts-ignore
12
+ import isEmpty from "lodash/isEmpty";
13
+ // @ts-ignore
14
+ import isEqual from "lodash/isEqual";
15
+ // @ts-ignore
16
+ import pick from "lodash/pick";
17
+ import { GsapPixieContext } from "../../providers/GsapPixieContextProvider";
18
+ import PixiTransformer from "../../utils/PixiTransformer";
19
+ import { getAnimByName } from "../../utils/GsapAnim";
20
+ import { TransformationEnd } from "../../types/transformation";
21
+
22
+ type PixiTextSpriteProps = {
23
+ uniqueId: string;
24
+ text: string;
25
+ startAt: number;
26
+ endAt: number;
27
+ initialAlpha: number;
28
+ locked: 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
+ fontWeight?: string;
42
+ fontSize?: number;
43
+ fontFamily?: string;
44
+ fontStyle?: string;
45
+ fontColor?: string;
46
+ fontVariant?: string;
47
+ lineHeight?: number;
48
+ letterSpacing?: number;
49
+ textDecoration?: string;
50
+ wordWrap?: boolean;
51
+ wordWrapWidth?: number;
52
+ leading?: number;
53
+ padding?: number;
54
+ border?: string;
55
+ dropShadow?: boolean;
56
+ dropShadowColor?: string | number;
57
+ shadowOffsetX?: number;
58
+ shadowOffsetY?: number;
59
+ dropShadowBlur?: number;
60
+ blurEnabled?: boolean;
61
+ blurRadius?: number;
62
+ fill: string | number;
63
+ stroke?: string | number;
64
+ strokeThickness?: number;
65
+ zIndex?: number;
66
+ align?: string;
67
+ textBaseline?: string;
68
+ trim?: boolean;
69
+
70
+ colorCorrection?: {
71
+ enabled?: boolean;
72
+ temperature?: number;
73
+ hue?: number;
74
+ contrast?: number;
75
+ saturation?: number;
76
+ exposure?: number;
77
+ reset?: boolean;
78
+ sharpness?: number;
79
+ value?: number;
80
+ levels?: number;
81
+ luminance?: number;
82
+ enhance?: number;
83
+ blurRadius?: number;
84
+ red?: number;
85
+ green?: number;
86
+ blue?: number;
87
+ alpha?: number;
88
+ scaleInput?: number;
89
+ };
90
+ effect?: string;
91
+ };
92
+ pointerdown?: () => void;
93
+ pointerup?: () => void;
94
+ mousedown?: () => void;
95
+ mouseup?: () => void;
96
+ pointerover?: () => void;
97
+ mouseover?: () => void;
98
+ mouseout?: () => void;
99
+ applyTransformer?: boolean;
100
+ onTextUpdate?: (data: any) => void;
101
+ onAnchorTransformationEnd?: (endData: any) => void;
102
+ };
103
+
104
+ const Filters = withFilters(Container, {
105
+ blur: PIXI.filters.BlurFilter,
106
+ adjust: AdjustmentFilter,
107
+ matrix: PIXI.filters.ColorMatrixFilter,
108
+ });
109
+
110
+ /** CYAN Filters */
111
+ const CYAN = [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0];
112
+ // change these to control the text size
113
+
114
+ const PixiTextSprite: React.FC<PixiTextSpriteProps> = (props) => {
115
+ //// State
116
+ const [isMounted, setIsMounted] = React.useState(false);
117
+ const [, setIsTransformerDragging] = useState(false);
118
+ const [, setIsMouseOverTransformer] = useState(false);
119
+ const [isEditing, setIsEditing] = useState(false);
120
+
121
+ console.log("allProps", props);
122
+ //// Refs
123
+ const containerRef = useRef<PIXI.Container>(null);
124
+ const parentNode = useRef<PIXI.Container>(null);
125
+ const imgGroupRef = useRef<PIXI.Container>(null);
126
+ const transformerRef = useRef<PIXI.Container>(null);
127
+
128
+ /// refs
129
+ const textRef = useRef<PIXI.Text>(null);
130
+ const textInputGroupRef = useRef(null);
131
+ const textInnerGroupRef = useRef(null);
132
+ const textFontSize = useRef<number>(16);
133
+ const textTransformDetailRef = useRef<any>(null);
134
+
135
+ //// Context
136
+ const { tl } = useContext(GsapPixieContext);
137
+
138
+ /// 1001
139
+ // console.log("contxt Values", tl);
140
+ const {
141
+ uniqueId,
142
+ text,
143
+ startAt,
144
+ endAt,
145
+ initialAlpha,
146
+ locked,
147
+ transformation,
148
+ pointerdown,
149
+ mouseout,
150
+ applyTransformer,
151
+ onAnchorTransformationEnd,
152
+ onTextUpdate,
153
+ } = props;
154
+
155
+ const {
156
+ width = 0,
157
+ height = 0,
158
+ scale = [1, 1],
159
+ x,
160
+ y,
161
+ rotation = 1,
162
+ /// font
163
+ fontFamily = "Arial",
164
+ fontWeight = "normal",
165
+ fontStyle = "normal",
166
+ fontSize = 16,
167
+
168
+ // fill
169
+ fill = "black",
170
+
171
+ // stroke
172
+ stroke,
173
+ strokeThickness: strokeWidth,
174
+ // drop shadow
175
+ blurRadius = 0,
176
+ blurEnabled = false,
177
+ dropShadowColor: shadowColor = null,
178
+
179
+ // multiline
180
+ wordWrapWidth = 50000000,
181
+ leading = 0,
182
+ letterSpacing,
183
+ colorCorrection = {},
184
+ animation,
185
+ effect,
186
+ } = transformation;
187
+
188
+ // color corrections
189
+ const {
190
+ contrast = 1,
191
+ saturation = 1,
192
+ exposure = 1,
193
+ alpha = 1,
194
+ } = colorCorrection || {};
195
+
196
+ /** adjustment filter */
197
+ const adjustments = {
198
+ brightness: exposure,
199
+ contrast,
200
+ saturation,
201
+ alpha,
202
+ };
203
+
204
+ /** handle on tranformer onchange */
205
+ const handleOnTransformChange = React.useCallback(() => {
206
+ setIsTransformerDragging(true);
207
+ }, []);
208
+
209
+ React.useEffect(() => {
210
+ textFontSize.current = Number(fontSize);
211
+ }, [fontSize]);
212
+
213
+ useEffect(() => {
214
+ let ctx = gsap.context(() => {});
215
+ if (containerRef.current && tl.current) {
216
+ const data = {
217
+ duration: Number(endAt) - Number(startAt),
218
+ };
219
+
220
+ const ease = getAnimByName(animation || "None");
221
+ ctx = gsap.context(() => {
222
+ if (!isEmpty(ease.from)) {
223
+ tl.current
224
+ .from(containerRef.current, { ...ease.from }, startAt)
225
+ .to(imgGroupRef.current, { alpha: 1, duration: 0.2 }, startAt)
226
+ .from(imgGroupRef.current, { ...data }, startAt)
227
+ .to(containerRef.current, { alpha: 0, duration: 0.2 }, endAt - 0.2);
228
+ } else if (!isEmpty(ease.to)) {
229
+ tl.current
230
+ .to(
231
+ containerRef.current,
232
+ { alpha: 1, duration: 0.2, ...ease.to },
233
+ startAt
234
+ )
235
+ .from(imgGroupRef.current, { ...data }, startAt)
236
+ .to(containerRef.current, { alpha: 0, duration: 0.2 }, endAt - 0.2);
237
+ } else if (!isEmpty(ease.fromTo)) {
238
+ tl.current
239
+ .fromTo(
240
+ containerRef.current,
241
+ ease.fromTo?.from,
242
+ ease.fromTo?.to,
243
+ startAt
244
+ )
245
+ .from(imgGroupRef.current, { ...data }, startAt)
246
+ .to(containerRef.current, { alpha: 0, duration: 0.2 }, endAt - 0.2);
247
+ } else {
248
+ tl.current
249
+ .to(containerRef.current, { alpha: 1, duration: 0.01 }, startAt)
250
+ .from(imgGroupRef.current, { ...data }, startAt)
251
+ .to(
252
+ containerRef.current,
253
+ { alpha: 0, duration: 0.1 },
254
+ Number(endAt) - Number(0.1)
255
+ );
256
+ }
257
+ });
258
+ }
259
+ return () => ctx.revert(); // cleanup!
260
+ }, [animation, startAt, endAt]);
261
+
262
+ React.useEffect(() => {
263
+ if (containerRef.current) {
264
+ setIsMounted(true);
265
+ }
266
+ }, []);
267
+
268
+ const nFontStyle = ["italic", "oblique"].includes(fontStyle)
269
+ ? fontStyle
270
+ : undefined;
271
+
272
+ const nFontWeight = ["bold", "lighter", "100", "200", "300"].includes(
273
+ fontWeight
274
+ )
275
+ ? fontWeight
276
+ : undefined;
277
+
278
+ const nLetterSpacing = Number(letterSpacing) > 0 ? letterSpacing : undefined;
279
+
280
+ const pixiStyles = React.useMemo(() => {
281
+ return new PIXI.TextStyle({
282
+ fontFamily: fontFamily,
283
+ fontSize: fontSize,
284
+ fill: fill || "white", //[color, '#00ff99'], // gradient
285
+ stroke: stroke,
286
+ strokeThickness: strokeWidth,
287
+ ...(nFontStyle && {
288
+ fontStyle: nFontStyle as unknown as PIXI.TextStyleFontStyle,
289
+ }),
290
+ ...(nFontWeight && {
291
+ fontWeight: nFontWeight as unknown as PIXI.TextStyleFontWeight,
292
+ }),
293
+ ...(nLetterSpacing && { letterSpacing: nLetterSpacing }),
294
+ ...(blurEnabled && {
295
+ dropShadow: true,
296
+ dropShadowBlur: Number(blurRadius),
297
+ dropShadowColor: shadowColor?.toString() || "black",
298
+ // / dropShadowAngle: Math.PI / 6,
299
+ dropShadowDistance: 0,
300
+ }),
301
+ wordWrap: true,
302
+ breakWords: true,
303
+ wordWrapWidth: wordWrapWidth || 500,
304
+ leading: leading || 0,
305
+ // lineHeight: lineHeight,
306
+ });
307
+ }, [
308
+ blurEnabled,
309
+ blurRadius,
310
+ fill,
311
+ fontFamily,
312
+ fontSize,
313
+ leading,
314
+ nFontStyle,
315
+ nFontWeight,
316
+ nLetterSpacing,
317
+ shadowColor,
318
+ stroke,
319
+ strokeWidth,
320
+ wordWrapWidth,
321
+ ]);
322
+
323
+ // let textMetrics = {};
324
+ // if (!isEmpty(text) && !isEmpty(pixiStyles)) {
325
+ // textMetrics = PIXI.TextMetrics.measureText(text, pixiStyles);
326
+ // }
327
+
328
+ // On transformation change, update the textTransformDetailRef
329
+ React.useEffect(() => {
330
+ textTransformDetailRef.current = {
331
+ ...transformation,
332
+ };
333
+ }, [transformation]);
334
+
335
+ const handleOnDoubleClickEditText = () => {
336
+ console.log("double click triggered");
337
+ setIsEditing(true);
338
+ };
339
+
340
+ const handleTextChange = (e: string) => {
341
+ if (onTextUpdate) {
342
+ onTextUpdate({
343
+ text: e,
344
+ uniqueId: uniqueId,
345
+ droptype: "titles",
346
+ });
347
+ }
348
+ };
349
+
350
+ const handleOnTransformEnd = React.useCallback(
351
+ (endData: TransformationEnd) => {
352
+ if (!textRef.current) return;
353
+ console.log("enddata", endData);
354
+ if (onAnchorTransformationEnd) {
355
+ console.log("running onAnchorTransformationEnd");
356
+ onAnchorTransformationEnd(endData);
357
+ }
358
+ },
359
+ [onAnchorTransformationEnd, uniqueId, width]
360
+ );
361
+
362
+ // const handleOnMoveOver = (interactionData) => {
363
+ // if (!isDragging) {
364
+ // setMouseOverSprite(true);
365
+ // }
366
+ // };
367
+
368
+ // const handleOnMoveOut = () => {
369
+ // if (!isDragging) {
370
+ // setMouseOverSprite(false);
371
+ // }
372
+ // };
373
+
374
+ React.useEffect(() => {
375
+ if (isEditing && textInputGroupRef.current) {
376
+ let el = document.getElementById("note-editor");
377
+ if (el) {
378
+ el.style.position = "absolute";
379
+ el.style.zIndex = "10";
380
+ el.style.left = x + "px";
381
+ el.style.top = y + "px";
382
+ el.style.backgroundColor = "var(--chakra-color-darkShark)";
383
+ el.style.transform = "scale(1.5)";
384
+ el.style.width = 300 + "px";
385
+ el.style.height = 100 + "px";
386
+ el.style.color = "#fff";
387
+ el.style.fontSize = "20px";
388
+ el.style.border = "1px solid #CBCEE0";
389
+
390
+ const keyboardbindings = {
391
+ // This will overwrite the default binding also named 'tab'
392
+ esc: {
393
+ key: 27,
394
+ handler: function () {
395
+ setIsEditing(false);
396
+ /// onUnSelectKeyFrame();
397
+ },
398
+ },
399
+ enter: {
400
+ key: 13,
401
+ handler: function () {
402
+ setIsEditing(false);
403
+ /// onUnSelectKeyFrame();
404
+ },
405
+ },
406
+ };
407
+
408
+ var quill = new Quill("#note-editor", {
409
+ modules: {
410
+ toolbar: false,
411
+ keyboard: {
412
+ bindings: {
413
+ ...keyboardbindings,
414
+ },
415
+ },
416
+ },
417
+ placeholder: "Compose your text here...",
418
+ theme: "snow", // or 'bubble'
419
+ });
420
+
421
+ quill.on("text-change", function () {
422
+ handleTextChange(quill.root.innerText);
423
+ });
424
+
425
+ quill.setText(text);
426
+ quill.focus();
427
+ quill.off("text-change", () => {
428
+ console.log("removed");
429
+ });
430
+ if (!quill.hasFocus()) {
431
+ el.style.display = "none";
432
+ }
433
+ }
434
+ }
435
+ }, [x, y, isEditing]);
436
+
437
+ return (
438
+ // @ts-ignore
439
+ <Container ref={parentNode}>
440
+ {/* @ts-ignore */}
441
+ <Container
442
+ ref={containerRef}
443
+ alpha={initialAlpha}
444
+ position={[x, y]}
445
+ pivot={[x, y]}
446
+ width={width}
447
+ height={height}
448
+ >
449
+ {isEditing && <Container ref={textInputGroupRef}></Container>}
450
+ {colorCorrection && colorCorrection.enabled ? (
451
+ <Filters
452
+ scale={1}
453
+ blur={{ blur: blurRadius, quality: 4 }}
454
+ adjust={adjustments}
455
+ apply={({ matrix }: { matrix: any }) => {
456
+ if (effect === "BlackAndWhite") {
457
+ matrix.desaturate();
458
+ } else if (effect === "Sepia") {
459
+ matrix.sepia();
460
+ } else if (effect === "RetroVintage") {
461
+ matrix.negative();
462
+ } else if (effect === "NightVision") {
463
+ matrix.negative();
464
+ } else if (effect === "Normal") {
465
+ matrix.reset();
466
+ }
467
+ }}
468
+ matrix={{
469
+ enabled: true,
470
+ // @ts-ignore
471
+ matrix: CYAN,
472
+ }}
473
+ >
474
+ {/* @ts-ignore */}
475
+ <Container alpha={isEditing ? 0 : 1} ref={textInnerGroupRef}>
476
+ <Text
477
+ style={pixiStyles}
478
+ x={x}
479
+ y={y}
480
+ rotation={rotation}
481
+ anchor={0.5}
482
+ text={text}
483
+ {...(!isEditing &&
484
+ !locked && {
485
+ interactive: true,
486
+ buttonMode: true,
487
+ pointerdown: pointerdown,
488
+ pointerout: mouseout,
489
+ })}
490
+ ref={textRef}
491
+ scale={scale}
492
+ />
493
+ </Container>
494
+ </Filters>
495
+ ) : (
496
+ // @ts-ignore
497
+ <Container alpha={isEditing ? 0 : 1} ref={textInnerGroupRef}>
498
+ <Text
499
+ style={pixiStyles}
500
+ x={x}
501
+ y={y}
502
+ rotation={rotation}
503
+ anchor={0.5}
504
+ text={text}
505
+ {...(!isEditing &&
506
+ !locked && {
507
+ interactive: true,
508
+ buttonMode: true,
509
+ pointerdown: pointerdown,
510
+ pointerout: mouseout,
511
+ })}
512
+ ref={textRef}
513
+ scale={scale}
514
+ />
515
+ </Container>
516
+ )}
517
+ </Container>
518
+ {applyTransformer && (
519
+ <PixiTransformer
520
+ pixiTransformerRef={transformerRef}
521
+ imageRef={containerRef}
522
+ isMounted={isMounted}
523
+ transformCommit={handleOnTransformEnd}
524
+ transformChange={handleOnTransformChange}
525
+ mouseoverEvent={setIsMouseOverTransformer}
526
+ uniqueId={uniqueId}
527
+ onDoubleClick={handleOnDoubleClickEditText}
528
+ />
529
+ )}
530
+ </Container>
531
+ );
532
+ };
533
+
534
+ export default PixiTextSprite;
535
+
536
+ // @ts-ignore
537
+ // PixiTextSprite.whyDidYouRender = {
538
+ // logOnDifferentValues: true,
539
+ // customName: "PixiTextSprite",
540
+ // };
@@ -0,0 +1 @@
1
+ export { default as PixiTextSprite } from "./PixiTextSprite";
@@ -7,7 +7,7 @@ import {
7
7
  GsapPixieContext,
8
8
  Events,
9
9
  } from "../../providers/GsapPixieContextProvider";
10
- import { Sprite, Container, useApp, withFilters } from "@pixi/react";
10
+ import { Sprite, Container, withFilters } from "@pixi/react";
11
11
  import { AdjustmentFilter } from "@pixi/filter-adjustment";
12
12
  import * as PIXI from "pixi.js";
13
13
  import gsap from "gsap";
@@ -73,9 +73,6 @@ type PixiVideoSpriteProps = {
73
73
  onAnchorTransformationEnd?: (endData: any) => void;
74
74
  };
75
75
 
76
- type EffectFunc = () => void;
77
- type Deps = ReadonlyArray<unknown>;
78
-
79
76
  interface VideoState {
80
77
  isPlaying: boolean;
81
78
  progress: number;
@@ -93,18 +90,6 @@ const Filters = withFilters(Container, {
93
90
  matrix: PIXI.filters.ColorMatrixFilter,
94
91
  });
95
92
 
96
- /** filter config */
97
- const config = {
98
- dot: {
99
- scale: 1,
100
- angle: 5,
101
- },
102
- blur: {
103
- blur: 0,
104
- quality: 4,
105
- },
106
- };
107
-
108
93
  /** CYAN Filters */
109
94
  const CYAN = [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0];
110
95
 
@@ -122,10 +107,9 @@ const initialState: VideoState = {
122
107
  const PixiVideoSprite: React.FC<PixiVideoSpriteProps> = (props) => {
123
108
  //// State
124
109
  const [isMounted, setIsMounted] = React.useState(false);
125
- const [vidPlay, setVidPlay] = React.useState(false);
126
- const [isTransformerDragging, setIsTransformerDragging] = useState(false);
127
- const [isMouseOverTransformer, setIsMouseOverTransformer] = useState(false);
128
- const [{ isWaiting, isStalled }, setVideoState] = React.useState({
110
+ /// const [isTransformerDragging, setIsTransformerDragging] = useState(false);
111
+ const [, setIsMouseOverTransformer] = useState(false);
112
+ const [, setVideoState] = React.useState({
129
113
  isWaiting: false,
130
114
  isStalled: false,
131
115
  });
@@ -173,7 +157,6 @@ const PixiVideoSprite: React.FC<PixiVideoSpriteProps> = (props) => {
173
157
  height,
174
158
  scale,
175
159
  rotation,
176
- anchor,
177
160
  animation,
178
161
  colorCorrection,
179
162
  effect,
@@ -187,35 +170,19 @@ const PixiVideoSprite: React.FC<PixiVideoSpriteProps> = (props) => {
187
170
  mouseout,
188
171
  applyTransformer,
189
172
  onAnchorTransformationEnd,
190
- ...restProps
191
173
  } = props;
192
174
 
193
175
  const videoUrl = src || "";
194
176
 
195
177
  // color corrections
196
178
  const {
197
- enabled = false,
198
- temperature = 1,
199
- hue = 1,
200
179
  contrast = 1,
201
180
  saturation = 1,
202
181
  exposure = 1,
203
- reset,
204
- sharpness = 1,
205
- value = 0,
206
- levels = 1,
207
- luminance = 0,
208
- enhance = 0,
209
182
  blurRadius = 0,
210
- red = 150,
211
- green = 150,
212
- blue = 150,
213
183
  alpha = 1,
214
- scaleInput = 1,
215
184
  } = colorCorrection || {};
216
185
 
217
- const app = useApp();
218
-
219
186
  /** adjustment filter */
220
187
  const adjustments = {
221
188
  brightness: exposure,
@@ -300,26 +267,9 @@ const PixiVideoSprite: React.FC<PixiVideoSpriteProps> = (props) => {
300
267
  }
301
268
  };
302
269
 
303
- const gsapOnPause = (startAt: number) => {
304
- if (videoElement.current) {
305
- setVidPlay(false);
306
-
307
- const vid = videoElement.current;
308
- const isVidPlaying =
309
- vid.currentTime > 0 &&
310
- !vid.paused &&
311
- !vid.ended &&
312
- vid.readyState > vid.HAVE_CURRENT_DATA;
313
- ///if (!isVidPlaying) videoElement.current.play();
314
- if (isVidPlaying) videoElement.current.pause();
315
- videoStateRef.current.isPlaying = false;
316
- }
317
- };
318
-
319
270
  const gsapOnComplete = () => {
320
271
  console.log("onComplete triggered");
321
272
  if (videoElement.current) {
322
- setVidPlay(false);
323
273
  const vid = videoElement.current;
324
274
  const isVidPlaying =
325
275
  vid.currentTime > 0 &&
@@ -378,13 +328,6 @@ const PixiVideoSprite: React.FC<PixiVideoSpriteProps> = (props) => {
378
328
  }
379
329
  };
380
330
 
381
- const handleComplete = () => {
382
- // if (onComplete) {
383
- // onComplete();
384
- // }
385
- videoStateRef.current.isPlaying = false;
386
- };
387
-
388
331
  useEffect(() => {
389
332
  let ctx = gsap.context(() => {});
390
333
  if (containerRef.current && tl.current) {
@@ -519,7 +462,7 @@ const PixiVideoSprite: React.FC<PixiVideoSpriteProps> = (props) => {
519
462
  Math.round((Number(frameStartAt) + Number.EPSILON) * 100) / 100;
520
463
  const endAt = Math.round((Number(frameEndAt) + Number.EPSILON) * 100) / 100;
521
464
  const urlWithTimestamp = `${videoUrl}#t=${stAt},${endAt}`;
522
- const urlWithQuery = `${videoUrl}?t=${stAt},${endAt}`;
465
+ /// const urlWithQuery = `${videoUrl}?t=${stAt},${endAt}`;
523
466
 
524
467
  console.log("urlTimestap", urlWithTimestamp);
525
468
  /// const texture =
@@ -628,6 +571,8 @@ const PixiVideoSprite: React.FC<PixiVideoSpriteProps> = (props) => {
628
571
  mousedown: mousedown,
629
572
  mouseover: mouseover,
630
573
  mouseout: mouseout,
574
+ mouseup: mouseup,
575
+ pointerup: pointerup,
631
576
  })}
632
577
  ref={imageRef}
633
578
  scale={scale}
@@ -657,6 +602,8 @@ const PixiVideoSprite: React.FC<PixiVideoSpriteProps> = (props) => {
657
602
  mousedown: mousedown,
658
603
  mouseover: mouseover,
659
604
  mouseout: mouseout,
605
+ mouseup: mouseup,
606
+ pointerup: pointerup,
660
607
  })}
661
608
  ref={imageRef}
662
609
  scale={scale}