@twick/timeline 0.14.3 → 0.14.4

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/index.mjs CHANGED
@@ -482,7 +482,9 @@ class TrackElement {
482
482
  this.type = type;
483
483
  this.props = {
484
484
  x: 0,
485
- y: 0
485
+ y: 0,
486
+ opacity: 1,
487
+ rotation: 0
486
488
  };
487
489
  }
488
490
  getId() {
@@ -519,6 +521,12 @@ class TrackElement {
519
521
  y: ((_b = this.props) == null ? void 0 : _b.y) ?? 0
520
522
  };
521
523
  }
524
+ getRotation() {
525
+ return this.props.rotation ?? 0;
526
+ }
527
+ getOpacity() {
528
+ return this.props.opacity ?? 1;
529
+ }
522
530
  setId(id) {
523
531
  this.id = id;
524
532
  return this;
@@ -552,6 +560,14 @@ class TrackElement {
552
560
  this.props.y = position.y;
553
561
  return this;
554
562
  }
563
+ setRotation(rotation) {
564
+ this.props.rotation = rotation;
565
+ return this;
566
+ }
567
+ setOpacity(opacity) {
568
+ this.props.opacity = opacity;
569
+ return this;
570
+ }
555
571
  setProps(props) {
556
572
  this.props = structuredClone(props);
557
573
  return this;
@@ -1040,13 +1056,35 @@ class CaptionElement extends TrackElement {
1040
1056
  }
1041
1057
  }
1042
1058
  class IconElement extends TrackElement {
1043
- constructor(src, size) {
1059
+ constructor(src, size, fill = "#866bbf") {
1044
1060
  super(TIMELINE_ELEMENT_TYPE.ICON);
1045
1061
  this.props = {
1046
1062
  src,
1063
+ fill,
1047
1064
  size
1048
1065
  };
1049
1066
  }
1067
+ getSrc() {
1068
+ return this.props.src;
1069
+ }
1070
+ getFill() {
1071
+ return this.props.fill;
1072
+ }
1073
+ getSize() {
1074
+ return this.props.size;
1075
+ }
1076
+ setSrc(src) {
1077
+ this.props.src = src;
1078
+ return this;
1079
+ }
1080
+ setFill(fill) {
1081
+ this.props.fill = fill;
1082
+ return this;
1083
+ }
1084
+ setSize(size) {
1085
+ this.props.size = size;
1086
+ return this;
1087
+ }
1050
1088
  accept(visitor) {
1051
1089
  return visitor.visitIconElement(this);
1052
1090
  }
@@ -1056,7 +1094,9 @@ class CircleElement extends TrackElement {
1056
1094
  super(TIMELINE_ELEMENT_TYPE.CIRCLE);
1057
1095
  this.props = {
1058
1096
  radius,
1059
- fill
1097
+ fill,
1098
+ strokeColor: fill,
1099
+ lineWidth: 1
1060
1100
  };
1061
1101
  }
1062
1102
  getFill() {
@@ -1065,6 +1105,12 @@ class CircleElement extends TrackElement {
1065
1105
  getRadius() {
1066
1106
  return this.props.radius;
1067
1107
  }
1108
+ getStrokeColor() {
1109
+ return this.props.strokeColor || this.props.fill;
1110
+ }
1111
+ getLineWidth() {
1112
+ return this.props.lineWidth ?? 0;
1113
+ }
1068
1114
  setFill(fill) {
1069
1115
  this.props.fill = fill;
1070
1116
  return this;
@@ -1073,6 +1119,14 @@ class CircleElement extends TrackElement {
1073
1119
  this.props.radius = radius;
1074
1120
  return this;
1075
1121
  }
1122
+ setStrokeColor(strokeColor) {
1123
+ this.props.strokeColor = strokeColor;
1124
+ return this;
1125
+ }
1126
+ setLineWidth(lineWidth) {
1127
+ this.props.lineWidth = lineWidth;
1128
+ return this;
1129
+ }
1076
1130
  accept(visitor) {
1077
1131
  return visitor.visitCircleElement(this);
1078
1132
  }
@@ -1083,18 +1137,48 @@ class RectElement extends TrackElement {
1083
1137
  this.props = {
1084
1138
  width: size.width,
1085
1139
  height: size.height,
1086
- fill
1140
+ fill,
1141
+ radius: 0,
1142
+ strokeColor: fill,
1143
+ lineWidth: 1
1087
1144
  };
1088
1145
  }
1146
+ getFill() {
1147
+ return this.props.fill;
1148
+ }
1089
1149
  setFill(fill) {
1090
1150
  this.props.fill = fill;
1091
1151
  return this;
1092
1152
  }
1153
+ getSize() {
1154
+ return { width: this.props.width, height: this.props.height };
1155
+ }
1156
+ getCornerRadius() {
1157
+ return this.props.radius;
1158
+ }
1159
+ getStrokeColor() {
1160
+ return this.props.strokeColor || this.props.fill;
1161
+ }
1162
+ getLineWidth() {
1163
+ return this.props.lineWidth ?? 0;
1164
+ }
1093
1165
  setSize(size) {
1094
1166
  this.props.width = size.width;
1095
1167
  this.props.height = size.height;
1096
1168
  return this;
1097
1169
  }
1170
+ setCornerRadius(cornerRadius) {
1171
+ this.props.radius = cornerRadius;
1172
+ return this;
1173
+ }
1174
+ setStrokeColor(strokeColor) {
1175
+ this.props.strokeColor = strokeColor;
1176
+ return this;
1177
+ }
1178
+ setLineWidth(lineWidth) {
1179
+ this.props.lineWidth = lineWidth;
1180
+ return this;
1181
+ }
1098
1182
  accept(visitor) {
1099
1183
  return visitor.visitRectElement(this);
1100
1184
  }
@@ -1103,6 +1187,7 @@ class ElementAnimation {
1103
1187
  constructor(name) {
1104
1188
  __publicField(this, "name");
1105
1189
  __publicField(this, "interval");
1190
+ __publicField(this, "duration");
1106
1191
  __publicField(this, "intensity");
1107
1192
  __publicField(this, "animate");
1108
1193
  __publicField(this, "mode");
@@ -1115,6 +1200,9 @@ class ElementAnimation {
1115
1200
  getInterval() {
1116
1201
  return this.interval;
1117
1202
  }
1203
+ getDuration() {
1204
+ return this.duration;
1205
+ }
1118
1206
  getIntensity() {
1119
1207
  return this.intensity;
1120
1208
  }
@@ -1131,6 +1219,10 @@ class ElementAnimation {
1131
1219
  this.interval = interval;
1132
1220
  return this;
1133
1221
  }
1222
+ setDuration(duration) {
1223
+ this.duration = duration;
1224
+ return this;
1225
+ }
1134
1226
  setIntensity(intensity) {
1135
1227
  this.intensity = intensity;
1136
1228
  return this;
@@ -1151,6 +1243,7 @@ class ElementAnimation {
1151
1243
  return {
1152
1244
  name: this.name,
1153
1245
  interval: this.interval,
1246
+ duration: this.duration,
1154
1247
  intensity: this.intensity,
1155
1248
  animate: this.animate,
1156
1249
  mode: this.mode,
@@ -1160,6 +1253,7 @@ class ElementAnimation {
1160
1253
  static fromJSON(json) {
1161
1254
  const animation = new ElementAnimation(json.name);
1162
1255
  animation.setInterval(json.interval);
1256
+ animation.setDuration(json.duration);
1163
1257
  animation.setIntensity(json.intensity);
1164
1258
  animation.setAnimate(json.animate);
1165
1259
  animation.setMode(json.mode);
@@ -1245,7 +1339,7 @@ class ElementTextEffect {
1245
1339
  return {
1246
1340
  name: this.name,
1247
1341
  delay: this.delay,
1248
- duration: this.duration,
1342
+ duration: this.duration ?? 1,
1249
1343
  bufferTime: this.bufferTime
1250
1344
  };
1251
1345
  }
@@ -1313,11 +1407,12 @@ class ElementDeserializer {
1313
1407
  return captionElement;
1314
1408
  }
1315
1409
  static deserializeIconElement(json) {
1316
- var _a, _b;
1317
- const size = ((_a = json.props) == null ? void 0 : _a.size) ? { width: json.props.size[0], height: json.props.size[1] } : { width: 0, height: 0 };
1410
+ var _a, _b, _c;
1411
+ const size = ((_a = json.props) == null ? void 0 : _a.size) ?? { width: 100, height: 100 };
1318
1412
  const iconElement = new IconElement(
1319
1413
  ((_b = json.props) == null ? void 0 : _b.src) || "",
1320
- size
1414
+ size,
1415
+ (_c = json.props) == null ? void 0 : _c.fill
1321
1416
  );
1322
1417
  ElementDeserializer.deserializeBaseElement(iconElement, json);
1323
1418
  return iconElement;
@@ -1553,10 +1648,6 @@ class ElementValidator {
1553
1648
  const basicValidation = this.validateBasicProperties(element);
1554
1649
  const errors = [...basicValidation.errors];
1555
1650
  const warnings = [...basicValidation.warnings];
1556
- const props = element.getProps();
1557
- if (!(props == null ? void 0 : props.icon)) {
1558
- errors.push("Icon element must have an icon name");
1559
- }
1560
1651
  return { errors, warnings };
1561
1652
  }
1562
1653
  validateCircleElement(element) {
@@ -1712,15 +1803,16 @@ class Track {
1712
1803
  * Creates a new Track instance.
1713
1804
  *
1714
1805
  * @param name - The display name for the track
1806
+ * @param type - The type of the track
1715
1807
  * @param id - Optional unique identifier (auto-generated if not provided)
1716
1808
  *
1717
1809
  * @example
1718
1810
  * ```js
1719
1811
  * const track = new Track("My Video Track");
1720
- * const trackWithId = new Track("Audio Track", "audio-track-1");
1812
+ * const trackWithId = new Track("Audio Track", "element", "video-track-1");
1721
1813
  * ```
1722
1814
  */
1723
- constructor(name, id) {
1815
+ constructor(name, type = "element", id) {
1724
1816
  __publicField(this, "id");
1725
1817
  __publicField(this, "name");
1726
1818
  __publicField(this, "type");
@@ -1728,7 +1820,7 @@ class Track {
1728
1820
  __publicField(this, "validator");
1729
1821
  this.name = name;
1730
1822
  this.id = id ?? `t-${generateShortUuid}`;
1731
- this.type = "element";
1823
+ this.type = type;
1732
1824
  this.elements = [];
1733
1825
  this.validator = new ElementValidator();
1734
1826
  }
@@ -1819,7 +1911,7 @@ class Track {
1819
1911
  *
1820
1912
  * @example
1821
1913
  * ```js
1822
- * const track = new Track("My Track", "track-123");
1914
+ * const track = new Track("My Track", "element", "track-123");
1823
1915
  * const id = track.getId(); // "track-123"
1824
1916
  * ```
1825
1917
  */
@@ -2161,7 +2253,7 @@ class Track {
2161
2253
  * ```
2162
2254
  */
2163
2255
  static fromJSON(json) {
2164
- const track = new Track(json.name, json.id);
2256
+ const track = new Track(json.name, json.type ?? "element", json.id);
2165
2257
  track.type = json.type;
2166
2258
  track.elements = (json.elements || []).map(ElementDeserializer.fromJSON);
2167
2259
  return track;
@@ -2583,7 +2675,8 @@ class ElementCloner {
2583
2675
  visitIconElement(element) {
2584
2676
  const clonedElement = new IconElement(
2585
2677
  element.getProps().src,
2586
- element.getProps().size
2678
+ element.getProps().size,
2679
+ element.getProps().fill
2587
2680
  );
2588
2681
  this.cloneElementProperties(element, clonedElement);
2589
2682
  return clonedElement;
@@ -2772,10 +2865,10 @@ class TimelineEditor {
2772
2865
  this.context.updateChangeLog();
2773
2866
  return updatedTimelineData;
2774
2867
  }
2775
- addTrack(name) {
2868
+ addTrack(name, type = "element") {
2776
2869
  const prevTimelineData = this.getTimelineData();
2777
2870
  const id = `t-${generateShortUuid()}`;
2778
- const track = new Track(name, id);
2871
+ const track = new Track(name, type, id);
2779
2872
  const updatedTimelines = [...(prevTimelineData == null ? void 0 : prevTimelineData.tracks) || [], track];
2780
2873
  this.setTimelineData(updatedTimelines);
2781
2874
  return track;
@@ -2862,12 +2955,12 @@ class TimelineEditor {
2862
2955
  /**
2863
2956
  * Update an element in a specific track using the visitor pattern
2864
2957
  * @param element The updated element
2865
- * @returns boolean true if element was updated successfully
2958
+ * @returns TrackElement the updated element
2866
2959
  */
2867
2960
  updateElement(element) {
2868
2961
  const track = this.getTrackById(element.getTrackId());
2869
2962
  if (!track) {
2870
- return false;
2963
+ return element;
2871
2964
  }
2872
2965
  try {
2873
2966
  const elementUpdater = new ElementUpdater(track);
@@ -2878,9 +2971,9 @@ class TimelineEditor {
2878
2971
  this.setTimelineData(currentData.tracks);
2879
2972
  }
2880
2973
  }
2881
- return result;
2974
+ return element;
2882
2975
  } catch (error) {
2883
- return false;
2976
+ return element;
2884
2977
  }
2885
2978
  }
2886
2979
  /**
@@ -7693,6 +7786,7 @@ const TimelineContext = createContext(
7693
7786
  const TimelineProviderInner = ({
7694
7787
  contextId,
7695
7788
  children,
7789
+ resolution,
7696
7790
  initialData
7697
7791
  }) => {
7698
7792
  const [timelineAction, setTimelineActionState] = useState({
@@ -7702,6 +7796,7 @@ const TimelineProviderInner = ({
7702
7796
  const [selectedItem, setSelectedItem] = useState(
7703
7797
  null
7704
7798
  );
7799
+ const [videoResolution, setVideoResolution] = useState(resolution ?? { width: 720, height: 1280 });
7705
7800
  const [totalDuration, setTotalDuration] = useState(0);
7706
7801
  const [changeLog, setChangeLog] = useState(0);
7707
7802
  const undoRedoContext = useUndoRedo();
@@ -7756,9 +7851,11 @@ const TimelineProviderInner = ({
7756
7851
  timelineAction,
7757
7852
  totalDuration,
7758
7853
  changeLog,
7854
+ videoResolution,
7759
7855
  present: undoRedoContext.present,
7760
7856
  canUndo: undoRedoContext.canUndo,
7761
7857
  canRedo: undoRedoContext.canRedo,
7858
+ setVideoResolution,
7762
7859
  setSelectedItem,
7763
7860
  setTimelineAction,
7764
7861
  editor
@@ -7769,6 +7866,7 @@ const TimelineProviderInner = ({
7769
7866
  const TimelineProvider = ({
7770
7867
  contextId,
7771
7868
  children,
7869
+ resolution = { width: 720, height: 1280 },
7772
7870
  initialData,
7773
7871
  undoRedoPersistenceKey,
7774
7872
  maxHistorySize
@@ -7790,6 +7888,7 @@ const TimelineProvider = ({
7790
7888
  children: /* @__PURE__ */ jsx(
7791
7889
  TimelineProviderInner,
7792
7890
  {
7891
+ resolution,
7793
7892
  initialData,
7794
7893
  contextId,
7795
7894
  undoRedoPersistenceKey,