This commit is contained in:
KhaiNguyen
2020-02-13 10:39:37 +07:00
commit 59401cb805
12867 changed files with 4646216 additions and 0 deletions

View File

@@ -0,0 +1,42 @@
/**
* External dependencies
*/
import { createContext, useContext, useEffect } from '@wordpress/element';
/**
* Internal dependencies
*/
import { assertValidContextValue } from './utils';
const validationMap = {
parentName: {
required: true,
type: 'string',
},
};
/**
* This context is a configuration object used for connecting
* all children blocks in a given tree contained in the context with information
* about the parent block. Typically this is used for extensibility features.
*
* @var {React.Context} InnerBlockConfigurationContext A react context object
*/
const InnerBlockConfigurationContext = createContext( { parentName: null } );
export const useInnerBlockConfigurationContext = () =>
useContext( InnerBlockConfigurationContext );
export const InnerBlockConfigurationProvider = ( { value, children } ) => {
useEffect( () => {
assertValidContextValue(
'InnerBlockConfigurationProvider',
validationMap,
value
);
}, [ value ] );
return (
<InnerBlockConfigurationContext.Provider value={ value }>
{ children }
</InnerBlockConfigurationContext.Provider>
);
};

View File

@@ -0,0 +1,42 @@
/**
* External dependencies
*/
import { createContext, useContext, useEffect } from '@wordpress/element';
/**
* Internal dependencies
*/
import { assertValidContextValue } from './utils';
const validationMap = {
layoutStyleClassPrefix: {
required: true,
type: 'string',
},
};
/**
* ProductLayoutContext is an configuration object for layout options shared
* among all components in a tree.
*
* @var {React.Context} ProductLayoutContext A react context object
*/
const ProductLayoutContext = createContext( {
layoutStyleClassPrefix: '',
} );
export const useProductLayoutContext = () => useContext( ProductLayoutContext );
export const ProductLayoutContextProvider = ( { value, children } ) => {
useEffect( () => {
assertValidContextValue(
'ProductLayoutContextProvider',
validationMap,
value
);
}, [ value ] );
return (
<ProductLayoutContext.Provider value={ value }>
{ children }
</ProductLayoutContext.Provider>
);
};

View File

@@ -0,0 +1,19 @@
/**
* External dependencies
*/
import { createContext, useContext } from '@wordpress/element';
/**
* Query state context is the index for used for a query state store. By
* exposing this via context, it allows for all children blocks to be
* synchronized to the same query state defined by the parent in the tree.
*
* Defaults to 'page' for general global querystate shared among all blocks
* in a view.
*
* @var {React.Context} QueryStateContext A react context object
*/
const QueryStateContext = createContext( 'page' );
export const useQueryStateContext = () => useContext( QueryStateContext );
export const QueryStateContextProvider = QueryStateContext.Provider;

View File

@@ -0,0 +1,42 @@
/**
* Internal dependencies
*/
import { assertValidContextValue } from '../utils';
describe( 'assertValidContextValue', () => {
const contextName = 'testContext';
const validationMap = {
cheeseburger: {
required: false,
type: 'string',
},
amountKetchup: {
required: true,
type: 'number',
},
};
it.each`
testValue | expectedMessage | expectError
${{}} | ${'expected'} | ${true}
${10} | ${'expected'} | ${true}
${{ amountKetchup: 20 }} | ${'not expected'} | ${false}
${{ amountKetchup: '10' }} | ${'expected'} | ${true}
${{ cheeseburger: 'fries', amountKetchup: 20 }} | ${'not expected'} | ${false}
`(
'The value of $testValue is $expectedMessage to trigger an Error',
( { testValue, expectError } ) => {
const invokeTest = () => {
assertValidContextValue(
contextName,
validationMap,
testValue
);
};
if ( expectError ) {
expect( invokeTest ).toThrow();
} else {
expect( invokeTest ).not.toThrow();
}
}
);
} );

View File

@@ -0,0 +1,61 @@
/**
* This is an assertion utility for validating that the incoming value prop
* value on a given context provider is valid and throws an error if it isn't.
*
* Note: this asserts values that are expected to be an object.
*
* The validationMap is expected to be an object in the following shape.
*
* {
* [expectedPropertyName<String>]: {
* required: [expectedRequired<Boolean>]
* type: [expectedType<String>]
* }
* }
*
* @param {string} contextName The name of the context provider being
* validated.
* @param {Object} validationMap A map for validating the incoming value against.
* @param {Object} value The value being validated.
*
* @throws {Error}
*/
export const assertValidContextValue = (
contextName,
validationMap,
value
) => {
if ( typeof value !== 'object' ) {
throw new Error(
`${ contextName } expects an object for its context value`
);
}
const errors = [];
for ( const expectedProperty in validationMap ) {
if (
validationMap[ expectedProperty ].required &&
typeof value[ expectedProperty ] === 'undefined'
) {
errors.push(
`The ${ expectedProperty } is required and is not present.`
);
} else if (
typeof value[ expectedProperty ] !== 'undefined' &&
typeof value[ expectedProperty ] !==
validationMap[ expectedProperty ].type
) {
errors.push(
`The ${ expectedProperty } must be of ${
validationMap[ expectedProperty ].type
} and instead was ${ typeof value[ expectedProperty ] }`
);
}
}
if ( errors.length > 0 ) {
throw new Error(
`There was a problem with the value passed in on ${ contextName }:\n ${ errors.join(
'\n'
) }`
);
}
};