11/**
22 * External dependencies
33 */
4- import { sortBy , forEach , without } from 'lodash' ;
4+ import { sortBy , forEach , without , some } from 'lodash' ;
55
66/**
77 * WordPress dependencies
88 */
99import { Component , createContext } from '@wordpress/element' ;
10+ import { createHigherOrderComponent } from '@wordpress/compose' ;
1011
1112const { Provider, Consumer } = createContext ( {
1213 registerSlot : ( ) => { } ,
@@ -21,22 +22,49 @@ class SlotFillProvider extends Component {
2122 constructor ( ) {
2223 super ( ...arguments ) ;
2324
24- this . registerSlot = this . registerSlot . bind ( this ) ;
25- this . registerFill = this . registerFill . bind ( this ) ;
26- this . unregisterSlot = this . unregisterSlot . bind ( this ) ;
27- this . unregisterFill = this . unregisterFill . bind ( this ) ;
28- this . getSlot = this . getSlot . bind ( this ) ;
29- this . getFills = this . getFills . bind ( this ) ;
30-
3125 this . slots = { } ;
3226 this . fills = { } ;
3327 this . state = {
34- registerSlot : this . registerSlot ,
35- unregisterSlot : this . unregisterSlot ,
36- registerFill : this . registerFill ,
37- unregisterFill : this . unregisterFill ,
38- getSlot : this . getSlot ,
39- getFills : this . getFills ,
28+ registerSlot : this . proxy ( 'registerSlot' ) . bind ( this ) ,
29+ registerFill : this . proxy ( 'registerFill' ) . bind ( this ) ,
30+ unregisterSlot : this . proxy ( 'unregisterSlot' ) . bind ( this ) ,
31+ unregisterFill : this . proxy ( 'unregisterFill' ) . bind ( this ) ,
32+ getSlot : this . proxy ( 'getSlot' ) . bind ( this ) ,
33+ getFills : this . proxy ( 'getFills' ) . bind ( this ) ,
34+ } ;
35+ }
36+
37+ /**
38+ * Given a function name for a function on the SlotFillProvider prototype,
39+ * returns a new function which either passes the arguments to the current
40+ * instance, or to the context ancestor, dependent on whether the provider
41+ * is configured to handle the given slot.
42+ *
43+ * @param {string } functionName SlotFillProvider function name.
44+ *
45+ * @return {Function } Proxying function.
46+ */
47+ proxy ( functionName ) {
48+ return ( name , ...args ) => {
49+ const { slots : handledSlots } = this . props ;
50+
51+ let handler = this [ functionName ] ;
52+
53+ if ( Array . isArray ( handledSlots ) ) {
54+ const isHandled = some ( handledSlots , ( slotNameOrComponent ) => {
55+ const { slotName = slotNameOrComponent } = slotNameOrComponent ;
56+ return typeof slotName === 'string' && (
57+ slotName === name ||
58+ name . startsWith ( slotName + '.' )
59+ ) ;
60+ } ) ;
61+
62+ if ( ! isHandled ) {
63+ handler = this . props [ functionName ] ;
64+ }
65+ }
66+
67+ return handler . call ( this , name , ...args ) ;
4068 } ;
4169 }
4270
@@ -129,5 +157,25 @@ class SlotFillProvider extends Component {
129157 }
130158}
131159
132- export default SlotFillProvider ;
133- export { Consumer } ;
160+ const withConsumerContext = createHigherOrderComponent (
161+ ( WrappedComponent ) => ( props ) => (
162+ < Consumer >
163+ { ( context ) => (
164+ < WrappedComponent
165+ { ...props }
166+ registerSlot = { context . registerSlot }
167+ unregisterSlot = { context . unregisterSlot }
168+ registerFill = { context . registerFill }
169+ unregisterFill = { context . unregisterFill }
170+ getSlot = { context . getSlot }
171+ getFills = { context . getFills }
172+ />
173+ ) }
174+ </ Consumer >
175+ ) ,
176+ 'withConsumerContext'
177+ ) ;
178+
179+ export default withConsumerContext ( SlotFillProvider ) ;
180+
181+ export { Consumer , withConsumerContext } ;
0 commit comments