diff --git a/packages/studio/src/hooks/useDomEditTextCommits.test.tsx b/packages/studio/src/hooks/useDomEditTextCommits.test.tsx
index 3057120c54..c4aeedc7cf 100644
--- a/packages/studio/src/hooks/useDomEditTextCommits.test.tsx
+++ b/packages/studio/src/hooks/useDomEditTextCommits.test.tsx
@@ -335,6 +335,29 @@ describe("useDomEditTextCommits", () => {
expect(outcome).toEqual({ ok: true, persistence });
});
+ it("saves a style map on a selection as one patch, so it is one undo step", async () => {
+ const { iframe, element } = previewElement("
Original
", "card");
+ const persist = vi.fn().mockResolvedValue({ sourceFile: "index.html", changed: true });
+ const hook = renderTextCommitHook(
+ commitParams({
+ previewIframeRef: { current: iframe },
+ domEditSelection: null,
+ persistDomEditOperations: persist,
+ }),
+ );
+
+ await act(async () => {
+ await hook.handleDomStyleCommitForSelection(selectionFor(element), {
+ "border-width": "4px",
+ "border-style": "solid",
+ });
+ });
+
+ expect(persist).toHaveBeenCalledTimes(1);
+ expect(element.style.borderWidth).toBe("4px");
+ expect(element.style.borderStyle).toBe("solid");
+ });
+
it("declines a style commit with no selection, without reaching the writer", async () => {
const persistDomEditOperations = vi.fn().mockResolvedValue(undefined);
const hook = renderTextCommitHook(
diff --git a/packages/studio/src/hooks/useDomEditTextCommits.ts b/packages/studio/src/hooks/useDomEditTextCommits.ts
index 21e26c3ca2..75ef5817bd 100644
--- a/packages/studio/src/hooks/useDomEditTextCommits.ts
+++ b/packages/studio/src/hooks/useDomEditTextCommits.ts
@@ -105,8 +105,13 @@ export function useDomEditTextCommits({
persistDomEditOperations,
});
+ // One property, or a map saved as one patch and one undo step.
const handleDomStyleCommitForSelection = useCallback(
- (selection: DomEditSelection, property: string, value: string): Promise =>
+ (
+ selection: DomEditSelection,
+ property: string | Record,
+ value = "",
+ ): Promise =>
commitDomStyles(
{
activeCompPath,
@@ -118,7 +123,7 @@ export function useDomEditTextCommits({
resync: refreshDomEditSelectionFromPreview,
},
selection,
- { [property]: value },
+ typeof property === "string" ? { [property]: value } : property,
),
[
activeCompPath,
diff --git a/packages/studio/src/index.ts b/packages/studio/src/index.ts
index c6ee950fae..4024a375d1 100644
--- a/packages/studio/src/index.ts
+++ b/packages/studio/src/index.ts
@@ -201,6 +201,8 @@ export type { DomEditZOrder } from "./components/editor/useDomEditZOrder";
export type { ZOrderAction } from "./components/editor/canvasContextMenuZOrder";
export type { DomEditCapabilities, DomEditSelection } from "./components/editor/domEditingTypes";
export { useDomStyleCommit } from "./hooks/useDomStyleCommit";
+export { ColorField } from "./components/editor/propertyPanelColor";
+export { GradientField } from "./components/editor/propertyPanelFill";
export type { UseDomStyleCommitOptions } from "./hooks/useDomStyleCommit";
export type { DomEditCommitDeclineReason, DomEditCommitOutcome } from "./hooks/domEditCommitRunner";
export { resolveDomEditSelection } from "./components/editor/domEditingLayers";