From f2eed05d36846cd771458b20e77840e907084bc5 Mon Sep 17 00:00:00 2001 From: Maze Winther Date: Tue, 24 Mar 2026 14:18:39 +0100 Subject: [PATCH 001/193] fix blog build when marble cms isn't available --- apps/web/Dockerfile | 6 ++- apps/web/src/app/blog/page.tsx | 2 +- apps/web/src/lib/blog/query.ts | 70 ++++++++++++++++++++++++++++++---- docker-compose.yml | 2 + 4 files changed, 70 insertions(+), 10 deletions(-) diff --git a/apps/web/Dockerfile b/apps/web/Dockerfile index 9f2dfa2c4..f8e13a69d 100644 --- a/apps/web/Dockerfile +++ b/apps/web/Dockerfile @@ -6,6 +6,8 @@ WORKDIR /app ARG FREESOUND_CLIENT_ID ARG FREESOUND_API_KEY +ARG NEXT_PUBLIC_MARBLE_API_URL=https://api.marblecms.com +ARG MARBLE_WORKSPACE_KEY=build-placeholder COPY package.json package.json COPY bun.lock bun.lock @@ -30,8 +32,8 @@ ENV BETTER_AUTH_SECRET="build-time-secret" ENV UPSTASH_REDIS_REST_URL="http://localhost:8079" ENV UPSTASH_REDIS_REST_TOKEN="example_token" ENV NEXT_PUBLIC_SITE_URL="http://localhost:3000" -ENV NEXT_PUBLIC_MARBLE_API_URL="https://api.marblecms.com" -ENV MARBLE_WORKSPACE_KEY="build-placeholder" +ENV NEXT_PUBLIC_MARBLE_API_URL=$NEXT_PUBLIC_MARBLE_API_URL +ENV MARBLE_WORKSPACE_KEY=$MARBLE_WORKSPACE_KEY ENV CLOUDFLARE_ACCOUNT_ID="build-placeholder" ENV R2_ACCESS_KEY_ID="build-placeholder" ENV R2_SECRET_ACCESS_KEY="build-placeholder" diff --git a/apps/web/src/app/blog/page.tsx b/apps/web/src/app/blog/page.tsx index 7a2b5f974..257a8f231 100644 --- a/apps/web/src/app/blog/page.tsx +++ b/apps/web/src/app/blog/page.tsx @@ -18,7 +18,7 @@ export const metadata: Metadata = { }; export default async function BlogPage() { - const data = await getPosts(); + const data = await getPosts().catch(() => null); if (!data || !data.posts) return
No posts yet
; return ( diff --git a/apps/web/src/lib/blog/query.ts b/apps/web/src/lib/blog/query.ts index e6d68bb60..f814eeaff 100644 --- a/apps/web/src/lib/blog/query.ts +++ b/apps/web/src/lib/blog/query.ts @@ -1,6 +1,7 @@ import type { MarbleAuthorList, MarbleCategoryList, + Pagination, MarblePost, MarblePostList, MarbleTagList, @@ -16,43 +17,98 @@ const url = process.env.NEXT_PUBLIC_MARBLE_API_URL ?? "https://api.marblecms.com"; const key = process.env.MARBLE_WORKSPACE_KEY ?? "cmd4iw9mm0006l804kwqv0k46"; +const EMPTY_PAGINATION: Pagination = { + limit: 0, + currpage: 1, + nextPage: null, + prevPage: null, + totalItems: 0, + totalPages: 0, +}; + +const EMPTY_POSTS: MarblePostList = { + posts: [], + pagination: EMPTY_PAGINATION, +}; + +const EMPTY_TAGS: MarbleTagList = { + tags: [], + pagination: EMPTY_PAGINATION, +}; + +const EMPTY_CATEGORIES: MarbleCategoryList = { + categories: [], + pagination: EMPTY_PAGINATION, +}; + +const EMPTY_AUTHORS: MarbleAuthorList = { + authors: [], + pagination: EMPTY_PAGINATION, +}; + +function isMarbleConfigured() { + return !["", "placeholder", "build-placeholder", "your_workspace_key_here"].includes(key); +} + async function fetchFromMarble({ endpoint, + fallback, }: { endpoint: string; + fallback: T; }): Promise { + if (!isMarbleConfigured()) { + return fallback; + } + try { const response = await fetch(`${url}/${key}/${endpoint}`); if (!response.ok) { - throw new Error( + console.warn( `Failed to fetch ${endpoint}: ${response.status} ${response.statusText}`, ); + return fallback; } return (await response.json()) as T; } catch (error) { console.error(`Error fetching ${endpoint}:`, error); - throw error; + return fallback; } } export async function getPosts() { - return fetchFromMarble({ endpoint: "posts" }); + return fetchFromMarble({ + endpoint: "posts", + fallback: EMPTY_POSTS, + }); } export async function getTags() { - return fetchFromMarble({ endpoint: "tags" }); + return fetchFromMarble({ + endpoint: "tags", + fallback: EMPTY_TAGS, + }); } export async function getSinglePost({ slug }: { slug: string }) { - return fetchFromMarble({ endpoint: `posts/${slug}` }); + return fetchFromMarble({ + endpoint: `posts/${slug}`, + fallback: null, + }); } export async function getCategories() { - return fetchFromMarble({ endpoint: "categories" }); + return fetchFromMarble({ + endpoint: "categories", + fallback: EMPTY_CATEGORIES, + }); } export async function getAuthors() { - return fetchFromMarble({ endpoint: "authors" }); + return fetchFromMarble({ + endpoint: "authors", + fallback: EMPTY_AUTHORS, + }); } export async function processHtmlContent({ diff --git a/docker-compose.yml b/docker-compose.yml index ae75391ee..a20c2654c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -54,6 +54,8 @@ services: args: - FREESOUND_CLIENT_ID=${FREESOUND_CLIENT_ID} - FREESOUND_API_KEY=${FREESOUND_API_KEY} + - NEXT_PUBLIC_MARBLE_API_URL=${NEXT_PUBLIC_MARBLE_API_URL:-https://api.marblecms.com} + - MARBLE_WORKSPACE_KEY=${MARBLE_WORKSPACE_KEY:-build-placeholder} restart: unless-stopped ports: - "3100:3000" From 63496d05a2f78b061f6d848fd00ece223acd7514 Mon Sep 17 00:00:00 2001 From: kcfancher Date: Sat, 28 Mar 2026 14:06:40 -0400 Subject: [PATCH 002/193] Fix transcription sample-rate handling (#740) Fix for #703. Adds an optional sampleRate parameter to the decodeAudioToFloat32() function. The caption transcriber passes in a value of 16000 to prepare audio in the format Whisper expects. --- .../components/editor/panels/assets/views/captions.tsx | 10 ++++++++-- apps/web/src/constants/transcription-constants.ts | 2 ++ apps/web/src/lib/media/audio.ts | 4 +++- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/apps/web/src/components/editor/panels/assets/views/captions.tsx b/apps/web/src/components/editor/panels/assets/views/captions.tsx index 7a3b16bf3..a73fd693b 100644 --- a/apps/web/src/components/editor/panels/assets/views/captions.tsx +++ b/apps/web/src/components/editor/panels/assets/views/captions.tsx @@ -11,7 +11,10 @@ import { useState, useRef } from "react"; import { extractTimelineAudio } from "@/lib/media/mediabunny"; import { useEditor } from "@/hooks/use-editor"; import { DEFAULT_TEXT_ELEMENT } from "@/constants/text-constants"; -import { TRANSCRIPTION_LANGUAGES } from "@/constants/transcription-constants"; +import { + DEFAULT_TRANSCRIPTION_SAMPLE_RATE, + TRANSCRIPTION_LANGUAGES, +} from "@/constants/transcription-constants"; import type { TranscriptionLanguage, TranscriptionProgress, @@ -52,7 +55,10 @@ export function Captions() { }); setProcessingStep("Preparing audio..."); - const { samples } = await decodeAudioToFloat32({ audioBlob }); + const { samples } = await decodeAudioToFloat32({ + audioBlob, + sampleRate: DEFAULT_TRANSCRIPTION_SAMPLE_RATE, + }); const result = await transcriptionService.transcribe({ audioData: samples, diff --git a/apps/web/src/constants/transcription-constants.ts b/apps/web/src/constants/transcription-constants.ts index 3fa914f25..ed19147c1 100644 --- a/apps/web/src/constants/transcription-constants.ts +++ b/apps/web/src/constants/transcription-constants.ts @@ -51,6 +51,8 @@ export const TRANSCRIPTION_MODELS: TranscriptionModel[] = [ export const DEFAULT_TRANSCRIPTION_MODEL: TranscriptionModelId = "whisper-small"; +export const DEFAULT_TRANSCRIPTION_SAMPLE_RATE = 16000; + export const DEFAULT_CHUNK_LENGTH_SECONDS = 30; export const DEFAULT_STRIDE_SECONDS = 5; diff --git a/apps/web/src/lib/media/audio.ts b/apps/web/src/lib/media/audio.ts index 6f7893017..e96f158b7 100644 --- a/apps/web/src/lib/media/audio.ts +++ b/apps/web/src/lib/media/audio.ts @@ -34,10 +34,12 @@ export interface DecodedAudio { export async function decodeAudioToFloat32({ audioBlob, + sampleRate, }: { audioBlob: Blob; + sampleRate?: number; }): Promise { - const audioContext = createAudioContext(); + const audioContext = createAudioContext({ sampleRate }); const arrayBuffer = await audioBlob.arrayBuffer(); const audioBuffer = await audioContext.decodeAudioData(arrayBuffer); From 7e2a913e1377f1f576832728374517a7265a706e Mon Sep 17 00:00:00 2001 From: Aspen Date: Sat, 28 Mar 2026 14:07:36 -0400 Subject: [PATCH 003/193] Update OpenCut logo in README (#741) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cacc4555c..9e9a8d666 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@
- OpenCut Logo + OpenCut Logo

OpenCut

From 6018efc5acb448d8c8ce71250e562e9e78961fee Mon Sep 17 00:00:00 2001 From: Maze Winther Date: Wed, 4 Mar 2026 17:26:54 +0100 Subject: [PATCH 004/193] changelog: new version with already-made changes --- apps/web/content/changelog/0.3.0.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 apps/web/content/changelog/0.3.0.md diff --git a/apps/web/content/changelog/0.3.0.md b/apps/web/content/changelog/0.3.0.md new file mode 100644 index 000000000..56e3b5b9e --- /dev/null +++ b/apps/web/content/changelog/0.3.0.md @@ -0,0 +1,13 @@ +--- +version: "0.3.0" +date: "2026-03-04" +title: "Brand & polish" +description: "This release adds a brand page with downloadable assets, alongside a few fixes and improvements." +changes: + - type: new + text: "Added a brand page with downloadable brand assets. Assets are also accessible directly from the header logo context menu." + - type: fixed + text: "Sponsor logos now correctly invert in dark mode." + - type: improved + text: "Added a changelog link to the footer." +--- From b09635064ab949c2b254767dde00e9dd13762d49 Mon Sep 17 00:00:00 2001 From: Maze Winther Date: Wed, 4 Mar 2026 18:27:02 +0100 Subject: [PATCH 005/193] fix: assets having unreasonable widths and heights --- .../src/components/editor/panels/assets/draggable-item.tsx | 2 +- apps/web/src/components/editor/panels/assets/views/assets.tsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/web/src/components/editor/panels/assets/draggable-item.tsx b/apps/web/src/components/editor/panels/assets/draggable-item.tsx index be4176ce7..fae74e841 100644 --- a/apps/web/src/components/editor/panels/assets/draggable-item.tsx +++ b/apps/web/src/components/editor/panels/assets/draggable-item.tsx @@ -98,7 +98,7 @@ export function DraggableItem({ {variant === "card" ? (
{items.map((item) => ( From 5e2b829f8a682a619cd0de6681ddd9f542235ebf Mon Sep 17 00:00:00 2001 From: Maze Winther Date: Wed, 4 Mar 2026 21:52:45 +0100 Subject: [PATCH 006/193] changelog: add already-completed item --- apps/web/content/changelog/0.3.0.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/web/content/changelog/0.3.0.md b/apps/web/content/changelog/0.3.0.md index 56e3b5b9e..09c7bfbd5 100644 --- a/apps/web/content/changelog/0.3.0.md +++ b/apps/web/content/changelog/0.3.0.md @@ -10,4 +10,6 @@ changes: text: "Sponsor logos now correctly invert in dark mode." - type: improved text: "Added a changelog link to the footer." + - type: fixed + text: "Media asset cards in the grid view were larger than their thumbnails, leaving empty space around each item. Cards now size to their content." --- From 2c0fd4f86b011bbc8c0d86c61f96ade3ea249508 Mon Sep 17 00:00:00 2001 From: Maze Winther Date: Wed, 25 Mar 2026 16:16:42 +0100 Subject: [PATCH 007/193] untrack .cursor/ --- .cursor/commands/review.md | 172 -- .cursor/rules/codebase-index.mdc | 2515 ---------------------- .cursor/rules/comments.mdc | 34 - .cursor/rules/handling-uncertainty.mdc | 20 - .cursor/rules/readability.mdc | 8 - .cursor/rules/separation-of-concerns.mdc | 51 - .cursor/rules/ultracite.mdc | 101 - .cursor/rules/writing-scannable-code.mdc | 52 - .cursor/settings.json | 7 - .cursor/skills/design/SKILL.md | 45 - 10 files changed, 3005 deletions(-) delete mode 100644 .cursor/commands/review.md delete mode 100644 .cursor/rules/codebase-index.mdc delete mode 100644 .cursor/rules/comments.mdc delete mode 100644 .cursor/rules/handling-uncertainty.mdc delete mode 100644 .cursor/rules/readability.mdc delete mode 100644 .cursor/rules/separation-of-concerns.mdc delete mode 100644 .cursor/rules/ultracite.mdc delete mode 100644 .cursor/rules/writing-scannable-code.mdc delete mode 100644 .cursor/settings.json delete mode 100644 .cursor/skills/design/SKILL.md diff --git a/.cursor/commands/review.md b/.cursor/commands/review.md deleted file mode 100644 index 4cc5de367..000000000 --- a/.cursor/commands/review.md +++ /dev/null @@ -1,172 +0,0 @@ -# Code Review Checklist - -Review every point below carefully to ensure files follow consistent code style and best practices. - ---- - -## Function Signatures & Parameters - -- [ ] Every function accepts a single object parameter with destructuring in the signature (for readability and future extensibility) - - Exception: tiny one-liner callbacks (e.g. `array.find(x => ...)`, `map`, `filter`, `sort`) do not need destructuring if it hurts readability - - ```tsx - // ❌ wrong - function formatTime(seconds: number, fps: number) { ... } - - // ✅ correct - function formatTime({ seconds, fps }: { seconds: number; fps: number }) { ... } - ``` - -## TypeScript & Type Safety - -- [ ] No `any` references -- [ ] General interfaces are in the `types` folder, not scattered in components - - Example: `TimelineTrack` interface belongs in `src/types/timeline.ts`, not `src/components/timeline/index.tsx` - -## JSX & Components - -- [ ] JSX is clean — no comments explaining what each part does -- [ ] Complex/reusable JSX is extracted into sub-components (placed below the main component) -- [ ] Components shared across multiple files are in separate files -- [ ] File order: constants specific to file (top) -> utils specific to file -> main component → sub-components (bottom) -- [ ] Components render UI only — domain logic lives in hooks, utilities, or managers - - Simple interaction logic (gestures, modifier keys) can stay if not complex - -## Code Organization & File Structure - -- [ ] Each file has one single purpose/responsibility - - Example: `timeline/index.tsx` should not define `validateElementTrackCompatibility` — that belongs in a lib file - - Example: `lib/timeline-utils.ts` should not declare `TRACK_COLORS` — that belongs in `constants/` -- [ ] File name accurately reflects what the file contains — a misleading name is a bug waiting to happen -- [ ] Business logic lives in either `src/lib`, `src/core` or `src/services` folder - -## Comments - -- [ ] No AI comments — only human comments that explain _why_, not _what_ - - Bad: changelog-style comments, explaining readable code, using more words than necessary -- [ ] All comments are lowercase - -## Naming Conventions - -- [ ] Readability over brevity — use `element` not `el`, `event` not `e` -- [ ] Booleans are named `isSomething`, `hasSomething`, or `shouldSomething` — not `something` -- [ ] No title case for multi-word text/UI — use `Hello world` not `Hello World` - -## Tailwind & Styling - -- [ ] Always use `cn()` for `className` — never string interpolation with `${}` or ternaries inline - ```tsx - // ❌ wrong - className={`base-class ${isActive && "active"} ${someHelper()}`} - - // ✅ correct - className={cn("base-class", isActive && "active", someHelper())} - ``` -- [ ] Use `gap-*` instead of `mb-*` or `mt-*` for consistent spacing -- [ ] Use `size-*` instead of `h-* w-*` when width and height are the same -- [ ] When using `size-*` on icons inside ` - ``` - -## State Management (Zustand) - -- [ ] React components never use `someStore.getState()` — use the `useSomeStore` hook instead -- [ ] High-frequency stores (timeline, playback, selections) use selectors — `useStore((s) => s.value)` not `const { value } = useStore()` -- [ ] Store/manager methods are not passed as props — sub-components access them directly - - ```tsx - // ❌ wrong - function Parent() { - const { selectedElements } = useTimelineStore(); - return ; - } - - // ✅ correct - function Parent() { - return ; - } - function Child() { - const { selectedElements } = useTimelineStore(); - } - ``` - -- [ ] Components and hooks should use the `useEditor` hook. Only use `EditorCore.getInstance()` if you are outside of a react component/hook. Eg: in a utility function, event handler. - -## Code Quality - -- [ ] Code is scannable — use variables and helper functions to make intent clear at a glance -- [ ] Complex logic is extracted into well-named variables or helpers -- [ ] No magic numbers or magic values — extract inline literals into named constants - - Applies to colors, durations, thresholds, sizes, config values, etc. - - If it's domain-specific to one file, a `const` at the top of that file is fine - - If it's generic enough, it belongs in `constants/` - -- [ ] No redundant single/plural function variants — if a function can operate on multiple items, it should accept an array and handle both cases. Don't create `doThing()` + `doThings()`. - - ```tsx - // ❌ wrong — redundant variants - function updateElement({ element }: { element: Element }) { ... } - function updateElements({ elements }: { elements: Element[] }) { ... } - - // ✅ correct — one function, accepts array - function updateElements({ elements }: { elements: Element[] }) { ... } - ``` - ---- - -## Function Keywords - -| Context | Keyword | -| --------------------------------- | ------------------------- | -| Next.js page components | `export default function` | -| Main react component | `export function` | -| Sub-components | `function` | -| Utility functions | `export function` | -| Functions inside react components | `const` | - ---- - -## Review Methodology - -Do NOT review by reading the file top-to-bottom and noting what jumps out. Instead: - -1. Go through each checklist section **one at a time** -2. For each section, scan the **entire file** for violations of that specific rule -3. Only move to the next section after you've exhausted the current one -4. After all sections are checked, do a final pass: re-read every checklist item and confirm you didn't skip it - -Before outputting the review, list each checklist section and confirm you checked it: -`Signatures ✓ | TypeScript ✓ | JSX ✓ | Organization ✓ | File Names ✓ | Comments ✓ | Naming ✓ | Tailwind ✓ | State ✓ | Quality ✓ | Keywords ✓` - ---- - -## IMPORTANT: Review Rules - -- **ONLY** flag issues that are explicitly covered by a checklist item above. -- Do **NOT** invent your own rules, suggestions, or "nice to haves" as primary issues. -- The review output must be a list of issues, each one mapping to a specific checklist item. -- If something looks off but isn't covered by the checklist, you can mention it as a brief side note at the end — but keep it clearly separate from the actual review. Always default to fixing the issues covered by the checklist above, unless the user says otherwise. - -> You WILL miss things if you try to review the whole file in one pass. Iterate rule by rule. - ---- - -## Think Bigger - -After the checklist review, step back and ask the hard questions. The biggest architectural problems get solved by the biggest questions. - -- Does this abstraction actually need to exist? Could it be deleted entirely? -- Is this the right layer for this logic? (wrong layer = future pain) -- Is this solving a real problem, or a problem we invented? -- Would a simpler data model make this whole file unnecessary? -- Are we adding complexity to work around a bad decision made earlier? -- Could this field be derived from other existing fields? Redundant data in a model is a source of bugs. - -Don't be shy about flagging these. A "why does this exist?" question is often worth more than 10 style fixes. diff --git a/.cursor/rules/codebase-index.mdc b/.cursor/rules/codebase-index.mdc deleted file mode 100644 index 547d05661..000000000 --- a/.cursor/rules/codebase-index.mdc +++ /dev/null @@ -1,2515 +0,0 @@ ---- -alwaysApply: false ---- - -# video-editor-oss Codebase Index - -**This file provides an index of exported functions, types, interfaces, classes, and constants in your codebase.** - -Updated in real-time by Twiggy. Use this to discover existing utilities and avoid duplicating code. - -## How to Use - -When implementing new features: - -1. Check if similar functionality already exists -2. Reuse existing types and utilities -3. Understand the API surface of your codebase - -```typescript -## apps/web/src/constants - -editor-constants.ts - export const PANEL_CONFIG - -export-constants.ts - export const DEFAULT_EXPORT_OPTIONS - export const EXPORT_MIME_TYPES - -font-constants.ts - export const DEFAULT_FONT - export const SYSTEM_FONTS - -language-constants.ts - export const LANGUAGES - -project-constants.ts - export const DEFAULT_CANVAS_PRESETS: TCanvasSize[] - export const FPS_PRESETS - export const BLUR_INTENSITY_PRESETS: { label: string; value: number }[] - export const DEFAULT_CANVAS_SIZE: TCanvasSize - export const DEFAULT_FPS - export const DEFAULT_BLUR_INTENSITY - export const DEFAULT_COLOR - -site-constants.ts - export const SITE_URL - export const SITE_INFO - export type ExternalTool = { - name: string; - description: string; - url: string; - icon: React.ElementType; - } - export const EXTERNAL_TOOLS: ExternalTool[] - export const DEFAULT_LOGO_URL - export const SOCIAL_LINKS - export type Sponsor = { - name: string; - url: string; - logo: string; - description: string; - } - export const SPONSORS: Sponsor[] - -sticker-constants.ts - export const STICKER_CATEGORIES - -text-constants.ts - export const MIN_FONT_SIZE - export const MAX_FONT_SIZE - export const FONT_SIZE_SCALE_REFERENCE - export const DEFAULT_LETTER_SPACING - export const DEFAULT_LINE_HEIGHT - export const DEFAULT_TEXT_ELEMENT: Omit - -timeline-constants.tsx - export const DEFAULT_TRANSFORM: Transform - export const DEFAULT_OPACITY - export const DEFAULT_BLEND_MODE: BlendMode - export const DEFAULT_BOOKMARK_COLOR - export const TRACK_COLORS: Record - export const TRACK_HEIGHTS: Record - export const TRACK_GAP - export const DRAG_THRESHOLD_PX - export const TIMELINE_CONSTANTS - export const DEFAULT_TIMELINE_VIEW_STATE: TTimelineViewState - export const TRACK_ICONS: Record - -transcription-constants.ts - export const TRANSCRIPTION_LANGUAGES - export const TRANSCRIPTION_MODELS: TranscriptionModel[] - export const DEFAULT_TRANSCRIPTION_MODEL: TranscriptionModelId - export const DEFAULT_CHUNK_LENGTH_SECONDS - export const DEFAULT_STRIDE_SECONDS - export const DEFAULT_WORDS_PER_CAPTION - export const MIN_CAPTION_DURATION_SECONDS - -## apps/web/src/core - -index.ts - export class EditorCore { - instance: EditorCore | null - command: CommandManager - playback: PlaybackManager - timeline: TimelineManager - scenes: ScenesManager - project: ProjectManager - media: MediaManager - renderer: RendererManager - save: SaveManager - audio: AudioManager - selection: SelectionManager - static getInstance(): EditorCore - static reset(): void - } - -## apps/web/src/hooks - -use-container-size.ts - export function useContainerSize({ - containerRef, - }: { - containerRef: React.RefObject; - }) - -use-editor.ts - export function useEditor(): EditorCore - -use-file-upload.ts - export function useFileUpload({ - accept, - multiple, - onFilesSelected, - }: UseFileUploadOptions = {}) - -use-focus-lock.ts - export function useFocusLock({ - isActive, - onDismiss, - cursor = "default", - allowSelector, - }: { - isActive: boolean; - onDismiss: () => void; - cursor?: FocusLockCursor; - allowSelector?: string; - }) - -use-fullscreen.ts - export function useFullscreen({ - containerRef, - }: { - containerRef: React.RefObject; - }) - -use-infinite-scroll.ts - export function useInfiniteScroll({ - onLoadMore, - hasMore, - isLoading, - threshold = 200, - enabled = true, - }: UseInfiniteScrollOptions) - -use-keybindings.ts - export function useKeybindingsListener() - export function useKeybindingDisabler() - -use-keyboard-shortcuts-help.ts - export interface KeyboardShortcut { - id: string - keys: string[] - description: string - category: string - action: TAction - icon?: React.ReactNode - } - export function useKeyboardShortcutsHelp() - -use-mobile.ts - export function useIsMobile() - -use-paste-media.ts - export function usePasteMedia() - -use-preview-interaction.ts - export function usePreviewInteraction({ - canvasRef, - }: { - canvasRef: React.RefObject; - }) - -use-raf-loop.ts - export function useRafLoop(callback: ({ time }: { time: number }) => void) - -use-reveal-item.ts - export function useRevealItem( - highlightId: string | null, - onClearHighlight: () => void, - highlightDuration = 1000, - ) - -use-shift-key.ts - export function useShiftKey(): RefObject - -use-sound-search.ts - export function useSoundSearch({ - query, - commercialOnly, - }: { - query: string; - commercialOnly: boolean; - }) - -use-transform-handles.ts - export function useTransformHandles({ - - canvasRef, - - }: { - - canvasRef: React.RefObject; - - }) - -## apps/web/src/hooks/actions - -use-action-handler.ts - export function useActionHandler( - action: A, - handler: TActionFunc, - isActive: TActionHandlerOptions, - ) - -use-editor-actions.ts - export function useEditorActions() - -## apps/web/src/hooks/storage - -use-local-storage.ts - export function useLocalStorage({ - key, - defaultValue, - }: { - key: string; - defaultValue: T; - }): [ - T, - ({ value }: { value: T | ((previousValue: T) => T) }) => void, - boolean, - ] - -## apps/web/src/hooks/timeline - -use-bookmark-drag.ts - export interface BookmarkDragState { - isDragging: boolean - bookmarkTime: number | null - currentTime: number - } - export function useBookmarkDrag({ - - zoomLevel, - - scrollRef, - - snappingEnabled, - - onSnapPointChange, - - }: UseBookmarkDragProps) - -use-edge-auto-scroll.ts - export function useEdgeAutoScroll({ - isActive, - getMouseClientX, - rulerScrollRef, - tracksScrollRef, - contentWidth, - edgeThreshold = 100, - maxScrollSpeed = 15, - }: UseEdgeAutoScrollParams): void - -use-scroll-position.ts - export function useScrollPosition({ - scrollRef, - }: { - scrollRef: React.RefObject; - }): UseScrollPositionReturn - -use-scroll-sync.ts - export function useScrollSync({ - tracksScrollRef, - rulerScrollRef, - trackLabelsScrollRef, - bookmarksScrollRef, - }: UseScrollSyncProps) - -use-selection-box.ts - export function useSelectionBox({ - containerRef, - onSelectionComplete, - isEnabled = true, - tracksScrollRef, - zoomLevel, - }: UseSelectionBoxProps) - -use-snap-indicator-position.ts - export function useSnapIndicatorPosition({ - snapPoint, - zoomLevel, - tracks, - timelineRef, - trackLabelsRef, - tracksScrollRef, - }: UseSnapIndicatorPositionParams): SnapIndicatorPosition - -use-timeline-drag-drop.ts - export function useTimelineDragDrop({ - containerRef, - headerRef, - zoomLevel, - }: UseTimelineDragDropProps) - -use-timeline-playhead.ts - export function useTimelinePlayhead({ - zoomLevel, - rulerRef, - rulerScrollRef, - tracksScrollRef, - playheadRef, - }: UseTimelinePlayheadProps) - -use-timeline-seek.ts - export function useTimelineSeek({ - playheadRef, - trackLabelsRef, - rulerScrollRef, - tracksScrollRef, - zoomLevel, - duration, - isSelecting, - clearSelectedElements, - seek, - }: UseTimelineSeekProps) - -use-timeline-snapping.ts - export interface SnapPoint { - time: number - type: "element-start" | "element-end" | "playhead" | "bookmark" - elementId?: string - trackId?: string - } - export interface SnapResult { - snappedTime: number - snapPoint: SnapPoint | null - snapDistance: number - } - export interface UseTimelineSnappingOptions { - snapThreshold?: number - enableElementSnapping?: boolean - enablePlayheadSnapping?: boolean - enableBookmarkSnapping?: boolean - } - export function useTimelineSnapping({ - snapThreshold = 10, - enableElementSnapping = true, - enablePlayheadSnapping = true, - enableBookmarkSnapping = true, - }: UseTimelineSnappingOptions = {}) - -use-timeline-zoom.ts - export function useTimelineZoom({ - containerRef, - minZoom = TIMELINE_CONSTANTS.ZOOM_MIN, - initialZoom, - initialScrollLeft, - initialPlayheadTime, - tracksScrollRef, - rulerScrollRef, - }: UseTimelineZoomProps): UseTimelineZoomReturn - -## apps/web/src/hooks/timeline/element - -use-element-interaction.ts - export function useElementInteraction({ - zoomLevel, - timelineRef, - tracksContainerRef, - tracksScrollRef, - headerRef, - snappingEnabled, - onSnapPointChange, - }: UseElementInteractionProps) - -use-element-resize.ts - export interface ResizeState { - elementId: string - side: "left" | "right" - startX: number - initialTrimStart: number - initialTrimEnd: number - initialStartTime: number - initialDuration: number - } - export function useTimelineElementResize({ - element, - track, - zoomLevel, - onSnapPointChange, - onResizeStateChange, - }: UseTimelineElementResizeProps) - -use-element-selection.ts - export function useElementSelection() - -## apps/web/src/lib - -drag-data.ts - export function setDragData({ - dataTransfer, - dragData, - }: { - dataTransfer: DataTransfer; - dragData: TimelineDragData; - }): void - export function getDragData({ - dataTransfer, - }: { - dataTransfer: DataTransfer; - }): TimelineDragData | null - export function hasDragData({ - dataTransfer, - }: { - dataTransfer: DataTransfer; - }): boolean - export function clearDragData(): void - -export.ts - export function getExportMimeType({ - format, - }: { - format: ExportFormat; - }): string - export function getExportFileExtension({ - format, - }: { - format: ExportFormat; - }): string - -iconify-api.ts - export const ICONIFY_HOSTS - export interface IconSet { - prefix: string - name: string - total: number - author?: { - name: string; - url?: string; - } - license?: { - title: string; - spdx?: string; - url?: string; - } - samples?: string[] - category?: string - palette?: boolean - } - export interface IconSearchResult { - icons: string[] - total: number - limit: number - start: number - collections: Record - } - export interface CollectionInfo { - prefix: string - total: number - title?: string - uncategorized?: string[] - categories?: Record - hidden?: string[] - aliases?: Record - } - export function getCollections( - category?: string, - ): Promise> - export function getCollection( - prefix: string, - ): Promise - export function searchIcons( - query: string, - limit: number = 64, - prefixes?: string[], - category?: string, - ): Promise - export function buildIconSvgUrl( - host: string, - iconName: string, - params?: { - color?: string; - width?: number; - height?: number; - flip?: "horizontal" | "vertical" | "horizontal,vertical"; - rotate?: number | string; - }, - ): string - export function getIconSvgUrl( - iconName: string, - params?: Parameters[2], - ): string - export function downloadSvgAsText( - iconName: string, - params?: Parameters[1], - ): Promise - export function svgToFile(svgText: string, fileName: string): File - export const POPULAR_COLLECTIONS - export function getCategoriesFromCollections( - collections: Record, - ): string[] - -rate-limit.ts - export const baseRateLimit - export function checkRateLimit({ request }: { request: Request }) - -scenes.ts - export function getMainScene({ scenes }: { scenes: TScene[] }): TScene | null - export function ensureMainScene({ scenes }: { scenes: TScene[] }): TScene[] - export function buildDefaultScene({ - name, - isMain, - }: { - name: string; - isMain: boolean; - }): TScene - export function canDeleteScene({ scene }: { scene: TScene }): { - canDelete: boolean; - reason?: string; - } - export function getFallbackSceneAfterDelete({ - scenes, - deletedSceneId, - currentSceneId, - }: { - scenes: TScene[]; - deletedSceneId: string; - currentSceneId: string | null; - }): TScene | null - export function findCurrentScene({ - scenes, - currentSceneId, - }: { - scenes: TScene[]; - currentSceneId: string; - }): TScene | null - export function getProjectDurationFromScenes({ - scenes, - }: { - scenes: TScene[]; - }): number - export function updateSceneInArray({ - scenes, - sceneId, - updates, - }: { - scenes: TScene[]; - sceneId: string; - updates: Partial; - }): TScene[] - -time.ts - export function roundToFrame({ - time, - fps, - }: { - time: number; - fps: number; - }): number - export function formatTimeCode({ - timeInSeconds, - format = "HH:MM:SS:CS", - fps, - }: { - timeInSeconds: number; - format?: TTimeCode; - fps?: number; - }): string - export function parseTimeCode({ - timeCode, - format = "HH:MM:SS:CS", - fps, - }: { - timeCode: string; - format?: TTimeCode; - fps: number; - }): number | null - export function guessTimeCodeFormat({ - timeCode, - }: { - timeCode: string; - }): TTimeCode | null - export function timeToFrame({ - time, - fps, - }: { - time: number; - fps: number; - }): number - export function frameToTime({ - frame, - fps, - }: { - frame: number; - fps: number; - }): number - export function snapTimeToFrame({ - time, - fps, - }: { - time: number; - fps: number; - }): number - export function getSnappedSeekTime({ - rawTime, - duration, - fps, - }: { - rawTime: number; - duration: number; - fps: number; - }): number - export function getLastFrameTime({ - duration, - fps, - }: { - duration: number; - fps: number; - }): number - -## apps/web/src/lib/actions - -definitions.ts - export type TActionCategory = | "playback" - | "navigation" - | "editing" - | "selection" - | "history" - | "timeline" - | "controls" - export interface TActionDefinition { - description: string - category: TActionCategory - defaultShortcuts?: ShortcutKey[] - args?: Record - } - export const ACTIONS - export type TAction = keyof typeof ACTIONS - export function getActionDefinition(action: TAction): TActionDefinition - export function getDefaultShortcuts(): Record - -registry.ts - export function bindAction( - action: A, - handler: TActionFunc, - ) - export function unbindAction( - action: A, - handler: TActionFunc, - ) - export const invokeAction = ( - action: A, - args?: TArgOfAction, - trigger?: TInvocationTrigger, - ) => ... - -types.ts - export type TActionArgsMap = { - "seek-forward": { seconds: number } | undefined; - "seek-backward": { seconds: number } | undef... - export type TActionWithArgs = keyof TActionArgsMap - export type TActionWithOptionalArgs = | TActionWithNoArgs - | TKeysWithValueUndefined - export type TActionWithNoArgs = Exclude - export type TArgOfAction = A extends TActionWithArgs - ? TActionArgsMap[A] - : undefined - export type TActionFunc = A extends TActionWithArgs - ? (arg: TArgOfAction, trigger?: TInvocationTrigger) => void - : (_?:... - export type TInvocationTrigger = "keypress" | "mouseclick" - export type TBoundActionList = { - [A in TAction]?: Array>; - } - export type TActionHandlerOptions = | MutableRefObject - | boolean - | undefined - -## apps/web/src/lib/auth - -server.ts - export const auth - export type Auth = typeof auth - -## apps/web/src/lib/blog - -query.ts - export function getPosts() - export function getTags() - export function getSinglePost({ slug }: { slug: string }) - export function getCategories() - export function getAuthors() - export function processHtmlContent({ - html, - }: { - html: string; - }): Promise - -## apps/web/src/lib/db - -index.ts - export const db - -schema.ts - export const users - export const sessions - export const accounts - export const verifications - -## apps/web/src/lib/fonts - -google-fonts.ts - export function getCachedFontAtlas(): FontAtlas | null - export function clearFontAtlasCache(): void - export function prefetchFontAtlas(): Promise - export function loadFullFont({ - family, - weights = [400, 700], - }: { - family: string; - weights?: number[]; - }): Promise - export function loadFonts({ - families, - }: { - families: string[]; - }): Promise - -## apps/web/src/lib/gradients - -canvas.ts - export function drawCssBackground({ - ctx, - width, - height, - css, - }: { - ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D; - width: number; - height: number; - css: string; - }): void - -parser.ts - export type GradientOrientation = LinearOrientation | Array - export type Color = | { type: "hex"; value: string } - | { type: "literal"; value: string } - | { type: "rgb"; value: A... - export type ColorStop = Color & { length?: Distance } - export type GradientAst = { - type: GradientType; - orientation: GradientOrientation | undefined; - colorStops: Array => ... - export const GradientParser - -## apps/web/src/lib/media - -audio.ts - export type CollectedAudioElement = Omit< - AudioElement, - "type" | "mediaId" | "volume" | "id" | "name" | "sourceType" | "sourceUrl" - ... - export function createAudioContext(): AudioContext - export interface DecodedAudio { - samples: Float32Array - sampleRate: number - } - export function decodeAudioToFloat32({ - audioBlob, - }: { - audioBlob: Blob; - }): Promise - export function collectAudioElements({ - tracks, - mediaAssets, - audioContext, - }: { - tracks: TimelineTrack[]; - mediaAssets: MediaAsset[]; - audioContext: AudioContext; - }): Promise - export interface AudioClipSource { - id: string - sourceKey: string - file: File - startTime: number - duration: number - trimStart: number - trimEnd: number - muted: boolean - } - export function collectAudioMixSources({ - tracks, - mediaAssets, - }: { - tracks: TimelineTrack[]; - mediaAssets: MediaAsset[]; - }): Promise - export function collectAudioClips({ - tracks, - mediaAssets, - }: { - tracks: TimelineTrack[]; - mediaAssets: MediaAsset[]; - }): Promise - export function createTimelineAudioBuffer({ - tracks, - mediaAssets, - duration, - sampleRate = 44100, - audioContext, - }: { - tracks: TimelineTrack[]; - mediaAssets: MediaAsset[]; - duration: number; - sampleRate?: number; - audioContext?: AudioContext; - }): Promise - -media-utils.ts - export const SUPPORTS_AUDIO: readonly MediaType[] - export function mediaSupportsAudio({ - media, - }: { - media: MediaAsset | null | undefined; - }): boolean - export const getMediaTypeFromFile = ({ - file, - }: { - file: File; - }): MediaType | null => ... - -mediabunny.ts - export function getVideoInfo({ - videoFile, - }: { - videoFile: File; - }): Promise<{ - duration: number; - width: number; - height: number; - fps: number; - }> - export const extractTimelineAudio = ({ - tracks, - mediaAssets, - totalDuration, - onProgress, - }: { - tracks: TimelineTrack[]; - mediaAssets: MediaAsset[]; - totalDuration: number; - onProgress?: (progress: number) => void; - }): Promise => ... - -processing.ts - export interface ProcessedMediaAsset extends Omit - export function generateThumbnail({ - videoFile, - timeInSeconds, - }: { - videoFile: File; - timeInSeconds: number; - }): Promise - export function generateImageThumbnail({ - imageFile, - }: { - imageFile: File; - }): Promise - export function processMediaAssets({ - files, - onProgress, - }: { - files: FileList | File[]; - onProgress?: ({ progress }: { progress: number }) => void; - }): Promise - -## apps/web/src/lib/preview - -element-bounds.ts - export interface ElementBounds { - cx: number - cy: number - width: number - height: number - rotation: number - } - export interface ElementWithBounds { - trackId: string - elementId: string - element: TimelineElement - bounds: ElementBounds - } - export function getElementBounds({ - element, - canvasSize, - mediaAsset, - }: { - element: TimelineElement; - canvasSize: { width: number; height: number }; - mediaAsset?: MediaAsset | null; - }): ElementBounds | null - export function getVisibleElementsWithBounds({ - tracks, - currentTime, - canvasSize, - mediaAssets, - }: { - tracks: TimelineTrack[]; - currentTime: number; - canvasSize: { width: number; height: number }; - mediaAssets: MediaAsset[]; - }): ElementWithBounds[] - -hit-test.ts - export function hitTest({ - - canvasX, - - canvasY, - - elementsWithBounds, - - }: { - - canvasX: number; - - canvasY: number; - - elementsWithBounds: ElementWithBounds[]; - - }): ElementWithBounds | null - -preview-coords.ts - export function screenToCanvas({ - - clientX, - - clientY, - - canvas, - - }: { - - clientX: number; - - clientY: number; - - canvas: HTMLCanvasElement; - - }): { x: number; y: number } - export function canvasToOverlay({ - - canvasX, - - canvasY, - - canvasRect, - - containerRect, - - canvasSize, - - }: { - - canvasX: number; - - canvasY: number; - - canvasRect: DOMRect; - - containerRect: DOMRect; - - canvasSize: { width: number; height: number }; - - }): { x: number; y: number } - export function positionToOverlay({ - - positionX, - - positionY, - - canvasRect, - - containerRect, - - canvasSize, - - }: { - - positionX: number; - - positionY: number; - - canvasRect: DOMRect; - - containerRect: DOMRect; - - canvasSize: { width: number; height: number }; - - }): { x: number; y: number } - export function getDisplayScale({ - - canvasRect, - - canvasSize, - - }: { - - canvasRect: DOMRect; - - canvasSize: { width: number; height: number }; - - }): { x: number; y: number } - -preview-snap.ts - export interface SnapLine { - type: "horizontal" | "vertical" - position: number - } - export const MIN_SCALE - export interface SnapResult { - snappedPosition: { x: number; y: number } - activeLines: SnapLine[] - } - export function snapPosition({ - - proposedPosition, - - canvasSize, - - elementSize, - - }: { - - proposedPosition: { x: number; y: number }; - - canvasSize: { width: number; height: number }; - - elementSize: { width: number; height: number }; - - }): SnapResult - export interface ScaleSnapResult { - snappedScale: number - activeLines: SnapLine[] - } - export function snapScale({ - - proposedScale, - - position, - - baseWidth, - - baseHeight, - - canvasSize, - - }: { - - proposedScale: number; - - position: { x: number; y: number }; - - baseWidth: number; - - baseHeight: number; - - canvasSize: { width: number; height: number }; - - }): ScaleSnapResult - export interface RotationSnapResult { - snappedRotation: number - isSnapped: boolean - } - export function snapRotation({ - - proposedRotation, - - }: { - - proposedRotation: number; - - }): RotationSnapResult - -## apps/web/src/lib/stickers - -index.ts - export function searchStickers({ - query, - category, - limit = DEFAULT_SEARCH_LIMIT, - }: { - query: string; - category: StickerCategory; - limit?: number; - }): Promise - export function browseStickers({ - category, - page = 1, - limit = DEFAULT_SEARCH_LIMIT, - }: { - category: StickerCategory; - page?: number; - limit?: number; - }): Promise - -registry.ts - export function registerProvider({ - provider, - }: { - provider: StickerProvider; - }): void - export function hasProvider({ providerId }: { providerId: string }): boolean - export function getProvider({ - providerId, - }: { - providerId: string; - }): StickerProvider - export function getAllProviders(): StickerProvider[] - -resolver.ts - export function resolveStickerId({ - stickerId, - options, - }: { - stickerId: string; - options?: StickerResolveOptions; - }): string - -sticker-id.ts - export function parseStickerId({ stickerId }: { stickerId: string }): { - providerId: string; - providerValue: string; - } - export function buildStickerId({ - providerId, - providerValue, - }: { - providerId: string; - providerValue: string; - }): string - -## apps/web/src/lib/stickers/providers - -emoji.ts - export const emojiProvider: StickerProvider - -flags.ts - export const flagsProvider: StickerProvider - -icons.ts - export const iconsProvider: StickerProvider - -index.ts - export function registerDefaultStickerProviders({ - providersToRegister = defaultProviders, - }: { - providersToRegister?: StickerProvider[]; - } = {}): void - -shapes.ts - export const shapesProvider: StickerProvider - -## apps/web/src/lib/timeline - -bookmarks.ts - export const BOOKMARK_TIME_EPSILON - export function findBookmarkIndex({ - bookmarks, - frameTime, - }: { - bookmarks: Bookmark[]; - frameTime: number; - }): number - export function isBookmarkAtTime({ - bookmarks, - frameTime, - }: { - bookmarks: Bookmark[]; - frameTime: number; - }): boolean - export function toggleBookmarkInArray({ - bookmarks, - frameTime, - }: { - bookmarks: Bookmark[]; - frameTime: number; - }): Bookmark[] - export function removeBookmarkFromArray({ - bookmarks, - frameTime, - }: { - bookmarks: Bookmark[]; - frameTime: number; - }): Bookmark[] - export function updateBookmarkInArray({ - bookmarks, - frameTime, - updates, - }: { - bookmarks: Bookmark[]; - frameTime: number; - updates: Partial>; - }): Bookmark[] - export function moveBookmarkInArray({ - bookmarks, - fromTime, - toTime, - }: { - bookmarks: Bookmark[]; - fromTime: number; - toTime: number; - }): Bookmark[] - export function getFrameTime({ - time, - fps, - }: { - time: number; - fps: number; - }): number - export function getBookmarkAtTime({ - bookmarks, - frameTime, - }: { - bookmarks: Bookmark[]; - frameTime: number; - }): Bookmark | null - export function getBookmarksActiveAtTime({ - bookmarks, - time, - }: { - bookmarks: Bookmark[]; - time: number; - }): Bookmark[] - -drag-utils.ts - export function getMouseTimeFromClientX({ - - clientX, - - containerRect, - - zoomLevel, - - scrollLeft, - - }: { - - clientX: number; - - containerRect: DOMRect; - - zoomLevel: number; - - scrollLeft: number; - - }): number - -drop-utils.ts - export function computeDropTarget({ - elementType, - mouseX, - mouseY, - tracks, - playheadTime, - isExternalDrop, - elementDuration, - pixelsPerSecond, - zoomLevel, - verticalDragDirection, - startTimeOverride, - excludeElementId, - }: ComputeDropTargetParams): DropTarget - export function getDropLineY({ - dropTarget, - tracks, - }: { - dropTarget: DropTarget; - tracks: TimelineTrack[]; - }): number - -element-utils.ts - export function canElementHaveAudio( - element: TimelineElement, - ) - export function isVisualElement( - element: TimelineElement, - ) - export function canElementBeHidden( - element: TimelineElement, - ) - export function hasMediaId( - element: TimelineElement, - ) - export function requiresMediaId({ - element, - }: { - element: CreateTimelineElement; - }): boolean - export function checkElementOverlaps({ - elements, - }: { - elements: TimelineElement[]; - }): boolean - export function resolveElementOverlaps({ - elements, - }: { - elements: TimelineElement[]; - }): TimelineElement[] - export function wouldElementOverlap({ - elements, - startTime, - endTime, - excludeElementId, - }: { - elements: TimelineElement[]; - startTime: number; - endTime: number; - excludeElementId?: string; - }): boolean - export function buildTextElement({ - raw, - startTime, - }: { - raw: Partial>; - startTime: number; - }): CreateTimelineElement - export function buildStickerElement({ - stickerId, - name, - startTime, - }: { - stickerId: string; - name?: string; - startTime: number; - }): CreateStickerElement - export function buildVideoElement({ - mediaId, - name, - duration, - startTime, - }: { - mediaId: string; - name: string; - duration: number; - startTime: number; - }): CreateVideoElement - export function buildImageElement({ - mediaId, - name, - duration, - startTime, - }: { - mediaId: string; - name: string; - duration: number; - startTime: number; - }): CreateImageElement - export function buildUploadAudioElement({ - mediaId, - name, - duration, - startTime, - buffer, - }: { - mediaId: string; - name: string; - duration: number; - startTime: number; - buffer?: AudioBuffer; - }): CreateUploadAudioElement - export function buildElementFromMedia({ - mediaId, - mediaType, - name, - duration, - startTime, - buffer, - }: { - mediaId: string; - mediaType: MediaType; - name: string; - duration: number; - startTime: number; - buffer?: AudioBuffer; - }): CreateTimelineElement - export function buildLibraryAudioElement({ - sourceUrl, - name, - duration, - startTime, - buffer, - }: { - sourceUrl: string; - name: string; - duration: number; - startTime: number; - buffer?: AudioBuffer; - }): CreateLibraryAudioElement - export function getElementsAtTime({ - tracks, - time, - }: { - tracks: TimelineTrack[]; - time: number; - }): { trackId: string; elementId: string }[] - export function collectFontFamilies({ - tracks, - }: { - tracks: TimelineTrack[]; - }): string[] - -index.ts - export function calculateTotalDuration({ - tracks, - }: { - tracks: TimelineTrack[]; - }): number - -ruler-utils.ts - export interface RulerConfig { - labelIntervalSeconds: number - tickIntervalSeconds: number - } - export function getRulerConfig({ - zoomLevel, - fps, - }: { - zoomLevel: number; - fps: number; - }): RulerConfig - export function shouldShowLabel({ - time, - labelIntervalSeconds, - }: { - time: number; - labelIntervalSeconds: number; - }): boolean - export function formatRulerLabel({ - timeInSeconds, - fps, - }: { - timeInSeconds: number; - fps: number; - }): string - -track-utils.ts - export function canTracktHaveAudio( - track: TimelineTrack, - ) - export function canTrackBeHidden( - track: TimelineTrack, - ) - export function getTrackColor({ type }: { type: TrackType }) - export function getTrackClasses({ type }: { type: TrackType }) - export function getTrackHeight({ type }: { type: TrackType }): number - export function getCumulativeHeightBefore({ - tracks, - trackIndex, - }: { - tracks: Array<{ type: TrackType }>; - trackIndex: number; - }): number - export function getTotalTracksHeight({ - tracks, - }: { - tracks: Array<{ type: TrackType }>; - }): number - export function buildEmptyTrack({ - id, - type, - name, - }: { - id: string; - type: TrackType; - name?: string; - }): TimelineTrack - export function getDefaultInsertIndexForTrack({ - tracks, - trackType, - }: { - tracks: TimelineTrack[]; - trackType: TrackType; - }): number - export function getHighestInsertIndexForTrack({ - tracks, - trackType, - }: { - tracks: TimelineTrack[]; - trackType: TrackType; - }): number - export function isMainTrack(track: TimelineTrack) - export function getMainTrack({ - tracks, - }: { - tracks: TimelineTrack[]; - }): TimelineTrack | null - export function ensureMainTrack({ - tracks, - }: { - tracks: TimelineTrack[]; - }): TimelineTrack[] - export function canElementGoOnTrack({ - elementType, - trackType, - }: { - elementType: ElementType; - trackType: TrackType; - }): boolean - export function validateElementTrackCompatibility({ - element, - track, - }: { - element: { type: ElementType }; - track: { type: TrackType }; - }): { isValid: boolean; errorMessage?: string } - export function getEarliestMainTrackElement({ - tracks, - excludeElementId, - }: { - tracks: TimelineTrack[]; - excludeElementId?: string; - }): TimelineElement | null - export function enforceMainTrackStart({ - tracks, - targetTrackId, - requestedStartTime, - excludeElementId, - }: { - tracks: TimelineTrack[]; - targetTrackId: string; - requestedStartTime: number; - excludeElementId?: string; - }): number - -zoom-utils.ts - export function getTimelineZoomMin({ - duration, - containerWidth, - }: { - duration: number; - containerWidth: number | null | undefined; - }): number - export function getTimelinePaddingPx({ - containerWidth, - zoomLevel, - minZoom, - }: { - containerWidth: number; - zoomLevel: number; - minZoom: number; - }): number - export function getZoomPercent({ - zoomLevel, - minZoom, - }: { - zoomLevel: number; - minZoom: number; - }): number - export function sliderToZoom({ - sliderPosition, - minZoom, - maxZoom = TIMELINE_CONSTANTS.ZOOM_MAX, - }: { - sliderPosition: number; - minZoom: number; - maxZoom?: number; - }): number - export function zoomToSlider({ - zoomLevel, - minZoom, - maxZoom = TIMELINE_CONSTANTS.ZOOM_MAX, - }: { - zoomLevel: number; - minZoom: number; - maxZoom?: number; - }): number - -## apps/web/src/lib/transcription - -caption.ts - export function buildCaptionChunks({ - segments, - wordsPerChunk = DEFAULT_WORDS_PER_CAPTION, - minDuration = MIN_CAPTION_DURATION_SECONDS, - }: { - segments: TranscriptionSegment[]; - wordsPerChunk?: number; - minDuration?: number; - }): CaptionChunk[] - -## apps/web/src/services/renderer - -canvas-renderer.ts - export type CanvasRendererParams = { - width: number; - height: number; - fps: number; - } - export class CanvasRenderer { - canvas: OffscreenCanvas | HTMLCanvasElement - context: OffscreenCanvasRenderingContext2D | CanvasRenderingContext2D - width: number - height: number - fps: number - constructor({ width, height, fps }: CanvasRendererParams) - setSize({ width, height }: { width: number; height: number }) - async render({ node, time }: { node: BaseNode; time: number }) - async renderToCanvas({ - node, - time, - targetCanvas, - }: { - node: BaseNode; - time: number; - targetCanvas: HTMLCanvasElement; - }) - } - -scene-builder.ts - export type BuildSceneParams = { - canvasSize: TCanvasSize; - tracks: TimelineTrack[]; - mediaAssets: MediaAsset[]; - duration: numb... - export function buildScene(params: BuildSceneParams) - -scene-exporter.ts - export type ExportFormat = "mp4" | "webm" - export type ExportQuality = "low" | "medium" | "high" | "very_high" - export type SceneExporterEvents = { - progress: [progress: number]; - complete: [buffer: ArrayBuffer]; - error: [error: Error]; - cance... - export class SceneExporter extends EventEmitter { - renderer: CanvasRenderer - format: ExportFormat - quality: ExportQuality - shouldIncludeAudio: boolean - audioBuffer: AudioBuffer - isCancelled - constructor({ - width, - height, - fps, - format, - quality, - shouldIncludeAudio, - audioBuffer, - }: ExportParams) - cancel(): void - async export({ - rootNode, - }: { - rootNode: RootNode; - }): Promise - } - -## apps/web/src/services/storage - -indexeddb-adapter.ts - export class IndexedDBAdapter implements StorageAdapter { - dbName: string - storeName: string - version: number - constructor(dbName: string, storeName: string, version = 1) - async get(key: string): Promise - async set(key: string, value: T): Promise - async remove(key: string): Promise - async list(): Promise - async getAll(): Promise - async clear(): Promise - } - export function deleteDatabase({ - dbName, - }: { - dbName: string; - }): Promise - -opfs-adapter.ts - export class OPFSAdapter implements StorageAdapter { - directoryName: string - constructor(directoryName = "media") - async get(key: string): Promise - async set(key: string, file: File): Promise - async remove(key: string): Promise - async list(): Promise - async clear(): Promise - static isSupported(): boolean - } - -service.ts - export const storageService - -types.ts - export interface StorageAdapter { - get(key: string): Promise - set(key: string, value: T): Promise - remove(key: string): Promise - list(): Promise - clear(): Promise - } - export interface MediaAssetData { - id: string - name: string - type: MediaType - size: number - lastModified: number - width?: number - height?: number - duration?: number - fps?: number - ephemeral?: boolean - thumbnailUrl?: string - } - export type SerializedScene = Omit & { - createdAt: string; - updatedAt: string; - } - export type SerializedProjectMetadata = Omit< - TProjectMetadata, - "createdAt" | "updatedAt" - > & { - createdAt: string; - updatedAt: string; - } - export type SerializedProject = Omit & { - metadata: SerializedProjectMetadata; - scenes: Serializ... - export interface StorageConfig { - projectsDb: string - mediaDb: string - savedSoundsDb: string - version: number - } - -## apps/web/src/services/transcription - -service.ts - export const transcriptionService - -worker.ts - export type WorkerMessage = | { type: "init"; modelId: string } - | { type: "transcribe"; audio: Float32Array; language: strin... - export type WorkerResponse = | { type: "init-progress"; progress: number } - | { type: "init-complete" } - | { type: "init-error... - -## apps/web/src/services/video-cache - -service.ts - export class VideoCache { - sinks - initPromises - async getFrameAt({ - mediaId, - file, - time, - }: { - mediaId: string; - file: File; - time: number; - }): Promise - clearVideo({ mediaId }: { mediaId: string }): void - clearAll(): void - getStats() - } - export const videoCache - -## apps/web/src/stores - -assets-panel-store.tsx - export const TAB_KEYS - export type Tab = (typeof TAB_KEYS)[number] - export const tabs - export const useAssetsPanelStore - -editor-store.ts - export const useEditorStore - -keybindings-store.ts - export const defaultKeybindings: KeybindingConfig - export interface KeybindingConflict { - key: ShortcutKey - existingAction: TActionWithOptionalArgs - newAction: TActionWithOptionalArgs - } - export const useKeybindingsStore - -panel-store.ts - export interface PanelSizes { - tools: number - preview: number - properties: number - mainContent: number - timeline: number - } - export type PanelId = keyof PanelSizes - export const usePanelStore - -preview-store.ts - export const usePreviewStore - -sounds-store.ts - export const useSoundsStore - -stickers-store.ts - export const useStickersStore - -timeline-store.ts - export const useTimelineStore - -## apps/web/src/types - -assets.ts - export type MediaType = "image" | "video" | "audio" - export interface MediaAsset extends Omit { - file: File - url?: string - } - -blog.ts - export type Post = { - id: string; - slug: string; - title: string; - content: string; - description: string; - coverImage... - export type Pagination = { - limit: number; - currpage: number; - nextPage: number | null; - prevPage: number | null; - totalIt... - export type MarblePostList = { - posts: Post[]; - pagination: Pagination; - } - export type MarblePost = { - post: Post; - } - export type Tag = { - id: string; - name: string; - slug: string; - } - export type MarbleTag = { - tag: Tag; - } - export type MarbleTagList = { - tags: Tag[]; - pagination: Pagination; - } - export type Category = { - id: string; - name: string; - slug: string; - } - export type MarbleCategory = { - category: Category; - } - export type MarbleCategoryList = { - categories: Category[]; - pagination: Pagination; - } - export type Author = { - id: string; - name: string; - image: string; - } - export type MarbleAuthor = { - author: Author; - } - export type MarbleAuthorList = { - authors: Author[]; - pagination: Pagination; - } - -drag.ts - export interface MediaDragData extends BaseDragData { - type: "media" - mediaType: "image" | "video" | "audio" - } - export interface TextDragData extends BaseDragData { - type: "text" - content: string - } - export interface StickerDragData extends BaseDragData { - type: "sticker" - stickerId: string - } - export type TimelineDragData = MediaDragData | TextDragData | StickerDragData - -editor.ts - export type TPlatformLayout = "tiktok" - -export.ts - export const EXPORT_QUALITY_VALUES - export const EXPORT_FORMAT_VALUES - export type ExportFormat = (typeof EXPORT_FORMAT_VALUES)[number] - export type ExportQuality = (typeof EXPORT_QUALITY_VALUES)[number] - export interface ExportOptions { - format: ExportFormat - quality: ExportQuality - fps?: number - includeAudio?: boolean - onProgress?: ({ progress }: { progress: number }) => void - onCancel?: () => boolean - } - export interface ExportResult { - success: boolean - buffer?: ArrayBuffer - error?: string - cancelled?: boolean - } - -fonts.ts - export interface FontOption { - value: string - label: string - category: "system" | "google" | "custom" - weights?: number[] - hasClassName?: boolean - } - export interface GoogleFontMeta { - family: string - category: string - } - export interface FontAtlasEntry { - x: number - y: number - w: number - ch: number - s: string[] - } - export interface FontAtlas { - fonts: Record - } - -keybinding.ts - export type ModifierKeys = | "ctrl" - | "alt" - | "shift" - | "ctrl+shift" - | "alt+shift" - | "ctrl+alt" - | "ctrl+alt+shift" - export type Key = | "a" - | "b" - | "c" - | "d" - | "e" - | "f" - | "g" - | "h" - | "i" - | "j" - | "k" - | "l" - | "m" - | "n" - ... - export type ModifierBasedShortcutKey = `${ModifierKeys}+${Key}` - export type SingleCharacterShortcutKey = `${Key}` - export type ShortcutKey = ModifierBasedShortcutKey | SingleCharacterShortcutKey - export type KeybindingConfig = { - [key in ShortcutKey]?: TActionWithOptionalArgs; - } - -language.ts - export type Language = (typeof LANGUAGES)[number] - export type LanguageCode = Language["code"] - -project.ts - export type TBackground = | { - type: "color"; - color: string; - } - | { - type: "blur"; - blurIntensity: number; - } - export interface TCanvasSize { - width: number - height: number - } - export interface TProjectMetadata { - id: string - name: string - thumbnail?: string - duration: number - createdAt: Date - updatedAt: Date - } - export interface TProjectSettings { - fps: number - canvasSize: TCanvasSize - originalCanvasSize?: TCanvasSize | null - background: TBackground - } - export interface TTimelineViewState { - zoomLevel: number - scrollLeft: number - playheadTime: number - } - export interface TProject { - metadata: TProjectMetadata - scenes: TScene[] - currentSceneId: string - settings: TProjectSettings - version: number - timelineViewState?: TTimelineViewState - } - export type TProjectSortKey = "createdAt" | "updatedAt" | "name" | "duration" - export type TSortOrder = "asc" | "desc" - export type TProjectSortOption = `${TProjectSortKey}-${TSortOrder}` - -rendering.ts - export type BlendMode = | "normal" - - | "darken" - - | "multiply" - - | "color-burn" - - | "lighten" - - | "screen" - - | "plus-ligh... - -sounds.ts - export interface SoundEffect { - id: number - name: string - description: string - url: string - previewUrl?: string - downloadUrl?: string - duration: number - filesize: number - type: string - channels: number - bitrate: number - bitdepth: number - samplerate: number - username: string - tags: string[] - license: string - created: string - downloads: number - rating: number - ratingCount: number - } - export interface SavedSound { - id: number - name: string - username: string - previewUrl?: string - downloadUrl?: string - duration: number - tags: string[] - license: string - savedAt: string - } - export interface SavedSoundsData { - sounds: SavedSound[] - lastModified: string - } - -stickers.ts - export type StickerCategory = keyof typeof STICKER_CATEGORIES - export interface StickerItem { - id: string - provider: string - name: string - previewUrl: string - metadata: Record - } - export interface StickerSearchResult { - items: StickerItem[] - total: number - hasMore: boolean - } - export interface StickerProviderSearchOptions { - limit?: number - } - export interface StickerProviderBrowseOptions { - page?: number - limit?: number - } - export interface StickerResolveOptions { - width?: number - height?: number - } - export interface StickerProvider { - id: string - search({ - query, - options, - }: { - query: string; - options?: StickerProviderSearchOptions; - }): Promise - browse({ - options, - }: { - options?: StickerProviderBrowseOptions; - }): Promise - resolveUrl({ - stickerId, - options, - }: { - stickerId: string; - options?: StickerResolveOptions; - }): string - } - -time.ts - export type TTimeCode = "MM:SS" | "HH:MM:SS" | "HH:MM:SS:CS" | "HH:MM:SS:FF" - -timeline.ts - export interface Bookmark { - time: number - note?: string - color?: string - duration?: number - } - export interface TScene { - id: string - name: string - isMain: boolean - tracks: TimelineTrack[] - bookmarks: Bookmark[] - createdAt: Date - updatedAt: Date - } - export type TrackType = "video" | "text" | "audio" | "sticker" - export interface VideoTrack extends BaseTrack { - type: "video" - elements: (VideoElement | ImageElement)[] - isMain: boolean - muted: boolean - hidden: boolean - } - export interface TextTrack extends BaseTrack { - type: "text" - elements: TextElement[] - hidden: boolean - } - export interface AudioTrack extends BaseTrack { - type: "audio" - elements: AudioElement[] - muted: boolean - } - export interface StickerTrack extends BaseTrack { - type: "sticker" - elements: StickerElement[] - hidden: boolean - } - export type TimelineTrack = VideoTrack | TextTrack | AudioTrack | StickerTrack - export interface Transform { - scale: number - position: { - x: number; - y: number; - } - rotate: number - } - export interface UploadAudioElement extends BaseAudioElement { - sourceType: "upload" - mediaId: string - } - export interface LibraryAudioElement extends BaseAudioElement { - sourceType: "library" - sourceUrl: string - } - export type AudioElement = UploadAudioElement | LibraryAudioElement - export interface VideoElement extends BaseTimelineElement { - type: "video" - mediaId: string - muted?: boolean - hidden?: boolean - transform: Transform - opacity: number - blendMode?: BlendMode - } - export interface ImageElement extends BaseTimelineElement { - type: "image" - mediaId: string - hidden?: boolean - transform: Transform - opacity: number - blendMode?: BlendMode - } - export interface TextElement extends BaseTimelineElement { - type: "text" - content: string - fontSize: number - fontFamily: string - color: string - backgroundColor: string - textAlign: "left" | "center" | "right" - fontWeight: "normal" | "bold" - fontStyle: "normal" | "italic" - textDecoration: "none" | "underline" | "line-through" - letterSpacing?: number - lineHeight?: number - hidden?: boolean - transform: Transform - opacity: number - blendMode?: BlendMode - } - export interface StickerElement extends BaseTimelineElement { - type: "sticker" - stickerId: string - hidden?: boolean - transform: Transform - opacity: number - blendMode?: BlendMode - } - export type TimelineElement = | AudioElement - | VideoElement - | ImageElement - | TextElement - | StickerElement - export type ElementType = TimelineElement["type"] - export type CreateUploadAudioElement = Omit - export type CreateLibraryAudioElement = Omit - export type CreateAudioElement = | CreateUploadAudioElement - | CreateLibraryAudioElement - export type CreateVideoElement = Omit - export type CreateImageElement = Omit - export type CreateTextElement = Omit - export type CreateStickerElement = Omit - export type CreateTimelineElement = | CreateAudioElement - | CreateVideoElement - | CreateImageElement - | CreateTextElement - | CreateSt... - export interface ElementDragState { - isDragging: boolean - elementId: string | null - trackId: string | null - startMouseX: number - startMouseY: number - startElementTime: number - clickOffsetTime: number - currentTime: number - currentMouseY: number - } - export interface DropTarget { - trackIndex: number - isNewTrack: boolean - insertPosition: "above" | "below" | null - xPosition: number - } - export interface ComputeDropTargetParams { - elementType: ElementType - mouseX: number - mouseY: number - tracks: TimelineTrack[] - playheadTime: number - isExternalDrop: boolean - elementDuration: number - pixelsPerSecond: number - zoomLevel: number - verticalDragDirection?: "up" | "down" | null - startTimeOverride?: number - excludeElementId?: string - } - export interface ClipboardItem { - trackId: string - trackType: TrackType - element: CreateTimelineElement - } - -transcription.ts - export type TranscriptionLanguage = LanguageCode | "auto" - export interface TranscriptionSegment { - text: string - start: number - end: number - } - export interface TranscriptionResult { - text: string - segments: TranscriptionSegment[] - language: string - } - export type TranscriptionStatus = | "idle" - | "loading-model" - | "transcribing" - | "complete" - | "error" - export interface TranscriptionProgress { - status: TranscriptionStatus - progress: number - message?: string - } - export type TranscriptionModelId = | "whisper-tiny" - | "whisper-small" - | "whisper-medium" - | "whisper-large-v3-turbo" - export interface TranscriptionModel { - id: TranscriptionModelId - name: string - huggingFaceId: string - description: string - } - export interface CaptionChunk { - text: string - startTime: number - duration: number - } - -## apps/web/src/utils - -browser.ts - export function isTypableDOMElement({ - element, - }: { - element: HTMLElement; - }): boolean - -color.ts - export type ColorFormat = "hex" | "rgb" | "hsl" | "hsv" - export function hexToHsv({ hex }: { hex: string }): [number, number, number] - export function hsvToHex({ - - h, - - s, - - v, - - }: { h: number; s: number; v: number }): string - export function parseHexAlpha({ hex }: { hex: string }): { - - rgb: string; - - alpha: number; - - } - export function appendAlpha({ - - rgbHex, - - alpha, - - }: { rgbHex: string; alpha: number }): string - export function extractColorFromText({ - - text, - - }: { text: string }): string | null - export function formatColorValue({ - - hex, - - format, - - }: { - - hex: string; - - format: ColorFormat; - - }): string - export function parseColorInput({ - - input, - - format, - - }: { - - input: string; - - format: ColorFormat; - - }): string | null - -date.ts - export function formatDate({ date }: { date: Date }): string - -geometry.ts - export function dimensionToAspectRatio({ - width, - height, - }: { - width: number; - height: number; - }): string - -id.ts - export function generateUUID(): string - -math.ts - export function clamp({ - value, - min, - max, - }: { - value: number; - min: number; - max: number; - }): number - export function evaluateMathExpression({ - input, - }: { - input: string; - }): number | null - -platform.ts - export function getPlatformSpecialKey(): string - export function getPlatformAlternateKey(): string - export function isAppleDevice(): boolean - -string.ts - export function capitalizeFirstLetter({ string }: { string: string }) - export function uppercase({ string }: { string: string }) - -ui.ts - export function cn(...inputs: ClassValue[]): string - -## packages/ui/src/icons - -brand.tsx - export function OcVercelIcon({ className }: { className?: string }) - export function OcMarbleIcon({ - className = "", - size = 32, - }: { - className?: string; - size?: number; - }) - export function OcDataBuddyIcon({ - className = "", - size = 32, - }: { - className?: string; - size?: number; - }) - -ui.tsx - export function OcVideoIcon({ - className = "", - size = 32, - }: { - className?: string; - size?: number; - }) - export function OcCheckerboardIcon({ - className = "", - size = 32, - }: { - className?: string; - size?: number; - }) - export function OcFontWeightIcon({ - className = "", - size = 32, - }: { - className?: string; - size?: number; - }) - export function OcSlidersVerticalIcon({ - className = "", - size = 32, - }: { - className?: string; - size?: number; - }) - export function OcSocialIcon({ - className = "", - size = 32, - }: { - className?: string; - size?: number; - }) - -``` - ---- - -_Generated and maintained by [Twiggy](https://github.com/twiggy-tools/Twiggy)_ diff --git a/.cursor/rules/comments.mdc b/.cursor/rules/comments.mdc deleted file mode 100644 index 4b9180cf1..000000000 --- a/.cursor/rules/comments.mdc +++ /dev/null @@ -1,34 +0,0 @@ ---- -alwaysApply: false ---- -# Comment Guidelines - -## Good Comments (Human-style) -- Explain WHY, not WHAT -- Document non-obvious behavior or edge cases -- Warn about performance implications or side effects -- Explain business logic that isn't clear from code - -Examples: -```javascript -// transfer, not copy; sender buffer detaches -// satisfies: check shape; keep literals -// keep multibyte across chunks -// timingSafeEqual throws on length mismatch -``` - -## Bad Comments (AI-style) -- Don't explain what the code literally does -- Don't add changelog-style comments in code -- Don't comment every line or obvious operations - -Avoid: -```javascript -// Prevent duplicate initialization -// Check if project is already loaded -// Mark as initializing to prevent race conditions -// (changed from blah to blah) -``` - -## Rule -Only add comments when there's genuinely non-obvious behavior, performance considerations, or business logic that needs context. Code should be self-documenting through naming and structure. \ No newline at end of file diff --git a/.cursor/rules/handling-uncertainty.mdc b/.cursor/rules/handling-uncertainty.mdc deleted file mode 100644 index 59cfb5bda..000000000 --- a/.cursor/rules/handling-uncertainty.mdc +++ /dev/null @@ -1,20 +0,0 @@ ---- -alwaysApply: false ---- -# Handling Uncertainty - -## Principle -If you can't confidently respond due to missing context, data access, or ambiguity (multiple interpretations), report it instead of guessing. Seek clarification to avoid errors. - -Apply when: query lacks details, no access to info/tools, or unclear intent. - -## How to Report -1. **Description**: Why uncertain and what you need. -2. **Questions**: 1-3 targeted ones. -3. **Assumptions** (opt.): State if proceeding; omit otherwise. - -Direct and concise. - -**Assumptions**: None. - -Builds transparency. \ No newline at end of file diff --git a/.cursor/rules/readability.mdc b/.cursor/rules/readability.mdc deleted file mode 100644 index 22bb5397e..000000000 --- a/.cursor/rules/readability.mdc +++ /dev/null @@ -1,8 +0,0 @@ ---- -alwaysApply: false ---- -# Readability First - -Optimize code for AI agents to understand and modify. - -Never abbreviate. `event` not `e`, `element` not `el`. If it's easy to read, it's correct. In this case, "config" is better than "configuration" because it's shorter and is **still very readable**. "El" is not very readable. diff --git a/.cursor/rules/separation-of-concerns.mdc b/.cursor/rules/separation-of-concerns.mdc deleted file mode 100644 index 4abb88089..000000000 --- a/.cursor/rules/separation-of-concerns.mdc +++ /dev/null @@ -1,51 +0,0 @@ ---- -alwaysApply: false ---- -# Separation of Concerns - -## Core Principle - -Each file should have one single purpose/responsibility. Related functionality should be grouped together, unrelated functionality should be separated. - -## Good Separation - -- One file per major concern (auth, validation, data transformation) -- Group related utilities together -- Extract shared logic into dedicated files -- Keep API routes focused on their specific endpoint logic - -Examples: - -```javascript -// ✅ Good: Each file has clear responsibility -/lib/rate-limit.ts // Rate limiting utilities -/lib/validation.ts // Input validation schemas -/lib/freesound-api.ts // External API integration -/api/sounds/search/route.ts // Route handler only -``` - -## Bad Mixing of Concerns - -Avoid cramming multiple responsibilities into one file: - -```javascript -// ❌ Bad: Route file doing everything -/api/sounds/search/route.ts -- Rate limiting logic -- Validation schemas -- API transformation -- External API calls -- Response formatting -- Error handling utilities -``` - -## When to Separate - -- File is getting long (>500 lines) -- Multiple distinct responsibilities in one file -- Logic could be reused elsewhere -- Complex utilities that distract from main purpose - -## Rule - -One file, one responsibility. Extract shared concerns into focused utility files \ No newline at end of file diff --git a/.cursor/rules/ultracite.mdc b/.cursor/rules/ultracite.mdc deleted file mode 100644 index 83e14c18c..000000000 --- a/.cursor/rules/ultracite.mdc +++ /dev/null @@ -1,101 +0,0 @@ ---- -alwaysApply: false ---- -# Project Context - -Ultracite enforces strict type safety, accessibility standards, and consistent code quality for JavaScript/TypeScript projects using Biome's formatter. - -## Key Principles - -- Zero configuration required -- Subsecond performance -- Maximum type safety -- AI-friendly code generation - -## Before Writing Code - -1. Analyze existing patterns in the codebase -2. Consider edge cases and error scenarios -3. Follow the rules below strictly -4. Validate accessibility requirements -5. Avoid code duplication - -## Rules - -### Accessibility (a11y) - -- Always include a `title` element for icons unless there's text beside the icon. -- Accompany `onClick` with at least one of: `onKeyUp`, `onKeyDown`, or `onKeyPress`. -- Accompany `onMouseOver`/`onMouseOut` with `onFocus`/`onBlur`. - -### Code Complexity and Quality - -- Don't use primitive type aliases or misleading types. -- Don't use the comma operator. -- Use for...of statements instead of Array.forEach. -- Don't initialize variables to undefined. -- Use .flatMap() instead of map().flat() when possible. - -### React and JSX Best Practices - -- Don't import `React` itself. -- Don't use both `children` and `dangerouslySetInnerHTML` props on the same element. -- Don't insert comments as text nodes. -- Use `<>...` instead of `...`. - -### Function Parameters and Props - -- Always use destructured props objects instead of individual parameters in functions. -- Example: `function helloWorld({ prop }: { prop: string })` instead of `function helloWorld(param: string)`. -- This applies to all functions, not just React components. - -### Correctness and Safety - -- Don't assign a value to itself. -- Avoid unused imports and variables. -- Don't use await inside loops. -- Don't hardcode sensitive data like API keys and tokens. -- Don't use the TypeScript directive @ts-ignore. -- Make sure the `preconnect` attribute is used when using Google Fonts. -- Don't use the `delete` operator. -- Don't use `require()` in TypeScript/ES modules - use proper `import` statements. - -### TypeScript Best Practices - -- Don't use TypeScript enums. -- Use either `T[]` or `Array` consistently. -- Don't use the `any` type. - -### Style and Consistency - -- Don't use global `eval()`. -- Use `String.slice()` instead of `String.substr()` and `String.substring()`. -- Don't use `else` blocks when the `if` block breaks early. -- Put default function parameters and optional function parameters last. -- Use `new` when throwing an error. -- Use `String.trimStart()` and `String.trimEnd()` over `String.trimLeft()` and `String.trimRight()`. - -### Next.js Specific Rules - -- Don't use `` elements in Next.js projects. -- Don't use `` elements in Next.js projects. - -## Example: Error Handling - -```typescript -// ✅ Good: Comprehensive error handling -try { - const result = await fetchData(); - return { success: true, data: result }; -} catch (error) { - console.error("API call failed:", error); - return { success: false, error: error.message }; -} - -// ❌ Bad: Swallowing errors -try { - return await fetchData(); -} catch (e) { - console.log(e); -} -``` diff --git a/.cursor/rules/writing-scannable-code.mdc b/.cursor/rules/writing-scannable-code.mdc deleted file mode 100644 index 2c36d4966..000000000 --- a/.cursor/rules/writing-scannable-code.mdc +++ /dev/null @@ -1,52 +0,0 @@ ---- -alwaysApply: false ---- -# Scannable Code Guidelines/Separating Concerns. - -## Core Principle - -Code should be scannable through proper abstraction, not comments. Use variables and helper functions to make intent clear at a glance. - -## Good Scannable Code - -- Extract complex logic into well-named variables -- Create helper functions for multi-step operations -- Use descriptive names that explain intent - -Examples: - -```javascript -// ✅ Scannable: Intent is clear from variable names -const isValidUser = user.isActive && user.hasPermissions; -const shouldProcessPayment = amount > 0 && !order.isPaid; - -// ✅ Scannable: Complex logic extracted to helper -const searchParams = buildFreesoundSearchParams({ query, filters, pagination }); -const transformedResults = transformFreesoundResults({ rawResults }); -``` - -## Bad Unscannable Code - -Avoid: - -```javascript -// ❌ Hard to scan: What does this condition mean? -if (type === "effects" || !type) { - params.append("filter", "duration:[* TO 30.0]"); - params.append("filter", `avg_rating:[${min_rating} TO *]`); - if (commercial_only) { - params.append("filter", 'license:("Attribution" OR "Creative Commons 0")'); - } -} - -// ❌ Hard to scan: Complex ternary -const sortParam = query - ? sort === "score" - ? "score" - : `${sort}_desc` - : `${sort}_desc`; -``` - -## Rule - -Make code scannable by extracting intent into variables and helper functions. If you need to think about what code does, extract it. The reader should understand the flow without diving into implementation details. \ No newline at end of file diff --git a/.cursor/settings.json b/.cursor/settings.json deleted file mode 100644 index 28a77607e..000000000 --- a/.cursor/settings.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "plugins": { - "figma": { - "enabled": true - } - } -} diff --git a/.cursor/skills/design/SKILL.md b/.cursor/skills/design/SKILL.md deleted file mode 100644 index d5a05e27b..000000000 --- a/.cursor/skills/design/SKILL.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -name: frontend-design -description: Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics. -license: Complete terms in LICENSE.txt ---- - -This skill guides creation of distinctive, production-grade frontend interfaces that avoid generic "AI slop" aesthetics. Implement real working code with exceptional attention to aesthetic details and creative choices. - -The user provides frontend requirements: a component, page, application, or interface to build. They may include context about the purpose, audience, or technical constraints. - -## Design Thinking - -Before coding, understand the context and commit to a BOLD aesthetic direction: - -- **Purpose**: What problem does this interface solve? Who uses it? -- **Tone**: Pick an extreme: brutally minimal, maximalist chaos, retro-futuristic, organic/natural, luxury/refined, playful/toy-like, editorial/magazine, brutalist/raw, art deco/geometric, soft/pastel, industrial/utilitarian, etc. There are so many flavors to choose from. Use these for inspiration but design one that is true to the aesthetic direction. -- **Constraints**: Technical requirements (framework, performance, accessibility). -- **Differentiation**: What makes this UNFORGETTABLE? What's the one thing someone will remember? - -**CRITICAL**: Choose a clear conceptual direction and execute it with precision. Bold maximalism and refined minimalism both work - the key is intentionality, not intensity. - -Then implement working code (HTML/CSS/JS, React, Vue, etc.) that is: - -- Production-grade and functional -- Visually striking and memorable -- Cohesive with a clear aesthetic point-of-view -- Meticulously refined in every detail - -## Frontend Aesthetics Guidelines - -Focus on: - -- **Typography**: Choose fonts that are beautiful, unique, and interesting. Avoid generic fonts like Arial and Inter; opt instead for distinctive choices that elevate the frontend's aesthetics; unexpected, characterful font choices. Pair a distinctive display font with a refined body font. -- **Color & Theme**: Commit to a cohesive aesthetic. Use CSS variables for consistency. Dominant colors with sharp accents outperform timid, evenly-distributed palettes. -- **Motion**: Use animations for effects and micro-interactions. Prioritize CSS-only solutions for HTML. Use Motion library for React when available. Focus on high-impact moments: one well-orchestrated page load with staggered reveals (animation-delay) creates more delight than scattered micro-interactions. Use scroll-triggering and hover states that surprise. -- **Spatial Composition**: Unexpected layouts. Asymmetry. Overlap. Diagonal flow. Grid-breaking elements. Generous negative space OR controlled density. -- **Backgrounds & Visual Details**: Create atmosphere and depth rather than defaulting to solid colors. Add contextual effects and textures that match the overall aesthetic. Apply creative forms like gradient meshes, noise textures, geometric patterns, layered transparencies, dramatic shadows, decorative borders, custom cursors, and grain overlays. - -NEVER use generic AI-generated aesthetics like overused font families (Inter, Roboto, Arial, system fonts), cliched color schemes (particularly purple gradients on white backgrounds), predictable layouts and component patterns, and cookie-cutter design that lacks context-specific character. - -Interpret creatively and make unexpected choices that feel genuinely designed for the context. No design should be the same. Vary between light and dark themes, different fonts, different aesthetics. NEVER converge on common choices (Space Grotesk, for example) across generations. - -**IMPORTANT**: Match implementation complexity to the aesthetic vision. Maximalist designs need elaborate code with extensive animations and effects. Minimalist or refined designs need restraint, precision, and careful attention to spacing, typography, and subtle details. Elegance comes from executing the vision well. - -Remember: Claude is capable of extraordinary creative work. Don't hold back, show what can truly be created when thinking outside the box and committing fully to a distinctive vision. From 39ea298a9ccba3104c549c0ca079c231981811f5 Mon Sep 17 00:00:00 2001 From: Maze Winther Date: Wed, 25 Mar 2026 16:20:52 +0100 Subject: [PATCH 008/193] chore: gitignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index fa3b5f687..67a2404de 100644 --- a/.gitignore +++ b/.gitignore @@ -17,4 +17,4 @@ bun.lockb .content-collections # Twiggy -.cursor/rules/file-structure.mdc +.cursor/ \ No newline at end of file From 8db3bead13441a5882d8689dfc6a9f09c82375d9 Mon Sep 17 00:00:00 2001 From: Maze Winther Date: Wed, 25 Mar 2026 16:47:22 +0100 Subject: [PATCH 009/193] feat: masks, properties refactor, shaders, storage migrations, and more --- apps/web/content/changelog/0.3.0.md | 67 ++ apps/web/next.config.ts | 4 + apps/web/package.json | 14 +- apps/web/postcss.config.mjs | 7 +- apps/web/public/flags/ad.svg | 150 +++ apps/web/public/flags/ae.svg | 6 + apps/web/public/flags/af.svg | 81 ++ apps/web/public/flags/ag.svg | 14 + apps/web/public/flags/ai.svg | 29 + apps/web/public/flags/al.svg | 5 + apps/web/public/flags/am.svg | 5 + apps/web/public/flags/ao.svg | 13 + apps/web/public/flags/aq.svg | 5 + apps/web/public/flags/ar.svg | 32 + apps/web/public/flags/arab.svg | 109 +++ apps/web/public/flags/as.svg | 72 ++ apps/web/public/flags/asean.svg | 13 + apps/web/public/flags/at.svg | 4 + apps/web/public/flags/au.svg | 8 + apps/web/public/flags/aw.svg | 186 ++++ apps/web/public/flags/ax.svg | 18 + apps/web/public/flags/az.svg | 8 + apps/web/public/flags/ba.svg | 12 + apps/web/public/flags/bb.svg | 6 + apps/web/public/flags/bd.svg | 4 + apps/web/public/flags/be.svg | 7 + apps/web/public/flags/bf.svg | 7 + apps/web/public/flags/bg.svg | 5 + apps/web/public/flags/bh.svg | 4 + apps/web/public/flags/bi.svg | 15 + apps/web/public/flags/bj.svg | 14 + apps/web/public/flags/bl.svg | 5 + apps/web/public/flags/bm.svg | 97 ++ apps/web/public/flags/bn.svg | 36 + apps/web/public/flags/bo.svg | 673 +++++++++++++ apps/web/public/flags/bq.svg | 5 + apps/web/public/flags/br.svg | 45 + apps/web/public/flags/bs.svg | 13 + apps/web/public/flags/bt.svg | 89 ++ apps/web/public/flags/bv.svg | 13 + apps/web/public/flags/bw.svg | 7 + apps/web/public/flags/by.svg | 18 + apps/web/public/flags/bz.svg | 145 +++ apps/web/public/flags/ca.svg | 4 + apps/web/public/flags/cc.svg | 19 + apps/web/public/flags/cd.svg | 5 + apps/web/public/flags/cefta.svg | 13 + apps/web/public/flags/cf.svg | 15 + apps/web/public/flags/cg.svg | 12 + apps/web/public/flags/ch.svg | 9 + apps/web/public/flags/ci.svg | 7 + apps/web/public/flags/ck.svg | 9 + apps/web/public/flags/cl.svg | 13 + apps/web/public/flags/cm.svg | 15 + apps/web/public/flags/cn.svg | 11 + apps/web/public/flags/co.svg | 7 + apps/web/public/flags/cp.svg | 7 + apps/web/public/flags/cr.svg | 7 + apps/web/public/flags/cu.svg | 13 + apps/web/public/flags/cv.svg | 13 + apps/web/public/flags/cw.svg | 14 + apps/web/public/flags/cx.svg | 15 + apps/web/public/flags/cy.svg | 6 + apps/web/public/flags/cz.svg | 5 + apps/web/public/flags/de.svg | 5 + apps/web/public/flags/dg.svg | 130 +++ apps/web/public/flags/dj.svg | 13 + apps/web/public/flags/dk.svg | 5 + apps/web/public/flags/dm.svg | 152 +++ apps/web/public/flags/do.svg | 121 +++ apps/web/public/flags/dz.svg | 5 + apps/web/public/flags/eac.svg | 48 + apps/web/public/flags/ec.svg | 138 +++ apps/web/public/flags/ee.svg | 5 + apps/web/public/flags/eg.svg | 38 + apps/web/public/flags/eh.svg | 16 + apps/web/public/flags/er.svg | 8 + apps/web/public/flags/es-ct.svg | 4 + apps/web/public/flags/es-ga.svg | 187 ++++ apps/web/public/flags/es-pv.svg | 5 + apps/web/public/flags/es.svg | 544 +++++++++++ apps/web/public/flags/et.svg | 14 + apps/web/public/flags/eu.svg | 28 + apps/web/public/flags/fi.svg | 5 + apps/web/public/flags/fj.svg | 120 +++ apps/web/public/flags/fk.svg | 90 ++ apps/web/public/flags/fm.svg | 11 + apps/web/public/flags/fo.svg | 12 + apps/web/public/flags/fr.svg | 5 + apps/web/public/flags/ga.svg | 7 + apps/web/public/flags/gb-eng.svg | 5 + apps/web/public/flags/gb-nir.svg | 132 +++ apps/web/public/flags/gb-sct.svg | 4 + apps/web/public/flags/gb-wls.svg | 9 + apps/web/public/flags/gb.svg | 7 + apps/web/public/flags/gd.svg | 27 + apps/web/public/flags/ge.svg | 6 + apps/web/public/flags/gf.svg | 5 + apps/web/public/flags/gg.svg | 9 + apps/web/public/flags/gh.svg | 6 + apps/web/public/flags/gi.svg | 32 + apps/web/public/flags/gl.svg | 4 + apps/web/public/flags/gm.svg | 14 + apps/web/public/flags/gn.svg | 7 + apps/web/public/flags/gp.svg | 5 + apps/web/public/flags/gq.svg | 23 + apps/web/public/flags/gr.svg | 16 + apps/web/public/flags/gs.svg | 133 +++ apps/web/public/flags/gt.svg | 204 ++++ apps/web/public/flags/gu.svg | 19 + apps/web/public/flags/gw.svg | 13 + apps/web/public/flags/gy.svg | 9 + apps/web/public/flags/hk.svg | 8 + apps/web/public/flags/hm.svg | 8 + apps/web/public/flags/hn.svg | 18 + apps/web/public/flags/hr.svg | 58 ++ apps/web/public/flags/ht.svg | 116 +++ apps/web/public/flags/hu.svg | 7 + apps/web/public/flags/ic.svg | 7 + apps/web/public/flags/id.svg | 4 + apps/web/public/flags/ie.svg | 7 + apps/web/public/flags/il.svg | 14 + apps/web/public/flags/im.svg | 36 + apps/web/public/flags/in.svg | 25 + apps/web/public/flags/io.svg | 130 +++ apps/web/public/flags/iq.svg | 10 + apps/web/public/flags/ir.svg | 219 +++++ apps/web/public/flags/is.svg | 12 + apps/web/public/flags/it.svg | 7 + apps/web/public/flags/je.svg | 62 ++ apps/web/public/flags/jm.svg | 8 + apps/web/public/flags/jo.svg | 16 + apps/web/public/flags/jp.svg | 11 + apps/web/public/flags/ke.svg | 23 + apps/web/public/flags/kg.svg | 4 + apps/web/public/flags/kh.svg | 61 ++ apps/web/public/flags/ki.svg | 36 + apps/web/public/flags/km.svg | 16 + apps/web/public/flags/kn.svg | 14 + apps/web/public/flags/kp.svg | 15 + apps/web/public/flags/kr.svg | 24 + apps/web/public/flags/kw.svg | 13 + apps/web/public/flags/ky.svg | 103 ++ apps/web/public/flags/kz.svg | 36 + apps/web/public/flags/la.svg | 12 + apps/web/public/flags/lb.svg | 15 + apps/web/public/flags/lc.svg | 8 + apps/web/public/flags/li.svg | 43 + apps/web/public/flags/lk.svg | 22 + apps/web/public/flags/lr.svg | 14 + apps/web/public/flags/ls.svg | 8 + apps/web/public/flags/lt.svg | 7 + apps/web/public/flags/lu.svg | 5 + apps/web/public/flags/lv.svg | 6 + apps/web/public/flags/ly.svg | 13 + apps/web/public/flags/ma.svg | 4 + apps/web/public/flags/mc.svg | 6 + apps/web/public/flags/md.svg | 70 ++ apps/web/public/flags/me.svg | 116 +++ apps/web/public/flags/mf.svg | 5 + apps/web/public/flags/mg.svg | 7 + apps/web/public/flags/mh.svg | 7 + apps/web/public/flags/mk.svg | 5 + apps/web/public/flags/ml.svg | 7 + apps/web/public/flags/mm.svg | 12 + apps/web/public/flags/mn.svg | 14 + apps/web/public/flags/mo.svg | 9 + apps/web/public/flags/mp.svg | 86 ++ apps/web/public/flags/mq.svg | 5 + apps/web/public/flags/mr.svg | 6 + apps/web/public/flags/ms.svg | 29 + apps/web/public/flags/mt.svg | 58 ++ apps/web/public/flags/mu.svg | 8 + apps/web/public/flags/mv.svg | 6 + apps/web/public/flags/mw.svg | 10 + apps/web/public/flags/mx.svg | 382 ++++++++ apps/web/public/flags/my.svg | 26 + apps/web/public/flags/mz.svg | 21 + apps/web/public/flags/na.svg | 16 + apps/web/public/flags/nc.svg | 13 + apps/web/public/flags/ne.svg | 6 + apps/web/public/flags/nf.svg | 9 + apps/web/public/flags/ng.svg | 6 + apps/web/public/flags/ni.svg | 129 +++ apps/web/public/flags/nl.svg | 5 + apps/web/public/flags/no.svg | 7 + apps/web/public/flags/np.svg | 13 + apps/web/public/flags/nr.svg | 12 + apps/web/public/flags/nu.svg | 10 + apps/web/public/flags/nz.svg | 36 + apps/web/public/flags/om.svg | 115 +++ apps/web/public/flags/pa.svg | 14 + apps/web/public/flags/pc.svg | 33 + apps/web/public/flags/pe.svg | 4 + apps/web/public/flags/pf.svg | 19 + apps/web/public/flags/pg.svg | 9 + apps/web/public/flags/ph.svg | 6 + apps/web/public/flags/pk.svg | 15 + apps/web/public/flags/pl.svg | 6 + apps/web/public/flags/pm.svg | 5 + apps/web/public/flags/pn.svg | 53 ++ apps/web/public/flags/pr.svg | 13 + apps/web/public/flags/ps.svg | 6 + apps/web/public/flags/pt.svg | 57 ++ apps/web/public/flags/pw.svg | 11 + apps/web/public/flags/py.svg | 157 ++++ apps/web/public/flags/qa.svg | 4 + apps/web/public/flags/re.svg | 5 + apps/web/public/flags/ro.svg | 7 + apps/web/public/flags/rs.svg | 292 ++++++ apps/web/public/flags/ru.svg | 5 + apps/web/public/flags/rw.svg | 13 + apps/web/public/flags/sa.svg | 25 + apps/web/public/flags/sb.svg | 13 + apps/web/public/flags/sc.svg | 7 + apps/web/public/flags/sd.svg | 13 + apps/web/public/flags/se.svg | 4 + apps/web/public/flags/sg.svg | 13 + apps/web/public/flags/sh-ac.svg | 689 ++++++++++++++ apps/web/public/flags/sh-hl.svg | 164 ++++ apps/web/public/flags/sh-ta.svg | 76 ++ apps/web/public/flags/sh.svg | 7 + apps/web/public/flags/si.svg | 18 + apps/web/public/flags/sj.svg | 7 + apps/web/public/flags/sk.svg | 9 + apps/web/public/flags/sl.svg | 7 + apps/web/public/flags/sm.svg | 75 ++ apps/web/public/flags/sn.svg | 8 + apps/web/public/flags/so.svg | 11 + apps/web/public/flags/sr.svg | 6 + apps/web/public/flags/ss.svg | 8 + apps/web/public/flags/st.svg | 16 + apps/web/public/flags/sv.svg | 593 ++++++++++++ apps/web/public/flags/sx.svg | 56 ++ apps/web/public/flags/sy.svg | 6 + apps/web/public/flags/sz.svg | 34 + apps/web/public/flags/tc.svg | 50 + apps/web/public/flags/td.svg | 7 + apps/web/public/flags/tf.svg | 15 + apps/web/public/flags/tg.svg | 14 + apps/web/public/flags/th.svg | 7 + apps/web/public/flags/tj.svg | 22 + apps/web/public/flags/tk.svg | 5 + apps/web/public/flags/tl.svg | 13 + apps/web/public/flags/tm.svg | 204 ++++ apps/web/public/flags/tn.svg | 4 + apps/web/public/flags/to.svg | 10 + apps/web/public/flags/tr.svg | 8 + apps/web/public/flags/tt.svg | 5 + apps/web/public/flags/tv.svg | 9 + apps/web/public/flags/tw.svg | 34 + apps/web/public/flags/tz.svg | 13 + apps/web/public/flags/ua.svg | 6 + apps/web/public/flags/ug.svg | 30 + apps/web/public/flags/um.svg | 9 + apps/web/public/flags/un.svg | 16 + apps/web/public/flags/us.svg | 9 + apps/web/public/flags/uy.svg | 28 + apps/web/public/flags/uz.svg | 30 + apps/web/public/flags/va.svg | 190 ++++ apps/web/public/flags/vc.svg | 8 + apps/web/public/flags/ve.svg | 26 + apps/web/public/flags/vg.svg | 59 ++ apps/web/public/flags/vi.svg | 28 + apps/web/public/flags/vn.svg | 11 + apps/web/public/flags/vu.svg | 21 + apps/web/public/flags/wf.svg | 5 + apps/web/public/flags/ws.svg | 7 + apps/web/public/flags/xk.svg | 5 + apps/web/public/flags/xx.svg | 4 + apps/web/public/flags/ye.svg | 7 + apps/web/public/flags/yt.svg | 5 + apps/web/public/flags/za.svg | 17 + apps/web/public/flags/zm.svg | 27 + apps/web/public/flags/zw.svg | 21 + apps/web/public/shapes/circle.svg | 2 +- apps/web/public/shapes/diamond.svg | 2 +- apps/web/public/shapes/hexagon.svg | 5 +- apps/web/public/shapes/square.svg | 2 +- apps/web/public/shapes/star.svg | 5 +- apps/web/public/shapes/triangle.svg | 2 +- apps/web/src/app/blog/[slug]/page.tsx | 2 +- apps/web/src/app/blog/page.tsx | 2 +- apps/web/src/app/globals.css | 438 ++++----- apps/web/src/app/layout.tsx | 19 +- apps/web/src/app/privacy/page.tsx | 121 +-- apps/web/src/app/projects/page.tsx | 20 +- apps/web/src/app/projects/store.ts | 2 +- apps/web/src/app/terms/page.tsx | 100 +- apps/web/src/components/editable-timecode.tsx | 26 +- .../editor/dialogs/project-info-dialog.tsx | 2 +- .../editor/dialogs/shortcuts-dialog.tsx | 2 +- .../dialogs/storage-persistence-dialog.tsx | 41 + .../src/components/editor/editor-header.tsx | 7 +- .../src/components/editor/export-button.tsx | 63 +- .../web/src/components/editor/mobile-gate.tsx | 6 +- .../editor/panels/assets/drag-overlay.tsx | 2 +- .../editor/panels/assets/draggable-item.tsx | 17 +- .../editor/panels/assets/tabbar.tsx | 15 +- .../editor/panels/assets/views/assets.tsx | 153 +-- .../views/{base-view.tsx => base-panel.tsx} | 11 +- .../editor/panels/assets/views/captions.tsx | 141 +-- .../editor/panels/assets/views/effects.tsx | 15 +- .../panels/assets/views/settings-legacy.tsx | 332 ------- .../editor/panels/assets/views/settings.tsx | 168 ---- .../assets/views/settings/background.tsx | 227 +++++ .../panels/assets/views/settings/index.tsx | 369 ++++++++ .../editor/panels/assets/views/sounds.tsx | 2 +- .../editor/panels/assets/views/stickers.tsx | 538 +++++++---- .../editor/panels/assets/views/text.tsx | 12 +- .../editor/panels/preview/context-menu.tsx | 39 +- .../editor/panels/preview/guide-overlay.tsx | 32 + .../editor/panels/preview/guide-popover.tsx | 100 ++ .../panels/preview/handle-primitives.tsx | 332 +++++++ .../editor/panels/preview/index.tsx | 266 ++++-- .../panels/preview/layout-guide-overlay.tsx | 27 - .../editor/panels/preview/mask-handles.tsx | 238 +++++ .../preview/preview-interaction-overlay.tsx | 109 ++- .../panels/preview/preview-viewport.tsx | 576 ++++++++++++ .../editor/panels/preview/snap-guides.tsx | 30 +- .../panels/preview/text-edit-overlay.tsx | 149 ++- .../editor/panels/preview/toolbar.tsx | 169 +++- .../panels/preview/transform-handles.tsx | 273 ++---- .../{ => components}/keyframe-toggle.tsx | 0 .../components/property-param-field.tsx | 194 ++++ .../hooks/use-keyframed-color-property.ts | 4 +- .../hooks/use-keyframed-number-property.ts | 26 +- .../hooks/use-keyframed-param-property.ts | 148 +++ .../hooks/use-keyframed-vector-property.ts | 190 ++++ .../editor/panels/properties/index.tsx | 141 +-- .../editor/panels/properties/registry.tsx | 303 ++++++ .../properties/stores/properties-store.ts | 18 + .../panels/properties/tabs/audio-tab.tsx | 109 +++ .../panels/properties/tabs/blending-tab.tsx | 230 +++++ .../panels/properties/tabs/effects-tab.tsx | 309 ++++++ .../panels/properties/tabs/graphic-tab.tsx | 238 +++++ .../panels/properties/tabs/masks-tab.tsx | 660 +++++++++++++ .../panels/properties/tabs/speed-tab.tsx | 137 +++ .../panels/properties/tabs/text-tab.tsx | 762 +++++++++++++++ .../panels/properties/tabs/transform-tab.tsx | 424 +++++++++ .../editor/panels/timeline/audio-waveform.tsx | 281 +++--- .../editor/panels/timeline/bookmarks.tsx | 27 +- .../editor/panels/timeline/drag-line.tsx | 5 +- .../editor/panels/timeline/index.tsx | 885 +++++++++++------- .../editor/panels/timeline/snap-indicator.tsx | 10 +- .../panels/timeline/timeline-element.tsx | 472 +++++----- .../panels/timeline/timeline-playhead.tsx | 38 +- .../editor/panels/timeline/timeline-ruler.tsx | 26 +- .../editor/panels/timeline/timeline-tick.tsx | 4 +- .../panels/timeline/timeline-toolbar.tsx | 16 +- .../editor/panels/timeline/timeline-track.tsx | 62 +- .../components/providers/editor-provider.tsx | 27 +- apps/web/src/components/section.tsx | 257 +++++ apps/web/src/components/ui/button.tsx | 2 +- apps/web/src/components/ui/color-picker.tsx | 13 +- apps/web/src/components/ui/context-menu.tsx | 14 +- apps/web/src/components/ui/dialog.tsx | 16 +- apps/web/src/components/ui/dropdown-menu.tsx | 23 +- apps/web/src/components/ui/font-picker.tsx | 107 +-- .../web/src/components/ui/input-with-back.tsx | 85 -- apps/web/src/components/ui/input.tsx | 7 +- apps/web/src/components/ui/number-field.tsx | 223 ++++- apps/web/src/components/ui/popover.tsx | 20 +- apps/web/src/components/ui/select.tsx | 16 +- apps/web/src/components/ui/sheet.tsx | 17 +- apps/web/src/components/ui/sonner.tsx | 2 +- apps/web/src/components/ui/tabs.tsx | 92 +- apps/web/src/components/ui/tooltip.tsx | 4 +- .../components/ui/use-overlay-open-change.ts | 78 ++ apps/web/src/constants/editor-constants.ts | 14 + apps/web/src/constants/export-constants.ts | 2 +- apps/web/src/constants/font-constants.ts | 2 - apps/web/src/constants/guide-constants.ts | 4 + apps/web/src/constants/language-constants.ts | 3 + apps/web/src/constants/mask-constants.ts | 4 + apps/web/src/constants/project-constants.ts | 10 +- apps/web/src/constants/retime-constants.ts | 30 + apps/web/src/constants/sticker-constants.ts | 4 +- apps/web/src/constants/text-constants.ts | 42 - apps/web/src/constants/timeline-constants.ts | 85 ++ apps/web/src/constants/timeline-constants.tsx | 102 -- .../src/constants/transcription-constants.ts | 4 +- apps/web/src/core/index.ts | 7 +- apps/web/src/core/managers/audio-manager.ts | 352 ++++++- apps/web/src/core/managers/media-manager.ts | 73 +- .../web/src/core/managers/playback-manager.ts | 15 +- apps/web/src/core/managers/project-manager.ts | 49 +- .../web/src/core/managers/renderer-manager.ts | 60 +- apps/web/src/core/managers/scenes-manager.ts | 6 +- .../src/core/managers/selection-manager.ts | 9 +- .../web/src/core/managers/timeline-manager.ts | 155 ++- apps/web/src/data/colors/syntax-ui.tsx | 2 - .../src/hooks/actions/use-editor-actions.ts | 89 +- .../element/use-element-interaction.ts | 83 +- .../timeline/element/use-element-resize.ts | 231 ++++- .../timeline/element/use-element-selection.ts | 35 +- .../timeline/element/use-keyframe-drag.ts | 18 +- .../element/use-keyframe-selection.ts | 2 +- .../src/hooks/timeline/use-bookmark-drag.ts | 2 +- .../timeline/use-initial-scroll-bottom.ts | 42 + .../timeline/use-snap-indicator-position.ts | 14 +- .../hooks/timeline/use-timeline-drag-drop.ts | 233 +++-- .../hooks/timeline/use-timeline-playhead.ts | 186 ++-- .../src/hooks/timeline/use-timeline-zoom.ts | 28 +- apps/web/src/hooks/use-container-size.ts | 24 +- apps/web/src/hooks/use-editor.ts | 63 +- apps/web/src/hooks/use-effect-preview.ts | 47 - apps/web/src/hooks/use-element-preview.ts | 38 + apps/web/src/hooks/use-file-upload.ts | 12 +- apps/web/src/hooks/use-font-atlas.ts | 53 ++ apps/web/src/hooks/use-keybindings.ts | 163 +++- apps/web/src/hooks/use-mask-handles.ts | 258 +++++ apps/web/src/hooks/use-menu-preview.ts | 26 + apps/web/src/hooks/use-paste-media.ts | 87 +- apps/web/src/hooks/use-preview-interaction.ts | 349 +++++-- apps/web/src/hooks/use-resize-observer.ts | 26 + apps/web/src/hooks/use-storage-persistence.ts | 45 + apps/web/src/hooks/use-transform-handles.ts | 457 ++++++--- apps/web/src/lib/actions/definitions.ts | 27 +- .../src/{types => lib/actions}/keybinding.ts | 2 +- apps/web/src/lib/actions/registry.ts | 27 +- apps/web/src/lib/actions/types.ts | 2 + .../__tests__/transform-keyframes.test.ts | 313 ------- apps/web/src/lib/animation/color-channel.ts | 2 +- .../src/lib/animation/effect-param-channel.ts | 55 +- .../lib/animation/graphic-param-channel.ts | 79 ++ apps/web/src/lib/animation/index.ts | 32 +- apps/web/src/lib/animation/interpolation.ts | 71 +- apps/web/src/lib/animation/keyframe-query.ts | 17 +- apps/web/src/lib/animation/keyframes.ts | 231 +++-- apps/web/src/lib/animation/number-channel.ts | 2 +- apps/web/src/lib/animation/property-groups.ts | 39 + .../src/lib/animation/property-registry.ts | 93 +- apps/web/src/lib/animation/resolve.ts | 69 +- apps/web/src/lib/animation/target-resolver.ts | 279 ++++++ .../animation.ts => lib/animation/types.ts} | 40 +- apps/web/src/lib/animation/vector-channel.ts | 72 ++ apps/web/src/lib/blog/query.ts | 2 +- .../src/{types/blog.ts => lib/blog/types.ts} | 0 apps/web/src/lib/cancel-interaction.ts | 24 + .../__tests__/keyframe-aware-commands.test.ts | 433 --------- apps/web/src/lib/commands/index.ts | 1 - .../src/lib/commands/media/add-media-asset.ts | 34 +- .../lib/commands/media/remove-media-asset.ts | 34 +- .../project/update-project-settings.ts | 2 +- .../src/lib/commands/scene/create-scene.ts | 2 +- .../src/lib/commands/scene/delete-scene.ts | 2 +- .../src/lib/commands/scene/move-bookmark.ts | 2 +- .../src/lib/commands/scene/remove-bookmark.ts | 2 +- .../src/lib/commands/scene/rename-scene.ts | 2 +- .../src/lib/commands/scene/toggle-bookmark.ts | 2 +- .../src/lib/commands/scene/update-bookmark.ts | 2 +- .../lib/commands/timeline/clipboard/paste.ts | 2 +- .../timeline/element/delete-elements.ts | 2 +- .../timeline/element/duplicate-elements.ts | 2 +- .../timeline/element/effects/add-effect.ts | 2 +- .../timeline/element/effects/remove-effect.ts | 2 +- .../element/effects/reorder-effect.ts | 2 +- .../timeline/element/effects/toggle-effect.ts | 2 +- .../element/effects/update-effect-params.ts | 22 +- .../lib/commands/timeline/element/index.ts | 2 + .../timeline/element/insert-element.ts | 20 +- .../keyframes/remove-effect-param-keyframe.ts | 2 +- .../element/keyframes/remove-keyframe.ts | 45 +- .../element/keyframes/retime-keyframe.ts | 20 +- .../keyframes/upsert-effect-param-keyframe.ts | 2 +- .../element/keyframes/upsert-keyframe.ts | 30 +- .../commands/timeline/element/masks/index.ts | 2 + .../timeline/element/masks/remove-mask.ts | 64 ++ .../element/masks/toggle-mask-inverted.ts | 75 ++ .../timeline/element/move-elements.ts | 2 +- .../commands/timeline/element/retime/index.ts | 1 + .../element/retime/update-element-retime.ts | 114 +++ .../timeline/element/split-elements.ts | 107 ++- .../timeline/element/toggle-elements-muted.ts | 2 +- .../element/toggle-elements-visibility.ts | 2 +- .../element/update-element-duration.ts | 2 +- .../element/update-element-start-time.ts | 2 +- .../timeline/element/update-element-trim.ts | 25 +- .../timeline/element/update-element.ts | 2 +- .../lib/commands/timeline/track/add-track.ts | 2 +- .../commands/timeline/track/remove-track.ts | 2 +- .../timeline/track/toggle-track-mute.ts | 2 +- .../timeline/track/toggle-track-visibility.ts | 2 +- .../lib/commands/timeline/tracks-snapshot.ts | 2 +- apps/web/src/lib/drag-data.ts | 2 +- .../lib/effects/definitions/blur.frag.glsl | 10 +- apps/web/src/lib/effects/definitions/blur.ts | 109 ++- apps/web/src/lib/effects/definitions/index.ts | 6 +- apps/web/src/lib/effects/index.ts | 45 +- apps/web/src/lib/effects/registry.ts | 33 +- apps/web/src/lib/effects/types.ts | 42 + apps/web/src/lib/export.ts | 33 +- apps/web/src/lib/fonts/google-fonts.ts | 26 +- .../{types/fonts.ts => lib/fonts/types.ts} | 0 .../src/lib/graphics/definitions/ellipse.ts | 73 ++ .../web/src/lib/graphics/definitions/index.ts | 29 + .../src/lib/graphics/definitions/polygon.ts | 211 +++++ .../src/lib/graphics/definitions/rectangle.ts | 85 ++ .../src/lib/graphics/definitions/shared.ts | 16 + apps/web/src/lib/graphics/definitions/star.ts | 109 +++ apps/web/src/lib/graphics/index.ts | 125 +++ apps/web/src/lib/graphics/registry.ts | 10 + apps/web/src/lib/graphics/stroke.ts | 102 ++ apps/web/src/lib/graphics/types.ts | 23 + .../web/src/lib/guides/definitions/custom.tsx | 24 + apps/web/src/lib/guides/definitions/grid.tsx | 125 +++ .../src/lib/guides/definitions/platforms.tsx | 65 ++ .../lib/guides/definitions/tiktok-layout.tsx | 335 +++++++ apps/web/src/lib/guides/index.ts | 13 + apps/web/src/lib/guides/registry.tsx | 28 + apps/web/src/lib/guides/types.ts | 20 + apps/web/src/lib/iconify-api.ts | 241 ----- apps/web/src/lib/masks/__tests__/snap.test.ts | 235 +++++ .../web/src/lib/masks/definitions/box-like.ts | 270 ++++++ apps/web/src/lib/masks/definitions/ellipse.ts | 72 ++ apps/web/src/lib/masks/definitions/index.ts | 39 + .../src/lib/masks/definitions/rectangle.ts | 94 ++ apps/web/src/lib/masks/definitions/split.ts | 347 +++++++ apps/web/src/lib/masks/geometry.ts | 112 +++ apps/web/src/lib/masks/handle-positions.ts | 382 ++++++++ apps/web/src/lib/masks/index.ts | 18 + apps/web/src/lib/masks/param-update.ts | 59 ++ apps/web/src/lib/masks/registry.ts | 70 ++ .../lib/masks/shaders/jfa-distance.frag.glsl | 36 + apps/web/src/lib/masks/snap.ts | 335 +++++++ apps/web/src/lib/masks/types.ts | 115 +++ apps/web/src/lib/masks/utils.ts | 64 ++ apps/web/src/lib/media/audio-mastering.ts | 103 ++ apps/web/src/lib/media/audio.ts | 249 ++++- apps/web/src/lib/media/media-utils.ts | 2 +- apps/web/src/lib/media/mediabunny.ts | 132 +-- apps/web/src/lib/media/processing.ts | 90 +- .../{types/assets.ts => lib/media/types.ts} | 0 apps/web/src/lib/media/upload-toast.ts | 51 + apps/web/src/lib/params.ts | 50 + apps/web/src/lib/preview/element-bounds.ts | 259 ++--- apps/web/src/lib/preview/hit-test.ts | 54 +- apps/web/src/lib/preview/preview-coords.ts | 99 +- apps/web/src/lib/preview/preview-snap.ts | 293 +++++- .../project.ts => lib/project/types.ts} | 4 +- apps/web/src/lib/registry.ts | 40 + apps/web/src/{types => lib}/rendering.ts | 3 +- .../src/lib/retime/__tests__/resolve.test.ts | 61 ++ .../src/lib/retime/__tests__/split.test.ts | 31 + apps/web/src/lib/retime/audio-stretch.ts | 182 ++++ apps/web/src/lib/retime/index.ts | 4 + apps/web/src/lib/retime/presets.ts | 12 + apps/web/src/lib/retime/resolve.ts | 48 + apps/web/src/lib/retime/split.ts | 34 + apps/web/src/lib/scenes.ts | 2 +- apps/web/src/lib/selection/constants.ts | 1 + apps/web/src/lib/selection/context.tsx | 52 + apps/web/src/lib/selection/hit-testing.ts | 50 + .../src/lib/selection/hooks/use-box-select.ts | 170 ++++ .../selection/hooks/use-selection-scope.ts | 28 + apps/web/src/lib/selection/index.ts | 4 + apps/web/src/lib/selection/scope.ts | 29 + .../web/src/lib/selection/selectable-item.tsx | 107 +++ .../src/lib/selection/selectable-surface.tsx | 288 ++++++ .../selection}/selection-box.tsx | 0 apps/web/src/lib/selection/state.ts | 165 ++++ apps/web/src/lib/selection/types.ts | 39 + apps/web/src/lib/shaders/jfa-init.frag.glsl | 25 + apps/web/src/lib/shaders/jfa-step.frag.glsl | 60 ++ .../{types/sounds.ts => lib/sounds/types.ts} | 0 .../lib/stickers/__tests__/sticker-id.test.ts | 14 +- apps/web/src/lib/stickers/index.ts | 230 ++++- .../lib/stickers/providers/countries-data.ts} | 57 +- apps/web/src/lib/stickers/providers/emoji.ts | 119 --- apps/web/src/lib/stickers/providers/flags.ts | 97 +- apps/web/src/lib/stickers/providers/icons.ts | 122 --- apps/web/src/lib/stickers/providers/index.ts | 14 +- apps/web/src/lib/stickers/providers/logos.ts | 31 + apps/web/src/lib/stickers/providers/shapes.ts | 160 +++- apps/web/src/lib/stickers/registry.ts | 33 +- apps/web/src/lib/stickers/resolver.ts | 8 +- apps/web/src/lib/stickers/types.ts | 79 +- apps/web/src/lib/text/layout.ts | 29 +- apps/web/src/lib/text/measure-element.ts | 132 +++ apps/web/src/lib/time.ts | 6 +- apps/web/src/lib/timeline/audio-constants.ts | 2 + apps/web/src/lib/timeline/audio-state.ts | 100 ++ apps/web/src/lib/timeline/bookmarks.ts | 2 +- apps/web/src/lib/timeline/defaults.ts | 77 ++ apps/web/src/{types => lib/timeline}/drag.ts | 12 +- apps/web/src/lib/timeline/drop-utils.ts | 4 +- apps/web/src/lib/timeline/element-utils.ts | 241 ++--- apps/web/src/lib/timeline/index.ts | 4 +- apps/web/src/lib/timeline/ripple-utils.ts | 2 +- .../src/lib/timeline/selection-hit-testing.ts | 133 +++ apps/web/src/lib/timeline/snap-utils.ts | 2 +- .../src/lib/timeline/track-element-update.ts | 2 +- apps/web/src/lib/timeline/track-utils.ts | 29 +- .../timeline.ts => lib/timeline/types.ts} | 90 +- apps/web/src/lib/transcription/caption.ts | 2 +- .../transcription/types.ts} | 2 +- .../src/services/renderer/effect-preview.ts | 335 ++++--- .../web/src/services/renderer/mask-feather.ts | 54 ++ .../renderer/nodes/blur-background-node.ts | 149 +++ .../renderer/nodes/composite-effect-node.ts | 77 -- .../renderer/nodes/effect-layer-node.ts | 29 +- .../services/renderer/nodes/graphic-node.ts | 92 ++ .../src/services/renderer/nodes/image-node.ts | 4 +- .../services/renderer/nodes/sticker-node.ts | 20 +- .../src/services/renderer/nodes/text-node.ts | 187 ++-- .../src/services/renderer/nodes/video-node.ts | 1 + .../services/renderer/nodes/visual-node.ts | 225 ++++- .../src/services/renderer/scene-builder.ts | 122 ++- .../src/services/renderer/scene-exporter.ts | 2 +- .../renderer/webgl-effect-renderer.ts | 73 -- apps/web/src/services/renderer/webgl/jfa.ts | 194 ++++ .../services/renderer/webgl/webgl-context.ts | 49 + .../renderer/webgl/webgl-effect-renderer.ts | 35 + .../renderer/{ => webgl}/webgl-utils.ts | 0 .../migrations/__tests__/v15-to-v16.test.ts | 93 ++ .../migrations/__tests__/v16-to-v17.test.ts | 132 +++ .../migrations/__tests__/v18-to-v19.test.ts | 63 ++ .../src/services/storage/migrations/index.ts | 22 +- .../storage/migrations/transformers/index.ts | 1 + .../migrations/transformers/v0-to-v1.ts | 13 +- .../migrations/transformers/v1-to-v2.ts | 144 ++- .../migrations/transformers/v10-to-v11.ts | 113 +++ .../migrations/transformers/v11-to-v12.ts | 196 ++++ .../migrations/transformers/v12-to-v13.ts | 102 ++ .../migrations/transformers/v13-to-v14.ts | 106 +++ .../migrations/transformers/v14-to-v15.ts | 67 ++ .../migrations/transformers/v15-to-v16.ts | 60 ++ .../migrations/transformers/v16-to-v17.ts | 107 +++ .../migrations/transformers/v17-to-v18.ts | 105 +++ .../migrations/transformers/v18-to-v19.ts | 46 + .../migrations/transformers/v2-to-v3.ts | 37 +- .../migrations/transformers/v9-to-v10.ts | 21 + .../services/storage/migrations/v10-to-v11.ts | 16 + .../services/storage/migrations/v11-to-v12.ts | 16 + .../services/storage/migrations/v12-to-v13.ts | 16 + .../services/storage/migrations/v13-to-v14.ts | 16 + .../services/storage/migrations/v14-to-v15.ts | 16 + .../services/storage/migrations/v15-to-v16.ts | 16 + .../services/storage/migrations/v16-to-v17.ts | 16 + .../services/storage/migrations/v17-to-v18.ts | 16 + .../services/storage/migrations/v18-to-v19.ts | 16 + .../services/storage/migrations/v9-to-v10.ts | 16 + apps/web/src/services/storage/quota.ts | 145 +++ apps/web/src/services/storage/service.ts | 52 +- apps/web/src/services/storage/types.ts | 7 +- .../web/src/services/transcription/service.ts | 2 +- apps/web/src/services/transcription/worker.ts | 2 +- apps/web/src/stores/editor-store.ts | 2 +- apps/web/src/stores/keybindings-store.ts | 158 +++- .../stores/keybindings/migrations/index.ts | 4 +- .../stores/keybindings/migrations/v2-to-v3.ts | 2 +- .../stores/keybindings/migrations/v3-to-v4.ts | 4 +- .../stores/keybindings/migrations/v4-to-v5.ts | 2 +- .../stores/keybindings/migrations/v5-to-v6.ts | 17 + apps/web/src/stores/preview-store.ts | 72 +- apps/web/src/stores/sounds-store.ts | 2 +- apps/web/src/stores/stickers-store.ts | 181 ++-- apps/web/src/stores/timeline-store.ts | 2 +- apps/web/src/types/editor.ts | 1 - apps/web/src/types/effects.ts | 69 -- apps/web/src/types/export.ts | 31 - apps/web/src/types/language.ts | 4 - apps/web/src/types/soundtouchjs.d.ts | 14 + apps/web/src/types/stickers.ts | 54 -- apps/web/src/types/time.ts | 1 - apps/web/src/utils/browser.ts | 14 + apps/web/src/utils/math.ts | 45 + apps/web/tsconfig.tsbuildinfo | 2 +- biome.json | 6 + bun.lock | 213 +---- docs/effects-renderer.md | 56 +- .../properties/audio-properties.tsx | 0 .../properties/clip-effects-properties.tsx | 0 .../properties/effect-param-field.tsx | 0 .../properties/effect-properties.tsx | 0 .../components/properties/keyframe-toggle.tsx | 32 + .../components}/properties/section.tsx | 0 .../properties/text-properties.tsx | 0 .../properties/video-properties.tsx | 0 .../sections/blending.tsx | 0 .../properties => legacy}/sections/index.tsx | 0 .../sections/transform.tsx | 0 .../timeline/use-selection-box.ts | 32 +- legacy/use-assets-selection-box.ts | 198 ++++ legacy/use-assets-selection.ts | 209 +++++ legacy/use-element-registry.ts | 31 + .../src/hooks => legacy}/use-reveal-item.ts | 18 +- package.json | 3 +- packages/ui/src/icons/ui.tsx | 144 +++ 690 files changed, 35586 insertions(+), 7305 deletions(-) create mode 100644 apps/web/public/flags/ad.svg create mode 100644 apps/web/public/flags/ae.svg create mode 100644 apps/web/public/flags/af.svg create mode 100644 apps/web/public/flags/ag.svg create mode 100644 apps/web/public/flags/ai.svg create mode 100644 apps/web/public/flags/al.svg create mode 100644 apps/web/public/flags/am.svg create mode 100644 apps/web/public/flags/ao.svg create mode 100644 apps/web/public/flags/aq.svg create mode 100644 apps/web/public/flags/ar.svg create mode 100644 apps/web/public/flags/arab.svg create mode 100644 apps/web/public/flags/as.svg create mode 100644 apps/web/public/flags/asean.svg create mode 100644 apps/web/public/flags/at.svg create mode 100644 apps/web/public/flags/au.svg create mode 100644 apps/web/public/flags/aw.svg create mode 100644 apps/web/public/flags/ax.svg create mode 100644 apps/web/public/flags/az.svg create mode 100644 apps/web/public/flags/ba.svg create mode 100644 apps/web/public/flags/bb.svg create mode 100644 apps/web/public/flags/bd.svg create mode 100644 apps/web/public/flags/be.svg create mode 100644 apps/web/public/flags/bf.svg create mode 100644 apps/web/public/flags/bg.svg create mode 100644 apps/web/public/flags/bh.svg create mode 100644 apps/web/public/flags/bi.svg create mode 100644 apps/web/public/flags/bj.svg create mode 100644 apps/web/public/flags/bl.svg create mode 100644 apps/web/public/flags/bm.svg create mode 100644 apps/web/public/flags/bn.svg create mode 100644 apps/web/public/flags/bo.svg create mode 100644 apps/web/public/flags/bq.svg create mode 100644 apps/web/public/flags/br.svg create mode 100644 apps/web/public/flags/bs.svg create mode 100644 apps/web/public/flags/bt.svg create mode 100644 apps/web/public/flags/bv.svg create mode 100644 apps/web/public/flags/bw.svg create mode 100644 apps/web/public/flags/by.svg create mode 100644 apps/web/public/flags/bz.svg create mode 100644 apps/web/public/flags/ca.svg create mode 100644 apps/web/public/flags/cc.svg create mode 100644 apps/web/public/flags/cd.svg create mode 100644 apps/web/public/flags/cefta.svg create mode 100644 apps/web/public/flags/cf.svg create mode 100644 apps/web/public/flags/cg.svg create mode 100644 apps/web/public/flags/ch.svg create mode 100644 apps/web/public/flags/ci.svg create mode 100644 apps/web/public/flags/ck.svg create mode 100644 apps/web/public/flags/cl.svg create mode 100644 apps/web/public/flags/cm.svg create mode 100644 apps/web/public/flags/cn.svg create mode 100644 apps/web/public/flags/co.svg create mode 100644 apps/web/public/flags/cp.svg create mode 100644 apps/web/public/flags/cr.svg create mode 100644 apps/web/public/flags/cu.svg create mode 100644 apps/web/public/flags/cv.svg create mode 100644 apps/web/public/flags/cw.svg create mode 100644 apps/web/public/flags/cx.svg create mode 100644 apps/web/public/flags/cy.svg create mode 100644 apps/web/public/flags/cz.svg create mode 100644 apps/web/public/flags/de.svg create mode 100644 apps/web/public/flags/dg.svg create mode 100644 apps/web/public/flags/dj.svg create mode 100644 apps/web/public/flags/dk.svg create mode 100644 apps/web/public/flags/dm.svg create mode 100644 apps/web/public/flags/do.svg create mode 100644 apps/web/public/flags/dz.svg create mode 100644 apps/web/public/flags/eac.svg create mode 100644 apps/web/public/flags/ec.svg create mode 100644 apps/web/public/flags/ee.svg create mode 100644 apps/web/public/flags/eg.svg create mode 100644 apps/web/public/flags/eh.svg create mode 100644 apps/web/public/flags/er.svg create mode 100644 apps/web/public/flags/es-ct.svg create mode 100644 apps/web/public/flags/es-ga.svg create mode 100644 apps/web/public/flags/es-pv.svg create mode 100644 apps/web/public/flags/es.svg create mode 100644 apps/web/public/flags/et.svg create mode 100644 apps/web/public/flags/eu.svg create mode 100644 apps/web/public/flags/fi.svg create mode 100644 apps/web/public/flags/fj.svg create mode 100644 apps/web/public/flags/fk.svg create mode 100644 apps/web/public/flags/fm.svg create mode 100644 apps/web/public/flags/fo.svg create mode 100644 apps/web/public/flags/fr.svg create mode 100644 apps/web/public/flags/ga.svg create mode 100644 apps/web/public/flags/gb-eng.svg create mode 100644 apps/web/public/flags/gb-nir.svg create mode 100644 apps/web/public/flags/gb-sct.svg create mode 100644 apps/web/public/flags/gb-wls.svg create mode 100644 apps/web/public/flags/gb.svg create mode 100644 apps/web/public/flags/gd.svg create mode 100644 apps/web/public/flags/ge.svg create mode 100644 apps/web/public/flags/gf.svg create mode 100644 apps/web/public/flags/gg.svg create mode 100644 apps/web/public/flags/gh.svg create mode 100644 apps/web/public/flags/gi.svg create mode 100644 apps/web/public/flags/gl.svg create mode 100644 apps/web/public/flags/gm.svg create mode 100644 apps/web/public/flags/gn.svg create mode 100644 apps/web/public/flags/gp.svg create mode 100644 apps/web/public/flags/gq.svg create mode 100644 apps/web/public/flags/gr.svg create mode 100644 apps/web/public/flags/gs.svg create mode 100644 apps/web/public/flags/gt.svg create mode 100644 apps/web/public/flags/gu.svg create mode 100644 apps/web/public/flags/gw.svg create mode 100644 apps/web/public/flags/gy.svg create mode 100644 apps/web/public/flags/hk.svg create mode 100644 apps/web/public/flags/hm.svg create mode 100644 apps/web/public/flags/hn.svg create mode 100644 apps/web/public/flags/hr.svg create mode 100644 apps/web/public/flags/ht.svg create mode 100644 apps/web/public/flags/hu.svg create mode 100644 apps/web/public/flags/ic.svg create mode 100644 apps/web/public/flags/id.svg create mode 100644 apps/web/public/flags/ie.svg create mode 100644 apps/web/public/flags/il.svg create mode 100644 apps/web/public/flags/im.svg create mode 100644 apps/web/public/flags/in.svg create mode 100644 apps/web/public/flags/io.svg create mode 100644 apps/web/public/flags/iq.svg create mode 100644 apps/web/public/flags/ir.svg create mode 100644 apps/web/public/flags/is.svg create mode 100644 apps/web/public/flags/it.svg create mode 100644 apps/web/public/flags/je.svg create mode 100644 apps/web/public/flags/jm.svg create mode 100644 apps/web/public/flags/jo.svg create mode 100644 apps/web/public/flags/jp.svg create mode 100644 apps/web/public/flags/ke.svg create mode 100644 apps/web/public/flags/kg.svg create mode 100644 apps/web/public/flags/kh.svg create mode 100644 apps/web/public/flags/ki.svg create mode 100644 apps/web/public/flags/km.svg create mode 100644 apps/web/public/flags/kn.svg create mode 100644 apps/web/public/flags/kp.svg create mode 100644 apps/web/public/flags/kr.svg create mode 100644 apps/web/public/flags/kw.svg create mode 100644 apps/web/public/flags/ky.svg create mode 100644 apps/web/public/flags/kz.svg create mode 100644 apps/web/public/flags/la.svg create mode 100644 apps/web/public/flags/lb.svg create mode 100644 apps/web/public/flags/lc.svg create mode 100644 apps/web/public/flags/li.svg create mode 100644 apps/web/public/flags/lk.svg create mode 100644 apps/web/public/flags/lr.svg create mode 100644 apps/web/public/flags/ls.svg create mode 100644 apps/web/public/flags/lt.svg create mode 100644 apps/web/public/flags/lu.svg create mode 100644 apps/web/public/flags/lv.svg create mode 100644 apps/web/public/flags/ly.svg create mode 100644 apps/web/public/flags/ma.svg create mode 100644 apps/web/public/flags/mc.svg create mode 100644 apps/web/public/flags/md.svg create mode 100644 apps/web/public/flags/me.svg create mode 100644 apps/web/public/flags/mf.svg create mode 100644 apps/web/public/flags/mg.svg create mode 100644 apps/web/public/flags/mh.svg create mode 100644 apps/web/public/flags/mk.svg create mode 100644 apps/web/public/flags/ml.svg create mode 100644 apps/web/public/flags/mm.svg create mode 100644 apps/web/public/flags/mn.svg create mode 100644 apps/web/public/flags/mo.svg create mode 100644 apps/web/public/flags/mp.svg create mode 100644 apps/web/public/flags/mq.svg create mode 100644 apps/web/public/flags/mr.svg create mode 100644 apps/web/public/flags/ms.svg create mode 100644 apps/web/public/flags/mt.svg create mode 100644 apps/web/public/flags/mu.svg create mode 100644 apps/web/public/flags/mv.svg create mode 100644 apps/web/public/flags/mw.svg create mode 100644 apps/web/public/flags/mx.svg create mode 100644 apps/web/public/flags/my.svg create mode 100644 apps/web/public/flags/mz.svg create mode 100644 apps/web/public/flags/na.svg create mode 100644 apps/web/public/flags/nc.svg create mode 100644 apps/web/public/flags/ne.svg create mode 100644 apps/web/public/flags/nf.svg create mode 100644 apps/web/public/flags/ng.svg create mode 100644 apps/web/public/flags/ni.svg create mode 100644 apps/web/public/flags/nl.svg create mode 100644 apps/web/public/flags/no.svg create mode 100644 apps/web/public/flags/np.svg create mode 100644 apps/web/public/flags/nr.svg create mode 100644 apps/web/public/flags/nu.svg create mode 100644 apps/web/public/flags/nz.svg create mode 100644 apps/web/public/flags/om.svg create mode 100644 apps/web/public/flags/pa.svg create mode 100644 apps/web/public/flags/pc.svg create mode 100644 apps/web/public/flags/pe.svg create mode 100644 apps/web/public/flags/pf.svg create mode 100644 apps/web/public/flags/pg.svg create mode 100644 apps/web/public/flags/ph.svg create mode 100644 apps/web/public/flags/pk.svg create mode 100644 apps/web/public/flags/pl.svg create mode 100644 apps/web/public/flags/pm.svg create mode 100644 apps/web/public/flags/pn.svg create mode 100644 apps/web/public/flags/pr.svg create mode 100644 apps/web/public/flags/ps.svg create mode 100644 apps/web/public/flags/pt.svg create mode 100644 apps/web/public/flags/pw.svg create mode 100644 apps/web/public/flags/py.svg create mode 100644 apps/web/public/flags/qa.svg create mode 100644 apps/web/public/flags/re.svg create mode 100644 apps/web/public/flags/ro.svg create mode 100644 apps/web/public/flags/rs.svg create mode 100644 apps/web/public/flags/ru.svg create mode 100644 apps/web/public/flags/rw.svg create mode 100644 apps/web/public/flags/sa.svg create mode 100644 apps/web/public/flags/sb.svg create mode 100644 apps/web/public/flags/sc.svg create mode 100644 apps/web/public/flags/sd.svg create mode 100644 apps/web/public/flags/se.svg create mode 100644 apps/web/public/flags/sg.svg create mode 100644 apps/web/public/flags/sh-ac.svg create mode 100644 apps/web/public/flags/sh-hl.svg create mode 100644 apps/web/public/flags/sh-ta.svg create mode 100644 apps/web/public/flags/sh.svg create mode 100644 apps/web/public/flags/si.svg create mode 100644 apps/web/public/flags/sj.svg create mode 100644 apps/web/public/flags/sk.svg create mode 100644 apps/web/public/flags/sl.svg create mode 100644 apps/web/public/flags/sm.svg create mode 100644 apps/web/public/flags/sn.svg create mode 100644 apps/web/public/flags/so.svg create mode 100644 apps/web/public/flags/sr.svg create mode 100644 apps/web/public/flags/ss.svg create mode 100644 apps/web/public/flags/st.svg create mode 100644 apps/web/public/flags/sv.svg create mode 100644 apps/web/public/flags/sx.svg create mode 100644 apps/web/public/flags/sy.svg create mode 100644 apps/web/public/flags/sz.svg create mode 100644 apps/web/public/flags/tc.svg create mode 100644 apps/web/public/flags/td.svg create mode 100644 apps/web/public/flags/tf.svg create mode 100644 apps/web/public/flags/tg.svg create mode 100644 apps/web/public/flags/th.svg create mode 100644 apps/web/public/flags/tj.svg create mode 100644 apps/web/public/flags/tk.svg create mode 100644 apps/web/public/flags/tl.svg create mode 100644 apps/web/public/flags/tm.svg create mode 100644 apps/web/public/flags/tn.svg create mode 100644 apps/web/public/flags/to.svg create mode 100644 apps/web/public/flags/tr.svg create mode 100644 apps/web/public/flags/tt.svg create mode 100644 apps/web/public/flags/tv.svg create mode 100644 apps/web/public/flags/tw.svg create mode 100644 apps/web/public/flags/tz.svg create mode 100644 apps/web/public/flags/ua.svg create mode 100644 apps/web/public/flags/ug.svg create mode 100644 apps/web/public/flags/um.svg create mode 100644 apps/web/public/flags/un.svg create mode 100644 apps/web/public/flags/us.svg create mode 100644 apps/web/public/flags/uy.svg create mode 100644 apps/web/public/flags/uz.svg create mode 100644 apps/web/public/flags/va.svg create mode 100644 apps/web/public/flags/vc.svg create mode 100644 apps/web/public/flags/ve.svg create mode 100644 apps/web/public/flags/vg.svg create mode 100644 apps/web/public/flags/vi.svg create mode 100644 apps/web/public/flags/vn.svg create mode 100644 apps/web/public/flags/vu.svg create mode 100644 apps/web/public/flags/wf.svg create mode 100644 apps/web/public/flags/ws.svg create mode 100644 apps/web/public/flags/xk.svg create mode 100644 apps/web/public/flags/xx.svg create mode 100644 apps/web/public/flags/ye.svg create mode 100644 apps/web/public/flags/yt.svg create mode 100644 apps/web/public/flags/za.svg create mode 100644 apps/web/public/flags/zm.svg create mode 100644 apps/web/public/flags/zw.svg create mode 100644 apps/web/src/components/editor/dialogs/storage-persistence-dialog.tsx rename apps/web/src/components/editor/panels/assets/views/{base-view.tsx => base-panel.tsx} (77%) delete mode 100644 apps/web/src/components/editor/panels/assets/views/settings-legacy.tsx delete mode 100644 apps/web/src/components/editor/panels/assets/views/settings.tsx create mode 100644 apps/web/src/components/editor/panels/assets/views/settings/background.tsx create mode 100644 apps/web/src/components/editor/panels/assets/views/settings/index.tsx create mode 100644 apps/web/src/components/editor/panels/preview/guide-overlay.tsx create mode 100644 apps/web/src/components/editor/panels/preview/guide-popover.tsx create mode 100644 apps/web/src/components/editor/panels/preview/handle-primitives.tsx delete mode 100644 apps/web/src/components/editor/panels/preview/layout-guide-overlay.tsx create mode 100644 apps/web/src/components/editor/panels/preview/mask-handles.tsx create mode 100644 apps/web/src/components/editor/panels/preview/preview-viewport.tsx rename apps/web/src/components/editor/panels/properties/{ => components}/keyframe-toggle.tsx (100%) create mode 100644 apps/web/src/components/editor/panels/properties/components/property-param-field.tsx create mode 100644 apps/web/src/components/editor/panels/properties/hooks/use-keyframed-param-property.ts create mode 100644 apps/web/src/components/editor/panels/properties/hooks/use-keyframed-vector-property.ts create mode 100644 apps/web/src/components/editor/panels/properties/registry.tsx create mode 100644 apps/web/src/components/editor/panels/properties/stores/properties-store.ts create mode 100644 apps/web/src/components/editor/panels/properties/tabs/audio-tab.tsx create mode 100644 apps/web/src/components/editor/panels/properties/tabs/blending-tab.tsx create mode 100644 apps/web/src/components/editor/panels/properties/tabs/effects-tab.tsx create mode 100644 apps/web/src/components/editor/panels/properties/tabs/graphic-tab.tsx create mode 100644 apps/web/src/components/editor/panels/properties/tabs/masks-tab.tsx create mode 100644 apps/web/src/components/editor/panels/properties/tabs/speed-tab.tsx create mode 100644 apps/web/src/components/editor/panels/properties/tabs/text-tab.tsx create mode 100644 apps/web/src/components/editor/panels/properties/tabs/transform-tab.tsx create mode 100644 apps/web/src/components/section.tsx delete mode 100644 apps/web/src/components/ui/input-with-back.tsx create mode 100644 apps/web/src/components/ui/use-overlay-open-change.ts create mode 100644 apps/web/src/constants/guide-constants.ts create mode 100644 apps/web/src/constants/mask-constants.ts create mode 100644 apps/web/src/constants/retime-constants.ts create mode 100644 apps/web/src/constants/timeline-constants.ts delete mode 100644 apps/web/src/constants/timeline-constants.tsx create mode 100644 apps/web/src/hooks/timeline/use-initial-scroll-bottom.ts delete mode 100644 apps/web/src/hooks/use-effect-preview.ts create mode 100644 apps/web/src/hooks/use-element-preview.ts create mode 100644 apps/web/src/hooks/use-font-atlas.ts create mode 100644 apps/web/src/hooks/use-mask-handles.ts create mode 100644 apps/web/src/hooks/use-menu-preview.ts create mode 100644 apps/web/src/hooks/use-resize-observer.ts create mode 100644 apps/web/src/hooks/use-storage-persistence.ts rename apps/web/src/{types => lib/actions}/keybinding.ts (94%) delete mode 100644 apps/web/src/lib/animation/__tests__/transform-keyframes.test.ts create mode 100644 apps/web/src/lib/animation/graphic-param-channel.ts create mode 100644 apps/web/src/lib/animation/property-groups.ts create mode 100644 apps/web/src/lib/animation/target-resolver.ts rename apps/web/src/{types/animation.ts => lib/animation/types.ts} (68%) create mode 100644 apps/web/src/lib/animation/vector-channel.ts rename apps/web/src/{types/blog.ts => lib/blog/types.ts} (100%) create mode 100644 apps/web/src/lib/cancel-interaction.ts delete mode 100644 apps/web/src/lib/commands/__tests__/keyframe-aware-commands.test.ts create mode 100644 apps/web/src/lib/commands/timeline/element/masks/index.ts create mode 100644 apps/web/src/lib/commands/timeline/element/masks/remove-mask.ts create mode 100644 apps/web/src/lib/commands/timeline/element/masks/toggle-mask-inverted.ts create mode 100644 apps/web/src/lib/commands/timeline/element/retime/index.ts create mode 100644 apps/web/src/lib/commands/timeline/element/retime/update-element-retime.ts create mode 100644 apps/web/src/lib/effects/types.ts rename apps/web/src/{types/fonts.ts => lib/fonts/types.ts} (100%) create mode 100644 apps/web/src/lib/graphics/definitions/ellipse.ts create mode 100644 apps/web/src/lib/graphics/definitions/index.ts create mode 100644 apps/web/src/lib/graphics/definitions/polygon.ts create mode 100644 apps/web/src/lib/graphics/definitions/rectangle.ts create mode 100644 apps/web/src/lib/graphics/definitions/shared.ts create mode 100644 apps/web/src/lib/graphics/definitions/star.ts create mode 100644 apps/web/src/lib/graphics/index.ts create mode 100644 apps/web/src/lib/graphics/registry.ts create mode 100644 apps/web/src/lib/graphics/stroke.ts create mode 100644 apps/web/src/lib/graphics/types.ts create mode 100644 apps/web/src/lib/guides/definitions/custom.tsx create mode 100644 apps/web/src/lib/guides/definitions/grid.tsx create mode 100644 apps/web/src/lib/guides/definitions/platforms.tsx create mode 100644 apps/web/src/lib/guides/definitions/tiktok-layout.tsx create mode 100644 apps/web/src/lib/guides/index.ts create mode 100644 apps/web/src/lib/guides/registry.tsx create mode 100644 apps/web/src/lib/guides/types.ts delete mode 100644 apps/web/src/lib/iconify-api.ts create mode 100644 apps/web/src/lib/masks/__tests__/snap.test.ts create mode 100644 apps/web/src/lib/masks/definitions/box-like.ts create mode 100644 apps/web/src/lib/masks/definitions/ellipse.ts create mode 100644 apps/web/src/lib/masks/definitions/index.ts create mode 100644 apps/web/src/lib/masks/definitions/rectangle.ts create mode 100644 apps/web/src/lib/masks/definitions/split.ts create mode 100644 apps/web/src/lib/masks/geometry.ts create mode 100644 apps/web/src/lib/masks/handle-positions.ts create mode 100644 apps/web/src/lib/masks/index.ts create mode 100644 apps/web/src/lib/masks/param-update.ts create mode 100644 apps/web/src/lib/masks/registry.ts create mode 100644 apps/web/src/lib/masks/shaders/jfa-distance.frag.glsl create mode 100644 apps/web/src/lib/masks/snap.ts create mode 100644 apps/web/src/lib/masks/types.ts create mode 100644 apps/web/src/lib/masks/utils.ts create mode 100644 apps/web/src/lib/media/audio-mastering.ts rename apps/web/src/{types/assets.ts => lib/media/types.ts} (100%) create mode 100644 apps/web/src/lib/media/upload-toast.ts create mode 100644 apps/web/src/lib/params.ts rename apps/web/src/{types/project.ts => lib/project/types.ts} (87%) create mode 100644 apps/web/src/lib/registry.ts rename apps/web/src/{types => lib}/rendering.ts (91%) create mode 100644 apps/web/src/lib/retime/__tests__/resolve.test.ts create mode 100644 apps/web/src/lib/retime/__tests__/split.test.ts create mode 100644 apps/web/src/lib/retime/audio-stretch.ts create mode 100644 apps/web/src/lib/retime/index.ts create mode 100644 apps/web/src/lib/retime/presets.ts create mode 100644 apps/web/src/lib/retime/resolve.ts create mode 100644 apps/web/src/lib/retime/split.ts create mode 100644 apps/web/src/lib/selection/constants.ts create mode 100644 apps/web/src/lib/selection/context.tsx create mode 100644 apps/web/src/lib/selection/hit-testing.ts create mode 100644 apps/web/src/lib/selection/hooks/use-box-select.ts create mode 100644 apps/web/src/lib/selection/hooks/use-selection-scope.ts create mode 100644 apps/web/src/lib/selection/index.ts create mode 100644 apps/web/src/lib/selection/scope.ts create mode 100644 apps/web/src/lib/selection/selectable-item.tsx create mode 100644 apps/web/src/lib/selection/selectable-surface.tsx rename apps/web/src/{components/editor => lib/selection}/selection-box.tsx (100%) create mode 100644 apps/web/src/lib/selection/state.ts create mode 100644 apps/web/src/lib/selection/types.ts create mode 100644 apps/web/src/lib/shaders/jfa-init.frag.glsl create mode 100644 apps/web/src/lib/shaders/jfa-step.frag.glsl rename apps/web/src/{types/sounds.ts => lib/sounds/types.ts} (100%) rename apps/web/{public/countries.json => src/lib/stickers/providers/countries-data.ts} (95%) delete mode 100644 apps/web/src/lib/stickers/providers/emoji.ts delete mode 100644 apps/web/src/lib/stickers/providers/icons.ts create mode 100644 apps/web/src/lib/stickers/providers/logos.ts create mode 100644 apps/web/src/lib/text/measure-element.ts create mode 100644 apps/web/src/lib/timeline/audio-constants.ts create mode 100644 apps/web/src/lib/timeline/audio-state.ts create mode 100644 apps/web/src/lib/timeline/defaults.ts rename apps/web/src/{types => lib/timeline}/drag.ts (65%) create mode 100644 apps/web/src/lib/timeline/selection-hit-testing.ts rename apps/web/src/{types/timeline.ts => lib/timeline/types.ts} (71%) rename apps/web/src/{types/transcription.ts => lib/transcription/types.ts} (92%) create mode 100644 apps/web/src/services/renderer/mask-feather.ts create mode 100644 apps/web/src/services/renderer/nodes/blur-background-node.ts delete mode 100644 apps/web/src/services/renderer/nodes/composite-effect-node.ts create mode 100644 apps/web/src/services/renderer/nodes/graphic-node.ts delete mode 100644 apps/web/src/services/renderer/webgl-effect-renderer.ts create mode 100644 apps/web/src/services/renderer/webgl/jfa.ts create mode 100644 apps/web/src/services/renderer/webgl/webgl-context.ts create mode 100644 apps/web/src/services/renderer/webgl/webgl-effect-renderer.ts rename apps/web/src/services/renderer/{ => webgl}/webgl-utils.ts (100%) create mode 100644 apps/web/src/services/storage/migrations/__tests__/v15-to-v16.test.ts create mode 100644 apps/web/src/services/storage/migrations/__tests__/v16-to-v17.test.ts create mode 100644 apps/web/src/services/storage/migrations/__tests__/v18-to-v19.test.ts create mode 100644 apps/web/src/services/storage/migrations/transformers/v10-to-v11.ts create mode 100644 apps/web/src/services/storage/migrations/transformers/v11-to-v12.ts create mode 100644 apps/web/src/services/storage/migrations/transformers/v12-to-v13.ts create mode 100644 apps/web/src/services/storage/migrations/transformers/v13-to-v14.ts create mode 100644 apps/web/src/services/storage/migrations/transformers/v14-to-v15.ts create mode 100644 apps/web/src/services/storage/migrations/transformers/v15-to-v16.ts create mode 100644 apps/web/src/services/storage/migrations/transformers/v16-to-v17.ts create mode 100644 apps/web/src/services/storage/migrations/transformers/v17-to-v18.ts create mode 100644 apps/web/src/services/storage/migrations/transformers/v18-to-v19.ts create mode 100644 apps/web/src/services/storage/migrations/transformers/v9-to-v10.ts create mode 100644 apps/web/src/services/storage/migrations/v10-to-v11.ts create mode 100644 apps/web/src/services/storage/migrations/v11-to-v12.ts create mode 100644 apps/web/src/services/storage/migrations/v12-to-v13.ts create mode 100644 apps/web/src/services/storage/migrations/v13-to-v14.ts create mode 100644 apps/web/src/services/storage/migrations/v14-to-v15.ts create mode 100644 apps/web/src/services/storage/migrations/v15-to-v16.ts create mode 100644 apps/web/src/services/storage/migrations/v16-to-v17.ts create mode 100644 apps/web/src/services/storage/migrations/v17-to-v18.ts create mode 100644 apps/web/src/services/storage/migrations/v18-to-v19.ts create mode 100644 apps/web/src/services/storage/migrations/v9-to-v10.ts create mode 100644 apps/web/src/services/storage/quota.ts create mode 100644 apps/web/src/stores/keybindings/migrations/v5-to-v6.ts delete mode 100644 apps/web/src/types/editor.ts delete mode 100644 apps/web/src/types/effects.ts delete mode 100644 apps/web/src/types/export.ts delete mode 100644 apps/web/src/types/language.ts create mode 100644 apps/web/src/types/soundtouchjs.d.ts delete mode 100644 apps/web/src/types/stickers.ts delete mode 100644 apps/web/src/types/time.ts rename {apps/web/src/components/editor/panels => legacy/components}/properties/audio-properties.tsx (100%) rename {apps/web/src/components/editor/panels => legacy/components}/properties/clip-effects-properties.tsx (100%) rename {apps/web/src/components/editor/panels => legacy/components}/properties/effect-param-field.tsx (100%) rename {apps/web/src/components/editor/panels => legacy/components}/properties/effect-properties.tsx (100%) create mode 100644 legacy/components/properties/keyframe-toggle.tsx rename {apps/web/src/components/editor/panels => legacy/components}/properties/section.tsx (100%) rename {apps/web/src/components/editor/panels => legacy/components}/properties/text-properties.tsx (100%) rename {apps/web/src/components/editor/panels => legacy/components}/properties/video-properties.tsx (100%) rename {apps/web/src/components/editor/panels/properties => legacy}/sections/blending.tsx (100%) rename {apps/web/src/components/editor/panels/properties => legacy}/sections/index.tsx (100%) rename {apps/web/src/components/editor/panels/properties => legacy}/sections/transform.tsx (100%) rename {apps/web/src/hooks => legacy}/timeline/use-selection-box.ts (88%) create mode 100644 legacy/use-assets-selection-box.ts create mode 100644 legacy/use-assets-selection.ts create mode 100644 legacy/use-element-registry.ts rename {apps/web/src/hooks => legacy}/use-reveal-item.ts (51%) diff --git a/apps/web/content/changelog/0.3.0.md b/apps/web/content/changelog/0.3.0.md index 09c7bfbd5..345688fa9 100644 --- a/apps/web/content/changelog/0.3.0.md +++ b/apps/web/content/changelog/0.3.0.md @@ -12,4 +12,71 @@ changes: text: "Added a changelog link to the footer." - type: fixed text: "Media asset cards in the grid view were larger than their thumbnails, leaving empty space around each item. Cards now size to their content." + - type: improved + text: "Playback performance is dramatically better. The editor used to slow to a crawl during playback, and audio would stutter when interacting with elements mid-play. Both are fixed. Playback now runs at a consistent 60fps." + - type: fixed + text: "Project thumbnails now generate correctly even when the timeline is empty. If you set a background color or gradient with no clips, the thumbnail reflects that instead of staying blank." + - type: fixed + text: "Clicking a selected element no longer keeps the rest of the selection." + - type: improved + text: "More vertical space between timeline tracks. Selection outlines on adjacent tracks no longer overlap each other." + - type: fixed + text: "Track labels on the left side of the timeline were misaligned with the tracks on the right." + - type: improved + text: "Holding Shift or Ctrl while drag-selecting in the timeline now adds to your existing selection instead of replacing it. Matches how Shift/Ctrl+click already worked." + - type: improved + text: "Timeline track rows now highlight when they contain a selected element, making it easier to see which tracks are active at a glance." + - type: fixed + text: "Clicking in the empty space below timeline tracks now seeks the playhead." + - type: fixed + text: "Timeline vertical scroll now works anywhere in the panel, not just over the track labels. The header no longer scrolls with the tracks." + - type: new + text: "Scale now has separate width and height controls. You can stretch or squash elements independently on each axis." + - type: improved + text: "System fonts (Arial, Helvetica, Times New Roman, and others) now appear in the font picker alongside Google Fonts." + - type: fixed + text: "MP4 exports with audio failed on Firefox. The export now completes successfully regardless of browser." + - type: improved + text: "Your projects can disappear if your disk runs low on space. OpenCut now asks the browser to protect them." + - type: fixed + text: "Opening the mask or effects panel for one element, then selecting a different element, would keep the wrong panel open and hide the transform handles for the new selection. Each element now remembers its own panel state independently." + - type: new + text: "Volume control for audio and video elements, both in the properties panel and inline on timeline clips." + - type: new + text: "Speed control for video and audio clips. Includes a maintain pitch option so audio doesn't chipmunk or deepen when you change the rate." + - type: improved + text: "Audio waveforms have gotten an upgrade. The old ones were inaccurate, prone to crashing, and not very useful. The new ones are RMS-based, properly scaled, and only render what's visible so they don't slow things down." + - type: improved + text: "The timeline now opens scrolled to the bottom, so your main video track is visible right away instead of being hidden above the fold." + - type: fixed + text: "Snap guides didn't show when moving a full-canvas element to the center of the frame." + - type: fixed + text: "The rotation handle could float above the editor UI when an element was near the top of the canvas. It now clips to the preview area." + - type: fixed + text: "Images with a blur effect at 0% intensity would disappear completely when a blurred background was also active. Now 0% blur correctly renders the image unchanged." + - type: fixed + text: "Section titles in the properties panel showed the wrong text color when the section wasn't collapsible. Non-collapsible titles now use the correct muted style." + - type: new + text: "Masks. Hide or reveal parts of any video or image layer. Choose from split, rectangle, ellipse, star, heart, diamond, text, and custom masks. Adjust position, size, rotation, feather, and stroke in the properties panel, or drag the handles in the preview." + - type: improved + text: "The settings panel has been redesigned with a cleaner layout and better organization." + - type: new + text: "Layout guides are back and expanded. TikTok was the only option before. Now includes a grid guide plus TikTok, Instagram Reels, YouTube Shorts, and Snapchat Spotlight." + - type: new + text: "Canvas backgrounds are back. Set a blur, solid color, or gradient as the canvas background from the new Background tab in the settings panel." + - type: fixed + text: "Blur looked pixelated at higher intensities instead of producing a real blur. Both the canvas background blur and the blur effect are now fixed." + - type: new + text: "Custom canvas size. Instead of being locked to a handful of presets, you can now enter any width and height you want." + - type: new + text: "Preview zoom and panning. Zoom into the canvas to work on fine details, and pan around to navigate when zoomed in." + - type: new + text: "Stickers panel now has content. Browse and add logos, country flags, and shapes." + - type: improved + text: "You can now select multiple assets in the assets panel. Useful for deleting several at once." + - type: fixed + text: "Auto-generated captions were sometimes inaccurate. The underlying issue has been fixed." + - type: new + text: "You can now import transcript files to generate captions instead of running auto-transcription." + --- diff --git a/apps/web/next.config.ts b/apps/web/next.config.ts index 2f509d2af..334e486e3 100644 --- a/apps/web/next.config.ts +++ b/apps/web/next.config.ts @@ -51,6 +51,10 @@ const nextConfig: NextConfig = { protocol: "https", hostname: "api.unisvg.com", }, + { + protocol: "https", + hostname: "cdn.brandfetch.io", + }, ], }, }; diff --git a/apps/web/package.json b/apps/web/package.json index a00c96712..9c8f229d6 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -16,13 +16,9 @@ "db:push:prod": "cross-env NODE_ENV=production drizzle-kit push" }, "dependencies": { - "@ffmpeg/core": "^0.12.10", - "@ffmpeg/ffmpeg": "^0.12.15", - "@ffmpeg/util": "^0.12.2", "@hello-pangea/dnd": "^18.0.1", - "@hookform/resolvers": "^3.9.1", "@hugeicons/core-free-icons": "^3.1.1", - "@hugeicons/react": "^1.1.4", + "@hugeicons/react": "^1.1.6", "@huggingface/transformers": "^3.8.1", "@opencut/env": "workspace:*", "@opencut/ui": "workspace:*", @@ -38,15 +34,12 @@ "@types/culori": "^4.0.1", "@upstash/ratelimit": "^2.0.6", "@upstash/redis": "^1.35.4", - "@vercel/analytics": "^1.4.1", - "aws4fetch": "^1.0.20", "better-auth": "^1.2.7", "botid": "^1.4.2", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "cmdk": "^1.0.0", "culori": "^4.0.2", - "dayjs": "^1.11.13", "drizzle-orm": "^0.44.2", "embla-carousel-react": "^8.5.1", "eventemitter3": "^5.0.1", @@ -67,21 +60,19 @@ "react-hook-form": "^7.54.0", "react-icons": "^5.4.0", "react-markdown": "^10.1.0", - "react-phone-number-input": "^3.4.11", "react-resizable-panels": "^2.1.7", "react-window": "^2.2.7", - "recharts": "^2.14.1", "rehype-autolink-headings": "^7.1.0", "rehype-parse": "^9.0.1", "rehype-sanitize": "^6.0.0", "rehype-slug": "^6.0.0", "rehype-stringify": "^10.0.1", "sonner": "^1.7.1", + "soundtouchjs": "^0.3.0", "tailwind-merge": "^3.5.0", "tailwindcss-animate": "^1.0.7", "unified": "^11.0.5", "use-deep-compare-effect": "^1.8.1", - "vaul": "^1.1.2", "wavesurfer.js": "^7.9.8", "zod": "^3.25.67", "zustand": "^5.0.2" @@ -104,7 +95,6 @@ "raw-loader": "^4.0.2", "sharp": "^0.34.5", "tailwindcss": "^4.2.1", - "tsx": "^4.7.1", "typescript": "^5.8.3" } } diff --git a/apps/web/postcss.config.mjs b/apps/web/postcss.config.mjs index 6ba14df98..61e36849c 100644 --- a/apps/web/postcss.config.mjs +++ b/apps/web/postcss.config.mjs @@ -1,8 +1,7 @@ -/** @type {import('postcss-load-config').Config} */ const config = { - plugins: { - "@tailwindcss/postcss": {}, - }, + plugins: { + "@tailwindcss/postcss": {}, + }, }; export default config; diff --git a/apps/web/public/flags/ad.svg b/apps/web/public/flags/ad.svg new file mode 100644 index 000000000..199ff198e --- /dev/null +++ b/apps/web/public/flags/ad.svg @@ -0,0 +1,150 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/ae.svg b/apps/web/public/flags/ae.svg new file mode 100644 index 000000000..651ac8523 --- /dev/null +++ b/apps/web/public/flags/ae.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/apps/web/public/flags/af.svg b/apps/web/public/flags/af.svg new file mode 100644 index 000000000..4dbe4556e --- /dev/null +++ b/apps/web/public/flags/af.svg @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/ag.svg b/apps/web/public/flags/ag.svg new file mode 100644 index 000000000..243c3d8f9 --- /dev/null +++ b/apps/web/public/flags/ag.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/ai.svg b/apps/web/public/flags/ai.svg new file mode 100644 index 000000000..9c2ea3398 --- /dev/null +++ b/apps/web/public/flags/ai.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/al.svg b/apps/web/public/flags/al.svg new file mode 100644 index 000000000..e85d95f0f --- /dev/null +++ b/apps/web/public/flags/al.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/web/public/flags/am.svg b/apps/web/public/flags/am.svg new file mode 100644 index 000000000..99fa4dc59 --- /dev/null +++ b/apps/web/public/flags/am.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/web/public/flags/ao.svg b/apps/web/public/flags/ao.svg new file mode 100644 index 000000000..b73b1ec5e --- /dev/null +++ b/apps/web/public/flags/ao.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/apps/web/public/flags/aq.svg b/apps/web/public/flags/aq.svg new file mode 100644 index 000000000..c7e353624 --- /dev/null +++ b/apps/web/public/flags/aq.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/web/public/flags/ar.svg b/apps/web/public/flags/ar.svg new file mode 100644 index 000000000..c753da103 --- /dev/null +++ b/apps/web/public/flags/ar.svg @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/arab.svg b/apps/web/public/flags/arab.svg new file mode 100644 index 000000000..9ef079f63 --- /dev/null +++ b/apps/web/public/flags/arab.svg @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/as.svg b/apps/web/public/flags/as.svg new file mode 100644 index 000000000..82459dec1 --- /dev/null +++ b/apps/web/public/flags/as.svg @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/asean.svg b/apps/web/public/flags/asean.svg new file mode 100644 index 000000000..189ae0205 --- /dev/null +++ b/apps/web/public/flags/asean.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/apps/web/public/flags/at.svg b/apps/web/public/flags/at.svg new file mode 100644 index 000000000..9d2775c08 --- /dev/null +++ b/apps/web/public/flags/at.svg @@ -0,0 +1,4 @@ + + + + diff --git a/apps/web/public/flags/au.svg b/apps/web/public/flags/au.svg new file mode 100644 index 000000000..96e80768b --- /dev/null +++ b/apps/web/public/flags/au.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/apps/web/public/flags/aw.svg b/apps/web/public/flags/aw.svg new file mode 100644 index 000000000..413b7c45b --- /dev/null +++ b/apps/web/public/flags/aw.svg @@ -0,0 +1,186 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/ax.svg b/apps/web/public/flags/ax.svg new file mode 100644 index 000000000..0584d713b --- /dev/null +++ b/apps/web/public/flags/ax.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/az.svg b/apps/web/public/flags/az.svg new file mode 100644 index 000000000..355752211 --- /dev/null +++ b/apps/web/public/flags/az.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/apps/web/public/flags/ba.svg b/apps/web/public/flags/ba.svg new file mode 100644 index 000000000..93bd9cf93 --- /dev/null +++ b/apps/web/public/flags/ba.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/apps/web/public/flags/bb.svg b/apps/web/public/flags/bb.svg new file mode 100644 index 000000000..cecd5cc33 --- /dev/null +++ b/apps/web/public/flags/bb.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/apps/web/public/flags/bd.svg b/apps/web/public/flags/bd.svg new file mode 100644 index 000000000..16b794deb --- /dev/null +++ b/apps/web/public/flags/bd.svg @@ -0,0 +1,4 @@ + + + + diff --git a/apps/web/public/flags/be.svg b/apps/web/public/flags/be.svg new file mode 100644 index 000000000..ac706a0b5 --- /dev/null +++ b/apps/web/public/flags/be.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/apps/web/public/flags/bf.svg b/apps/web/public/flags/bf.svg new file mode 100644 index 000000000..471382258 --- /dev/null +++ b/apps/web/public/flags/bf.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/apps/web/public/flags/bg.svg b/apps/web/public/flags/bg.svg new file mode 100644 index 000000000..af2d0d07c --- /dev/null +++ b/apps/web/public/flags/bg.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/web/public/flags/bh.svg b/apps/web/public/flags/bh.svg new file mode 100644 index 000000000..7a2ea549b --- /dev/null +++ b/apps/web/public/flags/bh.svg @@ -0,0 +1,4 @@ + + + + diff --git a/apps/web/public/flags/bi.svg b/apps/web/public/flags/bi.svg new file mode 100644 index 000000000..a4434a955 --- /dev/null +++ b/apps/web/public/flags/bi.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/bj.svg b/apps/web/public/flags/bj.svg new file mode 100644 index 000000000..0846724d1 --- /dev/null +++ b/apps/web/public/flags/bj.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/bl.svg b/apps/web/public/flags/bl.svg new file mode 100644 index 000000000..f84cbbaeb --- /dev/null +++ b/apps/web/public/flags/bl.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/web/public/flags/bm.svg b/apps/web/public/flags/bm.svg new file mode 100644 index 000000000..f43a5ebc8 --- /dev/null +++ b/apps/web/public/flags/bm.svg @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/bn.svg b/apps/web/public/flags/bn.svg new file mode 100644 index 000000000..f544c25e2 --- /dev/null +++ b/apps/web/public/flags/bn.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/bo.svg b/apps/web/public/flags/bo.svg new file mode 100644 index 000000000..7658e3f6c --- /dev/null +++ b/apps/web/public/flags/bo.svg @@ -0,0 +1,673 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/bq.svg b/apps/web/public/flags/bq.svg new file mode 100644 index 000000000..0e6bc76e6 --- /dev/null +++ b/apps/web/public/flags/bq.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/web/public/flags/br.svg b/apps/web/public/flags/br.svg new file mode 100644 index 000000000..719a763ca --- /dev/null +++ b/apps/web/public/flags/br.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/bs.svg b/apps/web/public/flags/bs.svg new file mode 100644 index 000000000..5cc918e5a --- /dev/null +++ b/apps/web/public/flags/bs.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/apps/web/public/flags/bt.svg b/apps/web/public/flags/bt.svg new file mode 100644 index 000000000..20aef3a63 --- /dev/null +++ b/apps/web/public/flags/bt.svg @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/bv.svg b/apps/web/public/flags/bv.svg new file mode 100644 index 000000000..40e16d948 --- /dev/null +++ b/apps/web/public/flags/bv.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/apps/web/public/flags/bw.svg b/apps/web/public/flags/bw.svg new file mode 100644 index 000000000..3435608d6 --- /dev/null +++ b/apps/web/public/flags/bw.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/apps/web/public/flags/by.svg b/apps/web/public/flags/by.svg new file mode 100644 index 000000000..948784ff1 --- /dev/null +++ b/apps/web/public/flags/by.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/bz.svg b/apps/web/public/flags/bz.svg new file mode 100644 index 000000000..d81b16c23 --- /dev/null +++ b/apps/web/public/flags/bz.svg @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/ca.svg b/apps/web/public/flags/ca.svg new file mode 100644 index 000000000..c9b23b498 --- /dev/null +++ b/apps/web/public/flags/ca.svg @@ -0,0 +1,4 @@ + + + + diff --git a/apps/web/public/flags/cc.svg b/apps/web/public/flags/cc.svg new file mode 100644 index 000000000..a42dec667 --- /dev/null +++ b/apps/web/public/flags/cc.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/cd.svg b/apps/web/public/flags/cd.svg new file mode 100644 index 000000000..b9cf52894 --- /dev/null +++ b/apps/web/public/flags/cd.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/web/public/flags/cefta.svg b/apps/web/public/flags/cefta.svg new file mode 100644 index 000000000..f748d08a1 --- /dev/null +++ b/apps/web/public/flags/cefta.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/apps/web/public/flags/cf.svg b/apps/web/public/flags/cf.svg new file mode 100644 index 000000000..a6cd3670f --- /dev/null +++ b/apps/web/public/flags/cf.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/cg.svg b/apps/web/public/flags/cg.svg new file mode 100644 index 000000000..f5a0e42d4 --- /dev/null +++ b/apps/web/public/flags/cg.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/apps/web/public/flags/ch.svg b/apps/web/public/flags/ch.svg new file mode 100644 index 000000000..b42d6709c --- /dev/null +++ b/apps/web/public/flags/ch.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/apps/web/public/flags/ci.svg b/apps/web/public/flags/ci.svg new file mode 100644 index 000000000..e400f0c1c --- /dev/null +++ b/apps/web/public/flags/ci.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/apps/web/public/flags/ck.svg b/apps/web/public/flags/ck.svg new file mode 100644 index 000000000..18e547b17 --- /dev/null +++ b/apps/web/public/flags/ck.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/apps/web/public/flags/cl.svg b/apps/web/public/flags/cl.svg new file mode 100644 index 000000000..5b3c72fa7 --- /dev/null +++ b/apps/web/public/flags/cl.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/apps/web/public/flags/cm.svg b/apps/web/public/flags/cm.svg new file mode 100644 index 000000000..70adc8b68 --- /dev/null +++ b/apps/web/public/flags/cm.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/cn.svg b/apps/web/public/flags/cn.svg new file mode 100644 index 000000000..10d3489a0 --- /dev/null +++ b/apps/web/public/flags/cn.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/apps/web/public/flags/co.svg b/apps/web/public/flags/co.svg new file mode 100644 index 000000000..ebd0a0fb2 --- /dev/null +++ b/apps/web/public/flags/co.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/apps/web/public/flags/cp.svg b/apps/web/public/flags/cp.svg new file mode 100644 index 000000000..b8aa9cfd6 --- /dev/null +++ b/apps/web/public/flags/cp.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/apps/web/public/flags/cr.svg b/apps/web/public/flags/cr.svg new file mode 100644 index 000000000..5a409eebb --- /dev/null +++ b/apps/web/public/flags/cr.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/apps/web/public/flags/cu.svg b/apps/web/public/flags/cu.svg new file mode 100644 index 000000000..053c9ee3a --- /dev/null +++ b/apps/web/public/flags/cu.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/apps/web/public/flags/cv.svg b/apps/web/public/flags/cv.svg new file mode 100644 index 000000000..aec899490 --- /dev/null +++ b/apps/web/public/flags/cv.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/apps/web/public/flags/cw.svg b/apps/web/public/flags/cw.svg new file mode 100644 index 000000000..bb0ece22e --- /dev/null +++ b/apps/web/public/flags/cw.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/cx.svg b/apps/web/public/flags/cx.svg new file mode 100644 index 000000000..3a83c23f6 --- /dev/null +++ b/apps/web/public/flags/cx.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/cy.svg b/apps/web/public/flags/cy.svg new file mode 100644 index 000000000..ee4b0c78c --- /dev/null +++ b/apps/web/public/flags/cy.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/apps/web/public/flags/cz.svg b/apps/web/public/flags/cz.svg new file mode 100644 index 000000000..7913de389 --- /dev/null +++ b/apps/web/public/flags/cz.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/web/public/flags/de.svg b/apps/web/public/flags/de.svg new file mode 100644 index 000000000..71aa2d2c3 --- /dev/null +++ b/apps/web/public/flags/de.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/web/public/flags/dg.svg b/apps/web/public/flags/dg.svg new file mode 100644 index 000000000..dfee2bb93 --- /dev/null +++ b/apps/web/public/flags/dg.svg @@ -0,0 +1,130 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/dj.svg b/apps/web/public/flags/dj.svg new file mode 100644 index 000000000..9b00a8205 --- /dev/null +++ b/apps/web/public/flags/dj.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/apps/web/public/flags/dk.svg b/apps/web/public/flags/dk.svg new file mode 100644 index 000000000..563277f81 --- /dev/null +++ b/apps/web/public/flags/dk.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/web/public/flags/dm.svg b/apps/web/public/flags/dm.svg new file mode 100644 index 000000000..5aa9cea5f --- /dev/null +++ b/apps/web/public/flags/dm.svg @@ -0,0 +1,152 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/do.svg b/apps/web/public/flags/do.svg new file mode 100644 index 000000000..6de2b268d --- /dev/null +++ b/apps/web/public/flags/do.svg @@ -0,0 +1,121 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/dz.svg b/apps/web/public/flags/dz.svg new file mode 100644 index 000000000..5ff29a74a --- /dev/null +++ b/apps/web/public/flags/dz.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/web/public/flags/eac.svg b/apps/web/public/flags/eac.svg new file mode 100644 index 000000000..59d02d218 --- /dev/null +++ b/apps/web/public/flags/eac.svg @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/ec.svg b/apps/web/public/flags/ec.svg new file mode 100644 index 000000000..88c50bf61 --- /dev/null +++ b/apps/web/public/flags/ec.svg @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/ee.svg b/apps/web/public/flags/ee.svg new file mode 100644 index 000000000..8b98c2c42 --- /dev/null +++ b/apps/web/public/flags/ee.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/web/public/flags/eg.svg b/apps/web/public/flags/eg.svg new file mode 100644 index 000000000..88e32b3ae --- /dev/null +++ b/apps/web/public/flags/eg.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/eh.svg b/apps/web/public/flags/eh.svg new file mode 100644 index 000000000..6aec72883 --- /dev/null +++ b/apps/web/public/flags/eh.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/er.svg b/apps/web/public/flags/er.svg new file mode 100644 index 000000000..48a13b47f --- /dev/null +++ b/apps/web/public/flags/er.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/apps/web/public/flags/es-ct.svg b/apps/web/public/flags/es-ct.svg new file mode 100644 index 000000000..4d8591140 --- /dev/null +++ b/apps/web/public/flags/es-ct.svg @@ -0,0 +1,4 @@ + + + + diff --git a/apps/web/public/flags/es-ga.svg b/apps/web/public/flags/es-ga.svg new file mode 100644 index 000000000..573ca45da --- /dev/null +++ b/apps/web/public/flags/es-ga.svg @@ -0,0 +1,187 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/es-pv.svg b/apps/web/public/flags/es-pv.svg new file mode 100644 index 000000000..63c19f417 --- /dev/null +++ b/apps/web/public/flags/es-pv.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/web/public/flags/es.svg b/apps/web/public/flags/es.svg new file mode 100644 index 000000000..a296ebf7e --- /dev/null +++ b/apps/web/public/flags/es.svg @@ -0,0 +1,544 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/et.svg b/apps/web/public/flags/et.svg new file mode 100644 index 000000000..3f99be486 --- /dev/null +++ b/apps/web/public/flags/et.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/eu.svg b/apps/web/public/flags/eu.svg new file mode 100644 index 000000000..b0874c1ed --- /dev/null +++ b/apps/web/public/flags/eu.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/fi.svg b/apps/web/public/flags/fi.svg new file mode 100644 index 000000000..470be2d07 --- /dev/null +++ b/apps/web/public/flags/fi.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/web/public/flags/fj.svg b/apps/web/public/flags/fj.svg new file mode 100644 index 000000000..332ae61d0 --- /dev/null +++ b/apps/web/public/flags/fj.svg @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/fk.svg b/apps/web/public/flags/fk.svg new file mode 100644 index 000000000..a0dace837 --- /dev/null +++ b/apps/web/public/flags/fk.svg @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/fm.svg b/apps/web/public/flags/fm.svg new file mode 100644 index 000000000..c1b7c9778 --- /dev/null +++ b/apps/web/public/flags/fm.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/apps/web/public/flags/fo.svg b/apps/web/public/flags/fo.svg new file mode 100644 index 000000000..f802d285a --- /dev/null +++ b/apps/web/public/flags/fo.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/apps/web/public/flags/fr.svg b/apps/web/public/flags/fr.svg new file mode 100644 index 000000000..4110e59e4 --- /dev/null +++ b/apps/web/public/flags/fr.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/web/public/flags/ga.svg b/apps/web/public/flags/ga.svg new file mode 100644 index 000000000..76edab429 --- /dev/null +++ b/apps/web/public/flags/ga.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/apps/web/public/flags/gb-eng.svg b/apps/web/public/flags/gb-eng.svg new file mode 100644 index 000000000..12e3b67d5 --- /dev/null +++ b/apps/web/public/flags/gb-eng.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/web/public/flags/gb-nir.svg b/apps/web/public/flags/gb-nir.svg new file mode 100644 index 000000000..e22190aae --- /dev/null +++ b/apps/web/public/flags/gb-nir.svg @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/gb-sct.svg b/apps/web/public/flags/gb-sct.svg new file mode 100644 index 000000000..f50cd322a --- /dev/null +++ b/apps/web/public/flags/gb-sct.svg @@ -0,0 +1,4 @@ + + + + diff --git a/apps/web/public/flags/gb-wls.svg b/apps/web/public/flags/gb-wls.svg new file mode 100644 index 000000000..d7f57912d --- /dev/null +++ b/apps/web/public/flags/gb-wls.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/apps/web/public/flags/gb.svg b/apps/web/public/flags/gb.svg new file mode 100644 index 000000000..799138319 --- /dev/null +++ b/apps/web/public/flags/gb.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/apps/web/public/flags/gd.svg b/apps/web/public/flags/gd.svg new file mode 100644 index 000000000..b3d250db9 --- /dev/null +++ b/apps/web/public/flags/gd.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/ge.svg b/apps/web/public/flags/ge.svg new file mode 100644 index 000000000..ab08a9ab4 --- /dev/null +++ b/apps/web/public/flags/ge.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/apps/web/public/flags/gf.svg b/apps/web/public/flags/gf.svg new file mode 100644 index 000000000..f8fe94c65 --- /dev/null +++ b/apps/web/public/flags/gf.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/web/public/flags/gg.svg b/apps/web/public/flags/gg.svg new file mode 100644 index 000000000..f8216c8bc --- /dev/null +++ b/apps/web/public/flags/gg.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/apps/web/public/flags/gh.svg b/apps/web/public/flags/gh.svg new file mode 100644 index 000000000..5c3e3e69a --- /dev/null +++ b/apps/web/public/flags/gh.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/apps/web/public/flags/gi.svg b/apps/web/public/flags/gi.svg new file mode 100644 index 000000000..a5d7570dd --- /dev/null +++ b/apps/web/public/flags/gi.svg @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/gl.svg b/apps/web/public/flags/gl.svg new file mode 100644 index 000000000..eb5a52e9e --- /dev/null +++ b/apps/web/public/flags/gl.svg @@ -0,0 +1,4 @@ + + + + diff --git a/apps/web/public/flags/gm.svg b/apps/web/public/flags/gm.svg new file mode 100644 index 000000000..8fe9d6692 --- /dev/null +++ b/apps/web/public/flags/gm.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/gn.svg b/apps/web/public/flags/gn.svg new file mode 100644 index 000000000..40d6ad4f0 --- /dev/null +++ b/apps/web/public/flags/gn.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/apps/web/public/flags/gp.svg b/apps/web/public/flags/gp.svg new file mode 100644 index 000000000..ee55c4bcd --- /dev/null +++ b/apps/web/public/flags/gp.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/web/public/flags/gq.svg b/apps/web/public/flags/gq.svg new file mode 100644 index 000000000..64c8eb220 --- /dev/null +++ b/apps/web/public/flags/gq.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/gr.svg b/apps/web/public/flags/gr.svg new file mode 100644 index 000000000..599741eec --- /dev/null +++ b/apps/web/public/flags/gr.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/gs.svg b/apps/web/public/flags/gs.svg new file mode 100644 index 000000000..29db9b942 --- /dev/null +++ b/apps/web/public/flags/gs.svg @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/gt.svg b/apps/web/public/flags/gt.svg new file mode 100644 index 000000000..7df9df579 --- /dev/null +++ b/apps/web/public/flags/gt.svg @@ -0,0 +1,204 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/gu.svg b/apps/web/public/flags/gu.svg new file mode 100644 index 000000000..3b95219a0 --- /dev/null +++ b/apps/web/public/flags/gu.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/gw.svg b/apps/web/public/flags/gw.svg new file mode 100644 index 000000000..d470bac9f --- /dev/null +++ b/apps/web/public/flags/gw.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/apps/web/public/flags/gy.svg b/apps/web/public/flags/gy.svg new file mode 100644 index 000000000..569fb5627 --- /dev/null +++ b/apps/web/public/flags/gy.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/apps/web/public/flags/hk.svg b/apps/web/public/flags/hk.svg new file mode 100644 index 000000000..4fd55bc14 --- /dev/null +++ b/apps/web/public/flags/hk.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/apps/web/public/flags/hm.svg b/apps/web/public/flags/hm.svg new file mode 100644 index 000000000..815c48208 --- /dev/null +++ b/apps/web/public/flags/hm.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/apps/web/public/flags/hn.svg b/apps/web/public/flags/hn.svg new file mode 100644 index 000000000..11fde67db --- /dev/null +++ b/apps/web/public/flags/hn.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/hr.svg b/apps/web/public/flags/hr.svg new file mode 100644 index 000000000..dde825c30 --- /dev/null +++ b/apps/web/public/flags/hr.svg @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/ht.svg b/apps/web/public/flags/ht.svg new file mode 100644 index 000000000..8e8efc46b --- /dev/null +++ b/apps/web/public/flags/ht.svg @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/hu.svg b/apps/web/public/flags/hu.svg new file mode 100644 index 000000000..baddf7f5e --- /dev/null +++ b/apps/web/public/flags/hu.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/apps/web/public/flags/ic.svg b/apps/web/public/flags/ic.svg new file mode 100644 index 000000000..81e6ee2e1 --- /dev/null +++ b/apps/web/public/flags/ic.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/apps/web/public/flags/id.svg b/apps/web/public/flags/id.svg new file mode 100644 index 000000000..3b7c8fcfd --- /dev/null +++ b/apps/web/public/flags/id.svg @@ -0,0 +1,4 @@ + + + + diff --git a/apps/web/public/flags/ie.svg b/apps/web/public/flags/ie.svg new file mode 100644 index 000000000..049be14de --- /dev/null +++ b/apps/web/public/flags/ie.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/apps/web/public/flags/il.svg b/apps/web/public/flags/il.svg new file mode 100644 index 000000000..f43be7e8e --- /dev/null +++ b/apps/web/public/flags/il.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/im.svg b/apps/web/public/flags/im.svg new file mode 100644 index 000000000..fe6a59a1a --- /dev/null +++ b/apps/web/public/flags/im.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/in.svg b/apps/web/public/flags/in.svg new file mode 100644 index 000000000..bc47d7491 --- /dev/null +++ b/apps/web/public/flags/in.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/io.svg b/apps/web/public/flags/io.svg new file mode 100644 index 000000000..3058f7dff --- /dev/null +++ b/apps/web/public/flags/io.svg @@ -0,0 +1,130 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/iq.svg b/apps/web/public/flags/iq.svg new file mode 100644 index 000000000..804451474 --- /dev/null +++ b/apps/web/public/flags/iq.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/apps/web/public/flags/ir.svg b/apps/web/public/flags/ir.svg new file mode 100644 index 000000000..8c6d51621 --- /dev/null +++ b/apps/web/public/flags/ir.svg @@ -0,0 +1,219 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/is.svg b/apps/web/public/flags/is.svg new file mode 100644 index 000000000..a6588afae --- /dev/null +++ b/apps/web/public/flags/is.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/apps/web/public/flags/it.svg b/apps/web/public/flags/it.svg new file mode 100644 index 000000000..20a8bfdcc --- /dev/null +++ b/apps/web/public/flags/it.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/apps/web/public/flags/je.svg b/apps/web/public/flags/je.svg new file mode 100644 index 000000000..70a8754ef --- /dev/null +++ b/apps/web/public/flags/je.svg @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/jm.svg b/apps/web/public/flags/jm.svg new file mode 100644 index 000000000..269df0383 --- /dev/null +++ b/apps/web/public/flags/jm.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/apps/web/public/flags/jo.svg b/apps/web/public/flags/jo.svg new file mode 100644 index 000000000..d6f927d44 --- /dev/null +++ b/apps/web/public/flags/jo.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/jp.svg b/apps/web/public/flags/jp.svg new file mode 100644 index 000000000..cc1c181ce --- /dev/null +++ b/apps/web/public/flags/jp.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/apps/web/public/flags/ke.svg b/apps/web/public/flags/ke.svg new file mode 100644 index 000000000..3a67ca3cc --- /dev/null +++ b/apps/web/public/flags/ke.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/kg.svg b/apps/web/public/flags/kg.svg new file mode 100644 index 000000000..e26db9535 --- /dev/null +++ b/apps/web/public/flags/kg.svg @@ -0,0 +1,4 @@ + + + + diff --git a/apps/web/public/flags/kh.svg b/apps/web/public/flags/kh.svg new file mode 100644 index 000000000..a7d52f2cb --- /dev/null +++ b/apps/web/public/flags/kh.svg @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/ki.svg b/apps/web/public/flags/ki.svg new file mode 100644 index 000000000..fda03f37b --- /dev/null +++ b/apps/web/public/flags/ki.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/km.svg b/apps/web/public/flags/km.svg new file mode 100644 index 000000000..414d65e47 --- /dev/null +++ b/apps/web/public/flags/km.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/kn.svg b/apps/web/public/flags/kn.svg new file mode 100644 index 000000000..47fe64d61 --- /dev/null +++ b/apps/web/public/flags/kn.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/kp.svg b/apps/web/public/flags/kp.svg new file mode 100644 index 000000000..ad1b713f1 --- /dev/null +++ b/apps/web/public/flags/kp.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/kr.svg b/apps/web/public/flags/kr.svg new file mode 100644 index 000000000..6947eab2b --- /dev/null +++ b/apps/web/public/flags/kr.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/kw.svg b/apps/web/public/flags/kw.svg new file mode 100644 index 000000000..3dd89e996 --- /dev/null +++ b/apps/web/public/flags/kw.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/apps/web/public/flags/ky.svg b/apps/web/public/flags/ky.svg new file mode 100644 index 000000000..aeaa7e08c --- /dev/null +++ b/apps/web/public/flags/ky.svg @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/kz.svg b/apps/web/public/flags/kz.svg new file mode 100644 index 000000000..2fac45bda --- /dev/null +++ b/apps/web/public/flags/kz.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/la.svg b/apps/web/public/flags/la.svg new file mode 100644 index 000000000..6aea6b72b --- /dev/null +++ b/apps/web/public/flags/la.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/apps/web/public/flags/lb.svg b/apps/web/public/flags/lb.svg new file mode 100644 index 000000000..bde2581d2 --- /dev/null +++ b/apps/web/public/flags/lb.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/lc.svg b/apps/web/public/flags/lc.svg new file mode 100644 index 000000000..bb256541c --- /dev/null +++ b/apps/web/public/flags/lc.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/apps/web/public/flags/li.svg b/apps/web/public/flags/li.svg new file mode 100644 index 000000000..7a4d18324 --- /dev/null +++ b/apps/web/public/flags/li.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/lk.svg b/apps/web/public/flags/lk.svg new file mode 100644 index 000000000..cbd660a54 --- /dev/null +++ b/apps/web/public/flags/lk.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/lr.svg b/apps/web/public/flags/lr.svg new file mode 100644 index 000000000..e482ab9d7 --- /dev/null +++ b/apps/web/public/flags/lr.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/ls.svg b/apps/web/public/flags/ls.svg new file mode 100644 index 000000000..a7c01a98f --- /dev/null +++ b/apps/web/public/flags/ls.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/apps/web/public/flags/lt.svg b/apps/web/public/flags/lt.svg new file mode 100644 index 000000000..90ec5d240 --- /dev/null +++ b/apps/web/public/flags/lt.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/apps/web/public/flags/lu.svg b/apps/web/public/flags/lu.svg new file mode 100644 index 000000000..cc1220681 --- /dev/null +++ b/apps/web/public/flags/lu.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/web/public/flags/lv.svg b/apps/web/public/flags/lv.svg new file mode 100644 index 000000000..6a9e75ec9 --- /dev/null +++ b/apps/web/public/flags/lv.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/apps/web/public/flags/ly.svg b/apps/web/public/flags/ly.svg new file mode 100644 index 000000000..1eaa51e46 --- /dev/null +++ b/apps/web/public/flags/ly.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/apps/web/public/flags/ma.svg b/apps/web/public/flags/ma.svg new file mode 100644 index 000000000..7ce56eff7 --- /dev/null +++ b/apps/web/public/flags/ma.svg @@ -0,0 +1,4 @@ + + + + diff --git a/apps/web/public/flags/mc.svg b/apps/web/public/flags/mc.svg new file mode 100644 index 000000000..9cb6c9e8a --- /dev/null +++ b/apps/web/public/flags/mc.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/apps/web/public/flags/md.svg b/apps/web/public/flags/md.svg new file mode 100644 index 000000000..e9ba506a2 --- /dev/null +++ b/apps/web/public/flags/md.svg @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/me.svg b/apps/web/public/flags/me.svg new file mode 100644 index 000000000..297888c7b --- /dev/null +++ b/apps/web/public/flags/me.svg @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/mf.svg b/apps/web/public/flags/mf.svg new file mode 100644 index 000000000..6305edc1c --- /dev/null +++ b/apps/web/public/flags/mf.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/web/public/flags/mg.svg b/apps/web/public/flags/mg.svg new file mode 100644 index 000000000..5fa2d2440 --- /dev/null +++ b/apps/web/public/flags/mg.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/apps/web/public/flags/mh.svg b/apps/web/public/flags/mh.svg new file mode 100644 index 000000000..7b9f49075 --- /dev/null +++ b/apps/web/public/flags/mh.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/apps/web/public/flags/mk.svg b/apps/web/public/flags/mk.svg new file mode 100644 index 000000000..4f5cae77e --- /dev/null +++ b/apps/web/public/flags/mk.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/web/public/flags/ml.svg b/apps/web/public/flags/ml.svg new file mode 100644 index 000000000..6f6b71695 --- /dev/null +++ b/apps/web/public/flags/ml.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/apps/web/public/flags/mm.svg b/apps/web/public/flags/mm.svg new file mode 100644 index 000000000..42b4dee2b --- /dev/null +++ b/apps/web/public/flags/mm.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/apps/web/public/flags/mn.svg b/apps/web/public/flags/mn.svg new file mode 100644 index 000000000..6a38a71fc --- /dev/null +++ b/apps/web/public/flags/mn.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/mo.svg b/apps/web/public/flags/mo.svg new file mode 100644 index 000000000..f638b6cbc --- /dev/null +++ b/apps/web/public/flags/mo.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/apps/web/public/flags/mp.svg b/apps/web/public/flags/mp.svg new file mode 100644 index 000000000..26bfa2217 --- /dev/null +++ b/apps/web/public/flags/mp.svg @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/mq.svg b/apps/web/public/flags/mq.svg new file mode 100644 index 000000000..b221951e3 --- /dev/null +++ b/apps/web/public/flags/mq.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/web/public/flags/mr.svg b/apps/web/public/flags/mr.svg new file mode 100644 index 000000000..d859972c5 --- /dev/null +++ b/apps/web/public/flags/mr.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/apps/web/public/flags/ms.svg b/apps/web/public/flags/ms.svg new file mode 100644 index 000000000..4367505bc --- /dev/null +++ b/apps/web/public/flags/ms.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/mt.svg b/apps/web/public/flags/mt.svg new file mode 100644 index 000000000..5d5d7c80a --- /dev/null +++ b/apps/web/public/flags/mt.svg @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/mu.svg b/apps/web/public/flags/mu.svg new file mode 100644 index 000000000..82d7a3bec --- /dev/null +++ b/apps/web/public/flags/mu.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/apps/web/public/flags/mv.svg b/apps/web/public/flags/mv.svg new file mode 100644 index 000000000..10450f984 --- /dev/null +++ b/apps/web/public/flags/mv.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/apps/web/public/flags/mw.svg b/apps/web/public/flags/mw.svg new file mode 100644 index 000000000..137ff8789 --- /dev/null +++ b/apps/web/public/flags/mw.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/apps/web/public/flags/mx.svg b/apps/web/public/flags/mx.svg new file mode 100644 index 000000000..e3ec2bc59 --- /dev/null +++ b/apps/web/public/flags/mx.svg @@ -0,0 +1,382 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/my.svg b/apps/web/public/flags/my.svg new file mode 100644 index 000000000..115f864d8 --- /dev/null +++ b/apps/web/public/flags/my.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/mz.svg b/apps/web/public/flags/mz.svg new file mode 100644 index 000000000..0f94c3a1a --- /dev/null +++ b/apps/web/public/flags/mz.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/na.svg b/apps/web/public/flags/na.svg new file mode 100644 index 000000000..35b9f783e --- /dev/null +++ b/apps/web/public/flags/na.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/nc.svg b/apps/web/public/flags/nc.svg new file mode 100644 index 000000000..fa1555169 --- /dev/null +++ b/apps/web/public/flags/nc.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/apps/web/public/flags/ne.svg b/apps/web/public/flags/ne.svg new file mode 100644 index 000000000..39a82b827 --- /dev/null +++ b/apps/web/public/flags/ne.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/apps/web/public/flags/nf.svg b/apps/web/public/flags/nf.svg new file mode 100644 index 000000000..fd61b25c1 --- /dev/null +++ b/apps/web/public/flags/nf.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/apps/web/public/flags/ng.svg b/apps/web/public/flags/ng.svg new file mode 100644 index 000000000..81eb35f78 --- /dev/null +++ b/apps/web/public/flags/ng.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/apps/web/public/flags/ni.svg b/apps/web/public/flags/ni.svg new file mode 100644 index 000000000..e4861f5ab --- /dev/null +++ b/apps/web/public/flags/ni.svg @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/nl.svg b/apps/web/public/flags/nl.svg new file mode 100644 index 000000000..e90f5b035 --- /dev/null +++ b/apps/web/public/flags/nl.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/web/public/flags/no.svg b/apps/web/public/flags/no.svg new file mode 100644 index 000000000..a5f2a152a --- /dev/null +++ b/apps/web/public/flags/no.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/apps/web/public/flags/np.svg b/apps/web/public/flags/np.svg new file mode 100644 index 000000000..624285684 --- /dev/null +++ b/apps/web/public/flags/np.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/apps/web/public/flags/nr.svg b/apps/web/public/flags/nr.svg new file mode 100644 index 000000000..ff394c411 --- /dev/null +++ b/apps/web/public/flags/nr.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/apps/web/public/flags/nu.svg b/apps/web/public/flags/nu.svg new file mode 100644 index 000000000..4067bafff --- /dev/null +++ b/apps/web/public/flags/nu.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/apps/web/public/flags/nz.svg b/apps/web/public/flags/nz.svg new file mode 100644 index 000000000..935d8a749 --- /dev/null +++ b/apps/web/public/flags/nz.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/om.svg b/apps/web/public/flags/om.svg new file mode 100644 index 000000000..4f1461a00 --- /dev/null +++ b/apps/web/public/flags/om.svg @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/pa.svg b/apps/web/public/flags/pa.svg new file mode 100644 index 000000000..8dc03bc61 --- /dev/null +++ b/apps/web/public/flags/pa.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/pc.svg b/apps/web/public/flags/pc.svg new file mode 100644 index 000000000..5202d6d62 --- /dev/null +++ b/apps/web/public/flags/pc.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/pe.svg b/apps/web/public/flags/pe.svg new file mode 100644 index 000000000..33e6cfd41 --- /dev/null +++ b/apps/web/public/flags/pe.svg @@ -0,0 +1,4 @@ + + + + diff --git a/apps/web/public/flags/pf.svg b/apps/web/public/flags/pf.svg new file mode 100644 index 000000000..bea0354d5 --- /dev/null +++ b/apps/web/public/flags/pf.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/pg.svg b/apps/web/public/flags/pg.svg new file mode 100644 index 000000000..7b7e77aad --- /dev/null +++ b/apps/web/public/flags/pg.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/apps/web/public/flags/ph.svg b/apps/web/public/flags/ph.svg new file mode 100644 index 000000000..b910e24cd --- /dev/null +++ b/apps/web/public/flags/ph.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/apps/web/public/flags/pk.svg b/apps/web/public/flags/pk.svg new file mode 100644 index 000000000..4ddc19f8e --- /dev/null +++ b/apps/web/public/flags/pk.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/pl.svg b/apps/web/public/flags/pl.svg new file mode 100644 index 000000000..0fa514524 --- /dev/null +++ b/apps/web/public/flags/pl.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/apps/web/public/flags/pm.svg b/apps/web/public/flags/pm.svg new file mode 100644 index 000000000..19a9330a3 --- /dev/null +++ b/apps/web/public/flags/pm.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/web/public/flags/pn.svg b/apps/web/public/flags/pn.svg new file mode 100644 index 000000000..209ea71a1 --- /dev/null +++ b/apps/web/public/flags/pn.svg @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/pr.svg b/apps/web/public/flags/pr.svg new file mode 100644 index 000000000..ec51831dc --- /dev/null +++ b/apps/web/public/flags/pr.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/apps/web/public/flags/ps.svg b/apps/web/public/flags/ps.svg new file mode 100644 index 000000000..362d4359b --- /dev/null +++ b/apps/web/public/flags/ps.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/apps/web/public/flags/pt.svg b/apps/web/public/flags/pt.svg new file mode 100644 index 000000000..2767cd4e9 --- /dev/null +++ b/apps/web/public/flags/pt.svg @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/pw.svg b/apps/web/public/flags/pw.svg new file mode 100644 index 000000000..9f89c5f14 --- /dev/null +++ b/apps/web/public/flags/pw.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/apps/web/public/flags/py.svg b/apps/web/public/flags/py.svg new file mode 100644 index 000000000..abccd8799 --- /dev/null +++ b/apps/web/public/flags/py.svg @@ -0,0 +1,157 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/qa.svg b/apps/web/public/flags/qa.svg new file mode 100644 index 000000000..901f3fa76 --- /dev/null +++ b/apps/web/public/flags/qa.svg @@ -0,0 +1,4 @@ + + + + diff --git a/apps/web/public/flags/re.svg b/apps/web/public/flags/re.svg new file mode 100644 index 000000000..64e788e01 --- /dev/null +++ b/apps/web/public/flags/re.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/web/public/flags/ro.svg b/apps/web/public/flags/ro.svg new file mode 100644 index 000000000..fda0f7bec --- /dev/null +++ b/apps/web/public/flags/ro.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/apps/web/public/flags/rs.svg b/apps/web/public/flags/rs.svg new file mode 100644 index 000000000..6d4f74d76 --- /dev/null +++ b/apps/web/public/flags/rs.svg @@ -0,0 +1,292 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/ru.svg b/apps/web/public/flags/ru.svg new file mode 100644 index 000000000..cf243011a --- /dev/null +++ b/apps/web/public/flags/ru.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/web/public/flags/rw.svg b/apps/web/public/flags/rw.svg new file mode 100644 index 000000000..06e26ae44 --- /dev/null +++ b/apps/web/public/flags/rw.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/apps/web/public/flags/sa.svg b/apps/web/public/flags/sa.svg new file mode 100644 index 000000000..596cf48bb --- /dev/null +++ b/apps/web/public/flags/sa.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/sb.svg b/apps/web/public/flags/sb.svg new file mode 100644 index 000000000..6066f94cd --- /dev/null +++ b/apps/web/public/flags/sb.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/apps/web/public/flags/sc.svg b/apps/web/public/flags/sc.svg new file mode 100644 index 000000000..9a46b369b --- /dev/null +++ b/apps/web/public/flags/sc.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/apps/web/public/flags/sd.svg b/apps/web/public/flags/sd.svg new file mode 100644 index 000000000..12818b411 --- /dev/null +++ b/apps/web/public/flags/sd.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/apps/web/public/flags/se.svg b/apps/web/public/flags/se.svg new file mode 100644 index 000000000..8ba745aca --- /dev/null +++ b/apps/web/public/flags/se.svg @@ -0,0 +1,4 @@ + + + + diff --git a/apps/web/public/flags/sg.svg b/apps/web/public/flags/sg.svg new file mode 100644 index 000000000..c4dd4ac9e --- /dev/null +++ b/apps/web/public/flags/sg.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/apps/web/public/flags/sh-ac.svg b/apps/web/public/flags/sh-ac.svg new file mode 100644 index 000000000..c43b301ef --- /dev/null +++ b/apps/web/public/flags/sh-ac.svg @@ -0,0 +1,689 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/sh-hl.svg b/apps/web/public/flags/sh-hl.svg new file mode 100644 index 000000000..2150bf609 --- /dev/null +++ b/apps/web/public/flags/sh-hl.svg @@ -0,0 +1,164 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/sh-ta.svg b/apps/web/public/flags/sh-ta.svg new file mode 100644 index 000000000..ba390631c --- /dev/null +++ b/apps/web/public/flags/sh-ta.svg @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/sh.svg b/apps/web/public/flags/sh.svg new file mode 100644 index 000000000..7aba0aec8 --- /dev/null +++ b/apps/web/public/flags/sh.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/apps/web/public/flags/si.svg b/apps/web/public/flags/si.svg new file mode 100644 index 000000000..1bbdd94fd --- /dev/null +++ b/apps/web/public/flags/si.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/sj.svg b/apps/web/public/flags/sj.svg new file mode 100644 index 000000000..bb2799ce7 --- /dev/null +++ b/apps/web/public/flags/sj.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/apps/web/public/flags/sk.svg b/apps/web/public/flags/sk.svg new file mode 100644 index 000000000..676018e62 --- /dev/null +++ b/apps/web/public/flags/sk.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/apps/web/public/flags/sl.svg b/apps/web/public/flags/sl.svg new file mode 100644 index 000000000..a07baf75b --- /dev/null +++ b/apps/web/public/flags/sl.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/apps/web/public/flags/sm.svg b/apps/web/public/flags/sm.svg new file mode 100644 index 000000000..e41d2f776 --- /dev/null +++ b/apps/web/public/flags/sm.svg @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/sn.svg b/apps/web/public/flags/sn.svg new file mode 100644 index 000000000..7c0673d6d --- /dev/null +++ b/apps/web/public/flags/sn.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/apps/web/public/flags/so.svg b/apps/web/public/flags/so.svg new file mode 100644 index 000000000..a581ac63c --- /dev/null +++ b/apps/web/public/flags/so.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/apps/web/public/flags/sr.svg b/apps/web/public/flags/sr.svg new file mode 100644 index 000000000..5e71c4002 --- /dev/null +++ b/apps/web/public/flags/sr.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/apps/web/public/flags/ss.svg b/apps/web/public/flags/ss.svg new file mode 100644 index 000000000..b257aa0b3 --- /dev/null +++ b/apps/web/public/flags/ss.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/apps/web/public/flags/st.svg b/apps/web/public/flags/st.svg new file mode 100644 index 000000000..1294bcb70 --- /dev/null +++ b/apps/web/public/flags/st.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/sv.svg b/apps/web/public/flags/sv.svg new file mode 100644 index 000000000..cbc674a6e --- /dev/null +++ b/apps/web/public/flags/sv.svg @@ -0,0 +1,593 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/sx.svg b/apps/web/public/flags/sx.svg new file mode 100644 index 000000000..ac7856178 --- /dev/null +++ b/apps/web/public/flags/sx.svg @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/sy.svg b/apps/web/public/flags/sy.svg new file mode 100644 index 000000000..97c05cfc9 --- /dev/null +++ b/apps/web/public/flags/sy.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/apps/web/public/flags/sz.svg b/apps/web/public/flags/sz.svg new file mode 100644 index 000000000..eb538e447 --- /dev/null +++ b/apps/web/public/flags/sz.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/tc.svg b/apps/web/public/flags/tc.svg new file mode 100644 index 000000000..125897107 --- /dev/null +++ b/apps/web/public/flags/tc.svg @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/td.svg b/apps/web/public/flags/td.svg new file mode 100644 index 000000000..fa3bd927c --- /dev/null +++ b/apps/web/public/flags/td.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/apps/web/public/flags/tf.svg b/apps/web/public/flags/tf.svg new file mode 100644 index 000000000..fba233563 --- /dev/null +++ b/apps/web/public/flags/tf.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/tg.svg b/apps/web/public/flags/tg.svg new file mode 100644 index 000000000..9d6ea6c5d --- /dev/null +++ b/apps/web/public/flags/tg.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/th.svg b/apps/web/public/flags/th.svg new file mode 100644 index 000000000..1e93a61e9 --- /dev/null +++ b/apps/web/public/flags/th.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/apps/web/public/flags/tj.svg b/apps/web/public/flags/tj.svg new file mode 100644 index 000000000..f8c9a0371 --- /dev/null +++ b/apps/web/public/flags/tj.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/tk.svg b/apps/web/public/flags/tk.svg new file mode 100644 index 000000000..05d3e86ce --- /dev/null +++ b/apps/web/public/flags/tk.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/web/public/flags/tl.svg b/apps/web/public/flags/tl.svg new file mode 100644 index 000000000..3d0701a2c --- /dev/null +++ b/apps/web/public/flags/tl.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/apps/web/public/flags/tm.svg b/apps/web/public/flags/tm.svg new file mode 100644 index 000000000..4154ed765 --- /dev/null +++ b/apps/web/public/flags/tm.svg @@ -0,0 +1,204 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/tn.svg b/apps/web/public/flags/tn.svg new file mode 100644 index 000000000..5735c1984 --- /dev/null +++ b/apps/web/public/flags/tn.svg @@ -0,0 +1,4 @@ + + + + diff --git a/apps/web/public/flags/to.svg b/apps/web/public/flags/to.svg new file mode 100644 index 000000000..d07233706 --- /dev/null +++ b/apps/web/public/flags/to.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/apps/web/public/flags/tr.svg b/apps/web/public/flags/tr.svg new file mode 100644 index 000000000..b96da21f0 --- /dev/null +++ b/apps/web/public/flags/tr.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/apps/web/public/flags/tt.svg b/apps/web/public/flags/tt.svg new file mode 100644 index 000000000..bc24938cf --- /dev/null +++ b/apps/web/public/flags/tt.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/web/public/flags/tv.svg b/apps/web/public/flags/tv.svg new file mode 100644 index 000000000..675210ec5 --- /dev/null +++ b/apps/web/public/flags/tv.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/apps/web/public/flags/tw.svg b/apps/web/public/flags/tw.svg new file mode 100644 index 000000000..57fd98b43 --- /dev/null +++ b/apps/web/public/flags/tw.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/tz.svg b/apps/web/public/flags/tz.svg new file mode 100644 index 000000000..a2cfbca42 --- /dev/null +++ b/apps/web/public/flags/tz.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/apps/web/public/flags/ua.svg b/apps/web/public/flags/ua.svg new file mode 100644 index 000000000..a339eb1b9 --- /dev/null +++ b/apps/web/public/flags/ua.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/apps/web/public/flags/ug.svg b/apps/web/public/flags/ug.svg new file mode 100644 index 000000000..520eee5c7 --- /dev/null +++ b/apps/web/public/flags/ug.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/um.svg b/apps/web/public/flags/um.svg new file mode 100644 index 000000000..9e9eddaa4 --- /dev/null +++ b/apps/web/public/flags/um.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/apps/web/public/flags/un.svg b/apps/web/public/flags/un.svg new file mode 100644 index 000000000..632bbb4ac --- /dev/null +++ b/apps/web/public/flags/un.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/us.svg b/apps/web/public/flags/us.svg new file mode 100644 index 000000000..9cfd0c927 --- /dev/null +++ b/apps/web/public/flags/us.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/apps/web/public/flags/uy.svg b/apps/web/public/flags/uy.svg new file mode 100644 index 000000000..62c36f8e5 --- /dev/null +++ b/apps/web/public/flags/uy.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/uz.svg b/apps/web/public/flags/uz.svg new file mode 100644 index 000000000..0ccca1b1b --- /dev/null +++ b/apps/web/public/flags/uz.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/va.svg b/apps/web/public/flags/va.svg new file mode 100644 index 000000000..3e297d638 --- /dev/null +++ b/apps/web/public/flags/va.svg @@ -0,0 +1,190 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/vc.svg b/apps/web/public/flags/vc.svg new file mode 100644 index 000000000..f26c2d8da --- /dev/null +++ b/apps/web/public/flags/vc.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/apps/web/public/flags/ve.svg b/apps/web/public/flags/ve.svg new file mode 100644 index 000000000..314e7f5f7 --- /dev/null +++ b/apps/web/public/flags/ve.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/vg.svg b/apps/web/public/flags/vg.svg new file mode 100644 index 000000000..ac900888e --- /dev/null +++ b/apps/web/public/flags/vg.svg @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/vi.svg b/apps/web/public/flags/vi.svg new file mode 100644 index 000000000..d88d68f99 --- /dev/null +++ b/apps/web/public/flags/vi.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/vn.svg b/apps/web/public/flags/vn.svg new file mode 100644 index 000000000..7e4bac8f4 --- /dev/null +++ b/apps/web/public/flags/vn.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/apps/web/public/flags/vu.svg b/apps/web/public/flags/vu.svg new file mode 100644 index 000000000..326d29e9d --- /dev/null +++ b/apps/web/public/flags/vu.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/wf.svg b/apps/web/public/flags/wf.svg new file mode 100644 index 000000000..054c57df9 --- /dev/null +++ b/apps/web/public/flags/wf.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/web/public/flags/ws.svg b/apps/web/public/flags/ws.svg new file mode 100644 index 000000000..0e758a7a9 --- /dev/null +++ b/apps/web/public/flags/ws.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/apps/web/public/flags/xk.svg b/apps/web/public/flags/xk.svg new file mode 100644 index 000000000..0e8958d88 --- /dev/null +++ b/apps/web/public/flags/xk.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/web/public/flags/xx.svg b/apps/web/public/flags/xx.svg new file mode 100644 index 000000000..9333be363 --- /dev/null +++ b/apps/web/public/flags/xx.svg @@ -0,0 +1,4 @@ + + + + diff --git a/apps/web/public/flags/ye.svg b/apps/web/public/flags/ye.svg new file mode 100644 index 000000000..1c9e6d639 --- /dev/null +++ b/apps/web/public/flags/ye.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/apps/web/public/flags/yt.svg b/apps/web/public/flags/yt.svg new file mode 100644 index 000000000..e7776b307 --- /dev/null +++ b/apps/web/public/flags/yt.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/web/public/flags/za.svg b/apps/web/public/flags/za.svg new file mode 100644 index 000000000..d563adb90 --- /dev/null +++ b/apps/web/public/flags/za.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/zm.svg b/apps/web/public/flags/zm.svg new file mode 100644 index 000000000..360f37aa1 --- /dev/null +++ b/apps/web/public/flags/zm.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/flags/zw.svg b/apps/web/public/flags/zw.svg new file mode 100644 index 000000000..93aac4f6c --- /dev/null +++ b/apps/web/public/flags/zw.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/shapes/circle.svg b/apps/web/public/shapes/circle.svg index adb837cf9..2de141cd3 100644 --- a/apps/web/public/shapes/circle.svg +++ b/apps/web/public/shapes/circle.svg @@ -1,3 +1,3 @@ - + diff --git a/apps/web/public/shapes/diamond.svg b/apps/web/public/shapes/diamond.svg index 4a039b5cb..a0a31aa8e 100644 --- a/apps/web/public/shapes/diamond.svg +++ b/apps/web/public/shapes/diamond.svg @@ -1,3 +1,3 @@ - + diff --git a/apps/web/public/shapes/hexagon.svg b/apps/web/public/shapes/hexagon.svg index e1eb087ec..e50cd91f9 100644 --- a/apps/web/public/shapes/hexagon.svg +++ b/apps/web/public/shapes/hexagon.svg @@ -1,3 +1,6 @@ - + diff --git a/apps/web/public/shapes/square.svg b/apps/web/public/shapes/square.svg index ed9b790fd..58a0f6adc 100644 --- a/apps/web/public/shapes/square.svg +++ b/apps/web/public/shapes/square.svg @@ -1,3 +1,3 @@ - + diff --git a/apps/web/public/shapes/star.svg b/apps/web/public/shapes/star.svg index c49e0c53d..f646764b1 100644 --- a/apps/web/public/shapes/star.svg +++ b/apps/web/public/shapes/star.svg @@ -1,3 +1,6 @@ - + diff --git a/apps/web/public/shapes/triangle.svg b/apps/web/public/shapes/triangle.svg index a1bd6b0ca..9c1c5a41e 100644 --- a/apps/web/public/shapes/triangle.svg +++ b/apps/web/public/shapes/triangle.svg @@ -1,3 +1,3 @@ - + diff --git a/apps/web/src/app/blog/[slug]/page.tsx b/apps/web/src/app/blog/[slug]/page.tsx index e1afc3a80..90afd9194 100644 --- a/apps/web/src/app/blog/[slug]/page.tsx +++ b/apps/web/src/app/blog/[slug]/page.tsx @@ -5,7 +5,7 @@ import { BasePage } from "@/app/base-page"; import Prose from "@/components/ui/prose"; import { Separator } from "@/components/ui/separator"; import { getPosts, getSinglePost, processHtmlContent } from "@/lib/blog/query"; -import type { Author, Post } from "@/types/blog"; +import type { Author, Post } from "@/lib/blog/types"; type PageProps = { params: Promise<{ slug: string }>; diff --git a/apps/web/src/app/blog/page.tsx b/apps/web/src/app/blog/page.tsx index 257a8f231..df0b195d9 100644 --- a/apps/web/src/app/blog/page.tsx +++ b/apps/web/src/app/blog/page.tsx @@ -3,7 +3,7 @@ import Link from "next/link"; import { BasePage } from "@/app/base-page"; import { Separator } from "@/components/ui/separator"; import { getPosts } from "@/lib/blog/query"; -import type { Post } from "@/types/blog"; +import type { Post } from "@/lib/blog/types"; export const metadata: Metadata = { title: "Blog - OpenCut", diff --git a/apps/web/src/app/globals.css b/apps/web/src/app/globals.css index 6d3e984f5..212194276 100644 --- a/apps/web/src/app/globals.css +++ b/apps/web/src/app/globals.css @@ -8,111 +8,111 @@ @plugin "tailwindcss-animate"; :root { - --background: hsl(0, 0%, 100%); - --foreground: hsl(0 0% 11%); - --card: hsl(0, 0%, 100%); - --card-foreground: hsl(0 0% 11%); - --popover: hsl(0, 0%, 100%); - --popover-hover: hsl(0, 0%, 96%); - --popover-foreground: hsl(0 0% 2%); - --primary: #009dff; - --primary-foreground: hsl(0, 0%, 100%); - --secondary: hsl(204, 100%, 97%); - --secondary-border: hsl(204, 100%, 94%); - --secondary-foreground: hsl(200, 98%, 39%); - --muted: hsl(0 0% 85.1%); - --muted-foreground: hsl(0 0% 50%); - --accent: hsl(0, 0%, 96%); - --accent-foreground: hsl(0 0% 2%); - --destructive: hsl(0, 83%, 50%); - --destructive-foreground: hsl(0, 0%, 100%); - --constructive: hsl(141, 71%, 48%); - --constructive-foreground: hsl(0, 0%, 100%); - --border: hsl(0 0% 91%); - --input: hsl(0, 0%, 100%); - --ring: hsl(0, 0%, 55%); - --chart-1: hsl(220 70% 50%); - --chart-2: hsl(160 60% 45%); - --chart-3: hsl(30 80% 55%); - --chart-4: hsl(280 65% 60%); - --chart-5: hsl(340 75% 55%); - --sidebar-background: hsl(0 0% 96.1%); - --sidebar-foreground: hsl(0 0% 2%); - --sidebar-primary: hsl(0 0% 2%); - --sidebar-primary-foreground: hsl(0 0% 91%); - --sidebar-accent: hsl(0 0% 85.1%); - --sidebar-accent-foreground: hsl(0 0% 2%); - --sidebar-border: hsl(0 0% 85.1%); - --sidebar-ring: hsl(0 0% 16.9%); - --sidebar: hsl(0 0% 98%); + --background: hsl(0, 0%, 100%); + --foreground: hsl(0 0% 11%); + --card: hsl(0, 0%, 100%); + --card-foreground: hsl(0 0% 11%); + --popover: hsl(0, 0%, 100%); + --popover-hover: hsl(0, 0%, 96%); + --popover-foreground: hsl(0 0% 2%); + --primary: hsl(200, 90%, 52%); + --primary-foreground: hsl(0, 0%, 100%); + --secondary: hsl(204, 100%, 97%); + --secondary-border: hsl(204, 100%, 94%); + --secondary-foreground: hsl(200, 98%, 39%); + --muted: hsl(0 0% 85.1%); + --muted-foreground: hsl(0 0% 50%); + --accent: hsl(0, 0%, 96%); + --accent-foreground: hsl(0 0% 2%); + --destructive: hsl(0, 83%, 50%); + --destructive-foreground: hsl(0, 0%, 100%); + --constructive: hsl(141, 71%, 48%); + --constructive-foreground: hsl(0, 0%, 100%); + --border: hsl(0 0% 91%); + --input: hsl(0, 0%, 100%); + --ring: hsl(0, 0%, 55%); + --chart-1: hsl(220 70% 50%); + --chart-2: hsl(160 60% 45%); + --chart-3: hsl(30 80% 55%); + --chart-4: hsl(280 65% 60%); + --chart-5: hsl(340 75% 55%); + --sidebar-background: hsl(0 0% 96.1%); + --sidebar-foreground: hsl(0 0% 2%); + --sidebar-primary: hsl(0 0% 2%); + --sidebar-primary-foreground: hsl(0 0% 91%); + --sidebar-accent: hsl(0 0% 85.1%); + --sidebar-accent-foreground: hsl(0 0% 2%); + --sidebar-border: hsl(0 0% 85.1%); + --sidebar-ring: hsl(0 0% 16.9%); + --sidebar: hsl(0 0% 98%); } .panel { - --background: hsl(216 13% 98%); - --foreground: hsl(0 0% 13%); - --card: hsl(0, 0%, 98%); - --card-foreground: hsl(0 0% 13%); - --primary-foreground: hsl(0, 0%, 98%); - --secondary: hsl(204, 100%, 95%); - --secondary-border: hsl(204, 100%, 92%); - --secondary-foreground: hsl(200, 98%, 37%); - --muted: hsl(0 0% 83.1%); - --muted-foreground: hsl(0 0% 48%); - --accent: hsl(0, 0%, 93%); - --accent-foreground: hsl(0 0% 5%); - --destructive-foreground: hsl(0, 0%, 98%); - --constructive-foreground: hsl(0, 0%, 98%); - --border: hsl(0 0% 89%); - --input: hsl(0 0% 93%); - --ring: hsl(0, 0%, 53%); + --background: hsl(210, 20%, 98%); + --foreground: hsl(0 0% 13%); + --card: hsl(0, 0%, 98%); + --card-foreground: hsl(0 0% 13%); + --primary-foreground: hsl(0, 0%, 98%); + --secondary: hsl(204, 100%, 95%); + --secondary-border: hsl(204, 100%, 92%); + --secondary-foreground: hsl(200, 98%, 37%); + --muted: hsl(0 0% 83.1%); + --muted-foreground: hsl(0 0% 48%); + --accent: hsl(0, 0%, 93%); + --accent-foreground: hsl(0 0% 5%); + --destructive-foreground: hsl(0, 0%, 98%); + --constructive-foreground: hsl(0, 0%, 98%); + --border: hsl(0 0% 87%); + --input: hsl(0 0% 93%); + --ring: hsl(0, 0%, 53%); } .dark { - --background: hsl(0, 0%, 5%); - --foreground: hsl(0 0% 87%); - --card: hsl(0, 0%, 5%); - --card-foreground: hsl(0 0% 87%); - --popover: hsl(0, 0%, 5%); - --popover-hover: hsl(0, 0%, 22%); - --popover-foreground: hsl(0 0% 95%); - --secondary: hsl(204, 100%, 12%); - --secondary-border: hsl(204, 100%, 15%); - --secondary-foreground: hsl(200, 98%, 61%); - --muted: hsl(0 0% 20%); - --accent: hsl(0, 0%, 14%); - --accent-foreground: hsl(0 0% 95%); - --border: hsl(0 0% 16%); - --input: hsl(0 0% 5%); - --ring: hsl(0, 0%, 50%); - --sidebar-background: hsl(0 0% 8%); - --sidebar-foreground: hsl(0 0% 95%); - --sidebar-primary: hsl(0 0% 95%); - --sidebar-primary-foreground: hsl(0 0% 15%); - --sidebar-accent: hsl(0 0% 20%); - --sidebar-accent-foreground: hsl(0 0% 95%); - --sidebar-border: hsl(0 0% 20%); - --sidebar-ring: hsl(0 0% 83.1%); - --sidebar: hsl(0 0% 6%); + --background: hsl(0, 0%, 5%); + --foreground: hsl(0 0% 87%); + --card: hsl(0, 0%, 5%); + --card-foreground: hsl(0 0% 87%); + --popover: hsl(0, 0%, 5%); + --popover-hover: hsl(0, 0%, 13%); + --popover-foreground: hsl(0 0% 95%); + --secondary: hsl(204, 100%, 12%); + --secondary-border: hsl(204, 100%, 15%); + --secondary-foreground: hsl(200, 98%, 61%); + --muted: hsl(0 0% 20%); + --accent: hsl(0, 0%, 14%); + --accent-foreground: hsl(0 0% 95%); + --border: hsl(0 0% 16%); + --input: hsl(0 0% 5%); + --ring: hsl(0, 0%, 50%); + --sidebar-background: hsl(0 0% 8%); + --sidebar-foreground: hsl(0 0% 95%); + --sidebar-primary: hsl(0 0% 95%); + --sidebar-primary-foreground: hsl(0 0% 15%); + --sidebar-accent: hsl(0 0% 20%); + --sidebar-accent-foreground: hsl(0 0% 95%); + --sidebar-border: hsl(0 0% 20%); + --sidebar-ring: hsl(0 0% 83.1%); + --sidebar: hsl(0 0% 6%); } .dark .panel { - --background: hsl(0 0% 10%); - --foreground: hsl(0 0% 85%); - --card: hsl(0, 0%, 10%); - --card-foreground: hsl(0 0% 85%); - --secondary: hsl(204, 67%, 9%); - --secondary-border: hsl(204, 100%, 14%); - --secondary-foreground: hsl(200, 98%, 63%); - --muted: hsl(0 0% 22%); - --accent: hsl(0, 0%, 15%); - --accent-foreground: hsl(0 0% 93%); - --border: hsl(0 0% 18%); - --input: hsl(0 0% 22%); - --ring: hsl(0, 0%, 52%); + --background: hsl(0 0% 10%); + --foreground: hsl(0 0% 85%); + --card: hsl(0, 0%, 10%); + --card-foreground: hsl(0 0% 85%); + --secondary: hsl(204, 67%, 9%); + --secondary-border: hsl(204, 100%, 14%); + --secondary-foreground: hsl(200, 98%, 63%); + --muted: hsl(0 0% 22%); + --accent: hsl(0, 0%, 15%); + --accent-foreground: hsl(0 0% 93%); + --border: hsl(0 0% 18%); + --input: hsl(0 0% 22%); + --ring: hsl(0, 0%, 52%); } @layer base { - /* + /* The default border color has changed to `currentcolor` in Tailwind CSS v4, so we've added these compatibility styles to make sure everything still looks the same as it did with Tailwind CSS v3. @@ -120,165 +120,165 @@ If we ever want to remove these styles, we need to add an explicit border color utility to any element that depends on these defaults. */ - *, - ::after, - ::before, - ::backdrop, - ::file-selector-button { - border-color: var(--color-gray-200, currentcolor); - } - /* Other default base styles */ - * { - @apply border-border; - } - body { - @apply bg-background text-foreground; - /* Prevent back/forward swipe */ - overscroll-behavior-x: contain; - } - ::selection { - @apply bg-primary/35 selection:text-primary-foreground; - } + *, + ::after, + ::before, + ::backdrop, + ::file-selector-button { + border-color: var(--color-gray-200, currentcolor); + } + /* Other default base styles */ + * { + @apply border-border; + } + body { + @apply bg-background text-foreground; + /* Prevent back/forward swipe */ + overscroll-behavior-x: contain; + } + ::selection { + @apply bg-primary/35 selection:text-primary-foreground; + } } @theme inline { - /* Responsive breakpoints */ - --breakpoint-xs: 30rem; + /* Responsive breakpoints */ + --breakpoint-xs: 30rem; - /* Typography */ - --font-sans: var(--font-inter), sans-serif; + /* Typography */ + --font-sans: var(--font-inter), sans-serif; - /* Font sizes */ - --text-xs: 0.72rem; - --text-sm: 0.79rem; - --text-base: 0.92rem; - --text-base--line-height: calc(1.5 / 0.95); - --text-xs--line-height: calc(1 / 0.8); + /* Font sizes */ + --text-xs: 0.72rem; + --text-sm: 0.79rem; + --text-base: 0.92rem; + --text-base--line-height: calc(1.5 / 0.95); + --text-xs--line-height: calc(1 / 0.8); - /* Border radius */ - --radius-lg: 0.82rem; - --radius-md: 0.65rem; - --radius-sm: 0.35rem; + /* Border radius */ + --radius-lg: 0.82rem; + --radius-md: 0.65rem; + --radius-sm: 0.35rem; - /* Palette mapped to root design tokens */ - --color-background: var(--background); - --color-foreground: var(--foreground); + /* Palette mapped to root design tokens */ + --color-background: var(--background); + --color-foreground: var(--foreground); - --color-card: var(--card); - --color-card-foreground: var(--card-foreground); + --color-card: var(--card); + --color-card-foreground: var(--card-foreground); - --color-popover: var(--popover); - --color-popover-hover: var(--popover-hover); - --color-popover-foreground: var(--popover-foreground); + --color-popover: var(--popover); + --color-popover-hover: var(--popover-hover); + --color-popover-foreground: var(--popover-foreground); - --color-primary: var(--primary); - --color-primary-foreground: var(--primary-foreground); - --color-secondary: var(--secondary); - --color-secondary-border: var(--secondary-border); - --color-secondary-foreground: var(--secondary-foreground); + --color-primary: var(--primary); + --color-primary-foreground: var(--primary-foreground); + --color-secondary: var(--secondary); + --color-secondary-border: var(--secondary-border); + --color-secondary-foreground: var(--secondary-foreground); - --color-muted: var(--muted); - --color-muted-foreground: var(--muted-foreground); + --color-muted: var(--muted); + --color-muted-foreground: var(--muted-foreground); - --color-accent: var(--accent); - --color-accent-foreground: var(--accent-foreground); + --color-accent: var(--accent); + --color-accent-foreground: var(--accent-foreground); - --color-destructive: var(--destructive); - --color-destructive-foreground: var(--destructive-foreground); + --color-destructive: var(--destructive); + --color-destructive-foreground: var(--destructive-foreground); - --color-constructive: var(--constructive); - --color-constructive-foreground: var(--constructive-foreground); + --color-constructive: var(--constructive); + --color-constructive-foreground: var(--constructive-foreground); - --color-border: var(--border); - --color-input: var(--input); - --color-ring: var(--ring); + --color-border: var(--border); + --color-input: var(--input); + --color-ring: var(--ring); - /* Chart colors */ - --color-chart-1: var(--chart-1); - --color-chart-2: var(--chart-2); - --color-chart-3: var(--chart-3); - --color-chart-4: var(--chart-4); - --color-chart-5: var(--chart-5); + /* Chart colors */ + --color-chart-1: var(--chart-1); + --color-chart-2: var(--chart-2); + --color-chart-3: var(--chart-3); + --color-chart-4: var(--chart-4); + --color-chart-5: var(--chart-5); - /* Sidebar */ - --color-sidebar: var(--sidebar-background); - --color-sidebar-foreground: var(--sidebar-foreground); - --color-sidebar-primary: var(--sidebar-primary); - --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); - --color-sidebar-accent: var(--sidebar-accent); - --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); - --color-sidebar-border: var(--sidebar-border); - --color-sidebar-ring: var(--sidebar-ring); + /* Sidebar */ + --color-sidebar: var(--sidebar-background); + --color-sidebar-foreground: var(--sidebar-foreground); + --color-sidebar-primary: var(--sidebar-primary); + --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); + --color-sidebar-accent: var(--sidebar-accent); + --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); + --color-sidebar-border: var(--sidebar-border); + --color-sidebar-ring: var(--sidebar-ring); - /* Animations */ - --animate-accordion-down: accordion-down 0.2s ease-out; - --animate-accordion-up: accordion-up 0.2s ease-out; + /* Animations */ + --animate-accordion-down: accordion-down 0.2s ease-out; + --animate-accordion-up: accordion-up 0.2s ease-out; - @keyframes accordion-down { - from { - height: 0; - } - to { - height: var(--radix-accordion-content-height); - } - } + @keyframes accordion-down { + from { + height: 0; + } + to { + height: var(--radix-accordion-content-height); + } + } - @keyframes accordion-up { - from { - height: var(--radix-accordion-content-height); - } - to { - height: 0; - } - } + @keyframes accordion-up { + from { + height: var(--radix-accordion-content-height); + } + to { + height: 0; + } + } } @utility scrollbar-hidden { - -ms-overflow-style: none; - scrollbar-width: none; - &::-webkit-scrollbar { - display: none; - } + -ms-overflow-style: none; + scrollbar-width: none; + &::-webkit-scrollbar { + display: none; + } } @utility scrollbar-x-hidden { - -ms-overflow-style: none; - scrollbar-width: none; - &::-webkit-scrollbar:horizontal { - display: none; - } + -ms-overflow-style: none; + scrollbar-width: none; + &::-webkit-scrollbar:horizontal { + display: none; + } } @utility scrollbar-y-hidden { - -ms-overflow-style: none; - scrollbar-width: none; - &::-webkit-scrollbar:vertical { - display: none; - } + -ms-overflow-style: none; + scrollbar-width: none; + &::-webkit-scrollbar:vertical { + display: none; + } } @utility scrollbar-thin { - &::-webkit-scrollbar { - width: 6px; - height: 8px; - } - &::-webkit-scrollbar-track { - background: transparent; - } - &::-webkit-scrollbar-thumb { - background: var(--border); - border-radius: 4px; - } - &::-webkit-scrollbar-thumb:hover { - background: var(--muted-foreground); - } + &::-webkit-scrollbar { + width: 7px; + height: 7px; + } + &::-webkit-scrollbar-track { + background: transparent; + } + &::-webkit-scrollbar-thumb { + background: var(--border); + border-radius: 4px; + } + &::-webkit-scrollbar-thumb:hover { + background: var(--muted-foreground); + } } @layer base { - * { - @apply border-border outline-ring/50; - } - body { - @apply bg-background text-foreground; - } + * { + @apply border-border outline-ring/50; + } + body { + @apply bg-background text-foreground; + } } diff --git a/apps/web/src/app/layout.tsx b/apps/web/src/app/layout.tsx index c2608bd9d..f8e6040fc 100644 --- a/apps/web/src/app/layout.tsx +++ b/apps/web/src/app/layout.tsx @@ -29,11 +29,20 @@ export default function RootLayout({ {process.env.NODE_ENV === "development" && ( -