Skip to content

Commit

Permalink
Extract the getSupportedStyles selector to the blocks store as a priv…
Browse files Browse the repository at this point in the history
…ate selector
  • Loading branch information
youknowriad committed Jan 31, 2023
1 parent b329b48 commit 0ecc13c
Show file tree
Hide file tree
Showing 18 changed files with 394 additions and 162 deletions.
3 changes: 2 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/blocks/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"@wordpress/deprecated": "file:../deprecated",
"@wordpress/dom": "file:../dom",
"@wordpress/element": "file:../element",
"@wordpress/experiments": "file:../experiments",
"@wordpress/hooks": "file:../hooks",
"@wordpress/html-entities": "file:../html-entities",
"@wordpress/i18n": "file:../i18n",
Expand Down
10 changes: 10 additions & 0 deletions packages/blocks/src/experiments.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* WordPress dependencies
*/
import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/experiments';

export const { lock, unlock } =
__dangerousOptInToUnstableAPIsOnlyForCoreModules(
'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.',
'@wordpress/blocks'
);
3 changes: 3 additions & 0 deletions packages/blocks/src/store/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ import { createReduxStore, register } from '@wordpress/data';
*/
import reducer from './reducer';
import * as selectors from './selectors';
import * as privateSelectors from './private-selectors';
import * as actions from './actions';
import { STORE_NAME } from './constants';
import { unlock } from '../experiments';

/**
* Store definition for the blocks namespace.
Expand All @@ -25,3 +27,4 @@ export const store = createReduxStore( STORE_NAME, {
} );

register( store );
unlock( store ).registerPrivateSelectors( privateSelectors );
137 changes: 137 additions & 0 deletions packages/blocks/src/store/private-selectors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/**
* External dependencies
*/
import createSelector from 'rememo';
import { get } from 'lodash';

/**
* Internal dependencies
*/
import { getBlockType } from './selectors';
import { __EXPERIMENTAL_STYLE_PROPERTY as STYLE_PROPERTY } from '../api/constants';

const ROOT_BLOCK_SUPPORTS = [
'background',
'backgroundColor',
'color',
'linkColor',
'buttonColor',
'fontFamily',
'fontSize',
'fontStyle',
'fontWeight',
'lineHeight',
'padding',
'contentSize',
'wideSize',
'blockGap',
'textDecoration',
'textTransform',
'letterSpacing',
];

function filterElementBlockSupports( blockSuppots, name, element ) {
return blockSuppots.filter( ( support ) => {
if ( support === 'fontSize' && element === 'heading' ) {
return false;
}

// This is only available for links
if ( support === 'textDecoration' && ! name && element !== 'link' ) {
return false;
}

// This is only available for heading
if (
support === 'textTransform' &&
! name &&
[ 'heading', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' ].includes(
element
)
) {
return false;
}

// This is only available for headings
if (
support === 'letterSpacing' &&
! name &&
[ 'heading', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' ].includes(
element
)
) {
return false;
}

return true;
} );
}

export const getSupportedStyles = createSelector(
( state, name, element ) => {
if ( ! name ) {
return filterElementBlockSupports(
ROOT_BLOCK_SUPPORTS,
name,
element
);
}

const blockType = getBlockType( state, name );

if ( ! blockType ) {
return [];
}

const supportKeys = [];

// Check for blockGap support.
// Block spacing support doesn't map directly to a single style property, so needs to be handled separately.
// Also, only allow `blockGap` support if serialization has not been skipped, to be sure global spacing can be applied.
if (
blockType?.supports?.spacing?.blockGap &&
blockType?.supports?.spacing?.__experimentalSkipSerialization !==
true &&
! blockType?.supports?.spacing?.__experimentalSkipSerialization?.some?.(
( spacingType ) => spacingType === 'blockGap'
)
) {
supportKeys.push( 'blockGap' );
}

Object.keys( STYLE_PROPERTY ).forEach( ( styleName ) => {
if ( ! STYLE_PROPERTY[ styleName ].support ) {
return;
}

// Opting out means that, for certain support keys like background color,
// blocks have to explicitly set the support value false. If the key is
// unset, we still enable it.
if ( STYLE_PROPERTY[ styleName ].requiresOptOut ) {
if (
STYLE_PROPERTY[ styleName ].support[ 0 ] in
blockType.supports &&
get(
blockType.supports,
STYLE_PROPERTY[ styleName ].support
) !== false
) {
return supportKeys.push( styleName );
}
}

if (
get(
blockType.supports,
STYLE_PROPERTY[ styleName ].support,
false
)
) {
return supportKeys.push( styleName );
}
} );

return filterElementBlockSupports( supportKeys, name, element );
},
( state, name ) => [ state.blockTypes[ name ] ]
);
151 changes: 151 additions & 0 deletions packages/blocks/src/store/test/private-selectors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
/**
* External dependencies
*/
import deepFreeze from 'deep-freeze';

