@twick/video-editor 0.15.15 → 0.15.16
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 +144 -33
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +144 -33
- 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,
|
|
@@ -9261,6 +9284,7 @@ const usePlayerManager = ({
|
|
|
9261
9284
|
const {
|
|
9262
9285
|
twickCanvas,
|
|
9263
9286
|
buildCanvas,
|
|
9287
|
+
resizeCanvas,
|
|
9264
9288
|
setCanvasElements,
|
|
9265
9289
|
bringToFront,
|
|
9266
9290
|
sendToBack,
|
|
@@ -9271,9 +9295,9 @@ const usePlayerManager = ({
|
|
|
9271
9295
|
onCanvasOperation: handleCanvasOperation,
|
|
9272
9296
|
enableShiftAxisLock: (canvasConfig == null ? void 0 : canvasConfig.enableShiftAxisLock) ?? false
|
|
9273
9297
|
});
|
|
9274
|
-
const updateCanvas = (seekTime) => {
|
|
9298
|
+
const updateCanvas = (seekTime, forceRefresh = false) => {
|
|
9275
9299
|
var _a;
|
|
9276
|
-
if (changeLog === currentChangeLog.current && seekTime === prevSeekTime.current) {
|
|
9300
|
+
if (!forceRefresh && changeLog === currentChangeLog.current && seekTime === prevSeekTime.current) {
|
|
9277
9301
|
return;
|
|
9278
9302
|
}
|
|
9279
9303
|
prevSeekTime.current = seekTime;
|
|
@@ -9367,6 +9391,7 @@ const usePlayerManager = ({
|
|
|
9367
9391
|
projectData,
|
|
9368
9392
|
updateCanvas,
|
|
9369
9393
|
buildCanvas,
|
|
9394
|
+
resizeCanvas,
|
|
9370
9395
|
onPlayerUpdate,
|
|
9371
9396
|
playerUpdating,
|
|
9372
9397
|
handleDropOnCanvas,
|
|
@@ -9460,6 +9485,47 @@ function getCanvasY(e3, container, videoSize) {
|
|
|
9460
9485
|
const relY = (e3.clientY - rect.top) / rect.height;
|
|
9461
9486
|
return Math.max(0, Math.min(videoSize.height, relY * videoSize.height));
|
|
9462
9487
|
}
|
|
9488
|
+
function debounce(fn2, delay2) {
|
|
9489
|
+
let timeoutId = null;
|
|
9490
|
+
return (...args) => {
|
|
9491
|
+
if (timeoutId !== null) {
|
|
9492
|
+
clearTimeout(timeoutId);
|
|
9493
|
+
}
|
|
9494
|
+
timeoutId = setTimeout(() => {
|
|
9495
|
+
timeoutId = null;
|
|
9496
|
+
fn2(...args);
|
|
9497
|
+
}, delay2);
|
|
9498
|
+
};
|
|
9499
|
+
}
|
|
9500
|
+
function throttle(fn2, interval) {
|
|
9501
|
+
let lastCallTime = 0;
|
|
9502
|
+
let trailingTimeoutId = null;
|
|
9503
|
+
let lastArgs = null;
|
|
9504
|
+
return (...args) => {
|
|
9505
|
+
const now2 = Date.now();
|
|
9506
|
+
const remaining = interval - (now2 - lastCallTime);
|
|
9507
|
+
if (remaining <= 0) {
|
|
9508
|
+
if (trailingTimeoutId !== null) {
|
|
9509
|
+
clearTimeout(trailingTimeoutId);
|
|
9510
|
+
trailingTimeoutId = null;
|
|
9511
|
+
}
|
|
9512
|
+
lastCallTime = now2;
|
|
9513
|
+
fn2(...args);
|
|
9514
|
+
} else {
|
|
9515
|
+
lastArgs = args;
|
|
9516
|
+
if (trailingTimeoutId === null) {
|
|
9517
|
+
trailingTimeoutId = setTimeout(() => {
|
|
9518
|
+
trailingTimeoutId = null;
|
|
9519
|
+
lastCallTime = Date.now();
|
|
9520
|
+
if (lastArgs) {
|
|
9521
|
+
fn2(...lastArgs);
|
|
9522
|
+
lastArgs = null;
|
|
9523
|
+
}
|
|
9524
|
+
}, remaining);
|
|
9525
|
+
}
|
|
9526
|
+
}
|
|
9527
|
+
};
|
|
9528
|
+
}
|
|
9463
9529
|
const CanvasContextMenu = ({
|
|
9464
9530
|
x: x2,
|
|
9465
9531
|
y: y2,
|
|
@@ -9555,6 +9621,7 @@ const CanvasContextMenu = ({
|
|
|
9555
9621
|
}
|
|
9556
9622
|
);
|
|
9557
9623
|
};
|
|
9624
|
+
const RESIZE_THROTTLE_MS = 200;
|
|
9558
9625
|
const PlayerManager = ({
|
|
9559
9626
|
videoProps,
|
|
9560
9627
|
playerProps,
|
|
@@ -9564,6 +9631,7 @@ const PlayerManager = ({
|
|
|
9564
9631
|
const containerRef = React.useRef(null);
|
|
9565
9632
|
const canvasRef = React.useRef(null);
|
|
9566
9633
|
const durationRef = React.useRef(0);
|
|
9634
|
+
const seekTimeRef = React.useRef(0);
|
|
9567
9635
|
const { changeLog } = timeline.useTimelineContext();
|
|
9568
9636
|
const {
|
|
9569
9637
|
playerState,
|
|
@@ -9576,6 +9644,7 @@ const PlayerManager = ({
|
|
|
9576
9644
|
twickCanvas,
|
|
9577
9645
|
projectData,
|
|
9578
9646
|
updateCanvas,
|
|
9647
|
+
resizeCanvas,
|
|
9579
9648
|
playerUpdating,
|
|
9580
9649
|
onPlayerUpdate,
|
|
9581
9650
|
buildCanvas,
|
|
@@ -9597,19 +9666,44 @@ const PlayerManager = ({
|
|
|
9597
9666
|
React.useEffect(() => {
|
|
9598
9667
|
const container = containerRef.current;
|
|
9599
9668
|
const canvasSize = {
|
|
9600
|
-
width: container == null ? void 0 : container.clientWidth,
|
|
9601
|
-
height: container == null ? void 0 : container.clientHeight
|
|
9669
|
+
width: (container == null ? void 0 : container.clientWidth) ?? 0,
|
|
9670
|
+
height: (container == null ? void 0 : container.clientHeight) ?? 0
|
|
9602
9671
|
};
|
|
9603
|
-
|
|
9604
|
-
|
|
9605
|
-
|
|
9606
|
-
|
|
9607
|
-
|
|
9608
|
-
|
|
9609
|
-
|
|
9610
|
-
|
|
9611
|
-
|
|
9672
|
+
if (canvasSize.width > 0 && canvasSize.height > 0) {
|
|
9673
|
+
buildCanvas({
|
|
9674
|
+
backgroundColor: videoProps.backgroundColor,
|
|
9675
|
+
videoSize: {
|
|
9676
|
+
width: videoProps.width,
|
|
9677
|
+
height: videoProps.height
|
|
9678
|
+
},
|
|
9679
|
+
canvasSize,
|
|
9680
|
+
canvasRef: canvasRef.current
|
|
9681
|
+
});
|
|
9682
|
+
}
|
|
9612
9683
|
}, [videoProps]);
|
|
9684
|
+
const handleResize = React.useMemo(
|
|
9685
|
+
() => throttle(() => {
|
|
9686
|
+
const container = containerRef.current;
|
|
9687
|
+
if (!container || !canvasMode || !twickCanvas) return;
|
|
9688
|
+
const width = container.clientWidth;
|
|
9689
|
+
const height = container.clientHeight;
|
|
9690
|
+
if (width <= 0 || height <= 0) return;
|
|
9691
|
+
resizeCanvas({
|
|
9692
|
+
canvasSize: { width, height },
|
|
9693
|
+
videoSize: { width: videoProps.width, height: videoProps.height }
|
|
9694
|
+
});
|
|
9695
|
+
updateCanvas(seekTimeRef.current, true);
|
|
9696
|
+
}, RESIZE_THROTTLE_MS),
|
|
9697
|
+
[canvasMode, twickCanvas, resizeCanvas, updateCanvas, videoProps.width, videoProps.height]
|
|
9698
|
+
);
|
|
9699
|
+
React.useEffect(() => {
|
|
9700
|
+
const container = containerRef.current;
|
|
9701
|
+
if (!container || !canvasMode) return;
|
|
9702
|
+
const resizeObserver = new ResizeObserver(handleResize);
|
|
9703
|
+
resizeObserver.observe(container);
|
|
9704
|
+
return () => resizeObserver.disconnect();
|
|
9705
|
+
}, [canvasMode, handleResize]);
|
|
9706
|
+
seekTimeRef.current = seekTime;
|
|
9613
9707
|
React.useEffect(() => {
|
|
9614
9708
|
if (twickCanvas && playerState === livePlayer.PLAYER_STATE.PAUSED) {
|
|
9615
9709
|
updateCanvas(seekTime);
|
|
@@ -11119,13 +11213,23 @@ function SeekTrack({
|
|
|
11119
11213
|
minorIntervalSec: minors > 0 ? major / (minors + 1) : major
|
|
11120
11214
|
};
|
|
11121
11215
|
}, [duration, timelineTickConfigs]);
|
|
11122
|
-
const
|
|
11123
|
-
|
|
11124
|
-
|
|
11125
|
-
|
|
11126
|
-
|
|
11127
|
-
onSeek
|
|
11128
|
-
|
|
11216
|
+
const seekToTime = React.useCallback(
|
|
11217
|
+
(time2) => {
|
|
11218
|
+
const clamped = Math.max(0, Math.min(duration, time2));
|
|
11219
|
+
onSeek(clamped);
|
|
11220
|
+
},
|
|
11221
|
+
[duration, onSeek]
|
|
11222
|
+
);
|
|
11223
|
+
const seekFromClientX = React.useCallback(
|
|
11224
|
+
(clientX) => {
|
|
11225
|
+
if (!containerRef.current) return;
|
|
11226
|
+
const rect = containerRef.current.getBoundingClientRect();
|
|
11227
|
+
const x2 = clientX - rect.left + (containerRef.current.scrollLeft || 0);
|
|
11228
|
+
const newTime = Math.max(0, Math.min(duration, x2 / pixelsPerSecond));
|
|
11229
|
+
seekToTime(newTime);
|
|
11230
|
+
},
|
|
11231
|
+
[duration, pixelsPerSecond, seekToTime]
|
|
11232
|
+
);
|
|
11129
11233
|
const bind = useDrag(({ event, xy: [x2], active }) => {
|
|
11130
11234
|
if (event) {
|
|
11131
11235
|
event.stopPropagation();
|
|
@@ -11135,10 +11239,11 @@ function SeekTrack({
|
|
|
11135
11239
|
const rect = containerRef.current.getBoundingClientRect();
|
|
11136
11240
|
const xPos = x2 - rect.left + (containerRef.current.scrollLeft || 0);
|
|
11137
11241
|
const newTime = Math.max(0, Math.min(duration, xPos / pixelsPerSecond));
|
|
11138
|
-
|
|
11139
|
-
|
|
11140
|
-
|
|
11242
|
+
if (active) {
|
|
11243
|
+
setDragPosition(xPos);
|
|
11244
|
+
} else {
|
|
11141
11245
|
setDragPosition(null);
|
|
11246
|
+
seekToTime(newTime);
|
|
11142
11247
|
}
|
|
11143
11248
|
});
|
|
11144
11249
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twick-seek-track", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -11146,7 +11251,7 @@ function SeekTrack({
|
|
|
11146
11251
|
{
|
|
11147
11252
|
ref: containerRef,
|
|
11148
11253
|
className: "twick-seek-track-container-no-scrollbar",
|
|
11149
|
-
onClick: (e3) =>
|
|
11254
|
+
onClick: (e3) => seekFromClientX(e3.clientX),
|
|
11150
11255
|
style: {
|
|
11151
11256
|
overflowX: "auto",
|
|
11152
11257
|
overflowY: "hidden",
|
|
@@ -18960,16 +19065,20 @@ function usePlayheadScroll(scrollContainerRef, playheadPositionPx, isActive, con
|
|
|
18960
19065
|
const container = scrollContainerRef.current;
|
|
18961
19066
|
const contentX = labelWidth + playheadPositionPx;
|
|
18962
19067
|
const scrollToKeepPlayheadVisible = () => {
|
|
18963
|
-
const { scrollLeft, clientWidth } = container;
|
|
19068
|
+
const { scrollLeft, clientWidth, scrollWidth } = container;
|
|
19069
|
+
const maxScrollLeft = Math.max(0, scrollWidth - clientWidth);
|
|
18964
19070
|
const minVisible = scrollLeft + margin;
|
|
18965
19071
|
const maxVisible = scrollLeft + clientWidth - margin;
|
|
18966
19072
|
let newScrollLeft = null;
|
|
18967
19073
|
if (contentX < minVisible) {
|
|
18968
|
-
newScrollLeft = Math.max(0, contentX - margin);
|
|
19074
|
+
newScrollLeft = Math.max(0, Math.min(maxScrollLeft, contentX - margin));
|
|
18969
19075
|
} else if (contentX > maxVisible) {
|
|
18970
|
-
newScrollLeft =
|
|
19076
|
+
newScrollLeft = Math.max(
|
|
19077
|
+
0,
|
|
19078
|
+
Math.min(maxScrollLeft, contentX - clientWidth + margin)
|
|
19079
|
+
);
|
|
18971
19080
|
}
|
|
18972
|
-
if (newScrollLeft !== null) {
|
|
19081
|
+
if (newScrollLeft !== null && Math.abs(newScrollLeft - scrollLeft) > 0.5) {
|
|
18973
19082
|
container.scrollLeft = newScrollLeft;
|
|
18974
19083
|
}
|
|
18975
19084
|
};
|
|
@@ -20381,9 +20490,11 @@ exports.TEXT_EFFECTS = TEXT_EFFECTS;
|
|
|
20381
20490
|
exports.TIMELINE_DROP_MEDIA_TYPE = TIMELINE_DROP_MEDIA_TYPE;
|
|
20382
20491
|
exports.TimelineManager = TimelineManager;
|
|
20383
20492
|
exports.animationGifs = animationGifs;
|
|
20493
|
+
exports.debounce = debounce;
|
|
20384
20494
|
exports.default = VideoEditor;
|
|
20385
20495
|
exports.getAnimationGif = getAnimationGif;
|
|
20386
20496
|
exports.setElementColors = setElementColors;
|
|
20497
|
+
exports.throttle = throttle;
|
|
20387
20498
|
exports.useEditorManager = useEditorManager;
|
|
20388
20499
|
exports.usePlayerControl = usePlayerControl;
|
|
20389
20500
|
exports.useTimelineControl = useTimelineControl;
|