@twick/video-editor 0.15.15 → 0.15.18
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/dist/helpers/constants.d.ts +0 -109
- package/dist/helpers/function.utils.d.ts +18 -0
- package/dist/hooks/use-player-manager.d.ts +2 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +155 -45
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +155 -45
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
|
@@ -4,17 +4,6 @@ import { TimelineTickConfig } from '../components/video-editor';
|
|
|
4
4
|
/**
|
|
5
5
|
* Initial timeline data structure for new video editor projects.
|
|
6
6
|
* Provides a default timeline with a sample text element to get started.
|
|
7
|
-
*
|
|
8
|
-
* @example
|
|
9
|
-
* ```js
|
|
10
|
-
* import { INITIAL_TIMELINE_DATA } from '@twick/video-editor';
|
|
11
|
-
*
|
|
12
|
-
* // Use as starting point for new projects
|
|
13
|
-
* const newProject = {
|
|
14
|
-
* ...INITIAL_TIMELINE_DATA,
|
|
15
|
-
* tracks: [...INITIAL_TIMELINE_DATA.tracks, newTrack]
|
|
16
|
-
* };
|
|
17
|
-
* ```
|
|
18
7
|
*/
|
|
19
8
|
export declare const INITIAL_TIMELINE_DATA: {
|
|
20
9
|
tracks: {
|
|
@@ -39,43 +28,8 @@ export declare const INITIAL_TIMELINE_DATA: {
|
|
|
39
28
|
/**
|
|
40
29
|
* Minimum duration for timeline elements in seconds.
|
|
41
30
|
* Used to prevent elements from having zero or negative duration.
|
|
42
|
-
*
|
|
43
|
-
* @example
|
|
44
|
-
* ```js
|
|
45
|
-
* import { MIN_DURATION } from '@twick/video-editor';
|
|
46
|
-
*
|
|
47
|
-
* const elementDuration = Math.max(duration, MIN_DURATION);
|
|
48
|
-
* // Ensures element has at least 0.1 seconds duration
|
|
49
|
-
* ```
|
|
50
31
|
*/
|
|
51
32
|
export declare const MIN_DURATION = 0.1;
|
|
52
|
-
/**
|
|
53
|
-
* Drag operation types for timeline interactions.
|
|
54
|
-
* Defines the different phases of drag operations on timeline elements.
|
|
55
|
-
*
|
|
56
|
-
* @example
|
|
57
|
-
* ```js
|
|
58
|
-
* import { DRAG_TYPE } from '@twick/video-editor';
|
|
59
|
-
*
|
|
60
|
-
* function handleDrag(type) {
|
|
61
|
-
* switch (type) {
|
|
62
|
-
* case DRAG_TYPE.START:
|
|
63
|
-
* // Handle drag start
|
|
64
|
-
* break;
|
|
65
|
-
* case DRAG_TYPE.MOVE:
|
|
66
|
-
* // Handle drag move
|
|
67
|
-
* break;
|
|
68
|
-
* case DRAG_TYPE.END:
|
|
69
|
-
* // Handle drag end
|
|
70
|
-
* break;
|
|
71
|
-
* }
|
|
72
|
-
* }
|
|
73
|
-
* ```
|
|
74
|
-
*/
|
|
75
|
-
/**
|
|
76
|
-
* MIME type for media items dragged from the studio's media panels (video, audio, image)
|
|
77
|
-
* to the timeline. The data format is JSON: { type: "video"|"audio"|"image", url: string }.
|
|
78
|
-
*/
|
|
79
33
|
export declare const TIMELINE_DROP_MEDIA_TYPE = "application/x-twick-media";
|
|
80
34
|
export declare const DRAG_TYPE: {
|
|
81
35
|
/** Drag operation is starting */
|
|
@@ -85,35 +39,10 @@ export declare const DRAG_TYPE: {
|
|
|
85
39
|
/** Drag operation has ended */
|
|
86
40
|
readonly END: "end";
|
|
87
41
|
};
|
|
88
|
-
/**
|
|
89
|
-
* Default zoom level for timeline view.
|
|
90
|
-
* Controls the initial magnification of the timeline interface.
|
|
91
|
-
*
|
|
92
|
-
* @example
|
|
93
|
-
* ```js
|
|
94
|
-
* import { DEFAULT_TIMELINE_ZOOM } from '@twick/video-editor';
|
|
95
|
-
*
|
|
96
|
-
* const [zoom, setZoom] = useState(DEFAULT_TIMELINE_ZOOM);
|
|
97
|
-
* // Timeline starts with 1.5x zoom
|
|
98
|
-
* ```
|
|
99
|
-
*/
|
|
100
42
|
export declare const DEFAULT_TIMELINE_ZOOM = 1.5;
|
|
101
43
|
/**
|
|
102
44
|
* Default timeline zoom configuration including min, max, step, and default values.
|
|
103
45
|
* Controls the zoom behavior and constraints for the timeline view.
|
|
104
|
-
*
|
|
105
|
-
* @example
|
|
106
|
-
* ```js
|
|
107
|
-
* import { DEFAULT_TIMELINE_ZOOM_CONFIG } from '@twick/video-editor';
|
|
108
|
-
*
|
|
109
|
-
* // Use default zoom configuration
|
|
110
|
-
* <VideoEditor
|
|
111
|
-
* editorConfig={{
|
|
112
|
-
* videoProps: { width: 1920, height: 1080 },
|
|
113
|
-
* timelineZoomConfig: DEFAULT_TIMELINE_ZOOM_CONFIG
|
|
114
|
-
* }}
|
|
115
|
-
* />
|
|
116
|
-
* ```
|
|
117
46
|
*/
|
|
118
47
|
/**
|
|
119
48
|
* Default frames per second for timeline time display.
|
|
@@ -139,54 +68,16 @@ export declare const DEFAULT_TIMELINE_ZOOM_CONFIG: {
|
|
|
139
68
|
*
|
|
140
69
|
* Each configuration applies when the duration is less than the specified threshold.
|
|
141
70
|
* Configurations are ordered by duration threshold ascending.
|
|
142
|
-
*
|
|
143
|
-
* @example
|
|
144
|
-
* ```js
|
|
145
|
-
* import { DEFAULT_TIMELINE_TICK_CONFIGS } from '@twick/video-editor';
|
|
146
|
-
*
|
|
147
|
-
* // Use default configurations
|
|
148
|
-
* <VideoEditor
|
|
149
|
-
* editorConfig={{
|
|
150
|
-
* videoProps: { width: 1920, height: 1080 },
|
|
151
|
-
* timelineTickConfigs: DEFAULT_TIMELINE_TICK_CONFIGS
|
|
152
|
-
* }}
|
|
153
|
-
* />
|
|
154
|
-
* ```
|
|
155
71
|
*/
|
|
156
72
|
export declare const DEFAULT_TIMELINE_TICK_CONFIGS: TimelineTickConfig[];
|
|
157
73
|
/**
|
|
158
74
|
* Default color scheme for different element types in the timeline.
|
|
159
75
|
* Provides consistent visual distinction between various timeline elements.
|
|
160
|
-
*
|
|
161
|
-
* @example
|
|
162
|
-
* ```js
|
|
163
|
-
* import { DEFAULT_ELEMENT_COLORS } from '@twick/video-editor';
|
|
164
|
-
*
|
|
165
|
-
* const videoColor = DEFAULT_ELEMENT_COLORS.video; // "#4B2E83"
|
|
166
|
-
* const textColor = DEFAULT_ELEMENT_COLORS.text; // "#375A7F"
|
|
167
|
-
*
|
|
168
|
-
* // Apply colors to timeline elements
|
|
169
|
-
* element.style.backgroundColor = DEFAULT_ELEMENT_COLORS[element.type];
|
|
170
|
-
* ```
|
|
171
76
|
*/
|
|
172
77
|
export declare const DEFAULT_ELEMENT_COLORS: ElementColors;
|
|
173
78
|
/**
|
|
174
79
|
* Available text fonts for video editor text elements.
|
|
175
80
|
* Includes Google Fonts, display fonts, and custom CDN fonts.
|
|
176
|
-
*
|
|
177
|
-
* @example
|
|
178
|
-
* ```js
|
|
179
|
-
* import { AVAILABLE_TEXT_FONTS } from '@twick/video-editor';
|
|
180
|
-
*
|
|
181
|
-
* // Use Google Fonts
|
|
182
|
-
* const googleFont = AVAILABLE_TEXT_FONTS.ROBOTO; // "Roboto"
|
|
183
|
-
*
|
|
184
|
-
* // Use decorative fonts
|
|
185
|
-
* const decorativeFont = AVAILABLE_TEXT_FONTS.BANGERS; // "Bangers"
|
|
186
|
-
*
|
|
187
|
-
* // Apply font to text element
|
|
188
|
-
* textElement.style.fontFamily = AVAILABLE_TEXT_FONTS.POPPINS;
|
|
189
|
-
* ```
|
|
190
81
|
*/
|
|
191
82
|
export declare const AVAILABLE_TEXT_FONTS: {
|
|
192
83
|
/** Modern sans-serif font */
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a debounced version of a function.
|
|
3
|
+
* The function will only be called after it has not been invoked
|
|
4
|
+
* for the specified delay.
|
|
5
|
+
*
|
|
6
|
+
* Useful for expensive operations that should not run on every
|
|
7
|
+
* keystroke / mouse move (e.g. resize handlers, search, etc.).
|
|
8
|
+
*/
|
|
9
|
+
export declare function debounce<T extends (...args: any[]) => any>(fn: T, delay: number): (...args: Parameters<T>) => void;
|
|
10
|
+
/**
|
|
11
|
+
* Creates a throttled version of a function.
|
|
12
|
+
* The function will be called at most once in every `interval`
|
|
13
|
+
* milliseconds, ignoring additional calls in between.
|
|
14
|
+
*
|
|
15
|
+
* Useful for high–frequency events like scroll / mousemove where
|
|
16
|
+
* you still want regular updates but not on every event.
|
|
17
|
+
*/
|
|
18
|
+
export declare function throttle<T extends (...args: any[]) => any>(fn: T, interval: number): (...args: Parameters<T>) => void;
|
|
@@ -27,8 +27,9 @@ export declare const usePlayerManager: ({ videoProps, canvasConfig, }: {
|
|
|
27
27
|
}) => {
|
|
28
28
|
twickCanvas: any;
|
|
29
29
|
projectData: any;
|
|
30
|
-
updateCanvas: (seekTime: number) => void;
|
|
30
|
+
updateCanvas: (seekTime: number, forceRefresh?: boolean) => void;
|
|
31
31
|
buildCanvas: any;
|
|
32
|
+
resizeCanvas: any;
|
|
32
33
|
onPlayerUpdate: (event: CustomEvent) => void;
|
|
33
34
|
playerUpdating: boolean;
|
|
34
35
|
handleDropOnCanvas: (payload: CanvasDropPayload) => Promise<void>;
|
package/dist/index.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ import { setElementColors } from './helpers/editor.utils';
|
|
|
15
15
|
export { setElementColors };
|
|
16
16
|
export type { MediaItem, PaginationOptions, SearchOptions, Animation, TextEffect, ElementColors };
|
|
17
17
|
export type { PlayerControlsProps, VideoEditorProps, VideoEditorConfig, TimelineTickConfig, TimelineZoomConfig, CanvasConfig };
|
|
18
|
+
export { throttle, debounce } from './helpers/function.utils';
|
|
18
19
|
export { ANIMATIONS, TEXT_EFFECTS };
|
|
19
20
|
export { usePlayerControl, useEditorManager, BrowserMediaManager, BaseMediaManager, animationGifs, getAnimationGif, PlayerControls, TimelineManager, useTimelineControl };
|
|
20
21
|
export * from './helpers/constants';
|
package/dist/index.js
CHANGED
|
@@ -6885,9 +6885,9 @@ const CANVAS_OPERATIONS = {
|
|
|
6885
6885
|
CAPTION_PROPS_UPDATED: "CAPTION_PROPS_UPDATED",
|
|
6886
6886
|
/** Watermark has been updated */
|
|
6887
6887
|
WATERMARK_UPDATED: "WATERMARK_UPDATED",
|
|
6888
|
-
/** A new element was added via drop on canvas; payload is
|
|
6888
|
+
/** A new element was added via drop on canvas; payload is { element } */
|
|
6889
6889
|
ADDED_NEW_ELEMENT: "ADDED_NEW_ELEMENT",
|
|
6890
|
-
/** Z-order changed (bring to front / send to back). Payload is
|
|
6890
|
+
/** Z-order changed (bring to front / send to back). Payload is { elementId, direction }. Timeline should reorder tracks. */
|
|
6891
6891
|
Z_ORDER_CHANGED: "Z_ORDER_CHANGED"
|
|
6892
6892
|
};
|
|
6893
6893
|
const ELEMENT_TYPES = {
|
|
@@ -8443,6 +8443,30 @@ const useTwickCanvas = ({
|
|
|
8443
8443
|
scaleX: 1,
|
|
8444
8444
|
scaleY: 1
|
|
8445
8445
|
});
|
|
8446
|
+
const resizeCanvas = ({
|
|
8447
|
+
canvasSize,
|
|
8448
|
+
videoSize = videoSizeRef.current
|
|
8449
|
+
}) => {
|
|
8450
|
+
const canvas = twickCanvasRef.current;
|
|
8451
|
+
if (!canvas || !getCanvasContext(canvas)) return;
|
|
8452
|
+
if (!(videoSize == null ? void 0 : videoSize.width) || !(videoSize == null ? void 0 : videoSize.height)) return;
|
|
8453
|
+
if (canvasResolutionRef.current.width === canvasSize.width && canvasResolutionRef.current.height === canvasSize.height) {
|
|
8454
|
+
return;
|
|
8455
|
+
}
|
|
8456
|
+
canvasMetadataRef.current = {
|
|
8457
|
+
width: canvasSize.width,
|
|
8458
|
+
height: canvasSize.height,
|
|
8459
|
+
aspectRatio: canvasSize.width / canvasSize.height,
|
|
8460
|
+
scaleX: Number((canvasSize.width / videoSize.width).toFixed(2)),
|
|
8461
|
+
scaleY: Number((canvasSize.height / videoSize.height).toFixed(2))
|
|
8462
|
+
};
|
|
8463
|
+
canvas.setDimensions({
|
|
8464
|
+
width: canvasSize.width,
|
|
8465
|
+
height: canvasSize.height
|
|
8466
|
+
});
|
|
8467
|
+
canvasResolutionRef.current = canvasSize;
|
|
8468
|
+
canvas.requestRenderAll();
|
|
8469
|
+
};
|
|
8446
8470
|
const onVideoSizeChange = (videoSize) => {
|
|
8447
8471
|
if (videoSize) {
|
|
8448
8472
|
videoSizeRef.current = videoSize;
|
|
@@ -8716,9 +8740,7 @@ const useTwickCanvas = ({
|
|
|
8716
8740
|
reorderElementsByZIndex(twickCanvas);
|
|
8717
8741
|
}
|
|
8718
8742
|
};
|
|
8719
|
-
const addWatermarkToCanvas = ({
|
|
8720
|
-
element
|
|
8721
|
-
}) => {
|
|
8743
|
+
const addWatermarkToCanvas = ({ element }) => {
|
|
8722
8744
|
if (!twickCanvas) return;
|
|
8723
8745
|
const handler = elementController.get("watermark");
|
|
8724
8746
|
if (handler) {
|
|
@@ -8748,6 +8770,7 @@ const useTwickCanvas = ({
|
|
|
8748
8770
|
return {
|
|
8749
8771
|
twickCanvas,
|
|
8750
8772
|
buildCanvas,
|
|
8773
|
+
resizeCanvas,
|
|
8751
8774
|
onVideoSizeChange,
|
|
8752
8775
|
addWatermarkToCanvas,
|
|
8753
8776
|
addElementToCanvas,
|
|
@@ -9166,10 +9189,12 @@ const usePlayerManager = ({
|
|
|
9166
9189
|
changeLog,
|
|
9167
9190
|
videoResolution
|
|
9168
9191
|
} = timeline.useTimelineContext();
|
|
9169
|
-
const { getCurrentTime } = livePlayer.useLivePlayerContext();
|
|
9192
|
+
const { getCurrentTime, setSeekTime } = livePlayer.useLivePlayerContext();
|
|
9170
9193
|
const currentChangeLog = React.useRef(changeLog);
|
|
9171
9194
|
const prevSeekTime = React.useRef(0);
|
|
9172
9195
|
const [playerUpdating, setPlayerUpdating] = React.useState(false);
|
|
9196
|
+
const updateCanvasRef = React.useRef(() => {
|
|
9197
|
+
});
|
|
9173
9198
|
const handleCanvasReady = (_canvas) => {
|
|
9174
9199
|
};
|
|
9175
9200
|
const handleCanvasOperation = (operation, data) => {
|
|
@@ -9205,13 +9230,14 @@ const usePlayerManager = ({
|
|
|
9205
9230
|
}
|
|
9206
9231
|
editor.reorderTracks(reordered);
|
|
9207
9232
|
currentChangeLog.current = currentChangeLog.current + 1;
|
|
9233
|
+
updateCanvasRef.current(getCurrentTime(), true);
|
|
9208
9234
|
return;
|
|
9209
9235
|
}
|
|
9210
9236
|
if (operation === CANVAS_OPERATIONS.CAPTION_PROPS_UPDATED) {
|
|
9211
9237
|
const captionsTrack = editor.getCaptionsTrack();
|
|
9212
9238
|
captionsTrack == null ? void 0 : captionsTrack.setProps(data.props);
|
|
9213
|
-
setSelectedItem(data.element);
|
|
9214
9239
|
editor.refresh();
|
|
9240
|
+
updateCanvasRef.current(getCurrentTime(), true);
|
|
9215
9241
|
} else if (operation === CANVAS_OPERATIONS.WATERMARK_UPDATED) {
|
|
9216
9242
|
const w2 = editor.getWatermark();
|
|
9217
9243
|
if (w2 && data) {
|
|
@@ -9222,6 +9248,7 @@ const usePlayerManager = ({
|
|
|
9222
9248
|
editor.setWatermark(w2);
|
|
9223
9249
|
currentChangeLog.current = currentChangeLog.current + 1;
|
|
9224
9250
|
}
|
|
9251
|
+
updateCanvasRef.current(getCurrentTime(), true);
|
|
9225
9252
|
} else {
|
|
9226
9253
|
const element = timeline.ElementDeserializer.fromJSON(data);
|
|
9227
9254
|
switch (operation) {
|
|
@@ -9233,6 +9260,7 @@ const usePlayerManager = ({
|
|
|
9233
9260
|
const updatedElement = editor.updateElement(element);
|
|
9234
9261
|
currentChangeLog.current = currentChangeLog.current + 1;
|
|
9235
9262
|
setSelectedItem(updatedElement);
|
|
9263
|
+
updateCanvasRef.current(getCurrentTime(), true);
|
|
9236
9264
|
}
|
|
9237
9265
|
break;
|
|
9238
9266
|
}
|
|
@@ -9250,17 +9278,20 @@ const usePlayerManager = ({
|
|
|
9250
9278
|
setSelectedItem(element);
|
|
9251
9279
|
currentChangeLog.current = currentChangeLog.current + 1;
|
|
9252
9280
|
editor.refresh();
|
|
9281
|
+
setSeekTime(currentTime);
|
|
9282
|
+
updateCanvasRef.current(currentTime, true);
|
|
9253
9283
|
handleCanvasOperation(CANVAS_OPERATIONS.ADDED_NEW_ELEMENT, {
|
|
9254
9284
|
element,
|
|
9255
9285
|
canvasPosition: canvasX != null && canvasY != null ? { x: canvasX, y: canvasY } : void 0
|
|
9256
9286
|
});
|
|
9257
9287
|
}
|
|
9258
9288
|
},
|
|
9259
|
-
[editor, videoResolution, getCurrentTime, setSelectedItem]
|
|
9289
|
+
[editor, videoResolution, getCurrentTime, setSelectedItem, setSeekTime]
|
|
9260
9290
|
);
|
|
9261
9291
|
const {
|
|
9262
9292
|
twickCanvas,
|
|
9263
9293
|
buildCanvas,
|
|
9294
|
+
resizeCanvas,
|
|
9264
9295
|
setCanvasElements,
|
|
9265
9296
|
bringToFront,
|
|
9266
9297
|
sendToBack,
|
|
@@ -9271,9 +9302,9 @@ const usePlayerManager = ({
|
|
|
9271
9302
|
onCanvasOperation: handleCanvasOperation,
|
|
9272
9303
|
enableShiftAxisLock: (canvasConfig == null ? void 0 : canvasConfig.enableShiftAxisLock) ?? false
|
|
9273
9304
|
});
|
|
9274
|
-
const updateCanvas = (seekTime) => {
|
|
9305
|
+
const updateCanvas = (seekTime, forceRefresh = false) => {
|
|
9275
9306
|
var _a;
|
|
9276
|
-
if (changeLog === currentChangeLog.current && seekTime === prevSeekTime.current) {
|
|
9307
|
+
if (!forceRefresh && changeLog === currentChangeLog.current && seekTime === prevSeekTime.current) {
|
|
9277
9308
|
return;
|
|
9278
9309
|
}
|
|
9279
9310
|
prevSeekTime.current = seekTime;
|
|
@@ -9314,6 +9345,7 @@ const usePlayerManager = ({
|
|
|
9314
9345
|
});
|
|
9315
9346
|
currentChangeLog.current = changeLog;
|
|
9316
9347
|
};
|
|
9348
|
+
updateCanvasRef.current = updateCanvas;
|
|
9317
9349
|
const onPlayerUpdate = (event) => {
|
|
9318
9350
|
var _a;
|
|
9319
9351
|
if (((_a = event == null ? void 0 : event.detail) == null ? void 0 : _a.status) === "ready") {
|
|
@@ -9367,6 +9399,7 @@ const usePlayerManager = ({
|
|
|
9367
9399
|
projectData,
|
|
9368
9400
|
updateCanvas,
|
|
9369
9401
|
buildCanvas,
|
|
9402
|
+
resizeCanvas,
|
|
9370
9403
|
onPlayerUpdate,
|
|
9371
9404
|
playerUpdating,
|
|
9372
9405
|
handleDropOnCanvas,
|
|
@@ -9460,6 +9493,47 @@ function getCanvasY(e3, container, videoSize) {
|
|
|
9460
9493
|
const relY = (e3.clientY - rect.top) / rect.height;
|
|
9461
9494
|
return Math.max(0, Math.min(videoSize.height, relY * videoSize.height));
|
|
9462
9495
|
}
|
|
9496
|
+
function debounce(fn2, delay2) {
|
|
9497
|
+
let timeoutId = null;
|
|
9498
|
+
return (...args) => {
|
|
9499
|
+
if (timeoutId !== null) {
|
|
9500
|
+
clearTimeout(timeoutId);
|
|
9501
|
+
}
|
|
9502
|
+
timeoutId = setTimeout(() => {
|
|
9503
|
+
timeoutId = null;
|
|
9504
|
+
fn2(...args);
|
|
9505
|
+
}, delay2);
|
|
9506
|
+
};
|
|
9507
|
+
}
|
|
9508
|
+
function throttle(fn2, interval) {
|
|
9509
|
+
let lastCallTime = 0;
|
|
9510
|
+
let trailingTimeoutId = null;
|
|
9511
|
+
let lastArgs = null;
|
|
9512
|
+
return (...args) => {
|
|
9513
|
+
const now2 = Date.now();
|
|
9514
|
+
const remaining = interval - (now2 - lastCallTime);
|
|
9515
|
+
if (remaining <= 0) {
|
|
9516
|
+
if (trailingTimeoutId !== null) {
|
|
9517
|
+
clearTimeout(trailingTimeoutId);
|
|
9518
|
+
trailingTimeoutId = null;
|
|
9519
|
+
}
|
|
9520
|
+
lastCallTime = now2;
|
|
9521
|
+
fn2(...args);
|
|
9522
|
+
} else {
|
|
9523
|
+
lastArgs = args;
|
|
9524
|
+
if (trailingTimeoutId === null) {
|
|
9525
|
+
trailingTimeoutId = setTimeout(() => {
|
|
9526
|
+
trailingTimeoutId = null;
|
|
9527
|
+
lastCallTime = Date.now();
|
|
9528
|
+
if (lastArgs) {
|
|
9529
|
+
fn2(...lastArgs);
|
|
9530
|
+
lastArgs = null;
|
|
9531
|
+
}
|
|
9532
|
+
}, remaining);
|
|
9533
|
+
}
|
|
9534
|
+
}
|
|
9535
|
+
};
|
|
9536
|
+
}
|
|
9463
9537
|
const CanvasContextMenu = ({
|
|
9464
9538
|
x: x2,
|
|
9465
9539
|
y: y2,
|
|
@@ -9555,6 +9629,7 @@ const CanvasContextMenu = ({
|
|
|
9555
9629
|
}
|
|
9556
9630
|
);
|
|
9557
9631
|
};
|
|
9632
|
+
const RESIZE_THROTTLE_MS = 200;
|
|
9558
9633
|
const PlayerManager = ({
|
|
9559
9634
|
videoProps,
|
|
9560
9635
|
playerProps,
|
|
@@ -9564,6 +9639,7 @@ const PlayerManager = ({
|
|
|
9564
9639
|
const containerRef = React.useRef(null);
|
|
9565
9640
|
const canvasRef = React.useRef(null);
|
|
9566
9641
|
const durationRef = React.useRef(0);
|
|
9642
|
+
const seekTimeRef = React.useRef(0);
|
|
9567
9643
|
const { changeLog } = timeline.useTimelineContext();
|
|
9568
9644
|
const {
|
|
9569
9645
|
playerState,
|
|
@@ -9576,6 +9652,7 @@ const PlayerManager = ({
|
|
|
9576
9652
|
twickCanvas,
|
|
9577
9653
|
projectData,
|
|
9578
9654
|
updateCanvas,
|
|
9655
|
+
resizeCanvas,
|
|
9579
9656
|
playerUpdating,
|
|
9580
9657
|
onPlayerUpdate,
|
|
9581
9658
|
buildCanvas,
|
|
@@ -9597,19 +9674,44 @@ const PlayerManager = ({
|
|
|
9597
9674
|
React.useEffect(() => {
|
|
9598
9675
|
const container = containerRef.current;
|
|
9599
9676
|
const canvasSize = {
|
|
9600
|
-
width: container == null ? void 0 : container.clientWidth,
|
|
9601
|
-
height: container == null ? void 0 : container.clientHeight
|
|
9677
|
+
width: (container == null ? void 0 : container.clientWidth) ?? 0,
|
|
9678
|
+
height: (container == null ? void 0 : container.clientHeight) ?? 0
|
|
9602
9679
|
};
|
|
9603
|
-
|
|
9604
|
-
|
|
9605
|
-
|
|
9606
|
-
|
|
9607
|
-
|
|
9608
|
-
|
|
9609
|
-
|
|
9610
|
-
|
|
9611
|
-
|
|
9680
|
+
if (canvasSize.width > 0 && canvasSize.height > 0) {
|
|
9681
|
+
buildCanvas({
|
|
9682
|
+
backgroundColor: videoProps.backgroundColor,
|
|
9683
|
+
videoSize: {
|
|
9684
|
+
width: videoProps.width,
|
|
9685
|
+
height: videoProps.height
|
|
9686
|
+
},
|
|
9687
|
+
canvasSize,
|
|
9688
|
+
canvasRef: canvasRef.current
|
|
9689
|
+
});
|
|
9690
|
+
}
|
|
9612
9691
|
}, [videoProps]);
|
|
9692
|
+
const handleResize = React.useMemo(
|
|
9693
|
+
() => throttle(() => {
|
|
9694
|
+
const container = containerRef.current;
|
|
9695
|
+
if (!container || !canvasMode || !twickCanvas) return;
|
|
9696
|
+
const width = container.clientWidth;
|
|
9697
|
+
const height = container.clientHeight;
|
|
9698
|
+
if (width <= 0 || height <= 0) return;
|
|
9699
|
+
resizeCanvas({
|
|
9700
|
+
canvasSize: { width, height },
|
|
9701
|
+
videoSize: { width: videoProps.width, height: videoProps.height }
|
|
9702
|
+
});
|
|
9703
|
+
updateCanvas(seekTimeRef.current, true);
|
|
9704
|
+
}, RESIZE_THROTTLE_MS),
|
|
9705
|
+
[canvasMode, twickCanvas, resizeCanvas, updateCanvas, videoProps.width, videoProps.height]
|
|
9706
|
+
);
|
|
9707
|
+
React.useEffect(() => {
|
|
9708
|
+
const container = containerRef.current;
|
|
9709
|
+
if (!container || !canvasMode) return;
|
|
9710
|
+
const resizeObserver = new ResizeObserver(handleResize);
|
|
9711
|
+
resizeObserver.observe(container);
|
|
9712
|
+
return () => resizeObserver.disconnect();
|
|
9713
|
+
}, [canvasMode, handleResize]);
|
|
9714
|
+
seekTimeRef.current = seekTime;
|
|
9613
9715
|
React.useEffect(() => {
|
|
9614
9716
|
if (twickCanvas && playerState === livePlayer.PLAYER_STATE.PAUSED) {
|
|
9615
9717
|
updateCanvas(seekTime);
|
|
@@ -11119,13 +11221,23 @@ function SeekTrack({
|
|
|
11119
11221
|
minorIntervalSec: minors > 0 ? major / (minors + 1) : major
|
|
11120
11222
|
};
|
|
11121
11223
|
}, [duration, timelineTickConfigs]);
|
|
11122
|
-
const
|
|
11123
|
-
|
|
11124
|
-
|
|
11125
|
-
|
|
11126
|
-
|
|
11127
|
-
onSeek
|
|
11128
|
-
|
|
11224
|
+
const seekToTime = React.useCallback(
|
|
11225
|
+
(time2) => {
|
|
11226
|
+
const clamped = Math.max(0, Math.min(duration, time2));
|
|
11227
|
+
onSeek(clamped);
|
|
11228
|
+
},
|
|
11229
|
+
[duration, onSeek]
|
|
11230
|
+
);
|
|
11231
|
+
const seekFromClientX = React.useCallback(
|
|
11232
|
+
(clientX) => {
|
|
11233
|
+
if (!containerRef.current) return;
|
|
11234
|
+
const rect = containerRef.current.getBoundingClientRect();
|
|
11235
|
+
const x2 = clientX - rect.left + (containerRef.current.scrollLeft || 0);
|
|
11236
|
+
const newTime = Math.max(0, Math.min(duration, x2 / pixelsPerSecond));
|
|
11237
|
+
seekToTime(newTime);
|
|
11238
|
+
},
|
|
11239
|
+
[duration, pixelsPerSecond, seekToTime]
|
|
11240
|
+
);
|
|
11129
11241
|
const bind = useDrag(({ event, xy: [x2], active }) => {
|
|
11130
11242
|
if (event) {
|
|
11131
11243
|
event.stopPropagation();
|
|
@@ -11135,10 +11247,11 @@ function SeekTrack({
|
|
|
11135
11247
|
const rect = containerRef.current.getBoundingClientRect();
|
|
11136
11248
|
const xPos = x2 - rect.left + (containerRef.current.scrollLeft || 0);
|
|
11137
11249
|
const newTime = Math.max(0, Math.min(duration, xPos / pixelsPerSecond));
|
|
11138
|
-
|
|
11139
|
-
|
|
11140
|
-
|
|
11250
|
+
if (active) {
|
|
11251
|
+
setDragPosition(xPos);
|
|
11252
|
+
} else {
|
|
11141
11253
|
setDragPosition(null);
|
|
11254
|
+
seekToTime(newTime);
|
|
11142
11255
|
}
|
|
11143
11256
|
});
|
|
11144
11257
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twick-seek-track", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -11146,7 +11259,7 @@ function SeekTrack({
|
|
|
11146
11259
|
{
|
|
11147
11260
|
ref: containerRef,
|
|
11148
11261
|
className: "twick-seek-track-container-no-scrollbar",
|
|
11149
|
-
onClick: (e3) =>
|
|
11262
|
+
onClick: (e3) => seekFromClientX(e3.clientX),
|
|
11150
11263
|
style: {
|
|
11151
11264
|
overflowX: "auto",
|
|
11152
11265
|
overflowY: "hidden",
|
|
@@ -18960,16 +19073,20 @@ function usePlayheadScroll(scrollContainerRef, playheadPositionPx, isActive, con
|
|
|
18960
19073
|
const container = scrollContainerRef.current;
|
|
18961
19074
|
const contentX = labelWidth + playheadPositionPx;
|
|
18962
19075
|
const scrollToKeepPlayheadVisible = () => {
|
|
18963
|
-
const { scrollLeft, clientWidth } = container;
|
|
19076
|
+
const { scrollLeft, clientWidth, scrollWidth } = container;
|
|
19077
|
+
const maxScrollLeft = Math.max(0, scrollWidth - clientWidth);
|
|
18964
19078
|
const minVisible = scrollLeft + margin;
|
|
18965
19079
|
const maxVisible = scrollLeft + clientWidth - margin;
|
|
18966
19080
|
let newScrollLeft = null;
|
|
18967
19081
|
if (contentX < minVisible) {
|
|
18968
|
-
newScrollLeft = Math.max(0, contentX - margin);
|
|
19082
|
+
newScrollLeft = Math.max(0, Math.min(maxScrollLeft, contentX - margin));
|
|
18969
19083
|
} else if (contentX > maxVisible) {
|
|
18970
|
-
newScrollLeft =
|
|
19084
|
+
newScrollLeft = Math.max(
|
|
19085
|
+
0,
|
|
19086
|
+
Math.min(maxScrollLeft, contentX - clientWidth + margin)
|
|
19087
|
+
);
|
|
18971
19088
|
}
|
|
18972
|
-
if (newScrollLeft !== null) {
|
|
19089
|
+
if (newScrollLeft !== null && Math.abs(newScrollLeft - scrollLeft) > 0.5) {
|
|
18973
19090
|
container.scrollLeft = newScrollLeft;
|
|
18974
19091
|
}
|
|
18975
19092
|
};
|
|
@@ -19356,15 +19473,6 @@ const useTimelineManager = () => {
|
|
|
19356
19473
|
for (const el of elements) {
|
|
19357
19474
|
const newStart = el.getStart() + clampedDelta;
|
|
19358
19475
|
const newEnd = el.getEnd() + clampedDelta;
|
|
19359
|
-
if (el instanceof timeline.VideoElement || el instanceof timeline.AudioElement) {
|
|
19360
|
-
const elementProps = el.getProps();
|
|
19361
|
-
const startDelta = newStart - el.getStart() * ((elementProps == null ? void 0 : elementProps.playbackRate) || 1);
|
|
19362
|
-
if (el instanceof timeline.AudioElement) {
|
|
19363
|
-
el.setStartAt(el.getStartAt() + startDelta);
|
|
19364
|
-
} else {
|
|
19365
|
-
el.setStartAt(el.getStartAt() + startDelta);
|
|
19366
|
-
}
|
|
19367
|
-
}
|
|
19368
19476
|
el.setStart(newStart);
|
|
19369
19477
|
el.setEnd(newEnd);
|
|
19370
19478
|
editor.updateElement(el);
|
|
@@ -20381,9 +20489,11 @@ exports.TEXT_EFFECTS = TEXT_EFFECTS;
|
|
|
20381
20489
|
exports.TIMELINE_DROP_MEDIA_TYPE = TIMELINE_DROP_MEDIA_TYPE;
|
|
20382
20490
|
exports.TimelineManager = TimelineManager;
|
|
20383
20491
|
exports.animationGifs = animationGifs;
|
|
20492
|
+
exports.debounce = debounce;
|
|
20384
20493
|
exports.default = VideoEditor;
|
|
20385
20494
|
exports.getAnimationGif = getAnimationGif;
|
|
20386
20495
|
exports.setElementColors = setElementColors;
|
|
20496
|
+
exports.throttle = throttle;
|
|
20387
20497
|
exports.useEditorManager = useEditorManager;
|
|
20388
20498
|
exports.usePlayerControl = usePlayerControl;
|
|
20389
20499
|
exports.useTimelineControl = useTimelineControl;
|