import React from 'react' import PropTypes from 'prop-types' import Button from '../Button' import SpecField from './SpecField' import NumberInput from '../inputs/NumberInput' import StringInput from '../inputs/StringInput' import SelectInput from '../inputs/SelectInput' import DocLabel from './DocLabel' import InputBlock from '../inputs/InputBlock' import labelFromFieldName from './_labelFromFieldName' import DeleteStopButton from './_DeleteStopButton' export default class DataProperty extends React.Component { static propTypes = { value: PropTypes.oneOfType([ PropTypes.object, PropTypes.string, PropTypes.number, PropTypes.bool, PropTypes.array ]), } getFieldFunctionType(fieldSpec) { if (fieldSpec.function === "interpolated") { return "exponential" } if (fieldSpec.type === "number") { return "interval" } return "categorical" } getDataFunctionTypes(functionType) { if (functionType === "interpolated") { return ["categorical", "interval", "exponential"] } else { return ["categorical", "interval"] } } changeStop(changeIdx, stopData, value) { const stops = this.props.value.stops.slice(0) stops[changeIdx] = [stopData, value] const changedValue = { ...this.props.value, stops: stops, } this.props.onChange(this.props.fieldName, changedValue) } changeDataProperty(propName, propVal) { if (propVal) { this.props.value[propName] = propVal } else { delete this.props.value[propName] } this.props.onChange(this.props.fieldName, this.props.value) } render() { if (typeof this.props.value.type === "undefined") { this.props.value.type = this.getFieldFunctionType(this.props.fieldSpec) } const dataFields = this.props.value.stops.map((stop, idx) => { const zoomLevel = stop[0].zoom const dataLevel = stop[0].value const value = stop[1] const deleteStopBtn = <DeleteStopButton onClick={this.props.onDeleteStop.bind(this, idx)} /> const dataProps = { label: "Data value", value: dataLevel, onChange: newData => this.changeStop(idx, { zoom: zoomLevel, value: newData }, value) } let dataInput; if(this.props.value.type === "categorical") { dataInput = <StringInput {...dataProps} /> } else { dataInput = <NumberInput {...dataProps} /> } return <InputBlock key={idx} action={deleteStopBtn} label=""> <div className="maputnik-data-spec-property-stop-edit"> <NumberInput value={zoomLevel} onChange={newZoom => this.changeStop(idx, {zoom: newZoom, value: dataLevel}, value)} min={0} max={22} /> </div> <div className="maputnik-data-spec-property-stop-data"> {dataInput} </div> <div className="maputnik-data-spec-property-stop-value"> <SpecField fieldName={this.props.fieldName} fieldSpec={this.props.fieldSpec} value={value} onChange={(_, newValue) => this.changeStop(idx, {zoom: zoomLevel, value: dataLevel}, newValue)} /> </div> </InputBlock> }) return <div className="maputnik-data-spec-block"> <div className="maputnik-data-spec-property"> <InputBlock doc={this.props.fieldSpec.doc} label={labelFromFieldName(this.props.fieldName)} > <div className="maputnik-data-spec-property-group"> <DocLabel label="Property" doc={"Input a data property to base styles off of."} /> <div className="maputnik-data-spec-property-input"> <StringInput value={this.props.value.property} onChange={propVal => this.changeDataProperty("property", propVal)} /> </div> </div> <div className="maputnik-data-spec-property-group"> <DocLabel label="Type" doc={"Select a type of data scale (default is 'categorical')."} /> <div className="maputnik-data-spec-property-input"> <SelectInput value={this.props.value.type} onChange={propVal => this.changeDataProperty("type", propVal)} options={this.getDataFunctionTypes(this.props.fieldSpec.function)} /> </div> </div> <div className="maputnik-data-spec-property-group"> <DocLabel label="Default" doc={"Input a default value for data if not covered by the scales."} /> <div className="maputnik-data-spec-property-input"> <SpecField fieldName={this.props.fieldName} fieldSpec={this.props.fieldSpec} value={this.props.value.default} onChange={(_, propVal) => this.changeDataProperty("default", propVal)} /> </div> </div> </InputBlock> </div> {dataFields} <Button className="maputnik-add-stop" onClick={this.props.onAddStop.bind(this)} > Add stop </Button> </div> } }