OpenCut/.cursor/rules/codebase-index.mdc

2516 lines
52 KiB
Plaintext

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