@twick/video-editor 0.15.27 → 0.15.28
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 +6 -1
- package/dist/components/track/track-base.d.ts +5 -1
- package/dist/components/track/track-element-context-menu.d.ts +16 -0
- package/dist/components/track/track-element.d.ts +6 -0
- package/dist/helpers/types.d.ts +1 -0
- package/dist/index.js +649 -108
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +650 -109
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -7,6 +7,7 @@ const jsxRuntime = require("react/jsx-runtime");
|
|
|
7
7
|
const livePlayer = require("@twick/live-player");
|
|
8
8
|
const timeline = require("@twick/timeline");
|
|
9
9
|
const React = require("react");
|
|
10
|
+
const reactDom = require("react-dom");
|
|
10
11
|
function t(t2, e3, s2) {
|
|
11
12
|
return (e3 = function(t3) {
|
|
12
13
|
var e4 = function(t4, e5) {
|
|
@@ -5945,6 +5946,9 @@ function ea() {
|
|
|
5945
5946
|
function sa() {
|
|
5946
5947
|
return !ta && (!(arguments.length > 0 && void 0 !== arguments[0]) || arguments[0]) && (ta = ea()), ta;
|
|
5947
5948
|
}
|
|
5949
|
+
function ia(t2) {
|
|
5950
|
+
ta = t2;
|
|
5951
|
+
}
|
|
5948
5952
|
const ra = ["filters", "resizeFilter", "src", "crossOrigin", "type"], na = ["cropX", "cropY"];
|
|
5949
5953
|
class oa extends Li {
|
|
5950
5954
|
static getDefaults() {
|
|
@@ -6472,13 +6476,7 @@ function Za(e3, s2) {
|
|
|
6472
6476
|
return tt.setClass(r2, e3), r2;
|
|
6473
6477
|
}
|
|
6474
6478
|
t(Qa, "type", "ColorMatrix"), t(Qa, "defaults", Ja), t(Qa, "uniformLocations", ["uColorMatrix", "uConstants"]), tt.setClass(Qa);
|
|
6475
|
-
Za("Brownie", [0.5997, 0.34553, -0.27082, 0, 0.186, -0.0377, 0.86095, 0.15059, 0, -0.1449, 0.24113, -0.07441, 0.44972, 0, -0.02965, 0, 0, 0, 1, 0]);
|
|
6476
|
-
Za("Vintage", [0.62793, 0.32021, -0.03965, 0, 0.03784, 0.02578, 0.64411, 0.03259, 0, 0.02926, 0.0466, -0.08512, 0.52416, 0, 0.02023, 0, 0, 0, 1, 0]);
|
|
6477
|
-
Za("Kodachrome", [1.12855, -0.39673, -0.03992, 0, 0.24991, -0.16404, 1.08352, -0.05498, 0, 0.09698, -0.16786, -0.56034, 1.60148, 0, 0.13972, 0, 0, 0, 1, 0]);
|
|
6478
|
-
Za("Technicolor", [1.91252, -0.85453, -0.09155, 0, 0.04624, -0.30878, 1.76589, -0.10601, 0, -0.27589, -0.2311, -0.75018, 1.84759, 0, 0.12137, 0, 0, 0, 1, 0]);
|
|
6479
|
-
Za("Polaroid", [1.438, -0.062, -0.062, 0, 0, -0.122, 1.378, -0.122, 0, 0, -0.016, -0.016, 1.483, 0, 0, 0, 0, 0, 1, 0]);
|
|
6480
|
-
Za("Sepia", [0.393, 0.769, 0.189, 0, 0, 0.349, 0.686, 0.168, 0, 0, 0.272, 0.534, 0.131, 0, 0, 0, 0, 0, 1, 0]);
|
|
6481
|
-
Za("BlackWhite", [1.5, 1.5, 1.5, 0, -1, 1.5, 1.5, 1.5, 0, -1, 1.5, 1.5, 1.5, 0, -1, 0, 0, 0, 1, 0]);
|
|
6479
|
+
const $a = Za("Brownie", [0.5997, 0.34553, -0.27082, 0, 0.186, -0.0377, 0.86095, 0.15059, 0, -0.1449, 0.24113, -0.07441, 0.44972, 0, -0.02965, 0, 0, 0, 1, 0]), th = Za("Vintage", [0.62793, 0.32021, -0.03965, 0, 0.03784, 0.02578, 0.64411, 0.03259, 0, 0.02926, 0.0466, -0.08512, 0.52416, 0, 0.02023, 0, 0, 0, 1, 0]), eh = Za("Kodachrome", [1.12855, -0.39673, -0.03992, 0, 0.24991, -0.16404, 1.08352, -0.05498, 0, 0.09698, -0.16786, -0.56034, 1.60148, 0, 0.13972, 0, 0, 0, 1, 0]), sh = Za("Technicolor", [1.91252, -0.85453, -0.09155, 0, 0.04624, -0.30878, 1.76589, -0.10601, 0, -0.27589, -0.2311, -0.75018, 1.84759, 0, 0.12137, 0, 0, 0, 1, 0]), ih = Za("Polaroid", [1.438, -0.062, -0.062, 0, 0, -0.122, 1.378, -0.122, 0, 0, -0.016, -0.016, 1.483, 0, 0, 0, 0, 0, 1, 0]), rh = Za("Sepia", [0.393, 0.769, 0.189, 0, 0, 0.349, 0.686, 0.168, 0, 0, 0.272, 0.534, 0.131, 0, 0, 0, 0, 0, 1, 0]), nh = Za("BlackWhite", [1.5, 1.5, 1.5, 0, -1, 1.5, 1.5, 1.5, 0, -1, 1.5, 1.5, 1.5, 0, -1, 0, 0, 0, 1, 0]);
|
|
6482
6480
|
class oh extends Va {
|
|
6483
6481
|
constructor() {
|
|
6484
6482
|
let t2 = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {};
|
|
@@ -6841,6 +6839,7 @@ class bh extends Va {
|
|
|
6841
6839
|
}
|
|
6842
6840
|
}
|
|
6843
6841
|
t(bh, "type", "Vibrance"), t(bh, "defaults", { vibrance: 0 }), t(bh, "uniformLocations", ["uVibrance"]), tt.setClass(bh);
|
|
6842
|
+
var Sh = Object.freeze({ __proto__: null, BaseFilter: Va, BlackWhite: nh, BlendColor: Ga, BlendImage: Ua, Blur: qa, Brightness: Ka, Brownie: $a, ColorMatrix: Qa, Composed: oh, Contrast: ah, Convolute: ch, Gamma: uh, Grayscale: gh, HueRotation: ph, Invert: mh, Kodachrome: eh, Noise: vh$1, Pixelate: yh, Polaroid: ih, RemoveColor: _h, Resize: xh, Saturation: Ch, Sepia: rh, Technicolor: sh, Vibrance: bh, Vintage: th });
|
|
6844
6843
|
var __defProp2 = Object.defineProperty;
|
|
6845
6844
|
var __defNormalProp2 = (obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
6846
6845
|
var __publicField2 = (obj, key, value) => __defNormalProp2(obj, key + "", value);
|
|
@@ -6901,6 +6900,8 @@ const ELEMENT_TYPES = {
|
|
|
6901
6900
|
RECT: "rect",
|
|
6902
6901
|
/** Circle element type */
|
|
6903
6902
|
CIRCLE: "circle",
|
|
6903
|
+
/** Emoji sticker element type */
|
|
6904
|
+
EMOJI: "emoji",
|
|
6904
6905
|
/** Arrow annotation element type */
|
|
6905
6906
|
ARROW: "arrow",
|
|
6906
6907
|
/** Line annotation / shape element type */
|
|
@@ -7149,6 +7150,24 @@ const rotateControl = new ai({
|
|
|
7149
7150
|
/** Whether to show connection line */
|
|
7150
7151
|
withConnection: true
|
|
7151
7152
|
});
|
|
7153
|
+
const COLOR_FILTERS = {
|
|
7154
|
+
SATURATED: "saturated",
|
|
7155
|
+
BRIGHT: "bright",
|
|
7156
|
+
VIBRANT: "vibrant",
|
|
7157
|
+
RETRO: "retro",
|
|
7158
|
+
BLACK_WHITE: "blackWhite",
|
|
7159
|
+
SEPIA: "sepia",
|
|
7160
|
+
COOL: "cool",
|
|
7161
|
+
WARM: "warm",
|
|
7162
|
+
CINEMATIC: "cinematic",
|
|
7163
|
+
SOFT_GLOW: "softGlow",
|
|
7164
|
+
MOODY: "moody",
|
|
7165
|
+
DREAMY: "dreamy",
|
|
7166
|
+
INVERTED: "inverted",
|
|
7167
|
+
VINTAGE: "vintage",
|
|
7168
|
+
DRAMATIC: "dramatic",
|
|
7169
|
+
FADED: "faded"
|
|
7170
|
+
};
|
|
7152
7171
|
class LRUCache {
|
|
7153
7172
|
constructor(maxSize = 100) {
|
|
7154
7173
|
if (maxSize <= 0) {
|
|
@@ -7532,6 +7551,275 @@ const getObjectFitSize = (objectFit, elementSize, containerSize) => {
|
|
|
7532
7551
|
};
|
|
7533
7552
|
}
|
|
7534
7553
|
};
|
|
7554
|
+
const {
|
|
7555
|
+
Blur,
|
|
7556
|
+
Brightness,
|
|
7557
|
+
ColorMatrix,
|
|
7558
|
+
Contrast,
|
|
7559
|
+
Grayscale,
|
|
7560
|
+
HueRotation,
|
|
7561
|
+
Invert,
|
|
7562
|
+
Saturation,
|
|
7563
|
+
Sepia
|
|
7564
|
+
} = Sh;
|
|
7565
|
+
let canvas2dFilterBackendInstalled = false;
|
|
7566
|
+
function ensureCanvas2dImageFilterBackend() {
|
|
7567
|
+
if (canvas2dFilterBackendInstalled) return;
|
|
7568
|
+
canvas2dFilterBackendInstalled = true;
|
|
7569
|
+
ia(new Zo());
|
|
7570
|
+
}
|
|
7571
|
+
function getSourceBitmapSize(img) {
|
|
7572
|
+
const el = img.getElement();
|
|
7573
|
+
if (!el) return null;
|
|
7574
|
+
const w2 = "naturalWidth" in el && el.naturalWidth > 0 ? el.naturalWidth : el.width;
|
|
7575
|
+
const h2 = "naturalHeight" in el && el.naturalHeight > 0 ? el.naturalHeight : el.height;
|
|
7576
|
+
if (!w2 || !h2) return null;
|
|
7577
|
+
return { w: w2, h: h2 };
|
|
7578
|
+
}
|
|
7579
|
+
function applyFiltersSafe(img) {
|
|
7580
|
+
ensureCanvas2dImageFilterBackend();
|
|
7581
|
+
img.applyFilters();
|
|
7582
|
+
}
|
|
7583
|
+
const bright = (m2) => Math.min(1, Math.max(-1, (m2 - 1) * 0.48));
|
|
7584
|
+
const contr = (m2) => Math.min(1, Math.max(-1, (m2 - 1) * 0.55));
|
|
7585
|
+
const sat = (m2) => Math.min(1, Math.max(-1, (m2 - 1) * 0.72));
|
|
7586
|
+
const IDENTITY = [
|
|
7587
|
+
1,
|
|
7588
|
+
0,
|
|
7589
|
+
0,
|
|
7590
|
+
0,
|
|
7591
|
+
0,
|
|
7592
|
+
0,
|
|
7593
|
+
1,
|
|
7594
|
+
0,
|
|
7595
|
+
0,
|
|
7596
|
+
0,
|
|
7597
|
+
0,
|
|
7598
|
+
0,
|
|
7599
|
+
1,
|
|
7600
|
+
0,
|
|
7601
|
+
0,
|
|
7602
|
+
0,
|
|
7603
|
+
0,
|
|
7604
|
+
0,
|
|
7605
|
+
1,
|
|
7606
|
+
0
|
|
7607
|
+
];
|
|
7608
|
+
const SEPIA_MATRIX = [
|
|
7609
|
+
0.393,
|
|
7610
|
+
0.769,
|
|
7611
|
+
0.189,
|
|
7612
|
+
0,
|
|
7613
|
+
0,
|
|
7614
|
+
0.349,
|
|
7615
|
+
0.686,
|
|
7616
|
+
0.168,
|
|
7617
|
+
0,
|
|
7618
|
+
0,
|
|
7619
|
+
0.272,
|
|
7620
|
+
0.534,
|
|
7621
|
+
0.131,
|
|
7622
|
+
0,
|
|
7623
|
+
0,
|
|
7624
|
+
0,
|
|
7625
|
+
0,
|
|
7626
|
+
0,
|
|
7627
|
+
1,
|
|
7628
|
+
0
|
|
7629
|
+
];
|
|
7630
|
+
function sepiaMix(strength) {
|
|
7631
|
+
const t2 = Math.min(1, Math.max(0, strength));
|
|
7632
|
+
const m2 = IDENTITY.map((v2, i2) => v2 + (SEPIA_MATRIX[i2] - v2) * t2);
|
|
7633
|
+
return new ColorMatrix({ matrix: m2, colorsOnly: true });
|
|
7634
|
+
}
|
|
7635
|
+
const twickBlurToFabric = (v2) => Math.min(0.22, Math.max(0, v2 * 0.045));
|
|
7636
|
+
function buildFilters(filterType) {
|
|
7637
|
+
switch (filterType) {
|
|
7638
|
+
case COLOR_FILTERS.SATURATED:
|
|
7639
|
+
return {
|
|
7640
|
+
filters: [
|
|
7641
|
+
new Saturation({ saturation: sat(1.4) }),
|
|
7642
|
+
new Contrast({ contrast: contr(1.1) })
|
|
7643
|
+
],
|
|
7644
|
+
opacityFactor: 1
|
|
7645
|
+
};
|
|
7646
|
+
case COLOR_FILTERS.BRIGHT:
|
|
7647
|
+
return {
|
|
7648
|
+
filters: [
|
|
7649
|
+
new Brightness({ brightness: bright(1.3) }),
|
|
7650
|
+
new Contrast({ contrast: contr(1.05) })
|
|
7651
|
+
],
|
|
7652
|
+
opacityFactor: 1
|
|
7653
|
+
};
|
|
7654
|
+
case COLOR_FILTERS.VIBRANT:
|
|
7655
|
+
return {
|
|
7656
|
+
filters: [
|
|
7657
|
+
new Saturation({ saturation: sat(1.6) }),
|
|
7658
|
+
new Brightness({ brightness: bright(1.15) }),
|
|
7659
|
+
new Contrast({ contrast: contr(1.1) })
|
|
7660
|
+
],
|
|
7661
|
+
opacityFactor: 1
|
|
7662
|
+
};
|
|
7663
|
+
case COLOR_FILTERS.RETRO:
|
|
7664
|
+
return {
|
|
7665
|
+
filters: [
|
|
7666
|
+
sepiaMix(0.8),
|
|
7667
|
+
new Contrast({ contrast: contr(1.3) }),
|
|
7668
|
+
new Brightness({ brightness: bright(0.85) }),
|
|
7669
|
+
new Saturation({ saturation: sat(0.8) })
|
|
7670
|
+
],
|
|
7671
|
+
opacityFactor: 1
|
|
7672
|
+
};
|
|
7673
|
+
case COLOR_FILTERS.BLACK_WHITE:
|
|
7674
|
+
return {
|
|
7675
|
+
filters: [
|
|
7676
|
+
new Grayscale(),
|
|
7677
|
+
new Contrast({ contrast: contr(1.25) }),
|
|
7678
|
+
new Brightness({ brightness: bright(1.05) })
|
|
7679
|
+
],
|
|
7680
|
+
opacityFactor: 1
|
|
7681
|
+
};
|
|
7682
|
+
case COLOR_FILTERS.SEPIA:
|
|
7683
|
+
return {
|
|
7684
|
+
filters: [
|
|
7685
|
+
new Sepia(),
|
|
7686
|
+
new Contrast({ contrast: contr(1.08) })
|
|
7687
|
+
],
|
|
7688
|
+
opacityFactor: 1
|
|
7689
|
+
};
|
|
7690
|
+
case COLOR_FILTERS.COOL:
|
|
7691
|
+
return {
|
|
7692
|
+
filters: [
|
|
7693
|
+
new HueRotation({ rotation: 15 / 180 }),
|
|
7694
|
+
new Brightness({ brightness: bright(1.1) }),
|
|
7695
|
+
new Saturation({ saturation: sat(1.3) }),
|
|
7696
|
+
new Contrast({ contrast: contr(1.05) })
|
|
7697
|
+
],
|
|
7698
|
+
opacityFactor: 1
|
|
7699
|
+
};
|
|
7700
|
+
case COLOR_FILTERS.WARM:
|
|
7701
|
+
return {
|
|
7702
|
+
filters: [
|
|
7703
|
+
new HueRotation({ rotation: -15 / 180 }),
|
|
7704
|
+
new Brightness({ brightness: bright(1.15) }),
|
|
7705
|
+
new Saturation({ saturation: sat(1.3) }),
|
|
7706
|
+
new Contrast({ contrast: contr(1.05) })
|
|
7707
|
+
],
|
|
7708
|
+
opacityFactor: 1
|
|
7709
|
+
};
|
|
7710
|
+
case COLOR_FILTERS.CINEMATIC:
|
|
7711
|
+
return {
|
|
7712
|
+
filters: [
|
|
7713
|
+
new Contrast({ contrast: contr(1.4) }),
|
|
7714
|
+
new Brightness({ brightness: bright(0.95) }),
|
|
7715
|
+
new Saturation({ saturation: sat(0.85) }),
|
|
7716
|
+
sepiaMix(0.2)
|
|
7717
|
+
],
|
|
7718
|
+
opacityFactor: 1
|
|
7719
|
+
};
|
|
7720
|
+
case COLOR_FILTERS.SOFT_GLOW:
|
|
7721
|
+
return {
|
|
7722
|
+
filters: [
|
|
7723
|
+
new Brightness({ brightness: bright(1.2) }),
|
|
7724
|
+
new Contrast({ contrast: contr(0.95) }),
|
|
7725
|
+
new Blur({ blur: twickBlurToFabric(1.2) }),
|
|
7726
|
+
new Saturation({ saturation: sat(1.1) })
|
|
7727
|
+
],
|
|
7728
|
+
opacityFactor: 1
|
|
7729
|
+
};
|
|
7730
|
+
case COLOR_FILTERS.MOODY:
|
|
7731
|
+
return {
|
|
7732
|
+
filters: [
|
|
7733
|
+
new Brightness({ brightness: bright(1.05) }),
|
|
7734
|
+
new Contrast({ contrast: contr(1.4) }),
|
|
7735
|
+
new Saturation({ saturation: sat(0.65) }),
|
|
7736
|
+
sepiaMix(0.2)
|
|
7737
|
+
],
|
|
7738
|
+
opacityFactor: 1
|
|
7739
|
+
};
|
|
7740
|
+
case COLOR_FILTERS.DREAMY:
|
|
7741
|
+
return {
|
|
7742
|
+
filters: [
|
|
7743
|
+
new Brightness({ brightness: bright(1.3) }),
|
|
7744
|
+
new Blur({ blur: twickBlurToFabric(2) }),
|
|
7745
|
+
new Saturation({ saturation: sat(1.4) }),
|
|
7746
|
+
new Contrast({ contrast: contr(0.95) })
|
|
7747
|
+
],
|
|
7748
|
+
opacityFactor: 1
|
|
7749
|
+
};
|
|
7750
|
+
case COLOR_FILTERS.INVERTED:
|
|
7751
|
+
return {
|
|
7752
|
+
filters: [
|
|
7753
|
+
new Invert({ invert: true, alpha: false }),
|
|
7754
|
+
new HueRotation({ rotation: 1 })
|
|
7755
|
+
],
|
|
7756
|
+
opacityFactor: 1
|
|
7757
|
+
};
|
|
7758
|
+
case COLOR_FILTERS.VINTAGE:
|
|
7759
|
+
return {
|
|
7760
|
+
filters: [
|
|
7761
|
+
sepiaMix(0.4),
|
|
7762
|
+
new Saturation({ saturation: sat(1.4) }),
|
|
7763
|
+
new Contrast({ contrast: contr(1.2) }),
|
|
7764
|
+
new Brightness({ brightness: bright(1.1) })
|
|
7765
|
+
],
|
|
7766
|
+
opacityFactor: 1
|
|
7767
|
+
};
|
|
7768
|
+
case COLOR_FILTERS.DRAMATIC:
|
|
7769
|
+
return {
|
|
7770
|
+
filters: [
|
|
7771
|
+
new Contrast({ contrast: contr(1.5) }),
|
|
7772
|
+
new Brightness({ brightness: bright(0.9) }),
|
|
7773
|
+
new Saturation({ saturation: sat(1.2) })
|
|
7774
|
+
],
|
|
7775
|
+
opacityFactor: 1
|
|
7776
|
+
};
|
|
7777
|
+
case COLOR_FILTERS.FADED:
|
|
7778
|
+
return {
|
|
7779
|
+
filters: [
|
|
7780
|
+
new Brightness({ brightness: bright(1.2) }),
|
|
7781
|
+
new Saturation({ saturation: sat(0.8) }),
|
|
7782
|
+
new Contrast({ contrast: contr(0.9) })
|
|
7783
|
+
],
|
|
7784
|
+
opacityFactor: 0.9
|
|
7785
|
+
};
|
|
7786
|
+
default:
|
|
7787
|
+
return { filters: [], opacityFactor: 1 };
|
|
7788
|
+
}
|
|
7789
|
+
}
|
|
7790
|
+
function applyFabricMediaColorFilters(img, mediaFilter, elementOpacity) {
|
|
7791
|
+
const key = (mediaFilter == null ? void 0 : mediaFilter.trim()) || "none";
|
|
7792
|
+
if (key === "none") {
|
|
7793
|
+
img.filters = [];
|
|
7794
|
+
img.set("opacity", elementOpacity);
|
|
7795
|
+
applyFiltersSafe(img);
|
|
7796
|
+
return;
|
|
7797
|
+
}
|
|
7798
|
+
const { filters: filterList, opacityFactor } = buildFilters(key);
|
|
7799
|
+
if (filterList.length === 0) {
|
|
7800
|
+
img.filters = [];
|
|
7801
|
+
img.set("opacity", elementOpacity);
|
|
7802
|
+
applyFiltersSafe(img);
|
|
7803
|
+
return;
|
|
7804
|
+
}
|
|
7805
|
+
if (!getSourceBitmapSize(img)) {
|
|
7806
|
+
img.filters = [];
|
|
7807
|
+
img.set("opacity", elementOpacity);
|
|
7808
|
+
return;
|
|
7809
|
+
}
|
|
7810
|
+
img.filters = filterList;
|
|
7811
|
+
img.set("opacity", elementOpacity * opacityFactor);
|
|
7812
|
+
try {
|
|
7813
|
+
applyFiltersSafe(img);
|
|
7814
|
+
} catch {
|
|
7815
|
+
img.filters = [];
|
|
7816
|
+
img.set("opacity", elementOpacity);
|
|
7817
|
+
try {
|
|
7818
|
+
applyFiltersSafe(img);
|
|
7819
|
+
} catch {
|
|
7820
|
+
}
|
|
7821
|
+
}
|
|
7822
|
+
}
|
|
7535
7823
|
const MARGIN = 10;
|
|
7536
7824
|
const addTextElement = ({
|
|
7537
7825
|
element,
|
|
@@ -7622,7 +7910,7 @@ const setImageProps = ({
|
|
|
7622
7910
|
canvasMetadata,
|
|
7623
7911
|
lockAspectRatio = true
|
|
7624
7912
|
}) => {
|
|
7625
|
-
var _a, _b, _c, _d, _e2;
|
|
7913
|
+
var _a, _b, _c, _d, _e2, _f;
|
|
7626
7914
|
const width = (((_a = element.props) == null ? void 0 : _a.width) || 0) * canvasMetadata.scaleX || canvasMetadata.width;
|
|
7627
7915
|
const height = (((_b = element.props) == null ? void 0 : _b.height) || 0) * canvasMetadata.scaleY || canvasMetadata.height;
|
|
7628
7916
|
const { x: x2, y: y2 } = convertToCanvasPosition(
|
|
@@ -7636,11 +7924,15 @@ const setImageProps = ({
|
|
|
7636
7924
|
img.set("height", height);
|
|
7637
7925
|
img.set("left", x2);
|
|
7638
7926
|
img.set("top", y2);
|
|
7639
|
-
img.set("opacity", ((_e2 = element.props) == null ? void 0 : _e2.opacity) ?? 1);
|
|
7640
7927
|
img.set("selectable", true);
|
|
7641
7928
|
img.set("hasControls", true);
|
|
7642
7929
|
img.set("touchAction", "all");
|
|
7643
7930
|
img.set("lockUniScaling", lockAspectRatio);
|
|
7931
|
+
applyFabricMediaColorFilters(
|
|
7932
|
+
img,
|
|
7933
|
+
(_e2 = element.props) == null ? void 0 : _e2.mediaFilter,
|
|
7934
|
+
((_f = element.props) == null ? void 0 : _f.opacity) ?? 1
|
|
7935
|
+
);
|
|
7644
7936
|
};
|
|
7645
7937
|
const addCaptionElement = ({
|
|
7646
7938
|
element,
|
|
@@ -7650,48 +7942,52 @@ const addCaptionElement = ({
|
|
|
7650
7942
|
canvasMetadata,
|
|
7651
7943
|
lockAspectRatio = false
|
|
7652
7944
|
}) => {
|
|
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
|
|
7654
|
-
const
|
|
7655
|
-
const
|
|
7945
|
+
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;
|
|
7946
|
+
const useTrackDefaults = ((_a = element.props) == null ? void 0 : _a.useTrackDefaults) ?? true;
|
|
7947
|
+
const trackColors = captionProps == null ? void 0 : captionProps.colors;
|
|
7948
|
+
const elementColors = (_b = element.props) == null ? void 0 : _b.colors;
|
|
7949
|
+
const resolvedColors = useTrackDefaults ? trackColors : { ...trackColors ?? {}, ...elementColors ?? {} };
|
|
7950
|
+
const captionTextColor = (resolvedColors == null ? void 0 : resolvedColors.text) ?? ((_c = captionProps == null ? void 0 : captionProps.color) == null ? void 0 : _c.text);
|
|
7656
7951
|
const { x: x2, y: y2 } = convertToCanvasPosition(
|
|
7657
|
-
(
|
|
7658
|
-
(
|
|
7952
|
+
(useTrackDefaults ? captionProps == null ? void 0 : captionProps.x : (_d = element.props) == null ? void 0 : _d.x) ?? (captionProps == null ? void 0 : captionProps.x) ?? 0,
|
|
7953
|
+
(useTrackDefaults ? captionProps == null ? void 0 : captionProps.y : (_e2 = element.props) == null ? void 0 : _e2.y) ?? (captionProps == null ? void 0 : captionProps.y) ?? 0,
|
|
7659
7954
|
canvasMetadata
|
|
7660
7955
|
);
|
|
7661
|
-
let width = ((
|
|
7662
|
-
if ((
|
|
7956
|
+
let width = ((_f = element.props) == null ? void 0 : _f.width) ? element.props.width * canvasMetadata.scaleX : canvasMetadata.width - 2 * MARGIN;
|
|
7957
|
+
if ((_g = element.props) == null ? void 0 : _g.maxWidth) {
|
|
7663
7958
|
width = Math.min(width, element.props.maxWidth * canvasMetadata.scaleX);
|
|
7664
7959
|
}
|
|
7665
|
-
const
|
|
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 trackColors = captionProps == null ? void 0 : captionProps.colors;
|
|
7960
|
+
const resolvedFill = (useTrackDefaults ? void 0 : (_h2 = element.props) == null ? void 0 : _h2.fill) ?? captionTextColor ?? DEFAULT_CAPTION_PROPS.fill;
|
|
7668
7961
|
const trackStroke = trackColors == null ? void 0 : trackColors.outlineColor;
|
|
7669
7962
|
const elementStroke = (elementColors == null ? void 0 : elementColors.outlineColor) ?? ((_i2 = element.props) == null ? void 0 : _i2.stroke);
|
|
7670
|
-
const resolvedStroke = (
|
|
7671
|
-
const
|
|
7963
|
+
const resolvedStroke = (useTrackDefaults ? trackStroke : elementStroke ?? trackStroke) ?? void 0;
|
|
7964
|
+
const trackFont = (captionProps == null ? void 0 : captionProps.font) ?? {};
|
|
7965
|
+
const elementFont = ((_j = element.props) == null ? void 0 : _j.font) ?? {};
|
|
7966
|
+
const resolvedFont = useTrackDefaults ? trackFont : { ...trackFont, ...elementFont };
|
|
7967
|
+
const caption = new Uo(((_k = element.props) == null ? void 0 : _k.text) || element.t || "", {
|
|
7672
7968
|
left: x2,
|
|
7673
7969
|
top: y2,
|
|
7674
7970
|
originX: "center",
|
|
7675
7971
|
originY: "center",
|
|
7676
|
-
angle: ((
|
|
7972
|
+
angle: ((_l = element.props) == null ? void 0 : _l.rotation) || 0,
|
|
7677
7973
|
fontSize: Math.round(
|
|
7678
|
-
((
|
|
7974
|
+
((resolvedFont == null ? void 0 : resolvedFont.size) ?? DEFAULT_CAPTION_PROPS.size) * canvasMetadata.scaleX
|
|
7679
7975
|
),
|
|
7680
|
-
fontFamily: (
|
|
7976
|
+
fontFamily: (resolvedFont == null ? void 0 : resolvedFont.family) ?? DEFAULT_CAPTION_PROPS.family,
|
|
7681
7977
|
fill: resolvedFill,
|
|
7682
|
-
fontWeight: (
|
|
7978
|
+
fontWeight: (resolvedFont == null ? void 0 : resolvedFont.weight) ?? DEFAULT_CAPTION_PROPS.fontWeight,
|
|
7683
7979
|
...resolvedStroke ? { stroke: resolvedStroke } : {},
|
|
7684
|
-
opacity: (
|
|
7980
|
+
opacity: (useTrackDefaults ? void 0 : (_m = element.props) == null ? void 0 : _m.opacity) ?? (captionProps == null ? void 0 : captionProps.opacity) ?? 1,
|
|
7685
7981
|
width,
|
|
7686
7982
|
splitByGrapheme: false,
|
|
7687
|
-
textAlign: ((
|
|
7983
|
+
textAlign: ((_n2 = element.props) == null ? void 0 : _n2.textAlign) ?? "center",
|
|
7688
7984
|
shadow: new Ds({
|
|
7689
|
-
offsetX: (
|
|
7690
|
-
offsetY: (
|
|
7691
|
-
blur: (
|
|
7692
|
-
color: (
|
|
7985
|
+
offsetX: (useTrackDefaults ? void 0 : (_p = (_o2 = element.props) == null ? void 0 : _o2.shadowOffset) == null ? void 0 : _p[0]) ?? ((_q = captionProps == null ? void 0 : captionProps.shadowOffset) == null ? void 0 : _q[0]) ?? ((_r2 = DEFAULT_CAPTION_PROPS.shadowOffset) == null ? void 0 : _r2[0]),
|
|
7986
|
+
offsetY: (useTrackDefaults ? void 0 : (_t2 = (_s2 = element.props) == null ? void 0 : _s2.shadowOffset) == null ? void 0 : _t2[1]) ?? ((_u = captionProps == null ? void 0 : captionProps.shadowOffset) == null ? void 0 : _u[1]) ?? ((_v = DEFAULT_CAPTION_PROPS.shadowOffset) == null ? void 0 : _v[1]),
|
|
7987
|
+
blur: (useTrackDefaults ? void 0 : (_w = element.props) == null ? void 0 : _w.shadowBlur) ?? (captionProps == null ? void 0 : captionProps.shadowBlur) ?? DEFAULT_CAPTION_PROPS.shadowBlur,
|
|
7988
|
+
color: (useTrackDefaults ? void 0 : (_x = element.props) == null ? void 0 : _x.shadowColor) ?? (captionProps == null ? void 0 : captionProps.shadowColor) ?? DEFAULT_CAPTION_PROPS.shadowColor
|
|
7693
7989
|
}),
|
|
7694
|
-
strokeWidth: ((
|
|
7990
|
+
strokeWidth: ((useTrackDefaults ? void 0 : (_y = element.props) == null ? void 0 : _y.lineWidth) ?? (captionProps == null ? void 0 : captionProps.lineWidth) ?? DEFAULT_CAPTION_PROPS.lineWidth) * 0.025
|
|
7695
7991
|
});
|
|
7696
7992
|
caption.set("id", element.id);
|
|
7697
7993
|
caption.set("zIndex", index);
|
|
@@ -7746,8 +8042,13 @@ const addImageElement = async ({
|
|
|
7746
8042
|
currentFrameEffect,
|
|
7747
8043
|
lockAspectRatio = true
|
|
7748
8044
|
}) => {
|
|
8045
|
+
var _a, _b;
|
|
7749
8046
|
try {
|
|
7750
|
-
const
|
|
8047
|
+
const rawSrc = imageUrl || element.props.src || "";
|
|
8048
|
+
const mediaFilter = (_b = (_a = element.props) == null ? void 0 : _a.mediaFilter) == null ? void 0 : _b.trim();
|
|
8049
|
+
const useFilter = !!mediaFilter && mediaFilter !== "none";
|
|
8050
|
+
const fromUrlOpts = useFilter && /^https?:\/\//i.test(rawSrc) ? { crossOrigin: "anonymous" } : {};
|
|
8051
|
+
const img = await oa.fromURL(rawSrc, fromUrlOpts);
|
|
7751
8052
|
img.set({
|
|
7752
8053
|
originX: "center",
|
|
7753
8054
|
originY: "center",
|
|
@@ -7784,7 +8085,7 @@ const addMediaGroup = ({
|
|
|
7784
8085
|
currentFrameEffect,
|
|
7785
8086
|
lockAspectRatio = true
|
|
7786
8087
|
}) => {
|
|
7787
|
-
var _a, _b, _c, _d, _e2, _f, _g, _h2, _i2, _j, _k, _l, _m, _n2;
|
|
8088
|
+
var _a, _b, _c, _d, _e2, _f, _g, _h2, _i2, _j, _k, _l, _m, _n2, _o2;
|
|
7788
8089
|
let frameSize;
|
|
7789
8090
|
let angle;
|
|
7790
8091
|
let framePosition;
|
|
@@ -7839,9 +8140,13 @@ const addMediaGroup = ({
|
|
|
7839
8140
|
originX: "center",
|
|
7840
8141
|
originY: "center",
|
|
7841
8142
|
scaleX: newSize.width / img.width,
|
|
7842
|
-
scaleY: newSize.height / img.height
|
|
7843
|
-
opacity: ((_n2 = element.props) == null ? void 0 : _n2.opacity) ?? 1
|
|
8143
|
+
scaleY: newSize.height / img.height
|
|
7844
8144
|
});
|
|
8145
|
+
applyFabricMediaColorFilters(
|
|
8146
|
+
img,
|
|
8147
|
+
(_n2 = element.props) == null ? void 0 : _n2.mediaFilter,
|
|
8148
|
+
((_o2 = element.props) == null ? void 0 : _o2.opacity) ?? 1
|
|
8149
|
+
);
|
|
7845
8150
|
const { x: x2, y: y2 } = convertToCanvasPosition(
|
|
7846
8151
|
(framePosition == null ? void 0 : framePosition.x) || 0,
|
|
7847
8152
|
(framePosition == null ? void 0 : framePosition.y) || 0,
|
|
@@ -8327,7 +8632,8 @@ const CaptionElement = {
|
|
|
8327
8632
|
context.canvasMetadata,
|
|
8328
8633
|
context.videoSize
|
|
8329
8634
|
);
|
|
8330
|
-
|
|
8635
|
+
const useTrackDefaults = ((_a = element.props) == null ? void 0 : _a.useTrackDefaults) ?? true;
|
|
8636
|
+
if (useTrackDefaults) {
|
|
8331
8637
|
return {
|
|
8332
8638
|
element,
|
|
8333
8639
|
operation: CANVAS_OPERATIONS.CAPTION_PROPS_UPDATED,
|
|
@@ -8544,6 +8850,72 @@ const EffectElement = {
|
|
|
8544
8850
|
return;
|
|
8545
8851
|
}
|
|
8546
8852
|
};
|
|
8853
|
+
const EmojiElement = {
|
|
8854
|
+
name: ELEMENT_TYPES.EMOJI,
|
|
8855
|
+
async add(params) {
|
|
8856
|
+
var _a;
|
|
8857
|
+
const { element, index, canvas, canvasMetadata, lockAspectRatio } = params;
|
|
8858
|
+
await addImageElement({
|
|
8859
|
+
element,
|
|
8860
|
+
index,
|
|
8861
|
+
canvas,
|
|
8862
|
+
canvasMetadata,
|
|
8863
|
+
lockAspectRatio: lockAspectRatio ?? ((_a = element.props) == null ? void 0 : _a.lockAspectRatio) ?? true
|
|
8864
|
+
});
|
|
8865
|
+
},
|
|
8866
|
+
updateFromFabricObject(object, element, context) {
|
|
8867
|
+
const canvasCenter = getObjectCanvasCenter(object);
|
|
8868
|
+
const { x: x2, y: y2 } = convertToVideoPosition(
|
|
8869
|
+
canvasCenter.x,
|
|
8870
|
+
canvasCenter.y,
|
|
8871
|
+
context.canvasMetadata,
|
|
8872
|
+
context.videoSize
|
|
8873
|
+
);
|
|
8874
|
+
if (object.type === "group") {
|
|
8875
|
+
const scaledW2 = (object.width ?? 0) * (object.scaleX ?? 1);
|
|
8876
|
+
const scaledH2 = (object.height ?? 0) * (object.scaleY ?? 1);
|
|
8877
|
+
const { width: fw, height: fh2 } = convertToVideoDimensions(
|
|
8878
|
+
scaledW2,
|
|
8879
|
+
scaledH2,
|
|
8880
|
+
context.canvasMetadata
|
|
8881
|
+
);
|
|
8882
|
+
const updatedFrameSize = [fw, fh2];
|
|
8883
|
+
const frame2 = element.frame;
|
|
8884
|
+
return {
|
|
8885
|
+
element: {
|
|
8886
|
+
...element,
|
|
8887
|
+
frame: {
|
|
8888
|
+
...frame2,
|
|
8889
|
+
rotation: getObjectCanvasAngle(object),
|
|
8890
|
+
size: updatedFrameSize,
|
|
8891
|
+
x: x2,
|
|
8892
|
+
y: y2
|
|
8893
|
+
}
|
|
8894
|
+
}
|
|
8895
|
+
};
|
|
8896
|
+
}
|
|
8897
|
+
const scaledW = (object.width ?? 0) * (object.scaleX ?? 1);
|
|
8898
|
+
const scaledH = (object.height ?? 0) * (object.scaleY ?? 1);
|
|
8899
|
+
const { width, height } = convertToVideoDimensions(
|
|
8900
|
+
scaledW,
|
|
8901
|
+
scaledH,
|
|
8902
|
+
context.canvasMetadata
|
|
8903
|
+
);
|
|
8904
|
+
return {
|
|
8905
|
+
element: {
|
|
8906
|
+
...element,
|
|
8907
|
+
props: {
|
|
8908
|
+
...element.props,
|
|
8909
|
+
rotation: getObjectCanvasAngle(object),
|
|
8910
|
+
width,
|
|
8911
|
+
height,
|
|
8912
|
+
x: x2,
|
|
8913
|
+
y: y2
|
|
8914
|
+
}
|
|
8915
|
+
}
|
|
8916
|
+
};
|
|
8917
|
+
}
|
|
8918
|
+
};
|
|
8547
8919
|
class ElementController {
|
|
8548
8920
|
constructor() {
|
|
8549
8921
|
__publicField2(this, "elements", /* @__PURE__ */ new Map());
|
|
@@ -8565,6 +8937,7 @@ function registerElements() {
|
|
|
8565
8937
|
elementController.register(RectElement);
|
|
8566
8938
|
elementController.register(CircleElement);
|
|
8567
8939
|
elementController.register(TextElement);
|
|
8940
|
+
elementController.register(EmojiElement);
|
|
8568
8941
|
elementController.register(CaptionElement);
|
|
8569
8942
|
elementController.register(WatermarkElement);
|
|
8570
8943
|
elementController.register(ArrowElement);
|
|
@@ -9149,6 +9522,8 @@ const DEFAULT_ELEMENT_COLORS = {
|
|
|
9149
9522
|
animation: "#4B9B78",
|
|
9150
9523
|
/** Icon element color - bright orchid */
|
|
9151
9524
|
icon: "#A76CD4",
|
|
9525
|
+
/** Emoji element color - warm amber */
|
|
9526
|
+
emoji: "#F59E0B",
|
|
9152
9527
|
/** Circle element color - deep byzantium */
|
|
9153
9528
|
circle: "#703D8B",
|
|
9154
9529
|
/** Effect element color - cyan accent for global effects */
|
|
@@ -19037,6 +19412,102 @@ const setElementColors = (colors) => {
|
|
|
19037
19412
|
...colors
|
|
19038
19413
|
};
|
|
19039
19414
|
};
|
|
19415
|
+
const VIEWPORT_MARGIN = 8;
|
|
19416
|
+
function clampMenuPosition(clientX, clientY, width, height) {
|
|
19417
|
+
const vw2 = window.innerWidth;
|
|
19418
|
+
const vh3 = window.innerHeight;
|
|
19419
|
+
const maxLeft = Math.max(VIEWPORT_MARGIN, vw2 - width - VIEWPORT_MARGIN);
|
|
19420
|
+
const maxTop = Math.max(VIEWPORT_MARGIN, vh3 - height - VIEWPORT_MARGIN);
|
|
19421
|
+
return {
|
|
19422
|
+
left: Math.min(Math.max(VIEWPORT_MARGIN, clientX), maxLeft),
|
|
19423
|
+
top: Math.min(Math.max(VIEWPORT_MARGIN, clientY), maxTop)
|
|
19424
|
+
};
|
|
19425
|
+
}
|
|
19426
|
+
const TrackElementContextMenu = ({
|
|
19427
|
+
x: x2,
|
|
19428
|
+
y: y2,
|
|
19429
|
+
canSplit,
|
|
19430
|
+
onSplit,
|
|
19431
|
+
onDelete,
|
|
19432
|
+
onClose
|
|
19433
|
+
}) => {
|
|
19434
|
+
const menuRef = React.useRef(null);
|
|
19435
|
+
const [position, setPosition] = React.useState(() => ({
|
|
19436
|
+
left: x2,
|
|
19437
|
+
top: y2
|
|
19438
|
+
}));
|
|
19439
|
+
const reposition = React.useCallback(() => {
|
|
19440
|
+
const el = menuRef.current;
|
|
19441
|
+
if (!el) return;
|
|
19442
|
+
const { width, height } = el.getBoundingClientRect();
|
|
19443
|
+
setPosition(clampMenuPosition(x2, y2, width, height));
|
|
19444
|
+
}, [x2, y2]);
|
|
19445
|
+
React.useLayoutEffect(() => {
|
|
19446
|
+
reposition();
|
|
19447
|
+
}, [reposition]);
|
|
19448
|
+
React.useEffect(() => {
|
|
19449
|
+
window.addEventListener("resize", reposition);
|
|
19450
|
+
return () => window.removeEventListener("resize", reposition);
|
|
19451
|
+
}, [reposition]);
|
|
19452
|
+
React.useEffect(() => {
|
|
19453
|
+
const handleClickOutside = (e3) => {
|
|
19454
|
+
if (menuRef.current && !menuRef.current.contains(e3.target)) {
|
|
19455
|
+
onClose();
|
|
19456
|
+
}
|
|
19457
|
+
};
|
|
19458
|
+
const handleEscape = (e3) => {
|
|
19459
|
+
if (e3.key === "Escape") onClose();
|
|
19460
|
+
};
|
|
19461
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
19462
|
+
document.addEventListener("keydown", handleEscape);
|
|
19463
|
+
return () => {
|
|
19464
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
19465
|
+
document.removeEventListener("keydown", handleEscape);
|
|
19466
|
+
};
|
|
19467
|
+
}, [onClose]);
|
|
19468
|
+
const wrap = (fn2) => {
|
|
19469
|
+
fn2();
|
|
19470
|
+
onClose();
|
|
19471
|
+
};
|
|
19472
|
+
const menu = /* @__PURE__ */ jsxRuntime.jsxs(
|
|
19473
|
+
"div",
|
|
19474
|
+
{
|
|
19475
|
+
ref: menuRef,
|
|
19476
|
+
className: "twick-canvas-context-menu",
|
|
19477
|
+
style: { left: position.left, top: position.top },
|
|
19478
|
+
role: "menu",
|
|
19479
|
+
children: [
|
|
19480
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
19481
|
+
"button",
|
|
19482
|
+
{
|
|
19483
|
+
type: "button",
|
|
19484
|
+
className: "twick-canvas-context-menu-item",
|
|
19485
|
+
onClick: () => wrap(onSplit),
|
|
19486
|
+
disabled: !canSplit,
|
|
19487
|
+
role: "menuitem",
|
|
19488
|
+
style: !canSplit ? { opacity: 0.45, cursor: "not-allowed" } : void 0,
|
|
19489
|
+
children: "Split at playhead"
|
|
19490
|
+
}
|
|
19491
|
+
),
|
|
19492
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "twick-canvas-context-menu-separator", role: "separator" }),
|
|
19493
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
19494
|
+
"button",
|
|
19495
|
+
{
|
|
19496
|
+
type: "button",
|
|
19497
|
+
className: "twick-canvas-context-menu-item twick-canvas-context-menu-item-danger",
|
|
19498
|
+
onClick: () => wrap(onDelete),
|
|
19499
|
+
role: "menuitem",
|
|
19500
|
+
children: "Delete"
|
|
19501
|
+
}
|
|
19502
|
+
)
|
|
19503
|
+
]
|
|
19504
|
+
}
|
|
19505
|
+
);
|
|
19506
|
+
if (typeof document === "undefined") {
|
|
19507
|
+
return null;
|
|
19508
|
+
}
|
|
19509
|
+
return reactDom.createPortal(menu, document.body);
|
|
19510
|
+
};
|
|
19040
19511
|
const TrackElementView = ({
|
|
19041
19512
|
element,
|
|
19042
19513
|
parentWidth,
|
|
@@ -19049,13 +19520,20 @@ const TrackElementView = ({
|
|
|
19049
19520
|
onDrag,
|
|
19050
19521
|
allowOverlap = false,
|
|
19051
19522
|
onDragStateChange,
|
|
19052
|
-
elementColors
|
|
19523
|
+
elementColors,
|
|
19524
|
+
currentTime = 0,
|
|
19525
|
+
onContextMenuTarget,
|
|
19526
|
+
onDeleteElement,
|
|
19527
|
+
onSplitElement
|
|
19053
19528
|
}) => {
|
|
19054
19529
|
var _a, _b;
|
|
19055
19530
|
const ref = React.useRef(null);
|
|
19056
19531
|
const dragType = React.useRef(null);
|
|
19057
19532
|
const lastPosRef = React.useRef(null);
|
|
19058
19533
|
const [isDragging2, setIsDragging] = React.useState(false);
|
|
19534
|
+
const [clipMenu, setClipMenu] = React.useState(
|
|
19535
|
+
null
|
|
19536
|
+
);
|
|
19059
19537
|
const [position, setPosition] = React.useState({
|
|
19060
19538
|
start: 0,
|
|
19061
19539
|
end: 0
|
|
@@ -19085,6 +19563,7 @@ const TrackElementView = ({
|
|
|
19085
19563
|
newStart = nextStart - span;
|
|
19086
19564
|
}
|
|
19087
19565
|
}
|
|
19566
|
+
newStart = Math.max(0, Math.min(newStart, duration - span));
|
|
19088
19567
|
return {
|
|
19089
19568
|
start: newStart,
|
|
19090
19569
|
end: newStart + span
|
|
@@ -19107,6 +19586,7 @@ const TrackElementView = ({
|
|
|
19107
19586
|
if (prevEnd !== null && !allowOverlap && newStart < prevEnd) {
|
|
19108
19587
|
newStart = prevEnd;
|
|
19109
19588
|
}
|
|
19589
|
+
newStart = Math.max(0, Math.min(newStart, prev.end - MIN_DURATION));
|
|
19110
19590
|
return {
|
|
19111
19591
|
start: newStart,
|
|
19112
19592
|
end: prev.end
|
|
@@ -19131,6 +19611,7 @@ const TrackElementView = ({
|
|
|
19131
19611
|
newEnd = nextStart;
|
|
19132
19612
|
}
|
|
19133
19613
|
}
|
|
19614
|
+
newEnd = Math.max(prev.start + MIN_DURATION, Math.min(newEnd, duration));
|
|
19134
19615
|
return {
|
|
19135
19616
|
start: prev.start,
|
|
19136
19617
|
end: newEnd
|
|
@@ -19168,7 +19649,7 @@ const TrackElementView = ({
|
|
|
19168
19649
|
};
|
|
19169
19650
|
const getElementColor = (elementType) => {
|
|
19170
19651
|
const colors = elementColors || ELEMENT_COLORS;
|
|
19171
|
-
const key = elementType === timeline.TIMELINE_ELEMENT_TYPE.VIDEO ? "video" : elementType === timeline.TIMELINE_ELEMENT_TYPE.AUDIO ? "audio" : elementType === timeline.TIMELINE_ELEMENT_TYPE.IMAGE ? "image" : elementType === timeline.TIMELINE_ELEMENT_TYPE.TEXT ? "text" : elementType === timeline.TIMELINE_ELEMENT_TYPE.CAPTION ? "caption" : elementType === timeline.TIMELINE_ELEMENT_TYPE.RECT ? "rect" : elementType === timeline.TIMELINE_ELEMENT_TYPE.CIRCLE ? "circle" : elementType === timeline.TIMELINE_ELEMENT_TYPE.ICON ? "icon" : elementType === timeline.TIMELINE_ELEMENT_TYPE.EFFECT ? "effect" : "element";
|
|
19652
|
+
const key = elementType === timeline.TIMELINE_ELEMENT_TYPE.VIDEO ? "video" : elementType === timeline.TIMELINE_ELEMENT_TYPE.AUDIO ? "audio" : elementType === timeline.TIMELINE_ELEMENT_TYPE.IMAGE ? "image" : elementType === timeline.TIMELINE_ELEMENT_TYPE.TEXT ? "text" : elementType === timeline.TIMELINE_ELEMENT_TYPE.CAPTION ? "caption" : elementType === timeline.TIMELINE_ELEMENT_TYPE.RECT ? "rect" : elementType === timeline.TIMELINE_ELEMENT_TYPE.CIRCLE ? "circle" : elementType === timeline.TIMELINE_ELEMENT_TYPE.ICON ? "icon" : elementType === timeline.TIMELINE_ELEMENT_TYPE.EMOJI ? "emoji" : elementType === timeline.TIMELINE_ELEMENT_TYPE.EFFECT ? "effect" : "element";
|
|
19172
19653
|
if (key in colors) {
|
|
19173
19654
|
return colors[key];
|
|
19174
19655
|
}
|
|
@@ -19178,6 +19659,16 @@ const TrackElementView = ({
|
|
|
19178
19659
|
return selectedIds.has(element.getId());
|
|
19179
19660
|
}, [selectedIds, element]);
|
|
19180
19661
|
const hasHandles = (selectedItem == null ? void 0 : selectedItem.getId()) === element.getId();
|
|
19662
|
+
const contextActionsEnabled = Boolean(
|
|
19663
|
+
onDeleteElement && onSplitElement && onContextMenuTarget
|
|
19664
|
+
);
|
|
19665
|
+
const handleContextMenu = (e3) => {
|
|
19666
|
+
if (!contextActionsEnabled) return;
|
|
19667
|
+
e3.preventDefault();
|
|
19668
|
+
e3.stopPropagation();
|
|
19669
|
+
onContextMenuTarget == null ? void 0 : onContextMenuTarget(element);
|
|
19670
|
+
setClipMenu({ x: e3.clientX, y: e3.clientY });
|
|
19671
|
+
};
|
|
19181
19672
|
const motionProps = {
|
|
19182
19673
|
ref,
|
|
19183
19674
|
className: `twick-track-element ${isSelected ? "twick-track-element-selected" : "twick-track-element-default"} ${isDragging2 ? "twick-track-element-dragging" : ""}`,
|
|
@@ -19198,6 +19689,7 @@ const TrackElementView = ({
|
|
|
19198
19689
|
onSelection(element, e3);
|
|
19199
19690
|
}
|
|
19200
19691
|
},
|
|
19692
|
+
onContextMenu: handleContextMenu,
|
|
19201
19693
|
style: {
|
|
19202
19694
|
backgroundColor: getElementColor(element.getType()),
|
|
19203
19695
|
width: `${(position.end - position.start) / duration * 100}%`,
|
|
@@ -19205,39 +19697,52 @@ const TrackElementView = ({
|
|
|
19205
19697
|
touchAction: "none"
|
|
19206
19698
|
}
|
|
19207
19699
|
};
|
|
19208
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
19209
|
-
|
|
19210
|
-
|
|
19211
|
-
{
|
|
19212
|
-
style: { touchAction: "none", zIndex: isSelected ? 100 : 1 },
|
|
19213
|
-
...bindStartHandle(),
|
|
19214
|
-
className: "twick-track-element-handle twick-track-element-handle-start"
|
|
19215
|
-
}
|
|
19216
|
-
) : null,
|
|
19217
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "twick-track-element-content", children: element.getType() === timeline.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() }),
|
|
19218
|
-
hasHandles ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
19219
|
-
"div",
|
|
19700
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(motion.div, { ...motionProps, children: [
|
|
19701
|
+
clipMenu && contextActionsEnabled ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
19702
|
+
TrackElementContextMenu,
|
|
19220
19703
|
{
|
|
19221
|
-
|
|
19222
|
-
|
|
19223
|
-
|
|
19704
|
+
x: clipMenu.x,
|
|
19705
|
+
y: clipMenu.y,
|
|
19706
|
+
canSplit: timeline.canSplitElement(element, currentTime),
|
|
19707
|
+
onSplit: () => onSplitElement == null ? void 0 : onSplitElement(element, currentTime),
|
|
19708
|
+
onDelete: () => onDeleteElement == null ? void 0 : onDeleteElement(element),
|
|
19709
|
+
onClose: () => setClipMenu(null)
|
|
19224
19710
|
}
|
|
19225
19711
|
) : null,
|
|
19226
|
-
|
|
19227
|
-
|
|
19712
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { touchAction: "none", height: "100%" }, ...bind(), children: [
|
|
19713
|
+
hasHandles ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
19228
19714
|
"div",
|
|
19229
19715
|
{
|
|
19230
|
-
|
|
19231
|
-
|
|
19232
|
-
|
|
19233
|
-
|
|
19234
|
-
|
|
19235
|
-
|
|
19236
|
-
|
|
19237
|
-
|
|
19238
|
-
|
|
19239
|
-
|
|
19240
|
-
|
|
19716
|
+
style: { touchAction: "none", zIndex: isSelected ? 100 : 1 },
|
|
19717
|
+
...bindStartHandle(),
|
|
19718
|
+
className: "twick-track-element-handle twick-track-element-handle-start"
|
|
19719
|
+
}
|
|
19720
|
+
) : null,
|
|
19721
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "twick-track-element-content", children: element.getType() === timeline.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() }),
|
|
19722
|
+
hasHandles ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
19723
|
+
"div",
|
|
19724
|
+
{
|
|
19725
|
+
style: { touchAction: "none", zIndex: isSelected ? 100 : 1 },
|
|
19726
|
+
...bindEndHandle(),
|
|
19727
|
+
className: "twick-track-element-handle twick-track-element-handle-end"
|
|
19728
|
+
}
|
|
19729
|
+
) : null,
|
|
19730
|
+
element.getFrameEffects ? element.getFrameEffects().map((frameEffect) => {
|
|
19731
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
19732
|
+
"div",
|
|
19733
|
+
{
|
|
19734
|
+
className: "twick-track-element-frame-effect",
|
|
19735
|
+
style: {
|
|
19736
|
+
backgroundColor: getElementColor("frameEffect"),
|
|
19737
|
+
width: `${(frameEffect.e - frameEffect.s) / element.getDuration() * 100}%`,
|
|
19738
|
+
left: `${frameEffect.s / element.getDuration() * 100}%`
|
|
19739
|
+
}
|
|
19740
|
+
},
|
|
19741
|
+
frameEffect.s + frameEffect.e
|
|
19742
|
+
);
|
|
19743
|
+
}) : null
|
|
19744
|
+
] })
|
|
19745
|
+
] });
|
|
19241
19746
|
};
|
|
19242
19747
|
const TrackBase = ({
|
|
19243
19748
|
duration,
|
|
@@ -19250,11 +19755,21 @@ const TrackBase = ({
|
|
|
19250
19755
|
onDrag,
|
|
19251
19756
|
allowOverlap = false,
|
|
19252
19757
|
onDragStateChange,
|
|
19253
|
-
elementColors
|
|
19758
|
+
elementColors,
|
|
19759
|
+
currentTime,
|
|
19760
|
+
onContextMenuTarget,
|
|
19761
|
+
onDeleteElement,
|
|
19762
|
+
onSplitElement
|
|
19254
19763
|
}) => {
|
|
19255
19764
|
const trackRef = React.useRef(null);
|
|
19256
19765
|
const trackWidthStyle = `${Math.max(100, duration * zoom * 100)}px`;
|
|
19257
|
-
const elements = track.getElements()
|
|
19766
|
+
const elements = [...track.getElements()].sort((a2, b2) => {
|
|
19767
|
+
const byStart = a2.getStart() - b2.getStart();
|
|
19768
|
+
if (byStart !== 0) return byStart;
|
|
19769
|
+
const byEnd = a2.getEnd() - b2.getEnd();
|
|
19770
|
+
if (byEnd !== 0) return byEnd;
|
|
19771
|
+
return a2.getId().localeCompare(b2.getId());
|
|
19772
|
+
});
|
|
19258
19773
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
19259
19774
|
"div",
|
|
19260
19775
|
{
|
|
@@ -19276,6 +19791,10 @@ const TrackBase = ({
|
|
|
19276
19791
|
onDrag,
|
|
19277
19792
|
onDragStateChange,
|
|
19278
19793
|
elementColors,
|
|
19794
|
+
currentTime,
|
|
19795
|
+
onContextMenuTarget,
|
|
19796
|
+
onDeleteElement,
|
|
19797
|
+
onSplitElement,
|
|
19279
19798
|
nextStart: index < elements.length - 1 ? elements[index + 1].getStart() : null,
|
|
19280
19799
|
prevEnd: index > 0 ? elements[index - 1].getEnd() : 0
|
|
19281
19800
|
},
|
|
@@ -19580,7 +20099,11 @@ function TimelineView({
|
|
|
19580
20099
|
onDropOnTimeline,
|
|
19581
20100
|
videoResolution,
|
|
19582
20101
|
enableDropOnTimeline = true,
|
|
19583
|
-
chapters = []
|
|
20102
|
+
chapters = [],
|
|
20103
|
+
currentTime = 0,
|
|
20104
|
+
onContextMenuTarget,
|
|
20105
|
+
onDeleteElement,
|
|
20106
|
+
onSplitElement
|
|
19584
20107
|
}) {
|
|
19585
20108
|
const containerRef = React.useRef(null);
|
|
19586
20109
|
const seekContainerRef = React.useRef(null);
|
|
@@ -19849,7 +20372,11 @@ function TimelineView({
|
|
|
19849
20372
|
onDragStateChange: (isDragging2, el) => {
|
|
19850
20373
|
setDraggingElementId(isDragging2 && el ? el.getId() : null);
|
|
19851
20374
|
},
|
|
19852
|
-
elementColors
|
|
20375
|
+
elementColors,
|
|
20376
|
+
currentTime,
|
|
20377
|
+
onContextMenuTarget,
|
|
20378
|
+
onDeleteElement,
|
|
20379
|
+
onSplitElement
|
|
19853
20380
|
}
|
|
19854
20381
|
)
|
|
19855
20382
|
] }),
|
|
@@ -19908,7 +20435,8 @@ const useTimelineManager = () => {
|
|
|
19908
20435
|
if (dragType === DRAG_TYPE.START) {
|
|
19909
20436
|
if (element instanceof timeline.VideoElement || element instanceof timeline.AudioElement) {
|
|
19910
20437
|
const elementProps = element.getProps();
|
|
19911
|
-
const
|
|
20438
|
+
const playbackRate = (elementProps == null ? void 0 : elementProps.playbackRate) || 1;
|
|
20439
|
+
const delta = (updates.start - element.getStart()) * playbackRate;
|
|
19912
20440
|
if (element instanceof timeline.AudioElement) {
|
|
19913
20441
|
element.setStartAt(element.getStartAt() + delta);
|
|
19914
20442
|
} else {
|
|
@@ -20021,6 +20549,38 @@ const useTimelineManager = () => {
|
|
|
20021
20549
|
totalDuration
|
|
20022
20550
|
};
|
|
20023
20551
|
};
|
|
20552
|
+
const useTimelineControl = () => {
|
|
20553
|
+
const { editor, setSelectedItem, selectedIds } = timeline.useTimelineContext();
|
|
20554
|
+
const deleteItem = (item) => {
|
|
20555
|
+
var _a;
|
|
20556
|
+
const tracks = ((_a = editor.getTimelineData()) == null ? void 0 : _a.tracks) ?? [];
|
|
20557
|
+
const toDelete = item !== void 0 ? [item] : timeline.resolveIds(selectedIds, tracks);
|
|
20558
|
+
for (const el of toDelete) {
|
|
20559
|
+
if (el instanceof timeline.Track) {
|
|
20560
|
+
editor.removeTrack(el);
|
|
20561
|
+
} else if (el instanceof timeline.TrackElement) {
|
|
20562
|
+
editor.removeElement(el);
|
|
20563
|
+
}
|
|
20564
|
+
}
|
|
20565
|
+
setSelectedItem(null);
|
|
20566
|
+
};
|
|
20567
|
+
const splitElement = (element, currentTime) => {
|
|
20568
|
+
if (!timeline.canSplitElement(element, currentTime)) return;
|
|
20569
|
+
void editor.splitElement(element, currentTime);
|
|
20570
|
+
};
|
|
20571
|
+
const handleUndo = () => {
|
|
20572
|
+
editor.undo();
|
|
20573
|
+
};
|
|
20574
|
+
const handleRedo = () => {
|
|
20575
|
+
editor.redo();
|
|
20576
|
+
};
|
|
20577
|
+
return {
|
|
20578
|
+
splitElement,
|
|
20579
|
+
deleteItem,
|
|
20580
|
+
handleUndo,
|
|
20581
|
+
handleRedo
|
|
20582
|
+
};
|
|
20583
|
+
};
|
|
20024
20584
|
function useTimelineSelection() {
|
|
20025
20585
|
const { editor, selectedIds, setSelection, setSelectedItem } = timeline.useTimelineContext();
|
|
20026
20586
|
const handleItemSelect = React.useCallback(
|
|
@@ -20101,8 +20661,9 @@ const TimelineManager = ({
|
|
|
20101
20661
|
elementColors
|
|
20102
20662
|
}) => {
|
|
20103
20663
|
var _a, _b;
|
|
20104
|
-
const { playerState } = livePlayer.useLivePlayerContext();
|
|
20664
|
+
const { playerState, currentTime } = livePlayer.useLivePlayerContext();
|
|
20105
20665
|
const { followPlayheadEnabled, editor, videoResolution, setSelectedItem } = timeline.useTimelineContext();
|
|
20666
|
+
const { deleteItem, splitElement } = useTimelineControl();
|
|
20106
20667
|
const {
|
|
20107
20668
|
timelineData,
|
|
20108
20669
|
totalDuration,
|
|
@@ -20123,6 +20684,12 @@ const TimelineManager = ({
|
|
|
20123
20684
|
setPlayheadState(state);
|
|
20124
20685
|
}, []);
|
|
20125
20686
|
const isPlayheadActive = followPlayheadEnabled && playerState === livePlayer.PLAYER_STATE.PLAYING || playheadState.isDragging;
|
|
20687
|
+
const handleContextMenuTarget = React.useCallback(
|
|
20688
|
+
(element) => {
|
|
20689
|
+
setSelectedItem(element);
|
|
20690
|
+
},
|
|
20691
|
+
[setSelectedItem]
|
|
20692
|
+
);
|
|
20126
20693
|
const handleDropOnTimeline = React.useCallback(
|
|
20127
20694
|
async (params) => {
|
|
20128
20695
|
const { track, timeSec, type, url } = params;
|
|
@@ -20170,6 +20737,10 @@ const TimelineManager = ({
|
|
|
20170
20737
|
onEmptyClick: handleEmptyClick,
|
|
20171
20738
|
onMarqueeSelect: handleMarqueeSelect,
|
|
20172
20739
|
elementColors,
|
|
20740
|
+
currentTime,
|
|
20741
|
+
onContextMenuTarget: handleContextMenuTarget,
|
|
20742
|
+
onDeleteElement: (el) => deleteItem(el),
|
|
20743
|
+
onSplitElement: (el, t2) => splitElement(el, t2),
|
|
20173
20744
|
playheadPositionPx: playheadState.positionPx,
|
|
20174
20745
|
isPlayheadActive,
|
|
20175
20746
|
chapters: ((_a = timelineData == null ? void 0 : timelineData.metadata) == null ? void 0 : _a.chapters) ?? [],
|
|
@@ -20253,11 +20824,12 @@ const PlayerControls = ({
|
|
|
20253
20824
|
}
|
|
20254
20825
|
}, [selectedIds.size, onDelete]);
|
|
20255
20826
|
const hasSelection = selectedIds.size > 0;
|
|
20827
|
+
const canSplitSelected = selectedItem instanceof timeline.TrackElement ? timeline.canSplitElement(selectedItem, currentTime) : false;
|
|
20256
20828
|
const handleSplit = React.useCallback(() => {
|
|
20257
|
-
if (selectedItem instanceof timeline.TrackElement && onSplit) {
|
|
20829
|
+
if (selectedItem instanceof timeline.TrackElement && onSplit && canSplitSelected) {
|
|
20258
20830
|
onSplit(selectedItem, currentTime);
|
|
20259
20831
|
}
|
|
20260
|
-
}, [selectedItem, onSplit, currentTime]);
|
|
20832
|
+
}, [selectedItem, onSplit, currentTime, canSplitSelected]);
|
|
20261
20833
|
const handleZoomIn = React.useCallback(() => {
|
|
20262
20834
|
if (setZoomLevel && zoomLevel < MAX_ZOOM) {
|
|
20263
20835
|
setZoomLevel(zoomLevel + ZOOM_STEP);
|
|
@@ -20284,9 +20856,9 @@ const PlayerControls = ({
|
|
|
20284
20856
|
"button",
|
|
20285
20857
|
{
|
|
20286
20858
|
onClick: handleSplit,
|
|
20287
|
-
disabled: !
|
|
20859
|
+
disabled: !canSplitSelected,
|
|
20288
20860
|
title: "Split",
|
|
20289
|
-
className: `control-btn split-btn ${!
|
|
20861
|
+
className: `control-btn split-btn ${!canSplitSelected ? "btn-disabled" : ""}`,
|
|
20290
20862
|
children: /* @__PURE__ */ jsxRuntime.jsx(Scissors, { className: "icon-md" })
|
|
20291
20863
|
}
|
|
20292
20864
|
),
|
|
@@ -20400,37 +20972,6 @@ const usePlayerControl = () => {
|
|
|
20400
20972
|
togglePlayback
|
|
20401
20973
|
};
|
|
20402
20974
|
};
|
|
20403
|
-
const useTimelineControl = () => {
|
|
20404
|
-
const { editor, setSelectedItem, selectedIds } = timeline.useTimelineContext();
|
|
20405
|
-
const deleteItem = (item) => {
|
|
20406
|
-
var _a;
|
|
20407
|
-
const tracks = ((_a = editor.getTimelineData()) == null ? void 0 : _a.tracks) ?? [];
|
|
20408
|
-
const toDelete = item !== void 0 ? [item] : timeline.resolveIds(selectedIds, tracks);
|
|
20409
|
-
for (const el of toDelete) {
|
|
20410
|
-
if (el instanceof timeline.Track) {
|
|
20411
|
-
editor.removeTrack(el);
|
|
20412
|
-
} else if (el instanceof timeline.TrackElement) {
|
|
20413
|
-
editor.removeElement(el);
|
|
20414
|
-
}
|
|
20415
|
-
}
|
|
20416
|
-
setSelectedItem(null);
|
|
20417
|
-
};
|
|
20418
|
-
const splitElement = (element, currentTime) => {
|
|
20419
|
-
editor.splitElement(element, currentTime);
|
|
20420
|
-
};
|
|
20421
|
-
const handleUndo = () => {
|
|
20422
|
-
editor.undo();
|
|
20423
|
-
};
|
|
20424
|
-
const handleRedo = () => {
|
|
20425
|
-
editor.redo();
|
|
20426
|
-
};
|
|
20427
|
-
return {
|
|
20428
|
-
splitElement,
|
|
20429
|
-
deleteItem,
|
|
20430
|
-
handleUndo,
|
|
20431
|
-
handleRedo
|
|
20432
|
-
};
|
|
20433
|
-
};
|
|
20434
20975
|
function shouldIgnoreKeydown() {
|
|
20435
20976
|
const active = document.activeElement;
|
|
20436
20977
|
if (!active) return false;
|