@twick/studio 0.14.6 → 0.14.8

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/README.md CHANGED
@@ -34,12 +34,32 @@ export default function App() {
34
34
  initialData={INITIAL_TIMELINE_DATA}
35
35
  contextId={"studio-demo"}
36
36
  >
37
- <TwickStudio studioConfig={{
38
- videoProps: {
39
- width: 720,
40
- height: 1280,
41
- },
42
- }}/>
37
+ <TwickStudio
38
+ studioConfig={{
39
+ videoProps: {
40
+ width: 720,
41
+ height: 1280,
42
+ },
43
+ // Optional: Customize timeline tick marks
44
+ timelineTickConfigs: [
45
+ { durationThreshold: 30, majorInterval: 5, minorTicks: 5 },
46
+ { durationThreshold: 300, majorInterval: 30, minorTicks: 6 }
47
+ ],
48
+ // Optional: Customize zoom behavior
49
+ timelineZoomConfig: {
50
+ min: 0.5, max: 2.0, step: 0.25, default: 1.0
51
+ },
52
+ // Optional: Customize element colors
53
+ elementColors: {
54
+ video: "#8B5FBF",
55
+ audio: "#3D8B8B",
56
+ image: "#D4956C",
57
+ text: "#A78EC8",
58
+ caption: "#9B8ACE",
59
+ fragment: "#1A1A1A"
60
+ }
61
+ }}
62
+ />
43
63
  </TimelineProvider>
44
64
  </LivePlayerProvider>
45
65
  );
@@ -59,6 +79,24 @@ The main studio component that provides a complete video editing interface.
59
79
  width: 1920,
60
80
  height: 1080
61
81
  },
82
+ // Optional: Customize timeline tick marks
83
+ timelineTickConfigs: [
84
+ { durationThreshold: 30, majorInterval: 5, minorTicks: 5 },
85
+ { durationThreshold: 300, majorInterval: 30, minorTicks: 6 }
86
+ ],
87
+ // Optional: Customize zoom behavior
88
+ timelineZoomConfig: {
89
+ min: 0.5, max: 2.0, step: 0.25, default: 1.0
90
+ },
91
+ // Optional: Customize element colors
92
+ elementColors: {
93
+ video: "#8B5FBF",
94
+ audio: "#3D8B8B",
95
+ image: "#D4956C",
96
+ text: "#A78EC8",
97
+ caption: "#9B8ACE",
98
+ fragment: "#1A1A1A"
99
+ },
62
100
  saveProject: async (project, fileName) => {
63
101
  // Custom save logic
64
102
  return { status: true, message: "Project saved" };
@@ -85,10 +123,39 @@ interface StudioConfig {
85
123
  width: number;
86
124
  height: number;
87
125
  };
126
+ // Timeline tick configuration
127
+ timelineTickConfigs?: TimelineTickConfig[];
128
+ // Zoom configuration
129
+ timelineZoomConfig?: TimelineZoomConfig;
130
+ // Element colors
131
+ elementColors?: ElementColors;
132
+ // Project management callbacks
88
133
  saveProject?: (project: ProjectJSON, fileName: string) => Promise<Result>;
89
134
  loadProject?: () => Promise<ProjectJSON>;
90
135
  exportVideo?: (project: ProjectJSON, videoSettings: VideoSettings) => Promise<Result>;
91
136
  }
