diff options
| author | Maze <167211895+mazeincoding@users.noreply.github.com> | 2026-02-23 03:24:02 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-02-23 03:24:02 +0100 |
| commit | 93d1e3383ce47e45157d70f9ba6251239dae6bc2 (patch) | |
| tree | 1e33a2d7533b65f0e7c8927f03905a1a99937bd1 /apps/web/src/types | |
| parent | fca99d6126c31fbb18ed9f1034cee6f940b040e8 (diff) | |
| download | opencut-93d1e3383ce47e45157d70f9ba6251239dae6bc2.tar.gz | |
feat: major editor overhaul (assets, properties, timeline, fonts) (#709)
* feat: major editor overhaul (assets, properties, timeline, fonts)
Refactor editor core systems to standardize UI architecture and improve performance.
Assets & Properties:
- Replace monolithic property items with composable `Section` architecture.
- Add specialized sections for Transform, Blending, and Text.
- Implement `NumberField` with scrubbing and math evaluation.
- Add new ColorPicker with EyeDropper and multiple format support.
- Standardize asset panels using new `PanelView` layout.
Fonts & Stickers:
- Implement custom font atlas/sprite system for high-performance previews.
- Add virtualized FontPicker with search and favorites.
- Refactor stickers to use a provider-based architecture (icons, emoji, flags, shapes).
- Standardize sticker IDs to `provider:value` format.
Timeline & Interaction:
- Convert bookmarks to rich objects with notes, colors, and duration.
- Refactor drag-and-drop to use Command pattern (enabling proper undo/redo).
- Add Shift modifier to disable snapping during moves/resizes.
- Add new overlays for layout guides and text editing.
Renderer:
- Add support for multi-line text, custom line-height, and letter-spacing.
- Implement global composite operation (blend modes).
- Update sticker node to resolve dynamic provider IDs.
Infrastructure:
- Add storage migrations (v3->v6) for text weights, sticker IDs, and bookmarks.
- Update global styles and core UI components (Button, Input, Popover).
* add ts-nocheck directive to settings-legacy.tsx to suppress TypeScript errors
* fix: correct global composite operation assignment in TextNode to ensure proper blend mode handling
* deleted shadcn components with errors
* formatting
* fix linter issues
* migrate from next middleware to proxy
* add missing component back
* add breadcrumb back
* chore: add @radix-ui/react-primitive deps
* chore: more deps
* chore: add missing env vars to bun-ci
* next env
Diffstat (limited to 'apps/web/src/types')
| -rw-r--r-- | apps/web/src/types/drag.ts | 2 | ||||
| -rw-r--r-- | apps/web/src/types/eyedropper.d.ts | 13 | ||||
| -rw-r--r-- | apps/web/src/types/fonts.ts | 24 | ||||
| -rw-r--r-- | apps/web/src/types/rendering.ts | 18 | ||||
| -rw-r--r-- | apps/web/src/types/sounds.ts | 78 | ||||
| -rw-r--r-- | apps/web/src/types/stickers.ts | 55 | ||||
| -rw-r--r-- | apps/web/src/types/timeline.ts | 22 |
7 files changed, 165 insertions, 47 deletions
diff --git a/apps/web/src/types/drag.ts b/apps/web/src/types/drag.ts index e6e5daba..61aba9b5 100644 --- a/apps/web/src/types/drag.ts +++ b/apps/web/src/types/drag.ts @@ -15,7 +15,7 @@ export interface TextDragData extends BaseDragData { export interface StickerDragData extends BaseDragData { type: "sticker"; - iconName: string; + stickerId: string; } export type TimelineDragData = MediaDragData | TextDragData | StickerDragData; diff --git a/apps/web/src/types/eyedropper.d.ts b/apps/web/src/types/eyedropper.d.ts new file mode 100644 index 00000000..2d0e17e8 --- /dev/null +++ b/apps/web/src/types/eyedropper.d.ts @@ -0,0 +1,13 @@ +interface EyeDropperResult { + sRGBHex: string; +} + +interface EyeDropper { + open(options?: { signal?: AbortSignal }): Promise<EyeDropperResult>; +} + +declare const EyeDropper: + | { + new (): EyeDropper; + } + | undefined; diff --git a/apps/web/src/types/fonts.ts b/apps/web/src/types/fonts.ts new file mode 100644 index 00000000..a2db6f91 --- /dev/null +++ b/apps/web/src/types/fonts.ts @@ -0,0 +1,24 @@ +export interface FontOption { + value: string; + label: string; + category: "system" | "google" | "custom"; + weights?: number[]; + hasClassName?: boolean; +} + +export interface GoogleFontMeta { + family: string; + category: string; +} + +export interface FontAtlasEntry { + x: number; + y: number; + w: number; + ch: number; + s: string[]; +} + +export interface FontAtlas { + fonts: Record<string, FontAtlasEntry>; +} diff --git a/apps/web/src/types/rendering.ts b/apps/web/src/types/rendering.ts new file mode 100644 index 00000000..f5e18502 --- /dev/null +++ b/apps/web/src/types/rendering.ts @@ -0,0 +1,18 @@ +export type BlendMode = + | "normal" + | "darken" + | "multiply" + | "color-burn" + | "lighten" + | "screen" + | "plus-lighter" + | "color-dodge" + | "overlay" + | "soft-light" + | "hard-light" + | "difference" + | "exclusion" + | "hue" + | "saturation" + | "color" + | "luminosity"; diff --git a/apps/web/src/types/sounds.ts b/apps/web/src/types/sounds.ts index f7526846..eecf7701 100644 --- a/apps/web/src/types/sounds.ts +++ b/apps/web/src/types/sounds.ts @@ -1,39 +1,39 @@ -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; // freesound id
- name: string;
- username: string;
- previewUrl?: string;
- downloadUrl?: string;
- duration: number;
- tags: string[];
- license: string;
- savedAt: string; // iso date string
-}
-
-export interface SavedSoundsData {
- sounds: SavedSound[];
- lastModified: string;
-}
+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; // freesound id + name: string; + username: string; + previewUrl?: string; + downloadUrl?: string; + duration: number; + tags: string[]; + license: string; + savedAt: string; // iso date string +} + +export interface SavedSoundsData { + sounds: SavedSound[]; + lastModified: string; +} diff --git a/apps/web/src/types/stickers.ts b/apps/web/src/types/stickers.ts index c6adfd7a..65c9aeb2 100644 --- a/apps/web/src/types/stickers.ts +++ b/apps/web/src/types/stickers.ts @@ -1,3 +1,54 @@ -import type { STICKER_CATEGORIES } from "@/constants/stickers-constants"; +import type { STICKER_CATEGORIES } from "@/constants/sticker-constants"; -export type StickerCategory = (typeof STICKER_CATEGORIES)[number]; +export type StickerCategory = keyof typeof STICKER_CATEGORIES; + +export interface StickerItem { + id: string; + provider: string; + name: string; + previewUrl: string; + metadata: Record<string, unknown>; +} + +export interface StickerSearchResult { + items: StickerItem[]; + total: number; + hasMore: boolean; +} + +export interface StickerProviderSearchOptions { + limit?: number; +} + +export interface StickerProviderBrowseOptions { + page?: number; + limit?: number; +} + +export interface StickerResolveOptions { + width?: number; + height?: number; +} + +export interface StickerProvider { + id: string; + search({ + query, + options, + }: { + query: string; + options?: StickerProviderSearchOptions; + }): Promise<StickerSearchResult>; + browse({ + options, + }: { + options?: StickerProviderBrowseOptions; + }): Promise<StickerSearchResult>; + resolveUrl({ + stickerId, + options, + }: { + stickerId: string; + options?: StickerResolveOptions; + }): string; +} diff --git a/apps/web/src/types/timeline.ts b/apps/web/src/types/timeline.ts index 69d40518..da96c7de 100644 --- a/apps/web/src/types/timeline.ts +++ b/apps/web/src/types/timeline.ts @@ -1,9 +1,18 @@ +import type { BlendMode } from "./rendering"; + +export interface Bookmark { + time: number; + note?: string; + color?: string; + duration?: number; +} + export interface TScene { id: string; name: string; isMain: boolean; tracks: TimelineTrack[]; - bookmarks: number[]; + bookmarks: Bookmark[]; createdAt: Date; updatedAt: Date; } @@ -87,6 +96,7 @@ export interface VideoElement extends BaseTimelineElement { hidden?: boolean; transform: Transform; opacity: number; + blendMode?: BlendMode; } export interface ImageElement extends BaseTimelineElement { @@ -95,6 +105,7 @@ export interface ImageElement extends BaseTimelineElement { hidden?: boolean; transform: Transform; opacity: number; + blendMode?: BlendMode; } export interface TextElement extends BaseTimelineElement { @@ -108,18 +119,21 @@ export interface TextElement extends BaseTimelineElement { 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"; - iconName: string; + stickerId: string; hidden?: boolean; transform: Transform; opacity: number; - color?: string; + blendMode?: BlendMode; } export type TimelineElement = @@ -147,8 +161,6 @@ export type CreateTimelineElement = | CreateTextElement | CreateStickerElement; -// ---- Drag State ---- - export interface ElementDragState { isDragging: boolean; elementId: string | null; |
