diff --git a/src/internal/components/InternalThemeEditor.tsx b/src/internal/components/InternalThemeEditor.tsx index 278c638e..49ea4aec 100644 --- a/src/internal/components/InternalThemeEditor.tsx +++ b/src/internal/components/InternalThemeEditor.tsx @@ -1,5 +1,5 @@ import { Puck, Config, InitialHistory } from "@measured/puck"; -import React from "react"; +import React, { useCallback, useEffect, useRef } from "react"; import { useState } from "react"; import { TemplateMetadata } from "../types/templateMetadata.ts"; import { EntityFieldProvider } from "../../components/EntityField.tsx"; @@ -45,6 +45,11 @@ export const InternalThemeEditor = ({ buildThemeLocalStorageKey, }: InternalThemeEditorProps) => { const [canEdit, setCanEdit] = useState(false); // helps sync puck preview and save state + const themeHistoriesRef = useRef(themeHistories); + + useEffect(() => { + themeHistoriesRef.current = themeHistories; + }, [themeHistories]); const handlePublishTheme = async () => { devLogger.logFunc("saveThemeData"); @@ -69,21 +74,22 @@ export const InternalThemeEditor = ({ }; const handleThemeChange = (topLevelKey: string, newValue: any) => { - if (!themeHistories || !themeConfig) { + if (!themeHistoriesRef.current || !themeConfig) { return; } const newThemeValues = { - ...themeHistories.histories[themeHistories.index]?.data, + ...themeHistoriesRef.current.histories[themeHistoriesRef.current.index] + ?.data, ...generateCssVariablesFromPuckFields(newValue, topLevelKey), }; const newHistory = { histories: [ - ...themeHistories.histories, + ...themeHistoriesRef.current.histories, { id: uuidv4(), data: newThemeValues }, ] as ThemeHistory[], - index: themeHistories.histories.length, + index: themeHistoriesRef.current.histories.length, }; window.localStorage.setItem( @@ -124,6 +130,16 @@ export const InternalThemeEditor = ({ } }; + const fieldsOverride = useCallback(() => { + return ( + + ); + }, []); + return ( <>, components: () => <>, - fields: () => ( - - ), + fields: fieldsOverride, }} /> diff --git a/src/internal/components/ThemeEditor.tsx b/src/internal/components/ThemeEditor.tsx index 6301f8da..e3f66623 100644 --- a/src/internal/components/ThemeEditor.tsx +++ b/src/internal/components/ThemeEditor.tsx @@ -182,9 +182,9 @@ export const ThemeEditor = (props: ThemeEditorProps) => { buildThemeLocalStorageKey, ]); - // Log THEME_INITIAL_HISTORY on load and update theme in editor to reflect save state + // Log THEME_HISTORIES on load and update theme in editor to reflect save state useEffect(() => { - devLogger.logData("THEME_INITIAL_HISTORY", themeHistories); + devLogger.logData("THEME_HISTORIES", themeHistories); if (themeHistories && themeConfig) { updateThemeInEditor( themeHistories.histories[themeHistories.index]?.data as SavedTheme, diff --git a/src/internal/puck/components/ColorSelector.tsx b/src/internal/puck/components/ColorSelector.tsx index b78eb882..e6c2c63c 100644 --- a/src/internal/puck/components/ColorSelector.tsx +++ b/src/internal/puck/components/ColorSelector.tsx @@ -1,52 +1,39 @@ import React, { useState } from "react"; -import { Field, FieldLabel } from "@measured/puck"; +import { FieldLabel } from "@measured/puck"; import { RenderProps } from "../../utils/renderEntityFields.ts"; import { Color, ColorResult, SketchPicker } from "react-color"; -export type ColorSelectorProps = { - label: string; -}; - -export const ColorSelector = (props: ColorSelectorProps): Field => { - return { - type: "custom", - label: props.label, - render: ({ field, value, onChange }: RenderProps) => { - const [isOpen, setIsOpen] = useState(false); +export const ColorSelector = ({ field, value, onChange }: RenderProps) => { + const [isOpen, setIsOpen] = useState(false); - const fieldStyles = colorPickerStyles(value); - return ( - <> - -
setIsOpen((current) => !current)} - > -
-
- {isOpen && ( -
-
setIsOpen(false)} - /> - { - onChange(colorResult.hex); - }} - /> -
- )} - - - ); - }, - }; + const fieldStyles = colorPickerStyles(value); + return ( + <> + +
setIsOpen((current) => !current)} + > +
+
+ {isOpen && ( +
+
setIsOpen(false)} /> + { + onChange(colorResult.hex); + }} + /> +
+ )} + + + ); }; const colorPickerStyles = (color: Color) => { diff --git a/src/internal/puck/components/ThemeSidebar.tsx b/src/internal/puck/components/ThemeSidebar.tsx index 6409cd8d..b04ead59 100644 --- a/src/internal/puck/components/ThemeSidebar.tsx +++ b/src/internal/puck/components/ThemeSidebar.tsx @@ -6,16 +6,21 @@ import { constructThemePuckFields, constructThemePuckValues, } from "../../utils/constructThemePuckFields.ts"; -import { ThemeHistory } from "../../types/themeData.ts"; +import { ThemeHistories } from "../../types/themeData.ts"; type ThemeSidebarProps = { + themeHistoriesRef: React.MutableRefObject; themeConfig?: ThemeConfig; - themeHistory: ThemeHistory[]; onThemeChange: (parentStyleKey: string, value: Record) => void; }; const ThemeSidebar = (props: ThemeSidebarProps) => { - const { themeConfig, themeHistory, onThemeChange } = props; + const { themeConfig, themeHistoriesRef, onThemeChange } = props; + + if (!themeHistoriesRef.current) { + return; + } + if (!themeConfig) { return (
@@ -28,6 +33,9 @@ const ThemeSidebar = (props: ThemeSidebarProps) => { ); } + const themeData = + themeHistoriesRef.current?.histories[themeHistoriesRef.current?.index].data; + return (
@@ -39,7 +47,7 @@ const ThemeSidebar = (props: ThemeSidebarProps) => { {Object.entries(themeConfig).map(([parentStyleKey, parentStyle]) => { const field = constructThemePuckFields(parentStyle); const values = constructThemePuckValues( - themeHistory[themeHistory.length - 1]?.data, + themeData, parentStyle, parentStyleKey ); diff --git a/src/internal/utils/constructThemePuckFields.ts b/src/internal/utils/constructThemePuckFields.ts index d72f220a..b3b5311a 100644 --- a/src/internal/utils/constructThemePuckFields.ts +++ b/src/internal/utils/constructThemePuckFields.ts @@ -1,4 +1,9 @@ -import { ObjectField, SelectField, NumberField } from "@measured/puck"; +import { + ObjectField, + SelectField, + NumberField, + CustomField, +} from "@measured/puck"; import { ParentStyle, SavedTheme, Style } from "../../utils/themeResolver.ts"; import { ColorSelector } from "../puck/components/ColorSelector.tsx"; @@ -36,7 +41,11 @@ export const convertStyleToPuckField = (style: Style) => { options: style.options, } as SelectField; case "color": - return ColorSelector({ label: style.label }); + return { + label: style.label, + type: "custom", + render: ColorSelector, + } as CustomField; } }; diff --git a/src/utils/devLogger.ts b/src/utils/devLogger.ts index 1f276c5f..309bd2f7 100644 --- a/src/utils/devLogger.ts +++ b/src/utils/devLogger.ts @@ -5,7 +5,7 @@ export type DevLoggerPrefix = | "THEME_SAVE_STATE" | "VISUAL_CONFIGURATION_DATA" | "THEME_DATA" - | "THEME_INITIAL_HISTORY" + | "THEME_HISTORIES" | "DOCUMENT" | "PUCK_INDEX" | "PUCK_HISTORY"