@twick/video-editor 0.15.19 → 0.15.21
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/components/timeline/timeline-view.d.ts +14 -3
- package/dist/components/track/track-base.d.ts +4 -9
- package/dist/components/track/track-element.d.ts +14 -8
- package/dist/helpers/types.d.ts +1 -0
- package/dist/hooks/use-edge-auto-scroll.d.ts +12 -0
- package/dist/hooks/use-player-manager.d.ts +1 -0
- package/dist/hooks/use-timeline-manager.d.ts +16 -4
- package/dist/index.js +551 -79
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +552 -80
- package/dist/index.mjs.map +1 -1
- package/dist/utils/drop-target.d.ts +12 -0
- package/package.json +5 -5
package/dist/index.mjs
CHANGED
|
@@ -3,7 +3,7 @@ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { en
|
|
|
3
3
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
4
|
import { jsxs, jsx } from "react/jsx-runtime";
|
|
5
5
|
import { useLivePlayerContext, PLAYER_STATE, LivePlayer } from "@twick/live-player";
|
|
6
|
-
import { ImageElement as ImageElement$1, AudioElement, VideoElement as VideoElement$1, useTimelineContext, TIMELINE_ACTION, ElementDeserializer, getCurrentElements, CaptionElement as CaptionElement$1, getDecimalNumber, resolveIds, TrackElement, resolveId, Track, getElementIdsInRange, ValidationError, VALIDATION_ERROR_CODE, formatTimeWithFrames } from "@twick/timeline";
|
|
6
|
+
import { ImageElement as ImageElement$1, AudioElement, VideoElement as VideoElement$1, useTimelineContext, TIMELINE_ACTION, ElementDeserializer, getCurrentElements, CaptionElement as CaptionElement$1, TIMELINE_ELEMENT_TYPE, getDecimalNumber, resolveIds, TrackElement, TRACK_TYPES, resolveId, Track, getElementIdsInRange, ValidationError, VALIDATION_ERROR_CODE, formatTimeWithFrames } from "@twick/timeline";
|
|
7
7
|
import React, { useState, useRef, useCallback, useEffect, useMemo, forwardRef, createElement, createContext, useContext, useId, useLayoutEffect, useInsertionEffect, Fragment, Component } from "react";
|
|
8
8
|
function t(t2, e3, s2) {
|
|
9
9
|
return (e3 = function(t3) {
|
|
@@ -6855,8 +6855,8 @@ const DEFAULT_TEXT_PROPS = {
|
|
|
6855
6855
|
lineWidth: 0
|
|
6856
6856
|
};
|
|
6857
6857
|
const DEFAULT_CAPTION_PROPS = {
|
|
6858
|
-
/** Font family for caption elements */
|
|
6859
|
-
family: "
|
|
6858
|
+
/** Font family for caption elements (matches highlight_bg default) */
|
|
6859
|
+
family: "Bangers",
|
|
6860
6860
|
/** Font size in pixels */
|
|
6861
6861
|
size: 48,
|
|
6862
6862
|
/** Text fill color */
|
|
@@ -6900,7 +6900,13 @@ const ELEMENT_TYPES = {
|
|
|
6900
6900
|
/** Rectangle element type */
|
|
6901
6901
|
RECT: "rect",
|
|
6902
6902
|
/** Circle element type */
|
|
6903
|
-
CIRCLE: "circle"
|
|
6903
|
+
CIRCLE: "circle",
|
|
6904
|
+
/** Arrow annotation element type */
|
|
6905
|
+
ARROW: "arrow",
|
|
6906
|
+
/** Line annotation / shape element type */
|
|
6907
|
+
LINE: "line",
|
|
6908
|
+
/** Global / adjustment-layer style effect element */
|
|
6909
|
+
EFFECT: "effect"
|
|
6904
6910
|
};
|
|
6905
6911
|
const isBrowser$2 = typeof window !== "undefined";
|
|
6906
6912
|
const isCanvasSupported = isBrowser$2 && !!window.HTMLCanvasElement;
|
|
@@ -7644,40 +7650,44 @@ const addCaptionElement = ({
|
|
|
7644
7650
|
canvasMetadata,
|
|
7645
7651
|
lockAspectRatio = false
|
|
7646
7652
|
}) => {
|
|
7647
|
-
var _a, _b, _c, _d, _e2, _f, _g, _h2, _i2, _j, _k, _l, _m, _n2, _o2, _p, _q, _r2, _s2, _t2, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J;
|
|
7653
|
+
var _a, _b, _c, _d, _e2, _f, _g, _h2, _i2, _j, _k, _l, _m, _n2, _o2, _p, _q, _r2, _s2, _t2, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L;
|
|
7654
|
+
const applyToAll = (captionProps == null ? void 0 : captionProps.applyToAll) ?? false;
|
|
7655
|
+
const captionTextColor = ((_a = captionProps == null ? void 0 : captionProps.colors) == null ? void 0 : _a.text) ?? ((_b = captionProps == null ? void 0 : captionProps.color) == null ? void 0 : _b.text);
|
|
7648
7656
|
const { x: x2, y: y2 } = convertToCanvasPosition(
|
|
7649
|
-
(
|
|
7650
|
-
(
|
|
7657
|
+
(applyToAll ? captionProps == null ? void 0 : captionProps.x : ((_c = element.props) == null ? void 0 : _c.x) ?? (captionProps == null ? void 0 : captionProps.x)) ?? 0,
|
|
7658
|
+
(applyToAll ? captionProps == null ? void 0 : captionProps.y : ((_d = element.props) == null ? void 0 : _d.y) ?? (captionProps == null ? void 0 : captionProps.y)) ?? 0,
|
|
7651
7659
|
canvasMetadata
|
|
7652
7660
|
);
|
|
7653
|
-
let width = ((
|
|
7654
|
-
if ((
|
|
7661
|
+
let width = ((_e2 = element.props) == null ? void 0 : _e2.width) ? element.props.width * canvasMetadata.scaleX : canvasMetadata.width - 2 * MARGIN;
|
|
7662
|
+
if ((_f = element.props) == null ? void 0 : _f.maxWidth) {
|
|
7655
7663
|
width = Math.min(width, element.props.maxWidth * canvasMetadata.scaleX);
|
|
7656
7664
|
}
|
|
7657
|
-
const
|
|
7665
|
+
const elementColors = (_g = element.props) == null ? void 0 : _g.colors;
|
|
7666
|
+
const resolvedFill = (applyToAll ? captionTextColor : ((_h2 = element.props) == null ? void 0 : _h2.fill) ?? (elementColors == null ? void 0 : elementColors.text) ?? captionTextColor) ?? DEFAULT_CAPTION_PROPS.fill;
|
|
7667
|
+
const caption = new Uo(((_i2 = element.props) == null ? void 0 : _i2.text) || element.t || "", {
|
|
7658
7668
|
left: x2,
|
|
7659
7669
|
top: y2,
|
|
7660
7670
|
originX: "center",
|
|
7661
7671
|
originY: "center",
|
|
7662
|
-
angle: ((
|
|
7672
|
+
angle: ((_j = element.props) == null ? void 0 : _j.rotation) || 0,
|
|
7663
7673
|
fontSize: Math.round(
|
|
7664
|
-
((
|
|
7674
|
+
((applyToAll ? (_k = captionProps == null ? void 0 : captionProps.font) == null ? void 0 : _k.size : ((_m = (_l = element.props) == null ? void 0 : _l.font) == null ? void 0 : _m.size) ?? ((_n2 = captionProps == null ? void 0 : captionProps.font) == null ? void 0 : _n2.size)) ?? DEFAULT_CAPTION_PROPS.size) * canvasMetadata.scaleX
|
|
7665
7675
|
),
|
|
7666
|
-
fontFamily: (
|
|
7667
|
-
fill:
|
|
7668
|
-
fontWeight: (
|
|
7669
|
-
stroke: (
|
|
7670
|
-
opacity: (
|
|
7676
|
+
fontFamily: (applyToAll ? (_o2 = captionProps == null ? void 0 : captionProps.font) == null ? void 0 : _o2.family : ((_q = (_p = element.props) == null ? void 0 : _p.font) == null ? void 0 : _q.family) ?? ((_r2 = captionProps == null ? void 0 : captionProps.font) == null ? void 0 : _r2.family)) ?? DEFAULT_CAPTION_PROPS.family,
|
|
7677
|
+
fill: resolvedFill,
|
|
7678
|
+
fontWeight: (applyToAll ? (_s2 = captionProps == null ? void 0 : captionProps.font) == null ? void 0 : _s2.weight : ((_u = (_t2 = element.props) == null ? void 0 : _t2.font) == null ? void 0 : _u.weight) ?? ((_v = captionProps == null ? void 0 : captionProps.font) == null ? void 0 : _v.weight)) ?? DEFAULT_CAPTION_PROPS.fontWeight,
|
|
7679
|
+
stroke: (applyToAll ? captionProps == null ? void 0 : captionProps.stroke : ((_w = element.props) == null ? void 0 : _w.stroke) ?? (captionProps == null ? void 0 : captionProps.stroke)) ?? DEFAULT_CAPTION_PROPS.stroke,
|
|
7680
|
+
opacity: (applyToAll ? captionProps == null ? void 0 : captionProps.opacity : ((_x = element.props) == null ? void 0 : _x.opacity) ?? (captionProps == null ? void 0 : captionProps.opacity)) ?? 1,
|
|
7671
7681
|
width,
|
|
7672
7682
|
splitByGrapheme: false,
|
|
7673
|
-
textAlign: ((
|
|
7683
|
+
textAlign: ((_y = element.props) == null ? void 0 : _y.textAlign) ?? "center",
|
|
7674
7684
|
shadow: new Ds({
|
|
7675
|
-
offsetX: (
|
|
7676
|
-
offsetY: (
|
|
7677
|
-
blur: (
|
|
7678
|
-
color: (
|
|
7685
|
+
offsetX: (applyToAll ? (_z = captionProps == null ? void 0 : captionProps.shadowOffset) == null ? void 0 : _z[0] : ((_B = (_A = element.props) == null ? void 0 : _A.shadowOffset) == null ? void 0 : _B[0]) ?? ((_C = captionProps == null ? void 0 : captionProps.shadowOffset) == null ? void 0 : _C[0])) ?? ((_D = DEFAULT_CAPTION_PROPS.shadowOffset) == null ? void 0 : _D[0]),
|
|
7686
|
+
offsetY: (applyToAll ? (_E = captionProps == null ? void 0 : captionProps.shadowOffset) == null ? void 0 : _E[1] : ((_G = (_F = element.props) == null ? void 0 : _F.shadowOffset) == null ? void 0 : _G[1]) ?? ((_H = captionProps == null ? void 0 : captionProps.shadowOffset) == null ? void 0 : _H[1])) ?? ((_I = DEFAULT_CAPTION_PROPS.shadowOffset) == null ? void 0 : _I[1]),
|
|
7687
|
+
blur: (applyToAll ? captionProps == null ? void 0 : captionProps.shadowBlur : ((_J = element.props) == null ? void 0 : _J.shadowBlur) ?? (captionProps == null ? void 0 : captionProps.shadowBlur)) ?? DEFAULT_CAPTION_PROPS.shadowBlur,
|
|
7688
|
+
color: (applyToAll ? captionProps == null ? void 0 : captionProps.shadowColor : ((_K = element.props) == null ? void 0 : _K.shadowColor) ?? (captionProps == null ? void 0 : captionProps.shadowColor)) ?? DEFAULT_CAPTION_PROPS.shadowColor
|
|
7679
7689
|
}),
|
|
7680
|
-
strokeWidth: (
|
|
7690
|
+
strokeWidth: (applyToAll ? captionProps == null ? void 0 : captionProps.lineWidth : ((_L = element.props) == null ? void 0 : _L.lineWidth) ?? (captionProps == null ? void 0 : captionProps.lineWidth)) ?? DEFAULT_CAPTION_PROPS.lineWidth
|
|
7681
7691
|
});
|
|
7682
7692
|
caption.set("id", element.id);
|
|
7683
7693
|
caption.set("zIndex", index);
|
|
@@ -8388,6 +8398,148 @@ const WatermarkElement = {
|
|
|
8388
8398
|
};
|
|
8389
8399
|
}
|
|
8390
8400
|
};
|
|
8401
|
+
const ArrowElement = {
|
|
8402
|
+
name: ELEMENT_TYPES.ARROW,
|
|
8403
|
+
async add(params) {
|
|
8404
|
+
var _a, _b, _c, _d, _e2, _f, _g, _h2, _i2;
|
|
8405
|
+
const { element, index, canvas, canvasMetadata, lockAspectRatio } = params;
|
|
8406
|
+
const baseWidth = ((_a = element.props) == null ? void 0 : _a.width) ?? 220;
|
|
8407
|
+
const baseHeight = ((_b = element.props) == null ? void 0 : _b.height) ?? 14;
|
|
8408
|
+
const { x: x2, y: y2 } = convertToCanvasPosition(
|
|
8409
|
+
((_c = element.props) == null ? void 0 : _c.x) ?? 0,
|
|
8410
|
+
((_d = element.props) == null ? void 0 : _d.y) ?? 0,
|
|
8411
|
+
canvasMetadata
|
|
8412
|
+
);
|
|
8413
|
+
const fill = ((_e2 = element.props) == null ? void 0 : _e2.fill) || "#f59e0b";
|
|
8414
|
+
const radius = (((_f = element.props) == null ? void 0 : _f.radius) ?? 4) * canvasMetadata.scaleX;
|
|
8415
|
+
const barWidth = baseWidth * canvasMetadata.scaleX;
|
|
8416
|
+
const barHeight = baseHeight * canvasMetadata.scaleY;
|
|
8417
|
+
const headSize = barHeight * 1.8;
|
|
8418
|
+
const barLength = barWidth - headSize * 0.5;
|
|
8419
|
+
const bar = new jr({
|
|
8420
|
+
left: -barWidth / 2,
|
|
8421
|
+
top: -barHeight / 2,
|
|
8422
|
+
originX: "left",
|
|
8423
|
+
originY: "top",
|
|
8424
|
+
width: barLength,
|
|
8425
|
+
height: barHeight,
|
|
8426
|
+
rx: radius,
|
|
8427
|
+
ry: radius,
|
|
8428
|
+
fill
|
|
8429
|
+
});
|
|
8430
|
+
const arrowHead = new yo({
|
|
8431
|
+
left: barWidth / 2 - headSize * 0.25,
|
|
8432
|
+
top: 0,
|
|
8433
|
+
originX: "center",
|
|
8434
|
+
originY: "center",
|
|
8435
|
+
width: headSize,
|
|
8436
|
+
height: headSize,
|
|
8437
|
+
fill,
|
|
8438
|
+
angle: 90
|
|
8439
|
+
});
|
|
8440
|
+
const opacity = ((_g = element.props) == null ? void 0 : _g.opacity) ?? 1;
|
|
8441
|
+
const group = new Ur([bar, arrowHead], {
|
|
8442
|
+
left: x2,
|
|
8443
|
+
top: y2,
|
|
8444
|
+
originX: "center",
|
|
8445
|
+
originY: "center",
|
|
8446
|
+
angle: ((_h2 = element.props) == null ? void 0 : _h2.rotation) || 0,
|
|
8447
|
+
opacity,
|
|
8448
|
+
selectable: true,
|
|
8449
|
+
hasControls: true
|
|
8450
|
+
});
|
|
8451
|
+
group.set(
|
|
8452
|
+
"lockUniScaling",
|
|
8453
|
+
lockAspectRatio ?? ((_i2 = element.props) == null ? void 0 : _i2.lockAspectRatio) ?? true
|
|
8454
|
+
);
|
|
8455
|
+
group.set("id", element.id);
|
|
8456
|
+
group.set("zIndex", index);
|
|
8457
|
+
canvas.add(group);
|
|
8458
|
+
},
|
|
8459
|
+
updateFromFabricObject(object, element, context) {
|
|
8460
|
+
var _a, _b, _c;
|
|
8461
|
+
const canvasCenter = getObjectCanvasCenter(object);
|
|
8462
|
+
const { x: x2, y: y2 } = convertToVideoPosition(
|
|
8463
|
+
canvasCenter.x,
|
|
8464
|
+
canvasCenter.y,
|
|
8465
|
+
context.canvasMetadata,
|
|
8466
|
+
context.videoSize
|
|
8467
|
+
);
|
|
8468
|
+
const baseWidth = ((_a = element.props) == null ? void 0 : _a.width) ?? 220;
|
|
8469
|
+
const baseHeight = ((_b = element.props) == null ? void 0 : _b.height) ?? 14;
|
|
8470
|
+
const opacity = object.opacity ?? ((_c = element.props) == null ? void 0 : _c.opacity) ?? 1;
|
|
8471
|
+
return {
|
|
8472
|
+
element: {
|
|
8473
|
+
...element,
|
|
8474
|
+
props: {
|
|
8475
|
+
...element.props,
|
|
8476
|
+
rotation: getObjectCanvasAngle(object),
|
|
8477
|
+
width: baseWidth * object.scaleX,
|
|
8478
|
+
height: baseHeight * object.scaleY,
|
|
8479
|
+
x: x2,
|
|
8480
|
+
y: y2,
|
|
8481
|
+
opacity
|
|
8482
|
+
}
|
|
8483
|
+
}
|
|
8484
|
+
};
|
|
8485
|
+
}
|
|
8486
|
+
};
|
|
8487
|
+
const LineElement = {
|
|
8488
|
+
name: ELEMENT_TYPES.LINE,
|
|
8489
|
+
async add(params) {
|
|
8490
|
+
var _a;
|
|
8491
|
+
const { element, index, canvas, canvasMetadata, lockAspectRatio } = params;
|
|
8492
|
+
const lineProps = element.props ?? {};
|
|
8493
|
+
const lineElement = {
|
|
8494
|
+
...element,
|
|
8495
|
+
props: {
|
|
8496
|
+
...lineProps,
|
|
8497
|
+
// Use fill as stroke color when a stroke is desired; otherwise rely
|
|
8498
|
+
// on fill-only rendering. Avoid the generic "#000000" fallback.
|
|
8499
|
+
stroke: lineProps.stroke ?? lineProps.fill,
|
|
8500
|
+
// If a specific lineWidth is provided, keep it; otherwise default to 0
|
|
8501
|
+
// so the stroke does not override the visual fill color.
|
|
8502
|
+
lineWidth: lineProps.lineWidth ?? 0
|
|
8503
|
+
}
|
|
8504
|
+
};
|
|
8505
|
+
await addRectElement({
|
|
8506
|
+
element: lineElement,
|
|
8507
|
+
index,
|
|
8508
|
+
canvas,
|
|
8509
|
+
canvasMetadata,
|
|
8510
|
+
lockAspectRatio: lockAspectRatio ?? ((_a = lineElement.props) == null ? void 0 : _a.lockAspectRatio)
|
|
8511
|
+
});
|
|
8512
|
+
},
|
|
8513
|
+
updateFromFabricObject(object, element, context) {
|
|
8514
|
+
var _a, _b;
|
|
8515
|
+
const canvasCenter = getObjectCanvasCenter(object);
|
|
8516
|
+
const { x: x2, y: y2 } = convertToVideoPosition(
|
|
8517
|
+
canvasCenter.x,
|
|
8518
|
+
canvasCenter.y,
|
|
8519
|
+
context.canvasMetadata,
|
|
8520
|
+
context.videoSize
|
|
8521
|
+
);
|
|
8522
|
+
return {
|
|
8523
|
+
element: {
|
|
8524
|
+
...element,
|
|
8525
|
+
props: {
|
|
8526
|
+
...element.props,
|
|
8527
|
+
rotation: getObjectCanvasAngle(object),
|
|
8528
|
+
width: (((_a = element.props) == null ? void 0 : _a.width) ?? 0) * object.scaleX,
|
|
8529
|
+
height: (((_b = element.props) == null ? void 0 : _b.height) ?? 0) * object.scaleY,
|
|
8530
|
+
x: x2,
|
|
8531
|
+
y: y2
|
|
8532
|
+
}
|
|
8533
|
+
}
|
|
8534
|
+
};
|
|
8535
|
+
}
|
|
8536
|
+
};
|
|
8537
|
+
const EffectElement = {
|
|
8538
|
+
name: ELEMENT_TYPES.EFFECT,
|
|
8539
|
+
async add() {
|
|
8540
|
+
return;
|
|
8541
|
+
}
|
|
8542
|
+
};
|
|
8391
8543
|
class ElementController {
|
|
8392
8544
|
constructor() {
|
|
8393
8545
|
__publicField2(this, "elements", /* @__PURE__ */ new Map());
|
|
@@ -8411,6 +8563,9 @@ function registerElements() {
|
|
|
8411
8563
|
elementController.register(TextElement);
|
|
8412
8564
|
elementController.register(CaptionElement);
|
|
8413
8565
|
elementController.register(WatermarkElement);
|
|
8566
|
+
elementController.register(ArrowElement);
|
|
8567
|
+
elementController.register(LineElement);
|
|
8568
|
+
elementController.register(EffectElement);
|
|
8414
8569
|
}
|
|
8415
8570
|
registerElements();
|
|
8416
8571
|
const useTwickCanvas = ({
|
|
@@ -8765,10 +8920,18 @@ const useTwickCanvas = ({
|
|
|
8765
8920
|
const sendToBack = (elementId) => applyZOrder(elementId, "back");
|
|
8766
8921
|
const bringForward = (elementId) => applyZOrder(elementId, "forward");
|
|
8767
8922
|
const sendBackward = (elementId) => applyZOrder(elementId, "backward");
|
|
8923
|
+
const setBackgroundColor = useCallback((color2) => {
|
|
8924
|
+
const canvas = twickCanvasRef.current;
|
|
8925
|
+
if (canvas) {
|
|
8926
|
+
canvas.backgroundColor = color2;
|
|
8927
|
+
canvas.requestRenderAll();
|
|
8928
|
+
}
|
|
8929
|
+
}, []);
|
|
8768
8930
|
return {
|
|
8769
8931
|
twickCanvas,
|
|
8770
8932
|
buildCanvas,
|
|
8771
8933
|
resizeCanvas,
|
|
8934
|
+
setBackgroundColor,
|
|
8772
8935
|
onVideoSizeChange,
|
|
8773
8936
|
addWatermarkToCanvas,
|
|
8774
8937
|
addElementToCanvas,
|
|
@@ -8983,7 +9146,9 @@ const DEFAULT_ELEMENT_COLORS = {
|
|
|
8983
9146
|
/** Icon element color - bright orchid */
|
|
8984
9147
|
icon: "#A76CD4",
|
|
8985
9148
|
/** Circle element color - deep byzantium */
|
|
8986
|
-
circle: "#703D8B"
|
|
9149
|
+
circle: "#703D8B",
|
|
9150
|
+
/** Effect element color - cyan accent for global effects */
|
|
9151
|
+
effect: "#22C3EE"
|
|
8987
9152
|
};
|
|
8988
9153
|
const AVAILABLE_TEXT_FONTS = {
|
|
8989
9154
|
// Google Fonts
|
|
@@ -9290,6 +9455,7 @@ const usePlayerManager = ({
|
|
|
9290
9455
|
twickCanvas,
|
|
9291
9456
|
buildCanvas,
|
|
9292
9457
|
resizeCanvas,
|
|
9458
|
+
setBackgroundColor,
|
|
9293
9459
|
setCanvasElements,
|
|
9294
9460
|
bringToFront,
|
|
9295
9461
|
sendToBack,
|
|
@@ -9366,7 +9532,7 @@ const usePlayerManager = ({
|
|
|
9366
9532
|
}
|
|
9367
9533
|
};
|
|
9368
9534
|
useEffect(() => {
|
|
9369
|
-
var _a, _b, _c, _d, _e2;
|
|
9535
|
+
var _a, _b, _c, _d, _e2, _f;
|
|
9370
9536
|
switch (timelineAction.type) {
|
|
9371
9537
|
case TIMELINE_ACTION.UPDATE_PLAYER_DATA:
|
|
9372
9538
|
if (videoProps) {
|
|
@@ -9376,11 +9542,12 @@ const usePlayerManager = ({
|
|
|
9376
9542
|
input: {
|
|
9377
9543
|
properties: videoProps,
|
|
9378
9544
|
tracks: ((_c = timelineAction.payload) == null ? void 0 : _c.tracks) ?? [],
|
|
9379
|
-
version: ((_d = timelineAction.payload) == null ? void 0 : _d.version) ?? 0
|
|
9545
|
+
version: ((_d = timelineAction.payload) == null ? void 0 : _d.version) ?? 0,
|
|
9546
|
+
backgroundColor: ((_e2 = timelineAction.payload) == null ? void 0 : _e2.backgroundColor) ?? "#000000"
|
|
9380
9547
|
}
|
|
9381
9548
|
};
|
|
9382
9549
|
setProjectData(_latestProjectData);
|
|
9383
|
-
if (((
|
|
9550
|
+
if (((_f = timelineAction.payload) == null ? void 0 : _f.version) === 1) {
|
|
9384
9551
|
setTimeout(() => {
|
|
9385
9552
|
setPlayerUpdating(false);
|
|
9386
9553
|
});
|
|
@@ -9398,6 +9565,7 @@ const usePlayerManager = ({
|
|
|
9398
9565
|
updateCanvas,
|
|
9399
9566
|
buildCanvas,
|
|
9400
9567
|
resizeCanvas,
|
|
9568
|
+
setBackgroundColor,
|
|
9401
9569
|
onPlayerUpdate,
|
|
9402
9570
|
playerUpdating,
|
|
9403
9571
|
handleDropOnCanvas,
|
|
@@ -9634,6 +9802,7 @@ const PlayerManager = ({
|
|
|
9634
9802
|
canvasMode,
|
|
9635
9803
|
canvasConfig
|
|
9636
9804
|
}) => {
|
|
9805
|
+
var _a;
|
|
9637
9806
|
const containerRef = useRef(null);
|
|
9638
9807
|
const canvasRef = useRef(null);
|
|
9639
9808
|
const durationRef = useRef(0);
|
|
@@ -9651,6 +9820,7 @@ const PlayerManager = ({
|
|
|
9651
9820
|
projectData,
|
|
9652
9821
|
updateCanvas,
|
|
9653
9822
|
resizeCanvas,
|
|
9823
|
+
setBackgroundColor,
|
|
9654
9824
|
playerUpdating,
|
|
9655
9825
|
onPlayerUpdate,
|
|
9656
9826
|
buildCanvas,
|
|
@@ -9670,6 +9840,7 @@ const PlayerManager = ({
|
|
|
9670
9840
|
enabled: !!handleDropOnCanvas && canvasMode
|
|
9671
9841
|
});
|
|
9672
9842
|
useEffect(() => {
|
|
9843
|
+
var _a2;
|
|
9673
9844
|
const container = containerRef.current;
|
|
9674
9845
|
const canvasSize = {
|
|
9675
9846
|
width: (container == null ? void 0 : container.clientWidth) ?? 0,
|
|
@@ -9677,7 +9848,7 @@ const PlayerManager = ({
|
|
|
9677
9848
|
};
|
|
9678
9849
|
if (canvasSize.width > 0 && canvasSize.height > 0) {
|
|
9679
9850
|
buildCanvas({
|
|
9680
|
-
backgroundColor: videoProps.backgroundColor,
|
|
9851
|
+
backgroundColor: videoProps.backgroundColor ?? ((_a2 = projectData == null ? void 0 : projectData.input) == null ? void 0 : _a2.backgroundColor) ?? "#000000",
|
|
9681
9852
|
videoSize: {
|
|
9682
9853
|
width: videoProps.width,
|
|
9683
9854
|
height: videoProps.height
|
|
@@ -9687,6 +9858,11 @@ const PlayerManager = ({
|
|
|
9687
9858
|
});
|
|
9688
9859
|
}
|
|
9689
9860
|
}, [videoProps]);
|
|
9861
|
+
useEffect(() => {
|
|
9862
|
+
var _a2;
|
|
9863
|
+
const color2 = ((_a2 = projectData == null ? void 0 : projectData.input) == null ? void 0 : _a2.backgroundColor) ?? videoProps.backgroundColor ?? "#000000";
|
|
9864
|
+
setBackgroundColor(color2);
|
|
9865
|
+
}, [(_a = projectData == null ? void 0 : projectData.input) == null ? void 0 : _a.backgroundColor, videoProps.backgroundColor, setBackgroundColor]);
|
|
9690
9866
|
const handleResize = useMemo(
|
|
9691
9867
|
() => throttle(() => {
|
|
9692
9868
|
const container = containerRef.current;
|
|
@@ -9718,10 +9894,10 @@ const PlayerManager = ({
|
|
|
9718
9894
|
useEffect(() => {
|
|
9719
9895
|
if (!twickCanvas || !canvasMode) return;
|
|
9720
9896
|
const onSelectionCreated = (e3) => {
|
|
9721
|
-
var
|
|
9897
|
+
var _a2, _b;
|
|
9722
9898
|
const ev = e3 == null ? void 0 : e3.e;
|
|
9723
9899
|
if (!ev) return;
|
|
9724
|
-
const id2 = (_b = (
|
|
9900
|
+
const id2 = (_b = (_a2 = e3.target) == null ? void 0 : _a2.get) == null ? void 0 : _b.call(_a2, "id");
|
|
9725
9901
|
if (id2) {
|
|
9726
9902
|
setContextMenu({ x: ev.clientX, y: ev.clientY, elementId: id2 });
|
|
9727
9903
|
}
|
|
@@ -11154,13 +11330,25 @@ function SeekTrack({
|
|
|
11154
11330
|
const containerRef = useRef(null);
|
|
11155
11331
|
const [isDragging2, setIsDragging] = useState(false);
|
|
11156
11332
|
const [dragPosition, setDragPosition] = useState(null);
|
|
11333
|
+
const [pendingSeekTime, setPendingSeekTime] = useState(null);
|
|
11157
11334
|
const pixelsPerSecond = 100 * zoom;
|
|
11158
11335
|
const totalWidth = duration * pixelsPerSecond;
|
|
11159
11336
|
const pinHeight = 2 + timelineCount * (2.75 + 0.5);
|
|
11337
|
+
React.useEffect(() => {
|
|
11338
|
+
if (pendingSeekTime === null) return;
|
|
11339
|
+
if (Math.abs(currentTime - pendingSeekTime) < 0.05) {
|
|
11340
|
+
setPendingSeekTime(null);
|
|
11341
|
+
}
|
|
11342
|
+
}, [currentTime, pendingSeekTime]);
|
|
11160
11343
|
const seekPosition = useMemo(() => {
|
|
11161
|
-
|
|
11162
|
-
|
|
11163
|
-
|
|
11344
|
+
if (isDragging2 && dragPosition !== null) {
|
|
11345
|
+
return Math.max(0, dragPosition);
|
|
11346
|
+
}
|
|
11347
|
+
if (pendingSeekTime !== null) {
|
|
11348
|
+
return Math.max(0, pendingSeekTime * pixelsPerSecond);
|
|
11349
|
+
}
|
|
11350
|
+
return Math.max(0, currentTime * pixelsPerSecond);
|
|
11351
|
+
}, [isDragging2, dragPosition, currentTime, pendingSeekTime, pixelsPerSecond]);
|
|
11164
11352
|
React.useEffect(() => {
|
|
11165
11353
|
onPlayheadUpdate == null ? void 0 : onPlayheadUpdate({
|
|
11166
11354
|
positionPx: seekPosition,
|
|
@@ -11249,6 +11437,7 @@ function SeekTrack({
|
|
|
11249
11437
|
setDragPosition(xPos);
|
|
11250
11438
|
} else {
|
|
11251
11439
|
setDragPosition(null);
|
|
11440
|
+
setPendingSeekTime(newTime);
|
|
11252
11441
|
seekToTime(newTime);
|
|
11253
11442
|
}
|
|
11254
11443
|
});
|
|
@@ -18847,8 +19036,10 @@ const TrackElementView = ({
|
|
|
18847
19036
|
onSelection,
|
|
18848
19037
|
onDrag,
|
|
18849
19038
|
allowOverlap = false,
|
|
19039
|
+
onDragStateChange,
|
|
18850
19040
|
elementColors
|
|
18851
19041
|
}) => {
|
|
19042
|
+
var _a, _b;
|
|
18852
19043
|
const ref = useRef(null);
|
|
18853
19044
|
const dragType = useRef(null);
|
|
18854
19045
|
const lastPosRef = useRef(null);
|
|
@@ -18866,7 +19057,10 @@ const TrackElementView = ({
|
|
|
18866
19057
|
const bind = useDrag(({ delta: [dx] }) => {
|
|
18867
19058
|
if (!parentWidth) return;
|
|
18868
19059
|
if (dx == 0) return;
|
|
18869
|
-
|
|
19060
|
+
if (!isDragging2) {
|
|
19061
|
+
setIsDragging(true);
|
|
19062
|
+
onDragStateChange == null ? void 0 : onDragStateChange(true, element);
|
|
19063
|
+
}
|
|
18870
19064
|
dragType.current = DRAG_TYPE.MOVE;
|
|
18871
19065
|
setPosition((prev) => {
|
|
18872
19066
|
const span = prev.end - prev.start;
|
|
@@ -18892,6 +19086,7 @@ const TrackElementView = ({
|
|
|
18892
19086
|
if (dx === 0) return;
|
|
18893
19087
|
if (isDragging2) {
|
|
18894
19088
|
setIsDragging(false);
|
|
19089
|
+
onDragStateChange == null ? void 0 : onDragStateChange(false, element);
|
|
18895
19090
|
}
|
|
18896
19091
|
dragType.current = DRAG_TYPE.START;
|
|
18897
19092
|
setPosition((prev) => {
|
|
@@ -18913,6 +19108,7 @@ const TrackElementView = ({
|
|
|
18913
19108
|
if (dx === 0) return;
|
|
18914
19109
|
if (isDragging2) {
|
|
18915
19110
|
setIsDragging(false);
|
|
19111
|
+
onDragStateChange == null ? void 0 : onDragStateChange(false, element);
|
|
18916
19112
|
}
|
|
18917
19113
|
dragType.current = DRAG_TYPE.END;
|
|
18918
19114
|
setPosition((prev) => {
|
|
@@ -18932,24 +19128,37 @@ const TrackElementView = ({
|
|
|
18932
19128
|
const setLastPos = () => {
|
|
18933
19129
|
lastPosRef.current = position;
|
|
18934
19130
|
};
|
|
18935
|
-
const sendUpdate = () => {
|
|
18936
|
-
var
|
|
19131
|
+
const sendUpdate = (e3) => {
|
|
19132
|
+
var _a2, _b2, _c;
|
|
19133
|
+
let dropPointer;
|
|
19134
|
+
if (e3) {
|
|
19135
|
+
if ("clientX" in e3) {
|
|
19136
|
+
dropPointer = { clientX: e3.clientX, clientY: e3.clientY };
|
|
19137
|
+
} else if ("changedTouches" in e3 && ((_a2 = e3.changedTouches) == null ? void 0 : _a2[0])) {
|
|
19138
|
+
const t2 = e3.changedTouches[0];
|
|
19139
|
+
dropPointer = { clientX: t2.clientX, clientY: t2.clientY };
|
|
19140
|
+
}
|
|
19141
|
+
}
|
|
18937
19142
|
setIsDragging(false);
|
|
18938
|
-
|
|
18939
|
-
|
|
18940
|
-
|
|
18941
|
-
|
|
18942
|
-
|
|
18943
|
-
|
|
18944
|
-
|
|
18945
|
-
|
|
18946
|
-
|
|
19143
|
+
onDragStateChange == null ? void 0 : onDragStateChange(false, element);
|
|
19144
|
+
const payload = {
|
|
19145
|
+
element,
|
|
19146
|
+
updates: {
|
|
19147
|
+
start: getDecimalNumber(position.start),
|
|
19148
|
+
end: getDecimalNumber(position.end)
|
|
19149
|
+
},
|
|
19150
|
+
dragType: dragType.current || ""
|
|
19151
|
+
};
|
|
19152
|
+
const didChange = ((_b2 = lastPosRef.current) == null ? void 0 : _b2.start) !== position.start || ((_c = lastPosRef.current) == null ? void 0 : _c.end) !== position.end;
|
|
19153
|
+
if (didChange || dropPointer) {
|
|
19154
|
+
onDrag(payload, dropPointer);
|
|
18947
19155
|
}
|
|
18948
19156
|
};
|
|
18949
19157
|
const getElementColor = (elementType) => {
|
|
18950
19158
|
const colors = elementColors || ELEMENT_COLORS;
|
|
18951
|
-
|
|
18952
|
-
|
|
19159
|
+
const key = elementType === TIMELINE_ELEMENT_TYPE.VIDEO ? "video" : elementType === TIMELINE_ELEMENT_TYPE.AUDIO ? "audio" : elementType === TIMELINE_ELEMENT_TYPE.IMAGE ? "image" : elementType === TIMELINE_ELEMENT_TYPE.TEXT ? "text" : elementType === TIMELINE_ELEMENT_TYPE.CAPTION ? "caption" : elementType === TIMELINE_ELEMENT_TYPE.RECT ? "rect" : elementType === TIMELINE_ELEMENT_TYPE.CIRCLE ? "circle" : elementType === TIMELINE_ELEMENT_TYPE.ICON ? "icon" : elementType === TIMELINE_ELEMENT_TYPE.EFFECT ? "effect" : "element";
|
|
19160
|
+
if (key in colors) {
|
|
19161
|
+
return colors[key];
|
|
18953
19162
|
}
|
|
18954
19163
|
return ELEMENT_COLORS.element;
|
|
18955
19164
|
};
|
|
@@ -18970,8 +19179,8 @@ const TrackElementView = ({
|
|
|
18970
19179
|
setLastPos();
|
|
18971
19180
|
}
|
|
18972
19181
|
},
|
|
18973
|
-
onMouseUp: sendUpdate,
|
|
18974
|
-
onTouchEnd: sendUpdate,
|
|
19182
|
+
onMouseUp: (e3) => sendUpdate(e3),
|
|
19183
|
+
onTouchEnd: (e3) => sendUpdate(e3),
|
|
18975
19184
|
onClick: (e3) => {
|
|
18976
19185
|
if (onSelection) {
|
|
18977
19186
|
onSelection(element, e3);
|
|
@@ -18993,7 +19202,7 @@ const TrackElementView = ({
|
|
|
18993
19202
|
className: "twick-track-element-handle twick-track-element-handle-start"
|
|
18994
19203
|
}
|
|
18995
19204
|
) : null,
|
|
18996
|
-
/* @__PURE__ */ jsx("div", { className: "twick-track-element-content", children: element.getText ? element.getText() : element.getName() || element.getType() }),
|
|
19205
|
+
/* @__PURE__ */ jsx("div", { className: "twick-track-element-content", children: element.getType() === TIMELINE_ELEMENT_TYPE.EFFECT ? ((_b = (_a = element.getProps) == null ? void 0 : _a.call(element)) == null ? void 0 : _b.effectKey) ?? "Effect" : element.getText ? element.getText() : element.getName() || element.getType() }),
|
|
18997
19206
|
hasHandles ? /* @__PURE__ */ jsx(
|
|
18998
19207
|
"div",
|
|
18999
19208
|
{
|
|
@@ -19028,6 +19237,7 @@ const TrackBase = ({
|
|
|
19028
19237
|
onItemSelection,
|
|
19029
19238
|
onDrag,
|
|
19030
19239
|
allowOverlap = false,
|
|
19240
|
+
onDragStateChange,
|
|
19031
19241
|
elementColors
|
|
19032
19242
|
}) => {
|
|
19033
19243
|
const trackRef = useRef(null);
|
|
@@ -19052,6 +19262,7 @@ const TrackBase = ({
|
|
|
19052
19262
|
selectedIds,
|
|
19053
19263
|
onSelection: onItemSelection,
|
|
19054
19264
|
onDrag,
|
|
19265
|
+
onDragStateChange,
|
|
19055
19266
|
elementColors,
|
|
19056
19267
|
nextStart: index < elements.length - 1 ? elements[index + 1].getStart() : null,
|
|
19057
19268
|
prevEnd: index > 0 ? elements[index - 1].getEnd() : 0
|
|
@@ -19226,6 +19437,67 @@ function useMarqueeSelection({
|
|
|
19226
19437
|
);
|
|
19227
19438
|
return { marquee, handleMouseDown };
|
|
19228
19439
|
}
|
|
19440
|
+
function useEdgeAutoScroll({
|
|
19441
|
+
isActive,
|
|
19442
|
+
getMouseClientX,
|
|
19443
|
+
scrollContainerRef,
|
|
19444
|
+
contentWidth,
|
|
19445
|
+
edgeThreshold = 60,
|
|
19446
|
+
maxScrollSpeed = 20
|
|
19447
|
+
}) {
|
|
19448
|
+
const rafRef = useRef(null);
|
|
19449
|
+
useEffect(() => {
|
|
19450
|
+
if (!isActive) {
|
|
19451
|
+
if (rafRef.current) {
|
|
19452
|
+
cancelAnimationFrame(rafRef.current);
|
|
19453
|
+
rafRef.current = null;
|
|
19454
|
+
}
|
|
19455
|
+
return;
|
|
19456
|
+
}
|
|
19457
|
+
const step = () => {
|
|
19458
|
+
const el = scrollContainerRef.current;
|
|
19459
|
+
if (!el) {
|
|
19460
|
+
rafRef.current = requestAnimationFrame(step);
|
|
19461
|
+
return;
|
|
19462
|
+
}
|
|
19463
|
+
const rect = el.getBoundingClientRect();
|
|
19464
|
+
const mouseX = getMouseClientX();
|
|
19465
|
+
const xRelative = mouseX - rect.left;
|
|
19466
|
+
const viewportWidth = el.clientWidth;
|
|
19467
|
+
const scrollMax = Math.max(0, contentWidth - viewportWidth);
|
|
19468
|
+
let scrollSpeed = 0;
|
|
19469
|
+
if (xRelative < edgeThreshold && el.scrollLeft > 0) {
|
|
19470
|
+
const intensity = 1 - Math.max(0, xRelative) / edgeThreshold;
|
|
19471
|
+
scrollSpeed = -maxScrollSpeed * intensity;
|
|
19472
|
+
} else if (xRelative > viewportWidth - edgeThreshold && el.scrollLeft < scrollMax) {
|
|
19473
|
+
const intensity = 1 - Math.max(0, viewportWidth - edgeThreshold - xRelative) / edgeThreshold;
|
|
19474
|
+
scrollSpeed = maxScrollSpeed * intensity;
|
|
19475
|
+
}
|
|
19476
|
+
if (scrollSpeed !== 0) {
|
|
19477
|
+
const newScrollLeft = Math.max(
|
|
19478
|
+
0,
|
|
19479
|
+
Math.min(scrollMax, el.scrollLeft + scrollSpeed)
|
|
19480
|
+
);
|
|
19481
|
+
el.scrollLeft = newScrollLeft;
|
|
19482
|
+
}
|
|
19483
|
+
rafRef.current = requestAnimationFrame(step);
|
|
19484
|
+
};
|
|
19485
|
+
rafRef.current = requestAnimationFrame(step);
|
|
19486
|
+
return () => {
|
|
19487
|
+
if (rafRef.current) {
|
|
19488
|
+
cancelAnimationFrame(rafRef.current);
|
|
19489
|
+
rafRef.current = null;
|
|
19490
|
+
}
|
|
19491
|
+
};
|
|
19492
|
+
}, [
|
|
19493
|
+
isActive,
|
|
19494
|
+
getMouseClientX,
|
|
19495
|
+
scrollContainerRef,
|
|
19496
|
+
contentWidth,
|
|
19497
|
+
edgeThreshold,
|
|
19498
|
+
maxScrollSpeed
|
|
19499
|
+
]);
|
|
19500
|
+
}
|
|
19229
19501
|
function MarqueeOverlay({ marquee }) {
|
|
19230
19502
|
return /* @__PURE__ */ jsx(
|
|
19231
19503
|
"div",
|
|
@@ -19256,8 +19528,25 @@ function MarqueeOverlay({ marquee }) {
|
|
|
19256
19528
|
}
|
|
19257
19529
|
);
|
|
19258
19530
|
}
|
|
19531
|
+
const SEPARATOR_HEIGHT$1 = 6;
|
|
19532
|
+
function getTrackOrSeparatorAt(clientY, containerTop, trackHeight) {
|
|
19533
|
+
const y2 = clientY - containerTop;
|
|
19534
|
+
if (y2 < 0) return null;
|
|
19535
|
+
const rowHeight = trackHeight + SEPARATOR_HEIGHT$1;
|
|
19536
|
+
if (y2 < SEPARATOR_HEIGHT$1) {
|
|
19537
|
+
return { type: "separator", separatorIndex: 0 };
|
|
19538
|
+
}
|
|
19539
|
+
const relativeY = y2 - SEPARATOR_HEIGHT$1;
|
|
19540
|
+
const index = Math.floor(relativeY / rowHeight);
|
|
19541
|
+
const remainder = relativeY % rowHeight;
|
|
19542
|
+
if (remainder < trackHeight) {
|
|
19543
|
+
return { type: "track", trackIndex: index };
|
|
19544
|
+
}
|
|
19545
|
+
return { type: "separator", separatorIndex: index + 1 };
|
|
19546
|
+
}
|
|
19259
19547
|
const LABEL_WIDTH = 40;
|
|
19260
19548
|
const TRACK_HEIGHT = 44;
|
|
19549
|
+
const SEPARATOR_HEIGHT = 6;
|
|
19261
19550
|
function TimelineView({
|
|
19262
19551
|
zoomLevel,
|
|
19263
19552
|
selectedItem,
|
|
@@ -19270,25 +19559,81 @@ function TimelineView({
|
|
|
19270
19559
|
onEmptyClick,
|
|
19271
19560
|
onMarqueeSelect,
|
|
19272
19561
|
onElementDrag,
|
|
19562
|
+
onElementDrop,
|
|
19563
|
+
onSeek,
|
|
19273
19564
|
elementColors,
|
|
19274
19565
|
selectedIds,
|
|
19275
19566
|
playheadPositionPx = 0,
|
|
19276
19567
|
isPlayheadActive = false,
|
|
19277
19568
|
onDropOnTimeline,
|
|
19278
19569
|
videoResolution,
|
|
19279
|
-
enableDropOnTimeline = true
|
|
19570
|
+
enableDropOnTimeline = true,
|
|
19571
|
+
chapters = []
|
|
19280
19572
|
}) {
|
|
19281
19573
|
const containerRef = useRef(null);
|
|
19282
19574
|
const seekContainerRef = useRef(null);
|
|
19283
19575
|
const timelineContentRef = useRef(null);
|
|
19284
19576
|
const [, setScrollLeft] = useState(0);
|
|
19577
|
+
const pointerRef = useRef(null);
|
|
19285
19578
|
const [draggedTimeline, setDraggedTimeline] = useState(null);
|
|
19579
|
+
const [draggingElementId, setDraggingElementId] = useState(null);
|
|
19580
|
+
const [activeDropTarget, setActiveDropTarget] = useState(null);
|
|
19286
19581
|
const { selectedTrackElement } = useMemo(() => {
|
|
19287
19582
|
if (selectedItem && "elements" in selectedItem) {
|
|
19288
19583
|
return { selectedTrackElement: null };
|
|
19289
19584
|
}
|
|
19290
19585
|
return { selectedTrackElement: selectedItem };
|
|
19291
19586
|
}, [selectedItem]);
|
|
19587
|
+
const handleDragWithDrop = useCallback(
|
|
19588
|
+
(payload, dropPointer) => {
|
|
19589
|
+
var _a;
|
|
19590
|
+
if (dropPointer && onElementDrop) {
|
|
19591
|
+
const rect = (_a = timelineContentRef.current) == null ? void 0 : _a.getBoundingClientRect();
|
|
19592
|
+
const dropTarget = rect ? getTrackOrSeparatorAt(dropPointer.clientY, rect.top, TRACK_HEIGHT) : null;
|
|
19593
|
+
onElementDrop({ ...payload, dropTarget });
|
|
19594
|
+
} else {
|
|
19595
|
+
onElementDrag(payload);
|
|
19596
|
+
}
|
|
19597
|
+
},
|
|
19598
|
+
[onElementDrag, onElementDrop]
|
|
19599
|
+
);
|
|
19600
|
+
useEdgeAutoScroll({
|
|
19601
|
+
isActive: !!draggingElementId,
|
|
19602
|
+
getMouseClientX: () => {
|
|
19603
|
+
var _a;
|
|
19604
|
+
return ((_a = pointerRef.current) == null ? void 0 : _a.clientX) ?? 0;
|
|
19605
|
+
},
|
|
19606
|
+
scrollContainerRef: containerRef,
|
|
19607
|
+
contentWidth: Math.max(100, duration * zoomLevel * 100)
|
|
19608
|
+
});
|
|
19609
|
+
useEffect(() => {
|
|
19610
|
+
if (!draggingElementId) return;
|
|
19611
|
+
const onMove = (e3) => {
|
|
19612
|
+
var _a;
|
|
19613
|
+
const pt2 = "touches" in e3 ? e3.touches[0] : e3;
|
|
19614
|
+
if (pt2) {
|
|
19615
|
+
pointerRef.current = { clientX: pt2.clientX, clientY: pt2.clientY };
|
|
19616
|
+
const rect = (_a = timelineContentRef.current) == null ? void 0 : _a.getBoundingClientRect();
|
|
19617
|
+
if (rect) {
|
|
19618
|
+
setActiveDropTarget(getTrackOrSeparatorAt(pt2.clientY, rect.top, TRACK_HEIGHT));
|
|
19619
|
+
}
|
|
19620
|
+
}
|
|
19621
|
+
};
|
|
19622
|
+
const onUp = () => {
|
|
19623
|
+
pointerRef.current = null;
|
|
19624
|
+
setActiveDropTarget(null);
|
|
19625
|
+
};
|
|
19626
|
+
document.addEventListener("mousemove", onMove);
|
|
19627
|
+
document.addEventListener("touchmove", onMove, { passive: true });
|
|
19628
|
+
document.addEventListener("mouseup", onUp);
|
|
19629
|
+
document.addEventListener("touchend", onUp);
|
|
19630
|
+
return () => {
|
|
19631
|
+
document.removeEventListener("mousemove", onMove);
|
|
19632
|
+
document.removeEventListener("touchmove", onMove);
|
|
19633
|
+
document.removeEventListener("mouseup", onUp);
|
|
19634
|
+
document.removeEventListener("touchend", onUp);
|
|
19635
|
+
};
|
|
19636
|
+
}, [draggingElementId]);
|
|
19292
19637
|
const timelineWidth = Math.max(100, duration * zoomLevel * 100);
|
|
19293
19638
|
const timelineWidthPx = `${timelineWidth}px`;
|
|
19294
19639
|
const handleScroll = (e3) => {
|
|
@@ -19385,9 +19730,36 @@ function TimelineView({
|
|
|
19385
19730
|
className: "twick-timeline-scroll-container",
|
|
19386
19731
|
onScroll: handleScroll,
|
|
19387
19732
|
children: [
|
|
19388
|
-
/* @__PURE__ */ jsx("div", { style: { width: timelineWidthPx }, children: seekTrack ? /* @__PURE__ */ jsxs("div", { style: { display: "flex", position: "relative" }, children: [
|
|
19733
|
+
/* @__PURE__ */ jsx("div", { style: { width: timelineWidthPx }, children: seekTrack ? /* @__PURE__ */ jsxs("div", { style: { display: "flex", position: "relative", minHeight: 34 }, children: [
|
|
19389
19734
|
/* @__PURE__ */ jsx("div", { className: "twick-seek-track-empty-space", onClick: onAddTrack, children: /* @__PURE__ */ jsx(Plus, { color: "white", size: 20 }) }),
|
|
19390
|
-
/* @__PURE__ */ jsx("div", { style: { flexGrow: 1 }, children: seekTrack })
|
|
19735
|
+
/* @__PURE__ */ jsx("div", { style: { flexGrow: 1 }, children: seekTrack }),
|
|
19736
|
+
chapters.map((chapter) => {
|
|
19737
|
+
const left = LABEL_WIDTH + chapter.time / Math.max(duration, 1e-3) * (timelineWidth - LABEL_WIDTH);
|
|
19738
|
+
return /* @__PURE__ */ jsx(
|
|
19739
|
+
"button",
|
|
19740
|
+
{
|
|
19741
|
+
className: "btn-ghost",
|
|
19742
|
+
title: chapter.title,
|
|
19743
|
+
onClick: (e3) => {
|
|
19744
|
+
e3.stopPropagation();
|
|
19745
|
+
onSeek(chapter.time);
|
|
19746
|
+
},
|
|
19747
|
+
style: {
|
|
19748
|
+
position: "absolute",
|
|
19749
|
+
left,
|
|
19750
|
+
top: 0,
|
|
19751
|
+
height: "100%",
|
|
19752
|
+
padding: "0 4px",
|
|
19753
|
+
borderRadius: 0,
|
|
19754
|
+
borderLeft: "1px solid rgba(255,255,255,0.4)",
|
|
19755
|
+
borderRight: "none",
|
|
19756
|
+
minWidth: 0
|
|
19757
|
+
},
|
|
19758
|
+
children: /* @__PURE__ */ jsx("span", { style: { fontSize: 10, opacity: 0.9 }, children: chapter.title })
|
|
19759
|
+
},
|
|
19760
|
+
chapter.id
|
|
19761
|
+
);
|
|
19762
|
+
})
|
|
19391
19763
|
] }) : null }),
|
|
19392
19764
|
/* @__PURE__ */ jsxs(
|
|
19393
19765
|
"div",
|
|
@@ -19413,34 +19785,61 @@ function TimelineView({
|
|
|
19413
19785
|
}
|
|
19414
19786
|
}
|
|
19415
19787
|
),
|
|
19416
|
-
/* @__PURE__ */
|
|
19417
|
-
/* @__PURE__ */ jsx("div", { className: "twick-timeline-header-container", children: /* @__PURE__ */ jsx(
|
|
19418
|
-
TrackHeader,
|
|
19419
|
-
{
|
|
19420
|
-
track,
|
|
19421
|
-
selectedIds,
|
|
19422
|
-
onSelect: handleItemSelection,
|
|
19423
|
-
onDragStart: handleTrackDragStart,
|
|
19424
|
-
onDragOver: handleTrackDragOver,
|
|
19425
|
-
onDrop: handleTrackDrop
|
|
19426
|
-
}
|
|
19427
|
-
) }),
|
|
19788
|
+
/* @__PURE__ */ jsxs("div", { style: { position: "relative", zIndex: 10 }, children: [
|
|
19428
19789
|
/* @__PURE__ */ jsx(
|
|
19429
|
-
|
|
19790
|
+
"div",
|
|
19430
19791
|
{
|
|
19431
|
-
|
|
19432
|
-
|
|
19433
|
-
|
|
19434
|
-
|
|
19435
|
-
|
|
19436
|
-
allowOverlap: false,
|
|
19437
|
-
trackWidth: timelineWidth - LABEL_WIDTH,
|
|
19438
|
-
onItemSelection: handleItemSelection,
|
|
19439
|
-
onDrag: onElementDrag,
|
|
19440
|
-
elementColors
|
|
19792
|
+
className: "twick-timeline-separator",
|
|
19793
|
+
style: {
|
|
19794
|
+
height: SEPARATOR_HEIGHT,
|
|
19795
|
+
background: (activeDropTarget == null ? void 0 : activeDropTarget.type) === "separator" && activeDropTarget.separatorIndex === 0 ? "rgba(255,255,255,0.2)" : "transparent"
|
|
19796
|
+
}
|
|
19441
19797
|
}
|
|
19442
|
-
)
|
|
19443
|
-
|
|
19798
|
+
),
|
|
19799
|
+
(tracks || []).map((track, index) => /* @__PURE__ */ jsxs("div", { children: [
|
|
19800
|
+
/* @__PURE__ */ jsxs("div", { className: "twick-timeline-container", children: [
|
|
19801
|
+
/* @__PURE__ */ jsx("div", { className: "twick-timeline-header-container", children: /* @__PURE__ */ jsx(
|
|
19802
|
+
TrackHeader,
|
|
19803
|
+
{
|
|
19804
|
+
track,
|
|
19805
|
+
selectedIds,
|
|
19806
|
+
onSelect: handleItemSelection,
|
|
19807
|
+
onDragStart: handleTrackDragStart,
|
|
19808
|
+
onDragOver: handleTrackDragOver,
|
|
19809
|
+
onDrop: handleTrackDrop
|
|
19810
|
+
}
|
|
19811
|
+
) }),
|
|
19812
|
+
/* @__PURE__ */ jsx(
|
|
19813
|
+
TrackBase,
|
|
19814
|
+
{
|
|
19815
|
+
track,
|
|
19816
|
+
duration,
|
|
19817
|
+
selectedItem: selectedTrackElement,
|
|
19818
|
+
selectedIds,
|
|
19819
|
+
zoom: zoomLevel,
|
|
19820
|
+
allowOverlap: false,
|
|
19821
|
+
trackWidth: timelineWidth - LABEL_WIDTH,
|
|
19822
|
+
onItemSelection: handleItemSelection,
|
|
19823
|
+
onDrag: handleDragWithDrop,
|
|
19824
|
+
onDragStateChange: (isDragging2, el) => {
|
|
19825
|
+
setDraggingElementId(isDragging2 && el ? el.getId() : null);
|
|
19826
|
+
},
|
|
19827
|
+
elementColors
|
|
19828
|
+
}
|
|
19829
|
+
)
|
|
19830
|
+
] }),
|
|
19831
|
+
/* @__PURE__ */ jsx(
|
|
19832
|
+
"div",
|
|
19833
|
+
{
|
|
19834
|
+
className: "twick-timeline-separator",
|
|
19835
|
+
style: {
|
|
19836
|
+
height: SEPARATOR_HEIGHT,
|
|
19837
|
+
background: (activeDropTarget == null ? void 0 : activeDropTarget.type) === "separator" && activeDropTarget.separatorIndex === index + 1 ? "rgba(255,255,255,0.2)" : "transparent"
|
|
19838
|
+
}
|
|
19839
|
+
}
|
|
19840
|
+
)
|
|
19841
|
+
] }, track.getId()))
|
|
19842
|
+
] })
|
|
19444
19843
|
]
|
|
19445
19844
|
}
|
|
19446
19845
|
)
|
|
@@ -19497,6 +19896,75 @@ const useTimelineManager = () => {
|
|
|
19497
19896
|
setSelectedItem(updatedElement);
|
|
19498
19897
|
editor.refresh();
|
|
19499
19898
|
};
|
|
19899
|
+
const isElementTrackType = (track) => track.getType() === TRACK_TYPES.ELEMENT;
|
|
19900
|
+
const wouldBeElementTrack = (el) => {
|
|
19901
|
+
const elType = el.getType().toLowerCase();
|
|
19902
|
+
return elType !== "video" && elType !== "image" && elType !== "audio";
|
|
19903
|
+
};
|
|
19904
|
+
const onElementDrop = async (params) => {
|
|
19905
|
+
var _a;
|
|
19906
|
+
const { element, dragType, updates, dropTarget } = params;
|
|
19907
|
+
const tracks = ((_a = editor.getTimelineData()) == null ? void 0 : _a.tracks) ?? [];
|
|
19908
|
+
if (!dropTarget) {
|
|
19909
|
+
return;
|
|
19910
|
+
}
|
|
19911
|
+
if (dropTarget.type === "separator") {
|
|
19912
|
+
if (!wouldBeElementTrack(element)) {
|
|
19913
|
+
return;
|
|
19914
|
+
}
|
|
19915
|
+
await editor.moveElementToNewTrackAt(
|
|
19916
|
+
element,
|
|
19917
|
+
dropTarget.separatorIndex,
|
|
19918
|
+
updates.start
|
|
19919
|
+
);
|
|
19920
|
+
setSelectedItem(element);
|
|
19921
|
+
editor.refresh();
|
|
19922
|
+
return;
|
|
19923
|
+
}
|
|
19924
|
+
const targetTrack = tracks[dropTarget.trackIndex];
|
|
19925
|
+
if (!targetTrack) {
|
|
19926
|
+
return;
|
|
19927
|
+
}
|
|
19928
|
+
if (!isElementTrackType(targetTrack)) {
|
|
19929
|
+
return;
|
|
19930
|
+
}
|
|
19931
|
+
const start = updates.start;
|
|
19932
|
+
const end = updates.end;
|
|
19933
|
+
const elementId = element.getId();
|
|
19934
|
+
const currentTrackId = element.getTrackId();
|
|
19935
|
+
let hasOverlap = false;
|
|
19936
|
+
const others = targetTrack.getElements().filter((el) => el.getId() !== elementId);
|
|
19937
|
+
for (const other of others) {
|
|
19938
|
+
const oStart = other.getStart();
|
|
19939
|
+
const oEnd = other.getEnd();
|
|
19940
|
+
if (start < oEnd && end > oStart) {
|
|
19941
|
+
hasOverlap = true;
|
|
19942
|
+
break;
|
|
19943
|
+
}
|
|
19944
|
+
}
|
|
19945
|
+
if (hasOverlap) {
|
|
19946
|
+
await editor.moveElementToNewTrackAt(
|
|
19947
|
+
element,
|
|
19948
|
+
dropTarget.trackIndex + 1,
|
|
19949
|
+
updates.start
|
|
19950
|
+
);
|
|
19951
|
+
setSelectedItem(element);
|
|
19952
|
+
editor.refresh();
|
|
19953
|
+
return;
|
|
19954
|
+
}
|
|
19955
|
+
if (currentTrackId === targetTrack.getId()) {
|
|
19956
|
+
onElementDrag({ element, dragType, updates });
|
|
19957
|
+
return;
|
|
19958
|
+
}
|
|
19959
|
+
editor.removeElement(element);
|
|
19960
|
+
element.setStart(updates.start);
|
|
19961
|
+
element.setEnd(updates.end);
|
|
19962
|
+
const added = await editor.addElementToTrack(targetTrack, element);
|
|
19963
|
+
if (added) {
|
|
19964
|
+
setSelectedItem(element);
|
|
19965
|
+
editor.refresh();
|
|
19966
|
+
}
|
|
19967
|
+
};
|
|
19500
19968
|
const timelineData = useMemo(() => editor.getTimelineData(), [changeLog]);
|
|
19501
19969
|
const { setSeekTime, setCurrentTime } = useLivePlayerContext();
|
|
19502
19970
|
const onReorder = (reorderedItems) => {
|
|
@@ -19519,6 +19987,7 @@ const useTimelineManager = () => {
|
|
|
19519
19987
|
timelineData,
|
|
19520
19988
|
onAddTrack,
|
|
19521
19989
|
onElementDrag,
|
|
19990
|
+
onElementDrop,
|
|
19522
19991
|
onReorder,
|
|
19523
19992
|
onSeek,
|
|
19524
19993
|
onSelectionChange,
|
|
@@ -19605,7 +20074,7 @@ const TimelineManager = ({
|
|
|
19605
20074
|
timelineTickConfigs,
|
|
19606
20075
|
elementColors
|
|
19607
20076
|
}) => {
|
|
19608
|
-
var _a;
|
|
20077
|
+
var _a, _b;
|
|
19609
20078
|
const { playerState } = useLivePlayerContext();
|
|
19610
20079
|
const { followPlayheadEnabled, editor, videoResolution, setSelectedItem } = useTimelineContext();
|
|
19611
20080
|
const {
|
|
@@ -19615,6 +20084,7 @@ const TimelineManager = ({
|
|
|
19615
20084
|
onAddTrack,
|
|
19616
20085
|
onReorder,
|
|
19617
20086
|
onElementDrag,
|
|
20087
|
+
onElementDrop,
|
|
19618
20088
|
onSeek
|
|
19619
20089
|
} = useTimelineManager();
|
|
19620
20090
|
const { selectedIds } = useTimelineContext();
|
|
@@ -19668,6 +20138,7 @@ const TimelineManager = ({
|
|
|
19668
20138
|
onAddTrack,
|
|
19669
20139
|
onReorder,
|
|
19670
20140
|
onElementDrag,
|
|
20141
|
+
onElementDrop,
|
|
19671
20142
|
onSeek,
|
|
19672
20143
|
onItemSelect: handleItemSelect,
|
|
19673
20144
|
onEmptyClick: handleEmptyClick,
|
|
@@ -19675,6 +20146,7 @@ const TimelineManager = ({
|
|
|
19675
20146
|
elementColors,
|
|
19676
20147
|
playheadPositionPx: playheadState.positionPx,
|
|
19677
20148
|
isPlayheadActive,
|
|
20149
|
+
chapters: ((_a = timelineData == null ? void 0 : timelineData.metadata) == null ? void 0 : _a.chapters) ?? [],
|
|
19678
20150
|
onDropOnTimeline: handleDropOnTimeline,
|
|
19679
20151
|
videoResolution,
|
|
19680
20152
|
enableDropOnTimeline: true,
|
|
@@ -19684,7 +20156,7 @@ const TimelineManager = ({
|
|
|
19684
20156
|
duration: totalDuration,
|
|
19685
20157
|
zoom: trackZoom,
|
|
19686
20158
|
onSeek,
|
|
19687
|
-
timelineCount: ((
|
|
20159
|
+
timelineCount: ((_b = timelineData == null ? void 0 : timelineData.tracks) == null ? void 0 : _b.length) ?? 0,
|
|
19688
20160
|
timelineTickConfigs,
|
|
19689
20161
|
onPlayheadUpdate: handlePlayheadUpdate
|
|
19690
20162
|
}
|