Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // @flow
- import * as React from 'react';
- import classNames from 'classnames';
- // import type { ClassNames } from 'classnames';
- type ClassNames = any;
- export type ClassNamesOrFunction = ClassNames | ((props: any) => ClassNames);
- type MinimalProps = {
- +className?: ClassNames,
- +children?: any
- };
- type MinimalAdditionalProps = {
- +className?: ClassNamesOrFunction
- };
- /**
- * Wraps a component and provides some useful behaviour:
- * - it can have default props
- * - it merges default classes with classes provided later (className prop)
- * - it forwards ref
- */
- export function wrapComponent<
- Props: MinimalProps,
- AdditionalProps: MinimalAdditionalProps,
- Instance
- >(
- Component: React.AbstractComponent<Props, Instance>,
- { className: componentClasses, ...defaultProps }: AdditionalProps = {}
- ): React.AbstractComponent<$Diff<Props, AdditionalProps>, Instance> {
- return React.forwardRef(({ className, children, ...props }, ref) => {
- const classes = getClasses(componentClasses, className, props);
- return (
- <Component className={classes} {...defaultProps} {...props} ref={ref}>
- {children}
- </Component>
- );
- });
- }
- function getClasses(
- componentClasses: ClassNamesOrFunction,
- className: ClassNames,
- props: any
- ): string {
- const cls =
- typeof componentClasses === 'function'
- ? componentClasses(props)
- : componentClasses;
- return classNames(cls, className);
- }
- type XProps = {|
- +className: ClassNames,
- +children?: any,
- +a: string,
- +b: string
- |};
- const X = ({ a, b }: XProps) => <div>{a + b}</div>;
- type DProps = {|
- +className: string,
- +a: string
- |};
- const Y = wrapComponent<XProps, DProps, mixed>(X, {
- className: 'foo',
- a: 'foo'
- });
- const t = () => (
- <>
- <Y className="foo" />
- <Y b="foo" />
- <X className="foo" />
- <X a="foo" b="foo" className="foo" />
- </>
- );
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement