diff --git a/packages/studio/src/components/editor/propertyPanelFlatMediaSection.test.tsx b/packages/studio/src/components/editor/propertyPanelFlatMediaSection.test.tsx
index d77472a88..cce0af420 100644
--- a/packages/studio/src/components/editor/propertyPanelFlatMediaSection.test.tsx
+++ b/packages/studio/src/components/editor/propertyPanelFlatMediaSection.test.tsx
@@ -364,3 +364,70 @@ describe("FlatMediaSection — loop/muted/has-audio", () => {
act(() => root.unmount());
});
});
+
+describe("FlatMediaSection — fit/position", () => {
+ it("commits object-fit and object-position changes", () => {
+ const onSetStyle = vi.fn();
+ const { host, root } = (() => {
+ const element = makeVideoElement();
+ const host = document.createElement("div");
+ document.body.append(host);
+ const root = createRoot(host);
+ act(() => {
+ root.render(
+ ,
+ );
+ });
+ return { host, root };
+ })();
+ const selects = host.querySelectorAll("select");
+ const fitSelect = Array.from(selects).find((s) => s.value === "cover");
+ expect(fitSelect).not.toBeUndefined();
+ act(() => {
+ if (fitSelect) {
+ fitSelect.value = "contain";
+ fitSelect.dispatchEvent(new Event("change", { bubbles: true }));
+ }
+ });
+ expect(onSetStyle).toHaveBeenCalledWith("object-fit", "contain");
+ act(() => root.unmount());
+ });
+
+ it("commits an object-position change", () => {
+ const onSetStyle = vi.fn();
+ const element = makeVideoElement();
+ const host = document.createElement("div");
+ document.body.append(host);
+ const root = createRoot(host);
+ act(() => {
+ root.render(
+ ,
+ );
+ });
+ const selects = host.querySelectorAll("select");
+ const positionSelect = Array.from(selects).find((s) => s.value === "center");
+ expect(positionSelect).not.toBeUndefined();
+ act(() => {
+ if (positionSelect) {
+ positionSelect.value = "left top";
+ positionSelect.dispatchEvent(new Event("change", { bubbles: true }));
+ }
+ });
+ expect(onSetStyle).toHaveBeenCalledWith("object-position", "left top");
+ act(() => root.unmount());
+ });
+});
diff --git a/packages/studio/src/components/editor/propertyPanelFlatMediaSection.tsx b/packages/studio/src/components/editor/propertyPanelFlatMediaSection.tsx
index 37f7a0c71..b3bcca833 100644
--- a/packages/studio/src/components/editor/propertyPanelFlatMediaSection.tsx
+++ b/packages/studio/src/components/editor/propertyPanelFlatMediaSection.tsx
@@ -15,9 +15,7 @@ import { FlatSelectRow, FlatSlider, FlatToggle } from "./propertyPanelFlatPrimit
export function FlatMediaSection({
projectDir,
element,
- // oxlint-disable-next-line no-unused-vars -- wired into the Fit/Position rows in Task 6
styles,
- // oxlint-disable-next-line no-unused-vars -- wired into the Fit/Position rows in Task 6
onSetStyle,
onSetAttribute,
onSetHtmlAttribute,
@@ -59,6 +57,8 @@ export function FlatMediaSection({
const hasLoop = el.hasAttribute("loop");
const hasMuted = el.hasAttribute("muted");
const hasAudio = element.dataAttributes["has-audio"] === "true";
+ const objectFit = styles["object-fit"] || "contain";
+ const objectPosition = styles["object-position"] || "center";
const srcAttr = el.getAttribute("src") ?? "";
const [copied, setCopied] = useState(false);
@@ -248,6 +248,34 @@ export function FlatMediaSection({
)}
>
)}
+ {isVisualMedia && (
+ <>
+ void onSetStyle("object-fit", next)}
+ />
+ void onSetStyle("object-position", next)}
+ />
+ >
+ )}
);
}