@twick/video-editor 0.14.4 → 0.14.6

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.
@@ -1,9 +1,12 @@
1
1
 
2
- export declare const PlayerManager: ({ videoProps, canvasMode, }: {
2
+ export declare const PlayerManager: ({ videoProps, playerProps, canvasMode, }: {
3
3
  videoProps: {
4
4
  width: number;
5
5
  height: number;
6
6
  backgroundColor?: string;
7
7
  };
8
+ playerProps?: {
9
+ quality?: number;
10
+ };
8
11
  canvasMode: boolean;
9
12
  }) => import("react/jsx-runtime").JSX.Element;
@@ -1,5 +1,4 @@
1
- declare const TimelineManager: ({ timelineControls, trackZoom, }: {
2
- timelineControls?: React.ReactNode;
1
+ declare const TimelineManager: ({ trackZoom, }: {
3
2
  trackZoom: number;
4
3
  }) => import("react/jsx-runtime").JSX.Element;
5
4
  export default TimelineManager;
@@ -1,7 +1,6 @@
1
1
  import { Track, TrackElement } from '@twick/timeline';
2
2
 
3
3
  declare function TimelineView({ zoomLevel, selectedItem, duration, tracks, seekTrack, onAddTrack, onReorder, onSelectionChange, onElementDrag, }: {
4
- timelineControls?: React.ReactNode;
5
4
  zoomLevel: number;
6
5
  duration: number;
7
6
  tracks: Track[];
@@ -22,6 +22,11 @@ export interface VideoEditorConfig {
22
22
  /** Background color of the video */
23
23
  backgroundColor?: string;
24
24
  };
25
+ playerProps?: {
26
+ quality?: number;
27
+ maxWidth?: number;
28
+ maxHeight?: number;
29
+ };
25
30
  /** Whether to use canvas mode for rendering */
26
31
  canvasMode?: boolean;
27
32
  }
@@ -50,8 +55,6 @@ export interface VideoEditorProps {
50
55
  rightPanel?: React.ReactNode;
51
56
  /** Custom bottom panel component (e.g., effects library) */
52
57
  bottomPanel?: React.ReactNode;
53
- /** Custom play controls component */
54
- playControls?: React.ReactNode;
55
58
  /** Whether to show default play controls if no custom controls provided */
56
59
  defaultPlayControls?: boolean;
57
60
  /** Editor configuration including video properties and mode settings */
package/dist/index.js CHANGED
@@ -6958,8 +6958,8 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
6958
6958
  };
6959
6959
  const convertToVideoPosition = (x2, y2, canvasMetadata, videoSize) => {
6960
6960
  return {
6961
- x: x2 / canvasMetadata.scaleX - videoSize.width / 2,
6962
- y: y2 / canvasMetadata.scaleY - videoSize.height / 2
6961
+ x: Number((x2 / canvasMetadata.scaleX - videoSize.width / 2).toFixed(2)),
6962
+ y: Number((y2 / canvasMetadata.scaleY - videoSize.height / 2).toFixed(2))
6963
6963
  };
6964
6964
  };
6965
6965
  const getCurrentFrameEffect = (item, seekTime) => {
@@ -6994,7 +6994,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
6994
6994
  ctx.save();
6995
6995
  ctx.translate(left, top);
6996
6996
  ctx.fillStyle = "#red";
6997
- ctx.fillRect(-0 / 2, -0 / 2, size, size);
6997
+ ctx.fillRect(-size / 2, -size / 2, size, size);
6998
6998
  ctx.restore();
6999
6999
  }
7000
7000
  });
@@ -7837,7 +7837,8 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
7837
7837
  videoProps
7838
7838
  }) => {
7839
7839
  const [projectData, setProjectData] = React.useState(null);
7840
- const { timelineAction, setTimelineAction, setSelectedItem, editor } = timeline.useTimelineContext();
7840
+ const { timelineAction, setTimelineAction, setSelectedItem, editor, changeLog } = timeline.useTimelineContext();
7841
+ const currentChangeLog = React.useRef(changeLog);
7841
7842
  const [playerUpdating, setPlayerUpdating] = React.useState(false);
7842
7843
  const handleCanvasReady = (canvas) => {
7843
7844
  console.log("canvas ready", canvas);
@@ -7851,6 +7852,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
7851
7852
  case CANVAS_OPERATIONS.ITEM_UPDATED:
7852
7853
  if (element) {
7853
7854
  const updatedElement = editor.updateElement(element);
7855
+ currentChangeLog.current = currentChangeLog.current + 1;
7854
7856
  setSelectedItem(updatedElement);
7855
7857
  }
7856
7858
  break;
@@ -7862,6 +7864,9 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
7862
7864
  });
7863
7865
  const updateCanvas = (seekTime) => {
7864
7866
  var _a2;
7867
+ if (changeLog === currentChangeLog.current) {
7868
+ return;
7869
+ }
7865
7870
  const elements = timeline.getCurrentElements(
7866
7871
  seekTime,
7867
7872
  ((_a2 = editor.getTimelineData()) == null ? void 0 : _a2.tracks) ?? []
@@ -7872,6 +7877,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
7872
7877
  captionProps: {},
7873
7878
  cleanAndAdd: true
7874
7879
  });
7880
+ currentChangeLog.current = changeLog;
7875
7881
  };
