diff --git a/node_modules/.vite/deps/_metadata.json b/node_modules/.vite/deps/_metadata.json index d216091e..6cfee876 100644 --- a/node_modules/.vite/deps/_metadata.json +++ b/node_modules/.vite/deps/_metadata.json @@ -1,61 +1,61 @@ { - "hash": "43216e8d", - "configHash": "0b9ed782", + "hash": "480f37ab", + "configHash": "e652d8ff", "lockfileHash": "dadb379e", - "browserHash": "4f0bb7c4", + "browserHash": "55e2ae32", "optimized": { "@nanostores/persistent": { "src": "../../.pnpm/@nanostores+persistent@1.1.0_nanostores@1.0.1/node_modules/@nanostores/persistent/index.js", "file": "@nanostores_persistent.js", - "fileHash": "7596f610", + "fileHash": "41270c63", "needsInterop": false }, "@nanostores/react": { "src": "../../.pnpm/@nanostores+react@1.0.0_nanostores@1.0.1_react@19.1.1/node_modules/@nanostores/react/index.js", "file": "@nanostores_react.js", - "fileHash": "19e1624e", + "fileHash": "125eb5ad", "needsInterop": false }, "jszip": { "src": "../../.pnpm/jszip@3.10.1/node_modules/jszip/dist/jszip.min.js", "file": "jszip.js", - "fileHash": "e59e7578", + "fileHash": "ea14d80a", "needsInterop": true }, "lucide-react": { "src": "../../.pnpm/lucide-react@0.544.0_react@19.1.1/node_modules/lucide-react/dist/esm/lucide-react.js", "file": "lucide-react.js", - "fileHash": "f256b1cf", + "fileHash": "347cd426", "needsInterop": false }, "react-dom": { "src": "../../.pnpm/react-dom@19.1.1_react@19.1.1/node_modules/react-dom/index.js", "file": "react-dom.js", - "fileHash": "74c66a5f", + "fileHash": "67fe1167", "needsInterop": true }, "react-dom/client": { "src": "../../.pnpm/react-dom@19.1.1_react@19.1.1/node_modules/react-dom/client.js", "file": "react-dom_client.js", - "fileHash": "41baaeaa", + "fileHash": "9c5fd5d6", "needsInterop": true }, "react": { "src": "../../.pnpm/react@19.1.1/node_modules/react/index.js", "file": "react.js", - "fileHash": "37acbd53", + "fileHash": "35a8de87", "needsInterop": true }, "react/jsx-dev-runtime": { "src": "../../.pnpm/react@19.1.1/node_modules/react/jsx-dev-runtime.js", "file": "react_jsx-dev-runtime.js", - "fileHash": "bf9c5ec3", + "fileHash": "675ff029", "needsInterop": true }, "react/jsx-runtime": { "src": "../../.pnpm/react@19.1.1/node_modules/react/jsx-runtime.js", "file": "react_jsx-runtime.js", - "fileHash": "082ac5fc", + "fileHash": "4bc2e93d", "needsInterop": true } }, diff --git a/src/App.tsx b/src/App.tsx index bc2fc0da..4f6889a0 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -114,8 +114,8 @@ function App() { } } - const handleEffectChange = (parameterId: string, value: number) => { - effectSettings.setKey(parameterId as keyof typeof effectValues, value) + const handleEffectChange = (parameterId: string, value: number | boolean) => { + effectSettings.setKey(parameterId as any, value as any) if (playbackManagerRef.current) { playbackManagerRef.current.setEffects(effectValues) } diff --git a/src/components/EffectsBar.tsx b/src/components/EffectsBar.tsx index 8a3dc86a..7207c1f2 100644 --- a/src/components/EffectsBar.tsx +++ b/src/components/EffectsBar.tsx @@ -1,11 +1,12 @@ import { Slider } from './Slider' +import { Switch } from './Switch' import { EFFECTS } from '../config/effects' import { getClipModeLabel } from '../utils/formatters' import type { EffectValues } from '../types/effects' interface EffectsBarProps { values: EffectValues - onChange: (parameterId: string, value: number) => void + onChange: (parameterId: string, value: number | boolean) => void } export function EffectsBar({ values, onChange }: EffectsBarProps) { @@ -18,23 +19,39 @@ export function EffectsBar({ values, onChange }: EffectsBarProps) { return (
-
- {EFFECTS.flatMap(effect => - effect.parameters.map(param => ( - onChange(param.id, value)} - formatValue={param.id === 'clipMode' ? formatValue : undefined} - valueId={param.id} - /> - )) - )} +
+ {EFFECTS.map(effect => ( +
+
+

+ {effect.name.toUpperCase()} +

+ {effect.bypassable && ( + onChange(`${effect.id}Bypass`, !checked)} + label={Boolean(values[`${effect.id}Bypass`]) ? 'OFF' : 'ON'} + /> + )} +
+
+ {effect.parameters.map(param => ( + onChange(param.id, value)} + formatValue={param.id === 'clipMode' ? formatValue : undefined} + valueId={param.id} + /> + ))} +
+
+ ))}
) diff --git a/src/components/EngineControls.tsx b/src/components/EngineControls.tsx index 20109295..36e4c0b6 100644 --- a/src/components/EngineControls.tsx +++ b/src/components/EngineControls.tsx @@ -31,7 +31,7 @@ export function EngineControls({ values, onChange }: EngineControlsProps) { {param.label.toUpperCase()} - {formatValue(param.id, values[param.id] ?? param.default)} + {formatValue(param.id, (values[param.id] as number) ?? param.default)}
onChange(param.id, Number(e.target.value))} className="w-full h-[2px] bg-white appearance-none cursor-pointer" /> diff --git a/src/components/Switch.tsx b/src/components/Switch.tsx new file mode 100644 index 00000000..1b5df511 --- /dev/null +++ b/src/components/Switch.tsx @@ -0,0 +1,29 @@ +interface SwitchProps { + checked: boolean + onChange: (checked: boolean) => void + label?: string +} + +export function Switch({ checked, onChange, label }: SwitchProps) { + return ( +