From 9a00e8ac5b77e8d82102457aaffd19945a2f52cb Mon Sep 17 00:00:00 2001 From: Maze Winther Date: Sun, 1 Mar 2026 21:48:37 +0100 Subject: [PATCH] disable cursor rules --- .cursor/rules/codebase-index.mdc | 4910 +++++++++++----------- .cursor/rules/comments.mdc | 3 +- .cursor/rules/handling-uncertainty.mdc | 3 +- .cursor/rules/readability.mdc | 3 +- .cursor/rules/separation-of-concerns.mdc | 3 +- .cursor/rules/ultracite.mdc | 5 +- .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 - -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 - export const TRACK_HEIGHTS: Record - 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 - -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; - }) - -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; - }) - -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; - }) - -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 - -use-sound-search.ts - export function useSoundSearch({ - query, - commercialOnly, - }: { - query: string; - commercialOnly: boolean; - }) - -use-transform-handles.ts - export function useTransformHandles({ - canvasRef, - }: { - canvasRef: React.RefObject; - }) - -## apps/web/src/hooks/actions - -use-action-handler.ts - export function useActionHandler( - action: A, - handler: TActionFunc, - 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; - }): 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 - } - export interface CollectionInfo { - prefix: string - total: number - title?: string - uncategorized?: string[] - categories?: Record - hidden?: string[] - aliases?: Record - } - export function getCollections( - category?: string, - ): Promise> - export function getCollection( - prefix: string, - ): Promise - export function searchIcons( - query: string, - limit: number = 64, - prefixes?: string[], - category?: string, - ): Promise - 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[2], - ): string - export function downloadSvgAsText( - iconName: string, - params?: Parameters[1], - ): Promise - export function svgToFile(svgText: string, fileName: string): File - export const POPULAR_COLLECTIONS - export function getCategoriesFromCollections( - collections: Record, - ): 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[] - -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 - } - export const ACTIONS - export type TAction = keyof typeof ACTIONS - export function getActionDefinition(action: TAction): TActionDefinition - export function getDefaultShortcuts(): Record - -registry.ts - export function bindAction( - action: A, - handler: TActionFunc, - ) - export function unbindAction( - action: A, - handler: TActionFunc, - ) - export const invokeAction = ( - action: A, - args?: TArgOfAction, - 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 - export type TActionWithNoArgs = Exclude - export type TArgOfAction = A extends TActionWithArgs - ? TActionArgsMap[A] - : undefined - export type TActionFunc = A extends TActionWithArgs - ? (arg: TArgOfAction, trigger?: TInvocationTrigger) => void - : (_?:... - export type TInvocationTrigger = "keypress" | "mouseclick" - export type TBoundActionList = { - [A in TAction]?: Array>; - } - export type TActionHandlerOptions = | MutableRefObject - | 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 - -## 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 - export function loadFullFont({ - family, - weights = [400, 700], - }: { - family: string; - weights?: number[]; - }): Promise - export function loadFonts({ - families, - }: { - families: string[]; - }): Promise - -## 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 - 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 => ... - 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 - export function collectAudioElements({ - tracks, - mediaAssets, - audioContext, - }: { - tracks: TimelineTrack[]; - mediaAssets: MediaAsset[]; - audioContext: AudioContext; - }): Promise - 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 - export function collectAudioClips({ - tracks, - mediaAssets, - }: { - tracks: TimelineTrack[]; - mediaAssets: MediaAsset[]; - }): Promise - export function createTimelineAudioBuffer({ - tracks, - mediaAssets, - duration, - sampleRate = 44100, - audioContext, - }: { - tracks: TimelineTrack[]; - mediaAssets: MediaAsset[]; - duration: number; - sampleRate?: number; - audioContext?: AudioContext; - }): Promise - -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 => ... - -processing.ts - export interface ProcessedMediaAsset extends Omit - export function generateThumbnail({ - videoFile, - timeInSeconds, - }: { - videoFile: File; - timeInSeconds: number; - }): Promise - export function generateImageThumbnail({ - imageFile, - }: { - imageFile: File; - }): Promise - export function processMediaAssets({ - files, - onProgress, - }: { - files: FileList | File[]; - onProgress?: ({ progress }: { progress: number }) => void; - }): Promise - -## 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 - export function browseStickers({ - category, - page = 1, - limit = DEFAULT_SEARCH_LIMIT, - }: { - category: StickerCategory; - page?: number; - limit?: number; - }): Promise - -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>; - }): 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>; - 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 { - 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 - } - -## apps/web/src/services/storage - -indexeddb-adapter.ts - export class IndexedDBAdapter implements StorageAdapter { - dbName: string - storeName: string - version: number - constructor(dbName: string, storeName: string, version = 1) - async get(key: string): Promise - async set(key: string, value: T): Promise - async remove(key: string): Promise - async list(): Promise - async getAll(): Promise - async clear(): Promise - } - export function deleteDatabase({ - dbName, - }: { - dbName: string; - }): Promise - -opfs-adapter.ts - export class OPFSAdapter implements StorageAdapter { - directoryName: string - constructor(directoryName = "media") - async get(key: string): Promise - async set(key: string, file: File): Promise - async remove(key: string): Promise - async list(): Promise - async clear(): Promise - static isSupported(): boolean - } - -service.ts - export const storageService - -types.ts - export interface StorageAdapter { - get(key: string): Promise - set(key: string, value: T): Promise - remove(key: string): Promise - list(): Promise - clear(): Promise - } - 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 & { - createdAt: string; - updatedAt: string; - } - export type SerializedProjectMetadata = Omit< - TProjectMetadata, - "createdAt" | "updatedAt" - > & { - createdAt: string; - updatedAt: string; - } - export type SerializedProject = Omit & { - 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 - 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 { - 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 - } - -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 - } - 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 - browse({ - options, - }: { - options?: StickerProviderBrowseOptions; - }): Promise - 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 - export type CreateLibraryAudioElement = Omit - export type CreateAudioElement = | CreateUploadAudioElement - | CreateLibraryAudioElement - export type CreateVideoElement = Omit - export type CreateImageElement = Omit - export type CreateTextElement = Omit - export type CreateStickerElement = Omit - 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 + +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 + export const TRACK_HEIGHTS: Record + 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 + +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; + }) + +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; + }) + +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; + }) + +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 + +use-sound-search.ts + export function useSoundSearch({ + query, + commercialOnly, + }: { + query: string; + commercialOnly: boolean; + }) + +use-transform-handles.ts + export function useTransformHandles({ + + canvasRef, + + }: { + + canvasRef: React.RefObject; + + }) + +## apps/web/src/hooks/actions + +use-action-handler.ts + export function useActionHandler( + action: A, + handler: TActionFunc, + 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; + }): 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 + } + export interface CollectionInfo { + prefix: string + total: number + title?: string + uncategorized?: string[] + categories?: Record + hidden?: string[] + aliases?: Record + } + export function getCollections( + category?: string, + ): Promise> + export function getCollection( + prefix: string, + ): Promise + export function searchIcons( + query: string, + limit: number = 64, + prefixes?: string[], + category?: string, + ): Promise + 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[2], + ): string + export function downloadSvgAsText( + iconName: string, + params?: Parameters[1], + ): Promise + export function svgToFile(svgText: string, fileName: string): File + export const POPULAR_COLLECTIONS + export function getCategoriesFromCollections( + collections: Record, + ): 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[] + +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 + } + export const ACTIONS + export type TAction = keyof typeof ACTIONS + export function getActionDefinition(action: TAction): TActionDefinition + export function getDefaultShortcuts(): Record + +registry.ts + export function bindAction( + action: A, + handler: TActionFunc, + ) + export function unbindAction( + action: A, + handler: TActionFunc, + ) + export const invokeAction = ( + action: A, + args?: TArgOfAction, + 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 + export type TActionWithNoArgs = Exclude + export type TArgOfAction = A extends TActionWithArgs + ? TActionArgsMap[A] + : undefined + export type TActionFunc = A extends TActionWithArgs + ? (arg: TArgOfAction, trigger?: TInvocationTrigger) => void + : (_?:... + export type TInvocationTrigger = "keypress" | "mouseclick" + export type TBoundActionList = { + [A in TAction]?: Array>; + } + export type TActionHandlerOptions = | MutableRefObject + | 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 + +## 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 + export function loadFullFont({ + family, + weights = [400, 700], + }: { + family: string; + weights?: number[]; + }): Promise + export function loadFonts({ + families, + }: { + families: string[]; + }): Promise + +## 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 + 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 => ... + 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 + export function collectAudioElements({ + tracks, + mediaAssets, + audioContext, + }: { + tracks: TimelineTrack[]; + mediaAssets: MediaAsset[]; + audioContext: AudioContext; + }): Promise + 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 + export function collectAudioClips({ + tracks, + mediaAssets, + }: { + tracks: TimelineTrack[]; + mediaAssets: MediaAsset[]; + }): Promise + export function createTimelineAudioBuffer({ + tracks, + mediaAssets, + duration, + sampleRate = 44100, + audioContext, + }: { + tracks: TimelineTrack[]; + mediaAssets: MediaAsset[]; + duration: number; + sampleRate?: number; + audioContext?: AudioContext; + }): Promise + +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 => ... + +processing.ts + export interface ProcessedMediaAsset extends Omit + export function generateThumbnail({ + videoFile, + timeInSeconds, + }: { + videoFile: File; + timeInSeconds: number; + }): Promise + export function generateImageThumbnail({ + imageFile, + }: { + imageFile: File; + }): Promise + export function processMediaAssets({ + files, + onProgress, + }: { + files: FileList | File[]; + onProgress?: ({ progress }: { progress: number }) => void; + }): Promise + +## 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 + export function browseStickers({ + category, + page = 1, + limit = DEFAULT_SEARCH_LIMIT, + }: { + category: StickerCategory; + page?: number; + limit?: number; + }): Promise + +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>; + }): 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>; + 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 { + 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 + } + +## apps/web/src/services/storage + +indexeddb-adapter.ts + export class IndexedDBAdapter implements StorageAdapter { + dbName: string + storeName: string + version: number + constructor(dbName: string, storeName: string, version = 1) + async get(key: string): Promise + async set(key: string, value: T): Promise + async remove(key: string): Promise + async list(): Promise + async getAll(): Promise + async clear(): Promise + } + export function deleteDatabase({ + dbName, + }: { + dbName: string; + }): Promise + +opfs-adapter.ts + export class OPFSAdapter implements StorageAdapter { + directoryName: string + constructor(directoryName = "media") + async get(key: string): Promise + async set(key: string, file: File): Promise + async remove(key: string): Promise + async list(): Promise + async clear(): Promise + static isSupported(): boolean + } + +service.ts + export const storageService + +types.ts + export interface StorageAdapter { + get(key: string): Promise + set(key: string, value: T): Promise + remove(key: string): Promise + list(): Promise + clear(): Promise + } + 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 & { + createdAt: string; + updatedAt: string; + } + export type SerializedProjectMetadata = Omit< + TProjectMetadata, + "createdAt" | "updatedAt" + > & { + createdAt: string; + updatedAt: string; + } + export type SerializedProject = Omit & { + 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 + 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 { + 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 + } + +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 + } + 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 + browse({ + options, + }: { + options?: StickerProviderBrowseOptions; + }): Promise + 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 + export type CreateLibraryAudioElement = Omit + export type CreateAudioElement = | CreateUploadAudioElement + | CreateLibraryAudioElement + export type CreateVideoElement = Omit + export type CreateImageElement = Omit + export type CreateTextElement = Omit + export type CreateStickerElement = Omit + 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