7876
7882
  const onPlayerUpdate = (event) => {
7877
7883
  var _a2;
@@ -7913,6 +7919,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
7913
7919
  };
7914
7920
  const PlayerManager = ({
7915
7921
  videoProps,
7922
+ playerProps,
7916
7923
  canvasMode
7917
7924
  }) => {
7918
7925
  const { changeLog } = timeline.useTimelineContext();
@@ -7979,6 +7986,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
7979
7986
  {
7980
7987
  seekTime,
7981
7988
  projectData,
7989
+ quality: playerProps == null ? void 0 : playerProps.quality,
7982
7990
  videoSize: {
7983
7991
  width: videoProps.width,
7984
7992
  height: videoProps.height
@@ -12548,7 +12556,7 @@ This message will only show in development mode. It won't appear in production.
12548
12556
  envelope = (undampedFreq2) => {
12549
12557
  const a2 = Math.exp(-undampedFreq2 * duration);
12550
12558
  const b2 = (undampedFreq2 - velocity) * duration + 1;
12551
- return -1e-3 + a2 * b2;
12559
+ return -safeMin + a2 * b2;
12552
12560
  };
12553
12561
  derivative = (undampedFreq2) => {
12554
12562
  const a2 = Math.exp(-undampedFreq2 * duration);
@@ -17416,7 +17424,6 @@ This message will only show in development mode. It won't appear in production.
17416
17424
  };
17417
17425
  };
17418
17426
  const TimelineManager = ({
17419
- timelineControls,
17420
17427
  trackZoom
17421
17428
  }) => {
17422
17429
  var _a2;
@@ -17424,7 +17431,6 @@ This message will only show in development mode. It won't appear in production.
17424
17431
  return /* @__PURE__ */ jsxRuntime.jsx(
17425
17432
  TimelineView,
17426
17433
  {
17427
- timelineControls,
17428
17434
  tracks: (timelineData == null ? void 0 : timelineData.tracks) ?? [],
17429
17435
  zoomLevel: trackZoom,
17430
17436
  duration: totalDuration,
@@ -17514,67 +17520,67 @@ This message will only show in development mode. It won't appear in production.
17514
17520
  setZoomLevel(zoomLevel - ZOOM_STEP);
17515
17521
  }
17516
17522
  }, [zoomLevel, setZoomLevel]);
17517
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `h-16 bg-gray-800 border-t border-gray-700 p-4 ${className}`, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
17518
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-4", children: [
17519
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
17520
- /* @__PURE__ */ jsxRuntime.jsx(
17521
- "button",
17522
- {
17523
- onClick: handleDelete,
17524
- disabled: !selectedItem,
17525
- title: "Delete",
17526
- className: `btn btn-ghost ${!!selectedItem ? "text-red-400 hover:text-red-300" : "text-gray-500 cursor-not-allowed"}`,
17527
- children: /* @__PURE__ */ jsxRuntime.jsx(Trash2, { className: "w-5 h-5" })
17528
- }
17529
- ),
17530
- /* @__PURE__ */ jsxRuntime.jsx(
17531
- "button",
17532
- {
17533
- onClick: handleSplit,
17534
- disabled: !(selectedItem instanceof timeline.TrackElement),
17535
- title: "Split",
17536
- className: `btn btn-ghost ${selectedItem instanceof timeline.TrackElement ? "text-purple-400 hover:text-purple-300" : "text-gray-500 cursor-not-allowed"}`,
17537
- children: /* @__PURE__ */ jsxRuntime.jsx(Scissors, { className: "w-5 h-5" })
17538
- }
17539
- ),
17540
- /* @__PURE__ */ jsxRuntime.jsx(
17541
- UndoRedoControls,
17542
- {
17543
- canUndo,
17544
- canRedo,
17545
- onUndo,
17546
- onRedo
17547
- }
17548
- )
17549
- ] }),
17523
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `player-controls ${className}`, children: [
17524
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "edit-controls", children: [
17525
+ /* @__PURE__ */ jsxRuntime.jsx(
17526
+ "button",
17527
+ {
17528
+ onClick: handleDelete,
17529
+ disabled: !selectedItem,
17530
+ title: "Delete",
17531
+ className: `control-btn delete-btn ${!selectedItem ? "btn-disabled" : ""}`,
17532
+ children: /* @__PURE__ */ jsxRuntime.jsx(Trash2, { className: "icon-md" })
17533
+ }
17534
+ ),
17535
+ /* @__PURE__ */ jsxRuntime.jsx(
17536
+ "button",
17537
+ {
17538
+ onClick: handleSplit,
17539
+ disabled: !(selectedItem instanceof timeline.TrackElement),
17540
+ title: "Split",
17541
+ className: `control-btn split-btn ${!(selectedItem instanceof timeline.TrackElement) ? "btn-disabled" : ""}`,
17542
+ children: /* @__PURE__ */ jsxRuntime.jsx(Scissors, { className: "icon-md" })
17543
+ }
17544
+ ),
17545
+ /* @__PURE__ */ jsxRuntime.jsx(
17546
+ UndoRedoControls,
17547
+ {
17548
+ canUndo,
17549
+ canRedo,
17550
+ onUndo,
17551
+ onRedo
17552
+ }
17553
+ )
17554
+ ] }),
17555
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "playback-controls", children: [
17550
17556
  /* @__PURE__ */ jsxRuntime.jsx(
17551
17557
  "button",
17552
17558
  {
17553
17559
  onClick: togglePlayback,
17554
17560
  disabled: playerState === livePlayer.PLAYER_STATE.REFRESH,
17555
17561
  title: playerState === livePlayer.PLAYER_STATE.PLAYING ? "Pause" : playerState === livePlayer.PLAYER_STATE.REFRESH ? "Refreshing" : "Play",
17556
- className: "btn btn-ghost text-white",
17557
- children: playerState === livePlayer.PLAYER_STATE.PLAYING ? /* @__PURE__ */ jsxRuntime.jsx(Pause, { className: "w-6 h-6" }) : playerState === livePlayer.PLAYER_STATE.REFRESH ? /* @__PURE__ */ jsxRuntime.jsx(LoaderCircle, { className: "w-6 h-6 animate-spin" }) : /* @__PURE__ */ jsxRuntime.jsx(Play, { className: "w-6 h-6" })
17562
+ className: "control-btn play-pause-btn",
17563
+ children: playerState === livePlayer.PLAYER_STATE.PLAYING ? /* @__PURE__ */ jsxRuntime.jsx(Pause, { className: "icon-lg" }) : playerState === livePlayer.PLAYER_STATE.REFRESH ? /* @__PURE__ */ jsxRuntime.jsx(LoaderCircle, { className: "icon-lg animate-spin" }) : /* @__PURE__ */ jsxRuntime.jsx(Play, { className: "icon-lg" })
17558
17564
  }
17559
17565
  ),
17560
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-gray-300", children: [
17561
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium", children: formatTime(currentTime) }),
17562
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-500", children: "/" }),
17563
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm", children: formatTime(duration) })
17566
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "time-display", children: [
17567
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "current-time", children: formatTime(currentTime) }),
17568
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "time-separator", children: "/" }),
17569
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "total-time", children: formatTime(duration) })
17564
17570
  ] })
