initial commit

This commit is contained in:
2021-12-10 12:03:04 +00:00
commit c46c7ddbf0
3643 changed files with 582794 additions and 0 deletions

View File

@ -0,0 +1,73 @@
/**
* External dependencies
*/
import PropTypes from 'prop-types';
import classnames from 'classnames';
import { Notice } from 'wordpress-components';
/**
* Internal dependencies
*/
import './style.scss';
const getWooClassName = ( { status = 'default' } ) => {
switch ( status ) {
case 'error':
return 'woocommerce-error';
case 'success':
return 'woocommerce-message';
case 'info':
case 'warning':
return 'woocommerce-info';
}
return '';
};
const StoreNoticesContainer = ( { className, notices, removeNotice } ) => {
const regularNotices = notices.filter(
( notice ) => notice.type !== 'snackbar'
);
if ( ! regularNotices.length ) {
return null;
}
const wrapperClass = classnames( className, 'wc-block-components-notices' );
return (
<div className={ wrapperClass }>
{ regularNotices.map( ( props ) => (
<Notice
key={ 'store-notice-' + props.id }
{ ...props }
className={ classnames(
'wc-block-components-notices__notice',
getWooClassName( props )
) }
onRemove={ () => {
if ( props.isDismissible ) {
removeNotice( props.id );
}
} }
>
{ props.content }
</Notice>
) ) }
</div>
);
};
StoreNoticesContainer.propTypes = {
className: PropTypes.string,
notices: PropTypes.arrayOf(
PropTypes.shape( {
content: PropTypes.string.isRequired,
id: PropTypes.string.isRequired,
status: PropTypes.string.isRequired,
isDismissible: PropTypes.bool,
type: PropTypes.oneOf( [ 'default', 'snackbar' ] ),
} )
),
};
export default StoreNoticesContainer;

View File

@ -0,0 +1,32 @@
.wc-block-components-notices {
display: block;
margin-bottom: 2em;
.wc-block-components-notices__notice {
margin: 0;
display: flex;
flex-wrap: nowrap;
.components-notice__dismiss {
background: transparent none;
padding: 0;
margin: 0 0 0 auto;
border: 0;
outline: 0;
color: currentColor;
svg {
fill: currentColor;
vertical-align: text-top;
}
}
}
.wc-block-components-notices__notice + .wc-block-components-notices__notice {
margin-top: 1em;
}
}
// @todo Either move notice style fixes to Woo core, or take full control over notice component styling in blocks.
.theme-twentytwentyone,
.theme-twentytwenty {
.wc-block-components-notices__notice {
padding: 1.5rem 3rem;
}
}

View File

@ -0,0 +1,130 @@
/**
* External dependencies
*/
import PropTypes from 'prop-types';
import {
createContext,
useContext,
useCallback,
useState,
} from '@wordpress/element';
import { useSelect, useDispatch } from '@wordpress/data';
/**
* Internal dependencies
*/
import { useStoreEvents } from '../../hooks/use-store-events';
import { useEditorContext } from '../editor-context';
import StoreNoticesContainer from './components/store-notices-container';
/**
* @typedef {import('@woocommerce/type-defs/contexts').NoticeContext} NoticeContext
* @typedef {import('react')} React
*/
const StoreNoticesContext = createContext( {
notices: [],
createNotice: ( status, text, props ) => void { status, text, props },
removeNotice: ( id, ctxt ) => void { id, ctxt },
setIsSuppressed: ( val ) => void { val },
context: 'wc/core',
} );
/**
* Returns the notices context values.
*
* @return {NoticeContext} The notice context value from the notice context.
*/
export const useStoreNoticesContext = () => {
return useContext( StoreNoticesContext );
};
/**
* Provides an interface for blocks to add notices to the frontend UI.
*
* Statuses map to https://github.com/WordPress/gutenberg/tree/master/packages/components/src/notice
* - Default (no status)
* - Error
* - Warning
* - Info
* - Success
*
* @param {Object} props Incoming props for the component.
* @param {JSX.Element} props.children The Elements wrapped by this component.
* @param {string} [props.className] CSS class used.
* @param {boolean} [props.createNoticeContainer] Whether to create a notice container or not.
* @param {string} [props.context] The notice context for notices being rendered.
*/
export const StoreNoticesProvider = ( {
children,
className = '',
createNoticeContainer = true,
context = 'wc/core',
} ) => {
const { createNotice, removeNotice } = useDispatch( 'core/notices' );
const [ isSuppressed, setIsSuppressed ] = useState( false );
const { dispatchStoreEvent } = useStoreEvents();
const { isEditor } = useEditorContext();
const createNoticeWithContext = useCallback(
( status = 'default', content = '', options = {} ) => {
createNotice( status, content, {
...options,
context: options.context || context,
} );
dispatchStoreEvent( 'store-notice-create', {
status,
content,
options,
} );
},
[ createNotice, dispatchStoreEvent, context ]
);
const removeNoticeWithContext = useCallback(
( id, ctxt = context ) => {
removeNotice( id, ctxt );
},
[ removeNotice, context ]
);
const { notices } = useSelect(
( select ) => {
return {
notices: select( 'core/notices' ).getNotices( context ),
};
},
[ context ]
);
const contextValue = {
notices,
createNotice: createNoticeWithContext,
removeNotice: removeNoticeWithContext,
context,
setIsSuppressed,
};
const noticeOutput = isSuppressed ? null : (
<StoreNoticesContainer
className={ className }
notices={ contextValue.notices }
removeNotice={ contextValue.removeNotice }
isEditor={ isEditor }
/>
);
return (
<StoreNoticesContext.Provider value={ contextValue }>
{ createNoticeContainer && noticeOutput }
{ children }
</StoreNoticesContext.Provider>
);
};
StoreNoticesProvider.propTypes = {
className: PropTypes.string,
createNoticeContainer: PropTypes.bool,
children: PropTypes.node,
context: PropTypes.string,
};

View File

@ -0,0 +1,2 @@
export * from './components/store-notices-container';
export * from './context';