137
+
138
+ interface TimelineTickConfig {
139
+ durationThreshold: number; // Applies when duration < threshold
140
+ majorInterval: number; // Major tick interval in seconds
141
+ minorTicks: number; // Number of minor ticks between majors
142
+ }
143
+
144
+ interface TimelineZoomConfig {
145
+ min: number; // Minimum zoom level
146
+ max: number; // Maximum zoom level
147
+ step: number; // Zoom step increment/decrement
148
+ default: number; // Default zoom level
149
+ }
150
+
151
+ interface ElementColors {
152
+ video: string;
153
+ audio: string;
154
+ image: string;
155
+ text: string;
156
+ caption: string;
157
+ fragment: string;
158
+ }
92
159
  ```
93
160
 
94
161
  ### Individual Panels
@@ -1,5 +1,9 @@
1
1
  import { Size, TrackElement } from '@twick/timeline';
2
2
 
3
+ /**
4
+ * Props interface for the ElementPanelContainer component.
5
+ * Defines the configuration and callback functions for element management.
6
+ */
3
7
  interface ElementPanelContainerProps {
4
8
  selectedTool: string;
5
9
  selectedElement: TrackElement | null;
@@ -8,5 +12,26 @@ interface ElementPanelContainerProps {
8
12
  addElement: (element: TrackElement) => void;
9
13
  updateElement: (element: TrackElement) => void;
10
14
  }
11
- declare const ElementPanelContainer: ({ selectedTool, setSelectedTool, videoResolution, selectedElement, addElement, updateElement, }: ElementPanelContainerProps) => JSX.Element;
15
+ /**
16
+ * ElementPanelContainer component that renders the appropriate element panel
17
+ * based on the currently selected tool. Provides a unified interface for
18
+ * managing different types of timeline elements including media, text, shapes,
19
+ * and subtitles. Shows an empty state when no tool is selected.
20
+ *
21
+ * @param props - Component props for element panel configuration
22
+ * @returns JSX element containing the appropriate element panel or empty state
23
+ *
24
+ * @example
25
+ * ```tsx
26
+ * <ElementPanelContainer
27
+ * selectedTool="text"
28
+ * selectedElement={currentElement}
29
+ * videoResolution={{ width: 1920, height: 1080 }}
30
+ * setSelectedTool={setTool}
31
+ * addElement={addToTimeline}
32
+ * updateElement={updateInTimeline}
33
+ * />
34
+ * ```
35
+ */
36
+ declare const ElementPanelContainer: ({ selectedTool, videoResolution, selectedElement, addElement, updateElement, }: ElementPanelContainerProps) => JSX.Element;
12
37
  export default ElementPanelContainer;
@@ -0,0 +1 @@
1
+ export declare function SubtitlesPanelContainer(): import("react/jsx-runtime").JSX.Element;
@@ -1,3 +1,3 @@
1
1
  import { AudioPanelProps } from '../../types/media-panel';
2
2
 
3
- export declare const AudioPanel: ({ items, searchQuery, onSearchChange, onItemSelect, onFileUpload, acceptFileTypes, }: AudioPanelProps) => import("react/jsx-runtime").JSX.Element;
3
+ export declare const AudioPanel: ({ items, onItemSelect, onFileUpload, acceptFileTypes, onUrlAdd, }: AudioPanelProps) => import("react/jsx-runtime").JSX.Element;
@@ -1,3 +1,3 @@
1
1
  import { ImagePanelProps } from '../../types/media-panel';
2
2
 
3
- export declare function ImagePanel({ items, searchQuery, onSearchChange, onItemSelect, onFileUpload, acceptFileTypes, }: ImagePanelProps): import("react/jsx-runtime").JSX.Element;
3
+ export declare function ImagePanel({ items, onItemSelect, onFileUpload, acceptFileTypes, onUrlAdd, }: ImagePanelProps): import("react/jsx-runtime").JSX.Element;
@@ -1,27 +1,46 @@
1
1
  /**
2
2
  * SubtitlesPanel Component
3
3
  *
4
- * A panel for managing video subtitles in the studio. Provides functionality
5
- * for creating, editing, and managing subtitle entries with timing and text.
6
- * Supports both manual entry and automatic generation (TODO).
4
+ * A presentational panel for managing subtitle entries in the studio.
5
+ * Renders a list of subtitle items, each with a text input and two actions:
6
+ * Split and Delete. A single Add button appears below the list.
7
+ *
8
+ * State is controlled by the parent via props; this component is stateless.
9
+ *
10
+ * Entry shape (SubtitleEntry):
11
+ * - `s`: start time (seconds)
12
+ * - `e`: end time (seconds)
13
+ * - `t`: subtitle text
14
+ *
15
+ * Props:
16
+ * - `subtitles`: SubtitleEntry[] — ordered list of subtitles
17
+ * - `addSubtitle()`: add a new subtitle at the end
18
+ * - `splitSubtitle(index)`: split the subtitle at `index`
19
+ * - `deleteSubtitle(index)`: remove the subtitle at `index`
20
+ * - `updateSubtitle(index, subtitle)`: update the subtitle at `index`
7
21
  *
8
22
  * @component
9
23
  * @example
10
24
  * ```tsx
