Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 33 additions & 8 deletions packages/global-styles-ui/src/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,21 @@ extend( [ a11yPlugin ] );
* @param blockName The name of the block, if applicable.
* @param readFrom Which source to read from: "base" (theme), "user" (customizations), or "merged" (final result).
* @param shouldDecodeEncode Whether to decode and encode the style value.
* @param state Optional pseudo-selector state (e.g. `:hover`, `:focus`). When provided,
* reads from and writes to the state sub-object automatically.
* @return An array containing the style value and a function to set the style
* value.
*
* @example
* const [ color, setColor ] = useStyle<string>( 'color.text', 'core/button', 'merged' );
* const [ hoverColor, setHoverColor ] = useStyle<string>( 'color.text', 'core/button', 'user', true, ':hover' );
*/
export function useStyle< T = any >(
path: string,
blockName?: string,
readFrom: 'base' | 'user' | 'merged' = 'merged',
shouldDecodeEncode: boolean = true
shouldDecodeEncode: boolean = true,
state?: string
) {
const { user, base, merged, onChange } = useContext( GlobalStylesContext );

Expand All @@ -57,22 +61,43 @@ export function useStyle< T = any >(
sourceValue = user;
}

const styleValue = useMemo(
() => getStyle< T >( sourceValue, path, blockName, shouldDecodeEncode ),
[ sourceValue, path, blockName, shouldDecodeEncode ]
);
const styleValue = useMemo( () => {
const rawValue = getStyle< T >(
sourceValue,
path,
blockName,
shouldDecodeEncode
);
if ( state ) {
return ( rawValue as any )?.[ state ] ?? {};
}
return rawValue;
}, [ sourceValue, path, blockName, shouldDecodeEncode, state ] );

const setStyleValue = useCallback(
( newValue: T | undefined ) => {
const newGlobalStyles = setStyle< T >(
let valueToSet: any = newValue;
if ( state ) {
const fullCurrentValue = getStyle(
user,
path,
blockName,
false
);
valueToSet = {
...( fullCurrentValue as object ),
[ state ]: newValue,
};
}
const newGlobalStyles = setStyle< any >(
user,
path,
newValue,
valueToSet,
blockName
);
onChange( newGlobalStyles );
},
[ user, onChange, path, blockName ]
[ user, onChange, path, blockName, state ]
);

return [ styleValue, setStyleValue ] as const;
Expand Down
49 changes: 12 additions & 37 deletions packages/global-styles-ui/src/screen-block.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,43 +114,22 @@ function ScreenBlock( { name, variation }: ScreenBlockProps ) {
const [ selectedState, setSelectedState ] = useState< string >( 'default' );
const validStates = useMemo( () => getValidStates( name ), [ name ] );

const [ rawStyle ] = useStyle( prefix, name, 'user', false );
const [ rawInheritedStyle, rawSetStyle ] = useStyle(
const stateParam = selectedState !== 'default' ? selectedState : undefined;
const [ style, setStyle ] = useStyle(
prefix,
name,
'user',
false,
stateParam
);
const [ inheritedStyle ] = useStyle(
prefix,
name,
'merged',
false
false,
stateParam
);

// Extract style for the selected state
const style = useMemo( () => {
if ( selectedState === 'default' ) {
return rawStyle || {};
}
return rawStyle?.[ selectedState ] || {};
}, [ rawStyle, selectedState ] );

const inheritedStyle = useMemo( () => {
if ( selectedState === 'default' ) {
return rawInheritedStyle || {};
}
return rawInheritedStyle?.[ selectedState ] || {};
}, [ rawInheritedStyle, selectedState ] );

// Wrapper for setStyle that handles states
const setStyle = ( newStyle: any ) => {
if ( selectedState === 'default' ) {
rawSetStyle( newStyle );
} else {
// Merge the new style into the state
const updatedStyle = {
...rawStyle,
[ selectedState ]: newStyle,
};
rawSetStyle( updatedStyle );
}
};

const [ userSettings ] = useSetting( '', name, 'user' );
const [ rawSettings, setSettings ] = useSetting( '', name );
const settingsForBlockElement = useSettingsForBlockElement(
Expand Down Expand Up @@ -355,11 +334,7 @@ function ScreenBlock( { name, variation }: ScreenBlockProps ) {
name={ name }
variation={ variation }
selectedState={ selectedState }
stateStyles={
selectedState !== 'default'
? rawStyle?.[ selectedState ]
: undefined
}
stateStyles={ selectedState !== 'default' ? style : undefined }
/>
{ hasVariationsPanel && (
<div className="global-styles-ui-screen-variations">
Expand Down
Loading