// Type definitions for core/kind

type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
type Merge<M, N> = Omit<M, Extract<keyof M, keyof N>> & N;

export interface RenderFunction {
  (props: { [key: string]: any }, context: { [key: string]: any }): any;
}
export interface ComputedPropFunction {
  (props: { [key: string]: any }, context: { [key: string]: any }): any;
}
export interface HandlerFunction {
  (
    event: any,
    props: { [key: string]: any },
    context: { [key: string]: any },
  ): void;
}
/**
 * Configuration for CSS class name mapping
 */
export interface StylesBlock {
  /**
   * The CSS of the component
   */
  css: { [key: string]: string } /**
   * The className of the component
   */;
  className?: string /**
 * Specifies which class names are overridable.
If this value is  `true` , all the class names of the component CSS will become public.
 */;
  publicClassNames?: boolean | string | string[];
}
export interface KindConfig {
  /**
   * The name of the component
   */
  name?: string /**
   * Boolean controlling whether the returned component should be a functional component
   */;
  functional?: boolean /**
   * Specifies expected props
   */;
  propTypes?: { [key: string]: Function } /**
   * Sets the default props
   */;
  defaultProps?: { [key: string]: any } /**
   * Specifies context type
   */;
  contextType?: object /**
   * Configures styles with the static className to merge with user className
   */;
  styles?: StylesBlock /**
 * Adds event handlers that are cached between calls to prevent recreating each call.
Any handlers are added to the props passed to  `render()` . See   .
 */;
  handlers?: { [key: string]: HandlerFunction } /**
   * Adds some computed properties, these are added to props passed to  `render()`
   */;
  computed?: { [key: string]: ComputedPropFunction } /**
   * The render function
   */;
  render: RenderFunction;
}
/**
 * Creates a new component with some helpful declarative syntactic sugar.
 * 
 * Example:
 * ```
import css from './Button.module.less';
const Button = kind({
	name: 'Button',
	// Return a functional component
	functional: true,
	// expect color and onClick properties but neither required
	propTypes: {
		color: PropTypes.string
	},
	// if no color is provided, it'll be green
	defaultProps: {
		color: 'green'
	},
	// expect backgroundColor via context
	contextType: React.createContext({ backgroundColor }),
	// configure styles with the static className to merge with user className
	styles: {
		// include the CSS modules map so 'button' can be resolved to the local name
		css,
		className: 'button'
	},
	// add event handlers that are cached between calls to prevent recreating each call. Any
	// handlers are added to the props passed to `render()`.  See core/handle.
	handlers: {
		onKeyDown: (evt, props) => { .... }
	},
	// add some computed properties, these are added to props passed to `render()`
	computed: {
		// border color will be the color prepended by 'light'
		borderColor: ({color}) => 'light' + color,
		// background color will be the contextual background color if specified
		color: ({color}, context) => context.backgroundColor || color
	},
	// Render the thing, already!
	render: ({color, borderColor, children, ...rest}) => (
		<button
			{...rest}
			style={{backgroundColor: color, borderColor}}
		>
			{children}
		</button>
	)
});
```
 */
export function kind<Props>(config: KindConfig): React.ComponentType<Props>;

export default kind;
