summaryrefslogtreecommitdiff
path: root/.cursor/rules/codebase-index.mdc
diff options
context:
space:
mode:
Diffstat (limited to '.cursor/rules/codebase-index.mdc')
-rw-r--r--.cursor/rules/codebase-index.mdc4910
1 files changed, 2515 insertions, 2395 deletions
diff --git a/.cursor/rules/codebase-index.mdc b/.cursor/rules/codebase-index.mdc
index 635e547b..547d0566 100644
--- a/.cursor/rules/codebase-index.mdc
+++ b/.cursor/rules/codebase-index.mdc
@@ -1,2395 +1,2515 @@
----
-alwaysApply: true
----
-
-# video-editor-oss Codebase Index
-
-**This file provides an index of exported functions, types, interfaces, classes, and constants in your codebase.**
-
-Updated in real-time by Twiggy. Use this to discover existing utilities and avoid duplicating code.
-
-## How to Use
-
-When implementing new features:
-1. Check if similar functionality already exists
-2. Reuse existing types and utilities
-3. Understand the API surface of your codebase
-
-```typescript
-## apps/web/src/constants
-
-editor-constants.ts
- export const PANEL_CONFIG
-
-export-constants.ts
- export const DEFAULT_EXPORT_OPTIONS
- export const EXPORT_MIME_TYPES
-
-font-constants.ts
- export const DEFAULT_FONT
- export const SYSTEM_FONTS
-
-language-constants.ts
- export const LANGUAGES
-
-project-constants.ts
- export const DEFAULT_CANVAS_PRESETS: TCanvasSize[]
- export const FPS_PRESETS
- export const BLUR_INTENSITY_PRESETS: { label: string; value: number }[]
- export const DEFAULT_CANVAS_SIZE: TCanvasSize
- export const DEFAULT_FPS
- export const DEFAULT_BLUR_INTENSITY
- export const DEFAULT_COLOR
-
-site-constants.ts
- export const SITE_URL
- export const SITE_INFO
- export type ExternalTool = {
- name: string;
- description: string;
- url: string;
- icon: React.ElementType;
- }
- export const EXTERNAL_TOOLS: ExternalTool[]
- export const DEFAULT_LOGO_URL
- export const SOCIAL_LINKS
- export type Sponsor = {
- name: string;
- url: string;
- logo: string;
- description: string;
- }
- export const SPONSORS: Sponsor[]
-
-sticker-constants.ts
- export const STICKER_CATEGORIES
-
-text-constants.ts
- export const MIN_FONT_SIZE
- export const MAX_FONT_SIZE
- export const FONT_SIZE_SCALE_REFERENCE
- export const DEFAULT_LETTER_SPACING
- export const DEFAULT_LINE_HEIGHT
- export const DEFAULT_TEXT_ELEMENT: Omit<TextElement, "id">
-
-timeline-constants.tsx
- export const DEFAULT_TRANSFORM: Transform
- export const DEFAULT_OPACITY
- export const DEFAULT_BLEND_MODE: BlendMode
- export const DEFAULT_BOOKMARK_COLOR
- export const TRACK_COLORS: Record<TrackType, { background: string }>
- export const TRACK_HEIGHTS: Record<TrackType, number>
- export const TRACK_GAP
- export const DRAG_THRESHOLD_PX
- export const TIMELINE_CONSTANTS
- export const DEFAULT_TIMELINE_VIEW_STATE: TTimelineViewState
- export const TRACK_ICONS: Record<TrackType, React.ReactNode>
-
-transcription-constants.ts
- export const TRANSCRIPTION_LANGUAGES
- export const TRANSCRIPTION_MODELS: TranscriptionModel[]
- export const DEFAULT_TRANSCRIPTION_MODEL: TranscriptionModelId
- export const DEFAULT_CHUNK_LENGTH_SECONDS
- export const DEFAULT_STRIDE_SECONDS
- export const DEFAULT_WORDS_PER_CAPTION
- export const MIN_CAPTION_DURATION_SECONDS
-
-## apps/web/src/core
-
-index.ts
- export class EditorCore {
- instance: EditorCore | null
- command: CommandManager
- playback: PlaybackManager
- timeline: TimelineManager
- scenes: ScenesManager
- project: ProjectManager
- media: MediaManager
- renderer: RendererManager
- save: SaveManager
- audio: AudioManager
- selection: SelectionManager
- static getInstance(): EditorCore
- static reset(): void
- }
-
-## apps/web/src/hooks
-
-use-container-size.ts
- export function useContainerSize({
- containerRef,
- }: {
- containerRef: React.RefObject<HTMLElement | null>;
- })
-
-use-editor.ts
- export function useEditor(): EditorCore
-
-use-file-upload.ts
- export function useFileUpload({
- accept,
- multiple,
- onFilesSelected,
- }: UseFileUploadOptions = {})
-
-use-focus-lock.ts
- export function useFocusLock({
- isActive,
- onDismiss,
- cursor = "default",
- allowSelector,
- }: {
- isActive: boolean;
- onDismiss: () => void;
- cursor?: FocusLockCursor;
- allowSelector?: string;
- })
-
-use-fullscreen.ts
- export function useFullscreen({
- containerRef,
- }: {
- containerRef: React.RefObject<HTMLElement | null>;
- })
-
-use-infinite-scroll.ts
- export function useInfiniteScroll({
- onLoadMore,
- hasMore,
- isLoading,
- threshold = 200,
- enabled = true,
- }: UseInfiniteScrollOptions)
-
-use-keybindings.ts
- export function useKeybindingsListener()
- export function useKeybindingDisabler()
-
-use-keyboard-shortcuts-help.ts
- export interface KeyboardShortcut {
- id: string
- keys: string[]
- description: string
- category: string
- action: TAction
- icon?: React.ReactNode
- }
- export function useKeyboardShortcutsHelp()
-
-use-mobile.ts
- export function useIsMobile()
-
-use-paste-media.ts
- export function usePasteMedia()
-
-use-preview-interaction.ts
- export function usePreviewInteraction({
- canvasRef,
- }: {
- canvasRef: React.RefObject<HTMLCanvasElement | null>;
- })
-
-use-raf-loop.ts
- export function useRafLoop(callback: ({ time }: { time: number }) => void)
-
-use-reveal-item.ts
- export function useRevealItem(
- highlightId: string | null,
- onClearHighlight: () => void,
- highlightDuration = 1000,
- )
-
-use-shift-key.ts
- export function useShiftKey(): RefObject<boolean>
-
-use-sound-search.ts
- export function useSoundSearch({
- query,
- commercialOnly,
- }: {
- query: string;
- commercialOnly: boolean;
- })
-
-use-transform-handles.ts
- export function useTransformHandles({
- canvasRef,
- }: {
- canvasRef: React.RefObject<HTMLCanvasElement | null>;
- })
-
-## apps/web/src/hooks/actions
-
-use-action-handler.ts
- export function useActionHandler(
- action: A,
- handler: TActionFunc<A>,
- isActive: TActionHandlerOptions,
- )
-
-use-editor-actions.ts
- export function useEditorActions()
-
-## apps/web/src/hooks/storage
-
-use-local-storage.ts
- export function useLocalStorage({
- key,
- defaultValue,
- }: {
- key: string;
- defaultValue: T;
- }): [
- T,
- ({ value }: { value: T | ((previousValue: T) => T) }) => void,
- boolean,
- ]
-
-## apps/web/src/hooks/timeline
-
-use-bookmark-drag.ts
- export interface BookmarkDragState {
- isDragging: boolean
- bookmarkTime: number | null
- currentTime: number
- }
- export function useBookmarkDrag({
- zoomLevel,
- scrollRef,
- snappingEnabled,
- onSnapPointChange,
- }: UseBookmarkDragProps)
-
-use-edge-auto-scroll.ts
- export function useEdgeAutoScroll({
- isActive,
- getMouseClientX,
- rulerScrollRef,
- tracksScrollRef,
- contentWidth,
- edgeThreshold = 100,
- maxScrollSpeed = 15,
- }: UseEdgeAutoScrollParams): void
-
-use-scroll-position.ts
- export function useScrollPosition({
- scrollRef,
- }: {
- scrollRef: React.RefObject<HTMLElement | null>;
- }): UseScrollPositionReturn
-
-use-scroll-sync.ts
- export function useScrollSync({
- tracksScrollRef,
- rulerScrollRef,
- trackLabelsScrollRef,
- bookmarksScrollRef,
- }: UseScrollSyncProps)
-
-use-selection-box.ts
- export function useSelectionBox({
- containerRef,
- onSelectionComplete,
- isEnabled = true,
- tracksScrollRef,
- zoomLevel,
- }: UseSelectionBoxProps)
-
-use-snap-indicator-position.ts
- export function useSnapIndicatorPosition({
- snapPoint,
- zoomLevel,
- tracks,
- timelineRef,
- trackLabelsRef,
- tracksScrollRef,
- }: UseSnapIndicatorPositionParams): SnapIndicatorPosition
-
-use-timeline-drag-drop.ts
- export function useTimelineDragDrop({
- containerRef,
- headerRef,
- zoomLevel,
- }: UseTimelineDragDropProps)
-
-use-timeline-playhead.ts
- export function useTimelinePlayhead({
- zoomLevel,
- rulerRef,
- rulerScrollRef,
- tracksScrollRef,
- playheadRef,
- }: UseTimelinePlayheadProps)
-
-use-timeline-seek.ts
- export function useTimelineSeek({
- playheadRef,
- trackLabelsRef,
- rulerScrollRef,
- tracksScrollRef,
- zoomLevel,
- duration,
- isSelecting,
- clearSelectedElements,
- seek,
- }: UseTimelineSeekProps)
-
-use-timeline-snapping.ts
- export interface SnapPoint {
- time: number
- type: "element-start" | "element-end" | "playhead" | "bookmark"
- elementId?: string
- trackId?: string
- }
- export interface SnapResult {
- snappedTime: number
- snapPoint: SnapPoint | null
- snapDistance: number
- }
- export interface UseTimelineSnappingOptions {
- snapThreshold?: number
- enableElementSnapping?: boolean
- enablePlayheadSnapping?: boolean
- enableBookmarkSnapping?: boolean
- }
- export function useTimelineSnapping({
- snapThreshold = 10,
- enableElementSnapping = true,
- enablePlayheadSnapping = true,
- enableBookmarkSnapping = true,
- }: UseTimelineSnappingOptions = {})
-
-use-timeline-zoom.ts
- export function useTimelineZoom({
- containerRef,
- minZoom = TIMELINE_CONSTANTS.ZOOM_MIN,
- initialZoom,
- initialScrollLeft,
- initialPlayheadTime,
- tracksScrollRef,
- rulerScrollRef,
- }: UseTimelineZoomProps): UseTimelineZoomReturn
-
-## apps/web/src/hooks/timeline/element
-
-use-element-interaction.ts
- export function useElementInteraction({
- zoomLevel,
- timelineRef,
- tracksContainerRef,
- tracksScrollRef,
- headerRef,
- snappingEnabled,
- onSnapPointChange,
- }: UseElementInteractionProps)
-
-use-element-resize.ts
- export interface ResizeState {
- elementId: string
- side: "left" | "right"
- startX: number
- initialTrimStart: number
- initialTrimEnd: number
- initialStartTime: number
- initialDuration: number
- }
- export function useTimelineElementResize({
- element,
- track,
- zoomLevel,
- onSnapPointChange,
- onResizeStateChange,
- }: UseTimelineElementResizeProps)
-
-use-element-selection.ts
- export function useElementSelection()
-
-## apps/web/src/lib
-
-drag-data.ts
- export function setDragData({
- dataTransfer,
- dragData,
- }: {
- dataTransfer: DataTransfer;
- dragData: TimelineDragData;
- }): void
- export function getDragData({
- dataTransfer,
- }: {
- dataTransfer: DataTransfer;
- }): TimelineDragData | null
- export function hasDragData({
- dataTransfer,
- }: {
- dataTransfer: DataTransfer;
- }): boolean
- export function clearDragData(): void
-
-export.ts
- export function getExportMimeType({
- format,
- }: {
- format: ExportFormat;
- }): string
- export function getExportFileExtension({
- format,
- }: {
- format: ExportFormat;
- }): string
-
-iconify-api.ts
- export const ICONIFY_HOSTS
- export interface IconSet {
- prefix: string
- name: string
- total: number
- author?: {
- name: string;
- url?: string;
- }
- license?: {
- title: string;
- spdx?: string;
- url?: string;
- }
- samples?: string[]
- category?: string
- palette?: boolean
- }
- export interface IconSearchResult {
- icons: string[]
- total: number
- limit: number
- start: number
- collections: Record<string, IconSet>
- }
- export interface CollectionInfo {
- prefix: string
- total: number
- title?: string
- uncategorized?: string[]
- categories?: Record<string, string[]>
- hidden?: string[]
- aliases?: Record<string, string>
- }
- export function getCollections(
- category?: string,
- ): Promise<Record<string, IconSet>>
- export function getCollection(
- prefix: string,
- ): Promise<CollectionInfo | null>
- export function searchIcons(
- query: string,
- limit: number = 64,
- prefixes?: string[],
- category?: string,
- ): Promise<IconSearchResult>
- export function buildIconSvgUrl(
- host: string,
- iconName: string,
- params?: {
- color?: string;
- width?: number;
- height?: number;
- flip?: "horizontal" | "vertical" | "horizontal,vertical";
- rotate?: number | string;
- },
- ): string
- export function getIconSvgUrl(
- iconName: string,
- params?: Parameters<typeof buildIconSvgUrl>[2],
- ): string
- export function downloadSvgAsText(
- iconName: string,
- params?: Parameters<typeof getIconSvgUrl>[1],
- ): Promise<string>
- export function svgToFile(svgText: string, fileName: string): File
- export const POPULAR_COLLECTIONS
- export function getCategoriesFromCollections(
- collections: Record<string, IconSet>,
- ): string[]
-
-rate-limit.ts
- export const baseRateLimit
- export function checkRateLimit({ request }: { request: Request })
-
-scenes.ts
- export function getMainScene({ scenes }: { scenes: TScene[] }): TScene | null
- export function ensureMainScene({ scenes }: { scenes: TScene[] }): TScene[]
- export function buildDefaultScene({
- name,
- isMain,
- }: {
- name: string;
- isMain: boolean;
- }): TScene
- export function canDeleteScene({ scene }: { scene: TScene }): {
- canDelete: boolean;
- reason?: string;
- }
- export function getFallbackSceneAfterDelete({
- scenes,
- deletedSceneId,
- currentSceneId,
- }: {
- scenes: TScene[];
- deletedSceneId: string;
- currentSceneId: string | null;
- }): TScene | null
- export function findCurrentScene({
- scenes,
- currentSceneId,
- }: {
- scenes: TScene[];
- currentSceneId: string;
- }): TScene | null
- export function getProjectDurationFromScenes({
- scenes,
- }: {
- scenes: TScene[];
- }): number
- export function updateSceneInArray({
- scenes,
- sceneId,
- updates,
- }: {
- scenes: TScene[];
- sceneId: string;
- updates: Partial<TScene>;
- }): TScene[]
-
-time.ts
- export function roundToFrame({
- time,
- fps,
- }: {
- time: number;
- fps: number;
- }): number
- export function formatTimeCode({
- timeInSeconds,
- format = "HH:MM:SS:CS",
- fps,
- }: {
- timeInSeconds: number;
- format?: TTimeCode;
- fps?: number;
- }): string
- export function parseTimeCode({
- timeCode,
- format = "HH:MM:SS:CS",
- fps,
- }: {
- timeCode: string;
- format?: TTimeCode;
- fps: number;
- }): number | null
- export function guessTimeCodeFormat({
- timeCode,
- }: {
- timeCode: string;
- }): TTimeCode | null
- export function timeToFrame({
- time,
- fps,
- }: {
- time: number;
- fps: number;
- }): number
- export function frameToTime({
- frame,
- fps,
- }: {
- frame: number;
- fps: number;
- }): number
- export function snapTimeToFrame({
- time,
- fps,
- }: {
- time: number;
- fps: number;
- }): number
- export function getSnappedSeekTime({
- rawTime,
- duration,
- fps,
- }: {
- rawTime: number;
- duration: number;
- fps: number;
- }): number
- export function getLastFrameTime({
- duration,
- fps,
- }: {
- duration: number;
- fps: number;
- }): number
-
-## apps/web/src/lib/actions
-
-definitions.ts
- export type TActionCategory = | "playback"
- | "navigation"
- | "editing"
- | "selection"
- | "history"
- | "timeline"
- | "controls"
- export interface TActionDefinition {
- description: string
- category: TActionCategory
- defaultShortcuts?: ShortcutKey[]
- args?: Record<string, unknown>
- }
- export const ACTIONS
- export type TAction = keyof typeof ACTIONS
- export function getActionDefinition(action: TAction): TActionDefinition
- export function getDefaultShortcuts(): Record<ShortcutKey, TAction>
-
-registry.ts
- export function bindAction(
- action: A,
- handler: TActionFunc<A>,
- )
- export function unbindAction(
- action: A,
- handler: TActionFunc<A>,
- )
- export const invokeAction = (
- action: A,
- args?: TArgOfAction<A>,
- trigger?: TInvocationTrigger,
- ) => ...
-
-types.ts
- export type TActionArgsMap = {
- "seek-forward": { seconds: number } | undefined;
- "seek-backward": { seconds: number } | undef...
- export type TActionWithArgs = keyof TActionArgsMap
- export type TActionWithOptionalArgs = | TActionWithNoArgs
- | TKeysWithValueUndefined<TActionArgsMap>
- export type TActionWithNoArgs = Exclude<TAction, TActionWithArgs>
- export type TArgOfAction<A extends TAction> = A extends TActionWithArgs
- ? TActionArgsMap[A]
- : undefined
- export type TActionFunc<A extends TAction> = A extends TActionWithArgs
- ? (arg: TArgOfAction<A>, trigger?: TInvocationTrigger) => void
- : (_?:...
- export type TInvocationTrigger = "keypress" | "mouseclick"
- export type TBoundActionList = {
- [A in TAction]?: Array<TActionFunc<A>>;
- }
- export type TActionHandlerOptions = | MutableRefObject<boolean>
- | boolean
- | undefined
-
-## apps/web/src/lib/auth
-
-server.ts
- export const auth
- export type Auth = typeof auth
-
-## apps/web/src/lib/blog
-
-query.ts
- export function getPosts()
- export function getTags()
- export function getSinglePost({ slug }: { slug: string })
- export function getCategories()
- export function getAuthors()
- export function processHtmlContent({
- html,
- }: {
- html: string;
- }): Promise<string>
-
-## apps/web/src/lib/db
-
-index.ts
- export const db
-
-schema.ts
- export const users
- export const sessions
- export const accounts
- export const verifications
-
-## apps/web/src/lib/fonts
-
-google-fonts.ts
- export function getCachedFontAtlas(): FontAtlas | null
- export function clearFontAtlasCache(): void
- export function prefetchFontAtlas(): Promise<FontAtlas | null>
- export function loadFullFont({
- family,
- weights = [400, 700],
- }: {
- family: string;
- weights?: number[];
- }): Promise<void>
- export function loadFonts({
- families,
- }: {
- families: string[];
- }): Promise<void>
-
-## apps/web/src/lib/gradients
-
-canvas.ts
- export function drawCssBackground({
- ctx,
- width,
- height,
- css,
- }: {
- ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D;
- width: number;
- height: number;
- css: string;
- }): void
-
-parser.ts
- export type GradientOrientation = LinearOrientation | Array<RadialOrientation>
- export type Color = | { type: "hex"; value: string }
- | { type: "literal"; value: string }
- | { type: "rgb"; value: A...
- export type ColorStop = Color & { length?: Distance }
- export type GradientAst = {
- type: GradientType;
- orientation: GradientOrientation | undefined;
- colorStops: Array<ColorSto...
- export const parseGradient = ({
- code,
- }: {
- code: string;
- }): Array<GradientAst> => ...
- export const GradientParser
-
-## apps/web/src/lib/media
-
-audio.ts
- export type CollectedAudioElement = Omit<
- AudioElement,
- "type" | "mediaId" | "volume" | "id" | "name" | "sourceType" | "sourceUrl"
- ...
- export function createAudioContext(): AudioContext
- export interface DecodedAudio {
- samples: Float32Array
- sampleRate: number
- }
- export function decodeAudioToFloat32({
- audioBlob,
- }: {
- audioBlob: Blob;
- }): Promise<DecodedAudio>
- export function collectAudioElements({
- tracks,
- mediaAssets,
- audioContext,
- }: {
- tracks: TimelineTrack[];
- mediaAssets: MediaAsset[];
- audioContext: AudioContext;
- }): Promise<CollectedAudioElement[]>
- export interface AudioClipSource {
- id: string
- sourceKey: string
- file: File
- startTime: number
- duration: number
- trimStart: number
- trimEnd: number
- muted: boolean
- }
- export function collectAudioMixSources({
- tracks,
- mediaAssets,
- }: {
- tracks: TimelineTrack[];
- mediaAssets: MediaAsset[];
- }): Promise<AudioMixSource[]>
- export function collectAudioClips({
- tracks,
- mediaAssets,
- }: {
- tracks: TimelineTrack[];
- mediaAssets: MediaAsset[];
- }): Promise<AudioClipSource[]>
- export function createTimelineAudioBuffer({
- tracks,
- mediaAssets,
- duration,
- sampleRate = 44100,
- audioContext,
- }: {
- tracks: TimelineTrack[];
- mediaAssets: MediaAsset[];
- duration: number;
- sampleRate?: number;
- audioContext?: AudioContext;
- }): Promise<AudioBuffer | null>
-
-media-utils.ts
- export const SUPPORTS_AUDIO: readonly MediaType[]
- export function mediaSupportsAudio({
- media,
- }: {
- media: MediaAsset | null | undefined;
- }): boolean
- export const getMediaTypeFromFile = ({
- file,
- }: {
- file: File;
- }): MediaType | null => ...
-
-mediabunny.ts
- export function getVideoInfo({
- videoFile,
- }: {
- videoFile: File;
- }): Promise<{
- duration: number;
- width: number;
- height: number;
- fps: number;
- }>
- export const extractTimelineAudio = ({
- tracks,
- mediaAssets,
- totalDuration,
- onProgress,
- }: {
- tracks: TimelineTrack[];
- mediaAssets: MediaAsset[];
- totalDuration: number;
- onProgress?: (progress: number) => void;
- }): Promise<Blob> => ...
-
-processing.ts
- export interface ProcessedMediaAsset extends Omit<MediaAsset, "id">
- export function generateThumbnail({
- videoFile,
- timeInSeconds,
- }: {
- videoFile: File;
- timeInSeconds: number;
- }): Promise<string>
- export function generateImageThumbnail({
- imageFile,
- }: {
- imageFile: File;
- }): Promise<string>
- export function processMediaAssets({
- files,
- onProgress,
- }: {
- files: FileList | File[];
- onProgress?: ({ progress }: { progress: number }) => void;
- }): Promise<ProcessedMediaAsset[]>
-
-## apps/web/src/lib/preview
-
-element-bounds.ts
- export interface ElementBounds {
- cx: number
- cy: number
- width: number
- height: number
- rotation: number
- }
- export interface ElementWithBounds {
- trackId: string
- elementId: string
- element: TimelineElement
- bounds: ElementBounds
- }
- export function getElementBounds({
- element,
- canvasSize,
- mediaAsset,
- }: {
- element: TimelineElement;
- canvasSize: { width: number; height: number };
- mediaAsset?: MediaAsset | null;
- }): ElementBounds | null
- export function getVisibleElementsWithBounds({
- tracks,
- currentTime,
- canvasSize,
- mediaAssets,
- }: {
- tracks: TimelineTrack[];
- currentTime: number;
- canvasSize: { width: number; height: number };
- mediaAssets: MediaAsset[];
- }): ElementWithBounds[]
-
-hit-test.ts
- export function hitTest({
- canvasX,
- canvasY,
- elementsWithBounds,
- }: {
- canvasX: number;
- canvasY: number;
- elementsWithBounds: ElementWithBounds[];
- }): ElementWithBounds | null
-
-preview-coords.ts
- export function screenToCanvas({
- clientX,
- clientY,
- canvas,
- }: {
- clientX: number;
- clientY: number;
- canvas: HTMLCanvasElement;
- }): { x: number; y: number }
- export function canvasToOverlay({
- canvasX,
- canvasY,
- canvasRect,
- containerRect,
- canvasSize,
- }: {
- canvasX: number;
- canvasY: number;
- canvasRect: DOMRect;
- containerRect: DOMRect;
- canvasSize: { width: number; height: number };
- }): { x: number; y: number }
- export function positionToOverlay({
- positionX,
- positionY,
- canvasRect,
- containerRect,
- canvasSize,
- }: {
- positionX: number;
- positionY: number;
- canvasRect: DOMRect;
- containerRect: DOMRect;
- canvasSize: { width: number; height: number };
- }): { x: number; y: number }
- export function getDisplayScale({
- canvasRect,
- canvasSize,
- }: {
- canvasRect: DOMRect;
- canvasSize: { width: number; height: number };
- }): { x: number; y: number }
-
-preview-snap.ts
- export interface SnapLine {
- type: "horizontal" | "vertical"
- position: number
- }
- export const MIN_SCALE
- export interface SnapResult {
- snappedPosition: { x: number; y: number }
- activeLines: SnapLine[]
- }
- export function snapPosition({
- proposedPosition,
- canvasSize,
- elementSize,
- }: {
- proposedPosition: { x: number; y: number };
- canvasSize: { width: number; height: number };
- elementSize: { width: number; height: number };
- }): SnapResult
- export interface ScaleSnapResult {
- snappedScale: number
- activeLines: SnapLine[]
- }
- export function snapScale({
- proposedScale,
- position,
- baseWidth,
- baseHeight,
- canvasSize,
- }: {
- proposedScale: number;
- position: { x: number; y: number };
- baseWidth: number;
- baseHeight: number;
- canvasSize: { width: number; height: number };
- }): ScaleSnapResult
- export interface RotationSnapResult {
- snappedRotation: number
- isSnapped: boolean
- }
- export function snapRotation({
- proposedRotation,
- }: {
- proposedRotation: number;
- }): RotationSnapResult
-
-## apps/web/src/lib/stickers
-
-index.ts
- export function searchStickers({
- query,
- category,
- limit = DEFAULT_SEARCH_LIMIT,
- }: {
- query: string;
- category: StickerCategory;
- limit?: number;
- }): Promise<StickerSearchResult>
- export function browseStickers({
- category,
- page = 1,
- limit = DEFAULT_SEARCH_LIMIT,
- }: {
- category: StickerCategory;
- page?: number;
- limit?: number;
- }): Promise<StickerSearchResult>
-
-registry.ts
- export function registerProvider({
- provider,
- }: {
- provider: StickerProvider;
- }): void
- export function hasProvider({ providerId }: { providerId: string }): boolean
- export function getProvider({
- providerId,
- }: {
- providerId: string;
- }): StickerProvider
- export function getAllProviders(): StickerProvider[]
-
-resolver.ts
- export function resolveStickerId({
- stickerId,
- options,
- }: {
- stickerId: string;
- options?: StickerResolveOptions;
- }): string
-
-sticker-id.ts
- export function parseStickerId({ stickerId }: { stickerId: string }): {
- providerId: string;
- providerValue: string;
- }
- export function buildStickerId({
- providerId,
- providerValue,
- }: {
- providerId: string;
- providerValue: string;
- }): string
-
-## apps/web/src/lib/stickers/providers
-
-emoji.ts
- export const emojiProvider: StickerProvider
-
-flags.ts
- export const flagsProvider: StickerProvider
-
-icons.ts
- export const iconsProvider: StickerProvider
-
-index.ts
- export function registerDefaultStickerProviders({
- providersToRegister = defaultProviders,
- }: {
- providersToRegister?: StickerProvider[];
- } = {}): void
-
-shapes.ts
- export const shapesProvider: StickerProvider
-
-## apps/web/src/lib/timeline
-
-bookmarks.ts
- export const BOOKMARK_TIME_EPSILON
- export function findBookmarkIndex({
- bookmarks,
- frameTime,
- }: {
- bookmarks: Bookmark[];
- frameTime: number;
- }): number
- export function isBookmarkAtTime({
- bookmarks,
- frameTime,
- }: {
- bookmarks: Bookmark[];
- frameTime: number;
- }): boolean
- export function toggleBookmarkInArray({
- bookmarks,
- frameTime,
- }: {
- bookmarks: Bookmark[];
- frameTime: number;
- }): Bookmark[]
- export function removeBookmarkFromArray({
- bookmarks,
- frameTime,
- }: {
- bookmarks: Bookmark[];
- frameTime: number;
- }): Bookmark[]
- export function updateBookmarkInArray({
- bookmarks,
- frameTime,
- updates,
- }: {
- bookmarks: Bookmark[];
- frameTime: number;
- updates: Partial<Omit<Bookmark, "time">>;
- }): Bookmark[]
- export function moveBookmarkInArray({
- bookmarks,
- fromTime,
- toTime,
- }: {
- bookmarks: Bookmark[];
- fromTime: number;
- toTime: number;
- }): Bookmark[]
- export function getFrameTime({
- time,
- fps,
- }: {
- time: number;
- fps: number;
- }): number
- export function getBookmarkAtTime({
- bookmarks,
- frameTime,
- }: {
- bookmarks: Bookmark[];
- frameTime: number;
- }): Bookmark | null
- export function getBookmarksActiveAtTime({
- bookmarks,
- time,
- }: {
- bookmarks: Bookmark[];
- time: number;
- }): Bookmark[]
-
-drag-utils.ts
- export function getMouseTimeFromClientX({
- clientX,
- containerRect,
- zoomLevel,
- scrollLeft,
- }: {
- clientX: number;
- containerRect: DOMRect;
- zoomLevel: number;
- scrollLeft: number;
- }): number
-
-drop-utils.ts
- export function computeDropTarget({
- elementType,
- mouseX,
- mouseY,
- tracks,
- playheadTime,
- isExternalDrop,
- elementDuration,
- pixelsPerSecond,
- zoomLevel,
- verticalDragDirection,
- startTimeOverride,
- excludeElementId,
- }: ComputeDropTargetParams): DropTarget
- export function getDropLineY({
- dropTarget,
- tracks,
- }: {
- dropTarget: DropTarget;
- tracks: TimelineTrack[];
- }): number
-
-element-utils.ts
- export function canElementHaveAudio(
- element: TimelineElement,
- )
- export function isVisualElement(
- element: TimelineElement,
- )
- export function canElementBeHidden(
- element: TimelineElement,
- )
- export function hasMediaId(
- element: TimelineElement,
- )
- export function requiresMediaId({
- element,
- }: {
- element: CreateTimelineElement;
- }): boolean
- export function checkElementOverlaps({
- elements,
- }: {
- elements: TimelineElement[];
- }): boolean
- export function resolveElementOverlaps({
- elements,
- }: {
- elements: TimelineElement[];
- }): TimelineElement[]
- export function wouldElementOverlap({
- elements,
- startTime,
- endTime,
- excludeElementId,
- }: {
- elements: TimelineElement[];
- startTime: number;
- endTime: number;
- excludeElementId?: string;
- }): boolean
- export function buildTextElement({
- raw,
- startTime,
- }: {
- raw: Partial<Omit<TextElement, "type" | "id">>;
- startTime: number;
- }): CreateTimelineElement
- export function buildStickerElement({
- stickerId,
- name,
- startTime,
- }: {
- stickerId: string;
- name?: string;
- startTime: number;
- }): CreateStickerElement
- export function buildVideoElement({
- mediaId,
- name,
- duration,
- startTime,
- }: {
- mediaId: string;
- name: string;
- duration: number;
- startTime: number;
- }): CreateVideoElement
- export function buildImageElement({
- mediaId,
- name,
- duration,
- startTime,
- }: {
- mediaId: string;
- name: string;
- duration: number;
- startTime: number;
- }): CreateImageElement
- export function buildUploadAudioElement({
- mediaId,
- name,
- duration,
- startTime,
- buffer,
- }: {
- mediaId: string;
- name: string;
- duration: number;
- startTime: number;
- buffer?: AudioBuffer;
- }): CreateUploadAudioElement
- export function buildElementFromMedia({
- mediaId,
- mediaType,
- name,
- duration,
- startTime,
- buffer,
- }: {
- mediaId: string;
- mediaType: MediaType;
- name: string;
- duration: number;
- startTime: number;
- buffer?: AudioBuffer;
- }): CreateTimelineElement
- export function buildLibraryAudioElement({
- sourceUrl,
- name,
- duration,
- startTime,
- buffer,
- }: {
- sourceUrl: string;
- name: string;
- duration: number;
- startTime: number;
- buffer?: AudioBuffer;
- }): CreateLibraryAudioElement
- export function getElementsAtTime({
- tracks,
- time,
- }: {
- tracks: TimelineTrack[];
- time: number;
- }): { trackId: string; elementId: string }[]
- export function collectFontFamilies({
- tracks,
- }: {
- tracks: TimelineTrack[];
- }): string[]
-
-index.ts
- export function calculateTotalDuration({
- tracks,
- }: {
- tracks: TimelineTrack[];
- }): number
-
-ruler-utils.ts
- export interface RulerConfig {
- labelIntervalSeconds: number
- tickIntervalSeconds: number
- }
- export function getRulerConfig({
- zoomLevel,
- fps,
- }: {
- zoomLevel: number;
- fps: number;
- }): RulerConfig
- export function shouldShowLabel({
- time,
- labelIntervalSeconds,
- }: {
- time: number;
- labelIntervalSeconds: number;
- }): boolean
- export function formatRulerLabel({
- timeInSeconds,
- fps,
- }: {
- timeInSeconds: number;
- fps: number;
- }): string
-
-track-utils.ts
- export function canTracktHaveAudio(
- track: TimelineTrack,
- )
- export function canTrackBeHidden(
- track: TimelineTrack,
- )
- export function getTrackColor({ type }: { type: TrackType })
- export function getTrackClasses({ type }: { type: TrackType })
- export function getTrackHeight({ type }: { type: TrackType }): number
- export function getCumulativeHeightBefore({
- tracks,
- trackIndex,
- }: {
- tracks: Array<{ type: TrackType }>;
- trackIndex: number;
- }): number
- export function getTotalTracksHeight({
- tracks,
- }: {
- tracks: Array<{ type: TrackType }>;
- }): number
- export function buildEmptyTrack({
- id,
- type,
- name,
- }: {
- id: string;
- type: TrackType;
- name?: string;
- }): TimelineTrack
- export function getDefaultInsertIndexForTrack({
- tracks,
- trackType,
- }: {
- tracks: TimelineTrack[];
- trackType: TrackType;
- }): number
- export function getHighestInsertIndexForTrack({
- tracks,
- trackType,
- }: {
- tracks: TimelineTrack[];
- trackType: TrackType;
- }): number
- export function isMainTrack(track: TimelineTrack)
- export function getMainTrack({
- tracks,
- }: {
- tracks: TimelineTrack[];
- }): TimelineTrack | null
- export function ensureMainTrack({
- tracks,
- }: {
- tracks: TimelineTrack[];
- }): TimelineTrack[]
- export function canElementGoOnTrack({
- elementType,
- trackType,
- }: {
- elementType: ElementType;
- trackType: TrackType;
- }): boolean
- export function validateElementTrackCompatibility({
- element,
- track,
- }: {
- element: { type: ElementType };
- track: { type: TrackType };
- }): { isValid: boolean; errorMessage?: string }
- export function getEarliestMainTrackElement({
- tracks,
- excludeElementId,
- }: {
- tracks: TimelineTrack[];
- excludeElementId?: string;
- }): TimelineElement | null
- export function enforceMainTrackStart({
- tracks,
- targetTrackId,
- requestedStartTime,
- excludeElementId,
- }: {
- tracks: TimelineTrack[];
- targetTrackId: string;
- requestedStartTime: number;
- excludeElementId?: string;
- }): number
-
-zoom-utils.ts
- export function getTimelineZoomMin({
- duration,
- containerWidth,
- }: {
- duration: number;
- containerWidth: number | null | undefined;
- }): number
- export function getTimelinePaddingPx({
- containerWidth,
- zoomLevel,
- minZoom,
- }: {
- containerWidth: number;
- zoomLevel: number;
- minZoom: number;
- }): number
- export function getZoomPercent({
- zoomLevel,
- minZoom,
- }: {
- zoomLevel: number;
- minZoom: number;
- }): number
- export function sliderToZoom({
- sliderPosition,
- minZoom,
- maxZoom = TIMELINE_CONSTANTS.ZOOM_MAX,
- }: {
- sliderPosition: number;
- minZoom: number;
- maxZoom?: number;
- }): number
- export function zoomToSlider({
- zoomLevel,
- minZoom,
- maxZoom = TIMELINE_CONSTANTS.ZOOM_MAX,
- }: {
- zoomLevel: number;
- minZoom: number;
- maxZoom?: number;
- }): number
-
-## apps/web/src/lib/transcription
-
-caption.ts
- export function buildCaptionChunks({
- segments,
- wordsPerChunk = DEFAULT_WORDS_PER_CAPTION,
- minDuration = MIN_CAPTION_DURATION_SECONDS,
- }: {
- segments: TranscriptionSegment[];
- wordsPerChunk?: number;
- minDuration?: number;
- }): CaptionChunk[]
-
-## apps/web/src/services/renderer
-
-canvas-renderer.ts
- export type CanvasRendererParams = {
- width: number;
- height: number;
- fps: number;
- }
- export class CanvasRenderer {
- canvas: OffscreenCanvas | HTMLCanvasElement
- context: OffscreenCanvasRenderingContext2D | CanvasRenderingContext2D
- width: number
- height: number
- fps: number
- constructor({ width, height, fps }: CanvasRendererParams)
- setSize({ width, height }: { width: number; height: number })
- async render({ node, time }: { node: BaseNode; time: number })
- async renderToCanvas({
- node,
- time,
- targetCanvas,
- }: {
- node: BaseNode;
- time: number;
- targetCanvas: HTMLCanvasElement;
- })
- }
-
-scene-builder.ts
- export type BuildSceneParams = {
- canvasSize: TCanvasSize;
- tracks: TimelineTrack[];
- mediaAssets: MediaAsset[];
- duration: numb...
- export function buildScene(params: BuildSceneParams)
-
-scene-exporter.ts
- export type ExportFormat = "mp4" | "webm"
- export type ExportQuality = "low" | "medium" | "high" | "very_high"
- export type SceneExporterEvents = {
- progress: [progress: number];
- complete: [buffer: ArrayBuffer];
- error: [error: Error];
- cance...
- export class SceneExporter extends EventEmitter<SceneExporterEvents> {
- renderer: CanvasRenderer
- format: ExportFormat
- quality: ExportQuality
- shouldIncludeAudio: boolean
- audioBuffer: AudioBuffer
- isCancelled
- constructor({
- width,
- height,
- fps,
- format,
- quality,
- shouldIncludeAudio,
- audioBuffer,
- }: ExportParams)
- cancel(): void
- async export({
- rootNode,
- }: {
- rootNode: RootNode;
- }): Promise<ArrayBuffer | null>
- }
-
-## apps/web/src/services/storage
-
-indexeddb-adapter.ts
- export class IndexedDBAdapter implements StorageAdapter<T> {
- dbName: string
- storeName: string
- version: number
- constructor(dbName: string, storeName: string, version = 1)
- async get(key: string): Promise<T | null>
- async set(key: string, value: T): Promise<void>
- async remove(key: string): Promise<void>
- async list(): Promise<string[]>
- async getAll(): Promise<T[]>
- async clear(): Promise<void>
- }
- export function deleteDatabase({
- dbName,
- }: {
- dbName: string;
- }): Promise<void>
-
-opfs-adapter.ts
- export class OPFSAdapter implements StorageAdapter<File> {
- directoryName: string
- constructor(directoryName = "media")
- async get(key: string): Promise<File | null>
- async set(key: string, file: File): Promise<void>
- async remove(key: string): Promise<void>
- async list(): Promise<string[]>
- async clear(): Promise<void>
- static isSupported(): boolean
- }
-
-service.ts
- export const storageService
-
-types.ts
- export interface StorageAdapter<T> {
- get(key: string): Promise<T | null>
- set(key: string, value: T): Promise<void>
- remove(key: string): Promise<void>
- list(): Promise<string[]>
- clear(): Promise<void>
- }
- export interface MediaAssetData {
- id: string
- name: string
- type: MediaType
- size: number
- lastModified: number
- width?: number
- height?: number
- duration?: number
- fps?: number
- ephemeral?: boolean
- thumbnailUrl?: string
- }
- export type SerializedScene = Omit<TScene, "createdAt" | "updatedAt"> & {
- createdAt: string;
- updatedAt: string;
- }
- export type SerializedProjectMetadata = Omit<
- TProjectMetadata,
- "createdAt" | "updatedAt"
- > & {
- createdAt: string;
- updatedAt: string;
- }
- export type SerializedProject = Omit<TProject, "metadata" | "scenes"> & {
- metadata: SerializedProjectMetadata;
- scenes: Serializ...
- export interface StorageConfig {
- projectsDb: string
- mediaDb: string
- savedSoundsDb: string
- version: number
- }
-
-## apps/web/src/services/transcription
-
-service.ts
- export const transcriptionService
-
-worker.ts
- export type WorkerMessage = | { type: "init"; modelId: string }
- | { type: "transcribe"; audio: Float32Array; language: strin...
- export type WorkerResponse = | { type: "init-progress"; progress: number }
- | { type: "init-complete" }
- | { type: "init-error...
-
-## apps/web/src/services/video-cache
-
-service.ts
- export class VideoCache {
- sinks
- initPromises
- async getFrameAt({
- mediaId,
- file,
- time,
- }: {
- mediaId: string;
- file: File;
- time: number;
- }): Promise<WrappedCanvas | null>
- clearVideo({ mediaId }: { mediaId: string }): void
- clearAll(): void
- getStats()
- }
- export const videoCache
-
-## apps/web/src/stores
-
-assets-panel-store.tsx
- export const TAB_KEYS
- export type Tab = (typeof TAB_KEYS)[number]
- export const tabs
- export const useAssetsPanelStore
-
-editor-store.ts
- export const useEditorStore
-
-keybindings-store.ts
- export const defaultKeybindings: KeybindingConfig
- export interface KeybindingConflict {
- key: ShortcutKey
- existingAction: TActionWithOptionalArgs
- newAction: TActionWithOptionalArgs
- }
- export const useKeybindingsStore
-
-panel-store.ts
- export interface PanelSizes {
- tools: number
- preview: number
- properties: number
- mainContent: number
- timeline: number
- }
- export type PanelId = keyof PanelSizes
- export const usePanelStore
-
-preview-store.ts
- export const usePreviewStore
-
-sounds-store.ts
- export const useSoundsStore
-
-stickers-store.ts
- export const useStickersStore
-
-timeline-store.ts
- export const useTimelineStore
-
-## apps/web/src/types
-
-assets.ts
- export type MediaType = "image" | "video" | "audio"
- export interface MediaAsset extends Omit<MediaAssetData, "size" | "lastModified"> {
- file: File
- url?: string
- }
-
-blog.ts
- export type Post = {
- id: string;
- slug: string;
- title: string;
- content: string;
- description: string;
- coverImage...
- export type Pagination = {
- limit: number;
- currpage: number;
- nextPage: number | null;
- prevPage: number | null;
- totalIt...
- export type MarblePostList = {
- posts: Post[];
- pagination: Pagination;
- }
- export type MarblePost = {
- post: Post;
- }
- export type Tag = {
- id: string;
- name: string;
- slug: string;
- }
- export type MarbleTag = {
- tag: Tag;
- }
- export type MarbleTagList = {
- tags: Tag[];
- pagination: Pagination;
- }
- export type Category = {
- id: string;
- name: string;
- slug: string;
- }
- export type MarbleCategory = {
- category: Category;
- }
- export type MarbleCategoryList = {
- categories: Category[];
- pagination: Pagination;
- }
- export type Author = {
- id: string;
- name: string;
- image: string;
- }
- export type MarbleAuthor = {
- author: Author;
- }
- export type MarbleAuthorList = {
- authors: Author[];
- pagination: Pagination;
- }
-
-drag.ts
- export interface MediaDragData extends BaseDragData {
- type: "media"
- mediaType: "image" | "video" | "audio"
- }
- export interface TextDragData extends BaseDragData {
- type: "text"
- content: string
- }
- export interface StickerDragData extends BaseDragData {
- type: "sticker"
- stickerId: string
- }
- export type TimelineDragData = MediaDragData | TextDragData | StickerDragData
-
-editor.ts
- export type TPlatformLayout = "tiktok"
-
-export.ts
- export const EXPORT_QUALITY_VALUES
- export const EXPORT_FORMAT_VALUES
- export type ExportFormat = (typeof EXPORT_FORMAT_VALUES)[number]
- export type ExportQuality = (typeof EXPORT_QUALITY_VALUES)[number]
- export interface ExportOptions {
- format: ExportFormat
- quality: ExportQuality
- fps?: number
- includeAudio?: boolean
- onProgress?: ({ progress }: { progress: number }) => void
- onCancel?: () => boolean
- }
- export interface ExportResult {
- success: boolean
- buffer?: ArrayBuffer
- error?: string
- cancelled?: boolean
- }
-
-fonts.ts
- export interface FontOption {
- value: string
- label: string
- category: "system" | "google" | "custom"
- weights?: number[]
- hasClassName?: boolean
- }
- export interface GoogleFontMeta {
- family: string
- category: string
- }
- export interface FontAtlasEntry {
- x: number
- y: number
- w: number
- ch: number
- s: string[]
- }
- export interface FontAtlas {
- fonts: Record<string, FontAtlasEntry>
- }
-
-keybinding.ts
- export type ModifierKeys = | "ctrl"
- | "alt"
- | "shift"
- | "ctrl+shift"
- | "alt+shift"
- | "ctrl+alt"
- | "ctrl+alt+shift"
- export type Key = | "a"
- | "b"
- | "c"
- | "d"
- | "e"
- | "f"
- | "g"
- | "h"
- | "i"
- | "j"
- | "k"
- | "l"
- | "m"
- | "n"
- ...
- export type ModifierBasedShortcutKey = `${ModifierKeys}+${Key}`
- export type SingleCharacterShortcutKey = `${Key}`
- export type ShortcutKey = ModifierBasedShortcutKey | SingleCharacterShortcutKey
- export type KeybindingConfig = {
- [key in ShortcutKey]?: TActionWithOptionalArgs;
- }
-
-language.ts
- export type Language = (typeof LANGUAGES)[number]
- export type LanguageCode = Language["code"]
-
-project.ts
- export type TBackground = | {
- type: "color";
- color: string;
- }
- | {
- type: "blur";
- blurIntensity: number;
- }
- export interface TCanvasSize {
- width: number
- height: number
- }
- export interface TProjectMetadata {
- id: string
- name: string
- thumbnail?: string
- duration: number
- createdAt: Date
- updatedAt: Date
- }
- export interface TProjectSettings {
- fps: number
- canvasSize: TCanvasSize
- originalCanvasSize?: TCanvasSize | null
- background: TBackground
- }
- export interface TTimelineViewState {
- zoomLevel: number
- scrollLeft: number
- playheadTime: number
- }
- export interface TProject {
- metadata: TProjectMetadata
- scenes: TScene[]
- currentSceneId: string
- settings: TProjectSettings
- version: number
- timelineViewState?: TTimelineViewState
- }
- export type TProjectSortKey = "createdAt" | "updatedAt" | "name" | "duration"
- export type TSortOrder = "asc" | "desc"
- export type TProjectSortOption = `${TProjectSortKey}-${TSortOrder}`
-
-rendering.ts
- export type BlendMode = | "normal"
- | "darken"
- | "multiply"
- | "color-burn"
- | "lighten"
- | "screen"
- | "plus-ligh...
-
-sounds.ts
- export interface SoundEffect {
- id: number
- name: string
- description: string
- url: string
- previewUrl?: string
- downloadUrl?: string
- duration: number
- filesize: number
- type: string
- channels: number
- bitrate: number
- bitdepth: number
- samplerate: number
- username: string
- tags: string[]
- license: string
- created: string
- downloads: number
- rating: number
- ratingCount: number
- }
- export interface SavedSound {
- id: number
- name: string
- username: string
- previewUrl?: string
- downloadUrl?: string
- duration: number
- tags: string[]
- license: string
- savedAt: string
- }
- export interface SavedSoundsData {
- sounds: SavedSound[]
- lastModified: string
- }
-
-stickers.ts
- export type StickerCategory = keyof typeof STICKER_CATEGORIES
- export interface StickerItem {
- id: string
- provider: string
- name: string
- previewUrl: string
- metadata: Record<string, unknown>
- }
- export interface StickerSearchResult {
- items: StickerItem[]
- total: number
- hasMore: boolean
- }
- export interface StickerProviderSearchOptions {
- limit?: number
- }
- export interface StickerProviderBrowseOptions {
- page?: number
- limit?: number
- }
- export interface StickerResolveOptions {
- width?: number
- height?: number
- }
- export interface StickerProvider {
- id: string
- search({
- query,
- options,
- }: {
- query: string;
- options?: StickerProviderSearchOptions;
- }): Promise<StickerSearchResult>
- browse({
- options,
- }: {
- options?: StickerProviderBrowseOptions;
- }): Promise<StickerSearchResult>
- resolveUrl({
- stickerId,
- options,
- }: {
- stickerId: string;
- options?: StickerResolveOptions;
- }): string
- }
-
-time.ts
- export type TTimeCode = "MM:SS" | "HH:MM:SS" | "HH:MM:SS:CS" | "HH:MM:SS:FF"
-
-timeline.ts
- export interface Bookmark {
- time: number
- note?: string
- color?: string
- duration?: number
- }
- export interface TScene {
- id: string
- name: string
- isMain: boolean
- tracks: TimelineTrack[]
- bookmarks: Bookmark[]
- createdAt: Date
- updatedAt: Date
- }
- export type TrackType = "video" | "text" | "audio" | "sticker"
- export interface VideoTrack extends BaseTrack {
- type: "video"
- elements: (VideoElement | ImageElement)[]
- isMain: boolean
- muted: boolean
- hidden: boolean
- }
- export interface TextTrack extends BaseTrack {
- type: "text"
- elements: TextElement[]
- hidden: boolean
- }
- export interface AudioTrack extends BaseTrack {
- type: "audio"
- elements: AudioElement[]
- muted: boolean
- }
- export interface StickerTrack extends BaseTrack {
- type: "sticker"
- elements: StickerElement[]
- hidden: boolean
- }
- export type TimelineTrack = VideoTrack | TextTrack | AudioTrack | StickerTrack
- export interface Transform {
- scale: number
- position: {
- x: number;
- y: number;
- }
- rotate: number
- }
- export interface UploadAudioElement extends BaseAudioElement {
- sourceType: "upload"
- mediaId: string
- }
- export interface LibraryAudioElement extends BaseAudioElement {
- sourceType: "library"
- sourceUrl: string
- }
- export type AudioElement = UploadAudioElement | LibraryAudioElement
- export interface VideoElement extends BaseTimelineElement {
- type: "video"
- mediaId: string
- muted?: boolean
- hidden?: boolean
- transform: Transform
- opacity: number
- blendMode?: BlendMode
- }
- export interface ImageElement extends BaseTimelineElement {
- type: "image"
- mediaId: string
- hidden?: boolean
- transform: Transform
- opacity: number
- blendMode?: BlendMode
- }
- export interface TextElement extends BaseTimelineElement {
- type: "text"
- content: string
- fontSize: number
- fontFamily: string
- color: string
- backgroundColor: string
- textAlign: "left" | "center" | "right"
- fontWeight: "normal" | "bold"
- fontStyle: "normal" | "italic"
- textDecoration: "none" | "underline" | "line-through"
- letterSpacing?: number
- lineHeight?: number
- hidden?: boolean
- transform: Transform
- opacity: number
- blendMode?: BlendMode
- }
- export interface StickerElement extends BaseTimelineElement {
- type: "sticker"
- stickerId: string
- hidden?: boolean
- transform: Transform
- opacity: number
- blendMode?: BlendMode
- }
- export type TimelineElement = | AudioElement
- | VideoElement
- | ImageElement
- | TextElement
- | StickerElement
- export type ElementType = TimelineElement["type"]
- export type CreateUploadAudioElement = Omit<UploadAudioElement, "id">
- export type CreateLibraryAudioElement = Omit<LibraryAudioElement, "id">
- export type CreateAudioElement = | CreateUploadAudioElement
- | CreateLibraryAudioElement
- export type CreateVideoElement = Omit<VideoElement, "id">
- export type CreateImageElement = Omit<ImageElement, "id">
- export type CreateTextElement = Omit<TextElement, "id">
- export type CreateStickerElement = Omit<StickerElement, "id">
- export type CreateTimelineElement = | CreateAudioElement
- | CreateVideoElement
- | CreateImageElement
- | CreateTextElement
- | CreateSt...
- export interface ElementDragState {
- isDragging: boolean
- elementId: string | null
- trackId: string | null
- startMouseX: number
- startMouseY: number
- startElementTime: number
- clickOffsetTime: number
- currentTime: number
- currentMouseY: number
- }
- export interface DropTarget {
- trackIndex: number
- isNewTrack: boolean
- insertPosition: "above" | "below" | null
- xPosition: number
- }
- export interface ComputeDropTargetParams {
- elementType: ElementType
- mouseX: number
- mouseY: number
- tracks: TimelineTrack[]
- playheadTime: number
- isExternalDrop: boolean
- elementDuration: number
- pixelsPerSecond: number
- zoomLevel: number
- verticalDragDirection?: "up" | "down" | null
- startTimeOverride?: number
- excludeElementId?: string
- }
- export interface ClipboardItem {
- trackId: string
- trackType: TrackType
- element: CreateTimelineElement
- }
-
-transcription.ts
- export type TranscriptionLanguage = LanguageCode | "auto"
- export interface TranscriptionSegment {
- text: string
- start: number
- end: number
- }
- export interface TranscriptionResult {
- text: string
- segments: TranscriptionSegment[]
- language: string
- }
- export type TranscriptionStatus = | "idle"
- | "loading-model"
- | "transcribing"
- | "complete"
- | "error"
- export interface TranscriptionProgress {
- status: TranscriptionStatus
- progress: number
- message?: string
- }
- export type TranscriptionModelId = | "whisper-tiny"
- | "whisper-small"
- | "whisper-medium"
- | "whisper-large-v3-turbo"
- export interface TranscriptionModel {
- id: TranscriptionModelId
- name: string
- huggingFaceId: string
- description: string
- }
- export interface CaptionChunk {
- text: string
- startTime: number
- duration: number
- }
-
-## apps/web/src/utils
-
-browser.ts
- export function isTypableDOMElement({
- element,
- }: {
- element: HTMLElement;
- }): boolean
-
-color.ts
- export type ColorFormat = "hex" | "rgb" | "hsl" | "hsv"
- export function hexToHsv({ hex }: { hex: string }): [number, number, number]
- export function hsvToHex({
- h,
- s,
- v,
- }: { h: number; s: number; v: number }): string
- export function parseHexAlpha({ hex }: { hex: string }): {
- rgb: string;
- alpha: number;
- }
- export function appendAlpha({
- rgbHex,
- alpha,
- }: { rgbHex: string; alpha: number }): string
- export function extractColorFromText({
- text,
- }: { text: string }): string | null
- export function formatColorValue({
- hex,
- format,
- }: {
- hex: string;
- format: ColorFormat;
- }): string
- export function parseColorInput({
- input,
- format,
- }: {
- input: string;
- format: ColorFormat;
- }): string | null
-
-date.ts
- export function formatDate({ date }: { date: Date }): string
-
-geometry.ts
- export function dimensionToAspectRatio({
- width,
- height,
- }: {
- width: number;
- height: number;
- }): string
-
-id.ts
- export function generateUUID(): string
-
-math.ts
- export function clamp({
- value,
- min,
- max,
- }: {
- value: number;
- min: number;
- max: number;
- }): number
- export function evaluateMathExpression({
- input,
- }: {
- input: string;
- }): number | null
-
-platform.ts
- export function getPlatformSpecialKey(): string
- export function getPlatformAlternateKey(): string
- export function isAppleDevice(): boolean
-
-string.ts
- export function capitalizeFirstLetter({ string }: { string: string })
- export function uppercase({ string }: { string: string })
-
-ui.ts
- export function cn(...inputs: ClassValue[]): string
-
-## packages/ui/src/icons
-
-brand.tsx
- export function OcVercelIcon({ className }: { className?: string })
- export function OcMarbleIcon({
- className = "",
- size = 32,
- }: {
- className?: string;
- size?: number;
- })
- export function OcDataBuddyIcon({
- className = "",
- size = 32,
- }: {
- className?: string;
- size?: number;
- })
-
-ui.tsx
- export function OcVideoIcon({
- className = "",
- size = 32,
- }: {
- className?: string;
- size?: number;
- })
- export function OcCheckerboardIcon({
- className = "",
- size = 32,
- }: {
- className?: string;
- size?: number;
- })
- export function OcFontWeightIcon({
- className = "",
- size = 32,
- }: {
- className?: string;
- size?: number;
- })
- export function OcSlidersVerticalIcon({
- className = "",
- size = 32,
- }: {
- className?: string;
- size?: number;
- })
- export function OcSocialIcon({
- className = "",
- size = 32,
- }: {
- className?: string;
- size?: number;
- })
-
-```
-
----
-
-*Generated and maintained by [Twiggy](https://github.com/twiggy-tools/Twiggy)*
+---
+alwaysApply: false
+---
+
+# video-editor-oss Codebase Index
+
+**This file provides an index of exported functions, types, interfaces, classes, and constants in your codebase.**
+
+Updated in real-time by Twiggy. Use this to discover existing utilities and avoid duplicating code.
+
+## How to Use
+
+When implementing new features:
+
+1. Check if similar functionality already exists
+2. Reuse existing types and utilities
+3. Understand the API surface of your codebase
+
+```typescript
+## apps/web/src/constants
+
+editor-constants.ts
+ export const PANEL_CONFIG
+
+export-constants.ts
+ export const DEFAULT_EXPORT_OPTIONS
+ export const EXPORT_MIME_TYPES
+
+font-constants.ts
+ export const DEFAULT_FONT
+ export const SYSTEM_FONTS
+
+language-constants.ts
+ export const LANGUAGES
+
+project-constants.ts
+ export const DEFAULT_CANVAS_PRESETS: TCanvasSize[]
+ export const FPS_PRESETS
+ export const BLUR_INTENSITY_PRESETS: { label: string; value: number }[]
+ export const DEFAULT_CANVAS_SIZE: TCanvasSize
+ export const DEFAULT_FPS
+ export const DEFAULT_BLUR_INTENSITY
+ export const DEFAULT_COLOR
+
+site-constants.ts
+ export const SITE_URL
+ export const SITE_INFO
+ export type ExternalTool = {
+ name: string;
+ description: string;
+ url: string;
+ icon: React.ElementType;
+ }
+ export const EXTERNAL_TOOLS: ExternalTool[]
+ export const DEFAULT_LOGO_URL
+ export const SOCIAL_LINKS
+ export type Sponsor = {
+ name: string;
+ url: string;
+ logo: string;
+ description: string;
+ }
+ export const SPONSORS: Sponsor[]
+
+sticker-constants.ts
+ export const STICKER_CATEGORIES
+
+text-constants.ts
+ export const MIN_FONT_SIZE
+ export const MAX_FONT_SIZE
+ export const FONT_SIZE_SCALE_REFERENCE
+ export const DEFAULT_LETTER_SPACING
+ export const DEFAULT_LINE_HEIGHT
+ export const DEFAULT_TEXT_ELEMENT: Omit<TextElement, "id">
+
+timeline-constants.tsx
+ export const DEFAULT_TRANSFORM: Transform
+ export const DEFAULT_OPACITY
+ export const DEFAULT_BLEND_MODE: BlendMode
+ export const DEFAULT_BOOKMARK_COLOR
+ export const TRACK_COLORS: Record<TrackType, { background: string }>
+ export const TRACK_HEIGHTS: Record<TrackType, number>
+ export const TRACK_GAP
+ export const DRAG_THRESHOLD_PX
+ export const TIMELINE_CONSTANTS
+ export const DEFAULT_TIMELINE_VIEW_STATE: TTimelineViewState
+ export const TRACK_ICONS: Record<TrackType, React.ReactNode>
+
+transcription-constants.ts
+ export const TRANSCRIPTION_LANGUAGES
+ export const TRANSCRIPTION_MODELS: TranscriptionModel[]
+ export const DEFAULT_TRANSCRIPTION_MODEL: TranscriptionModelId
+ export const DEFAULT_CHUNK_LENGTH_SECONDS
+ export const DEFAULT_STRIDE_SECONDS
+ export const DEFAULT_WORDS_PER_CAPTION
+ export const MIN_CAPTION_DURATION_SECONDS
+
+## apps/web/src/core
+
+index.ts
+ export class EditorCore {
+ instance: EditorCore | null
+ command: CommandManager
+ playback: PlaybackManager
+ timeline: TimelineManager
+ scenes: ScenesManager
+ project: ProjectManager
+ media: MediaManager
+ renderer: RendererManager
+ save: SaveManager
+ audio: AudioManager
+ selection: SelectionManager
+ static getInstance(): EditorCore
+ static reset(): void
+ }
+
+## apps/web/src/hooks
+
+use-container-size.ts
+ export function useContainerSize({
+ containerRef,
+ }: {
+ containerRef: React.RefObject<HTMLElement | null>;
+ })
+
+use-editor.ts
+ export function useEditor(): EditorCore
+
+use-file-upload.ts
+ export function useFileUpload({
+ accept,
+ multiple,
+ onFilesSelected,
+ }: UseFileUploadOptions = {})
+
+use-focus-lock.ts
+ export function useFocusLock({
+ isActive,
+ onDismiss,
+ cursor = "default",
+ allowSelector,
+ }: {
+ isActive: boolean;
+ onDismiss: () => void;
+ cursor?: FocusLockCursor;
+ allowSelector?: string;
+ })
+
+use-fullscreen.ts
+ export function useFullscreen({
+ containerRef,
+ }: {
+ containerRef: React.RefObject<HTMLElement | null>;
+ })
+
+use-infinite-scroll.ts
+ export function useInfiniteScroll({
+ onLoadMore,
+ hasMore,
+ isLoading,
+ threshold = 200,
+ enabled = true,
+ }: UseInfiniteScrollOptions)
+
+use-keybindings.ts
+ export function useKeybindingsListener()
+ export function useKeybindingDisabler()
+
+use-keyboard-shortcuts-help.ts
+ export interface KeyboardShortcut {
+ id: string
+ keys: string[]
+ description: string
+ category: string
+ action: TAction
+ icon?: React.ReactNode
+ }
+ export function useKeyboardShortcutsHelp()
+
+use-mobile.ts
+ export function useIsMobile()
+
+use-paste-media.ts
+ export function usePasteMedia()
+
+use-preview-interaction.ts
+ export function usePreviewInteraction({
+ canvasRef,
+ }: {
+ canvasRef: React.RefObject<HTMLCanvasElement | null>;
+ })
+
+use-raf-loop.ts
+ export function useRafLoop(callback: ({ time }: { time: number }) => void)
+
+use-reveal-item.ts
+ export function useRevealItem(
+ highlightId: string | null,
+ onClearHighlight: () => void,
+ highlightDuration = 1000,
+ )
+
+use-shift-key.ts
+ export function useShiftKey(): RefObject<boolean>
+
+use-sound-search.ts
+ export function useSoundSearch({
+ query,
+ commercialOnly,
+ }: {
+ query: string;
+ commercialOnly: boolean;
+ })
+
+use-transform-handles.ts
+ export function useTransformHandles({
+
+ canvasRef,
+
+ }: {
+
+ canvasRef: React.RefObject<HTMLCanvasElement | null>;
+
+ })
+
+## apps/web/src/hooks/actions
+
+use-action-handler.ts
+ export function useActionHandler(
+ action: A,
+ handler: TActionFunc<A>,
+ isActive: TActionHandlerOptions,
+ )
+
+use-editor-actions.ts
+ export function useEditorActions()
+
+## apps/web/src/hooks/storage
+
+use-local-storage.ts
+ export function useLocalStorage({
+ key,
+ defaultValue,
+ }: {
+ key: string;
+ defaultValue: T;
+ }): [
+ T,
+ ({ value }: { value: T | ((previousValue: T) => T) }) => void,
+ boolean,
+ ]
+
+## apps/web/src/hooks/timeline
+
+use-bookmark-drag.ts
+ export interface BookmarkDragState {
+ isDragging: boolean
+ bookmarkTime: number | null
+ currentTime: number
+ }
+ export function useBookmarkDrag({
+
+ zoomLevel,
+
+ scrollRef,
+
+ snappingEnabled,
+
+ onSnapPointChange,
+
+ }: UseBookmarkDragProps)
+
+use-edge-auto-scroll.ts
+ export function useEdgeAutoScroll({
+ isActive,
+ getMouseClientX,
+ rulerScrollRef,
+ tracksScrollRef,
+ contentWidth,
+ edgeThreshold = 100,
+ maxScrollSpeed = 15,
+ }: UseEdgeAutoScrollParams): void
+
+use-scroll-position.ts
+ export function useScrollPosition({
+ scrollRef,
+ }: {
+ scrollRef: React.RefObject<HTMLElement | null>;
+ }): UseScrollPositionReturn
+
+use-scroll-sync.ts
+ export function useScrollSync({
+ tracksScrollRef,
+ rulerScrollRef,
+ trackLabelsScrollRef,
+ bookmarksScrollRef,
+ }: UseScrollSyncProps)
+
+use-selection-box.ts
+ export function useSelectionBox({
+ containerRef,
+ onSelectionComplete,
+ isEnabled = true,
+ tracksScrollRef,
+ zoomLevel,
+ }: UseSelectionBoxProps)
+
+use-snap-indicator-position.ts
+ export function useSnapIndicatorPosition({
+ snapPoint,
+ zoomLevel,
+ tracks,
+ timelineRef,
+ trackLabelsRef,
+ tracksScrollRef,
+ }: UseSnapIndicatorPositionParams): SnapIndicatorPosition
+
+use-timeline-drag-drop.ts
+ export function useTimelineDragDrop({
+ containerRef,
+ headerRef,
+ zoomLevel,
+ }: UseTimelineDragDropProps)
+
+use-timeline-playhead.ts
+ export function useTimelinePlayhead({
+ zoomLevel,
+ rulerRef,
+ rulerScrollRef,
+ tracksScrollRef,
+ playheadRef,
+ }: UseTimelinePlayheadProps)
+
+use-timeline-seek.ts
+ export function useTimelineSeek({
+ playheadRef,
+ trackLabelsRef,
+ rulerScrollRef,
+ tracksScrollRef,
+ zoomLevel,
+ duration,
+ isSelecting,
+ clearSelectedElements,
+ seek,
+ }: UseTimelineSeekProps)
+
+use-timeline-snapping.ts
+ export interface SnapPoint {
+ time: number
+ type: "element-start" | "element-end" | "playhead" | "bookmark"
+ elementId?: string
+ trackId?: string
+ }
+ export interface SnapResult {
+ snappedTime: number
+ snapPoint: SnapPoint | null
+ snapDistance: number
+ }
+ export interface UseTimelineSnappingOptions {
+ snapThreshold?: number
+ enableElementSnapping?: boolean
+ enablePlayheadSnapping?: boolean
+ enableBookmarkSnapping?: boolean
+ }
+ export function useTimelineSnapping({
+ snapThreshold = 10,
+ enableElementSnapping = true,
+ enablePlayheadSnapping = true,
+ enableBookmarkSnapping = true,
+ }: UseTimelineSnappingOptions = {})
+
+use-timeline-zoom.ts
+ export function useTimelineZoom({
+ containerRef,
+ minZoom = TIMELINE_CONSTANTS.ZOOM_MIN,
+ initialZoom,
+ initialScrollLeft,
+ initialPlayheadTime,
+ tracksScrollRef,
+ rulerScrollRef,
+ }: UseTimelineZoomProps): UseTimelineZoomReturn
+
+## apps/web/src/hooks/timeline/element
+
+use-element-interaction.ts
+ export function useElementInteraction({
+ zoomLevel,
+ timelineRef,
+ tracksContainerRef,
+ tracksScrollRef,
+ headerRef,
+ snappingEnabled,
+ onSnapPointChange,
+ }: UseElementInteractionProps)
+
+use-element-resize.ts
+ export interface ResizeState {
+ elementId: string
+ side: "left" | "right"
+ startX: number
+ initialTrimStart: number
+ initialTrimEnd: number
+ initialStartTime: number
+ initialDuration: number
+ }
+ export function useTimelineElementResize({
+ element,
+ track,
+ zoomLevel,
+ onSnapPointChange,
+ onResizeStateChange,
+ }: UseTimelineElementResizeProps)
+
+use-element-selection.ts
+ export function useElementSelection()
+
+## apps/web/src/lib
+
+drag-data.ts
+ export function setDragData({
+ dataTransfer,
+ dragData,
+ }: {
+ dataTransfer: DataTransfer;
+ dragData: TimelineDragData;
+ }): void
+ export function getDragData({
+ dataTransfer,
+ }: {
+ dataTransfer: DataTransfer;
+ }): TimelineDragData | null
+ export function hasDragData({
+ dataTransfer,
+ }: {
+ dataTransfer: DataTransfer;
+ }): boolean
+ export function clearDragData(): void
+
+export.ts
+ export function getExportMimeType({
+ format,
+ }: {
+ format: ExportFormat;
+ }): string
+ export function getExportFileExtension({
+ format,
+ }: {
+ format: ExportFormat;
+ }): string
+
+iconify-api.ts
+ export const ICONIFY_HOSTS
+ export interface IconSet {
+ prefix: string
+ name: string
+ total: number
+ author?: {
+ name: string;
+ url?: string;
+ }
+ license?: {
+ title: string;
+ spdx?: string;
+ url?: string;
+ }
+ samples?: string[]
+ category?: string
+ palette?: boolean
+ }
+ export interface IconSearchResult {
+ icons: string[]
+ total: number
+ limit: number
+ start: number
+ collections: Record<string, IconSet>
+ }
+ export interface CollectionInfo {
+ prefix: string
+ total: number
+ title?: string
+ uncategorized?: string[]
+ categories?: Record<string, string[]>
+ hidden?: string[]
+ aliases?: Record<string, string>
+ }
+ export function getCollections(
+ category?: string,
+ ): Promise<Record<string, IconSet>>
+ export function getCollection(
+ prefix: string,
+ ): Promise<CollectionInfo | null>
+ export function searchIcons(
+ query: string,
+ limit: number = 64,
+ prefixes?: string[],
+ category?: string,
+ ): Promise<IconSearchResult>
+ export function buildIconSvgUrl(
+ host: string,
+ iconName: string,
+ params?: {
+ color?: string;
+ width?: number;
+ height?: number;
+ flip?: "horizontal" | "vertical" | "horizontal,vertical";
+ rotate?: number | string;
+ },
+ ): string
+ export function getIconSvgUrl(
+ iconName: string,
+ params?: Parameters<typeof buildIconSvgUrl>[2],
+ ): string
+ export function downloadSvgAsText(
+ iconName: string,
+ params?: Parameters<typeof getIconSvgUrl>[1],
+ ): Promise<string>
+ export function svgToFile(svgText: string, fileName: string): File
+ export const POPULAR_COLLECTIONS
+ export function getCategoriesFromCollections(
+ collections: Record<string, IconSet>,
+ ): string[]
+
+rate-limit.ts
+ export const baseRateLimit
+ export function checkRateLimit({ request }: { request: Request })
+
+scenes.ts
+ export function getMainScene({ scenes }: { scenes: TScene[] }): TScene | null
+ export function ensureMainScene({ scenes }: { scenes: TScene[] }): TScene[]
+ export function buildDefaultScene({
+ name,
+ isMain,
+ }: {
+ name: string;
+ isMain: boolean;
+ }): TScene
+ export function canDeleteScene({ scene }: { scene: TScene }): {
+ canDelete: boolean;
+ reason?: string;
+ }
+ export function getFallbackSceneAfterDelete({
+ scenes,
+ deletedSceneId,
+ currentSceneId,
+ }: {
+ scenes: TScene[];
+ deletedSceneId: string;
+ currentSceneId: string | null;
+ }): TScene | null
+ export function findCurrentScene({
+ scenes,
+ currentSceneId,
+ }: {
+ scenes: TScene[];
+ currentSceneId: string;
+ }): TScene | null
+ export function getProjectDurationFromScenes({
+ scenes,
+ }: {
+ scenes: TScene[];
+ }): number
+ export function updateSceneInArray({
+ scenes,
+ sceneId,
+ updates,
+ }: {
+ scenes: TScene[];
+ sceneId: string;
+ updates: Partial<TScene>;
+ }): TScene[]
+
+time.ts
+ export function roundToFrame({
+ time,
+ fps,
+ }: {
+ time: number;
+ fps: number;
+ }): number
+ export function formatTimeCode({
+ timeInSeconds,
+ format = "HH:MM:SS:CS",
+ fps,
+ }: {
+ timeInSeconds: number;
+ format?: TTimeCode;
+ fps?: number;
+ }): string
+ export function parseTimeCode({
+ timeCode,
+ format = "HH:MM:SS:CS",
+ fps,
+ }: {
+ timeCode: string;
+ format?: TTimeCode;
+ fps: number;
+ }): number | null
+ export function guessTimeCodeFormat({
+ timeCode,
+ }: {
+ timeCode: string;
+ }): TTimeCode | null
+ export function timeToFrame({
+ time,
+ fps,
+ }: {
+ time: number;
+ fps: number;
+ }): number
+ export function frameToTime({
+ frame,
+ fps,
+ }: {
+ frame: number;
+ fps: number;
+ }): number
+ export function snapTimeToFrame({
+ time,
+ fps,
+ }: {
+ time: number;
+ fps: number;
+ }): number
+ export function getSnappedSeekTime({
+ rawTime,
+ duration,
+ fps,
+ }: {
+ rawTime: number;
+ duration: number;
+ fps: number;
+ }): number
+ export function getLastFrameTime({
+ duration,
+ fps,
+ }: {
+ duration: number;
+ fps: number;
+ }): number
+
+## apps/web/src/lib/actions
+
+definitions.ts
+ export type TActionCategory = | "playback"
+ | "navigation"
+ | "editing"
+ | "selection"
+ | "history"
+ | "timeline"
+ | "controls"
+ export interface TActionDefinition {
+ description: string
+ category: TActionCategory
+ defaultShortcuts?: ShortcutKey[]
+ args?: Record<string, unknown>
+ }
+ export const ACTIONS
+ export type TAction = keyof typeof ACTIONS
+ export function getActionDefinition(action: TAction): TActionDefinition
+ export function getDefaultShortcuts(): Record<ShortcutKey, TAction>
+
+registry.ts
+ export function bindAction(
+ action: A,
+ handler: TActionFunc<A>,
+ )
+ export function unbindAction(
+ action: A,
+ handler: TActionFunc<A>,
+ )
+ export const invokeAction = (
+ action: A,
+ args?: TArgOfAction<A>,
+ trigger?: TInvocationTrigger,
+ ) => ...
+
+types.ts
+ export type TActionArgsMap = {
+ "seek-forward": { seconds: number } | undefined;
+ "seek-backward": { seconds: number } | undef...
+ export type TActionWithArgs = keyof TActionArgsMap
+ export type TActionWithOptionalArgs = | TActionWithNoArgs
+ | TKeysWithValueUndefined<TActionArgsMap>
+ export type TActionWithNoArgs = Exclude<TAction, TActionWithArgs>
+ export type TArgOfAction<A extends TAction> = A extends TActionWithArgs
+ ? TActionArgsMap[A]
+ : undefined
+ export type TActionFunc<A extends TAction> = A extends TActionWithArgs
+ ? (arg: TArgOfAction<A>, trigger?: TInvocationTrigger) => void
+ : (_?:...
+ export type TInvocationTrigger = "keypress" | "mouseclick"
+ export type TBoundActionList = {
+ [A in TAction]?: Array<TActionFunc<A>>;
+ }
+ export type TActionHandlerOptions = | MutableRefObject<boolean>
+ | boolean
+ | undefined
+
+## apps/web/src/lib/auth
+
+server.ts
+ export const auth
+ export type Auth = typeof auth
+
+## apps/web/src/lib/blog
+
+query.ts
+ export function getPosts()
+ export function getTags()
+ export function getSinglePost({ slug }: { slug: string })
+ export function getCategories()
+ export function getAuthors()
+ export function processHtmlContent({
+ html,
+ }: {
+ html: string;
+ }): Promise<string>
+
+## apps/web/src/lib/db
+
+index.ts
+ export const db
+
+schema.ts
+ export const users
+ export const sessions
+ export const accounts
+ export const verifications
+
+## apps/web/src/lib/fonts
+
+google-fonts.ts
+ export function getCachedFontAtlas(): FontAtlas | null
+ export function clearFontAtlasCache(): void
+ export function prefetchFontAtlas(): Promise<FontAtlas | null>
+ export function loadFullFont({
+ family,
+ weights = [400, 700],
+ }: {
+ family: string;
+ weights?: number[];
+ }): Promise<void>
+ export function loadFonts({
+ families,
+ }: {
+ families: string[];
+ }): Promise<void>
+
+## apps/web/src/lib/gradients
+
+canvas.ts
+ export function drawCssBackground({
+ ctx,
+ width,
+ height,
+ css,
+ }: {
+ ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D;
+ width: number;
+ height: number;
+ css: string;
+ }): void
+
+parser.ts
+ export type GradientOrientation = LinearOrientation | Array<RadialOrientation>
+ export type Color = | { type: "hex"; value: string }
+ | { type: "literal"; value: string }
+ | { type: "rgb"; value: A...
+ export type ColorStop = Color & { length?: Distance }
+ export type GradientAst = {
+ type: GradientType;
+ orientation: GradientOrientation | undefined;
+ colorStops: Array<ColorSto...
+ export const parseGradient = ({
+ code,
+ }: {
+ code: string;
+ }): Array<GradientAst> => ...
+ export const GradientParser
+
+## apps/web/src/lib/media
+
+audio.ts
+ export type CollectedAudioElement = Omit<
+ AudioElement,
+ "type" | "mediaId" | "volume" | "id" | "name" | "sourceType" | "sourceUrl"
+ ...
+ export function createAudioContext(): AudioContext
+ export interface DecodedAudio {
+ samples: Float32Array
+ sampleRate: number
+ }
+ export function decodeAudioToFloat32({
+ audioBlob,
+ }: {
+ audioBlob: Blob;
+ }): Promise<DecodedAudio>
+ export function collectAudioElements({
+ tracks,
+ mediaAssets,
+ audioContext,
+ }: {
+ tracks: TimelineTrack[];
+ mediaAssets: MediaAsset[];
+ audioContext: AudioContext;
+ }): Promise<CollectedAudioElement[]>
+ export interface AudioClipSource {
+ id: string
+ sourceKey: string
+ file: File
+ startTime: number
+ duration: number
+ trimStart: number
+ trimEnd: number
+ muted: boolean
+ }
+ export function collectAudioMixSources({
+ tracks,
+ mediaAssets,
+ }: {
+ tracks: TimelineTrack[];
+ mediaAssets: MediaAsset[];
+ }): Promise<AudioMixSource[]>
+ export function collectAudioClips({
+ tracks,
+ mediaAssets,
+ }: {
+ tracks: TimelineTrack[];
+ mediaAssets: MediaAsset[];
+ }): Promise<AudioClipSource[]>
+ export function createTimelineAudioBuffer({
+ tracks,
+ mediaAssets,
+ duration,
+ sampleRate = 44100,
+ audioContext,
+ }: {
+ tracks: TimelineTrack[];
+ mediaAssets: MediaAsset[];
+ duration: number;
+ sampleRate?: number;
+ audioContext?: AudioContext;
+ }): Promise<AudioBuffer | null>
+
+media-utils.ts
+ export const SUPPORTS_AUDIO: readonly MediaType[]
+ export function mediaSupportsAudio({
+ media,
+ }: {
+ media: MediaAsset | null | undefined;
+ }): boolean
+ export const getMediaTypeFromFile = ({
+ file,
+ }: {
+ file: File;
+ }): MediaType | null => ...
+
+mediabunny.ts
+ export function getVideoInfo({
+ videoFile,
+ }: {
+ videoFile: File;
+ }): Promise<{
+ duration: number;
+ width: number;
+ height: number;
+ fps: number;
+ }>
+ export const extractTimelineAudio = ({
+ tracks,
+ mediaAssets,
+ totalDuration,
+ onProgress,
+ }: {
+ tracks: TimelineTrack[];
+ mediaAssets: MediaAsset[];
+ totalDuration: number;
+ onProgress?: (progress: number) => void;
+ }): Promise<Blob> => ...
+
+processing.ts
+ export interface ProcessedMediaAsset extends Omit<MediaAsset, "id">
+ export function generateThumbnail({
+ videoFile,
+ timeInSeconds,
+ }: {
+ videoFile: File;
+ timeInSeconds: number;
+ }): Promise<string>
+ export function generateImageThumbnail({
+ imageFile,
+ }: {
+ imageFile: File;
+ }): Promise<string>
+ export function processMediaAssets({
+ files,
+ onProgress,
+ }: {
+ files: FileList | File[];
+ onProgress?: ({ progress }: { progress: number }) => void;
+ }): Promise<ProcessedMediaAsset[]>
+
+## apps/web/src/lib/preview
+
+element-bounds.ts
+ export interface ElementBounds {
+ cx: number
+ cy: number
+ width: number
+ height: number
+ rotation: number
+ }
+ export interface ElementWithBounds {
+ trackId: string
+ elementId: string
+ element: TimelineElement
+ bounds: ElementBounds
+ }
+ export function getElementBounds({
+ element,
+ canvasSize,
+ mediaAsset,
+ }: {
+ element: TimelineElement;
+ canvasSize: { width: number; height: number };
+ mediaAsset?: MediaAsset | null;
+ }): ElementBounds | null
+ export function getVisibleElementsWithBounds({
+ tracks,
+ currentTime,
+ canvasSize,
+ mediaAssets,
+ }: {
+ tracks: TimelineTrack[];
+ currentTime: number;
+ canvasSize: { width: number; height: number };
+ mediaAssets: MediaAsset[];
+ }): ElementWithBounds[]
+
+hit-test.ts
+ export function hitTest({
+
+ canvasX,
+
+ canvasY,
+
+ elementsWithBounds,
+
+ }: {
+
+ canvasX: number;
+
+ canvasY: number;
+
+ elementsWithBounds: ElementWithBounds[];
+
+ }): ElementWithBounds | null
+
+preview-coords.ts
+ export function screenToCanvas({
+
+ clientX,
+
+ clientY,
+
+ canvas,
+
+ }: {
+
+ clientX: number;
+
+ clientY: number;
+
+ canvas: HTMLCanvasElement;
+
+ }): { x: number; y: number }
+ export function canvasToOverlay({
+
+ canvasX,
+
+ canvasY,
+
+ canvasRect,
+
+ containerRect,
+
+ canvasSize,
+
+ }: {
+
+ canvasX: number;
+
+ canvasY: number;
+
+ canvasRect: DOMRect;
+
+ containerRect: DOMRect;
+
+ canvasSize: { width: number; height: number };
+
+ }): { x: number; y: number }
+ export function positionToOverlay({
+
+ positionX,
+
+ positionY,
+
+ canvasRect,
+
+ containerRect,
+
+ canvasSize,
+
+ }: {
+
+ positionX: number;
+
+ positionY: number;
+
+ canvasRect: DOMRect;
+
+ containerRect: DOMRect;
+
+ canvasSize: { width: number; height: number };
+
+ }): { x: number; y: number }
+ export function getDisplayScale({
+
+ canvasRect,
+
+ canvasSize,
+
+ }: {
+
+ canvasRect: DOMRect;
+
+ canvasSize: { width: number; height: number };
+
+ }): { x: number; y: number }
+
+preview-snap.ts
+ export interface SnapLine {
+ type: "horizontal" | "vertical"
+ position: number
+ }
+ export const MIN_SCALE
+ export interface SnapResult {
+ snappedPosition: { x: number; y: number }
+ activeLines: SnapLine[]
+ }
+ export function snapPosition({
+
+ proposedPosition,
+
+ canvasSize,
+
+ elementSize,
+
+ }: {
+
+ proposedPosition: { x: number; y: number };
+
+ canvasSize: { width: number; height: number };
+
+ elementSize: { width: number; height: number };
+
+ }): SnapResult
+ export interface ScaleSnapResult {
+ snappedScale: number
+ activeLines: SnapLine[]
+ }
+ export function snapScale({
+
+ proposedScale,
+
+ position,
+
+ baseWidth,
+
+ baseHeight,
+
+ canvasSize,
+
+ }: {
+
+ proposedScale: number;
+
+ position: { x: number; y: number };
+
+ baseWidth: number;
+
+ baseHeight: number;
+
+ canvasSize: { width: number; height: number };
+
+ }): ScaleSnapResult
+ export interface RotationSnapResult {
+ snappedRotation: number
+ isSnapped: boolean
+ }
+ export function snapRotation({
+
+ proposedRotation,
+
+ }: {
+
+ proposedRotation: number;
+
+ }): RotationSnapResult
+
+## apps/web/src/lib/stickers
+
+index.ts
+ export function searchStickers({
+ query,
+ category,
+ limit = DEFAULT_SEARCH_LIMIT,
+ }: {
+ query: string;
+ category: StickerCategory;
+ limit?: number;
+ }): Promise<StickerSearchResult>
+ export function browseStickers({
+ category,
+ page = 1,
+ limit = DEFAULT_SEARCH_LIMIT,
+ }: {
+ category: StickerCategory;
+ page?: number;
+ limit?: number;
+ }): Promise<StickerSearchResult>
+
+registry.ts
+ export function registerProvider({
+ provider,
+ }: {
+ provider: StickerProvider;
+ }): void
+ export function hasProvider({ providerId }: { providerId: string }): boolean
+ export function getProvider({
+ providerId,
+ }: {
+ providerId: string;
+ }): StickerProvider
+ export function getAllProviders(): StickerProvider[]
+
+resolver.ts
+ export function resolveStickerId({
+ stickerId,
+ options,
+ }: {
+ stickerId: string;
+ options?: StickerResolveOptions;
+ }): string
+
+sticker-id.ts
+ export function parseStickerId({ stickerId }: { stickerId: string }): {
+ providerId: string;
+ providerValue: string;
+ }
+ export function buildStickerId({
+ providerId,
+ providerValue,
+ }: {
+ providerId: string;
+ providerValue: string;
+ }): string
+
+## apps/web/src/lib/stickers/providers
+
+emoji.ts
+ export const emojiProvider: StickerProvider
+
+flags.ts
+ export const flagsProvider: StickerProvider
+
+icons.ts
+ export const iconsProvider: StickerProvider
+
+index.ts
+ export function registerDefaultStickerProviders({
+ providersToRegister = defaultProviders,
+ }: {
+ providersToRegister?: StickerProvider[];
+ } = {}): void
+
+shapes.ts
+ export const shapesProvider: StickerProvider
+
+## apps/web/src/lib/timeline
+
+bookmarks.ts
+ export const BOOKMARK_TIME_EPSILON
+ export function findBookmarkIndex({
+ bookmarks,
+ frameTime,
+ }: {
+ bookmarks: Bookmark[];
+ frameTime: number;
+ }): number
+ export function isBookmarkAtTime({
+ bookmarks,
+ frameTime,
+ }: {
+ bookmarks: Bookmark[];
+ frameTime: number;
+ }): boolean
+ export function toggleBookmarkInArray({
+ bookmarks,
+ frameTime,
+ }: {
+ bookmarks: Bookmark[];
+ frameTime: number;
+ }): Bookmark[]
+ export function removeBookmarkFromArray({
+ bookmarks,
+ frameTime,
+ }: {
+ bookmarks: Bookmark[];
+ frameTime: number;
+ }): Bookmark[]
+ export function updateBookmarkInArray({
+ bookmarks,
+ frameTime,
+ updates,
+ }: {
+ bookmarks: Bookmark[];
+ frameTime: number;
+ updates: Partial<Omit<Bookmark, "time">>;
+ }): Bookmark[]
+ export function moveBookmarkInArray({
+ bookmarks,
+ fromTime,
+ toTime,
+ }: {
+ bookmarks: Bookmark[];
+ fromTime: number;
+ toTime: number;
+ }): Bookmark[]
+ export function getFrameTime({
+ time,
+ fps,
+ }: {
+ time: number;
+ fps: number;
+ }): number
+ export function getBookmarkAtTime({
+ bookmarks,
+ frameTime,
+ }: {
+ bookmarks: Bookmark[];
+ frameTime: number;
+ }): Bookmark | null
+ export function getBookmarksActiveAtTime({
+ bookmarks,
+ time,
+ }: {
+ bookmarks: Bookmark[];
+ time: number;
+ }): Bookmark[]
+
+drag-utils.ts
+ export function getMouseTimeFromClientX({
+
+ clientX,
+
+ containerRect,
+
+ zoomLevel,
+
+ scrollLeft,
+
+ }: {
+
+ clientX: number;
+
+ containerRect: DOMRect;
+
+ zoomLevel: number;
+
+ scrollLeft: number;
+
+ }): number
+
+drop-utils.ts
+ export function computeDropTarget({
+ elementType,
+ mouseX,
+ mouseY,
+ tracks,
+ playheadTime,
+ isExternalDrop,
+ elementDuration,
+ pixelsPerSecond,
+ zoomLevel,
+ verticalDragDirection,
+ startTimeOverride,
+ excludeElementId,
+ }: ComputeDropTargetParams): DropTarget
+ export function getDropLineY({
+ dropTarget,
+ tracks,
+ }: {
+ dropTarget: DropTarget;
+ tracks: TimelineTrack[];
+ }): number
+
+element-utils.ts
+ export function canElementHaveAudio(
+ element: TimelineElement,
+ )
+ export function isVisualElement(
+ element: TimelineElement,
+ )
+ export function canElementBeHidden(
+ element: TimelineElement,
+ )
+ export function hasMediaId(
+ element: TimelineElement,
+ )
+ export function requiresMediaId({
+ element,
+ }: {
+ element: CreateTimelineElement;
+ }): boolean
+ export function checkElementOverlaps({
+ elements,
+ }: {
+ elements: TimelineElement[];
+ }): boolean
+ export function resolveElementOverlaps({
+ elements,
+ }: {
+ elements: TimelineElement[];
+ }): TimelineElement[]
+ export function wouldElementOverlap({
+ elements,
+ startTime,
+ endTime,
+ excludeElementId,
+ }: {
+ elements: TimelineElement[];
+ startTime: number;
+ endTime: number;
+ excludeElementId?: string;
+ }): boolean
+ export function buildTextElement({
+ raw,
+ startTime,
+ }: {
+ raw: Partial<Omit<TextElement, "type" | "id">>;
+ startTime: number;
+ }): CreateTimelineElement
+ export function buildStickerElement({
+ stickerId,
+ name,
+ startTime,
+ }: {
+ stickerId: string;
+ name?: string;
+ startTime: number;
+ }): CreateStickerElement
+ export function buildVideoElement({
+ mediaId,
+ name,
+ duration,
+ startTime,
+ }: {
+ mediaId: string;
+ name: string;
+ duration: number;
+ startTime: number;
+ }): CreateVideoElement
+ export function buildImageElement({
+ mediaId,
+ name,
+ duration,
+ startTime,
+ }: {
+ mediaId: string;
+ name: string;
+ duration: number;
+ startTime: number;
+ }): CreateImageElement
+ export function buildUploadAudioElement({
+ mediaId,
+ name,
+ duration,
+ startTime,
+ buffer,
+ }: {
+ mediaId: string;
+ name: string;
+ duration: number;
+ startTime: number;
+ buffer?: AudioBuffer;
+ }): CreateUploadAudioElement
+ export function buildElementFromMedia({
+ mediaId,
+ mediaType,
+ name,
+ duration,
+ startTime,
+ buffer,
+ }: {
+ mediaId: string;
+ mediaType: MediaType;
+ name: string;
+ duration: number;
+ startTime: number;
+ buffer?: AudioBuffer;
+ }): CreateTimelineElement
+ export function buildLibraryAudioElement({
+ sourceUrl,
+ name,
+ duration,
+ startTime,
+ buffer,
+ }: {
+ sourceUrl: string;
+ name: string;
+ duration: number;
+ startTime: number;
+ buffer?: AudioBuffer;
+ }): CreateLibraryAudioElement
+ export function getElementsAtTime({
+ tracks,
+ time,
+ }: {
+ tracks: TimelineTrack[];
+ time: number;
+ }): { trackId: string; elementId: string }[]
+ export function collectFontFamilies({
+ tracks,
+ }: {
+ tracks: TimelineTrack[];
+ }): string[]
+
+index.ts
+ export function calculateTotalDuration({
+ tracks,
+ }: {
+ tracks: TimelineTrack[];
+ }): number
+
+ruler-utils.ts
+ export interface RulerConfig {
+ labelIntervalSeconds: number
+ tickIntervalSeconds: number
+ }
+ export function getRulerConfig({
+ zoomLevel,
+ fps,
+ }: {
+ zoomLevel: number;
+ fps: number;
+ }): RulerConfig
+ export function shouldShowLabel({
+ time,
+ labelIntervalSeconds,
+ }: {
+ time: number;
+ labelIntervalSeconds: number;
+ }): boolean
+ export function formatRulerLabel({
+ timeInSeconds,
+ fps,
+ }: {
+ timeInSeconds: number;
+ fps: number;
+ }): string
+
+track-utils.ts
+ export function canTracktHaveAudio(
+ track: TimelineTrack,
+ )
+ export function canTrackBeHidden(
+ track: TimelineTrack,
+ )
+ export function getTrackColor({ type }: { type: TrackType })
+ export function getTrackClasses({ type }: { type: TrackType })
+ export function getTrackHeight({ type }: { type: TrackType }): number
+ export function getCumulativeHeightBefore({
+ tracks,
+ trackIndex,
+ }: {
+ tracks: Array<{ type: TrackType }>;
+ trackIndex: number;
+ }): number
+ export function getTotalTracksHeight({
+ tracks,
+ }: {
+ tracks: Array<{ type: TrackType }>;
+ }): number
+ export function buildEmptyTrack({
+ id,
+ type,
+ name,
+ }: {
+ id: string;
+ type: TrackType;
+ name?: string;
+ }): TimelineTrack
+ export function getDefaultInsertIndexForTrack({
+ tracks,
+ trackType,
+ }: {
+ tracks: TimelineTrack[];
+ trackType: TrackType;
+ }): number
+ export function getHighestInsertIndexForTrack({
+ tracks,
+ trackType,
+ }: {
+ tracks: TimelineTrack[];
+ trackType: TrackType;
+ }): number
+ export function isMainTrack(track: TimelineTrack)
+ export function getMainTrack({
+ tracks,
+ }: {
+ tracks: TimelineTrack[];
+ }): TimelineTrack | null
+ export function ensureMainTrack({
+ tracks,
+ }: {
+ tracks: TimelineTrack[];
+ }): TimelineTrack[]
+ export function canElementGoOnTrack({
+ elementType,
+ trackType,
+ }: {
+ elementType: ElementType;
+ trackType: TrackType;
+ }): boolean
+ export function validateElementTrackCompatibility({
+ element,
+ track,
+ }: {
+ element: { type: ElementType };
+ track: { type: TrackType };
+ }): { isValid: boolean; errorMessage?: string }
+ export function getEarliestMainTrackElement({
+ tracks,
+ excludeElementId,
+ }: {
+ tracks: TimelineTrack[];
+ excludeElementId?: string;
+ }): TimelineElement | null
+ export function enforceMainTrackStart({
+ tracks,
+ targetTrackId,
+ requestedStartTime,
+ excludeElementId,
+ }: {
+ tracks: TimelineTrack[];
+ targetTrackId: string;
+ requestedStartTime: number;
+ excludeElementId?: string;
+ }): number
+
+zoom-utils.ts
+ export function getTimelineZoomMin({
+ duration,
+ containerWidth,
+ }: {
+ duration: number;
+ containerWidth: number | null | undefined;
+ }): number
+ export function getTimelinePaddingPx({
+ containerWidth,
+ zoomLevel,
+ minZoom,
+ }: {
+ containerWidth: number;
+ zoomLevel: number;
+ minZoom: number;
+ }): number
+ export function getZoomPercent({
+ zoomLevel,
+ minZoom,
+ }: {
+ zoomLevel: number;
+ minZoom: number;
+ }): number
+ export function sliderToZoom({
+ sliderPosition,
+ minZoom,
+ maxZoom = TIMELINE_CONSTANTS.ZOOM_MAX,
+ }: {
+ sliderPosition: number;
+ minZoom: number;
+ maxZoom?: number;
+ }): number
+ export function zoomToSlider({
+ zoomLevel,
+ minZoom,
+ maxZoom = TIMELINE_CONSTANTS.ZOOM_MAX,
+ }: {
+ zoomLevel: number;
+ minZoom: number;
+ maxZoom?: number;
+ }): number
+
+## apps/web/src/lib/transcription
+
+caption.ts
+ export function buildCaptionChunks({
+ segments,
+ wordsPerChunk = DEFAULT_WORDS_PER_CAPTION,
+ minDuration = MIN_CAPTION_DURATION_SECONDS,
+ }: {
+ segments: TranscriptionSegment[];
+ wordsPerChunk?: number;
+ minDuration?: number;
+ }): CaptionChunk[]
+
+## apps/web/src/services/renderer
+
+canvas-renderer.ts
+ export type CanvasRendererParams = {
+ width: number;
+ height: number;
+ fps: number;
+ }
+ export class CanvasRenderer {
+ canvas: OffscreenCanvas | HTMLCanvasElement
+ context: OffscreenCanvasRenderingContext2D | CanvasRenderingContext2D
+ width: number
+ height: number
+ fps: number
+ constructor({ width, height, fps }: CanvasRendererParams)
+ setSize({ width, height }: { width: number; height: number })
+ async render({ node, time }: { node: BaseNode; time: number })
+ async renderToCanvas({
+ node,
+ time,
+ targetCanvas,
+ }: {
+ node: BaseNode;
+ time: number;
+ targetCanvas: HTMLCanvasElement;
+ })
+ }
+
+scene-builder.ts
+ export type BuildSceneParams = {
+ canvasSize: TCanvasSize;
+ tracks: TimelineTrack[];
+ mediaAssets: MediaAsset[];
+ duration: numb...
+ export function buildScene(params: BuildSceneParams)
+
+scene-exporter.ts
+ export type ExportFormat = "mp4" | "webm"
+ export type ExportQuality = "low" | "medium" | "high" | "very_high"
+ export type SceneExporterEvents = {
+ progress: [progress: number];
+ complete: [buffer: ArrayBuffer];
+ error: [error: Error];
+ cance...
+ export class SceneExporter extends EventEmitter<SceneExporterEvents> {
+ renderer: CanvasRenderer
+ format: ExportFormat
+ quality: ExportQuality
+ shouldIncludeAudio: boolean
+ audioBuffer: AudioBuffer
+ isCancelled
+ constructor({
+ width,
+ height,
+ fps,
+ format,
+ quality,
+ shouldIncludeAudio,
+ audioBuffer,
+ }: ExportParams)
+ cancel(): void
+ async export({
+ rootNode,
+ }: {
+ rootNode: RootNode;
+ }): Promise<ArrayBuffer | null>
+ }
+
+## apps/web/src/services/storage
+
+indexeddb-adapter.ts
+ export class IndexedDBAdapter implements StorageAdapter<T> {
+ dbName: string
+ storeName: string
+ version: number
+ constructor(dbName: string, storeName: string, version = 1)
+ async get(key: string): Promise<T | null>
+ async set(key: string, value: T): Promise<void>
+ async remove(key: string): Promise<void>
+ async list(): Promise<string[]>
+ async getAll(): Promise<T[]>
+ async clear(): Promise<void>
+ }
+ export function deleteDatabase({
+ dbName,
+ }: {
+ dbName: string;
+ }): Promise<void>
+
+opfs-adapter.ts
+ export class OPFSAdapter implements StorageAdapter<File> {
+ directoryName: string
+ constructor(directoryName = "media")
+ async get(key: string): Promise<File | null>
+ async set(key: string, file: File): Promise<void>
+ async remove(key: string): Promise<void>
+ async list(): Promise<string[]>
+ async clear(): Promise<void>
+ static isSupported(): boolean
+ }
+
+service.ts
+ export const storageService
+
+types.ts
+ export interface StorageAdapter<T> {
+ get(key: string): Promise<T | null>
+ set(key: string, value: T): Promise<void>
+ remove(key: string): Promise<void>
+ list(): Promise<string[]>
+ clear(): Promise<void>
+ }
+ export interface MediaAssetData {
+ id: string
+ name: string
+ type: MediaType
+ size: number
+ lastModified: number
+ width?: number
+ height?: number
+ duration?: number
+ fps?: number
+ ephemeral?: boolean
+ thumbnailUrl?: string
+ }
+ export type SerializedScene = Omit<TScene, "createdAt" | "updatedAt"> & {
+ createdAt: string;
+ updatedAt: string;
+ }
+ export type SerializedProjectMetadata = Omit<
+ TProjectMetadata,
+ "createdAt" | "updatedAt"
+ > & {
+ createdAt: string;
+ updatedAt: string;
+ }
+ export type SerializedProject = Omit<TProject, "metadata" | "scenes"> & {
+ metadata: SerializedProjectMetadata;
+ scenes: Serializ...
+ export interface StorageConfig {
+ projectsDb: string
+ mediaDb: string
+ savedSoundsDb: string
+ version: number
+ }
+
+## apps/web/src/services/transcription
+
+service.ts
+ export const transcriptionService
+
+worker.ts
+ export type WorkerMessage = | { type: "init"; modelId: string }
+ | { type: "transcribe"; audio: Float32Array; language: strin...
+ export type WorkerResponse = | { type: "init-progress"; progress: number }
+ | { type: "init-complete" }
+ | { type: "init-error...
+
+## apps/web/src/services/video-cache
+
+service.ts
+ export class VideoCache {
+ sinks
+ initPromises
+ async getFrameAt({
+ mediaId,
+ file,
+ time,
+ }: {
+ mediaId: string;
+ file: File;
+ time: number;
+ }): Promise<WrappedCanvas | null>
+ clearVideo({ mediaId }: { mediaId: string }): void
+ clearAll(): void
+ getStats()
+ }
+ export const videoCache
+
+## apps/web/src/stores
+
+assets-panel-store.tsx
+ export const TAB_KEYS
+ export type Tab = (typeof TAB_KEYS)[number]
+ export const tabs
+ export const useAssetsPanelStore
+
+editor-store.ts
+ export const useEditorStore
+
+keybindings-store.ts
+ export const defaultKeybindings: KeybindingConfig
+ export interface KeybindingConflict {
+ key: ShortcutKey
+ existingAction: TActionWithOptionalArgs
+ newAction: TActionWithOptionalArgs
+ }
+ export const useKeybindingsStore
+
+panel-store.ts
+ export interface PanelSizes {
+ tools: number
+ preview: number
+ properties: number
+ mainContent: number
+ timeline: number
+ }
+ export type PanelId = keyof PanelSizes
+ export const usePanelStore
+
+preview-store.ts
+ export const usePreviewStore
+
+sounds-store.ts
+ export const useSoundsStore
+
+stickers-store.ts
+ export const useStickersStore
+
+timeline-store.ts
+ export const useTimelineStore
+
+## apps/web/src/types
+
+assets.ts
+ export type MediaType = "image" | "video" | "audio"
+ export interface MediaAsset extends Omit<MediaAssetData, "size" | "lastModified"> {
+ file: File
+ url?: string
+ }
+
+blog.ts
+ export type Post = {
+ id: string;
+ slug: string;
+ title: string;
+ content: string;
+ description: string;
+ coverImage...
+ export type Pagination = {
+ limit: number;
+ currpage: number;
+ nextPage: number | null;
+ prevPage: number | null;
+ totalIt...
+ export type MarblePostList = {
+ posts: Post[];
+ pagination: Pagination;
+ }
+ export type MarblePost = {
+ post: Post;
+ }
+ export type Tag = {
+ id: string;
+ name: string;
+ slug: string;
+ }
+ export type MarbleTag = {
+ tag: Tag;
+ }
+ export type MarbleTagList = {
+ tags: Tag[];
+ pagination: Pagination;
+ }
+ export type Category = {
+ id: string;
+ name: string;
+ slug: string;
+ }
+ export type MarbleCategory = {
+ category: Category;
+ }
+ export type MarbleCategoryList = {
+ categories: Category[];
+ pagination: Pagination;
+ }
+ export type Author = {
+ id: string;
+ name: string;
+ image: string;
+ }
+ export type MarbleAuthor = {
+ author: Author;
+ }
+ export type MarbleAuthorList = {
+ authors: Author[];
+ pagination: Pagination;
+ }
+
+drag.ts
+ export interface MediaDragData extends BaseDragData {
+ type: "media"
+ mediaType: "image" | "video" | "audio"
+ }
+ export interface TextDragData extends BaseDragData {
+ type: "text"
+ content: string
+ }
+ export interface StickerDragData extends BaseDragData {
+ type: "sticker"
+ stickerId: string
+ }
+ export type TimelineDragData = MediaDragData | TextDragData | StickerDragData
+
+editor.ts
+ export type TPlatformLayout = "tiktok"
+
+export.ts
+ export const EXPORT_QUALITY_VALUES
+ export const EXPORT_FORMAT_VALUES
+ export type ExportFormat = (typeof EXPORT_FORMAT_VALUES)[number]
+ export type ExportQuality = (typeof EXPORT_QUALITY_VALUES)[number]
+ export interface ExportOptions {
+ format: ExportFormat
+ quality: ExportQuality
+ fps?: number
+ includeAudio?: boolean
+ onProgress?: ({ progress }: { progress: number }) => void
+ onCancel?: () => boolean
+ }
+ export interface ExportResult {
+ success: boolean
+ buffer?: ArrayBuffer
+ error?: string
+ cancelled?: boolean
+ }
+
+fonts.ts
+ export interface FontOption {
+ value: string
+ label: string
+ category: "system" | "google" | "custom"
+ weights?: number[]
+ hasClassName?: boolean
+ }
+ export interface GoogleFontMeta {
+ family: string
+ category: string
+ }
+ export interface FontAtlasEntry {
+ x: number
+ y: number
+ w: number
+ ch: number
+ s: string[]
+ }
+ export interface FontAtlas {
+ fonts: Record<string, FontAtlasEntry>
+ }
+
+keybinding.ts
+ export type ModifierKeys = | "ctrl"
+ | "alt"
+ | "shift"
+ | "ctrl+shift"
+ | "alt+shift"
+ | "ctrl+alt"
+ | "ctrl+alt+shift"
+ export type Key = | "a"
+ | "b"
+ | "c"
+ | "d"
+ | "e"
+ | "f"
+ | "g"
+ | "h"
+ | "i"
+ | "j"
+ | "k"
+ | "l"
+ | "m"
+ | "n"
+ ...
+ export type ModifierBasedShortcutKey = `${ModifierKeys}+${Key}`
+ export type SingleCharacterShortcutKey = `${Key}`
+ export type ShortcutKey = ModifierBasedShortcutKey | SingleCharacterShortcutKey
+ export type KeybindingConfig = {
+ [key in ShortcutKey]?: TActionWithOptionalArgs;
+ }
+
+language.ts
+ export type Language = (typeof LANGUAGES)[number]
+ export type LanguageCode = Language["code"]
+
+project.ts
+ export type TBackground = | {
+ type: "color";
+ color: string;
+ }
+ | {
+ type: "blur";
+ blurIntensity: number;
+ }
+ export interface TCanvasSize {
+ width: number
+ height: number
+ }
+ export interface TProjectMetadata {
+ id: string
+ name: string
+ thumbnail?: string
+ duration: number
+ createdAt: Date
+ updatedAt: Date
+ }
+ export interface TProjectSettings {
+ fps: number
+ canvasSize: TCanvasSize
+ originalCanvasSize?: TCanvasSize | null
+ background: TBackground
+ }
+ export interface TTimelineViewState {
+ zoomLevel: number
+ scrollLeft: number
+ playheadTime: number
+ }
+ export interface TProject {
+ metadata: TProjectMetadata
+ scenes: TScene[]
+ currentSceneId: string
+ settings: TProjectSettings
+ version: number
+ timelineViewState?: TTimelineViewState
+ }
+ export type TProjectSortKey = "createdAt" | "updatedAt" | "name" | "duration"
+ export type TSortOrder = "asc" | "desc"
+ export type TProjectSortOption = `${TProjectSortKey}-${TSortOrder}`
+
+rendering.ts
+ export type BlendMode = | "normal"
+
+ | "darken"
+
+ | "multiply"
+
+ | "color-burn"
+
+ | "lighten"
+
+ | "screen"
+
+ | "plus-ligh...
+
+sounds.ts
+ export interface SoundEffect {
+ id: number
+ name: string
+ description: string
+ url: string
+ previewUrl?: string
+ downloadUrl?: string
+ duration: number
+ filesize: number
+ type: string
+ channels: number
+ bitrate: number
+ bitdepth: number
+ samplerate: number
+ username: string
+ tags: string[]
+ license: string
+ created: string
+ downloads: number
+ rating: number
+ ratingCount: number
+ }
+ export interface SavedSound {
+ id: number
+ name: string
+ username: string
+ previewUrl?: string
+ downloadUrl?: string
+ duration: number
+ tags: string[]
+ license: string
+ savedAt: string
+ }
+ export interface SavedSoundsData {
+ sounds: SavedSound[]
+ lastModified: string
+ }
+
+stickers.ts
+ export type StickerCategory = keyof typeof STICKER_CATEGORIES
+ export interface StickerItem {
+ id: string
+ provider: string
+ name: string
+ previewUrl: string
+ metadata: Record<string, unknown>
+ }
+ export interface StickerSearchResult {
+ items: StickerItem[]
+ total: number
+ hasMore: boolean
+ }
+ export interface StickerProviderSearchOptions {
+ limit?: number
+ }
+ export interface StickerProviderBrowseOptions {
+ page?: number
+ limit?: number
+ }
+ export interface StickerResolveOptions {
+ width?: number
+ height?: number
+ }
+ export interface StickerProvider {
+ id: string
+ search({
+ query,
+ options,
+ }: {
+ query: string;
+ options?: StickerProviderSearchOptions;
+ }): Promise<StickerSearchResult>
+ browse({
+ options,
+ }: {
+ options?: StickerProviderBrowseOptions;
+ }): Promise<StickerSearchResult>
+ resolveUrl({
+ stickerId,
+ options,
+ }: {
+ stickerId: string;
+ options?: StickerResolveOptions;
+ }): string
+ }
+
+time.ts
+ export type TTimeCode = "MM:SS" | "HH:MM:SS" | "HH:MM:SS:CS" | "HH:MM:SS:FF"
+
+timeline.ts
+ export interface Bookmark {
+ time: number
+ note?: string
+ color?: string
+ duration?: number
+ }
+ export interface TScene {
+ id: string
+ name: string
+ isMain: boolean
+ tracks: TimelineTrack[]
+ bookmarks: Bookmark[]
+ createdAt: Date
+ updatedAt: Date
+ }
+ export type TrackType = "video" | "text" | "audio" | "sticker"
+ export interface VideoTrack extends BaseTrack {
+ type: "video"
+ elements: (VideoElement | ImageElement)[]
+ isMain: boolean
+ muted: boolean
+ hidden: boolean
+ }
+ export interface TextTrack extends BaseTrack {
+ type: "text"
+ elements: TextElement[]
+ hidden: boolean
+ }
+ export interface AudioTrack extends BaseTrack {
+ type: "audio"
+ elements: AudioElement[]
+ muted: boolean
+ }
+ export interface StickerTrack extends BaseTrack {
+ type: "sticker"
+ elements: StickerElement[]
+ hidden: boolean
+ }
+ export type TimelineTrack = VideoTrack | TextTrack | AudioTrack | StickerTrack
+ export interface Transform {
+ scale: number
+ position: {
+ x: number;
+ y: number;
+ }
+ rotate: number
+ }
+ export interface UploadAudioElement extends BaseAudioElement {
+ sourceType: "upload"
+ mediaId: string
+ }
+ export interface LibraryAudioElement extends BaseAudioElement {
+ sourceType: "library"
+ sourceUrl: string
+ }
+ export type AudioElement = UploadAudioElement | LibraryAudioElement
+ export interface VideoElement extends BaseTimelineElement {
+ type: "video"
+ mediaId: string
+ muted?: boolean
+ hidden?: boolean
+ transform: Transform
+ opacity: number
+ blendMode?: BlendMode
+ }
+ export interface ImageElement extends BaseTimelineElement {
+ type: "image"
+ mediaId: string
+ hidden?: boolean
+ transform: Transform
+ opacity: number
+ blendMode?: BlendMode
+ }
+ export interface TextElement extends BaseTimelineElement {
+ type: "text"
+ content: string
+ fontSize: number
+ fontFamily: string
+ color: string
+ backgroundColor: string
+ textAlign: "left" | "center" | "right"
+ fontWeight: "normal" | "bold"
+ fontStyle: "normal" | "italic"
+ textDecoration: "none" | "underline" | "line-through"
+ letterSpacing?: number
+ lineHeight?: number
+ hidden?: boolean
+ transform: Transform
+ opacity: number
+ blendMode?: BlendMode
+ }
+ export interface StickerElement extends BaseTimelineElement {
+ type: "sticker"
+ stickerId: string
+ hidden?: boolean
+ transform: Transform
+ opacity: number
+ blendMode?: BlendMode
+ }
+ export type TimelineElement = | AudioElement
+ | VideoElement
+ | ImageElement
+ | TextElement
+ | StickerElement
+ export type ElementType = TimelineElement["type"]
+ export type CreateUploadAudioElement = Omit<UploadAudioElement, "id">
+ export type CreateLibraryAudioElement = Omit<LibraryAudioElement, "id">
+ export type CreateAudioElement = | CreateUploadAudioElement
+ | CreateLibraryAudioElement
+ export type CreateVideoElement = Omit<VideoElement, "id">
+ export type CreateImageElement = Omit<ImageElement, "id">
+ export type CreateTextElement = Omit<TextElement, "id">
+ export type CreateStickerElement = Omit<StickerElement, "id">
+ export type CreateTimelineElement = | CreateAudioElement
+ | CreateVideoElement
+ | CreateImageElement
+ | CreateTextElement
+ | CreateSt...
+ export interface ElementDragState {
+ isDragging: boolean
+ elementId: string | null
+ trackId: string | null
+ startMouseX: number
+ startMouseY: number
+ startElementTime: number
+ clickOffsetTime: number
+ currentTime: number
+ currentMouseY: number
+ }
+ export interface DropTarget {
+ trackIndex: number
+ isNewTrack: boolean
+ insertPosition: "above" | "below" | null
+ xPosition: number
+ }
+ export interface ComputeDropTargetParams {
+ elementType: ElementType
+ mouseX: number
+ mouseY: number
+ tracks: TimelineTrack[]
+ playheadTime: number
+ isExternalDrop: boolean
+ elementDuration: number
+ pixelsPerSecond: number
+ zoomLevel: number
+ verticalDragDirection?: "up" | "down" | null
+ startTimeOverride?: number
+ excludeElementId?: string
+ }
+ export interface ClipboardItem {
+ trackId: string
+ trackType: TrackType
+ element: CreateTimelineElement
+ }
+
+transcription.ts
+ export type TranscriptionLanguage = LanguageCode | "auto"
+ export interface TranscriptionSegment {
+ text: string
+ start: number
+ end: number
+ }
+ export interface TranscriptionResult {
+ text: string
+ segments: TranscriptionSegment[]
+ language: string
+ }
+ export type TranscriptionStatus = | "idle"
+ | "loading-model"
+ | "transcribing"
+ | "complete"
+ | "error"
+ export interface TranscriptionProgress {
+ status: TranscriptionStatus
+ progress: number
+ message?: string
+ }
+ export type TranscriptionModelId = | "whisper-tiny"
+ | "whisper-small"
+ | "whisper-medium"
+ | "whisper-large-v3-turbo"
+ export interface TranscriptionModel {
+ id: TranscriptionModelId
+ name: string
+ huggingFaceId: string
+ description: string
+ }
+ export interface CaptionChunk {
+ text: string
+ startTime: number
+ duration: number
+ }
+
+## apps/web/src/utils
+
+browser.ts
+ export function isTypableDOMElement({
+ element,
+ }: {
+ element: HTMLElement;
+ }): boolean
+
+color.ts
+ export type ColorFormat = "hex" | "rgb" | "hsl" | "hsv"
+ export function hexToHsv({ hex }: { hex: string }): [number, number, number]
+ export function hsvToHex({
+
+ h,
+
+ s,
+
+ v,
+
+ }: { h: number; s: number; v: number }): string
+ export function parseHexAlpha({ hex }: { hex: string }): {
+
+ rgb: string;
+
+ alpha: number;
+
+ }
+ export function appendAlpha({
+
+ rgbHex,
+
+ alpha,
+
+ }: { rgbHex: string; alpha: number }): string
+ export function extractColorFromText({
+
+ text,
+
+ }: { text: string }): string | null
+ export function formatColorValue({
+
+ hex,
+
+ format,
+
+ }: {
+
+ hex: string;
+
+ format: ColorFormat;
+
+ }): string
+ export function parseColorInput({
+
+ input,
+
+ format,
+
+ }: {
+
+ input: string;
+
+ format: ColorFormat;
+
+ }): string | null
+
+date.ts
+ export function formatDate({ date }: { date: Date }): string
+
+geometry.ts
+ export function dimensionToAspectRatio({
+ width,
+ height,
+ }: {
+ width: number;
+ height: number;
+ }): string
+
+id.ts
+ export function generateUUID(): string
+
+math.ts
+ export function clamp({
+ value,
+ min,
+ max,
+ }: {
+ value: number;
+ min: number;
+ max: number;
+ }): number
+ export function evaluateMathExpression({
+ input,
+ }: {
+ input: string;
+ }): number | null
+
+platform.ts
+ export function getPlatformSpecialKey(): string
+ export function getPlatformAlternateKey(): string
+ export function isAppleDevice(): boolean
+
+string.ts
+ export function capitalizeFirstLetter({ string }: { string: string })
+ export function uppercase({ string }: { string: string })
+
+ui.ts
+ export function cn(...inputs: ClassValue[]): string
+
+## packages/ui/src/icons
+
+brand.tsx
+ export function OcVercelIcon({ className }: { className?: string })
+ export function OcMarbleIcon({
+ className = "",
+ size = 32,
+ }: {
+ className?: string;
+ size?: number;
+ })
+ export function OcDataBuddyIcon({
+ className = "",
+ size = 32,
+ }: {
+ className?: string;
+ size?: number;
+ })
+
+ui.tsx
+ export function OcVideoIcon({
+ className = "",
+ size = 32,
+ }: {
+ className?: string;
+ size?: number;
+ })
+ export function OcCheckerboardIcon({
+ className = "",
+ size = 32,
+ }: {
+ className?: string;
+ size?: number;
+ })
+ export function OcFontWeightIcon({
+ className = "",
+ size = 32,
+ }: {
+ className?: string;
+ size?: number;
+ })
+ export function OcSlidersVerticalIcon({
+ className = "",
+ size = 32,
+ }: {
+ className?: string;
+ size?: number;
+ })
+ export function OcSocialIcon({
+ className = "",
+ size = 32,
+ }: {
+ className?: string;
+ size?: number;
+ })
+
+```
+
+---
+
+_Generated and maintained by [Twiggy](https://github.com/twiggy-tools/Twiggy)_