Advertisement
Guest User

Untitled

a guest
Aug 20th, 2019
98
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 1.83 KB | None | 0 0
  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. );
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement