@twick/studio 0.15.13 → 0.15.15

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.
Files changed (35) hide show
  1. package/README.md +2 -2
  2. package/dist/components/container/captions-panel-container.d.ts +1 -0
  3. package/dist/components/container/element-panel-container.d.ts +1 -1
  4. package/dist/components/container/properties-panel-container.d.ts +7 -7
  5. package/dist/components/panel/captions-panel.d.ts +46 -0
  6. package/dist/components/panel/circle-panel.d.ts +1 -1
  7. package/dist/components/panel/rect-panel.d.ts +1 -1
  8. package/dist/components/panel/text-panel.d.ts +1 -1
  9. package/dist/components/properties/{subtitlte-prop.d.ts → caption-prop.d.ts} +4 -4
  10. package/dist/components/properties/generate-captions.d.ts +13 -0
  11. package/dist/components/properties/property-row.d.ts +10 -0
  12. package/dist/components/properties/text-props.d.ts +3 -0
  13. package/dist/helpers/generate-captions.service.d.ts +21 -0
  14. package/dist/helpers/volume-db.d.ts +22 -0
  15. package/dist/hooks/use-captions-panel.d.ts +13 -0
  16. package/dist/hooks/use-generate-captions.d.ts +9 -0
  17. package/dist/hooks/use-studio-operation.d.ts +4 -4
  18. package/dist/hooks/use-text-panel.d.ts +6 -0
  19. package/dist/index.d.ts +10 -13
  20. package/dist/index.js +1209 -1046
  21. package/dist/index.js.map +1 -1
  22. package/dist/index.mjs +1194 -1034
  23. package/dist/index.mjs.map +1 -1
  24. package/dist/studio.css +521 -162
  25. package/dist/types/index.d.ts +18 -16
  26. package/package.json +14 -12
  27. package/dist/components/container/icon-panel-container.d.ts +0 -3
  28. package/dist/components/container/subtitles-panel-container.d.ts +0 -1
  29. package/dist/components/panel/icon-panel.d.ts +0 -4
  30. package/dist/components/panel/subtitles-panel.d.ts +0 -46
  31. package/dist/components/properties/generate-subtitles.d.ts +0 -13
  32. package/dist/helpers/generate-subtitles.service.d.ts +0 -21
  33. package/dist/hooks/use-generate-subtitles.d.ts +0 -9
  34. package/dist/hooks/use-icon-panel.d.ts +0 -24
  35. package/dist/hooks/use-subtitles-panel.d.ts +0 -13
package/README.md CHANGED
@@ -194,7 +194,7 @@ The studio includes specialized panels for different element types:
194
194
  - **VideoPanel**: Video management and library
195
195
  - **ImagePanel**: Image management and library
196
196
  - **TextPanel**: Text editing with advanced styling
197
- - **SubtitlesPanel**: Subtitle and caption management
197
+ - **CaptionsPanel**: Caption and caption management
198
198
  - **CirclePanel**: Circle shape creation and editing
199
199
  - **RectPanel**: Rectangle shape creation and editing
200
200
  - **IconPanel**: Icon library with search and customization
@@ -202,7 +202,7 @@ The studio includes specialized panels for different element types:
202
202
  ### Hooks
203
203
 
204
204
  - **useStudioManager**: Hook for managing studio state, selected tools, and element manipulation
205
- - **useGenerateSubtitles**: Hook for subtitle generation and polling
205
+ - **useGenerateCaptions**: Hook for caption generation and polling
206
206
 
207
207
  ### Re-exported Components
208
208
 
