1843 lines
44 KiB
Plaintext
1843 lines
44 KiB
Plaintext
---
|
|
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/components/editor/timeline
|
|
|
|
audio-waveform.tsx
|
|
export function AudioWaveform({
|
|
|
|
audioUrl,
|
|
|
|
audioBuffer,
|
|
|
|
height = 32,
|
|
|
|
className = "",
|
|
|
|
}: AudioWaveformProps)
|
|
|
|
## apps/web/src/constants
|
|
|
|
editor-constants.ts
|
|
export const PLATFORM_LAYOUTS: Record<TPlatformLayout, string>
|
|
export const PANEL_CONFIG
|
|
|
|
export-constants.ts
|
|
export const DEFAULT_EXPORT_OPTIONS
|
|
export const EXPORT_MIME_TYPES
|
|
|
|
font-constants.ts
|
|
export interface FontOption {
|
|
value: string
|
|
label: string
|
|
category: "system" | "google" | "custom"
|
|
weights?: number[]
|
|
hasClassName?: boolean
|
|
}
|
|
export const FONT_OPTIONS: FontOption[]
|
|
export const DEFAULT_FONT
|
|
export type FontFamily = (typeof FONT_OPTIONS)[number]["value"]
|
|
export const getFontByValue = (value: string): FontOption | undefined => ...
|
|
export const getGoogleFonts = (): FontOption[] => ...
|
|
export const getSystemFonts = (): FontOption[] => ...
|
|
|
|
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[]
|
|
|
|
stickers-constants.ts
|
|
export const STICKER_CATEGORIES
|
|
export const STICKER_CATEGORY_CONFIG: Record<
|
|
|
|
(typeof STICKER_CATEGORIES)[number],
|
|
|
|
string | undefined
|
|
|
|
>
|
|
|
|
text-constants.ts
|
|
export const DEFAULT_TEXT_ELEMENT: Omit<TextElement, "id">
|
|
|
|
timeline-constants.tsx
|
|
export const TRACK_COLORS: Record<TrackType, { background: string }>
|
|
export const TRACK_HEIGHTS: Record<TrackType, number>
|
|
export const TRACK_GAP
|
|
export const TIMELINE_CONSTANTS
|
|
export const DEFAULT_TIMELINE_VIEW_STATE: TTimelineViewState
|
|
export const TRACK_ICONS: Record<TrackType, React.ReactNode>
|
|
|
|
transcription-constants.ts
|
|
export const TRANSCRIPTION_LANGUAGES
|
|
export const TRANSCRIPTION_MODELS: TranscriptionModel[]
|
|
export const DEFAULT_TRANSCRIPTION_MODEL: TranscriptionModelId
|
|
export const DEFAULT_CHUNK_LENGTH_SECONDS
|
|
export const DEFAULT_STRIDE_SECONDS
|
|
export const DEFAULT_WORDS_PER_CAPTION
|
|
export const MIN_CAPTION_DURATION_SECONDS
|
|
|
|
## apps/web/src/core
|
|
|
|
index.ts
|
|
export class EditorCore {
|
|
instance: EditorCore | null
|
|
command: CommandManager
|
|
playback: PlaybackManager
|
|
timeline: TimelineManager
|
|
scenes: ScenesManager
|
|
project: ProjectManager
|
|
media: MediaManager
|
|
renderer: RendererManager
|
|
save: SaveManager
|
|
audio: AudioManager
|
|
selection: SelectionManager
|
|
static getInstance(): EditorCore
|
|
static reset(): void
|
|
}
|
|
|
|
## apps/web/src/hooks
|
|
|
|
use-editor.ts
|
|
export function useEditor(): EditorCore
|
|
|
|
use-file-upload.ts
|
|
export function useFileUpload({
|
|
|
|
accept,
|
|
|
|
multiple,
|
|
|
|
onFilesSelected,
|
|
|
|
}: UseFileUploadOptions = {})
|
|
|
|
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-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-sound-search.ts
|
|
export function useSoundSearch({
|
|
|
|
query,
|
|
|
|
commercialOnly,
|
|
|
|
}: {
|
|
|
|
query: string;
|
|
|
|
commercialOnly: boolean;
|
|
|
|
})
|
|
|
|
## apps/web/src/hooks/actions
|
|
|
|
use-action-handler.ts
|
|
export function useActionHandler(
|
|
|
|
action: A,
|
|
|
|
handler: TActionFunc<A>,
|
|
|
|
isActive: TActionHandlerOptions,
|
|
|
|
)
|
|
|
|
use-editor-actions.ts
|
|
export function useEditorActions()
|
|
|
|
## apps/web/src/hooks/storage
|
|
|
|
use-local-storage.ts
|
|
export function useLocalStorage({
|
|
|
|
key,
|
|
|
|
defaultValue,
|
|
|
|
}: {
|
|
|
|
key: string;
|
|
|
|
defaultValue: T;
|
|
|
|
}): [
|
|
|
|
T,
|
|
|
|
({ value }: { value: T | ((previousValue: T) => T) }) => void,
|
|
|
|
boolean,
|
|
|
|
]
|
|
|
|
## apps/web/src/hooks/timeline
|
|
|
|
use-edge-auto-scroll.ts
|
|
export function useEdgeAutoScroll({
|
|
|
|
isActive,
|
|
|
|
getMouseClientX,
|
|
|
|
rulerScrollRef,
|
|
|
|
tracksScrollRef,
|
|
|
|
contentWidth,
|
|
|
|
edgeThreshold = 100,
|
|
|
|
maxScrollSpeed = 15,
|
|
|
|
}: UseEdgeAutoScrollParams): void
|
|
|
|
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"
|
|
elementId?: string
|
|
trackId?: string
|
|
}
|
|
export interface SnapResult {
|
|
snappedTime: number
|
|
snapPoint: SnapPoint | null
|
|
snapDistance: number
|
|
}
|
|
export interface UseTimelineSnappingOptions {
|
|
snapThreshold?: number
|
|
enableElementSnapping?: boolean
|
|
enablePlayheadSnapping?: boolean
|
|
}
|
|
export function useTimelineSnapping({
|
|
|
|
snapThreshold = 10,
|
|
|
|
enableElementSnapping = true,
|
|
|
|
enablePlayheadSnapping = true,
|
|
|
|
}: UseTimelineSnappingOptions = {})
|
|
|
|
use-timeline-zoom.ts
|
|
export function useTimelineZoom({
|
|
|
|
containerRef,
|
|
|
|
minZoom = TIMELINE_CONSTANTS.ZOOM_MIN,
|
|
|
|
initialZoom,
|
|
|
|
initialScrollLeft,
|
|
|
|
initialPlayheadTime,
|
|
|
|
tracksScrollRef,
|
|
|
|
rulerScrollRef,
|
|
|
|
}: UseTimelineZoomProps): UseTimelineZoomReturn
|
|
|
|
## apps/web/src/hooks/timeline/element
|
|
|
|
use-element-interaction.ts
|
|
export function useElementInteraction({
|
|
|
|
zoomLevel,
|
|
|
|
timelineRef,
|
|
|
|
tracksContainerRef,
|
|
|
|
tracksScrollRef,
|
|
|
|
headerRef,
|
|
|
|
snappingEnabled,
|
|
|
|
onSnapPointChange,
|
|
|
|
}: UseElementInteractionProps)
|
|
|
|
use-element-resize.ts
|
|
export interface ResizeState {
|
|
elementId: string
|
|
side: "left" | "right"
|
|
startX: number
|
|
initialTrimStart: number
|
|
initialTrimEnd: number
|
|
initialStartTime: number
|
|
initialDuration: number
|
|
}
|
|
export function useTimelineElementResize({
|
|
|
|
element,
|
|
|
|
track,
|
|
|
|
zoomLevel,
|
|
|
|
onSnapPointChange,
|
|
|
|
onResizeStateChange,
|
|
|
|
}: UseTimelineElementResizeProps)
|
|
|
|
use-element-selection.ts
|
|
export function useElementSelection()
|
|
|
|
## apps/web/src/lib
|
|
|
|
drag-data.ts
|
|
export function setDragData({
|
|
|
|
dataTransfer,
|
|
|
|
dragData,
|
|
|
|
}: {
|
|
|
|
dataTransfer: DataTransfer;
|
|
|
|
dragData: TimelineDragData;
|
|
|
|
}): void
|
|
export function getDragData({
|
|
|
|
dataTransfer,
|
|
|
|
}: {
|
|
|
|
dataTransfer: DataTransfer;
|
|
|
|
}): TimelineDragData | null
|
|
export function hasDragData({
|
|
|
|
dataTransfer,
|
|
|
|
}: {
|
|
|
|
dataTransfer: DataTransfer;
|
|
|
|
}): boolean
|
|
export function clearDragData(): void
|
|
|
|
export.ts
|
|
export function getExportMimeType({
|
|
|
|
format,
|
|
|
|
}: {
|
|
|
|
format: ExportFormat;
|
|
|
|
}): string
|
|
export function getExportFileExtension({
|
|
|
|
format,
|
|
|
|
}: {
|
|
|
|
format: ExportFormat;
|
|
|
|
}): string
|
|
|
|
iconify-api.ts
|
|
export const ICONIFY_HOSTS
|
|
export interface IconSet {
|
|
prefix: string
|
|
name: string
|
|
total: number
|
|
author?: {
|
|
|
|
name: string;
|
|
|
|
url?: string;
|
|
|
|
}
|
|
license?: {
|
|
|
|
title: string;
|
|
|
|
spdx?: string;
|
|
|
|
url?: string;
|
|
|
|
}
|
|
samples?: string[]
|
|
category?: string
|
|
palette?: boolean
|
|
}
|
|
export interface IconSearchResult {
|
|
icons: string[]
|
|
total: number
|
|
limit: number
|
|
start: number
|
|
collections: Record<string, IconSet>
|
|
}
|
|
export interface CollectionInfo {
|
|
prefix: string
|
|
total: number
|
|
title?: string
|
|
uncategorized?: string[]
|
|
categories?: Record<string, string[]>
|
|
hidden?: string[]
|
|
aliases?: Record<string, string>
|
|
}
|
|
export function getCollections(
|
|
|
|
category?: string,
|
|
|
|
): Promise<Record<string, IconSet>>
|
|
export function getCollection(
|
|
|
|
prefix: string,
|
|
|
|
): Promise<CollectionInfo | null>
|
|
export function searchIcons(
|
|
|
|
query: string,
|
|
|
|
limit: number = 64,
|
|
|
|
prefixes?: string[],
|
|
|
|
category?: string,
|
|
|
|
): Promise<IconSearchResult>
|
|
export function buildIconSvgUrl(
|
|
|
|
host: string,
|
|
|
|
iconName: string,
|
|
|
|
params?: {
|
|
|
|
color?: string;
|
|
|
|
width?: number;
|
|
|
|
height?: number;
|
|
|
|
flip?: "horizontal" | "vertical" | "horizontal,vertical";
|
|
|
|
rotate?: number | string;
|
|
|
|
},
|
|
|
|
): string
|
|
export function getIconSvgUrl(
|
|
|
|
iconName: string,
|
|
|
|
params?: Parameters<typeof buildIconSvgUrl>[2],
|
|
|
|
): string
|
|
export function downloadSvgAsText(
|
|
|
|
iconName: string,
|
|
|
|
params?: Parameters<typeof getIconSvgUrl>[1],
|
|
|
|
): Promise<string>
|
|
export function svgToFile(svgText: string, fileName: string): File
|
|
export const POPULAR_COLLECTIONS
|
|
export function getCategoriesFromCollections(
|
|
|
|
collections: Record<string, IconSet>,
|
|
|
|
): string[]
|
|
|
|
rate-limit.ts
|
|
export const baseRateLimit
|
|
export function checkRateLimit({ request }: { request: Request })
|
|
|
|
scenes.ts
|
|
export function getMainScene({ scenes }: { scenes: TScene[] }): TScene | null
|
|
export function ensureMainScene({ scenes }: { scenes: TScene[] }): TScene[]
|
|
export function buildDefaultScene({
|
|
|
|
name,
|
|
|
|
isMain,
|
|
|
|
}: {
|
|
|
|
name: string;
|
|
|
|
isMain: boolean;
|
|
|
|
}): TScene
|
|
export function canDeleteScene({ scene }: { scene: TScene }): {
|
|
|
|
canDelete: boolean;
|
|
|
|
reason?: string;
|
|
|
|
}
|
|
export function getFallbackSceneAfterDelete({
|
|
|
|
scenes,
|
|
|
|
deletedSceneId,
|
|
|
|
currentSceneId,
|
|
|
|
}: {
|
|
|
|
scenes: TScene[];
|
|
|
|
deletedSceneId: string;
|
|
|
|
currentSceneId: string | null;
|
|
|
|
}): TScene | null
|
|
export function findCurrentScene({
|
|
|
|
scenes,
|
|
|
|
currentSceneId,
|
|
|
|
}: {
|
|
|
|
scenes: TScene[];
|
|
|
|
currentSceneId: string;
|
|
|
|
}): TScene | null
|
|
export function getProjectDurationFromScenes({
|
|
|
|
scenes,
|
|
|
|
}: {
|
|
|
|
scenes: TScene[];
|
|
|
|
}): number
|
|
export function updateSceneInArray({
|
|
|
|
scenes,
|
|
|
|
sceneId,
|
|
|
|
updates,
|
|
|
|
}: {
|
|
|
|
scenes: TScene[];
|
|
|
|
sceneId: string;
|
|
|
|
updates: Partial<TScene>;
|
|
|
|
}): TScene[]
|
|
|
|
time.ts
|
|
export function roundToFrame({
|
|
time,
|
|
fps,
|
|
}: {
|
|
time: number;
|
|
fps: number;
|
|
}): number
|
|
export function formatTimeCode({
|
|
timeInSeconds,
|
|
format = "HH:MM:SS:CS",
|
|
fps,
|
|
}: {
|
|
timeInSeconds: number;
|
|
format?: TTimeCode;
|
|
fps?: number;
|
|
}): string
|
|
export function parseTimeCode({
|
|
timeCode,
|
|
format = "HH:MM:SS:CS",
|
|
fps,
|
|
}: {
|
|
timeCode: string;
|
|
format?: TTimeCode;
|
|
fps: number;
|
|
}): number | null
|
|
export function guessTimeCodeFormat({
|
|
timeCode,
|
|
}: {
|
|
timeCode: string;
|
|
}): TTimeCode | null
|
|
export function timeToFrame({
|
|
time,
|
|
fps,
|
|
}: {
|
|
time: number;
|
|
fps: number;
|
|
}): number
|
|
export function frameToTime({
|
|
frame,
|
|
fps,
|
|
}: {
|
|
frame: number;
|
|
fps: number;
|
|
}): number
|
|
export function snapTimeToFrame({
|
|
time,
|
|
fps,
|
|
}: {
|
|
time: number;
|
|
fps: number;
|
|
}): number
|
|
export function getSnappedSeekTime({
|
|
rawTime,
|
|
duration,
|
|
fps,
|
|
}: {
|
|
rawTime: number;
|
|
duration: number;
|
|
fps: number;
|
|
}): number
|
|
export function getLastFrameTime({
|
|
duration,
|
|
fps,
|
|
}: {
|
|
duration: number;
|
|
fps: number;
|
|
}): number
|
|
|
|
## apps/web/src/lib/actions
|
|
|
|
definitions.ts
|
|
export type TActionCategory = | "playback"
|
|
|
|
| "navigation"
|
|
|
|
| "editing"
|
|
|
|
| "selection"
|
|
|
|
| "history"
|
|
|
|
| "timeline"
|
|
|
|
| "con...
|
|
export interface TActionDefinition {
|
|
description: string
|
|
category: TActionCategory
|
|
defaultShortcuts?: ShortcutKey[]
|
|
args?: Record<string, unknown>
|
|
}
|
|
export const ACTIONS
|
|
export type TAction = keyof typeof ACTIONS
|
|
export function getActionDefinition(action: TAction): TActionDefinition
|
|
export function getDefaultShortcuts(): Record<ShortcutKey, TAction>
|
|
|
|
registry.ts
|
|
export function bindAction(
|
|
|
|
action: A,
|
|
|
|
handler: TActionFunc<A>,
|
|
|
|
)
|
|
export function unbindAction(
|
|
|
|
action: A,
|
|
|
|
handler: TActionFunc<A>,
|
|
|
|
)
|
|
export const invokeAction = (
|
|
|
|
action: A,
|
|
|
|
args?: TArgOfAction<A>,
|
|
|
|
trigger?: TInvocationTrigger,
|
|
|
|
) => ...
|
|
|
|
types.ts
|
|
export type TActionArgsMap = {
|
|
|
|
"seek-forward": { seconds: number } | undefined;
|
|
|
|
"seek-backward": { seconds: number } | und...
|
|
export type TActionWithArgs = keyof TActionArgsMap
|
|
export type TActionWithOptionalArgs = | TActionWithNoArgs
|
|
|
|
| TKeysWithValueUndefined<TActionArgsMap>
|
|
export type TActionWithNoArgs = Exclude<TAction, TActionWithArgs>
|
|
export type TArgOfAction<A extends TAction> = A extends TActionWithArgs
|
|
|
|
? TActionArgsMap[A]
|
|
|
|
: undefined
|
|
export type TActionFunc<A extends TAction> = A extends TActionWithArgs
|
|
|
|
? (arg: TArgOfAction<A>, trigger?: TInvocationTrigger) => void
|
|
|
|
: (_...
|
|
export type TInvocationTrigger = "keypress" | "mouseclick"
|
|
export type TBoundActionList = {
|
|
|
|
[A in TAction]?: Array<TActionFunc<A>>;
|
|
|
|
}
|
|
export type TActionHandlerOptions = | MutableRefObject<boolean>
|
|
|
|
| boolean
|
|
|
|
| undefined
|
|
|
|
## apps/web/src/lib/auth
|
|
|
|
server.ts
|
|
export const auth
|
|
export type Auth = typeof auth
|
|
|
|
## apps/web/src/lib/blog
|
|
|
|
query.ts
|
|
export function getPosts()
|
|
export function getTags()
|
|
export function getSinglePost({ slug }: { slug: string })
|
|
export function getCategories()
|
|
export function getAuthors()
|
|
export function processHtmlContent({
|
|
|
|
html,
|
|
|
|
}: {
|
|
|
|
html: string;
|
|
|
|
}): Promise<string>
|
|
|
|
## apps/web/src/lib/db
|
|
|
|
index.ts
|
|
export const db
|
|
|
|
schema.ts
|
|
export const users
|
|
export const sessions
|
|
export const accounts
|
|
export const verifications
|
|
|
|
## apps/web/src/lib/gradients
|
|
|
|
canvas.ts
|
|
export function drawCssBackground({
|
|
|
|
ctx,
|
|
|
|
width,
|
|
|
|
height,
|
|
|
|
css,
|
|
|
|
}: {
|
|
|
|
ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D;
|
|
|
|
width: number;
|
|
|
|
height: number;
|
|
|
|
css: string;
|
|
|
|
}): void
|
|
|
|
parser.ts
|
|
export type GradientOrientation = LinearOrientation | Array<RadialOrientation>
|
|
export type Color = | { type: "hex"; value: string }
|
|
|
|
| { type: "literal"; value: string }
|
|
|
|
| { type: "rgb"; value:...
|
|
export type ColorStop = Color & { length?: Distance }
|
|
export type GradientAst = {
|
|
|
|
type: GradientType;
|
|
|
|
orientation: GradientOrientation | undefined;
|
|
|
|
colorStops: Array<Color...
|
|
export const parseGradient = ({
|
|
|
|
code,
|
|
|
|
}: {
|
|
|
|
code: string;
|
|
|
|
}): Array<GradientAst> => ...
|
|
export const GradientParser
|
|
|
|
## apps/web/src/lib/media
|
|
|
|
audio.ts
|
|
export type CollectedAudioElement = Omit<
|
|
|
|
AudioElement,
|
|
|
|
"type" | "mediaId" | "volume" | "id" | "name" | "sourceType" | "sourceUrl...
|
|
export function createAudioContext(): AudioContext
|
|
export interface DecodedAudio {
|
|
samples: Float32Array
|
|
sampleRate: number
|
|
}
|
|
export function decodeAudioToFloat32({
|
|
|
|
audioBlob,
|
|
|
|
}: {
|
|
|
|
audioBlob: Blob;
|
|
|
|
}): Promise<DecodedAudio>
|
|
export function collectAudioElements({
|
|
|
|
tracks,
|
|
|
|
mediaAssets,
|
|
|
|
audioContext,
|
|
|
|
}: {
|
|
|
|
tracks: TimelineTrack[];
|
|
|
|
mediaAssets: MediaAsset[];
|
|
|
|
audioContext: AudioContext;
|
|
|
|
}): Promise<CollectedAudioElement[]>
|
|
export interface AudioClipSource {
|
|
id: string
|
|
sourceKey: string
|
|
file: File
|
|
startTime: number
|
|
duration: number
|
|
trimStart: number
|
|
trimEnd: number
|
|
muted: boolean
|
|
}
|
|
export function collectAudioMixSources({
|
|
|
|
tracks,
|
|
|
|
mediaAssets,
|
|
|
|
}: {
|
|
|
|
tracks: TimelineTrack[];
|
|
|
|
mediaAssets: MediaAsset[];
|
|
|
|
}): Promise<AudioMixSource[]>
|
|
export function collectAudioClips({
|
|
|
|
tracks,
|
|
|
|
mediaAssets,
|
|
|
|
}: {
|
|
|
|
tracks: TimelineTrack[];
|
|
|
|
mediaAssets: MediaAsset[];
|
|
|
|
}): Promise<AudioClipSource[]>
|
|
export function createTimelineAudioBuffer({
|
|
|
|
tracks,
|
|
|
|
mediaAssets,
|
|
|
|
duration,
|
|
|
|
sampleRate = 44100,
|
|
|
|
audioContext,
|
|
|
|
}: {
|
|
|
|
tracks: TimelineTrack[];
|
|
|
|
mediaAssets: MediaAsset[];
|
|
|
|
duration: number;
|
|
|
|
sampleRate?: number;
|
|
|
|
audioContext?: AudioContext;
|
|
|
|
}): Promise<AudioBuffer | null>
|
|
|
|
media-utils.ts
|
|
export const SUPPORTS_AUDIO: readonly MediaType[]
|
|
export function mediaSupportsAudio({
|
|
|
|
media,
|
|
|
|
}: {
|
|
|
|
media: MediaAsset | null | undefined;
|
|
|
|
}): boolean
|
|
export const getMediaTypeFromFile = ({
|
|
|
|
file,
|
|
|
|
}: {
|
|
|
|
file: File;
|
|
|
|
}): MediaType | null => ...
|
|
|
|
mediabunny.ts
|
|
export function getVideoInfo({
|
|
|
|
videoFile,
|
|
|
|
}: {
|
|
|
|
videoFile: File;
|
|
|
|
}): Promise<{
|
|
|
|
duration: number;
|
|
|
|
width: number;
|
|
|
|
height: number;
|
|
|
|
fps: number;
|
|
|
|
}>
|
|
export const extractTimelineAudio = ({
|
|
|
|
tracks,
|
|
|
|
mediaAssets,
|
|
|
|
totalDuration,
|
|
|
|
onProgress,
|
|
|
|
}: {
|
|
|
|
tracks: TimelineTrack[];
|
|
|
|
mediaAssets: MediaAsset[];
|
|
|
|
totalDuration: number;
|
|
|
|
onProgress?: (progress: number) => void;
|
|
|
|
}): Promise<Blob> => ...
|
|
|
|
processing.ts
|
|
export interface ProcessedMediaAsset extends Omit<MediaAsset, "id">
|
|
export function generateThumbnail({
|
|
|
|
videoFile,
|
|
|
|
timeInSeconds,
|
|
|
|
}: {
|
|
|
|
videoFile: File;
|
|
|
|
timeInSeconds: number;
|
|
|
|
}): Promise<string>
|
|
export function generateImageThumbnail({
|
|
|
|
imageFile,
|
|
|
|
}: {
|
|
|
|
imageFile: File;
|
|
|
|
}): Promise<string>
|
|
export function processMediaAssets({
|
|
|
|
files,
|
|
|
|
onProgress,
|
|
|
|
}: {
|
|
|
|
files: FileList | File[];
|
|
|
|
onProgress?: ({ progress }: { progress: number }) => void;
|
|
|
|
}): Promise<ProcessedMediaAsset[]>
|
|
|
|
## apps/web/src/lib/timeline
|
|
|
|
bookmarks.ts
|
|
export function findBookmarkIndex({
|
|
|
|
bookmarks,
|
|
|
|
frameTime,
|
|
|
|
}: {
|
|
|
|
bookmarks: number[];
|
|
|
|
frameTime: number;
|
|
|
|
}): number
|
|
export function isBookmarkAtTime({
|
|
|
|
bookmarks,
|
|
|
|
frameTime,
|
|
|
|
}: {
|
|
|
|
bookmarks: number[];
|
|
|
|
frameTime: number;
|
|
|
|
}): boolean
|
|
export function toggleBookmarkInArray({
|
|
|
|
bookmarks,
|
|
|
|
frameTime,
|
|
|
|
}: {
|
|
|
|
bookmarks: number[];
|
|
|
|
frameTime: number;
|
|
|
|
}): number[]
|
|
export function removeBookmarkFromArray({
|
|
|
|
bookmarks,
|
|
|
|
frameTime,
|
|
|
|
}: {
|
|
|
|
bookmarks: number[];
|
|
|
|
frameTime: number;
|
|
|
|
}): number[]
|
|
export function getFrameTime({
|
|
|
|
time,
|
|
|
|
fps,
|
|
|
|
}: {
|
|
|
|
time: number;
|
|
|
|
fps: 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 canElementBeHidden(
|
|
|
|
element: TimelineElement,
|
|
|
|
)
|
|
export function hasMediaId(
|
|
|
|
element: TimelineElement,
|
|
|
|
)
|
|
export function requiresMediaId({
|
|
|
|
element,
|
|
|
|
}: {
|
|
|
|
element: CreateTimelineElement;
|
|
|
|
}): boolean
|
|
export function checkElementOverlaps({
|
|
|
|
elements,
|
|
|
|
}: {
|
|
|
|
elements: TimelineElement[];
|
|
|
|
}): boolean
|
|
export function resolveElementOverlaps({
|
|
|
|
elements,
|
|
|
|
}: {
|
|
|
|
elements: TimelineElement[];
|
|
|
|
}): TimelineElement[]
|
|
export function wouldElementOverlap({
|
|
|
|
elements,
|
|
|
|
startTime,
|
|
|
|
endTime,
|
|
|
|
excludeElementId,
|
|
|
|
}: {
|
|
|
|
elements: TimelineElement[];
|
|
|
|
startTime: number;
|
|
|
|
endTime: number;
|
|
|
|
excludeElementId?: string;
|
|
|
|
}): boolean
|
|
export function buildTextElement({
|
|
|
|
raw,
|
|
|
|
startTime,
|
|
|
|
}: {
|
|
|
|
raw: Partial<Omit<TextElement, "type" | "id">>;
|
|
|
|
startTime: number;
|
|
|
|
}): CreateTimelineElement
|
|
export function buildStickerElement({
|
|
|
|
iconName,
|
|
|
|
startTime,
|
|
|
|
}: {
|
|
|
|
iconName: 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 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 }[]
|
|
|
|
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 }
|
|
|
|
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
|
|
|
|
## 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: ...
|
|
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];
|
|
|
|
c...
|
|
export class SceneExporter extends EventEmitter<SceneExporterEvents> {
|
|
renderer: CanvasRenderer
|
|
format: ExportFormat
|
|
quality: ExportQuality
|
|
shouldIncludeAudio: boolean
|
|
audioBuffer: AudioBuffer
|
|
isCancelled
|
|
constructor({
|
|
|
|
width,
|
|
|
|
height,
|
|
|
|
fps,
|
|
|
|
format,
|
|
|
|
quality,
|
|
|
|
shouldIncludeAudio,
|
|
|
|
audioBuffer,
|
|
|
|
}: ExportParams)
|
|
cancel(): void
|
|
async export({
|
|
|
|
rootNode,
|
|
|
|
}: {
|
|
|
|
rootNode: RootNode;
|
|
|
|
}): Promise<ArrayBuffer | null>
|
|
}
|
|
|
|
## apps/web/src/services/storage
|
|
|
|
indexeddb-adapter.ts
|
|
export class IndexedDBAdapter implements StorageAdapter<T> {
|
|
dbName: string
|
|
storeName: string
|
|
version: number
|
|
constructor(dbName: string, storeName: string, version = 1)
|
|
async get(key: string): Promise<T | null>
|
|
async set(key: string, value: T): Promise<void>
|
|
async remove(key: string): Promise<void>
|
|
async list(): Promise<string[]>
|
|
async getAll(): Promise<T[]>
|
|
async clear(): Promise<void>
|
|
}
|
|
|
|
opfs-adapter.ts
|
|
export class OPFSAdapter implements StorageAdapter<File> {
|
|
directoryName: string
|
|
constructor(directoryName = "media")
|
|
async get(key: string): Promise<File | null>
|
|
async set(key: string, file: File): Promise<void>
|
|
async remove(key: string): Promise<void>
|
|
async list(): Promise<string[]>
|
|
async clear(): Promise<void>
|
|
static isSupported(): boolean
|
|
}
|
|
|
|
service.ts
|
|
export const storageService
|
|
|
|
types.ts
|
|
export interface StorageAdapter<T> {
|
|
get(key: string): Promise<T | null>
|
|
set(key: string, value: T): Promise<void>
|
|
remove(key: string): Promise<void>
|
|
list(): Promise<string[]>
|
|
clear(): Promise<void>
|
|
}
|
|
export interface MediaAssetData {
|
|
id: string
|
|
name: string
|
|
type: MediaType
|
|
size: number
|
|
lastModified: number
|
|
width?: number
|
|
height?: number
|
|
duration?: number
|
|
fps?: number
|
|
ephemeral?: boolean
|
|
thumbnailUrl?: string
|
|
sourceStickerIconName?: string
|
|
}
|
|
export type SerializedScene = Omit<TScene, "createdAt" | "updatedAt"> & {
|
|
|
|
createdAt: string;
|
|
|
|
updatedAt: string;
|
|
|
|
}
|
|
export type SerializedProjectMetadata = Omit<
|
|
|
|
TProjectMetadata,
|
|
|
|
"createdAt" | "updatedAt"
|
|
|
|
> & {
|
|
|
|
createdAt: string;
|
|
|
|
updatedAt: st...
|
|
export type SerializedProject = Omit<TProject, "metadata" | "scenes"> & {
|
|
|
|
metadata: SerializedProjectMetadata;
|
|
|
|
scenes: Serial...
|
|
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: stri...
|
|
export type WorkerResponse = | { type: "init-progress"; progress: number }
|
|
|
|
| { type: "init-complete" }
|
|
|
|
| { type: "init-err...
|
|
|
|
## apps/web/src/services/video-cache
|
|
|
|
service.ts
|
|
export class VideoCache {
|
|
sinks
|
|
initPromises
|
|
async getFrameAt({
|
|
|
|
mediaId,
|
|
|
|
file,
|
|
|
|
time,
|
|
|
|
}: {
|
|
|
|
mediaId: string;
|
|
|
|
file: File;
|
|
|
|
time: number;
|
|
|
|
}): Promise<WrappedCanvas | null>
|
|
clearVideo({ mediaId }: { mediaId: string }): void
|
|
clearAll(): void
|
|
getStats()
|
|
}
|
|
export const videoCache
|
|
|
|
## apps/web/src/stores
|
|
|
|
assets-panel-store.tsx
|
|
export const TAB_KEYS
|
|
export type Tab = (typeof TAB_KEYS)[number]
|
|
export const tabs
|
|
export const useAssetsPanelStore
|
|
|
|
editor-store.ts
|
|
export const useEditorStore
|
|
|
|
keybindings-store.ts
|
|
export const defaultKeybindings: KeybindingConfig
|
|
export interface KeybindingConflict {
|
|
key: ShortcutKey
|
|
existingAction: TActionWithOptionalArgs
|
|
newAction: TActionWithOptionalArgs
|
|
}
|
|
export const useKeybindingsStore
|
|
|
|
panel-store.ts
|
|
export interface PanelSizes {
|
|
tools: number
|
|
preview: number
|
|
properties: number
|
|
mainContent: number
|
|
timeline: number
|
|
}
|
|
export type PanelId = keyof PanelSizes
|
|
export const usePanelStore
|
|
|
|
sounds-store.ts
|
|
export const useSoundsStore
|
|
|
|
stickers-store.ts
|
|
export const useStickersStore
|
|
|
|
text-properties-store.ts
|
|
export type TextPropertiesTab = "text" | "transform"
|
|
export interface TextPropertiesTabMeta {
|
|
value: TextPropertiesTab
|
|
label: string
|
|
}
|
|
export const TEXT_PROPERTIES_TABS: ReadonlyArray<TextPropertiesTabMeta>
|
|
export function isTextPropertiesTab(value: string)
|
|
export const useTextPropertiesStore
|
|
|
|
timeline-store.ts
|
|
export const useTimelineStore
|
|
|
|
## apps/web/src/types
|
|
|
|
assets.ts
|
|
export type MediaType = "image" | "video" | "audio"
|
|
export interface MediaAsset extends Omit<MediaAssetData, "size" | "lastModified"> {
|
|
file: File
|
|
url?: string
|
|
}
|
|
|
|
blog.ts
|
|
export type Post = {
|
|
|
|
id: string;
|
|
|
|
slug: string;
|
|
|
|
title: string;
|
|
|
|
content: string;
|
|
|
|
description: string;
|
|
|
|
cove...
|
|
export type Pagination = {
|
|
|
|
limit: number;
|
|
|
|
currpage: number;
|
|
|
|
nextPage: number | null;
|
|
|
|
prevPage: number | null;
|
|
|
|
to...
|
|
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"
|
|
iconName: 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
|
|
}
|
|
|
|
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"
|
|
|
|
|...
|
|
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}`
|
|
|
|
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 = (typeof STICKER_CATEGORIES)[number]
|
|
|
|
time.ts
|
|
export type TTimeCode = "MM:SS" | "HH:MM:SS" | "HH:MM:SS:CS" | "HH:MM:SS:FF"
|
|
|
|
timeline.ts
|
|
export interface TScene {
|
|
id: string
|
|
name: string
|
|
isMain: boolean
|
|
tracks: TimelineTrack[]
|
|
bookmarks: number[]
|
|
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
|
|
}
|
|
export interface ImageElement extends BaseTimelineElement {
|
|
type: "image"
|
|
mediaId: string
|
|
hidden?: boolean
|
|
transform: Transform
|
|
opacity: number
|
|
}
|
|
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"
|
|
hidden?: boolean
|
|
transform: Transform
|
|
opacity: number
|
|
}
|
|
export interface StickerElement extends BaseTimelineElement {
|
|
type: "sticker"
|
|
iconName: string
|
|
hidden?: boolean
|
|
transform: Transform
|
|
opacity: number
|
|
color?: string
|
|
}
|
|
export type TimelineElement = | AudioElement
|
|
|
|
| VideoElement
|
|
|
|
| ImageElement
|
|
|
|
| TextElement
|
|
|
|
| StickerElement
|
|
export type ElementType = TimelineElement["type"]
|
|
export type CreateUploadAudioElement = Omit<UploadAudioElement, "id">
|
|
export type CreateLibraryAudioElement = Omit<LibraryAudioElement, "id">
|
|
export type CreateAudioElement = | CreateUploadAudioElement
|
|
|
|
| CreateLibraryAudioElement
|
|
export type CreateVideoElement = Omit<VideoElement, "id">
|
|
export type CreateImageElement = Omit<ImageElement, "id">
|
|
export type CreateTextElement = Omit<TextElement, "id">
|
|
export type CreateStickerElement = Omit<StickerElement, "id">
|
|
export type CreateTimelineElement = | CreateAudioElement
|
|
|
|
| CreateVideoElement
|
|
|
|
| CreateImageElement
|
|
|
|
| CreateTextElement
|
|
|
|
| Crea...
|
|
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
|
|
|
|
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
|
|
|
|
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;
|
|
|
|
})
|
|
|
|
```
|
|
|
|
---
|
|
|
|
*Generated and maintained by [Twiggy](https://github.com/twiggy-tools/Twiggy)*
|