17565
17571
  ] }),
17566
- setZoomLevel && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
17572
+ setZoomLevel && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twick-track-zoom-container", children: [
17567
17573
  /* @__PURE__ */ jsxRuntime.jsx(
17568
17574
  "button",
17569
17575
  {
17570
17576
  onClick: handleZoomOut,
17571
17577
  disabled: zoomLevel <= MIN_ZOOM,
17572
17578
  title: "Zoom Out",
17573
- className: `btn btn-ghost ${zoomLevel > MIN_ZOOM ? "text-gray-300 hover:text-white" : "text-gray-500 cursor-not-allowed"}`,
17574
- children: /* @__PURE__ */ jsxRuntime.jsx(ZoomOut, { className: "w-5 h-5" })
17579
+ className: `control-btn ${zoomLevel <= MIN_ZOOM ? "btn-disabled" : ""}`,
17580
+ children: /* @__PURE__ */ jsxRuntime.jsx(ZoomOut, { className: "icon-md" })
17575
17581
  }
17576
17582
  ),
17577
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-sm text-gray-300 font-medium min-w-[3rem] text-center", children: [
17583
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "zoom-level", children: [
17578
17584
  Math.round(zoomLevel * 100),
17579
17585
  "%"
17580
17586
  ] }),
@@ -17584,12 +17590,12 @@ This message will only show in development mode. It won't appear in production.
17584
17590
  onClick: handleZoomIn,
