diff options
| author | Maze Winther <mazewinther@gmail.com> | 2026-03-01 21:48:37 +0100 |
|---|---|---|
| committer | Maze Winther <mazewinther@gmail.com> | 2026-03-01 21:48:37 +0100 |
| commit | 9a00e8ac5b77e8d82102457aaffd19945a2f52cb (patch) | |
| tree | eb2158b23512d02d2a8f6833fa6dbe144ce5c913 | |
| parent | 51234e673bdd17156d3ba4882172b2eea0752750 (diff) | |
| download | opencut-9a00e8ac5b77e8d82102457aaffd19945a2f52cb.tar.gz | |
disable cursor rules
| -rw-r--r-- | .cursor/rules/codebase-index.mdc | 4910 | ||||
| -rw-r--r-- | .cursor/rules/comments.mdc | 3 | ||||
| -rw-r--r-- | .cursor/rules/handling-uncertainty.mdc | 3 | ||||
| -rw-r--r-- | .cursor/rules/readability.mdc | 3 | ||||
| -rw-r--r-- | .cursor/rules/separation-of-concerns.mdc | 3 | ||||
| -rw-r--r-- | .cursor/rules/ultracite.mdc | 5 | ||||
| -rw-r--r-- | .cursor/rules/writing-scannable-code.mdc | 3 |
7 files changed, 2521 insertions, 2409 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)_ diff --git a/.cursor/rules/comments.mdc b/.cursor/rules/comments.mdc index e732e859..4b9180cf 100644 --- a/.cursor/rules/comments.mdc +++ b/.cursor/rules/comments.mdc @@ -1,7 +1,6 @@ --- -alwaysApply: true +alwaysApply: false --- - # Comment Guidelines ## Good Comments (Human-style) diff --git a/.cursor/rules/handling-uncertainty.mdc b/.cursor/rules/handling-uncertainty.mdc index c6bae730..59cfb5bd 100644 --- a/.cursor/rules/handling-uncertainty.mdc +++ b/.cursor/rules/handling-uncertainty.mdc @@ -1,7 +1,6 @@ --- -alwaysApply: true +alwaysApply: false --- - # Handling Uncertainty ## Principle diff --git a/.cursor/rules/readability.mdc b/.cursor/rules/readability.mdc index 6be08cf7..22bb5397 100644 --- a/.cursor/rules/readability.mdc +++ b/.cursor/rules/readability.mdc @@ -1,7 +1,6 @@ --- -alwaysApply: true +alwaysApply: false --- - # Readability First Optimize code for AI agents to understand and modify. diff --git a/.cursor/rules/separation-of-concerns.mdc b/.cursor/rules/separation-of-concerns.mdc index 0dd97118..4abb8808 100644 --- a/.cursor/rules/separation-of-concerns.mdc +++ b/.cursor/rules/separation-of-concerns.mdc @@ -1,7 +1,6 @@ --- -alwaysApply: true +alwaysApply: false --- - # Separation of Concerns ## Core Principle diff --git a/.cursor/rules/ultracite.mdc b/.cursor/rules/ultracite.mdc index 3dcaabaa..83e14c18 100644 --- a/.cursor/rules/ultracite.mdc +++ b/.cursor/rules/ultracite.mdc @@ -1,9 +1,6 @@ --- -description: Ultracite Rules - AI-Ready Formatter and Linter -globs: "**/*.{ts,tsx,js,jsx}" -alwaysApply: true +alwaysApply: false --- - # Project Context Ultracite enforces strict type safety, accessibility standards, and consistent code quality for JavaScript/TypeScript projects using Biome's formatter. diff --git a/.cursor/rules/writing-scannable-code.mdc b/.cursor/rules/writing-scannable-code.mdc index 97ed87e9..2c36d496 100644 --- a/.cursor/rules/writing-scannable-code.mdc +++ b/.cursor/rules/writing-scannable-code.mdc @@ -1,7 +1,6 @@ --- -alwaysApply: true +alwaysApply: false --- - # Scannable Code Guidelines/Separating Concerns. ## Core Principle |
