UNPKG

@wordpress/blocks

Version:
269 lines (252 loc) 5.75 kB
/** * External dependencies */ import { filter, find, get, isEmpty, keyBy, map, mapValues, omit, uniqBy, } from 'lodash'; /** * WordPress dependencies */ import { combineReducers } from '@wordpress/data'; import { __ } from '@wordpress/i18n'; /** * @typedef {Object} WPBlockCategory * * @property {string} slug Unique category slug. * @property {string} title Category label, for display in user interface. */ /** * Default set of categories. * * @type {WPBlockCategory[]} */ export const DEFAULT_CATEGORIES = [ { slug: 'text', title: __( 'Text' ) }, { slug: 'media', title: __( 'Media' ) }, { slug: 'design', title: __( 'Design' ) }, { slug: 'widgets', title: __( 'Widgets' ) }, { slug: 'theme', title: __( 'Theme' ) }, { slug: 'embed', title: __( 'Embeds' ) }, { slug: 'reusable', title: __( 'Reusable blocks' ) }, ]; /** * Reducer managing the block types * * @param {Object} state Current state. * @param {Object} action Dispatched action. * * @return {Object} Updated state. */ export function blockTypes( state = {}, action ) { switch ( action.type ) { case 'ADD_BLOCK_TYPES': return { ...state, ...keyBy( map( action.blockTypes, ( blockType ) => omit( blockType, 'styles ' ) ), 'name' ), }; case 'REMOVE_BLOCK_TYPES': return omit( state, action.names ); } return state; } /** * Reducer managing the block style variations. * * @param {Object} state Current state. * @param {Object} action Dispatched action. * * @return {Object} Updated state. */ export function blockStyles( state = {}, action ) { switch ( action.type ) { case 'ADD_BLOCK_TYPES': return { ...state, ...mapValues( keyBy( action.blockTypes, 'name' ), ( blockType ) => { return uniqBy( [ ...get( blockType, [ 'styles' ], [] ), ...get( state, [ blockType.name ], [] ), ], ( style ) => style.name ); } ), }; case 'ADD_BLOCK_STYLES': return { ...state, [ action.blockName ]: uniqBy( [ ...get( state, [ action.blockName ], [] ), ...action.styles, ], ( style ) => style.name ), }; case 'REMOVE_BLOCK_STYLES': return { ...state, [ action.blockName ]: filter( get( state, [ action.blockName ], [] ), ( style ) => action.styleNames.indexOf( style.name ) === -1 ), }; } return state; } /** * Reducer managing the block variations. * * @param {Object} state Current state. * @param {Object} action Dispatched action. * * @return {Object} Updated state. */ export function blockVariations( state = {}, action ) { switch ( action.type ) { case 'ADD_BLOCK_TYPES': return { ...state, ...mapValues( keyBy( action.blockTypes, 'name' ), ( blockType ) => { return uniqBy( [ ...get( blockType, [ 'variations' ], [] ), ...get( state, [ blockType.name ], [] ), ], ( variation ) => variation.name ); } ), }; case 'ADD_BLOCK_VARIATIONS': return { ...state, [ action.blockName ]: uniqBy( [ ...get( state, [ action.blockName ], [] ), ...action.variations, ], ( variation ) => variation.name ), }; case 'REMOVE_BLOCK_VARIATIONS': return { ...state, [ action.blockName ]: filter( get( state, [ action.blockName ], [] ), ( variation ) => action.variationNames.indexOf( variation.name ) === -1 ), }; } return state; } /** * Higher-order Reducer creating a reducer keeping track of given block name. * * @param {string} setActionType Action type. * * @return {Function} Reducer. */ export function createBlockNameSetterReducer( setActionType ) { return ( state = null, action ) => { switch ( action.type ) { case 'REMOVE_BLOCK_TYPES': if ( action.names.indexOf( state ) !== -1 ) { return null; } return state; case setActionType: return action.name || null; } return state; }; } export const defaultBlockName = createBlockNameSetterReducer( 'SET_DEFAULT_BLOCK_NAME' ); export const freeformFallbackBlockName = createBlockNameSetterReducer( 'SET_FREEFORM_FALLBACK_BLOCK_NAME' ); export const unregisteredFallbackBlockName = createBlockNameSetterReducer( 'SET_UNREGISTERED_FALLBACK_BLOCK_NAME' ); export const groupingBlockName = createBlockNameSetterReducer( 'SET_GROUPING_BLOCK_NAME' ); /** * Reducer managing the categories * * @param {WPBlockCategory[]} state Current state. * @param {Object} action Dispatched action. * * @return {WPBlockCategory[]} Updated state. */ export function categories( state = DEFAULT_CATEGORIES, action ) { switch ( action.type ) { case 'SET_CATEGORIES': return action.categories || []; case 'UPDATE_CATEGORY': { if ( ! action.category || isEmpty( action.category ) ) { return state; } const categoryToChange = find( state, [ 'slug', action.slug ] ); if ( categoryToChange ) { return map( state, ( category ) => { if ( category.slug === action.slug ) { return { ...category, ...action.category, }; } return category; } ); } } } return state; } export function collections( state = {}, action ) { switch ( action.type ) { case 'ADD_BLOCK_COLLECTION': return { ...state, [ action.namespace ]: { title: action.title, icon: action.icon, }, }; case 'REMOVE_BLOCK_COLLECTION': return omit( state, action.namespace ); } return state; } export default combineReducers( { blockTypes, blockStyles, blockVariations, defaultBlockName, freeformFallbackBlockName, unregisteredFallbackBlockName, groupingBlockName, categories, collections, } );