2016-09-12 19:44:28 +02:00
|
|
|
import React from 'react'
|
2017-11-06 16:32:04 +01:00
|
|
|
import PropTypes from 'prop-types'
|
2016-12-17 17:40:44 +01:00
|
|
|
|
2016-12-20 11:44:22 +01:00
|
|
|
import ColorField from './ColorField'
|
2016-12-26 11:48:52 +01:00
|
|
|
import NumberInput from '../inputs/NumberInput'
|
|
|
|
import CheckboxInput from '../inputs/CheckboxInput'
|
|
|
|
import StringInput from '../inputs/StringInput'
|
|
|
|
import SelectInput from '../inputs/SelectInput'
|
2016-12-28 16:48:49 +01:00
|
|
|
import MultiButtonInput from '../inputs/MultiButtonInput'
|
2016-12-29 22:37:54 +01:00
|
|
|
import ArrayInput from '../inputs/ArrayInput'
|
2017-05-25 22:00:34 +02:00
|
|
|
import DynamicArrayInput from '../inputs/DynamicArrayInput'
|
2016-12-30 18:13:41 +01:00
|
|
|
import FontInput from '../inputs/FontInput'
|
2017-01-10 11:13:53 +01:00
|
|
|
import IconInput from '../inputs/IconInput'
|
2016-12-28 16:48:49 +01:00
|
|
|
import capitalize from 'lodash.capitalize'
|
|
|
|
|
2017-01-10 11:13:53 +01:00
|
|
|
const iconProperties = ['background-pattern', 'fill-pattern', 'line-pattern', 'fill-extrusion-pattern', 'icon-image']
|
2016-12-20 11:44:22 +01:00
|
|
|
|
2016-12-17 20:36:43 +01:00
|
|
|
function labelFromFieldName(fieldName) {
|
|
|
|
let label = fieldName.split('-').slice(1).join(' ')
|
|
|
|
if(label.length > 0) {
|
|
|
|
label = label.charAt(0).toUpperCase() + label.slice(1);
|
|
|
|
}
|
|
|
|
return label
|
|
|
|
}
|
|
|
|
|
2016-12-29 22:12:36 +01:00
|
|
|
function optionsLabelLength(options) {
|
|
|
|
let sum = 0;
|
|
|
|
options.forEach(([_, label]) => {
|
|
|
|
sum += label.length
|
|
|
|
})
|
|
|
|
return sum
|
|
|
|
}
|
|
|
|
|
2016-12-17 17:40:44 +01:00
|
|
|
/** Display any field from the Mapbox GL style spec and
|
|
|
|
* choose the correct field component based on the @{fieldSpec}
|
|
|
|
* to display @{value}. */
|
2016-12-20 11:44:22 +01:00
|
|
|
export default class SpecField extends React.Component {
|
2016-12-17 17:40:44 +01:00
|
|
|
static propTypes = {
|
2017-11-06 16:32:04 +01:00
|
|
|
onChange: PropTypes.func.isRequired,
|
|
|
|
fieldName: PropTypes.string.isRequired,
|
|
|
|
fieldSpec: PropTypes.object.isRequired,
|
|
|
|
value: PropTypes.oneOfType([
|
|
|
|
PropTypes.string,
|
|
|
|
PropTypes.number,
|
|
|
|
PropTypes.array,
|
|
|
|
PropTypes.bool
|
2016-12-17 17:40:44 +01:00
|
|
|
]),
|
2016-12-19 16:21:22 +01:00
|
|
|
/** Override the style of the field */
|
2017-11-06 16:32:04 +01:00
|
|
|
style: PropTypes.object,
|
2016-12-17 17:40:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
render() {
|
2016-12-20 14:13:37 +01:00
|
|
|
const commonProps = {
|
|
|
|
style: this.props.style,
|
|
|
|
value: this.props.value,
|
2017-01-10 09:51:18 +01:00
|
|
|
default: this.props.fieldSpec.default,
|
2016-12-20 14:13:37 +01:00
|
|
|
name: this.props.fieldName,
|
|
|
|
onChange: newValue => this.props.onChange(this.props.fieldName, newValue)
|
|
|
|
}
|
2016-12-29 22:12:36 +01:00
|
|
|
|
2018-01-05 18:45:55 +01:00
|
|
|
function childNodes() {
|
|
|
|
switch(this.props.fieldSpec.type) {
|
|
|
|
case 'number': return (
|
|
|
|
<NumberInput
|
2016-12-28 16:48:49 +01:00
|
|
|
{...commonProps}
|
2018-01-05 18:45:55 +01:00
|
|
|
min={this.props.fieldSpec.minimum}
|
|
|
|
max={this.props.fieldSpec.maximum}
|
2016-12-28 16:48:49 +01:00
|
|
|
/>
|
2018-01-05 18:45:55 +01:00
|
|
|
)
|
|
|
|
case 'enum':
|
|
|
|
const options = Object.keys(this.props.fieldSpec.values).map(v => [v, capitalize(v)])
|
|
|
|
|
|
|
|
if(options.length <= 3 && optionsLabelLength(options) <= 20) {
|
|
|
|
return <MultiButtonInput
|
|
|
|
{...commonProps}
|
|
|
|
options={options}
|
|
|
|
/>
|
|
|
|
} else {
|
|
|
|
return <SelectInput
|
|
|
|
{...commonProps}
|
|
|
|
options={options}
|
|
|
|
/>
|
|
|
|
}
|
2019-01-05 22:38:58 +01:00
|
|
|
case 'formatted':
|
2018-01-05 18:45:55 +01:00
|
|
|
case 'string':
|
|
|
|
if(iconProperties.indexOf(this.props.fieldName) >= 0) {
|
|
|
|
return <IconInput
|
|
|
|
{...commonProps}
|
|
|
|
icons={this.props.fieldSpec.values}
|
|
|
|
/>
|
|
|
|
} else {
|
|
|
|
return <StringInput
|
|
|
|
{...commonProps}
|
|
|
|
/>
|
|
|
|
}
|
|
|
|
case 'color': return (
|
|
|
|
<ColorField
|
2017-01-10 11:13:53 +01:00
|
|
|
{...commonProps}
|
|
|
|
/>
|
2018-01-05 18:45:55 +01:00
|
|
|
)
|
|
|
|
case 'boolean': return (
|
|
|
|
<CheckboxInput
|
2016-12-30 18:13:41 +01:00
|
|
|
{...commonProps}
|
|
|
|
/>
|
2018-01-05 18:45:55 +01:00
|
|
|
)
|
|
|
|
case 'array':
|
|
|
|
if(this.props.fieldName === 'text-font') {
|
|
|
|
return <FontInput
|
2017-05-25 22:00:34 +02:00
|
|
|
{...commonProps}
|
2018-01-05 18:45:55 +01:00
|
|
|
fonts={this.props.fieldSpec.values}
|
2017-05-25 22:00:34 +02:00
|
|
|
/>
|
|
|
|
} else {
|
2018-01-05 18:45:55 +01:00
|
|
|
if (this.props.fieldSpec.length) {
|
|
|
|
return <ArrayInput
|
|
|
|
{...commonProps}
|
|
|
|
type={this.props.fieldSpec.value}
|
|
|
|
length={this.props.fieldSpec.length}
|
|
|
|
/>
|
|
|
|
} else {
|
|
|
|
return <DynamicArrayInput
|
|
|
|
{...commonProps}
|
|
|
|
type={this.props.fieldSpec.value}
|
|
|
|
/>
|
|
|
|
}
|
2017-05-25 22:00:34 +02:00
|
|
|
}
|
2018-01-05 18:45:55 +01:00
|
|
|
default: return null
|
|
|
|
}
|
2016-12-17 17:40:44 +01:00
|
|
|
}
|
2018-01-05 18:45:55 +01:00
|
|
|
|
|
|
|
return (
|
|
|
|
<div data-wd-key={"spec-field:"+this.props.fieldName}>
|
|
|
|
{childNodes.call(this)}
|
|
|
|
</div>
|
|
|
|
);
|
2016-12-17 17:40:44 +01:00
|
|
|
}
|
2016-09-12 19:44:28 +02:00
|
|
|
}
|