diff --git a/src/features/editor/control-item/control-item.tsx b/src/features/editor/control-item/control-item.tsx
index 356c5a49..aa14e8da 100644
--- a/src/features/editor/control-item/control-item.tsx
+++ b/src/features/editor/control-item/control-item.tsx
@@ -1,5 +1,4 @@
-import React from "react";
-import {
+import type {
IAudio,
ICaption,
IImage,
@@ -8,15 +7,16 @@ import {
ITrackItemAndDetails,
IVideo,
} from "@designcombo/types";
+import { LassoSelect } from "lucide-react";
+import React, { useCallback } from "react";
import { useEffect, useState } from "react";
-import BasicText from "./basic-text";
-import BasicImage from "./basic-image";
-import BasicVideo from "./basic-video";
-import BasicAudio from "./basic-audio";
-import useStore from "../store/use-store";
import useLayoutStore from "../store/use-layout-store";
+import useStore from "../store/use-store";
+import BasicAudio from "./basic-audio";
import BasicCaption from "./basic-caption";
-import { LassoSelect } from "lucide-react";
+import BasicImage from "./basic-image";
+import BasicText from "./basic-text";
+import BasicVideo from "./basic-video";
const Container = ({ children }: { children: React.ReactNode }) => {
const { activeIds, trackItemsMap, trackItemDetailsMap, transitionsMap } =
@@ -24,26 +24,35 @@ const Container = ({ children }: { children: React.ReactNode }) => {
const [trackItem, setTrackItem] = useState
(null);
const { setTrackItem: setLayoutTrackItem } = useLayoutStore();
+ const updateTrackItem = useCallback(
+ (ids: string[]) => {
+ if (ids.length === 1) {
+ const [id] = ids;
+ const trackItemDetails = trackItemDetailsMap[id];
+ const currentTrackItem = {
+ ...trackItemsMap[id],
+ details: trackItemDetails?.details || {},
+ };
+ if (trackItemDetails) {
+ setTrackItem(currentTrackItem);
+ setLayoutTrackItem(currentTrackItem);
+ } else {
+ console.log('No trackItemDetails', transitionsMap[id]);
+ }
+ } else {
+ setTrackItem(null);
+ setLayoutTrackItem(null);
+ }
+ },
+ [trackItemsMap, trackItemDetailsMap, setLayoutTrackItem, transitionsMap]
+ );
+
useEffect(() => {
- if (activeIds.length === 1) {
- const [id] = activeIds;
- const trackItemDetails = trackItemDetailsMap[id];
- const trackItem = {
- ...trackItemsMap[id],
- details: trackItemDetails?.details || {},
- };
- if (trackItemDetails) {
- setTrackItem(trackItem);
- setLayoutTrackItem(trackItem);
- } else console.log(transitionsMap[id]);
- } else {
- setTrackItem(null);
- setLayoutTrackItem(null);
- }
- }, [activeIds, trackItemsMap]);
+ updateTrackItem(activeIds);
+ }, [activeIds, updateTrackItem]);
return (
-
+
{React.cloneElement(children as React.ReactElement
, {
trackItem,
})}
diff --git a/src/features/editor/editor.tsx b/src/features/editor/editor.tsx
index bcefddfe..0e444fef 100644
--- a/src/features/editor/editor.tsx
+++ b/src/features/editor/editor.tsx
@@ -11,7 +11,7 @@ import {
ResizablePanel,
ResizablePanelGroup,
} from "@/components/ui/resizable";
-import { ImperativePanelHandle } from "react-resizable-panels";
+import type { ImperativePanelHandle } from "react-resizable-panels";
import { getCompactFontData, loadFonts } from "./utils/fonts";
import { SECONDARY_FONT, SECONDARY_FONT_URL } from "./constants/constants";
import MenuList from "./menu-list";
@@ -50,7 +50,7 @@ const Editor = () => {
url: SECONDARY_FONT_URL,
},
]);
- }, []);
+ });
useEffect(() => {
const screenHeight = window.innerHeight;
@@ -93,7 +93,7 @@ const Editor = () => {
-
+
diff --git a/src/features/editor/menu-item/audios.tsx b/src/features/editor/menu-item/audios.tsx
index b595ab2d..72e06f2a 100644
--- a/src/features/editor/menu-item/audios.tsx
+++ b/src/features/editor/menu-item/audios.tsx
@@ -1,13 +1,13 @@
-import Draggable from "@/components/shared/draggable";
-import { ScrollArea } from "@/components/ui/scroll-area";
-import { AUDIOS } from "../data/audio";
-import { dispatch } from "@designcombo/events";
-import { ADD_AUDIO } from "@designcombo/state";
-import { IAudio } from "@designcombo/types";
-import { Music } from "lucide-react";
-import { useIsDraggingOverTimeline } from "../hooks/is-dragging-over-timeline";
-import React from "react";
-import { generateId } from "@designcombo/timeline";
+import Draggable from '@/components/shared/draggable';
+import { ScrollArea } from '@/components/ui/scroll-area';
+import { dispatch } from '@designcombo/events';
+import { ADD_AUDIO } from '@designcombo/state';
+import { generateId } from '@designcombo/timeline';
+import type { IAudio } from '@designcombo/types';
+import { Music } from 'lucide-react';
+import React from 'react';
+import { AUDIOS } from '../data/audio';
+import { useIsDraggingOverTimeline } from '../hooks/is-dragging-over-timeline';
export const Audios = () => {
const isDraggingOverTimeline = useIsDraggingOverTimeline();
@@ -22,7 +22,7 @@ export const Audios = () => {
return (
-
+
Audios
@@ -54,12 +54,12 @@ const AudioItem = ({
}) => {
const style = React.useMemo(
() => ({
- backgroundImage: `url(https://cdn.designcombo.dev/thumbnails/music-preview.png)`,
- backgroundSize: "cover",
- width: "70px",
- height: "70px",
+ backgroundImage: 'url(https://cdn.designcombo.dev/thumbnails/music-preview.png)',
+ backgroundSize: 'cover',
+ width: '70px',
+ height: '70px',
}),
- [],
+ []
);
return (
@@ -72,8 +72,8 @@ const AudioItem = ({
draggable={false}
onClick={() => handleAddAudio(audio)}
style={{
- display: "grid",
- gridTemplateColumns: "48px 1fr",
+ display: 'grid',
+ gridTemplateColumns: '48px 1fr',
}}
className="flex cursor-pointer gap-4 px-2 py-1 text-sm hover:bg-zinc-800/70"
>
diff --git a/src/features/editor/menu-item/images.tsx b/src/features/editor/menu-item/images.tsx
index 44e0c4f3..aa9c0fc7 100644
--- a/src/features/editor/menu-item/images.tsx
+++ b/src/features/editor/menu-item/images.tsx
@@ -1,12 +1,12 @@
-import { ScrollArea } from "@/components/ui/scroll-area";
-import { IMAGES } from "../data/images";
-import { dispatch } from "@designcombo/events";
-import { generateId } from "@designcombo/timeline";
-import Draggable from "@/components/shared/draggable";
-import { IImage } from "@designcombo/types";
-import React from "react";
-import { useIsDraggingOverTimeline } from "../hooks/is-dragging-over-timeline";
-import { ADD_ITEMS } from "@designcombo/state";
+import Draggable from '@/components/shared/draggable';
+import { ScrollArea } from '@/components/ui/scroll-area';
+import { dispatch } from '@designcombo/events';
+import { ADD_ITEMS } from '@designcombo/state';
+import { generateId } from '@designcombo/timeline';
+import type { IImage } from '@designcombo/types';
+import React from 'react';
+import { IMAGES } from '../data/images';
+import { useIsDraggingOverTimeline } from '../hooks/is-dragging-over-timeline';
export const Images = () => {
const isDraggingOverTimeline = useIsDraggingOverTimeline();
@@ -51,7 +51,7 @@ export const Images = () => {
return (
-
+
Photos
@@ -84,11 +84,11 @@ const ImageItem = ({
const style = React.useMemo(
() => ({
backgroundImage: `url(${image.preview})`,
- backgroundSize: "cover",
- width: "80px",
- height: "80px",
+ backgroundSize: 'cover',
+ width: '80px',
+ height: '80px',
}),
- [image.preview],
+ [image.preview]
);
return (
@@ -102,7 +102,7 @@ const ImageItem = ({
handleAddImage({
id: generateId(),
details: {
- src: image.details!.src,
+ src: image.details.src,
},
} as IImage)
}
@@ -112,7 +112,7 @@ const ImageItem = ({
draggable={false}
src={image.preview}
className="h-full w-full rounded-md object-cover"
- alt="image"
+ alt="timeline element"
/>
diff --git a/src/features/editor/store/use-store.ts b/src/features/editor/store/use-store.ts
index 0dbf3047..4d0d8eae 100644
--- a/src/features/editor/store/use-store.ts
+++ b/src/features/editor/store/use-store.ts
@@ -1,15 +1,16 @@
-import Timeline from "@designcombo/timeline";
-import {
+import type Timeline from '@designcombo/timeline';
+import type {
ISize,
ITimelineScaleState,
ITimelineScrollState,
ITrack,
ITrackItem,
ITransition,
-} from "@designcombo/types";
-import Moveable from "@interactify/moveable";
-import { PlayerRef } from "@remotion/player";
-import { create } from "zustand";
+} from '@designcombo/types';
+import type Moveable from '@interactify/moveable';
+import type { PlayerRef } from '@remotion/player';
+import type { RefObject } from 'react';
+import { create } from 'zustand';
interface ITimelineStore {
duration: number;
@@ -28,11 +29,11 @@ interface ITimelineStore {
setTimeline: (timeline: Timeline) => void;
setScale: (scale: ITimelineScaleState) => void;
setScroll: (scroll: ITimelineScrollState) => void;
- playerRef: React.RefObject
| null;
- setPlayerRef: (playerRef: React.RefObject | null) => void;
+ playerRef: RefObject | null;
+ setPlayerRef: (playerRef: RefObject | null) => void;
- sceneMoveableRef: React.RefObject | null;
- setSceneMoveableRef: (ref: React.RefObject) => void;
+ sceneMoveableRef: RefObject | null;
+ setSceneMoveableRef: (ref: RefObject) => void;
setState: (state: any) => Promise;
}
@@ -82,8 +83,7 @@ const useStore = create((set) => ({
setState: async (state) => {
return set({ ...state });
},
- setPlayerRef: (playerRef: React.RefObject | null) =>
- set({ playerRef }),
+ setPlayerRef: (playerRef: RefObject | null) => set({ playerRef }),
setSceneMoveableRef: (ref) => set({ sceneMoveableRef: ref }),
}));
diff --git a/src/features/editor/timeline/header.tsx b/src/features/editor/timeline/header.tsx
index 6da1e330..48d9dced 100644
--- a/src/features/editor/timeline/header.tsx
+++ b/src/features/editor/timeline/header.tsx
@@ -1,26 +1,27 @@
-import { Button } from "@/components/ui/button";
-import { dispatch } from "@designcombo/events";
+import { TooltipButton } from '@/components/tooltip-button';
+import { Button } from '@/components/ui/button';
+import { Slider } from '@/components/ui/slider';
+import { dispatch } from '@designcombo/events';
import {
ACTIVE_SPLIT,
LAYER_CLONE,
LAYER_DELETE,
TIMELINE_SCALE_CHANGED,
-} from "@designcombo/state";
-import { PLAYER_PAUSE, PLAYER_PLAY } from "../constants/events";
-import { frameToTimeString, getCurrentTime, timeToString } from "../utils/time";
-import useStore from "../store/use-store";
-import { SquareSplitHorizontal, Trash, ZoomIn, ZoomOut } from "lucide-react";
+} from '@designcombo/state';
+import type { ITimelineScaleState } from '@designcombo/types';
+import { SquareSplitHorizontal, Trash, ZoomIn, ZoomOut } from 'lucide-react';
+import { useCallback, useEffect, useState } from 'react';
+import { PLAYER_PAUSE, PLAYER_PLAY } from '../constants/events';
+import { useCurrentPlayerFrame } from '../hooks/use-current-frame';
+import useUpdateAnsestors from '../hooks/use-update-ansestors';
+import useStore from '../store/use-store';
+import { frameToTimeString, getCurrentTime, timeToString } from '../utils/time';
import {
getFitZoomLevel,
getNextZoomLevel,
getPreviousZoomLevel,
getZoomByIndex,
-} from "../utils/timeline";
-import { useCurrentPlayerFrame } from "../hooks/use-current-frame";
-import { Slider } from "@/components/ui/slider";
-import { useEffect, useState } from "react";
-import useUpdateAnsestors from "../hooks/use-update-ansestors";
-import { ITimelineScaleState } from "@designcombo/types";
+} from '../utils/timeline';
const IconPlayerPlayFilled = ({ size }: { size: number }) => (