diff --git a/packages/studio/src/components/editor/PropertyPanelFlat.tsx b/packages/studio/src/components/editor/PropertyPanelFlat.tsx index 5006f8e0a..59e2a92c8 100644 --- a/packages/studio/src/components/editor/PropertyPanelFlat.tsx +++ b/packages/studio/src/components/editor/PropertyPanelFlat.tsx @@ -16,6 +16,7 @@ import { FlatMotionSection } from "./propertyPanelFlatMotionSection"; import { isCanaryEnabled } from "../../telemetry/canary"; import { audioFxSummary } from "./audioFxSummary"; import { AudioFxGroup } from "./propertyPanelAudioFxGroup"; +import { useVolumeAutomation } from "./useVolumeAutomation"; import { FlatMediaSection } from "./propertyPanelFlatMediaSection"; import { deriveElementTiming } from "./propertyPanelFlatTimingDerivation"; import { createGsapLivePreview } from "./gsapLivePreview"; @@ -67,6 +68,7 @@ export function PropertyPanelFlat({ onSetAttribute, onSetAttributes, onSetAttributeLive, + onSetAttributeQuiet, onApplyColorGradingScope, onSetHtmlAttribute, onRemoveBackground, @@ -255,6 +257,8 @@ export function PropertyPanelFlat({ const showMotionEffects = gsapEffectHandlers !== null; const showMotionGroup = showMotionTiming || showMotionEffects; + const volumeAutomation = useVolumeAutomation(element, onSetAttributeQuiet ?? onSetAttributeLive); + const groups: FlatGroupDescriptor[] = []; if (isTextEditable) { groups.push({ @@ -434,7 +438,7 @@ export function PropertyPanelFlat({ content: ( ), @@ -454,6 +458,7 @@ export function PropertyPanelFlat({ onSetAttribute={onSetAttribute} onSetHtmlAttribute={onSetHtmlAttribute} onRemoveBackground={onRemoveBackground} + {...volumeAutomation} /> ), }); diff --git a/packages/studio/src/components/editor/propertyPanelAudioFxGroup.test.tsx b/packages/studio/src/components/editor/propertyPanelAudioFxGroup.test.tsx new file mode 100644 index 000000000..de4153689 --- /dev/null +++ b/packages/studio/src/components/editor/propertyPanelAudioFxGroup.test.tsx @@ -0,0 +1,358 @@ +// @vitest-environment happy-dom +import { act } from "react"; +import { afterEach, describe, expect, it, vi } from "vitest"; +import { createRoot } from "react-dom/client"; +import { AudioFxGroup } from "./propertyPanelAudioFxGroup.js"; +import type { DomEditSelection } from "./domEditingTypes"; + +(globalThis as unknown as { IS_REACT_ACT_ENVIRONMENT: boolean }).IS_REACT_ACT_ENVIRONMENT = true; + +const CHAIN = JSON.stringify({ + version: 1, + nodes: [{ type: "lowpass", id: "n1", params: { frequency: 900, q: 1.2, poles: "2" } }], +}); + +// Each mount appends its tracks to the document; without clearing, a later +// "only one audio track" case would still find the previous test's sibling. +afterEach(() => { + document.body.innerHTML = ""; +}); + +/** + * A selected `