Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update SlotFillProvider to the new context API #11123

Merged
merged 9 commits into from
Nov 2, 2018
36 changes: 19 additions & 17 deletions packages/components/src/popover/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
* External dependencies
*/
import classnames from 'classnames';
import { noop } from 'lodash';

/**
* WordPress dependencies
Expand All @@ -20,7 +19,7 @@ import withConstrainedTabbing from '../higher-order/with-constrained-tabbing';
import PopoverDetectOutside from './detect-outside';
import IconButton from '../icon-button';
import ScrollLock from '../scroll-lock';
import { Slot, Fill } from '../slot-fill';
import { Slot, Fill, Consumer } from '../slot-fill';

const FocusManaged = withConstrainedTabbing( withFocusReturn( ( { children } ) => children ) );

Expand Down Expand Up @@ -302,17 +301,24 @@ class Popover extends Component {
content = <FocusManaged>{ content }</FocusManaged>;
}

// In case there is no slot context in which to render, default to an
// in-place rendering.
const { getSlot } = this.context;
if ( getSlot && getSlot( SLOT_NAME ) ) {
content = <Fill name={ SLOT_NAME }>{ content }</Fill>;
}

return <span ref={ this.anchorNode }>
{ content }
{ isMobile && expandOnMobile && <ScrollLock /> }
</span>;
return (
<Consumer>
{ ( { getSlot } ) => {
// In case there is no slot context in which to render,
// default to an in-place rendering.
if ( getSlot && getSlot( SLOT_NAME ) ) {
content = <Fill name={ SLOT_NAME }>{ content }</Fill>;
}

return (
<span ref={ this.anchorNode }>
{ content }
{ isMobile && expandOnMobile && <ScrollLock /> }
</span>
);
} }
</Consumer>
);
}
}

Expand All @@ -323,10 +329,6 @@ Popover.defaultProps = {

const PopoverContainer = Popover;

PopoverContainer.contextTypes = {
getSlot: noop,
};

PopoverContainer.Slot = () => <Slot bubblesVirtually name={ SLOT_NAME } />;

export default PopoverContainer;
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
/**
* External dependencies
*/
import { pick, sortBy, forEach, without, noop } from 'lodash';
import { sortBy, forEach, without } from 'lodash';

/**
* WordPress dependencies
*/
import { Component } from '@wordpress/element';
import { Component, createContext } from '@wordpress/element';

const { Provider, Consumer } = createContext( {
registerSlot: () => {},
unregisterSlot: () => {},
registerFill: () => {},
unregisterFill: () => {},
getSlot: () => {},
getFills: () => {},
} );

