diff --git a/craft/src/panels/right/styles/BackgroundSectionStylePanel.tsx b/craft/src/panels/right/styles/BackgroundSectionStylePanel.tsx index ba6c09f..4781e8c 100644 --- a/craft/src/panels/right/styles/BackgroundSectionStylePanel.tsx +++ b/craft/src/panels/right/styles/BackgroundSectionStylePanel.tsx @@ -1,5 +1,4 @@ -import React, { useCallback } from 'react'; -import { useEditor } from '@craftjs/core'; +import React from 'react'; import { BG_COLORS, SPACING_PRESETS, @@ -15,22 +14,13 @@ import { labelStyle, inputStyle, sectionGap, + useNodeProp, } from './shared'; import { AssetPicker } from '../../../ui/AssetPicker'; /* ---------- BACKGROUND SECTION ---------- */ export const BackgroundSectionStylePanel: React.FC = ({ selectedId, nodeProps }) => { - const { actions } = useEditor(); - - const setProp = useCallback((key: string, value: any) => { - actions.setProp(selectedId, (props: any) => { props[key] = value; }); - }, [actions, selectedId]); - - const setPropStyle = useCallback((key: string, value: string) => { - actions.setProp(selectedId, (props: any) => { - props.style = { ...props.style, [key]: value }; - }); - }, [actions, selectedId]); + const { setProp, setPropStyle } = useNodeProp(selectedId); const style = nodeProps.style || {}; diff --git a/craft/src/panels/right/styles/ButtonStylePanel.tsx b/craft/src/panels/right/styles/ButtonStylePanel.tsx index 9247b7e..e2970b6 100644 --- a/craft/src/panels/right/styles/ButtonStylePanel.tsx +++ b/craft/src/panels/right/styles/ButtonStylePanel.tsx @@ -12,6 +12,7 @@ import { PresetButtonGrid, TextInputField, autoTextColor, + useNodeProp, } from './shared'; /* ---------- BUTTON ---------- */ @@ -19,14 +20,7 @@ export const ButtonStylePanel: React.FC = ({ selectedId, nodePr const { actions } = useEditor(); const style: CSSProperties = nodeProps.style || {}; - const setPropStyle = useCallback( - (property: string, value: string) => { - actions.setProp(selectedId, (props: any) => { - props.style = { ...props.style, [property]: value }; - }); - }, - [actions, selectedId], - ); + const { setPropStyle } = useNodeProp(selectedId); const setButtonColor = useCallback( (bgColor: string) => { diff --git a/craft/src/panels/right/styles/ContainerStylePanel.tsx b/craft/src/panels/right/styles/ContainerStylePanel.tsx index c3420ef..d642b2e 100644 --- a/craft/src/panels/right/styles/ContainerStylePanel.tsx +++ b/craft/src/panels/right/styles/ContainerStylePanel.tsx @@ -1,5 +1,4 @@ -import React, { useCallback, CSSProperties } from 'react'; -import { useEditor } from '@craftjs/core'; +import React, { CSSProperties } from 'react'; import { BG_COLORS, SPACING_PRESETS, @@ -14,28 +13,14 @@ import { labelStyle, inputStyle, sectionGap, + useNodeProp, } from './shared'; /* ---------- CONTAINER / SECTION ---------- */ export const ContainerStylePanel: React.FC = ({ selectedId, nodeProps }) => { - const { actions } = useEditor(); const style: CSSProperties = nodeProps.style || {}; - const setPropStyle = useCallback( - (property: string, value: string) => { - actions.setProp(selectedId, (props: any) => { - props.style = { ...props.style, [property]: value }; - }); - }, - [actions, selectedId], - ); - - const setProp = useCallback( - (key: string, value: string) => { - actions.setProp(selectedId, (props: any) => { props[key] = value; }); - }, - [actions, selectedId], - ); + const { setProp, setPropStyle } = useNodeProp(selectedId); return ( <> diff --git a/craft/src/panels/right/styles/FormStylePanel.tsx b/craft/src/panels/right/styles/FormStylePanel.tsx index 76f343b..7e22e64 100644 --- a/craft/src/panels/right/styles/FormStylePanel.tsx +++ b/craft/src/panels/right/styles/FormStylePanel.tsx @@ -1,5 +1,4 @@ -import React, { useCallback } from 'react'; -import { useEditor } from '@craftjs/core'; +import React from 'react'; import { BG_COLORS, SPACING_PRESETS, @@ -15,21 +14,12 @@ import { inputStyle, btnActiveStyle, sectionGap, + useNodeProp, } from './shared'; /* ---------- FORM ---------- */ export const FormStylePanel: React.FC = ({ selectedId, nodeProps }) => { - const { actions } = useEditor(); - - const setProp = useCallback((key: string, value: any) => { - actions.setProp(selectedId, (props: any) => { props[key] = value; }); - }, [actions, selectedId]); - - const setPropStyle = useCallback((key: string, value: string) => { - actions.setProp(selectedId, (props: any) => { - props.style = { ...props.style, [key]: value }; - }); - }, [actions, selectedId]); + const { setProp, setPropStyle } = useNodeProp(selectedId); const style = nodeProps.style || {}; diff --git a/craft/src/panels/right/styles/GenericPropsEditor.tsx b/craft/src/panels/right/styles/GenericPropsEditor.tsx index d1a53fe..f21d1f2 100644 --- a/craft/src/panels/right/styles/GenericPropsEditor.tsx +++ b/craft/src/panels/right/styles/GenericPropsEditor.tsx @@ -1,4 +1,4 @@ -import React, { useCallback } from 'react'; +import React from 'react'; import { useEditor } from '@craftjs/core'; import { TEXT_COLORS, @@ -17,6 +17,7 @@ import { inputStyle, smallInputStyle, sectionGap, + useNodeProp, } from './shared'; /* ---------- SMART GENERIC PROPS EDITOR (Fallback) ---------- */ @@ -27,15 +28,7 @@ export const GenericPropsEditor: React.FC<{ selectedId: string; nodeProps: Recor const SKIP_PROPS = new Set(['style', 'children', 'cssId', 'cssClass']); - const setPropValue = useCallback((key: string, value: any) => { - actions.setProp(selectedId, (props: any) => { props[key] = value; }); - }, [actions, selectedId]); - - const setStyleValue = useCallback((key: string, value: string) => { - actions.setProp(selectedId, (props: any) => { - props.style = { ...props.style, [key]: value }; - }); - }, [actions, selectedId]); + const { setProp: setPropValue, setPropStyle: setStyleValue } = useNodeProp(selectedId); // Categorize all props const allProps = Object.entries(nodeProps).filter(([key]) => !SKIP_PROPS.has(key)); diff --git a/craft/src/panels/right/styles/HeroStylePanel.tsx b/craft/src/panels/right/styles/HeroStylePanel.tsx index 83c0799..7bab6f9 100644 --- a/craft/src/panels/right/styles/HeroStylePanel.tsx +++ b/craft/src/panels/right/styles/HeroStylePanel.tsx @@ -1,5 +1,4 @@ -import React, { useCallback } from 'react'; -import { useEditor } from '@craftjs/core'; +import React from 'react'; import { StylePanelProps, CollapsibleSection, @@ -8,16 +7,13 @@ import { inputStyle, btnActiveStyle, sectionGap, + useNodeProp, } from './shared'; import { AssetPicker } from '../../../ui/AssetPicker'; /* ---------- HERO STYLE PANEL ---------- */ export const HeroStylePanel: React.FC = ({ selectedId, nodeProps }) => { - const { actions } = useEditor(); - - const setProp = useCallback((key: string, value: any) => { - actions.setProp(selectedId, (props: any) => { props[key] = value; }); - }, [actions, selectedId]); + const { setProp } = useNodeProp(selectedId); const bgType = nodeProps.bgType || 'color'; diff --git a/craft/src/panels/right/styles/ImageStylePanel.tsx b/craft/src/panels/right/styles/ImageStylePanel.tsx index 01850f7..413c506 100644 --- a/craft/src/panels/right/styles/ImageStylePanel.tsx +++ b/craft/src/panels/right/styles/ImageStylePanel.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, CSSProperties } from 'react'; +import React, { CSSProperties } from 'react'; import { useEditor } from '@craftjs/core'; import { IMAGE_RADIUS_PRESETS, @@ -8,6 +8,7 @@ import { SectionLabel, PresetButtonGrid, TextInputField, + useNodeProp, } from './shared'; import { AssetPicker } from '../../../ui/AssetPicker'; @@ -16,14 +17,7 @@ export const ImageStylePanel: React.FC = ({ selectedId, nodePro const { actions } = useEditor(); const style: CSSProperties = nodeProps.style || {}; - const setPropStyle = useCallback( - (property: string, value: string) => { - actions.setProp(selectedId, (props: any) => { - props.style = { ...props.style, [property]: value }; - }); - }, - [actions, selectedId], - ); + const { setPropStyle } = useNodeProp(selectedId); const maxWidthPresets = [ { label: '25%', value: '25%' }, diff --git a/craft/src/panels/right/styles/MediaStylePanel.tsx b/craft/src/panels/right/styles/MediaStylePanel.tsx index cc5fb78..6100e9b 100644 --- a/craft/src/panels/right/styles/MediaStylePanel.tsx +++ b/craft/src/panels/right/styles/MediaStylePanel.tsx @@ -1,4 +1,4 @@ -import React, { useCallback } from 'react'; +import React from 'react'; import { useEditor } from '@craftjs/core'; import { BG_COLORS, @@ -17,22 +17,14 @@ import { inputStyle, smallInputStyle, sectionGap, + useNodeProp, } from './shared'; import { AssetPicker } from '../../../ui/AssetPicker'; /* ---------- MEDIA (Video / Gallery / Map / Slider) ---------- */ export const MediaStylePanel: React.FC = ({ selectedId, nodeProps }) => { const { actions } = useEditor(); - - const setProp = useCallback((key: string, value: any) => { - actions.setProp(selectedId, (props: any) => { props[key] = value; }); - }, [actions, selectedId]); - - const setPropStyle = useCallback((key: string, value: string) => { - actions.setProp(selectedId, (props: any) => { - props.style = { ...props.style, [key]: value }; - }); - }, [actions, selectedId]); + const { setProp, setPropStyle } = useNodeProp(selectedId); const style = nodeProps.style || {}; diff --git a/craft/src/panels/right/styles/NavStylePanel.tsx b/craft/src/panels/right/styles/NavStylePanel.tsx index 47dc4df..b801f95 100644 --- a/craft/src/panels/right/styles/NavStylePanel.tsx +++ b/craft/src/panels/right/styles/NavStylePanel.tsx @@ -15,22 +15,14 @@ import { inputStyle, smallInputStyle, sectionGap, + useNodeProp, } from './shared'; import { AssetPicker } from '../../../ui/AssetPicker'; /* ---------- NAV / MENU / LOGO ---------- */ export const NavStylePanel: React.FC = ({ selectedId, nodeProps }) => { const { actions } = useEditor(); - - const setProp = useCallback((key: string, value: any) => { - actions.setProp(selectedId, (props: any) => { props[key] = value; }); - }, [actions, selectedId]); - - const setPropStyle = useCallback((key: string, value: string) => { - actions.setProp(selectedId, (props: any) => { - props.style = { ...props.style, [key]: value }; - }); - }, [actions, selectedId]); + const { setProp, setPropStyle } = useNodeProp(selectedId); const links: any[] = nodeProps.links || []; diff --git a/craft/src/panels/right/styles/SectionTypePanel.tsx b/craft/src/panels/right/styles/SectionTypePanel.tsx index 4570048..7369de8 100644 --- a/craft/src/panels/right/styles/SectionTypePanel.tsx +++ b/craft/src/panels/right/styles/SectionTypePanel.tsx @@ -1,4 +1,4 @@ -import React, { useCallback } from 'react'; +import React from 'react'; import { useEditor } from '@craftjs/core'; import { BG_COLORS, @@ -17,22 +17,14 @@ import { inputStyle, smallInputStyle, sectionGap, + useNodeProp, } from './shared'; import { FeaturesEditor } from './FeaturesEditor'; /* ---------- SECTION-TYPE (Accordion, Tabs, Pricing, Testimonials, etc.) ---------- */ export const SectionTypePanel: React.FC = ({ selectedId, nodeProps, typeName }) => { const { actions } = useEditor(); - - const setProp = useCallback((key: string, value: any) => { - actions.setProp(selectedId, (props: any) => { props[key] = value; }); - }, [actions, selectedId]); - - const setPropStyle = useCallback((key: string, value: string) => { - actions.setProp(selectedId, (props: any) => { - props.style = { ...props.style, [key]: value }; - }); - }, [actions, selectedId]); + const { setProp, setPropStyle } = useNodeProp(selectedId); const style = nodeProps.style || {}; diff --git a/craft/src/panels/right/styles/SocialStylePanel.tsx b/craft/src/panels/right/styles/SocialStylePanel.tsx index 9e42610..06af9d9 100644 --- a/craft/src/panels/right/styles/SocialStylePanel.tsx +++ b/craft/src/panels/right/styles/SocialStylePanel.tsx @@ -1,4 +1,4 @@ -import React, { useCallback } from 'react'; +import React from 'react'; import { useEditor } from '@craftjs/core'; import { BG_COLORS, @@ -16,21 +16,13 @@ import { smallInputStyle, btnActiveStyle, sectionGap, + useNodeProp, } from './shared'; /* ---------- SOCIAL / ICON / STAR RATING ---------- */ export const SocialStylePanel: React.FC = ({ selectedId, nodeProps }) => { const { actions } = useEditor(); - - const setProp = useCallback((key: string, value: any) => { - actions.setProp(selectedId, (props: any) => { props[key] = value; }); - }, [actions, selectedId]); - - const setPropStyle = useCallback((key: string, value: string) => { - actions.setProp(selectedId, (props: any) => { - props.style = { ...props.style, [key]: value }; - }); - }, [actions, selectedId]); + const { setProp, setPropStyle } = useNodeProp(selectedId); const style = nodeProps.style || {}; diff --git a/craft/src/panels/right/styles/TextStylePanel.tsx b/craft/src/panels/right/styles/TextStylePanel.tsx index e55cb91..f17085a 100644 --- a/craft/src/panels/right/styles/TextStylePanel.tsx +++ b/craft/src/panels/right/styles/TextStylePanel.tsx @@ -1,5 +1,4 @@ -import React, { useCallback, CSSProperties } from 'react'; -import { useEditor } from '@craftjs/core'; +import React, { CSSProperties } from 'react'; import { TEXT_COLORS, FONT_FAMILIES, @@ -11,21 +10,14 @@ import { SectionLabel, ColorSwatchGrid, PresetButtonGrid, + useNodeProp, } from './shared'; /* ---------- TEXT ---------- */ export const TextStylePanel: React.FC = ({ selectedId, nodeProps }) => { - const { actions } = useEditor(); const style: CSSProperties = nodeProps.style || {}; - const setPropStyle = useCallback( - (property: string, value: string) => { - actions.setProp(selectedId, (props: any) => { - props.style = { ...props.style, [property]: value }; - }); - }, - [actions, selectedId], - ); + const { setPropStyle } = useNodeProp(selectedId); return ( <> diff --git a/craft/src/panels/right/styles/shared.tsx b/craft/src/panels/right/styles/shared.tsx index 8b7c853..96f860a 100644 --- a/craft/src/panels/right/styles/shared.tsx +++ b/craft/src/panels/right/styles/shared.tsx @@ -288,6 +288,18 @@ export interface StylePanelProps { nodeProps: Record; } +/* ---------- useNodeProp ---------- + Shared setProp/setPropStyle boilerplate repeated across many *StylePanel.tsx + files. Only adopted where a panel's inline definitions were byte-equivalent + to this (some panels use different param names or extra logic and keep + their own local versions). */ +export function useNodeProp(selectedId: string) { + const { actions } = useEditor(); + const setProp = useCallback((key: string, value: any) => actions.setProp(selectedId, (p: any) => { p[key] = value; }), [actions, selectedId]); + const setPropStyle = useCallback((prop: string, value: string) => actions.setProp(selectedId, (p: any) => { p.style = { ...p.style, [prop]: value }; }), [actions, selectedId]); + return { setProp, setPropStyle }; +} + /* ---------- Array Prop Editor (reusable for features, items, plans, etc.) ---------- */ interface ArrayPropEditorProps { selectedId: string;