// Type definitions for ui/Toggleable

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 ToggleableConfig extends Object {
  /**
 * Configures the event name that activates the component.
 * 
 * Note : When using  `activate` / `deactivate` , the event payload will only forward the original
event and not include toggled  `prop`  value. Use  `toggle`  to receive toggled value from the
event payload.
 * 
 * Example:
 * ```
const ToggleItem = Toggleable({activate: 'onFocus', deactivate: 'onBlur'}, Item);

handleEvent = (ev) => {
	// do something with `ev.selected` here
}

<ToggleItem onToggle={handleEvent}>This is a toggle item</Item>
```
 */
  activate?: string;
  /**
 * Configures the event name that deactivates the component.
 * 
 * Note : When using  `activate` / `deactivate` , the event payload will only forward the original
event and not include toggled  `prop`  value. Use  `toggle`  to receive toggled value from the
event payload.
 * 
 * Example:
 * ```
const ToggleItem = Toggleable({activate: 'onFocus', deactivate: 'onBlur'}, Item);

handleEvent = (ev) => {
	// do something with `ev.selected` here
}

<ToggleItem onToggle={handleEvent}>This is a toggle item</Item>
```
 */
  deactivate?: string;
  /**
   * Configures additional props to attach to the event that is sent when toggled.
   */
  eventProps?: string[];
  /**
   * Configures the property that is passed to the wrapped component when toggled.
   */
  prop?: string;
  /**
 * Configures the event name that toggles the component.
 * 
 * The payload includes a toggled Boolean value of  `prop` .
 * 
 * Note : The payload will override the original event. If a native event is set, then the native
event payload will be lost.
 */
  toggle?: string;
  /**
 * Allows you to remap the incoming  `toggle`  callback to an event name of your choosing.
 * 
 * For example, run  `onToggle`  when the wrapped component has an  `onClick`  property and you've specified
 `onClick`  here.
 */
  toggleProp?: string;
}
export interface ToggleableProps {
  /**
 * Default toggled state applied at construction when the toggled prop is  `undefined`  or
 `null` .
 */
  defaultSelected?: boolean;
  /**
   * Whether or not the component is in a disabled state.
   */
  disabled?: boolean;
  /**
 * Current toggled state.
 * 
 * When set at construction, the component is considered 'controlled' and will only
update its internal value when updated by new props. If undefined, the component
is 'uncontrolled' and  `Toggleable`  will manage the toggled state using callbacks
defined by its configuration.
 */
  selected?: boolean;
  /**
   * Event callback to notify that state should be toggled.
   */
  onToggle?: Function;
}
export function Toggleable<P>(
  config: ToggleableConfig,
  Component: React.ComponentType<P> | string,
): React.ComponentType<P & ToggleableProps>;

export function Toggleable<P>(
  Component: React.ComponentType<P> | string,
): React.ComponentType<P & ToggleableProps>;

export default Toggleable;
