Skip to content

Instantly share code, notes, and snippets.

@nkt
Created October 26, 2016 17:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nkt/c0315e2a0b3bfdb5c82b002be5fe6a12 to your computer and use it in GitHub Desktop.
Save nkt/c0315e2a0b3bfdb5c82b002be5fe6a12 to your computer and use it in GitHub Desktop.
/**
* Copyright 2016 Dialog LLC <info@dlg.im>
* @flow
*/
import React, { Component } from 'react';
import Scroller from '../Scroller/Scroller';
import calculateCursor from '../../utils/calculateCursor';
import { KeyCodes } from './constants';
export type VariantProps<T> = {
variant: T,
hover: boolean,
onHover: (variant: T) => any,
onSelect: (variant: T) => any
};
export type Props<T> = {
className?: string,
looped: boolean,
variants: T[],
renderVariant: (props: VariantProps<T>) => React.Element<any>,
onSelect: (variant: T) => any,
onCancel: () => any
};
export type State = {
cursor: number
};
class Selector<T> extends Component<void, Props<T>, State> {
props: Props<T>;
state: State;
handleHover: Function;
handleKeyPress: Function;
handleCurrentChange: Function;
constructor(props: Props<T>): void {
super(props);
this.state = {
cursor: 0
};
this.handleHover = this.handleHover.bind(this);
this.handleKeyPress = this.handleKeyPress.bind(this);
this.handleCurrentChange = this.handleCurrentChange.bind(this);
}
handleHover(variant: T): void {
const cursor = this.props.variants.indexOf(variant);
if (cursor !== -1) {
this.setState({ cursor });
}
}
handleKeyPress(event: SyntheticKeyboardEvent): void {
switch (event.keyCode) {
case KeyCodes.ARROW_UP:
event.preventDefault();
this.handleCurrentChange(this.state.cursor + 1);
break;
case KeyCodes.ARROW_DOWN:
event.preventDefault();
this.handleCurrentChange(this.state.cursor - 1);
break;
case KeyCodes.ENTER: {
event.preventDefault();
const variant: ?T = this.props.variants[this.state.cursor];
if (variant) {
this.props.onSelect(variant);
}
break;
}
case KeyCodes.ESCAPE:
event.preventDefault();
this.props.onCancel();
break;
default:
// do nothing
break;
}
}
handleCurrentChange(next: number): void {
this.setState({
cursor: calculateCursor({
next,
max: this.props.variants.length - 1,
looped: this.props.looped
})
});
}
render(): React.Element<any> {
const children = this.props.variants.map((variant, index) => {
return this.props.renderVariant({
variant,
hover: index === this.state.cursor,
onHover: this.handleHover,
onSelect: this.props.onSelect
});
});
return (
<Scroller>
{children}
</Scroller>
)
}
}
export default Selector;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment