@twick/video-editor 0.14.0 → 0.14.3
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/README.md +135 -19
- package/dist/components/controls/player-controls.d.ts +34 -1
- package/dist/components/video-editor.d.ts +94 -8
- package/dist/helpers/animation-manager.d.ts +35 -0
- package/dist/helpers/constants.d.ts +145 -25
- package/dist/helpers/text-effects-manager.d.ts +32 -0
- package/dist/helpers/types.d.ts +150 -0
- package/dist/hooks/use-player-control.d.ts +15 -0
- package/dist/hooks/use-player-manager.d.ts +17 -0
- package/dist/hooks/use-timeline-control.d.ts +18 -0
- package/dist/hooks/use-timeline-manager.d.ts +18 -0
- package/dist/index.d.ts +5 -4
- package/dist/index.js +106 -22
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +106 -22
- package/dist/index.mjs.map +1 -1
- package/dist/video-editor.css +493 -470
- package/package.json +14 -14
- package/LICENSE +0 -197
package/dist/helpers/types.d.ts
CHANGED
|
@@ -1,50 +1,200 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Represents a media item in the video editor.
|
|
3
|
+
* Defines the structure for images, videos, and audio files
|
|
4
|
+
* that can be used in video editing projects.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```js
|
|
8
|
+
* const mediaItem: MediaItem = {
|
|
9
|
+
* id: "media-123",
|
|
10
|
+
* type: "video",
|
|
11
|
+
* url: "https://example.com/video.mp4",
|
|
12
|
+
* thumbnail: "https://example.com/thumbnail.jpg",
|
|
13
|
+
* metadata: {
|
|
14
|
+
* duration: 30,
|
|
15
|
+
* width: 1920,
|
|
16
|
+
* height: 1080
|
|
17
|
+
* }
|
|
18
|
+
* };
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
1
21
|
export type MediaItem = {
|
|
22
|
+
/** Unique identifier for the media item */
|
|
2
23
|
id: string;
|
|
24
|
+
/** Type of media (image, video, or audio) */
|
|
3
25
|
type: 'image' | 'video' | 'audio';
|
|
26
|
+
/** URL or path to the media file */
|
|
4
27
|
url: string;
|
|
28
|
+
/** Optional array buffer containing the media data */
|
|
5
29
|
arrayBuffer?: ArrayBuffer;
|
|
30
|
+
/** Optional thumbnail URL for the media item */
|
|
6
31
|
thumbnail?: string;
|
|
32
|
+
/** Optional metadata about the media item */
|
|
7
33
|
metadata?: Record<string, any>;
|
|
8
34
|
};
|
|
35
|
+
/**
|
|
36
|
+
* Pagination options for media library queries.
|
|
37
|
+
* Used to control the number of items returned and pagination.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```js
|
|
41
|
+
* const pagination: PaginationOptions = {
|
|
42
|
+
* page: 1,
|
|
43
|
+
* limit: 20
|
|
44
|
+
* };
|
|
45
|
+
*
|
|
46
|
+
* // Fetch first 20 items
|
|
47
|
+
* const mediaItems = await mediaManager.getMedia(pagination);
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
9
50
|
export type PaginationOptions = {
|
|
51
|
+
/** Page number (1-based) */
|
|
10
52
|
page: number;
|
|
53
|
+
/** Number of items per page */
|
|
11
54
|
limit: number;
|
|
12
55
|
};
|
|
56
|
+
/**
|
|
57
|
+
* Search options for filtering media items.
|
|
58
|
+
* Defines search criteria for finding specific media content.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```js
|
|
62
|
+
* const searchOptions: SearchOptions = {
|
|
63
|
+
* query: "nature",
|
|
64
|
+
* type: "image",
|
|
65
|
+
* metadata: {
|
|
66
|
+
* tags: ["landscape", "outdoor"]
|
|
67
|
+
* }
|
|
68
|
+
* };
|
|
69
|
+
*
|
|
70
|
+
* // Search for nature images with specific tags
|
|
71
|
+
* const results = await mediaManager.searchMedia(searchOptions);
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
13
74
|
export type SearchOptions = {
|
|
75
|
+
/** Search query string */
|
|
14
76
|
query: string;
|
|
77
|
+
/** Optional media type filter */
|
|
15
78
|
type?: 'image' | 'video' | 'audio';
|
|
79
|
+
/** Optional metadata filters */
|
|
16
80
|
metadata?: Record<string, any>;
|
|
17
81
|
};
|
|
82
|
+
/**
|
|
83
|
+
* Text effect configuration for animated text elements.
|
|
84
|
+
* Defines how text animations are applied to timeline elements.
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```js
|
|
88
|
+
* const textEffect: TextEffect = {
|
|
89
|
+
* name: "typewriter",
|
|
90
|
+
* delay: 0.5,
|
|
91
|
+
* bufferTime: 0.1,
|
|
92
|
+
* getSample: (effect) => "Sample text animation"
|
|
93
|
+
* };
|
|
94
|
+
*
|
|
95
|
+
* // Apply text effect to element
|
|
96
|
+
* textElement.setTextEffect(textEffect);
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
18
99
|
export type TextEffect = {
|
|
100
|
+
/** Name of the text effect */
|
|
19
101
|
name: string;
|
|
102
|
+
/** Delay before effect starts (in seconds) */
|
|
20
103
|
delay?: number;
|
|
104
|
+
/** Buffer time between characters (in seconds) */
|
|
21
105
|
bufferTime?: number;
|
|
106
|
+
/** Function to get sample text for preview */
|
|
22
107
|
getSample: (textEffect?: TextEffect) => string;
|
|
23
108
|
};
|
|
109
|
+
/**
|
|
110
|
+
* Animation configuration for timeline elements.
|
|
111
|
+
* Defines how elements are animated during playback.
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* ```js
|
|
115
|
+
* const animation: Animation = {
|
|
116
|
+
* name: "fade",
|
|
117
|
+
* interval: 0.5,
|
|
118
|
+
* animate: "enter",
|
|
119
|
+
* mode: "in",
|
|
120
|
+
* direction: "center",
|
|
121
|
+
* options: {
|
|
122
|
+
* animate: ["enter", "exit"],
|
|
123
|
+
* direction: ["up", "down", "left", "right"],
|
|
124
|
+
* mode: ["in", "out"]
|
|
125
|
+
* },
|
|
126
|
+
* getSample: (anim) => "Sample animation preview"
|
|
127
|
+
* };
|
|
128
|
+
*
|
|
129
|
+
* // Apply animation to element
|
|
130
|
+
* element.setAnimation(animation);
|
|
131
|
+
* ```
|
|
132
|
+
*/
|
|
24
133
|
export type Animation = {
|
|
134
|
+
/** Name of the animation */
|
|
25
135
|
name: string;
|
|
136
|
+
/** Interval between animation cycles (in seconds) */
|
|
26
137
|
interval?: number;
|
|
138
|
+
/** When to apply the animation */
|
|
27
139
|
animate?: "enter" | "exit" | "both";
|
|
140
|
+
/** Animation mode (in/out) */
|
|
28
141
|
mode?: "in" | "out";
|
|
142
|
+
/** Direction of the animation */
|
|
29
143
|
direction?: "up" | "down" | "left" | "right" | "center";
|
|
144
|
+
/** Available options for the animation */
|
|
30
145
|
options?: {
|
|
146
|
+
/** Available animation types */
|
|
31
147
|
animate?: string[];
|
|
148
|
+
/** Available directions */
|
|
32
149
|
direction?: string[];
|
|
150
|
+
/** Available modes */
|
|
33
151
|
mode?: string[];
|
|
34
152
|
};
|
|
153
|
+
/** Function to get sample preview */
|
|
35
154
|
getSample: (animation?: Animation) => string;
|
|
36
155
|
};
|
|
156
|
+
/**
|
|
157
|
+
* Color scheme for different element types in the timeline.
|
|
158
|
+
* Provides consistent visual distinction between various timeline elements.
|
|
159
|
+
* Each property represents the default color for a specific element type.
|
|
160
|
+
*
|
|
161
|
+
* @example
|
|
162
|
+
* ```js
|
|
163
|
+
* const colors: ElementColors = {
|
|
164
|
+
* video: "#4B2E83",
|
|
165
|
+
* text: "#375A7F",
|
|
166
|
+
* image: "#805A38",
|
|
167
|
+
* audio: "#3C665B",
|
|
168
|
+
* // ... other element colors
|
|
169
|
+
* };
|
|
170
|
+
*
|
|
171
|
+
* // Apply color to element
|
|
172
|
+
* element.style.backgroundColor = colors[element.type];
|
|
173
|
+
* ```
|
|
174
|
+
*/
|
|
37
175
|
export interface ElementColors {
|
|
176
|
+
/** Fragment element color */
|
|
38
177
|
fragment: string;
|
|
178
|
+
/** Video element color */
|
|
39
179
|
video: string;
|
|
180
|
+
/** Caption element color */
|
|
40
181
|
caption: string;
|
|
182
|
+
/** Image element color */
|
|
41
183
|
image: string;
|
|
184
|
+
/** Audio element color */
|
|
42
185
|
audio: string;
|
|
186
|
+
/** Text element color */
|
|
43
187
|
text: string;
|
|
188
|
+
/** Generic element color */
|
|
44
189
|
element: string;
|
|
190
|
+
/** Rectangle element color */
|
|
45
191
|
rect: string;
|
|
192
|
+
/** Frame effect color */
|
|
46
193
|
frameEffect: string;
|
|
194
|
+
/** Filters color */
|
|
47
195
|
filters: string;
|
|
196
|
+
/** Transition color */
|
|
48
197
|
transition: string;
|
|
198
|
+
/** Animation color */
|
|
49
199
|
animation: string;
|
|
50
200
|
}
|
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom hook to manage player control state and playback.
|
|
3
|
+
* Handles play/pause toggling and synchronization with timeline context
|
|
4
|
+
* for video editor playback control.
|
|
5
|
+
*
|
|
6
|
+
* @returns Object containing player control functions
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```js
|
|
10
|
+
* const { togglePlayback } = usePlayerControl();
|
|
11
|
+
*
|
|
12
|
+
* // Toggle between play and pause states
|
|
13
|
+
* togglePlayback();
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
1
16
|
export declare const usePlayerControl: () => {
|
|
2
17
|
togglePlayback: () => void;
|
|
3
18
|
};
|
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom hook to manage player state and canvas interactions.
|
|
3
|
+
* Handles player data updates, canvas operations, and timeline synchronization
|
|
4
|
+
* for the video editor component.
|
|
5
|
+
*
|
|
6
|
+
* @param videoProps - Object containing video dimensions
|
|
7
|
+
* @returns Object containing player management functions and state
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```js
|
|
11
|
+
* const { twickCanvas, projectData, updateCanvas } = usePlayerManager({
|
|
12
|
+
* videoProps: { width: 1920, height: 1080 }
|
|
13
|
+
* });
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
1
16
|
export declare const usePlayerManager: ({ videoProps, }: {
|
|
2
17
|
videoProps: {
|
|
3
18
|
width: number;
|
|
@@ -8,4 +23,6 @@ export declare const usePlayerManager: ({ videoProps, }: {
|
|
|
8
23
|
projectData: any;
|
|
9
24
|
updateCanvas: (seekTime: number) => void;
|
|
10
25
|
buildCanvas: any;
|
|
26
|
+
onPlayerUpdate: (event: CustomEvent) => void;
|
|
27
|
+
playerUpdating: boolean;
|
|
11
28
|
};
|
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
import { TrackElement, Track } from '@twick/timeline';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Custom hook to manage timeline control operations.
|
|
5
|
+
* Provides functions for deleting items, splitting elements,
|
|
6
|
+
* and handling undo/redo operations in the video editor.
|
|
7
|
+
*
|
|
8
|
+
* @returns Object containing timeline control functions
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```js
|
|
12
|
+
* const { deleteItem, splitElement, handleUndo, handleRedo } = useTimelineControl();
|
|
13
|
+
*
|
|
14
|
+
* // Delete a track or element
|
|
15
|
+
* deleteItem(trackOrElement);
|
|
16
|
+
*
|
|
17
|
+
* // Split an element at current time
|
|
18
|
+
* splitElement(element, 5.5);
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
3
21
|
declare const useTimelineControl: () => {
|
|
4
22
|
splitElement: (element: TrackElement, currentTime: number) => void;
|
|
5
23
|
deleteItem: (item: Track | TrackElement) => void;
|
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
import { TrackElement, Track } from '@twick/timeline';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Custom hook to manage timeline operations and state.
|
|
5
|
+
* Provides functions for handling element dragging, track reordering,
|
|
6
|
+
* seeking, and selection changes in the video editor.
|
|
7
|
+
*
|
|
8
|
+
* @returns Object containing timeline management functions and state
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```js
|
|
12
|
+
* const { timelineData, onElementDrag, onSeek, onSelectionChange } = useTimelineManager();
|
|
13
|
+
*
|
|
14
|
+
* // Handle element dragging
|
|
15
|
+
* onElementDrag({ element, dragType: "START", updates: { start: 5, end: 10 } });
|
|
16
|
+
*
|
|
17
|
+
* // Seek to specific time
|
|
18
|
+
* onSeek(15.5);
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
3
21
|
export declare const useTimelineManager: () => {
|
|
4
22
|
timelineData: import('@twick/timeline/dist/services/data.service').TimelineTrackData | null;
|
|
5
23
|
onElementDrag: ({ element, dragType, updates, }: {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
import { default as VideoEditor } from './components/video-editor';
|
|
2
|
-
import { default as PlayerControls } from './components/controls/player-controls';
|
|
1
|
+
import { default as VideoEditor, VideoEditorProps, VideoEditorConfig } from './components/video-editor';
|
|
2
|
+
import { default as PlayerControls, PlayerControlsProps } from './components/controls/player-controls';
|
|
3
3
|
import { default as TimelineManager } from './components/timeline/timeline-manager';
|
|
4
4
|
import { usePlayerControl } from './hooks/use-player-control';
|
|
5
5
|
import { default as BrowserMediaManager } from './helpers/media-manager/browser-media-manager';
|
|
6
|
-
import { MediaItem, PaginationOptions, SearchOptions, Animation } from './helpers/types';
|
|
6
|
+
import { MediaItem, PaginationOptions, SearchOptions, Animation, TextEffect, ElementColors } from './helpers/types';
|
|
7
7
|
import { default as BaseMediaManager } from './helpers/media-manager/base-media-manager';
|
|
8
8
|
import { animationGifs, getAnimationGif } from './assets';
|
|
9
9
|
import { ANIMATIONS } from './helpers/animation-manager';
|
|
10
10
|
import { TEXT_EFFECTS } from './helpers/text-effects-manager';
|
|
11
11
|
import { default as useTimelineControl } from './hooks/use-timeline-control';
|
|
12
12
|
|
|
13
|
-
export type { MediaItem, PaginationOptions, SearchOptions, Animation };
|
|
13
|
+
export type { MediaItem, PaginationOptions, SearchOptions, Animation, TextEffect, ElementColors };
|
|
14
|
+
export type { PlayerControlsProps, VideoEditorProps, VideoEditorConfig };
|
|
14
15
|
export { ANIMATIONS, TEXT_EFFECTS };
|
|
15
16
|
export { usePlayerControl, BrowserMediaManager, BaseMediaManager, animationGifs, getAnimationGif, PlayerControls, TimelineManager, useTimelineControl };
|
|
16
17
|
export * from './helpers/constants';
|
package/dist/index.js
CHANGED
|
@@ -6816,32 +6816,53 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
6816
6816
|
};
|
|
6817
6817
|
t(vh$1, "type", "Vibrance"), t(vh$1, "defaults", { vibrance: 0 }), t(vh$1, "uniformLocations", ["uVibrance"]), tt.setClass(vh$1);
|
|
6818
6818
|
const DEFAULT_TEXT_PROPS = {
|
|
6819
|
+
/** Font family for text elements */
|
|
6819
6820
|
family: "Poppins",
|
|
6821
|
+
/** Font size in pixels */
|
|
6820
6822
|
size: 48,
|
|
6823
|
+
/** Text fill color */
|
|
6821
6824
|
fill: "#FFFFFF",
|
|
6825
|
+
/** Text stroke color */
|
|
6822
6826
|
stroke: "#000000",
|
|
6827
|
+
/** Stroke line width */
|
|
6823
6828
|
lineWidth: 0
|
|
6824
6829
|
};
|
|
6825
6830
|
const DEFAULT_CAPTION_PROPS = {
|
|
6831
|
+
/** Font family for caption elements */
|
|
6826
6832
|
family: "Poppins",
|
|
6833
|
+
/** Font size in pixels */
|
|
6827
6834
|
size: 48,
|
|
6835
|
+
/** Text fill color */
|
|
6828
6836
|
fill: "#FFFFFF",
|
|
6837
|
+
/** Font weight */
|
|
6829
6838
|
fontWeight: 600,
|
|
6839
|
+
/** Text stroke color */
|
|
6830
6840
|
stroke: "#000000",
|
|
6841
|
+
/** Stroke line width */
|
|
6831
6842
|
lineWidth: 0.2,
|
|
6843
|
+
/** Shadow color */
|
|
6832
6844
|
shadowColor: "#000000",
|
|
6845
|
+
/** Shadow blur radius */
|
|
6833
6846
|
shadowBlur: 2,
|
|
6847
|
+
/** Shadow offset [x, y] */
|
|
6834
6848
|
shadowOffset: [0, 0]
|
|
6835
6849
|
};
|
|
6836
6850
|
const CANVAS_OPERATIONS = {
|
|
6851
|
+
/** An item has been selected on the canvas */
|
|
6837
6852
|
ITEM_SELECTED: "ITEM_SELECTED",
|
|
6853
|
+
/** An item has been updated/modified on the canvas */
|
|
6838
6854
|
ITEM_UPDATED: "ITEM_UPDATED"
|
|
6839
6855
|
};
|
|
6840
6856
|
const ELEMENT_TYPES = {
|
|
6857
|
+
/** Text element type */
|
|
6841
6858
|
TEXT: "text",
|
|
6859
|
+
/** Caption element type */
|
|
6842
6860
|
CAPTION: "caption",
|
|
6861
|
+
/** Image element type */
|
|
6843
6862
|
IMAGE: "image",
|
|
6863
|
+
/** Video element type */
|
|
6844
6864
|
VIDEO: "video",
|
|
6865
|
+
/** Rectangle element type */
|
|
6845
6866
|
RECT: "rect"
|
|
6846
6867
|
};
|
|
6847
6868
|
const isBrowser$2 = typeof window !== "undefined";
|
|
@@ -6944,14 +6965,21 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
6944
6965
|
return currentFrameEffect;
|
|
6945
6966
|
};
|
|
6946
6967
|
const disabledControl = new Hs({
|
|
6968
|
+
/** X position offset */
|
|
6947
6969
|
x: 0,
|
|
6970
|
+
/** Y position offset */
|
|
6948
6971
|
y: -0.5,
|
|
6972
|
+
/** Additional Y offset */
|
|
6949
6973
|
offsetY: 0,
|
|
6974
|
+
/** Cursor style when hovering */
|
|
6950
6975
|
cursorStyle: "pointer",
|
|
6976
|
+
/** Action handler that does nothing */
|
|
6951
6977
|
actionHandler: () => {
|
|
6952
6978
|
return true;
|
|
6953
6979
|
},
|
|
6980
|
+
/** Name of the action */
|
|
6954
6981
|
actionName: "scale",
|
|
6982
|
+
/** Render function for the control */
|
|
6955
6983
|
render: function(ctx, left, top) {
|
|
6956
6984
|
const size = 0;
|
|
6957
6985
|
ctx.save();
|
|
@@ -6962,12 +6990,19 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
6962
6990
|
}
|
|
6963
6991
|
});
|
|
6964
6992
|
const rotateControl = new Hs({
|
|
6993
|
+
/** X position offset */
|
|
6965
6994
|
x: 0,
|
|
6995
|
+
/** Y position offset */
|
|
6966
6996
|
y: -0.5,
|
|
6997
|
+
/** Additional Y offset for positioning */
|
|
6967
6998
|
offsetY: -25,
|
|
6999
|
+
/** Cursor style when hovering */
|
|
6968
7000
|
cursorStyle: "crosshair",
|
|
7001
|
+
/** Action handler with rotation and snapping */
|
|
6969
7002
|
actionHandler: Ma.rotationWithSnapping,
|
|
7003
|
+
/** Name of the action */
|
|
6970
7004
|
actionName: "rotate",
|
|
7005
|
+
/** Whether to show connection line */
|
|
6971
7006
|
withConnection: true
|
|
6972
7007
|
});
|
|
6973
7008
|
const getThumbnail = async (videoUrl, seekTime = 0.1, playbackRate = 1) => {
|
|
@@ -7779,6 +7814,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
7779
7814
|
}) => {
|
|
7780
7815
|
const [projectData, setProjectData] = React.useState(null);
|
|
7781
7816
|
const { timelineAction, setTimelineAction, setSelectedItem, editor } = timeline.useTimelineContext();
|
|
7817
|
+
const [playerUpdating, setPlayerUpdating] = React.useState(false);
|
|
7782
7818
|
const handleCanvasReady = (canvas) => {
|
|
7783
7819
|
console.log("canvas ready", canvas);
|
|
7784
7820
|
};
|
|
@@ -7812,12 +7848,20 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
7812
7848
|
cleanAndAdd: true
|
|
7813
7849
|
});
|
|
7814
7850
|
};
|
|
7851
|
+
const onPlayerUpdate = (event) => {
|
|
7852
|
+
var _a2;
|
|
7853
|
+
if (((_a2 = event == null ? void 0 : event.detail) == null ? void 0 : _a2.status) === "ready") {
|
|
7854
|
+
setPlayerUpdating(false);
|
|
7855
|
+
setTimelineAction(timeline.TIMELINE_ACTION.ON_PLAYER_UPDATED, null);
|
|
7856
|
+
}
|
|
7857
|
+
};
|
|
7815
7858
|
React.useEffect(() => {
|
|
7816
7859
|
var _a2, _b, _c, _d;
|
|
7817
7860
|
switch (timelineAction.type) {
|
|
7818
7861
|
case timeline.TIMELINE_ACTION.UPDATE_PLAYER_DATA:
|
|
7819
7862
|
if (videoProps) {
|
|
7820
7863
|
if (((_a2 = timelineAction.payload) == null ? void 0 : _a2.forceUpdate) || editor.getLatestVersion() !== ((_b = projectData == null ? void 0 : projectData.input) == null ? void 0 : _b.version)) {
|
|
7864
|
+
setPlayerUpdating(true);
|
|
7821
7865
|
const _latestProjectData = {
|
|
7822
7866
|
input: {
|
|
7823
7867
|
properties: videoProps,
|
|
@@ -7826,9 +7870,10 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
7826
7870
|
}
|
|
7827
7871
|
};
|
|
7828
7872
|
setProjectData(_latestProjectData);
|
|
7873
|
+
} else {
|
|
7874
|
+
setTimelineAction(timeline.TIMELINE_ACTION.ON_PLAYER_UPDATED, null);
|
|
7829
7875
|
}
|
|
7830
7876
|
}
|
|
7831
|
-
setTimelineAction(timeline.TIMELINE_ACTION.ON_PLAYER_UPDATED, null);
|
|
7832
7877
|
break;
|
|
7833
7878
|
}
|
|
7834
7879
|
}, [timelineAction]);
|
|
@@ -7836,7 +7881,9 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
7836
7881
|
twickCanvas,
|
|
7837
7882
|
projectData,
|
|
7838
7883
|
updateCanvas,
|
|
7839
|
-
buildCanvas
|
|
7884
|
+
buildCanvas,
|
|
7885
|
+
onPlayerUpdate,
|
|
7886
|
+
playerUpdating
|
|
7840
7887
|
};
|
|
7841
7888
|
};
|
|
7842
7889
|
const PlayerManager = ({
|
|
@@ -7844,7 +7891,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
7844
7891
|
canvasMode
|
|
7845
7892
|
}) => {
|
|
7846
7893
|
const { changeLog } = timeline.useTimelineContext();
|
|
7847
|
-
const { twickCanvas, projectData, updateCanvas, buildCanvas } = usePlayerManager({ videoProps });
|
|
7894
|
+
const { twickCanvas, projectData, updateCanvas, playerUpdating, onPlayerUpdate, buildCanvas } = usePlayerManager({ videoProps });
|
|
7848
7895
|
const durationRef = React.useRef(0);
|
|
7849
7896
|
const {
|
|
7850
7897
|
playerState,
|
|
@@ -7876,7 +7923,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
7876
7923
|
}
|
|
7877
7924
|
}, [twickCanvas, playerState, seekTime, changeLog]);
|
|
7878
7925
|
const handleTimeUpdate = (time2) => {
|
|
7879
|
-
if (time2 >= durationRef.current) {
|
|
7926
|
+
if (durationRef.current && time2 >= durationRef.current) {
|
|
7880
7927
|
setCurrentTime(0);
|
|
7881
7928
|
setPlayerState(livePlayer.PLAYER_STATE.PAUSED);
|
|
7882
7929
|
} else {
|
|
@@ -7891,6 +7938,16 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
7891
7938
|
aspectRatio: `${videoProps.width}/${videoProps.height}`
|
|
7892
7939
|
},
|
|
7893
7940
|
children: [
|
|
7941
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7942
|
+
"div",
|
|
7943
|
+
{
|
|
7944
|
+
className: "twick-editor-loading-overlay",
|
|
7945
|
+
style: {
|
|
7946
|
+
display: playerUpdating ? "flex" : "none"
|
|
7947
|
+
},
|
|
7948
|
+
children: playerUpdating ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twick-editor-loading-spinner" }) : null
|
|
7949
|
+
}
|
|
7950
|
+
),
|
|
7894
7951
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7895
7952
|
livePlayer.LivePlayer,
|
|
7896
7953
|
{
|
|
@@ -7900,6 +7957,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
7900
7957
|
width: videoProps.width,
|
|
7901
7958
|
height: videoProps.height
|
|
7902
7959
|
},
|
|
7960
|
+
onPlayerUpdate,
|
|
7903
7961
|
containerStyle: {
|
|
7904
7962
|
opacity: canvasMode ? playerState === livePlayer.PLAYER_STATE.PAUSED ? 0 : 1 : 1
|
|
7905
7963
|
},
|
|
@@ -16826,61 +16884,87 @@ This message will only show in development mode. It won't appear in production.
|
|
|
16826
16884
|
};
|
|
16827
16885
|
const MIN_DURATION = 0.1;
|
|
16828
16886
|
const DRAG_TYPE = {
|
|
16887
|
+
/** Drag operation is starting */
|
|
16829
16888
|
START: "start",
|
|
16889
|
+
/** Drag operation is in progress */
|
|
16830
16890
|
MOVE: "move",
|
|
16891
|
+
/** Drag operation has ended */
|
|
16831
16892
|
END: "end"
|
|
16832
16893
|
};
|
|
16833
16894
|
const DEFAULT_TIMELINE_ZOOM = 1.5;
|
|
16834
16895
|
const DEFAULT_ELEMENT_COLORS = {
|
|
16896
|
+
/** Fragment element color */
|
|
16835
16897
|
fragment: "#111111",
|
|
16898
|
+
/** Video element color - muted deep violet */
|
|
16836
16899
|
video: "#4B2E83",
|
|
16837
|
-
|
|
16900
|
+
/** Caption element color - faded violet/blue */
|
|
16838
16901
|
caption: "#5C5470",
|
|
16839
|
-
|
|
16902
|
+
/** Image element color - earthy brown-orange */
|
|
16840
16903
|
image: "#805A38",
|
|
16841
|
-
|
|
16904
|
+
/** Audio element color - dark muted teal-green */
|
|
16842
16905
|
audio: "#3C665B",
|
|
16843
|
-
|
|
16906
|
+
/** Text element color - dusty steel blue */
|
|
16844
16907
|
text: "#375A7F",
|
|
16845
|
-
|
|
16908
|
+
/** Generic element color - muted berry purple */
|
|
16846
16909
|
element: "#6B3A5B",
|
|
16847
|
-
|
|
16910
|
+
/** Rectangle element color - desaturated deep indigo */
|
|
16848
16911
|
rect: "#4C3A72",
|
|
16849
|
-
|
|
16912
|
+
/** Frame effect color - dusty rose/maroon */
|
|
16850
16913
|
frameEffect: "#703C57",
|
|
16851
|
-
|
|
16914
|
+
/** Filters color - muted twilight purple */
|
|
16852
16915
|
filters: "#5A4C82",
|
|
16853
|
-
|
|
16916
|
+
/** Transition color - toasted copper */
|
|
16854
16917
|
transition: "#7A573A",
|
|
16855
|
-
|
|
16918
|
+
/** Animation color - slate pine green */
|
|
16856
16919
|
animation: "#32645C"
|
|
16857
|
-
// Slate pine green
|
|
16858
16920
|
};
|
|
16859
16921
|
const AVAILABLE_TEXT_FONTS = {
|
|
16860
16922
|
// Google Fonts
|
|
16923
|
+
/** Modern sans-serif font */
|
|
16861
16924
|
RUBIK: "Rubik",
|
|
16925
|
+
/** Clean and readable font */
|
|
16862
16926
|
MULISH: "Mulish",
|
|
16927
|
+
/** Bold display font */
|
|
16863
16928
|
LUCKIEST_GUY: "Luckiest Guy",
|
|
16929
|
+
/** Elegant serif font */
|
|
16864
16930
|
PLAYFAIR_DISPLAY: "Playfair Display",
|
|
16931
|
+
/** Classic sans-serif font */
|
|
16865
16932
|
ROBOTO: "Roboto",
|
|
16933
|
+
/** Modern geometric font */
|
|
16866
16934
|
POPPINS: "Poppins",
|
|
16867
16935
|
// Display and Decorative Fonts
|
|
16936
|
+
/** Comic-style display font */
|
|
16868
16937
|
BANGERS: "Bangers",
|
|
16938
|
+
/** Handwritten-style font */
|
|
16869
16939
|
BIRTHSTONE: "Birthstone",
|
|
16940
|
+
/** Elegant script font */
|
|
16870
16941
|
CORINTHIA: "Corinthia",
|
|
16942
|
+
/** Formal script font */
|
|
16871
16943
|
IMPERIAL_SCRIPT: "Imperial Script",
|
|
16944
|
+
/** Bold outline font */
|
|
16872
16945
|
KUMAR_ONE_OUTLINE: "Kumar One Outline",
|
|
16946
|
+
/** Light outline font */
|
|
16873
16947
|
LONDRI_OUTLINE: "Londrina Outline",
|
|
16948
|
+
/** Casual script font */
|
|
16874
16949
|
MARCK_SCRIPT: "Marck Script",
|
|
16950
|
+
/** Modern sans-serif font */
|
|
16875
16951
|
MONTSERRAT: "Montserrat",
|
|
16952
|
+
/** Stylish display font */
|
|
16876
16953
|
PATTAYA: "Pattaya",
|
|
16877
16954
|
// CDN Fonts
|
|
16955
|
+
/** Unique display font */
|
|
16878
16956
|
PERALTA: "Peralta",
|
|
16957
|
+
/** Bold impact font */
|
|
16879
16958
|
IMPACT: "Impact",
|
|
16959
|
+
/** Handwritten-style font */
|
|
16880
16960
|
LUMANOSIMO: "Lumanosimo",
|
|
16961
|
+
/** Custom display font */
|
|
16881
16962
|
KAPAKANA: "Kapakana",
|
|
16963
|
+
/** Handwritten font */
|
|
16882
16964
|
HANDYRUSH: "HandyRush",
|
|
16965
|
+
/** Decorative font */
|
|
16883
16966
|
DASHER: "Dasher",
|
|
16967
|
+
/** Signature-style font */
|
|
16884
16968
|
BRITTANY_SIGNATURE: "Brittany Signature"
|
|
16885
16969
|
};
|
|
16886
16970
|
let ELEMENT_COLORS = { ...DEFAULT_ELEMENT_COLORS };
|
|
@@ -17392,11 +17476,11 @@ This message will only show in development mode. It won't appear in production.
|
|
|
17392
17476
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17393
17477
|
"button",
|
|
17394
17478
|
{
|
|
17395
|
-
className: `control-btn play-pause-btn player-controls-play-pause-btn${playerState === livePlayer.PLAYER_STATE.PLAYING ? " playing" : ""}${playerState === livePlayer.PLAYER_STATE.
|
|
17479
|
+
className: `control-btn play-pause-btn player-controls-play-pause-btn${playerState === livePlayer.PLAYER_STATE.PLAYING ? " playing" : ""}${playerState === livePlayer.PLAYER_STATE.REFRESH ? " refreshing" : ""}`,
|
|
17396
17480
|
onClick: togglePlayback,
|
|
17397
|
-
title: playerState === livePlayer.PLAYER_STATE.PLAYING ? "Pause" : playerState === livePlayer.PLAYER_STATE.
|
|
17398
|
-
disabled: playerState === livePlayer.PLAYER_STATE.
|
|
17399
|
-
children: playerState === livePlayer.PLAYER_STATE.PLAYING ? /* @__PURE__ */ jsxRuntime.jsx(Pause, { size: 28, strokeWidth: 2 }) : playerState === livePlayer.PLAYER_STATE.
|
|
17481
|
+
title: playerState === livePlayer.PLAYER_STATE.PLAYING ? "Pause" : playerState === livePlayer.PLAYER_STATE.REFRESH ? "Refreshing" : "Play",
|
|
17482
|
+
disabled: playerState === livePlayer.PLAYER_STATE.REFRESH,
|
|
17483
|
+
children: playerState === livePlayer.PLAYER_STATE.PLAYING ? /* @__PURE__ */ jsxRuntime.jsx(Pause, { size: 28, strokeWidth: 2 }) : playerState === livePlayer.PLAYER_STATE.REFRESH ? /* @__PURE__ */ jsxRuntime.jsx(LoaderCircle, { size: 28, strokeWidth: 2, className: "refreshing-spinner" }) : /* @__PURE__ */ jsxRuntime.jsx(Play, { size: 28, strokeWidth: 2 })
|
|
17400
17484
|
}
|
|
17401
17485
|
),
|
|
17402
17486
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "time-display player-controls-time-display", children: [
|
|
@@ -17418,14 +17502,14 @@ This message will only show in development mode. It won't appear in production.
|
|
|
17418
17502
|
playerStateRef.current = livePlayer.PLAYER_STATE.PAUSED;
|
|
17419
17503
|
setPlayerState(livePlayer.PLAYER_STATE.PAUSED);
|
|
17420
17504
|
} else if (playerState === livePlayer.PLAYER_STATE.PAUSED) {
|
|
17421
|
-
playerStateRef.current = livePlayer.PLAYER_STATE.
|
|
17422
|
-
setPlayerState(livePlayer.PLAYER_STATE.
|
|
17505
|
+
playerStateRef.current = livePlayer.PLAYER_STATE.REFRESH;
|
|
17506
|
+
setPlayerState(livePlayer.PLAYER_STATE.REFRESH);
|
|
17423
17507
|
setTimelineAction(timeline.TIMELINE_ACTION.UPDATE_PLAYER_DATA, present);
|
|
17424
17508
|
}
|
|
17425
17509
|
};
|
|
17426
17510
|
React.useEffect(() => {
|
|
17427
17511
|
if (timelineAction.type === timeline.TIMELINE_ACTION.ON_PLAYER_UPDATED) {
|
|
17428
|
-
if (playerStateRef.current === livePlayer.PLAYER_STATE.
|
|
17512
|
+
if (playerStateRef.current === livePlayer.PLAYER_STATE.REFRESH) {
|
|
17429
17513
|
playerStateRef.current = livePlayer.PLAYER_STATE.PLAYING;
|
|
17430
17514
|
setPlayerState(livePlayer.PLAYER_STATE.PLAYING);
|
|
17431
17515
|
}
|