@@ -0,0 +1 @@
1
+ export declare function CaptionsPanelContainer(): import("react/jsx-runtime").JSX.Element;
@@ -17,7 +17,7 @@ interface ElementPanelContainerProps {
17
17
  * ElementPanelContainer component that renders the appropriate element panel
18
18
  * based on the currently selected tool. Provides a unified interface for
19
19
  * managing different types of timeline elements including media, text, shapes,
20
- * and subtitles. Shows an empty state when no tool is selected.
20
+ * and captions. Shows an empty state when no tool is selected.
21
21
  *
22
22
  * @param props - Component props for element panel configuration
23
23
  * @returns JSX element containing the appropriate element panel or empty state
@@ -1,13 +1,13 @@
1
- import { VideoElement, TrackElement } from '@twick/timeline';
2
- import { ISubtitleGenerationPollingResponse, SubtitleEntry } from '../../types';
1
+ import { VideoElement, TrackElement, Size } from '@twick/timeline';
2
+ import { ICaptionGenerationPollingResponse, CaptionEntry } from '../../types';
3
3
 
4
4
  interface PropertiesPanelContainerProps {
5
- selectedProp: string;
6
5
  selectedElement: TrackElement | null;
7
6
  updateElement: (element: TrackElement) => void;
8
- addSubtitlesToTimeline: (subtitles: SubtitleEntry[]) => void;
9
- onGenerateSubtitles: (videoElement: VideoElement) => Promise<string | null>;
10
- getSubtitleStatus: (reqId: string) => Promise<ISubtitleGenerationPollingResponse>;
7
+ addCaptionsToTimeline: (captions: CaptionEntry[]) => void;
8
+ onGenerateCaptions: (videoElement: VideoElement) => Promise<string | null>;
9
+ getCaptionstatus: (reqId: string) => Promise<ICaptionGenerationPollingResponse>;
10
+ videoResolution: Size;
11
11
  }
12
- export declare function PropertiesPanelContainer({ selectedProp, selectedElement, updateElement, addSubtitlesToTimeline, onGenerateSubtitles, getSubtitleStatus, }: PropertiesPanelContainerProps): import("react/jsx-runtime").JSX.Element;
12
+ export declare function PropertiesPanelContainer({ selectedElement, updateElement, addCaptionsToTimeline, onGenerateCaptions, getCaptionstatus, videoResolution, }: PropertiesPanelContainerProps): import("react/jsx-runtime").JSX.Element;
13
13
  export {};
@@ -0,0 +1,46 @@
1
+ /**
2
+ * CaptionsPanel Component
3
+ *
4
+ * A presentational panel for managing caption entries in the studio.
5
+ * Renders a list of caption 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 (CaptionEntry):
11
+ * - `s`: start time (seconds)
12
+ * - `e`: end time (seconds)
13
+ * - `t`: caption text
14
+ *
15
+ * Props:
16
+ * - `captions`: CaptionEntry[] — ordered list of captions
17
+ * - `addCaption()`: add a new caption at the end
18
+ * - `splitCaption(index)`: split the caption at `index`
19
+ * - `deleteCaption(index)`: remove the caption at `index`
20
+ * - `updateCaption(index, caption)`: update the caption at `index`
21
+ *
22
+ * @component
23
+ * @example
24
+ * ```tsx
25
+ * <CaptionsPanel
26
+ * captions={captions}
27
+ * addCaption={addCaption}
28
+ * splitCaption={splitCaption}
29
+ * deleteCaption={deleteCaption}
30
+ * updateCaption={updateCaption}
31
+ * />
32
+ * ```
33
+ */
34
+ interface CaptionEntry {
35
+ s: number;
36
+ e: number;
37
+ t: string;
38
+ }
39
+ export declare function CaptionsPanel({ captions, addCaption, splitCaption, deleteCaption, updateCaption, }: {
40
+ captions: CaptionEntry[];
41
+ addCaption: () => void;
42
+ splitCaption: (index: number) => void;
43
+ deleteCaption: (index: number) => void;
44
+ updateCaption: (index: number, caption: CaptionEntry) => void;
45
+ }): import("react/jsx-runtime").JSX.Element;
46
+ export {};
@@ -1,4 +1,4 @@
1
1
  import { CirclePanelState, CirclePanelActions } from '../../hooks/use-circle-panel';
2
2
 
3
3
  export type CirclePanelProps = CirclePanelState & CirclePanelActions;
4
- export declare function CirclePanel({ radius, fillColor, opacity, strokeColor, lineWidth, operation, setRadius, setFillColor, setOpacity, setStrokeColor, setLineWidth, handleApplyChanges, }: CirclePanelProps): import("react/jsx-runtime").JSX.Element;
4
+ export declare function CirclePanel({ radius, fillColor, strokeColor, lineWidth, operation, setRadius, setFillColor, setStrokeColor, setLineWidth, handleApplyChanges, }: CirclePanelProps): import("react/jsx-runtime").JSX.Element;
@@ -1,4 +1,4 @@
1
1
  import { RectPanelState, RectPanelActions } from '../../hooks/use-rect-panel';
2
2
 
3
3
  export type RectPanelProps = RectPanelState & RectPanelActions;
4
- export declare function RectPanel({ cornerRadius, fillColor, opacity, strokeColor, lineWidth, operation, setCornerRadius, setFillColor, setOpacity, setStrokeColor, setLineWidth, handleApplyChanges, }: RectPanelProps): import("react/jsx-runtime").JSX.Element;
4
+ export declare function RectPanel({ cornerRadius, fillColor, strokeColor, lineWidth, operation, setCornerRadius, setFillColor, setStrokeColor, setLineWidth, handleApplyChanges, }: RectPanelProps): import("react/jsx-runtime").JSX.Element;
@@ -1,4 +1,4 @@
1
1
  import { TextPanelState, TextPanelActions } from '../../hooks/use-text-panel';
2
2
 
3
3
  export type TextPanelProps = TextPanelState & TextPanelActions;
4
- export declare function TextPanel({ textContent, fontSize, selectedFont, isBold, isItalic, textColor, strokeColor, applyShadow, shadowColor, strokeWidth, fonts, operation, setTextContent, setFontSize, setSelectedFont, setIsBold, setIsItalic, setTextColor, setStrokeColor, setApplyShadow, setShadowColor, setStrokeWidth, handleApplyChanges, }: TextPanelProps): import("react/jsx-runtime").JSX.Element;
4
+ export declare function TextPanel({ textContent, fontSize, selectedFont, isBold, isItalic, textColor, strokeColor, applyShadow, shadowColor, strokeWidth, applyBackground, backgroundColor, backgroundOpacity, fonts, operation, setTextContent, setFontSize, setSelectedFont, setIsBold, setIsItalic, setTextColor, setStrokeColor, setApplyShadow, setShadowColor, setStrokeWidth, setApplyBackground, setBackgroundColor, setBackgroundOpacity, handleApplyChanges, }: TextPanelProps): import("react/jsx-runtime").JSX.Element;
@@ -28,8 +28,8 @@ export declare const CAPTION_COLOR: {
28
28
  highlight: string;
29
29
  bgColor: string;
30
30
  };
31
- interface SubtitlePropPanelProps {
32
- setApplyPropsToAllSubtitle: (apply: boolean) => void;
31
+ interface CaptionPropPanelProps {
32
+ setApplyPropsToAllCaption: (apply: boolean) => void;
33
33
  }
34
- export declare function SubtitlePropPanel({ selectedElement, updateElement, setApplyPropsToAllSubtitle, }: SubtitlePropPanelProps & PropertiesPanelProps): import("react/jsx-runtime").JSX.Element | null;
35
- export default SubtitlePropPanel;
34
+ export declare function CaptionPropPanel({ selectedElement, updateElement, setApplyPropsToAllCaption, }: CaptionPropPanelProps & PropertiesPanelProps): import("react/jsx-runtime").JSX.Element | null;
35
+ export default CaptionPropPanel;
@@ -0,0 +1,13 @@
1
+ import { TrackElement, VideoElement } from '@twick/timeline';
2
+ import { ICaptionGenerationPollingResponse } from '../../types';
3
+
4
+ export declare function GenerateCaptionsPanel({ selectedElement, addCaptionsToTimeline, onGenerateCaptions, getCaptionstatus, }: {
5
+ selectedElement: TrackElement;
6
+ addCaptionsToTimeline: (captions: {
7
+ s: number;
8
+ e: number;
9
+ t: string;
10
+ }[]) => void;
11
+ onGenerateCaptions: (videoElement: VideoElement) => Promise<string | null>;
12
+ getCaptionstatus: (reqId: string) => Promise<ICaptionGenerationPollingResponse>;
13
+ }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,10 @@
1
+ import { ReactNode } from 'react';
2
+
3
+ interface PropertyRowProps {
4
+ label: string;
5
+ children: ReactNode;
6
+ /** Optional secondary label/value on the right (e.g. units, current value) */
7
+ secondary?: ReactNode;
8
+ }
9
+ export declare function PropertyRow({ label, children, secondary }: PropertyRowProps): import("react/jsx-runtime").JSX.Element;
10
+ export {};
@@ -0,0 +1,3 @@
1
+ import { PropertiesPanelProps } from '../../types';
2
+
3
+ export declare function TextPropsPanel({ selectedElement, updateElement, }: PropertiesPanelProps): import("react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,21 @@
1
+ import { ProjectJSON, VideoElement } from '@twick/timeline';
2
+ import { ICaptionGenerationPollingResponse, ICaptionGenerationService, CaptionEntry } from '../types';
3
+
4
+ declare class GenerateCaptionsService implements ICaptionGenerationService {
5
+ videoElement: VideoElement | null;
6
+ projectJSON: ProjectJSON | null;
7
+ generateSubtiltesApi: (videoUrl: string) => Promise<string>;
8
+ requestStatusApi: (reqId: string) => Promise<ICaptionGenerationPollingResponse>;
9
+ constructor({ generateSubtiltesApi, requestStatusApi, }: {
10
+ generateSubtiltesApi: (videoUrl: string) => Promise<string>;
11
+ requestStatusApi: (reqId: string) => Promise<ICaptionGenerationPollingResponse>;
12
+ });
13
+ generateCaptions(videoElement: VideoElement, projectJSON: ProjectJSON): Promise<string>;
14
+ getRequestStatus(reqId: string): Promise<ICaptionGenerationPollingResponse>;
15
+ updateProjectWithCaptions(captions: CaptionEntry[]): ProjectJSON;
16
+ generateCaptionVideo(videoUrl: string, videoSize?: {
17
+ width: number;
18
+ height: number;
19
+ }): Promise<string>;
20
+ }
21
+ export default GenerateCaptionsService;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Volume conversion between linear (0-1) and dB scale.
3
+ * Used for PlaybackPropsPanel to match professional audio tools (e.g. -60 dB to +6 dB).
4
+ *
5
+ * Formula: dB = 20 * log10(linear)
6
+ * - 0 dB = 1.0 linear (full volume)
7
+ * - -60 dB ≈ 0.001 linear (effectively mute)
8
+ * - +6 dB ≈ 2.0 linear (amplification)
9
+ */
10
+ declare const MIN_DB = -60;
11
+ declare const MAX_DB = 6;
12
+ /**
13
+ * Convert linear volume (0 to ~2) to dB.
14
+ * Returns MIN_DB for linear <= 0 to avoid -Infinity.
15
+ */
16
+ export declare function linearToDb(linear: number): number;
17
+ /**
18
+ * Convert dB to linear volume.
19
+ * Returns 0 for dB <= MIN_DB (mute).
20
+ */
21
+ export declare function dbToLinear(db: number): number;
22
+ export { MIN_DB, MAX_DB };
@@ -0,0 +1,13 @@
1
+ interface CaptionEntry {
2
+ s: number;
3
+ e: number;
4
+ t: string;
5
+ }
6
+ export declare const useCaptionsPanel: () => {
7
+ captions: CaptionEntry[];
8
+ addCaption: () => void;
9
+ splitCaption: (index: number) => Promise<void>;
10
+ deleteCaption: (index: number) => void;
11
+ updateCaption: (index: number, caption: CaptionEntry) => void;
12
+ };
13
+ export {};
@@ -0,0 +1,9 @@
1
+ import { VideoElement } from '@twick/timeline';
2
+ import { ICaptionGenerationPollingResponse, StudioConfig, CaptionEntry } from '../types';
3
+
4
+ declare const useGenerateCaptions: (studioConfig?: StudioConfig) => {
5
+ onGenerateCaptions: (videoElement: VideoElement) => Promise<string | null>;
6
+ addCaptionsToTimeline: (captions: CaptionEntry[]) => void;
7
+ getCaptionstatus: (reqId: string) => Promise<ICaptionGenerationPollingResponse>;
8
+ };
9
+ export default useGenerateCaptions;
@@ -1,13 +1,13 @@
1
1
  import { VideoElement } from '@twick/timeline';
2
- import { ISubtitleGenerationPollingResponse, StudioConfig, SubtitleEntry } from '../types';
2
+ import { ICaptionGenerationPollingResponse, StudioConfig, CaptionEntry } from '../types';
3
3
 
4
4
  declare const useStudioOperation: (studioConfig?: StudioConfig) => {
5
5
  onLoadProject: () => Promise<void>;
6
6
  onSaveProject: () => Promise<void>;
7
7
  onExportVideo: () => Promise<void>;
8
8
  onNewProject: () => void;
9
- onGenerateSubtitles: (videoElement: VideoElement) => Promise<string | null>;
10
- addSubtitlesToTimeline: (subtitles: SubtitleEntry[]) => void;
11
- getSubtitleStatus: (reqId: string) => Promise<ISubtitleGenerationPollingResponse>;
9
+ onGenerateCaptions: (videoElement: VideoElement) => Promise<string | null>;
10
+ addCaptionsToTimeline: (captions: CaptionEntry[]) => void;
11
+ getCaptionstatus: (reqId: string) => Promise<ICaptionGenerationPollingResponse>;
12
12
  };
13
13
  export default useStudioOperation;
@@ -27,6 +27,9 @@ export interface TextPanelState {
27
27
  applyShadow: boolean;
28
28
  shadowColor: string;
29
29
  strokeWidth: number;
30
+ applyBackground: boolean;
31
+ backgroundColor: string;
32
+ backgroundOpacity: number;
30
33
  fonts: string[];
31
34
  operation: string;
32
35
  }
@@ -41,6 +44,9 @@ export interface TextPanelActions {
41
44
  setApplyShadow: (shadow: boolean) => void;
42
45
  setShadowColor: (color: string) => void;
43
46
  setStrokeWidth: (width: number) => void;
47
+ setApplyBackground: (apply: boolean) => void;
48
+ setBackgroundColor: (color: string) => void;
49
+ setBackgroundOpacity: (opacity: number) => void;
44
50
  handleApplyChanges: () => void;
45
51
  }
46
52
  export declare const useTextPanel: ({ selectedElement, addElement, updateElement, }: {
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { TwickStudio } from './components/twick-studio';
2
2
  import { Toolbar } from './components/toolbar';
3
3
  import { useStudioManager } from './hooks/use-studio-manager';
4
- import { default as useGenerateSubtitles } from './hooks/use-generate-subtitles';
4
+ import { default as useGenerateCaptions } from './hooks/use-generate-captions';
5
5
  import { default as StudioHeader } from './components/header';
6
6
  import { AudioPanel } from './components/panel/audio-panel';
7
7
  import { VideoPanel } from './components/panel/video-panel';
@@ -9,8 +9,7 @@ import { ImagePanel } from './components/panel/image-panel';
9
9
  import { TextPanel } from './components/panel/text-panel';
10
10
  import { CirclePanel } from './components/panel/circle-panel';
11
11
  import { RectPanel } from './components/panel/rect-panel';
12
- import { IconPanel } from './components/panel/icon-panel';
13
- import { SubtitlesPanel } from './components/panel/subtitles-panel';
12
+ import { CaptionsPanel } from './components/panel/captions-panel';
14
13
 
15
14
  export {
16
15
  /** Main studio editing environment */
@@ -28,20 +27,18 @@ VideoPanel,
28
27
  ImagePanel,
29
28
  /** Panel for editing/add text elements */
30
29
  TextPanel,
31
- /** Panel for subtitle/caption management */
32
- SubtitlesPanel,
30
+ /** Panel for caption/caption management */
31
+ CaptionsPanel,
33
32
  /** Panel for adding circles */
34
33
  CirclePanel,
35
34
  /** Panel for adding rectangles */
36
- RectPanel,
37
- /** Panel for icon assets */
38
- IconPanel, };
35
+ RectPanel, };
39
36
  export {
40
37
  /** Hook for managing studio state and selections */
41
38
  useStudioManager,
42
- /** Hook for polling-based subtitle generation */
43
- useGenerateSubtitles, };
44
- export * from './helpers/generate-subtitles.service';
39
+ /** Hook for polling-based caption generation */
40
+ useGenerateCaptions, };
41
+ export * from './helpers/generate-captions.service';
45
42
  export * from './helpers/constant';
46
43
  export * from './types';
47
44
  /**
@@ -83,7 +80,7 @@ export * from './types';
83
80
  * Main video editor component and related types
84
81
  */
85
82
  export { default as VideoEditor } from '@twick/video-editor';
86
- export type { VideoEditorProps, VideoEditorConfig, TimelineTickConfig, TimelineZoomConfig, PlayerControlsProps } from '@twick/video-editor';
83
+ export type { VideoEditorProps, VideoEditorConfig, CanvasConfig, TimelineTickConfig, TimelineZoomConfig, PlayerControlsProps } from '@twick/video-editor';
87
84
  /**
88
85
  * Video editor hooks for custom implementations
89
86
  */
@@ -116,7 +113,7 @@ export { PLAYER_STATE, getBaseProject, generateId } from '@twick/live-player';
116
113
  /**
117
114
  * Timeline provider and editor
118
115
  */
119
- export { TimelineProvider, TimelineEditor, INITIAL_TIMELINE_DATA } from '@twick/timeline';
116
+ export { useTimelineContext, TimelineProvider, TimelineEditor, INITIAL_TIMELINE_DATA } from '@twick/timeline';
120
117
  export type { TimelineProviderProps } from '@twick/timeline';
121
118
  /**
122
119
  * Timeline element classes