diff options
| author | Maze Winther <mazewinther@gmail.com> | 2026-03-25 16:47:22 +0100 |
|---|---|---|
| committer | Maze Winther <mazewinther@gmail.com> | 2026-03-29 15:48:22 +0200 |
| commit | 8db3bead13441a5882d8689dfc6a9f09c82375d9 (patch) | |
| tree | e9d0cafa93904ffcbec3188c37961bcc16c6422d /apps/web/src/components/editor/panels/properties/clip-effects-properties.tsx | |
| parent | 39ea298a9ccba3104c549c0ca079c231981811f5 (diff) | |
| download | opencut-8db3bead13441a5882d8689dfc6a9f09c82375d9.tar.gz | |
feat: masks, properties refactor, shaders, storage migrations, and more
Diffstat (limited to 'apps/web/src/components/editor/panels/properties/clip-effects-properties.tsx')
| -rw-r--r-- | apps/web/src/components/editor/panels/properties/clip-effects-properties.tsx | 215 |
1 files changed, 0 insertions, 215 deletions
diff --git a/apps/web/src/components/editor/panels/properties/clip-effects-properties.tsx b/apps/web/src/components/editor/panels/properties/clip-effects-properties.tsx deleted file mode 100644 index a1324bdf..00000000 --- a/apps/web/src/components/editor/panels/properties/clip-effects-properties.tsx +++ /dev/null @@ -1,215 +0,0 @@ -"use client"; - -import { useEffect, useState } from "react"; -import type { Effect } from "@/types/effects"; -import type { VisualElement } from "@/types/timeline"; -import { getEffect } from "@/lib/effects/registry"; -import { useEditor } from "@/hooks/use-editor"; -import { usePropertiesStore } from "@/stores/properties-store"; -import { - Section, - SectionContent, - SectionHeader, - SectionTitle, - SectionFields, -} from "./section"; -import { EffectParamField } from "./effect-param-field"; -import { Button } from "@/components/ui/button"; -import { HugeiconsIcon } from "@hugeicons/react"; -import { - ArrowLeft01Icon, - Delete02Icon, - ViewIcon, - ViewOffSlashIcon, -} from "@hugeicons/core-free-icons"; -import { ScrollArea } from "@/components/ui/scroll-area"; -import { cn } from "@/utils/ui"; -export function ClipEffectsProperties({ - element, - trackId, -}: { - element: VisualElement; - trackId: string; -}) { - const closeClipEffects = usePropertiesStore( - (state) => state.closeClipEffects, - ); - const editor = useEditor(); - const effects = element.effects ?? []; - - useEffect(() => { - if (effects.length === 0) closeClipEffects(); - }, [effects.length, closeClipEffects]); - - const [dragIndex, setDragIndex] = useState<number | null>(null); - const [dropIndex, setDropIndex] = useState<number | null>(null); - - const handleDragStart = ({ index }: { index: number }) => { - setDragIndex(index); - }; - - const handleDragOver = ({ event, index }: { event: React.DragEvent; index: number }) => { - event.preventDefault(); - if (index !== dropIndex) setDropIndex(index); - }; - - const handleDrop = ({ toIndex }: { toIndex: number }) => { - if (dragIndex !== null && dragIndex !== toIndex) { - editor.timeline.reorderClipEffects({ - trackId, - elementId: element.id, - fromIndex: dragIndex, - toIndex, - }); - } - setDragIndex(null); - setDropIndex(null); - }; - - const handleDragEnd = () => { - setDragIndex(null); - setDropIndex(null); - }; - - return ( - <div className="flex h-full flex-col"> - <div className="flex h-11 shrink-0 items-center gap-2 border-b px-1.5"> - <Button - variant="ghost" - size="icon" - onClick={closeClipEffects} - aria-label="Back to properties" - > - <HugeiconsIcon icon={ArrowLeft01Icon} /> - </Button> - <span className="text-sm font-medium">Effects</span> - </div> - <ScrollArea className="flex-1 scrollbar-hidden"> - {effects.map((effect, index) => ( - // biome-ignore lint/a11y/noStaticElementInteractions: drag-and-drop list reorder - <div - key={effect.id} - draggable - onDragStart={() => handleDragStart({ index })} - onDragOver={(event) => handleDragOver({ event, index })} - onDrop={() => handleDrop({ toIndex: index })} - onDragEnd={handleDragEnd} - className={cn( - "group", - dragIndex === index && "opacity-40", - dropIndex === index && - dragIndex !== null && - dragIndex !== index && - (index < dragIndex - ? "border-t-2 border-primary" - : "border-b-2 border-primary"), - )} - > - <ClipEffectSection - effect={effect} - element={element} - trackId={trackId} - /> - </div> - ))} - </ScrollArea> - </div> - ); -} - -function ClipEffectSection({ - effect, - element, - trackId, -}: { - effect: Effect; - element: VisualElement; - trackId: string; -}) { - const editor = useEditor(); - const definition = getEffect({ effectType: effect.type }); - - const previewParam = ({ key }: { key: string }) => (value: number | string | boolean) => { - const updatedEffects = (element.effects ?? []).map((existing) => - existing.id !== effect.id - ? existing - : { ...existing, params: { ...existing.params, [key]: value } }, - ); - editor.timeline.previewElements({ - updates: [ - { - trackId, - elementId: element.id, - updates: { effects: updatedEffects }, - }, - ], - }); - }; - - const commitParam = () => editor.timeline.commitPreview(); - - const toggleEffect = () => - editor.timeline.toggleClipEffect({ - trackId, - elementId: element.id, - effectId: effect.id, - }); - - const removeEffect = () => - editor.timeline.removeClipEffect({ - trackId, - elementId: element.id, - effectId: effect.id, - }); - - return ( - <Section sectionKey={`clip-effect:${effect.id}`} showTopBorder={false}> - <SectionHeader - className="cursor-move" - trailing={ - <div className="flex items-center gap-1"> - <Button - variant={effect.enabled ? "secondary" : "ghost"} - size="icon" - aria-label={`Toggle ${definition.name}`} - onClick={toggleEffect} - > - <HugeiconsIcon - icon={effect.enabled ? ViewIcon : ViewOffSlashIcon} - /> - </Button> - <Button - variant="ghost" - size="icon" - aria-label={`Remove ${definition.name}`} - onClick={removeEffect} - > - <HugeiconsIcon icon={Delete02Icon} /> - </Button> - </div> - } - > - <SectionTitle - className={cn(!effect.enabled && "text-muted-foreground")} - > - {definition.name} - </SectionTitle> - </SectionHeader> - {effect.enabled && ( - <SectionContent> - <SectionFields> - {definition.params.map((param) => ( - <EffectParamField - key={param.key} - param={param} - value={effect.params[param.key] ?? param.default} - onPreview={previewParam({ key: param.key })} - onCommit={commitParam} - /> - ))} - </SectionFields> - </SectionContent> - )} - </Section> - ); -} |