class SlotFillProvider extends Component {
constructor() {
Expand All @@ -21,17 +30,14 @@ class SlotFillProvider extends Component {

this.slots = {};
this.fills = {};
}

getChildContext() {
return pick( this, [
'registerSlot',
'registerFill',
'unregisterSlot',
'unregisterFill',
'getSlot',
'getFills',
] );
this.state = {
registerSlot: this.registerSlot,
unregisterSlot: this.unregisterSlot,
registerFill: this.registerFill,
unregisterFill: this.unregisterFill,
getSlot: this.getSlot,
getFills: this.getFills,
};
}

registerSlot( name, slot ) {
Expand Down Expand Up @@ -94,17 +100,13 @@ class SlotFillProvider extends Component {
}

render() {
return this.props.children;
return (
<Provider value={ this.state }>
{ this.props.children }
</Provider>
);
}
}

SlotFillProvider.childContextTypes = {
registerSlot: noop,
unregisterSlot: noop,
registerFill: noop,
unregisterFill: noop,
getSlot: noop,
getFills: noop,
};

export default SlotFillProvider;
export { Consumer };
41 changes: 24 additions & 17 deletions packages/components/src/slot-fill/fill.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,28 @@
/**
* External dependencies
*/
import { noop, isFunction } from 'lodash';
import { isFunction } from 'lodash';

/**
* WordPress dependencies
*/
import { Component, createPortal } from '@wordpress/element';

/**
* Internal dependencies
*/
import { Consumer } from './context';

let occurrences = 0;

class Fill extends Component {
class FillComponent extends Component {
constructor() {
super( ...arguments );
this.occurrence = ++occurrences;
}

componentDidMount() {
const { registerFill = noop } = this.context;
const { registerFill } = this.props;

registerFill( this.props.name, this );
}
Expand All @@ -26,25 +31,21 @@ class Fill extends Component {
if ( ! this.occurrence ) {
this.occurrence = ++occurrences;
}
const { getSlot = noop } = this.context;
const { getSlot } = this.props;
const slot = getSlot( this.props.name );
if ( slot && ! slot.props.bubblesVirtually ) {
slot.forceUpdate();
}
}

componentWillUnmount() {
const { unregisterFill = noop } = this.context;
const { unregisterFill } = this.props;

unregisterFill( this.props.name, this );
}

componentDidUpdate( prevProps ) {
const { name } = this.props;
const {
unregisterFill = noop,
registerFill = noop,
} = this.context;
const { name, unregisterFill, registerFill } = this.props;

if ( prevProps.name !== name ) {
unregisterFill( prevProps.name, this );
Expand All @@ -57,8 +58,7 @@ class Fill extends Component {
}

render() {
const { getSlot = noop } = this.context;
const { name } = this.props;
const { name, getSlot } = this.props;
let { children } = this.props;
const slot = getSlot( name );

Expand All @@ -75,10 +75,17 @@ class Fill extends Component {
}
}

Fill.contextTypes = {
getSlot: noop,
registerFill: noop,
unregisterFill: noop,
};
const Fill = ( props ) => (
<Consumer>
{ ( { getSlot, registerFill, unregisterFill } ) => (
<FillComponent
{ ...props }
getSlot={ getSlot }
registerFill={ registerFill }
unregisterFill={ unregisterFill }
/>
) }
</Consumer>
);

export default Fill;
4 changes: 2 additions & 2 deletions packages/components/src/slot-fill/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
*/
import Slot from './slot';
import Fill from './fill';
import Provider from './provider';
import Provider, { Consumer } from './context';

export { Slot };
export { Fill };
export { Provider };
export { Provider, Consumer };
oandregal marked this conversation as resolved.
Show resolved Hide resolved

export function createSlotFill( name ) {
const FillComponent = ( props ) => <Fill name={ name } { ...props } />;
Expand Down
38 changes: 22 additions & 16 deletions packages/components/src/slot-fill/slot.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
isString,
map,
negate,
noop,
} from 'lodash';

/**
Expand All @@ -20,31 +19,32 @@ import {
isEmptyElement,
} from '@wordpress/element';

class Slot extends Component {
/**
* Internal dependencies
*/
import { Consumer } from './context';

class SlotComponent extends Component {
constructor() {
super( ...arguments );

this.bindNode = this.bindNode.bind( this );
}

componentDidMount() {
const { registerSlot = noop } = this.context;
const { registerSlot } = this.props;

registerSlot( this.props.name, this );
}

componentWillUnmount() {
const { unregisterSlot = noop } = this.context;
const { unregisterSlot } = this.props;

unregisterSlot( this.props.name, this );
}

componentDidUpdate( prevProps ) {
const { name } = this.props;
const {
unregisterSlot = noop,
registerSlot = noop,
} = this.context;
const { name, unregisterSlot, registerSlot } = this.props;

if ( prevProps.name !== name ) {
unregisterSlot( prevProps.name );
Expand All @@ -57,8 +57,7 @@ class Slot extends Component {
}

render() {
const { children, name, bubblesVirtually = false, fillProps = {} } = this.props;
const { getFills = noop } = this.context;
const { children, name, bubblesVirtually = false, fillProps = {}, getFills } = this.props;

if ( bubblesVirtually ) {
return <div ref={ this.bindNode } />;
Expand Down Expand Up @@ -91,10 +90,17 @@ class Slot extends Component {
}
}

Slot.contextTypes = {
registerSlot: noop,
unregisterSlot: noop,
getFills: noop,
};
const Slot = ( props ) => (
<Consumer>
{ ( { registerSlot, unregisterSlot, getFills } ) => (
<SlotComponent
{ ...props }
registerSlot={ registerSlot }
unregisterSlot={ unregisterSlot }
getFills={ getFills }
/>
) }
</Consumer>
);

export default Slot;
2 changes: 1 addition & 1 deletion packages/components/src/slot-fill/test/slot.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import ReactTestRenderer from 'react-test-renderer';
*/
import Slot from '../slot';
import Fill from '../fill';
import Provider from '../provider';
import Provider from '../context';

/**
* WordPress Dependencies
Expand Down