Components: Export reusable components to a separate file + global (https://github.com/woocommerce/woocommerce-admin/pull/297)

* Importing all components from a root components file

* Update Ratings component to avoid circular dependencies, fix tests

* Export components on `wc.components`, use this for importing

* Move react-dates initialize to the components file

* Push query changes to history

Fixes an issues where native a links do not update the query in `history`

* Update test config for new @woocommerce/components path

* Update chart components import

* Merge simple/complex & alphabetize by first exported name

* Add a readme with info about how to call these components
This commit is contained in:
Kelly Dwan 2018-08-20 17:18:13 -04:00 committed by GitHub
parent 11524e19e1
commit dec97d178e
29 changed files with 210 additions and 126 deletions

View File

@ -9,7 +9,7 @@ import { Component, Fragment } from '@wordpress/element';
* Internal dependencies * Internal dependencies
*/ */
import Header from 'layout/header'; import Header from 'layout/header';
import { SummaryList, SummaryNumber } from 'components/summary'; import { SummaryList, SummaryNumber } from '@woocommerce/components';
export default class extends Component { export default class extends Component {
render() { render() {

View File

@ -13,10 +13,9 @@ import { partial } from 'lodash';
/** /**
* Internal dependencies * Internal dependencies
*/ */
import Card from 'components/card'; import { Card, ReportFilters } from '@woocommerce/components';
import { filters, filterPaths, advancedFilterConfig } from './constants'; import { filters, filterPaths, advancedFilterConfig } from './constants';
import Header from 'layout/header/index'; import Header from 'layout/header/index';
import { ReportFilters } from 'components/filters';
import './style.scss'; import './style.scss';
class OrdersReport extends Component { class OrdersReport extends Component {

View File

@ -10,7 +10,7 @@ import { Component, Fragment } from '@wordpress/element';
*/ */
import { filterPaths, filters } from './constants'; import { filterPaths, filters } from './constants';
import Header from 'layout/header'; import Header from 'layout/header';
import { ReportFilters } from 'components/filters'; import { ReportFilters } from '@woocommerce/components';
import './style.scss'; import './style.scss';
export default class extends Component { export default class extends Component {

View File

@ -11,15 +11,18 @@ import PropTypes from 'prop-types';
/** /**
* Internal dependencies * Internal dependencies
*/ */
import Card from 'components/card'; import {
import Chart from 'components/chart'; Card,
Chart,
ReportFilters,
SummaryList,
SummaryNumber,
TableCard,
} from '@woocommerce/components';
import { formatCurrency, getCurrencyFormatDecimal } from 'lib/currency'; import { formatCurrency, getCurrencyFormatDecimal } from 'lib/currency';
import { getAdminLink, updateQueryString } from 'lib/nav-utils'; import { getAdminLink, updateQueryString } from 'lib/nav-utils';
import { getReportData } from 'lib/swagger'; import { getReportData } from 'lib/swagger';
import Header from 'layout/header'; import Header from 'layout/header';
import { ReportFilters } from 'components/filters';
import { SummaryList, SummaryNumber } from 'components/summary';
import { TableCard } from 'components/table';
// Mock data until we fetch from an API // Mock data until we fetch from an API
import rawData from './mock-data'; import rawData from './mock-data';

View File

@ -0,0 +1,38 @@
Components
==========
This folder contains the WooCommerce-created components. These are exported onto a global, `wc.components`, for general use.
## How to use:
For any files not imported into `components/index.js` (`analytics/*`, `layout/*`, `dashboard/*`, etc), we can use `import { Card, etc … } from @woocommerce/components`.
For any `component/*` files, we should import from component-specific paths, not from `component/index.js`, to prevent circular dependencies. See `components/card/index.js` for an example.
```jsx
import { Card, Link } from '@woocommerce/components';
render: function() {
return (
<Card title="Card demo">
Card content with an <Link href="/">example link.</Link>
</Card>
);
}
```
## For external development
External developers will need to enqueue the components library, `wc-components`, and then can access them from the global.
```jsx
const { Card, Link } = wc.components;
render: function() {
return (
<Card title="Card demo">
Card content with an <Link href="/">example link.</Link>
</Card>
);
}
```

View File

@ -10,7 +10,7 @@ import PropTypes from 'prop-types';
* Internal dependencies * Internal dependencies
*/ */
import './style.scss'; import './style.scss';
import { EllipsisMenu } from '../ellipsis-menu'; import { EllipsisMenu } from 'components/ellipsis-menu';
import { H, Section } from 'layout/section'; import { H, Section } from 'layout/section';
class Card extends Component { class Card extends Component {

View File

@ -9,7 +9,7 @@ import { Component, Fragment } from '@wordpress/element';
* Internal dependencies * Internal dependencies
*/ */
import Card from 'components/card'; import Card from 'components/card';
import Chart from 'components/chart'; import Chart from './index';
import dummyOrders from './test/fixtures/dummy'; import dummyOrders from './test/fixtures/dummy';
class WidgetCharts extends Component { class WidgetCharts extends Component {

View File

@ -14,7 +14,6 @@ import classnames from 'classnames';
import ComparePeriods from './compare-periods'; import ComparePeriods from './compare-periods';
import { DateRange } from 'components/calendar'; import { DateRange } from 'components/calendar';
import { H, Section } from 'layout/section'; import { H, Section } from 'layout/section';
import Link from 'components/link';
import PresetPeriods from './preset-periods'; import PresetPeriods from './preset-periods';
const isMobileViewport = () => window.innerWidth < 782; const isMobileViewport = () => window.innerWidth < 782;
@ -45,7 +44,7 @@ class DatePickerContent extends Component {
before, before,
onUpdate, onUpdate,
onClose, onClose,
getUpdatePath, onSelect,
isValidSelection, isValidSelection,
resetCustomValues, resetCustomValues,
focusedInput, focusedInput,
@ -127,13 +126,13 @@ class DatePickerContent extends Component {
</Button> </Button>
) } ) }
{ isValidSelection( selectedTab ) ? ( { isValidSelection( selectedTab ) ? (
<Link <Button
className="woocommerce-filters-date__button components-button is-button is-primary" className="woocommerce-filters-date__button"
href={ getUpdatePath( selectedTab ) } onClick={ onSelect( selectedTab, onClose ) }
onClick={ onClose } isPrimary
> >
{ __( 'Update', 'wc-admin' ) } { __( 'Update', 'wc-admin' ) }
</Link> </Button>
) : ( ) : (
<Button className="woocommerce-filters-date__button" isPrimary disabled> <Button className="woocommerce-filters-date__button" isPrimary disabled>
{ __( 'Update', 'wc-admin' ) } { __( 'Update', 'wc-admin' ) }
@ -155,7 +154,7 @@ DatePickerContent.propTypes = {
compare: PropTypes.string.isRequired, compare: PropTypes.string.isRequired,
onUpdate: PropTypes.func.isRequired, onUpdate: PropTypes.func.isRequired,
onClose: PropTypes.func.isRequired, onClose: PropTypes.func.isRequired,
getUpdatePath: PropTypes.func.isRequired, onSelect: PropTypes.func.isRequired,
resetCustomValues: PropTypes.func.isRequired, resetCustomValues: PropTypes.func.isRequired,
focusedInput: PropTypes.string, focusedInput: PropTypes.string,
afterText: PropTypes.string, afterText: PropTypes.string,

View File

@ -12,7 +12,7 @@ import { Dropdown } from '@wordpress/components';
import DatePickerContent from './content'; import DatePickerContent from './content';
import DropdownButton from 'components/dropdown-button'; import DropdownButton from 'components/dropdown-button';
import { getCurrentDates, getDateParamsFromQuery, isoDateFormat } from 'lib/date'; import { getCurrentDates, getDateParamsFromQuery, isoDateFormat } from 'lib/date';
import { getNewPath, getQuery } from 'lib/nav-utils'; import { getQuery, updateQueryString } from 'lib/nav-utils';
import './style.scss'; import './style.scss';
const shortDateFormat = __( 'MM/DD/YYYY', 'wc-admin' ); const shortDateFormat = __( 'MM/DD/YYYY', 'wc-admin' );
@ -23,7 +23,7 @@ class DatePicker extends Component {
this.state = this.getResetState(); this.state = this.getResetState();
this.update = this.update.bind( this ); this.update = this.update.bind( this );
this.getUpdatePath = this.getUpdatePath.bind( this ); this.onSelect = this.onSelect.bind( this );
this.isValidSelection = this.isValidSelection.bind( this ); this.isValidSelection = this.isValidSelection.bind( this );
this.resetCustomValues = this.resetCustomValues.bind( this ); this.resetCustomValues = this.resetCustomValues.bind( this );
} }
@ -47,7 +47,8 @@ class DatePicker extends Component {
this.setState( update ); this.setState( update );
} }
getUpdatePath( selectedTab ) { onSelect( selectedTab, onClose ) {
return event => {
const { period, compare, after, before } = this.state; const { period, compare, after, before } = this.state;
const data = { const data = {
period: 'custom' === selectedTab ? 'custom' : period, period: 'custom' === selectedTab ? 'custom' : period,
@ -57,7 +58,9 @@ class DatePicker extends Component {
data.after = after ? after.format( isoDateFormat ) : ''; data.after = after ? after.format( isoDateFormat ) : '';
data.before = before ? before.format( isoDateFormat ) : ''; data.before = before ? before.format( isoDateFormat ) : '';
} }
return getNewPath( data ); updateQueryString( data );
onClose( event );
};
} }
getButtonLabel() { getButtonLabel() {
@ -122,7 +125,7 @@ class DatePicker extends Component {
before={ before } before={ before }
onUpdate={ this.update } onUpdate={ this.update }
onClose={ onClose } onClose={ onClose }
getUpdatePath={ this.getUpdatePath } onSelect={ this.onSelect }
isValidSelection={ this.isValidSelection } isValidSelection={ this.isValidSelection }
resetCustomValues={ this.resetCustomValues } resetCustomValues={ this.resetCustomValues }
focusedInput={ focusedInput } focusedInput={ focusedInput }

View File

@ -14,8 +14,7 @@ import PropTypes from 'prop-types';
*/ */
import AnimationSlider from 'components/animation-slider'; import AnimationSlider from 'components/animation-slider';
import DropdownButton from 'components/dropdown-button'; import DropdownButton from 'components/dropdown-button';
import { getNewPath, getQuery } from 'lib/nav-utils'; import { getQuery, updateQueryString } from 'lib/nav-utils';
import Link from 'components/link';
import './style.scss'; import './style.scss';
export const DEFAULT_FILTER = 'all'; export const DEFAULT_FILTER = 'all';
@ -30,7 +29,6 @@ class FilterPicker extends Component {
animate: null, animate: null,
}; };
this.getSelectionPath = this.getSelectionPath.bind( this );
this.getSelectedFilter = this.getSelectedFilter.bind( this ); this.getSelectedFilter = this.getSelectedFilter.bind( this );
this.selectSubFilters = this.selectSubFilters.bind( this ); this.selectSubFilters = this.selectSubFilters.bind( this );
this.getVisibleFilters = this.getVisibleFilters.bind( this ); this.getVisibleFilters = this.getVisibleFilters.bind( this );
@ -42,10 +40,6 @@ class FilterPicker extends Component {
return query.filter || DEFAULT_FILTER; return query.filter || DEFAULT_FILTER;
} }
getSelectionPath( filter ) {
return getNewPath( { filter: filter.value } );
}
getSelectedFilter() { getSelectedFilter() {
const { filters, filterPaths } = this.props; const { filters, filterPaths } = this.props;
const value = this.getFilterValue(); const value = this.getFilterValue();
@ -111,14 +105,15 @@ class FilterPicker extends Component {
); );
} }
const onClick = event => {
onClose( event );
updateQueryString( { filter: filter.value } );
};
return ( return (
<Link <Button className="woocommerce-filters-filter__button" onClick={ onClick }>
className="woocommerce-filters-filter__button components-button"
href={ this.getSelectionPath( filter ) }
onClick={ onClose }
>
{ filter.label } { filter.label }
</Link> </Button>
); );
} }

View File

@ -0,0 +1,30 @@
/** @format */
/**
* External Dependencies
*/
// Turn on react-dates classes/styles, see https://github.com/airbnb/react-dates#initialize
import 'react-dates/initialize';
export { AdvancedFilters, DatePicker, FilterPicker, ReportFilters } from './filters';
export { default as AnimationSlider } from './animation-slider';
export { default as Card } from './card';
export { default as Chart } from './chart';
export { default as Count } from './count';
export { DateRange } from './calendar';
export { default as DropdownButton } from './dropdown-button';
export { EllipsisMenu, MenuItem, MenuTitle } from './ellipsis-menu';
export { default as Flag } from './flag';
export { default as Gravatar } from './gravatar';
export { default as Link } from './link';
export { default as OrderStatus } from './order-status';
export { default as Pagination } from './pagination';
export { default as ProductImage } from './product-image';
export { default as ProductRating } from './rating/product';
export { default as Rating } from './rating';
export { default as ReviewRating } from './rating/review';
export { default as SegmentedSelection } from './segmented-selection';
export { default as SplitButton } from './split-button';
export { SummaryList, SummaryNumber } from './summary';
export { TableCard, Table, TableSummary } from './table';
export { default as useFilters } from './higher-order/use-filters';

View File

@ -64,6 +64,4 @@ Rating.defaultProps = {
size: 18, size: 18,
}; };
export { Rating }; export default Rating;
export { default as ProductRating } from './product';
export { default as ReviewRating } from './review';

View File

@ -3,21 +3,17 @@
/** /**
* External dependencies * External dependencies
*/ */
import { Component } from '@wordpress/element';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
/** /**
* Internal dependencies * Internal dependencies
*/ */
import { Rating } from './index'; import Rating from './index';
class ProductRating extends Component { const ProductRating = ( { product, ...props } ) => {
render() {
const { product, restOfProps } = this.props;
const rating = ( product && product.average_rating ) || 0; const rating = ( product && product.average_rating ) || 0;
return <Rating rating={ rating } { ...restOfProps } />; return <Rating rating={ rating } { ...props } />;
} };
}
ProductRating.propTypes = { ProductRating.propTypes = {
product: PropTypes.object.isRequired, product: PropTypes.object.isRequired,

View File

@ -3,21 +3,17 @@
/** /**
* External dependencies * External dependencies
*/ */
import { Component } from '@wordpress/element';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
/** /**
* Internal dependencies * Internal dependencies
*/ */
import { Rating } from './index'; import Rating from './index';
class ReviewRating extends Component { const ReviewRating = ( { review, ...props } ) => {
render() {
const { review, restOfProps } = this.props;
const rating = ( review && review.rating ) || 0; const rating = ( review && review.rating ) || 0;
return <Rating rating={ rating } { ...restOfProps } />; return <Rating rating={ rating } { ...props } />;
} };
}
ReviewRating.propTypes = { ReviewRating.propTypes = {
review: PropTypes.object.isRequired, review: PropTypes.object.isRequired,

View File

@ -7,7 +7,9 @@ import { shallow } from 'enzyme';
/** /**
* Internal dependencies * Internal dependencies
*/ */
import { ReviewRating, ProductRating, Rating } from '../'; import Rating from '../';
import ProductRating from '../product';
import ReviewRating from '../review';
describe( 'Rating', () => { describe( 'Rating', () => {
test( 'should render the passed rating prop', () => { test( 'should render the passed rating prop', () => {
@ -28,28 +30,22 @@ describe( 'Rating', () => {
describe( 'ReviewRating', () => { describe( 'ReviewRating', () => {
test( 'should render rating based on review object', () => { test( 'should render rating based on review object', () => {
const rating = shallow( const review = {
<ReviewRating
review={ {
review: 'Nice T-shirt!', review: 'Nice T-shirt!',
rating: 1.5, rating: 1.5,
} } };
/> const rating = shallow( <ReviewRating review={ review } /> );
);
expect( rating ).toMatchSnapshot(); expect( rating ).toMatchSnapshot();
} ); } );
} ); } );
describe( 'ProductRating', () => { describe( 'ProductRating', () => {
test( 'should render rating based on product object', () => { test( 'should render rating based on product object', () => {
const rating = shallow( const product = {
<ProductRating
product={ {
name: 'Test Product', name: 'Test Product',
average_rating: 2.5, average_rating: 2.5,
} } };
/> const rating = shallow( <ProductRating product={ product } /> );
);
expect( rating ).toMatchSnapshot(); expect( rating ).toMatchSnapshot();
} ); } );
} ); } );

View File

@ -9,11 +9,11 @@ import { Component, Fragment } from '@wordpress/element';
* Internal dependencies * Internal dependencies
*/ */
import './style.scss'; import './style.scss';
import { Card } from '@woocommerce/components';
import ChartExample from 'components/chart/example';
import Header from 'layout/header'; import Header from 'layout/header';
import StorePerformance from './store-performance'; import StorePerformance from './store-performance';
import TopSellingProducts from './top-selling-products'; import TopSellingProducts from './top-selling-products';
import Chart from 'components/chart/example';
import Card from 'components/card';
export default class Dashboard extends Component { export default class Dashboard extends Component {
render() { render() {
@ -21,7 +21,7 @@ export default class Dashboard extends Component {
<Fragment> <Fragment>
<Header sections={ [ __( 'Dashboard', 'wc-admin' ) ] } /> <Header sections={ [ __( 'Dashboard', 'wc-admin' ) ] } />
<StorePerformance /> <StorePerformance />
<Chart /> <ChartExample />
<div className="woocommerce-dashboard__columns"> <div className="woocommerce-dashboard__columns">
<div> <div>
<TopSellingProducts /> <TopSellingProducts />

View File

@ -9,9 +9,14 @@ import { Component } from '@wordpress/element';
/** /**
* Internal dependencies * Internal dependencies
*/ */
import Card from 'components/card'; import {
import { EllipsisMenu, MenuItem, MenuTitle } from 'components/ellipsis-menu'; Card,
import { SummaryList, SummaryNumber } from 'components/summary'; EllipsisMenu,
MenuItem,
MenuTitle,
SummaryList,
SummaryNumber,
} from '@woocommerce/components';
import './style.scss'; import './style.scss';
class StorePerformance extends Component { class StorePerformance extends Component {

View File

@ -9,11 +9,10 @@ import { map } from 'lodash';
/** /**
* Internal dependencies * Internal dependencies
*/ */
import Card from 'components/card'; import { Card, Table } from '@woocommerce/components';
import { getAdminLink } from 'lib/nav-utils'; import { getAdminLink } from 'lib/nav-utils';
import { numberFormat } from 'lib/number'; import { numberFormat } from 'lib/number';
import { formatCurrency, getCurrencyFormatDecimal } from 'lib/currency'; import { formatCurrency, getCurrencyFormatDecimal } from 'lib/currency';
import { Table } from 'components/table';
import './style.scss'; import './style.scss';
// Mock data until we fetch from an API // Mock data until we fetch from an API

View File

@ -6,7 +6,6 @@ import { APIProvider } from '@wordpress/components';
import { pick } from 'lodash'; import { pick } from 'lodash';
import { render } from '@wordpress/element'; import { render } from '@wordpress/element';
import { Provider as SlotFillProvider } from 'react-slot-fill'; import { Provider as SlotFillProvider } from 'react-slot-fill';
import 'react-dates/initialize';
/** /**
* Internal dependencies * Internal dependencies

View File

@ -10,7 +10,7 @@ import { shallow } from 'enzyme';
* Internal dependencies * Internal dependencies
*/ */
import { ActivityCard } from '../'; import { ActivityCard } from '../';
import Gravatar from 'components/gravatar'; import { Gravatar } from '@woocommerce/components';
describe( 'ActivityCard', () => { describe( 'ActivityCard', () => {
test( 'should have correct title', () => { test( 'should have correct title', () => {

View File

@ -10,7 +10,7 @@ import PropTypes from 'prop-types';
* Internal dependencies * Internal dependencies
*/ */
import './style.scss'; import './style.scss';
import { EllipsisMenu } from 'components/ellipsis-menu'; import { EllipsisMenu } from '@woocommerce/components';
import { H } from 'layout/section'; import { H } from 'layout/section';
class ActivityHeader extends Component { class ActivityHeader extends Component {

View File

@ -11,7 +11,7 @@ import Gridicon from 'gridicons';
* Internal dependencies * Internal dependencies
*/ */
import './style.scss'; import './style.scss';
import Link from 'components/link'; import { Link } from '@woocommerce/components';
const ActivityOutboundLink = props => { const ActivityOutboundLink = props => {
const { href, type, className, children, ...restOfProps } = props; const { href, type, className, children, ...restOfProps } = props;

View File

@ -14,12 +14,16 @@ import { noop } from 'lodash';
import { ActivityCard } from '../activity-card'; import { ActivityCard } from '../activity-card';
import ActivityHeader from '../activity-header'; import ActivityHeader from '../activity-header';
import ActivityOutboundLink from '../activity-outbound-link'; import ActivityOutboundLink from '../activity-outbound-link';
import { EllipsisMenu, MenuTitle, MenuItem } from 'components/ellipsis-menu'; import {
EllipsisMenu,
Gravatar,
Flag,
MenuTitle,
MenuItem,
OrderStatus,
} from '@woocommerce/components';
import { formatCurrency, getCurrencyFormatDecimal } from 'lib/currency'; import { formatCurrency, getCurrencyFormatDecimal } from 'lib/currency';
import { getOrderRefundTotal } from 'lib/order-values'; import { getOrderRefundTotal } from 'lib/order-values';
import Gravatar from 'components/gravatar';
import Flag from 'components/flag';
import OrderStatus from 'components/order-status';
import { Section } from 'layout/section'; import { Section } from 'layout/section';
function OrdersPanel( { orders } ) { function OrdersPanel( { orders } ) {

View File

@ -13,12 +13,8 @@ import { noop } from 'lodash';
*/ */
import { ActivityCard, ActivityCardPlaceholder } from '../activity-card'; import { ActivityCard, ActivityCardPlaceholder } from '../activity-card';
import ActivityHeader from '../activity-header'; import ActivityHeader from '../activity-header';
import Gravatar from 'components/gravatar'; import { Gravatar, Link, ProductImage, ReviewRating, SplitButton } from '@woocommerce/components';
import Link from 'components/link';
import ProductImage from 'components/product-image';
import { ReviewRating } from 'components/rating';
import { Section } from 'layout/section'; import { Section } from 'layout/section';
import SplitButton from 'components/split-button';
// TODO Pull proper data from the API // TODO Pull proper data from the API
const demoReviews = [ const demoReviews = [

View File

@ -8,7 +8,6 @@ import classnames from 'classnames';
import { decodeEntities } from '@wordpress/html-entities'; import { decodeEntities } from '@wordpress/html-entities';
import { Fill } from 'react-slot-fill'; import { Fill } from 'react-slot-fill';
import { isArray } from 'lodash'; import { isArray } from 'lodash';
import Link from 'components/link';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import ReactDom from 'react-dom'; import ReactDom from 'react-dom';
@ -17,6 +16,7 @@ import ReactDom from 'react-dom';
*/ */
import './style.scss'; import './style.scss';
import ActivityPanel from '../activity-panel'; import ActivityPanel from '../activity-panel';
import { Link } from '@woocommerce/components';
class Header extends Component { class Header extends Component {
constructor() { constructor() {

View File

@ -1,4 +1,10 @@
<?php <?php
/**
* Register javascript & css files.
*
* @package WC_Admin
*/
/** /**
* Registers the JS & CSS for the admin and admin embed * Registers the JS & CSS for the admin and admin embed
*/ */
@ -14,10 +20,25 @@ function wc_admin_register_script() {
$css_entry = 'dist/css/index.css'; $css_entry = 'dist/css/index.css';
} }
wp_register_script(
'wc-components',
wc_admin_url( 'dist/components.js' ),
[ 'wp-components', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-keycodes' ],
filemtime( wc_admin_dir_path( 'dist/components.js' ) ),
true
);
wp_register_style(
'wc-components',
wc_admin_url( 'dist/css/components.css' ),
[ 'wp-edit-blocks' ],
filemtime( wc_admin_dir_path( 'dist/css/components.css' ) )
);
wp_register_script( wp_register_script(
WC_ADMIN_APP, WC_ADMIN_APP,
wc_admin_url( $js_entry ), wc_admin_url( $js_entry ),
[ 'wp-blocks', 'wp-components', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n', 'wp-keycodes' ], [ 'wc-components', 'wp-date', 'wp-html-entities', 'wp-keycodes' ],
filemtime( wc_admin_dir_path( $js_entry ) ), filemtime( wc_admin_dir_path( $js_entry ) ),
true true
); );
@ -25,18 +46,18 @@ function wc_admin_register_script() {
wp_register_style( wp_register_style(
WC_ADMIN_APP, WC_ADMIN_APP,
wc_admin_url( $css_entry ), wc_admin_url( $css_entry ),
[ 'wp-edit-blocks' ], [ 'wc-components' ],
filemtime( wc_admin_dir_path( $css_entry ) ) filemtime( wc_admin_dir_path( $css_entry ) )
); );
// Set up the text domain and translations // Set up the text domain and translations.
$locale_data = gutenberg_get_jed_locale_data( 'wc-admin' ); $locale_data = gutenberg_get_jed_locale_data( 'wc-admin' );
$content = 'wp.i18n.setLocaleData( ' . json_encode( $locale_data ) . ', "wc-admin" );'; $content = 'wp.i18n.setLocaleData( ' . json_encode( $locale_data ) . ', "wc-admin" );';
wp_add_inline_script( WC_ADMIN_APP, $content, 'before' ); wp_add_inline_script( 'wc-components', $content, 'before' );
wp_enqueue_script( 'wp-api' ); wp_enqueue_script( 'wp-api' );
// Settings and variables can be passed here for access in the app // Settings and variables can be passed here for access in the app.
$settings = array( $settings = array(
'adminUrl' => admin_url(), 'adminUrl' => admin_url(),
'wcAssetUrl' => plugins_url( 'assets/', WC_PLUGIN_FILE ), 'wcAssetUrl' => plugins_url( 'assets/', WC_PLUGIN_FILE ),
@ -51,12 +72,12 @@ function wc_admin_register_script() {
); );
wp_add_inline_script( wp_add_inline_script(
WC_ADMIN_APP, 'wc-components',
'var wcSettings = '. json_encode( $settings ) . ';', 'var wcSettings = ' . json_encode( $settings ) . ';',
'before' 'before'
); );
// Resets lodash to wp-admin's version of lodash // Resets lodash to wp-admin's version of lodash.
wp_add_inline_script( wp_add_inline_script(
WC_ADMIN_APP, WC_ADMIN_APP,
'_.noConflict();', '_.noConflict();',

View File

@ -8,7 +8,8 @@
], ],
"moduleDirectories": ["node_modules", "<rootDir>/client"], "moduleDirectories": ["node_modules", "<rootDir>/client"],
"moduleNameMapper": { "moduleNameMapper": {
"tinymce": "<rootDir>/tests/js/mocks/tinymce" "tinymce": "<rootDir>/tests/js/mocks/tinymce",
"@woocommerce/components": "<rootDir>/client/components"
}, },
"setupFiles": [ "setupFiles": [
"<rootDir>/node_modules/@wordpress/jest-preset-default/scripts/setup-globals.js", "<rootDir>/node_modules/@wordpress/jest-preset-default/scripts/setup-globals.js",

View File

@ -14,6 +14,8 @@ global.wp = {
}, },
}; };
global.wc = {};
Object.defineProperty( global.wp, 'element', { Object.defineProperty( global.wp, 'element', {
get: () => require( '@wordpress/element' ), get: () => require( '@wordpress/element' ),
} ); } );
@ -22,6 +24,10 @@ Object.defineProperty( global.wp, 'date', {
get: () => require( '@wordpress/date' ), get: () => require( '@wordpress/date' ),
} ); } );
Object.defineProperty( global.wc, 'components', {
get: () => require( '@woocommerce/components' ),
} );
global.wcSettings = { global.wcSettings = {
adminUrl: 'https://vagrant.local/wp/wp-admin/', adminUrl: 'https://vagrant.local/wp/wp-admin/',
locale: 'en-US', locale: 'en-US',

View File

@ -9,6 +9,7 @@ const ExtractTextPlugin = require( 'extract-text-webpack-plugin' );
const NODE_ENV = process.env.NODE_ENV || 'development'; const NODE_ENV = process.env.NODE_ENV || 'development';
const externals = { const externals = {
'@woocommerce/components': { this: [ 'wc', 'components' ] },
'@wordpress/blocks': { this: [ 'wp', 'blocks' ] }, '@wordpress/blocks': { this: [ 'wp', 'blocks' ] },
'@wordpress/components': { this: [ 'wp', 'components' ] }, '@wordpress/components': { this: [ 'wp', 'components' ] },
'@wordpress/compose': { this: [ 'wp', 'compose' ] }, '@wordpress/compose': { this: [ 'wp', 'compose' ] },
@ -31,6 +32,7 @@ const webpackConfig = {
mode: NODE_ENV, mode: NODE_ENV,
entry: { entry: {
index: './client/index.js', index: './client/index.js',
components: './client/components/index.js',
embedded: './client/embedded.js', embedded: './client/embedded.js',
}, },
output: { output: {
@ -85,9 +87,7 @@ const webpackConfig = {
'gutenberg-components': path.resolve( __dirname, 'node_modules/@wordpress/components/src' ), 'gutenberg-components': path.resolve( __dirname, 'node_modules/@wordpress/components/src' ),
}, },
}, },
plugins: [ plugins: [ new ExtractTextPlugin( 'css/[name].css' ) ],
new ExtractTextPlugin( 'css/[name].css' ),
],
}; };
if ( webpackConfig.mode !== 'production' ) { if ( webpackConfig.mode !== 'production' ) {