11
- * <SubtitlesPanel />
25
+ * <SubtitlesPanel
26
+ * subtitles={subtitles}
27
+ * addSubtitle={addSubtitle}
28
+ * splitSubtitle={splitSubtitle}
29
+ * deleteSubtitle={deleteSubtitle}
30
+ * updateSubtitle={updateSubtitle}
31
+ * />
12
32
  * ```
13
- *
14
- * Features:
15
- * - Add/delete subtitle entries
16
- * - Set start/end times
17
- * - Edit subtitle text
18
- * - Automatic subtitle generation (planned)
19
- * - Save subtitles to timeline
20
- *
21
- * Each subtitle entry includes:
22
- * - Start time (in seconds)
23
- * - End time (in seconds)
24
- * - Subtitle text
25
- * - Delete and save actions
26
33
  */
27
- export declare function SubtitlesPanel(): import("react/jsx-runtime").JSX.Element;
34
+ interface SubtitleEntry {
35
+ s: number;
36
+ e: number;
37
+ t: string;
38
+ }
39
+ export declare function SubtitlesPanel({ subtitles, addSubtitle, splitSubtitle, deleteSubtitle, updateSubtitle, }: {
40
+ subtitles: SubtitleEntry[];
41
+ addSubtitle: () => void;
42
+ splitSubtitle: (index: number) => void;
43
+ deleteSubtitle: (index: number) => void;
44
+ updateSubtitle: (index: number, subtitle: SubtitleEntry) => void;
45
+ }): import("react/jsx-runtime").JSX.Element;
46
+ export {};
@@ -1,3 +1,3 @@
1
1
  import { VideoPanelProps } from '../../types/media-panel';
2
2
 
3
- export declare function VideoPanel({ items, searchQuery, onSearchChange, onItemSelect, onFileUpload, acceptFileTypes, }: VideoPanelProps): import("react/jsx-runtime").JSX.Element;
3
+ export declare function VideoPanel({ items, onItemSelect, onFileUpload, acceptFileTypes, onUrlAdd, }: VideoPanelProps): import("react/jsx-runtime").JSX.Element;
@@ -1,3 +1,4 @@
1
1
  export * from './color-input';
2
2
  export * from './file-input';
3
3
  export * from './media-manager';
4
+ export { default as UrlInput } from './url-input';
@@ -0,0 +1,6 @@
1
+ type MediaType = "video" | "audio" | "image";
2
+ export default function UrlInput({ type, onSubmit, }: {
3
+ type: MediaType;
4
+ onSubmit: (url: string) => void;
5
+ }): import("react/jsx-runtime").JSX.Element;
6
+ export {};
@@ -0,0 +1,52 @@
1
+ export declare const CAPTION_PROPS: {
2
+ highlight_bg: {
3
+ font: {
4
+ size: number;
5
+ weight: number;
6
+ family: string;
7
+ };
8
+ colors: {
9
+ text: string;
10
+ highlight: string;
11
+ bgColor: string;
12
+ };
13
+ lineWidth: number;
14
+ stroke: string;
15
+ fontWeight: number;
16
+ shadowOffset: number[];
17
+ shadowColor: string;
18
+ };
19
+ word_by_word: {
20
+ font: {
21
+ size: number;
22
+ weight: number;
23
+ family: string;
24
+ };
25
+ colors: {
26
+ text: string;
27
+ highlight: string;
28
+ bgColor: string;
29
+ };
30
+ lineWidth: number;
31
+ stroke: string;
32
+ shadowOffset: number[];
33
+ shadowColor: string;
34
+ shadowBlur: number;
35
+ };
36
+ word_by_word_with_bg: {
37
+ font: {
38
+ size: number;
39
+ weight: number;
40
+ family: string;
41
+ };
42
+ colors: {
43
+ text: string;
44
+ highlight: string;
45
+ bgColor: string;
46
+ };
47
+ lineWidth: number;
48
+ shadowOffset: number[];
49
+ shadowColor: string;
50
+ shadowBlur: number;
51
+ };
52
+ };
@@ -6,6 +6,6 @@ export declare const useStudioManager: () => {
6
6
  selectedTool: string;
7
7
  setSelectedTool: import('react').Dispatch<import('react').SetStateAction<string>>;
8
8
  selectedElement: TrackElement | null;
9
- addElement: (element: TrackElement) => void;
9
+ addElement: (element: TrackElement) => Promise<void>;
10
10
  updateElement: (element: TrackElement) => void;
11
11
  };
@@ -0,0 +1,13 @@
1
+ interface SubtitleEntry {
2
+ s: number;
3
+ e: number;
4
+ t: string;
5
+ }
6
+ export declare const useSubtitlesPanel: () => {
7
+ subtitles: SubtitleEntry[];
8
+ addSubtitle: () => void;
9
+ splitSubtitle: (index: number) => Promise<void>;
10
+ deleteSubtitle: (index: number) => void;
11
+ updateSubtitle: (index: number, subtitle: SubtitleEntry) => void;
12
+ };
13
+ export {};