17585
17591
  disabled: zoomLevel >= MAX_ZOOM,
17586
17592
  title: "Zoom In",
17587
- className: `btn btn-ghost ${zoomLevel < MAX_ZOOM ? "text-gray-300 hover:text-white" : "text-gray-500 cursor-not-allowed"}`,
17588
- children: /* @__PURE__ */ jsxRuntime.jsx(ZoomIn, { className: "w-5 h-5" })
17593
+ className: `control-btn ${zoomLevel >= MAX_ZOOM ? "btn-disabled" : ""}`,
17594
+ children: /* @__PURE__ */ jsxRuntime.jsx(ZoomIn, { className: "icon-md" })
17589
17595
  }
17590
17596
  )
17591
17597
  ] })
17592
- ] }) });
17598
+ ] });
17593
17599
  };
17594
17600
  const usePlayerControl = () => {
17595
17601
  const { playerState, setPlayerState } = livePlayer.useLivePlayerContext();
@@ -17675,7 +17681,6 @@ This message will only show in development mode. It won't appear in production.
17675
17681
  rightPanel,
17676
17682
  bottomPanel,
17677
17683
  editorConfig,
17678
- playControls,
17679
17684
  defaultPlayControls = true
17680
17685
  }) => {
17681
17686
  const [trackZoom, setTrackZoom] = React.useState(DEFAULT_TIMELINE_ZOOM);
@@ -17684,6 +17689,7 @@ This message will only show in development mode. It won't appear in production.
17684
17689
  PlayerManager,
17685
17690
  {
17686
17691
  videoProps: editorConfig.videoProps,
17692
+ playerProps: editorConfig.playerProps,
17687
17693
  canvasMode: editorConfig.canvasMode ?? true
17688
17694
  }
17689
17695
  ),
@@ -17697,7 +17703,7 @@ This message will only show in development mode. It won't appear in production.
17697
17703
  ] }),
17698
17704
  bottomPanel ? bottomPanel : null,
17699
17705
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twick-editor-timeline-section", children: [
17700
- playControls ? playControls : defaultPlayControls ? /* @__PURE__ */ jsxRuntime.jsx(ControlManager, { trackZoom, setTrackZoom }) : null,
17706
+ defaultPlayControls ? /* @__PURE__ */ jsxRuntime.jsx(ControlManager, { trackZoom, setTrackZoom }) : null,
17701
17707
  /* @__PURE__ */ jsxRuntime.jsx(TimelineManager, { trackZoom })
17702
17708
  ] })
17703
17709
  ] });