mirror of
https://github.com/OpenCut-app/OpenCut.git
synced 2026-07-13 21:52:53 +02:00
fix: resolve typescript/lint errors
This commit is contained in:
@@ -6,6 +6,7 @@ import { useRouter } from "next/navigation";
|
|||||||
import type { KeyboardEvent, MouseEvent } from "react";
|
import type { KeyboardEvent, MouseEvent } from "react";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
|
import type { EditorCore } from "@/core";
|
||||||
import { MigrationDialog } from "@/components/editor/dialogs/migration-dialog";
|
import { MigrationDialog } from "@/components/editor/dialogs/migration-dialog";
|
||||||
import { StoragePersistenceDialog } from "@/components/editor/dialogs/storage-persistence-dialog";
|
import { StoragePersistenceDialog } from "@/components/editor/dialogs/storage-persistence-dialog";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
@@ -359,7 +360,7 @@ async function deleteProjects({
|
|||||||
editor,
|
editor,
|
||||||
ids,
|
ids,
|
||||||
}: {
|
}: {
|
||||||
editor: ReturnType<typeof useEditor>;
|
editor: EditorCore;
|
||||||
ids: string[];
|
ids: string[];
|
||||||
}) {
|
}) {
|
||||||
await editor.project.deleteProjects({ ids });
|
await editor.project.deleteProjects({ ids });
|
||||||
@@ -369,7 +370,7 @@ async function duplicateProjects({
|
|||||||
editor,
|
editor,
|
||||||
ids,
|
ids,
|
||||||
}: {
|
}: {
|
||||||
editor: ReturnType<typeof useEditor>;
|
editor: EditorCore;
|
||||||
ids: string[];
|
ids: string[];
|
||||||
}) {
|
}) {
|
||||||
await editor.project.duplicateProjects({ ids });
|
await editor.project.duplicateProjects({ ids });
|
||||||
@@ -380,7 +381,7 @@ async function renameProject({
|
|||||||
id,
|
id,
|
||||||
name,
|
name,
|
||||||
}: {
|
}: {
|
||||||
editor: ReturnType<typeof useEditor>;
|
editor: EditorCore;
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
}) {
|
}) {
|
||||||
|
|||||||
@@ -551,7 +551,6 @@ export function Timeline() {
|
|||||||
timelineRef={timelineRef}
|
timelineRef={timelineRef}
|
||||||
tracksScrollRef={tracksScrollRef}
|
tracksScrollRef={tracksScrollRef}
|
||||||
isVisible={showSnapIndicator}
|
isVisible={showSnapIndicator}
|
||||||
tracks={tracks}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
@@ -134,20 +134,28 @@ function NumberField({
|
|||||||
ref,
|
ref,
|
||||||
...props
|
...props
|
||||||
}: NumberFieldProps & { ref?: React.Ref<HTMLInputElement> }) {
|
}: NumberFieldProps & { ref?: React.Ref<HTMLInputElement> }) {
|
||||||
const iconRef = useRef<HTMLSpanElement>(null);
|
const iconRef = useRef<HTMLButtonElement>(null);
|
||||||
const inputRef = useRef<HTMLInputElement>(null);
|
const inputRef = useRef<HTMLInputElement>(null);
|
||||||
const ghostRef = useRef<HTMLSpanElement>(null);
|
const ghostRef = useRef<HTMLSpanElement>(null);
|
||||||
const startValueRef = useRef(0);
|
const startValueRef = useRef(0);
|
||||||
const cumulativeDeltaRef = useRef(0);
|
const cumulativeDeltaRef = useRef(0);
|
||||||
const [isInputFocused, setIsInputFocused] = useState(false);
|
const [isInputFocused, setIsInputFocused] = useState(false);
|
||||||
const [suffixLeft, setSuffixLeft] = useState(0);
|
const [suffixLeft, setSuffixLeft] = useState(0);
|
||||||
|
const ghostValue = Array.isArray(value) ? value.join(", ") : String(value ?? "");
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
if (!suffix || !ghostRef.current || !inputRef.current) return;
|
if (!suffix) {
|
||||||
|
setSuffixLeft(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!ghostRef.current || !inputRef.current) return;
|
||||||
|
if (ghostRef.current.textContent !== ghostValue) {
|
||||||
|
ghostRef.current.textContent = ghostValue;
|
||||||
|
}
|
||||||
const paddingLeft =
|
const paddingLeft =
|
||||||
parseFloat(getComputedStyle(inputRef.current).paddingLeft) || 0;
|
parseFloat(getComputedStyle(inputRef.current).paddingLeft) || 0;
|
||||||
setSuffixLeft(paddingLeft + ghostRef.current.offsetWidth);
|
setSuffixLeft(paddingLeft + ghostRef.current.offsetWidth);
|
||||||
}, [value, suffix]);
|
}, [ghostValue, suffix]);
|
||||||
|
|
||||||
const { containerRef: wrapperRef } = useFocusLock<HTMLDivElement>({
|
const { containerRef: wrapperRef } = useFocusLock<HTMLDivElement>({
|
||||||
isActive: isInputFocused,
|
isActive: isInputFocused,
|
||||||
@@ -243,19 +251,24 @@ function NumberField({
|
|||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{icon && (
|
{icon &&
|
||||||
<span
|
(canScrub ? (
|
||||||
ref={iconRef}
|
<button
|
||||||
className={cn(
|
ref={iconRef}
|
||||||
"text-muted-foreground [&_svg]:size-3.5! shrink-0 select-none pl-2.5 text-sm leading-none",
|
type="button"
|
||||||
canScrub && "cursor-ew-resize",
|
aria-label="Drag to adjust value"
|
||||||
)}
|
disabled={disabled}
|
||||||
onMouseDown={canScrub ? (event) => event.preventDefault() : undefined}
|
className="text-muted-foreground [&_svg]:size-3.5! shrink-0 select-none pl-2.5 text-sm leading-none cursor-ew-resize"
|
||||||
onPointerDown={canScrub ? handleIconPointerDown : undefined}
|
onMouseDown={(event) => event.preventDefault()}
|
||||||
>
|
onPointerDown={handleIconPointerDown}
|
||||||
{icon}
|
>
|
||||||
</span>
|
{icon}
|
||||||
)}
|
</button>
|
||||||
|
) : (
|
||||||
|
<span className="text-muted-foreground [&_svg]:size-3.5! shrink-0 select-none pl-2.5 text-sm leading-none">
|
||||||
|
{icon}
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
<span
|
<span
|
||||||
className={cn(
|
className={cn(
|
||||||
"relative flex flex-1 min-w-0 items-center",
|
"relative flex flex-1 min-w-0 items-center",
|
||||||
@@ -272,7 +285,7 @@ function NumberField({
|
|||||||
className="invisible absolute text-sm leading-none whitespace-pre pointer-events-none"
|
className="invisible absolute text-sm leading-none whitespace-pre pointer-events-none"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
>
|
>
|
||||||
{value}
|
{ghostValue}
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
className={cn(
|
className={cn(
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import { useMemo } from "react";
|
import { useMemo } from "react";
|
||||||
import { useKeybindingsStore } from "@/stores/keybindings-store";
|
import { useKeybindingsStore } from "@/stores/keybindings-store";
|
||||||
import { ACTIONS, type TAction } from "@/lib/actions";
|
import { ACTIONS, type TActionWithOptionalArgs } from "@/lib/actions";
|
||||||
import {
|
import {
|
||||||
getPlatformAlternateKey,
|
getPlatformAlternateKey,
|
||||||
getPlatformSpecialKey,
|
getPlatformSpecialKey,
|
||||||
@@ -13,7 +13,7 @@ export interface KeyboardShortcut {
|
|||||||
keys: string[];
|
keys: string[];
|
||||||
description: string;
|
description: string;
|
||||||
category: string;
|
category: string;
|
||||||
action: TAction;
|
action: TActionWithOptionalArgs;
|
||||||
icon?: React.ReactNode;
|
icon?: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,9 +40,11 @@ export function useKeyboardShortcutsHelp() {
|
|||||||
|
|
||||||
const shortcuts = useMemo(() => {
|
const shortcuts = useMemo(() => {
|
||||||
const result: KeyboardShortcut[] = [];
|
const result: KeyboardShortcut[] = [];
|
||||||
const actionToKeys: Record<string, string[]> = {};
|
const actionToKeys: Partial<Record<TActionWithOptionalArgs, string[]>> = {};
|
||||||
|
|
||||||
for (const [key, action] of Object.entries(keybindings)) {
|
for (const [key, action] of Object.entries(keybindings) as Array<
|
||||||
|
[string, TActionWithOptionalArgs | undefined]
|
||||||
|
>) {
|
||||||
if (action) {
|
if (action) {
|
||||||
if (!actionToKeys[action]) {
|
if (!actionToKeys[action]) {
|
||||||
actionToKeys[action] = [];
|
actionToKeys[action] = [];
|
||||||
@@ -51,16 +53,16 @@ export function useKeyboardShortcutsHelp() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const [actionId, keys] of Object.entries(actionToKeys)) {
|
for (const [action, keys] of Object.entries(actionToKeys) as Array<
|
||||||
if (!isAction(actionId)) continue;
|
[TActionWithOptionalArgs, string[]]
|
||||||
|
>) {
|
||||||
const actionDef = ACTIONS[actionId];
|
const actionDef = ACTIONS[action];
|
||||||
result.push({
|
result.push({
|
||||||
id: actionId,
|
id: action,
|
||||||
keys,
|
keys,
|
||||||
description: actionDef.description,
|
description: actionDef.description,
|
||||||
category: actionDef.category,
|
category: actionDef.category,
|
||||||
action: actionId,
|
action,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,7 +78,3 @@ export function useKeyboardShortcutsHelp() {
|
|||||||
shortcuts,
|
shortcuts,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function isAction(id: string): id is TAction {
|
|
||||||
return id in ACTIONS;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
import type { ShortcutKey } from "@/lib/actions/keybinding";
|
import type {
|
||||||
|
KeybindingConfig,
|
||||||
|
ShortcutKey,
|
||||||
|
} from "@/lib/actions/keybinding";
|
||||||
|
import type { TActionWithOptionalArgs } from "./types";
|
||||||
|
|
||||||
export type TActionCategory =
|
export type TActionCategory =
|
||||||
| "playback"
|
| "playback"
|
||||||
@@ -10,18 +14,20 @@ export type TActionCategory =
|
|||||||
| "controls"
|
| "controls"
|
||||||
| "assets";
|
| "assets";
|
||||||
|
|
||||||
export interface TActionDefinition {
|
export interface TActionBaseDefinition {
|
||||||
description: string;
|
description: string;
|
||||||
category: TActionCategory;
|
category: TActionCategory;
|
||||||
defaultShortcuts?: ShortcutKey[];
|
|
||||||
args?: Record<string, unknown>;
|
args?: Record<string, unknown>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface TActionDefinition extends TActionBaseDefinition {
|
||||||
|
defaultShortcuts?: readonly ShortcutKey[];
|
||||||
|
}
|
||||||
|
|
||||||
export const ACTIONS = {
|
export const ACTIONS = {
|
||||||
"toggle-play": {
|
"toggle-play": {
|
||||||
description: "Play/Pause",
|
description: "Play/Pause",
|
||||||
category: "playback",
|
category: "playback",
|
||||||
defaultShortcuts: ["space", "k"],
|
|
||||||
},
|
},
|
||||||
"stop-playback": {
|
"stop-playback": {
|
||||||
description: "Stop playback",
|
description: "Stop playback",
|
||||||
@@ -30,81 +36,66 @@ export const ACTIONS = {
|
|||||||
"seek-forward": {
|
"seek-forward": {
|
||||||
description: "Seek forward 1 second",
|
description: "Seek forward 1 second",
|
||||||
category: "playback",
|
category: "playback",
|
||||||
defaultShortcuts: ["l"],
|
|
||||||
args: { seconds: "number" },
|
args: { seconds: "number" },
|
||||||
},
|
},
|
||||||
"seek-backward": {
|
"seek-backward": {
|
||||||
description: "Seek backward 1 second",
|
description: "Seek backward 1 second",
|
||||||
category: "playback",
|
category: "playback",
|
||||||
defaultShortcuts: ["j"],
|
|
||||||
args: { seconds: "number" },
|
args: { seconds: "number" },
|
||||||
},
|
},
|
||||||
"frame-step-forward": {
|
"frame-step-forward": {
|
||||||
description: "Frame step forward",
|
description: "Frame step forward",
|
||||||
category: "navigation",
|
category: "navigation",
|
||||||
defaultShortcuts: ["right"],
|
|
||||||
},
|
},
|
||||||
"frame-step-backward": {
|
"frame-step-backward": {
|
||||||
description: "Frame step backward",
|
description: "Frame step backward",
|
||||||
category: "navigation",
|
category: "navigation",
|
||||||
defaultShortcuts: ["left"],
|
|
||||||
},
|
},
|
||||||
"jump-forward": {
|
"jump-forward": {
|
||||||
description: "Jump forward 5 seconds",
|
description: "Jump forward 5 seconds",
|
||||||
category: "navigation",
|
category: "navigation",
|
||||||
defaultShortcuts: ["shift+right"],
|
|
||||||
args: { seconds: "number" },
|
args: { seconds: "number" },
|
||||||
},
|
},
|
||||||
"jump-backward": {
|
"jump-backward": {
|
||||||
description: "Jump backward 5 seconds",
|
description: "Jump backward 5 seconds",
|
||||||
category: "navigation",
|
category: "navigation",
|
||||||
defaultShortcuts: ["shift+left"],
|
|
||||||
args: { seconds: "number" },
|
args: { seconds: "number" },
|
||||||
},
|
},
|
||||||
"goto-start": {
|
"goto-start": {
|
||||||
description: "Go to timeline start",
|
description: "Go to timeline start",
|
||||||
category: "navigation",
|
category: "navigation",
|
||||||
defaultShortcuts: ["home", "enter"],
|
|
||||||
},
|
},
|
||||||
"goto-end": {
|
"goto-end": {
|
||||||
description: "Go to timeline end",
|
description: "Go to timeline end",
|
||||||
category: "navigation",
|
category: "navigation",
|
||||||
defaultShortcuts: ["end"],
|
|
||||||
},
|
},
|
||||||
split: {
|
split: {
|
||||||
description: "Split elements at playhead",
|
description: "Split elements at playhead",
|
||||||
category: "editing",
|
category: "editing",
|
||||||
defaultShortcuts: ["s"],
|
|
||||||
},
|
},
|
||||||
"split-left": {
|
"split-left": {
|
||||||
description: "Split and remove left",
|
description: "Split and remove left",
|
||||||
category: "editing",
|
category: "editing",
|
||||||
defaultShortcuts: ["q"],
|
|
||||||
},
|
},
|
||||||
"split-right": {
|
"split-right": {
|
||||||
description: "Split and remove right",
|
description: "Split and remove right",
|
||||||
category: "editing",
|
category: "editing",
|
||||||
defaultShortcuts: ["w"],
|
|
||||||
},
|
},
|
||||||
"delete-selected": {
|
"delete-selected": {
|
||||||
description: "Delete selected elements",
|
description: "Delete selected elements",
|
||||||
category: "editing",
|
category: "editing",
|
||||||
defaultShortcuts: ["backspace", "delete"],
|
|
||||||
},
|
},
|
||||||
"copy-selected": {
|
"copy-selected": {
|
||||||
description: "Copy selected elements",
|
description: "Copy selected elements",
|
||||||
category: "editing",
|
category: "editing",
|
||||||
defaultShortcuts: ["ctrl+c"],
|
|
||||||
},
|
},
|
||||||
"paste-copied": {
|
"paste-copied": {
|
||||||
description: "Paste elements at playhead",
|
description: "Paste elements at playhead",
|
||||||
category: "editing",
|
category: "editing",
|
||||||
defaultShortcuts: ["ctrl+v"],
|
|
||||||
},
|
},
|
||||||
"toggle-snapping": {
|
"toggle-snapping": {
|
||||||
description: "Toggle snapping",
|
description: "Toggle snapping",
|
||||||
category: "editing",
|
category: "editing",
|
||||||
defaultShortcuts: ["n"],
|
|
||||||
},
|
},
|
||||||
"toggle-ripple-editing": {
|
"toggle-ripple-editing": {
|
||||||
description: "Toggle ripple editing",
|
description: "Toggle ripple editing",
|
||||||
@@ -113,12 +104,10 @@ export const ACTIONS = {
|
|||||||
"select-all": {
|
"select-all": {
|
||||||
description: "Select all elements",
|
description: "Select all elements",
|
||||||
category: "selection",
|
category: "selection",
|
||||||
defaultShortcuts: ["ctrl+a"],
|
|
||||||
},
|
},
|
||||||
"cancel-interaction": {
|
"cancel-interaction": {
|
||||||
description: "Cancel current interaction",
|
description: "Cancel current interaction",
|
||||||
category: "controls",
|
category: "controls",
|
||||||
defaultShortcuts: ["escape"],
|
|
||||||
},
|
},
|
||||||
"deselect-all": {
|
"deselect-all": {
|
||||||
description: "Deselect all elements",
|
description: "Deselect all elements",
|
||||||
@@ -127,7 +116,6 @@ export const ACTIONS = {
|
|||||||
"duplicate-selected": {
|
"duplicate-selected": {
|
||||||
description: "Duplicate selected element",
|
description: "Duplicate selected element",
|
||||||
category: "selection",
|
category: "selection",
|
||||||
defaultShortcuts: ["ctrl+d"],
|
|
||||||
},
|
},
|
||||||
"toggle-elements-muted-selected": {
|
"toggle-elements-muted-selected": {
|
||||||
description: "Mute/unmute selected elements",
|
description: "Mute/unmute selected elements",
|
||||||
@@ -144,12 +132,10 @@ export const ACTIONS = {
|
|||||||
undo: {
|
undo: {
|
||||||
description: "Undo",
|
description: "Undo",
|
||||||
category: "history",
|
category: "history",
|
||||||
defaultShortcuts: ["ctrl+z"],
|
|
||||||
},
|
},
|
||||||
redo: {
|
redo: {
|
||||||
description: "Redo",
|
description: "Redo",
|
||||||
category: "history",
|
category: "history",
|
||||||
defaultShortcuts: ["ctrl+shift+z", "ctrl+y"],
|
|
||||||
},
|
},
|
||||||
"remove-media-asset": {
|
"remove-media-asset": {
|
||||||
description: "Remove media asset",
|
description: "Remove media asset",
|
||||||
@@ -161,30 +147,59 @@ export const ACTIONS = {
|
|||||||
category: "assets",
|
category: "assets",
|
||||||
args: { projectId: "string", assetIds: "string[]" },
|
args: { projectId: "string", assetIds: "string[]" },
|
||||||
},
|
},
|
||||||
} as const satisfies Record<string, TActionDefinition>;
|
} as const satisfies Record<string, TActionBaseDefinition>;
|
||||||
|
|
||||||
export type TAction = keyof typeof ACTIONS;
|
export type TAction = keyof typeof ACTIONS;
|
||||||
|
|
||||||
|
const ACTION_DEFAULT_SHORTCUTS = {
|
||||||
|
"toggle-play": ["space", "k"],
|
||||||
|
"seek-forward": ["l"],
|
||||||
|
"seek-backward": ["j"],
|
||||||
|
"frame-step-forward": ["right"],
|
||||||
|
"frame-step-backward": ["left"],
|
||||||
|
"jump-forward": ["shift+right"],
|
||||||
|
"jump-backward": ["shift+left"],
|
||||||
|
"goto-start": ["home", "enter"],
|
||||||
|
"goto-end": ["end"],
|
||||||
|
split: ["s"],
|
||||||
|
"split-left": ["q"],
|
||||||
|
"split-right": ["w"],
|
||||||
|
"delete-selected": ["backspace", "delete"],
|
||||||
|
"copy-selected": ["ctrl+c"],
|
||||||
|
"paste-copied": ["ctrl+v"],
|
||||||
|
"toggle-snapping": ["n"],
|
||||||
|
"select-all": ["ctrl+a"],
|
||||||
|
"cancel-interaction": ["escape"],
|
||||||
|
"duplicate-selected": ["ctrl+d"],
|
||||||
|
undo: ["ctrl+z"],
|
||||||
|
redo: ["ctrl+shift+z", "ctrl+y"],
|
||||||
|
} as const satisfies Partial<Record<TActionWithOptionalArgs, readonly ShortcutKey[]>>;
|
||||||
|
|
||||||
|
const ACTION_DEFAULT_SHORTCUTS_BY_ACTION: Partial<
|
||||||
|
Record<TAction, readonly ShortcutKey[]>
|
||||||
|
> = ACTION_DEFAULT_SHORTCUTS;
|
||||||
|
|
||||||
export function getActionDefinition({
|
export function getActionDefinition({
|
||||||
action,
|
action,
|
||||||
}: {
|
}: {
|
||||||
action: TAction;
|
action: TAction;
|
||||||
}): TActionDefinition {
|
}): TActionDefinition {
|
||||||
return ACTIONS[action];
|
return {
|
||||||
|
...ACTIONS[action],
|
||||||
|
defaultShortcuts: ACTION_DEFAULT_SHORTCUTS_BY_ACTION[action],
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getDefaultShortcuts(): Record<ShortcutKey, TAction> {
|
export function getDefaultShortcuts(): KeybindingConfig {
|
||||||
const shortcuts: Record<string, TAction> = {};
|
const shortcuts: KeybindingConfig = {};
|
||||||
|
|
||||||
for (const [action, def] of Object.entries(ACTIONS) as Array<
|
for (const [action, defaultShortcuts] of Object.entries(
|
||||||
[TAction, TActionDefinition]
|
ACTION_DEFAULT_SHORTCUTS,
|
||||||
>) {
|
) as Array<[TActionWithOptionalArgs, readonly ShortcutKey[]]>) {
|
||||||
if (def.defaultShortcuts) {
|
for (const shortcut of defaultShortcuts) {
|
||||||
for (const shortcut of def.defaultShortcuts) {
|
shortcuts[shortcut] = action;
|
||||||
shortcuts[shortcut] = action;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return shortcuts as Record<ShortcutKey, TAction>;
|
return shortcuts;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,11 +26,9 @@ export function buildEffectParamPath({
|
|||||||
return `${EFFECT_PARAM_PATH_PREFIX}${effectId}${EFFECT_PARAM_PATH_SUFFIX}${paramKey}`;
|
return `${EFFECT_PARAM_PATH_PREFIX}${effectId}${EFFECT_PARAM_PATH_SUFFIX}${paramKey}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isEffectParamPath({
|
export function isEffectParamPath(
|
||||||
propertyPath,
|
propertyPath: string,
|
||||||
}: {
|
): propertyPath is EffectParamPath {
|
||||||
propertyPath: string;
|
|
||||||
}): propertyPath is EffectParamPath {
|
|
||||||
return (
|
return (
|
||||||
propertyPath.startsWith(EFFECT_PARAM_PATH_PREFIX) &&
|
propertyPath.startsWith(EFFECT_PARAM_PATH_PREFIX) &&
|
||||||
propertyPath.includes(EFFECT_PARAM_PATH_SUFFIX)
|
propertyPath.includes(EFFECT_PARAM_PATH_SUFFIX)
|
||||||
@@ -42,7 +40,7 @@ export function parseEffectParamPath({
|
|||||||
}: {
|
}: {
|
||||||
propertyPath: string;
|
propertyPath: string;
|
||||||
}): { effectId: string; paramKey: string } | null {
|
}): { effectId: string; paramKey: string } | null {
|
||||||
if (!isEffectParamPath({ propertyPath })) {
|
if (!isEffectParamPath(propertyPath)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,11 +20,9 @@ export function buildGraphicParamPath({
|
|||||||
return `${GRAPHIC_PARAM_PATH_PREFIX}${paramKey}`;
|
return `${GRAPHIC_PARAM_PATH_PREFIX}${paramKey}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isGraphicParamPath({
|
export function isGraphicParamPath(
|
||||||
propertyPath,
|
propertyPath: string,
|
||||||
}: {
|
): propertyPath is GraphicParamPath {
|
||||||
propertyPath: string;
|
|
||||||
}): propertyPath is GraphicParamPath {
|
|
||||||
return propertyPath.startsWith(GRAPHIC_PARAM_PATH_PREFIX);
|
return propertyPath.startsWith(GRAPHIC_PARAM_PATH_PREFIX);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,7 +31,7 @@ export function parseGraphicParamPath({
|
|||||||
}: {
|
}: {
|
||||||
propertyPath: string;
|
propertyPath: string;
|
||||||
}): { paramKey: string } | null {
|
}): { paramKey: string } | null {
|
||||||
if (!isGraphicParamPath({ propertyPath })) {
|
if (!isGraphicParamPath(propertyPath)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export function getElementKeyframes({
|
|||||||
if (
|
if (
|
||||||
!channel ||
|
!channel ||
|
||||||
channel.keyframes.length === 0 ||
|
channel.keyframes.length === 0 ||
|
||||||
!isAnimationPath({ propertyPath })
|
!isAnimationPath(propertyPath)
|
||||||
) {
|
) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -616,8 +616,8 @@ export function splitAnimationsAtTime({
|
|||||||
time: splitTime,
|
time: splitTime,
|
||||||
fallbackValue: normalizedChannel.keyframes[0].value,
|
fallbackValue: normalizedChannel.keyframes[0].value,
|
||||||
});
|
});
|
||||||
const knownPropertyPath = isAnimationPropertyPath({ propertyPath })
|
const knownPropertyPath = isAnimationPropertyPath(propertyPath)
|
||||||
? (propertyPath as AnimationPropertyPath)
|
? propertyPath
|
||||||
: null;
|
: null;
|
||||||
const boundaryInterpolation = knownPropertyPath
|
const boundaryInterpolation = knownPropertyPath
|
||||||
? getDefaultInterpolationForProperty({
|
? getDefaultInterpolationForProperty({
|
||||||
|
|||||||
@@ -245,12 +245,10 @@ const ANIMATION_PROPERTY_REGISTRY: Record<
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export function isAnimationPropertyPath({
|
export function isAnimationPropertyPath(
|
||||||
propertyPath,
|
propertyPath: string,
|
||||||
}: {
|
): propertyPath is AnimationPropertyPath {
|
||||||
propertyPath: string;
|
return Object.hasOwn(ANIMATION_PROPERTY_REGISTRY, propertyPath);
|
||||||
}): boolean {
|
|
||||||
return propertyPath in ANIMATION_PROPERTY_REGISTRY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getAnimationPropertyDefinition({
|
export function getAnimationPropertyDefinition({
|
||||||
|
|||||||
@@ -204,15 +204,13 @@ function buildEffectParamDescriptor({
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isAnimationPath({
|
export function isAnimationPath(
|
||||||
propertyPath,
|
propertyPath: string,
|
||||||
}: {
|
): propertyPath is AnimationPath {
|
||||||
propertyPath: string;
|
|
||||||
}): propertyPath is AnimationPath {
|
|
||||||
return (
|
return (
|
||||||
isAnimationPropertyPath({ propertyPath }) ||
|
isAnimationPropertyPath(propertyPath) ||
|
||||||
isGraphicParamPath({ propertyPath }) ||
|
isGraphicParamPath(propertyPath) ||
|
||||||
isEffectParamPath({ propertyPath })
|
isEffectParamPath(propertyPath)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,7 +221,7 @@ export function resolveAnimationTarget({
|
|||||||
element: TimelineElement;
|
element: TimelineElement;
|
||||||
path: AnimationPath;
|
path: AnimationPath;
|
||||||
}): AnimationPathDescriptor | null {
|
}): AnimationPathDescriptor | null {
|
||||||
if (isAnimationPropertyPath({ propertyPath: path })) {
|
if (isAnimationPropertyPath(path)) {
|
||||||
const propertyDefinition = getAnimationPropertyDefinition({
|
const propertyDefinition = getAnimationPropertyDefinition({
|
||||||
propertyPath: path,
|
propertyPath: path,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ export function clampDb(value: number): number {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function dBToLinear(db: number): number {
|
export function dBToLinear(db: number): number {
|
||||||
return Math.pow(10, clampDb(db) / 20);
|
return 10 ** (clampDb(db) / 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function hasAnimatedVolume({
|
export function hasAnimatedVolume({
|
||||||
|
|||||||
@@ -6,7 +6,11 @@ import type {
|
|||||||
import { TRACK_CONFIG, TRACK_GAP } from "@/constants/timeline-constants";
|
import { TRACK_CONFIG, TRACK_GAP } from "@/constants/timeline-constants";
|
||||||
import { wouldElementOverlap } from "./element-utils";
|
import { wouldElementOverlap } from "./element-utils";
|
||||||
import type { ComputeDropTargetParams, DropTarget } from "@/lib/timeline";
|
import type { ComputeDropTargetParams, DropTarget } from "@/lib/timeline";
|
||||||
import { isMainTrack, enforceMainTrackStart } from "./track-utils";
|
import {
|
||||||
|
canElementGoOnTrack,
|
||||||
|
isMainTrack,
|
||||||
|
enforceMainTrackStart,
|
||||||
|
} from "./track-utils";
|
||||||
|
|
||||||
function findElementAtPosition({
|
function findElementAtPosition({
|
||||||
mouseX,
|
mouseX,
|
||||||
@@ -85,14 +89,7 @@ function isCompatible({
|
|||||||
elementType: ElementType;
|
elementType: ElementType;
|
||||||
trackType: TimelineTrack["type"];
|
trackType: TimelineTrack["type"];
|
||||||
}): boolean {
|
}): boolean {
|
||||||
if (elementType === "text") return trackType === "text";
|
return canElementGoOnTrack({ elementType, trackType });
|
||||||
if (elementType === "audio") return trackType === "audio";
|
|
||||||
if (elementType === "sticker") return trackType === "sticker";
|
|
||||||
if (elementType === "effect") return trackType === "effect";
|
|
||||||
if (elementType === "video" || elementType === "image") {
|
|
||||||
return trackType === "video";
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getMainTrackIndex({ tracks }: { tracks: TimelineTrack[] }): number {
|
function getMainTrackIndex({ tracks }: { tracks: TimelineTrack[] }): number {
|
||||||
|
|||||||
Reference in New Issue
Block a user