/**
* Internal dependencies
*/
import { getSupportedStyles } from '../private-selectors';

const keyBlocksByName = ( blocks ) =>
blocks.reduce(
( result, block ) => ( { ...result, [ block.name ]: block } ),
{}
);

describe( 'private selectors', () => {
describe( 'getSupportedStyles', () => {
const getState = ( blocks ) => {
return deepFreeze( {
blockTypes: keyBlocksByName( blocks ),
} );
};

it( 'return the list of globally supported panels (no block name)', () => {
const supports = getSupportedStyles( getState( [] ) );

expect( supports ).toEqual( [
'background',
'backgroundColor',
'color',
'linkColor',
'buttonColor',
'fontFamily',
'fontSize',
'fontStyle',
'fontWeight',
'lineHeight',
'padding',
'contentSize',
'wideSize',
'blockGap',
] );
} );

it( 'return the list of globally supported panels including link specific styles', () => {
const supports = getSupportedStyles( getState( [] ), null, 'link' );

expect( supports ).toEqual( [
'background',
'backgroundColor',
'color',
'linkColor',
'buttonColor',
'fontFamily',
'fontSize',
'fontStyle',
'fontWeight',
'lineHeight',
'padding',
'contentSize',
'wideSize',
'blockGap',
'textDecoration',
] );
} );

it( 'return the list of globally supported panels including heading specific styles', () => {
const supports = getSupportedStyles(
getState( [] ),
null,
'heading'
);

expect( supports ).toEqual( [
'background',
'backgroundColor',
'color',
'linkColor',
'buttonColor',
'fontFamily',
'fontStyle',
'fontWeight',
'lineHeight',
'padding',
'contentSize',
'wideSize',
'blockGap',
'textTransform',
'letterSpacing',
] );
} );

it( 'return an empty list for unknown blocks', () => {
const supports = getSupportedStyles(
getState( [] ),
'unkown/block'
);

expect( supports ).toEqual( [] );
} );

it( 'return empty by default for blocks without support keys', () => {
const supports = getSupportedStyles(
getState( [
{
name: 'core/example-block',
supports: {},
},
] ),
'core/example-block'
);

expect( supports ).toEqual( [] );
} );

it( 'return the allowed styles according to the blocks support keys', () => {
const supports = getSupportedStyles(
getState( [
{
name: 'core/example-block',
supports: {
typography: {
__experimentalFontFamily: true,
__experimentalFontStyle: true,
__experimentalFontWeight: true,
__experimentalTextDecoration: true,
__experimentalTextTransform: true,
__experimentalLetterSpacing: true,
fontSize: true,
lineHeight: true,
},
},
},
] ),
'core/example-block'
);

expect( supports ).toEqual( [
'fontFamily',
'fontSize',
'fontStyle',
'fontWeight',
'lineHeight',
'textDecoration',
'textTransform',
'letterSpacing',
] );
} );
} );
} );
10 changes: 5 additions & 5 deletions packages/edit-site/src/components/global-styles/border-panel.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { __ } from '@wordpress/i18n';
/**
* Internal dependencies
*/
import { getSupportedGlobalStylesPanels, useColorsPerOrigin } from './hooks';
import { useSupportedStyles, useColorsPerOrigin } from './hooks';
import { unlock } from '../../experiments';

const { useGlobalSetting, useGlobalStyle } = unlock( blockEditorExperiments );
Expand All @@ -35,31 +35,31 @@ export function useHasBorderPanel( name ) {
}

function useHasBorderColorControl( name ) {
const supports = getSupportedGlobalStylesPanels( name );
const supports = useSupportedStyles( name );
return (
useGlobalSetting( 'border.color', name )[ 0 ] &&
supports.includes( 'borderColor' )
);
}

function useHasBorderRadiusControl( name ) {
const supports = getSupportedGlobalStylesPanels( name );
const supports = useSupportedStyles( name );
return (
useGlobalSetting( 'border.radius', name )[ 0 ] &&
supports.includes( 'borderRadius' )
);
}

function useHasBorderStyleControl( name ) {
const supports = getSupportedGlobalStylesPanels( name );
const supports = useSupportedStyles( name );
return (
useGlobalSetting( 'border.style', name )[ 0 ] &&
supports.includes( 'borderStyle' )
);
}

function useHasBorderWidthControl( name ) {
const supports = getSupportedGlobalStylesPanels( name );
const supports = useSupportedStyles( name );
return (
useGlobalSetting( 'border.width', name )[ 0 ] &&
supports.includes( 'borderWidth' )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
* Internal dependencies
*/

import { getSupportedGlobalStylesPanels } from './hooks';
import { useSupportedStyles } from './hooks';

export function useHasColorPanel( name ) {
const supports = getSupportedGlobalStylesPanels( name );
const supports = useSupportedStyles( name );
return (
supports.includes( 'color' ) ||
supports.includes( 'backgroundColor' ) ||
Expand Down
Loading

0 comments on commit 0ecc13c

Please sign in to comment.