-
Notifications
You must be signed in to change notification settings - Fork 4.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
compose: Add types to createHigherOrderComponent and ifCondition
- Loading branch information
1 parent
0fa010e
commit 4b81b46
Showing
6 changed files
with
122 additions
and
66 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
/** | ||
* Internal dependencies | ||
*/ | ||
import createHigherOrderComponent from '../../utils/create-higher-order-component'; | ||
// eslint-disable-next-line no-duplicate-imports | ||
import type { HigherOrderComponent } from '../../utils/create-higher-order-component'; | ||
|
||
/** | ||
* Higher-order component creator, creating a new component which renders if | ||
* the given condition is satisfied or with the given optional prop name. | ||
* | ||
* @example | ||
* ```ts | ||
* type Props = { foo: string }; | ||
* const Component = ( props: Props ) => <div>{ props.foo }</div>; | ||
* const ConditionalComponent = ifCondition( ( props: Props ) => props.foo.length !== 0 )( Component ); | ||
* <ConditionalComponent foo="" />; // => null | ||
* <ConditionalComponent foo="bar" />; // => <div>bar</div>; | ||
* ``` | ||
* | ||
* @param predicate Function to test condition. | ||
* | ||
* @return Higher-order component. | ||
*/ | ||
const ifCondition = < TProps, >( | ||
predicate: ( props: TProps ) => boolean | ||
): HigherOrderComponent => | ||
createHigherOrderComponent< {}, TProps >( | ||
( WrappedComponent ) => ( props: TProps ) => { | ||
if ( ! predicate( props ) ) { | ||
return null; | ||
} | ||
|
||
return <WrappedComponent { ...props } />; | ||
}, | ||
'ifCondition' | ||
); | ||
|
||
export default ifCondition; |
36 changes: 0 additions & 36 deletions
36
packages/compose/src/utils/create-higher-order-component/index.js
This file was deleted.
Oops, something went wrong.
58 changes: 58 additions & 0 deletions
58
packages/compose/src/utils/create-higher-order-component/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import { camelCase, upperFirst } from 'lodash'; | ||
// eslint-disable-next-line no-restricted-imports | ||
import type { ComponentType } from 'react'; | ||
import type { Subtract } from 'utility-types'; | ||
|
||
/** | ||
* Higher order components can cause props to be obviated. For example a HOC that | ||
* injects i18n props will obviate the need for the i18n props to be passed to the component. | ||
* | ||
* If a HOC does not obviate the need for any specific props then we default to `{}` which | ||
* essentially subtracts 0 from the original props of the passed in component. An example | ||
* of this is the `pure` HOC which does not change the API surface of the component but | ||
* simply modifies the internals. | ||
*/ | ||
export interface HigherOrderComponent< TObviatedProps extends object = {} > { | ||
< TP extends TObviatedProps >( | ||
OriginalComponent: ComponentType< TP > | ||
): ComponentType< Subtract< TP, TObviatedProps > >; | ||
} | ||
|
||
/** | ||
* Given a function mapping a component to an enhanced component and modifier | ||
* name, returns the enhanced component augmented with a generated displayName. | ||
* | ||
* @param mapComponentToEnhancedComponent Function mapping component to enhanced component. | ||
* @param modifierName Seed name from which to generated display name. | ||
* | ||
* @return Component class with generated display name assigned. | ||
*/ | ||
function createHigherOrderComponent< | ||
TObviatedProps extends object, | ||
TProps extends TObviatedProps | ||
>( | ||
mapComponentToEnhancedComponent: ( | ||
OriginalComponent: ComponentType< TProps > | ||
) => ComponentType< Subtract< TProps, TObviatedProps > >, | ||
modifierName: string | ||
): HigherOrderComponent< TObviatedProps > { | ||
return ( ( OriginalComponent: ComponentType< TProps > ) => { | ||
const EnhancedComponent = mapComponentToEnhancedComponent( | ||
OriginalComponent | ||
); | ||
|
||
const { | ||
displayName = OriginalComponent.name || 'Component', | ||
} = OriginalComponent; | ||
|
||
EnhancedComponent.displayName = `${ upperFirst( | ||
camelCase( modifierName ) | ||
) }(${ displayName })`; | ||
|
||
return EnhancedComponent; | ||
} ) as HigherOrderComponent< TObviatedProps >; | ||
} | ||
export default createHigherOrderComponent; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{ | ||
"extends": "../../tsconfig.base.json", | ||
"compilerOptions": { | ||
"rootDir": "src", | ||
"declarationDir": "build-types" | ||
}, | ||
"include": [ | ||
"src/higher-order/if-condition/**/*", | ||
"src/utils/**/*" | ||
] | ||
} |