import * as React from "react"; import { action } from "mobx"; import { observer } from "mobx-react"; import { BoxedValue } from "boxm"; import { FormElementProps, removeProps, StyleComponent } from "./FormElementProps"; export interface SelectProps extends FormElementProps { value: BoxedValue; options: T[]; labels?: (value: T) => string; keys?: (value: T) => string; size?: number; selectComponent?: StyleComponent; optionComponent?: StyleComponent; } @observer export class TypedSelect extends React.Component, {}> { static defaultLabels(value: any) { return value + ""; } static defaultKeys(value: any) { if (value === undefined) { return "undefined"; } value = value.valueOf(); return JSON.stringify(value); } @action.bound updateValue(ev: React.FormEvent) { const keys = this.props.keys || TypedSelect.defaultKeys; // Find a value in the list that coerces to the new value for (const option of this.props.options) { if (keys(option) === ev.currentTarget.value) { this.props.value.set(option); return; } } } render() { const { selectComponent: SelectComponent = "select", optionComponent: OptionComponent = "option", } = this.props; const labels = this.props.labels || TypedSelect.defaultLabels; const keys = this.props.keys || TypedSelect.defaultKeys; var selectedValue = this.props.value.get(); var selectedKey = keys(selectedValue); let options = this.props.options.map(option => ({ key: keys(option), label: labels(option) })); if (!options.some(option => option.key === selectedKey)) { options = options.concat({ key: selectedKey, label: labels(selectedValue) }); } return ( { options.map(option => {option.label}) } ); } } export class Select extends TypedSelect {} export class SelectString extends TypedSelect {} export class SelectNumber extends TypedSelect {} export function SelectUsing( selectComponent: StyleComponent, optionComponent?: StyleComponent) { const S = class extends TypedSelect {}; return (props: SelectProps) => ( ); }