diff --git a/packages/visual-editor/src/components/testing/screenshots/Grid/[desktop] version 45 - CTAs with Dark background.png b/packages/visual-editor/src/components/testing/screenshots/Grid/[desktop] version 45 - CTAs with Dark background.png index fef3cb865..32f21bad7 100644 Binary files a/packages/visual-editor/src/components/testing/screenshots/Grid/[desktop] version 45 - CTAs with Dark background.png and b/packages/visual-editor/src/components/testing/screenshots/Grid/[desktop] version 45 - CTAs with Dark background.png differ diff --git a/packages/visual-editor/src/components/testing/screenshots/Grid/[mobile] version 45 - CTAs with Dark background.png b/packages/visual-editor/src/components/testing/screenshots/Grid/[mobile] version 45 - CTAs with Dark background.png index cfbca0ec8..4123389ed 100644 Binary files a/packages/visual-editor/src/components/testing/screenshots/Grid/[mobile] version 45 - CTAs with Dark background.png and b/packages/visual-editor/src/components/testing/screenshots/Grid/[mobile] version 45 - CTAs with Dark background.png differ diff --git a/packages/visual-editor/src/components/testing/screenshots/Grid/[tablet] version 45 - CTAs with Dark background.png b/packages/visual-editor/src/components/testing/screenshots/Grid/[tablet] version 45 - CTAs with Dark background.png index d4220f54b..a165f298b 100644 Binary files a/packages/visual-editor/src/components/testing/screenshots/Grid/[tablet] version 45 - CTAs with Dark background.png and b/packages/visual-editor/src/components/testing/screenshots/Grid/[tablet] version 45 - CTAs with Dark background.png differ diff --git a/packages/visual-editor/src/components/testing/screenshots/Locator/[mobile] latest version default props.png b/packages/visual-editor/src/components/testing/screenshots/Locator/[mobile] latest version default props.png index 144bfb309..552a6108a 100644 Binary files a/packages/visual-editor/src/components/testing/screenshots/Locator/[mobile] latest version default props.png and b/packages/visual-editor/src/components/testing/screenshots/Locator/[mobile] latest version default props.png differ diff --git a/packages/visual-editor/src/components/testing/screenshots/Locator/[tablet] latest version default props.png b/packages/visual-editor/src/components/testing/screenshots/Locator/[tablet] latest version default props.png index 40a6a4579..ffd6d13ed 100644 Binary files a/packages/visual-editor/src/components/testing/screenshots/Locator/[tablet] latest version default props.png and b/packages/visual-editor/src/components/testing/screenshots/Locator/[tablet] latest version default props.png differ diff --git a/packages/visual-editor/src/components/testing/screenshots/PhotoGallerySection/[desktop] version 59 with showSectionHeading false.png b/packages/visual-editor/src/components/testing/screenshots/PhotoGallerySection/[desktop] version 59 with showSectionHeading false.png index 78479fbdf..b9bf47805 100644 Binary files a/packages/visual-editor/src/components/testing/screenshots/PhotoGallerySection/[desktop] version 59 with showSectionHeading false.png and b/packages/visual-editor/src/components/testing/screenshots/PhotoGallerySection/[desktop] version 59 with showSectionHeading false.png differ diff --git a/packages/visual-editor/src/editor/types.ts b/packages/visual-editor/src/editor/types.ts index 61250d0dc..201d69b9b 100644 --- a/packages/visual-editor/src/editor/types.ts +++ b/packages/visual-editor/src/editor/types.ts @@ -4,6 +4,7 @@ export type LocalDevOptions = { locale?: string; locales?: string[]; layoutScopeKey?: string; + themeScopeKey?: string; initialLayoutData?: Record; showOverrideButtons?: boolean; }; diff --git a/packages/visual-editor/src/internal/components/LayoutEditor.tsx b/packages/visual-editor/src/internal/components/LayoutEditor.tsx index 9c7c5a33b..16d594589 100644 --- a/packages/visual-editor/src/internal/components/LayoutEditor.tsx +++ b/packages/visual-editor/src/internal/components/LayoutEditor.tsx @@ -206,9 +206,9 @@ export const LayoutEditor = (props: LayoutEditorProps) => { } } - // Otherwise start fresh from Content + // Otherwise start fresh from published layout data devLogger.log( - "Layout Dev Mode - No localStorage. Using layout data from Content" + "Layout Dev Mode - No localStorage. Using published layout data" ); if (layoutData) { setPuckInitialHistory({ @@ -221,12 +221,12 @@ export const LayoutEditor = (props: LayoutEditorProps) => { return; } - // Nothing in save_state table, start fresh from Content + // Nothing in save_state table, start fresh from published layout data if (!layoutSaveState) { clearVisualConfigLocalStorage(); devLogger.log( - "Layout Prod Mode - No saveState. Using layout data from Content" + "Layout Prod Mode - No saveState. Using published layout data" ); if (layoutData) { setPuckInitialHistory({ diff --git a/packages/visual-editor/src/internal/components/ThemeEditor.tsx b/packages/visual-editor/src/internal/components/ThemeEditor.tsx index f94bdf7e1..667f5db82 100644 --- a/packages/visual-editor/src/internal/components/ThemeEditor.tsx +++ b/packages/visual-editor/src/internal/components/ThemeEditor.tsx @@ -88,9 +88,17 @@ export const ThemeEditor = (props: ThemeEditorProps) => { const localHistoryArray = lzstring.decompress( window.localStorage.getItem(buildVisualConfigLocalStorageKey()) || "" ); - const localHistories = ( - localHistoryArray ? JSON.parse(localHistoryArray) : [] - ) as History[]; + let localHistories: History[] = []; + if (localHistoryArray) { + try { + localHistories = JSON.parse(localHistoryArray) as History[]; + } catch (error) { + console.warn( + "Failed to parse local theme editor layout history. Falling back to template layout data.", + error + ); + } + } const histories = localHistories .filter((h) => h?.state) .map((h) => { @@ -109,6 +117,12 @@ export const ThemeEditor = (props: ThemeEditorProps) => { sendDevLayoutSaveStateData({ payload: { devSaveStateData: JSON.stringify(layoutToSend) }, }); + } else if (layoutData) { + devLogger.log("Theme Dev Mode - Using published layout data"); + setPuckInitialHistory({ + histories: [{ id: "root", state: { data: layoutData } }], + appendData: false, + }); } setPuckInitialHistoryFetched(true); return; @@ -150,13 +164,23 @@ export const ThemeEditor = (props: ThemeEditorProps) => { // Use localStorage directly if it exists if (localHistoryArray) { devLogger.log("Theme Dev Mode - Using theme localStorage"); - histories = JSON.parse(localHistoryArray) as ThemeHistory[]; - index = histories.length - 1; - } else { + try { + histories = JSON.parse(localHistoryArray) as ThemeHistory[]; + index = histories.length - 1; + } catch (error) { + console.warn( + "Failed to parse local theme history. Falling back to theme data from Content.", + error + ); + } + } + + if (!histories?.length) { // Otherwise start fresh from Content devLogger.log( "Theme Dev Mode - No localStorage. Using theme data from Content" ); + index = 0; if (themeData) { histories = [{ id: "root", data: themeData }]; } diff --git a/packages/visual-editor/src/internal/types/templateMetadata.test.ts b/packages/visual-editor/src/internal/types/templateMetadata.test.ts index ce0875565..355015efd 100644 --- a/packages/visual-editor/src/internal/types/templateMetadata.test.ts +++ b/packages/visual-editor/src/internal/types/templateMetadata.test.ts @@ -35,4 +35,18 @@ describe("generateTemplateMetadata", () => { "type.image" ); }); + + it("uses themeScopeKey for a shared local-dev theme entity", () => { + const directoryMetadata = generateTemplateMetadata(undefined, { + templateId: "directory", + themeScopeKey: "local-editor", + }); + const locatorMetadata = generateTemplateMetadata(undefined, { + templateId: "locator", + themeScopeKey: "local-editor", + }); + + expect(directoryMetadata.themeEntityId).toBeDefined(); + expect(directoryMetadata.themeEntityId).toBe(locatorMetadata.themeEntityId); + }); }); diff --git a/packages/visual-editor/src/internal/types/templateMetadata.ts b/packages/visual-editor/src/internal/types/templateMetadata.ts index f59f67d8d..2d10ca546 100644 --- a/packages/visual-editor/src/internal/types/templateMetadata.ts +++ b/packages/visual-editor/src/internal/types/templateMetadata.ts @@ -133,6 +133,7 @@ export function generateTemplateMetadata( entityId: localDevOptions?.entityId ?? cleanString, locale, }); + const themeScopeKey = localDevOptions?.themeScopeKey; const locales = localDevOptions?.locales?.length ? localDevOptions.locales : ["en", "es", "fr"]; @@ -141,6 +142,7 @@ export function generateTemplateMetadata( siteId: 1337, templateId, entityId, + themeEntityId: themeScopeKey ? hashCode(themeScopeKey) : undefined, layoutId: hashCode(layoutScopeKey), assignment: "ALL", isDevMode: true, diff --git a/packages/visual-editor/src/local-editor/LocalEditorControls.tsx b/packages/visual-editor/src/local-editor/LocalEditorControls.tsx index 2cda956b1..a9dad97a6 100644 --- a/packages/visual-editor/src/local-editor/LocalEditorControls.tsx +++ b/packages/visual-editor/src/local-editor/LocalEditorControls.tsx @@ -1,5 +1,5 @@ import React from "react"; -import type { LocalEditorEntityOption } from "./types.ts"; +import type { LocalEditorEntityOption, LocalEditorMode } from "./types.ts"; type LocalEditorControlsProps = { activeEntities: LocalEditorEntityOption[]; @@ -7,9 +7,11 @@ type LocalEditorControlsProps = { controlsDisabled: boolean; selectedEntityId?: string; selectedLocale: string; + selectedMode: LocalEditorMode; selectedTemplateId: string; onEntityChange: (entityId: string) => void; onLocaleChange: (locale: string) => void; + onModeChange: (mode: LocalEditorMode) => void; onTemplateChange: (templateId: string) => void; }; @@ -19,9 +21,11 @@ export const LocalEditorControls = ({ controlsDisabled, selectedEntityId, selectedLocale, + selectedMode, selectedTemplateId, onEntityChange, onLocaleChange, + onModeChange, onTemplateChange, }: LocalEditorControlsProps) => { const selectedEntity = activeEntities.find((entity) => { @@ -53,6 +57,30 @@ export const LocalEditorControls = ({ + + + +