SHARE
TWEET

Untitled

a guest Aug 20th, 2019 74 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // @flow
  2.  
  3. import * as React from 'react';
  4. import classNames from 'classnames';
  5. // import type { ClassNames } from 'classnames';
  6.  
  7. type ClassNames = any;
  8.  
  9. export type ClassNamesOrFunction = ClassNames | ((props: any) => ClassNames);
  10.  
  11. type MinimalProps = {
  12.   +className?: ClassNames,
  13.   +children?: any
  14. };
  15.  
  16. type MinimalAdditionalProps = {
  17.   +className?: ClassNamesOrFunction
  18. };
  19.  
  20. /**
  21.  * Wraps a component and provides some useful behaviour:
  22.  *  - it can have default props
  23.  *  - it merges default classes with classes provided later (className prop)
  24.  *  - it forwards ref
  25.  */
  26. export function wrapComponent<
  27.   Props: MinimalProps,
  28.   AdditionalProps: MinimalAdditionalProps,
  29.   Instance
  30. >(
  31.   Component: React.AbstractComponent<Props, Instance>,
  32.   { className: componentClasses, ...defaultProps }: AdditionalProps = {}
  33. ): React.AbstractComponent<$Diff<Props, AdditionalProps>, Instance> {
  34.   return React.forwardRef(({ className, children, ...props }, ref) => {
  35.     const classes = getClasses(componentClasses, className, props);
  36.  
  37.     return (
  38.       <Component className={classes} {...defaultProps} {...props} ref={ref}>
  39.         {children}
  40.       </Component>
  41.     );
  42.   });
  43. }
  44.  
  45. function getClasses(
  46.   componentClasses: ClassNamesOrFunction,
  47.   className: ClassNames,
  48.   props: any
  49. ): string {
  50.   const cls =
  51.     typeof componentClasses === 'function'
  52.       ? componentClasses(props)
  53.       : componentClasses;
  54.  
  55.   return classNames(cls, className);
  56. }
  57.  
  58. type XProps = {|
  59.   +className: ClassNames,
  60.   +children?: any,
  61.   +a: string,
  62.   +b: string
  63. |};
  64.  
  65. const X = ({ a, b }: XProps) => <div>{a + b}</div>;
  66.  
  67. type DProps = {|
  68.   +className: string,
  69.   +a: string
  70. |};
  71.  
  72. const Y = wrapComponent<XProps, DProps, mixed>(X, {
  73.   className: 'foo',
  74.   a: 'foo'
  75. });
  76.  
  77. const t = () => (
  78.   <>
  79.     <Y className="foo" />
  80.     <Y b="foo" />
  81.     <X className="foo" />
  82.     <X a="foo" b="foo" className="foo" />
  83.   </>
  84. );
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top