mirror of
https://github.com/a-nyx/maputnik-with-pmtiles.git
synced 2025-01-28 04:27:58 +01:00
Merge pull request #563 from orangemug/feature/more-root-property-support
Added support for more root level properties
This commit is contained in:
commit
c45cf2f0c8
7 changed files with 236 additions and 21 deletions
|
@ -59,7 +59,7 @@ export default class PropertyGroup extends React.Component {
|
|||
onChange={this.onPropertyChange}
|
||||
key={fieldName}
|
||||
fieldName={fieldName}
|
||||
value={fieldValue === undefined ? fieldSpec.default : fieldValue}
|
||||
value={fieldValue}
|
||||
fieldSpec={fieldSpec}
|
||||
/>
|
||||
})
|
||||
|
|
|
@ -12,29 +12,89 @@ class ArrayInput extends React.Component {
|
|||
onChange: PropTypes.func,
|
||||
}
|
||||
|
||||
changeValue(idx, newValue) {
|
||||
console.log(idx, newValue)
|
||||
const values = this.values.slice(0)
|
||||
values[idx] = newValue
|
||||
this.props.onChange(values)
|
||||
static defaultProps = {
|
||||
value: [],
|
||||
default: [],
|
||||
}
|
||||
|
||||
get values() {
|
||||
return this.props.value || this.props.default || []
|
||||
constructor (props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
value: this.props.value.slice(0),
|
||||
// This is so we can compare changes in getDerivedStateFromProps
|
||||
initialPropsValue: this.props.value.slice(0),
|
||||
};
|
||||
}
|
||||
|
||||
static getDerivedStateFromProps(props, state) {
|
||||
const value = [];
|
||||
const initialPropsValue = state.initialPropsValue.slice(0);
|
||||
|
||||
Array(props.length).fill(null).map((_, i) => {
|
||||
if (props.value[i] === state.initialPropsValue[i]) {
|
||||
value[i] = state.value[i];
|
||||
}
|
||||
else {
|
||||
value[i] = state.value[i];
|
||||
initialPropsValue[i] = state.value[i];
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
value,
|
||||
initialPropsValue,
|
||||
};
|
||||
}
|
||||
|
||||
isComplete (value) {
|
||||
return Array(this.props.length).fill(null).every((_, i) => {
|
||||
const val = value[i]
|
||||
return !(val === undefined || val === "");
|
||||
});
|
||||
}
|
||||
|
||||
changeValue(idx, newValue) {
|
||||
const value = this.state.value.slice(0);
|
||||
value[idx] = newValue;
|
||||
|
||||
this.setState({
|
||||
value,
|
||||
}, () => {
|
||||
if (this.isComplete(value)) {
|
||||
this.props.onChange(value);
|
||||
}
|
||||
else {
|
||||
// Unset until complete
|
||||
this.props.onChange(undefined);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const inputs = this.values.map((v, i) => {
|
||||
const {value} = this.state;
|
||||
|
||||
const containsValues = (
|
||||
value.length > 0 &&
|
||||
!value.every(val => {
|
||||
return (val === "" || val === undefined)
|
||||
})
|
||||
);
|
||||
|
||||
const inputs = Array(this.props.length).fill(null).map((_, i) => {
|
||||
if(this.props.type === 'number') {
|
||||
return <NumberInput
|
||||
key={i}
|
||||
value={v}
|
||||
default={containsValues ? undefined : this.props.default[i]}
|
||||
value={value[i]}
|
||||
required={containsValues ? true : false}
|
||||
onChange={this.changeValue.bind(this, i)}
|
||||
/>
|
||||
} else {
|
||||
return <StringInput
|
||||
key={i}
|
||||
value={v}
|
||||
default={containsValues ? undefined : this.props.default[i]}
|
||||
value={value[i]}
|
||||
required={containsValues ? true : false}
|
||||
onChange={this.changeValue.bind(this, i)}
|
||||
/>
|
||||
}
|
||||
|
|
|
@ -29,13 +29,13 @@ class EnumInput extends React.Component {
|
|||
if(options.length <= 3 && optionsLabelLength(options) <= 20) {
|
||||
return <MultiButtonInput
|
||||
options={options}
|
||||
value={value}
|
||||
value={value || this.props.default}
|
||||
onChange={onChange}
|
||||
/>
|
||||
} else {
|
||||
return <SelectInput
|
||||
options={options}
|
||||
value={value}
|
||||
value={value || this.props.default}
|
||||
onChange={onChange}
|
||||
/>
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ class NumberInput extends React.Component {
|
|||
min: PropTypes.number,
|
||||
max: PropTypes.number,
|
||||
onChange: PropTypes.func,
|
||||
required: PropTypes.bool,
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
|
@ -65,7 +66,7 @@ class NumberInput extends React.Component {
|
|||
this.setState({editing: false});
|
||||
// Reset explicitly to default value if value has been cleared
|
||||
if(this.state.value === "") {
|
||||
return this.changeValue(this.props.default)
|
||||
return;
|
||||
}
|
||||
|
||||
// If set value is invalid fall back to the last valid value from props or at last resort the default value
|
||||
|
@ -73,7 +74,7 @@ class NumberInput extends React.Component {
|
|||
if(this.isValid(this.props.value)) {
|
||||
this.changeValue(this.props.value)
|
||||
} else {
|
||||
this.changeValue(this.props.default)
|
||||
this.changeValue(undefined);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -83,9 +84,10 @@ class NumberInput extends React.Component {
|
|||
spellCheck="false"
|
||||
className="maputnik-number"
|
||||
placeholder={this.props.default}
|
||||
value={this.state.value || ""}
|
||||
value={this.state.value === undefined ? "" : this.state.value}
|
||||
onChange={e => this.changeValue(e.target.value)}
|
||||
onBlur={this.resetValue}
|
||||
required={this.props.required}
|
||||
/>
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ class StringInput extends React.Component {
|
|||
default: PropTypes.string,
|
||||
onChange: PropTypes.func,
|
||||
multi: PropTypes.bool,
|
||||
required: PropTypes.bool,
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
|
@ -50,7 +51,7 @@ class StringInput extends React.Component {
|
|||
spellCheck: !(tag === "input"),
|
||||
className: classes.join(" "),
|
||||
style: this.props.style,
|
||||
value: this.state.value,
|
||||
value: this.state.value === undefined ? "" : this.state.value,
|
||||
placeholder: this.props.default,
|
||||
onChange: e => {
|
||||
this.setState({
|
||||
|
@ -63,7 +64,8 @@ class StringInput extends React.Component {
|
|||
this.setState({editing: false});
|
||||
this.props.onChange(this.state.value);
|
||||
}
|
||||
}
|
||||
},
|
||||
required: this.props.required,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,8 +3,12 @@ import PropTypes from 'prop-types'
|
|||
|
||||
import {latest} from '@mapbox/mapbox-gl-style-spec'
|
||||
import InputBlock from '../inputs/InputBlock'
|
||||
import ArrayInput from '../inputs/ArrayInput'
|
||||
import NumberInput from '../inputs/NumberInput'
|
||||
import StringInput from '../inputs/StringInput'
|
||||
import SelectInput from '../inputs/SelectInput'
|
||||
import EnumInput from '../inputs/EnumInput'
|
||||
import ColorField from '../fields/ColorField'
|
||||
import Modal from './Modal'
|
||||
|
||||
class SettingsModal extends React.Component {
|
||||
|
@ -16,18 +20,64 @@ class SettingsModal extends React.Component {
|
|||
onOpenToggle: PropTypes.func.isRequired,
|
||||
}
|
||||
|
||||
changeTransitionProperty(property, value) {
|
||||
const transition = {
|
||||
...this.props.mapStyle.transition,
|
||||
}
|
||||
|
||||
if (value === undefined) {
|
||||
delete transition[property];
|
||||
}
|
||||
else {
|
||||
transition[property] = value;
|
||||
}
|
||||
|
||||
this.props.onStyleChanged({
|
||||
...this.props.mapStyle,
|
||||
transition,
|
||||
});
|
||||
}
|
||||
|
||||
changeLightProperty(property, value) {
|
||||
const light = {
|
||||
...this.props.mapStyle.light,
|
||||
}
|
||||
|
||||
if (value === undefined) {
|
||||
delete light[property];
|
||||
}
|
||||
else {
|
||||
light[property] = value;
|
||||
}
|
||||
|
||||
this.props.onStyleChanged({
|
||||
...this.props.mapStyle,
|
||||
light,
|
||||
});
|
||||
}
|
||||
|
||||
changeStyleProperty(property, value) {
|
||||
const changedStyle = {
|
||||
...this.props.mapStyle,
|
||||
[property]: value
|
||||
};
|
||||
|
||||
if (value === undefined) {
|
||||
delete changedStyle[property];
|
||||
}
|
||||
this.props.onStyleChanged(changedStyle)
|
||||
else {
|
||||
changedStyle[property] = value;
|
||||
}
|
||||
this.props.onStyleChanged(changedStyle);
|
||||
}
|
||||
|
||||
render() {
|
||||
const metadata = this.props.mapStyle.metadata || {}
|
||||
const {onChangeMetadataProperty} = this.props;
|
||||
const {onChangeMetadataProperty, mapStyle} = this.props;
|
||||
const inputProps = { }
|
||||
|
||||
const light = this.props.mapStyle.light || {};
|
||||
const transition = this.props.mapStyle.transition || {};
|
||||
|
||||
return <Modal
|
||||
data-wd-key="modal-settings"
|
||||
isOpen={this.props.isOpen}
|
||||
|
@ -89,6 +139,100 @@ class SettingsModal extends React.Component {
|
|||
/>
|
||||
</InputBlock>
|
||||
|
||||
<InputBlock label={"Center"} doc={latest.$root.center.doc}>
|
||||
<ArrayInput
|
||||
length={2}
|
||||
type="number"
|
||||
value={mapStyle.center}
|
||||
default={latest.$root.center.default || [0, 0]}
|
||||
onChange={this.changeStyleProperty.bind(this, "center")}
|
||||
/>
|
||||
</InputBlock>
|
||||
|
||||
<InputBlock label={"Zoom"} doc={latest.$root.zoom.doc}>
|
||||
<NumberInput
|
||||
{...inputProps}
|
||||
value={mapStyle.zoom}
|
||||
default={latest.$root.zoom.default || 0}
|
||||
onChange={this.changeStyleProperty.bind(this, "zoom")}
|
||||
/>
|
||||
</InputBlock>
|
||||
|
||||
<InputBlock label={"Bearing"} doc={latest.$root.bearing.doc}>
|
||||
<NumberInput
|
||||
{...inputProps}
|
||||
value={mapStyle.bearing}
|
||||
default={latest.$root.bearing.default}
|
||||
onChange={this.changeStyleProperty.bind(this, "bearing")}
|
||||
/>
|
||||
</InputBlock>
|
||||
|
||||
<InputBlock label={"Pitch"} doc={latest.$root.pitch.doc}>
|
||||
<NumberInput
|
||||
{...inputProps}
|
||||
value={mapStyle.pitch}
|
||||
default={latest.$root.pitch.default}
|
||||
onChange={this.changeStyleProperty.bind(this, "pitch")}
|
||||
/>
|
||||
</InputBlock>
|
||||
|
||||
<InputBlock label={"Light anchor"} doc={latest.light.anchor.doc}>
|
||||
<EnumInput
|
||||
{...inputProps}
|
||||
value={light.anchor}
|
||||
options={Object.keys(latest.light.anchor.values)}
|
||||
default={latest.light.anchor.default}
|
||||
onChange={this.changeLightProperty.bind(this, "anchor")}
|
||||
/>
|
||||
</InputBlock>
|
||||
|
||||
<InputBlock label={"Light color"} doc={latest.light.color.doc}>
|
||||
<ColorField
|
||||
{...inputProps}
|
||||
value={light.color}
|
||||
default={latest.light.color.default}
|
||||
onChange={this.changeLightProperty.bind(this, "color")}
|
||||
/>
|
||||
</InputBlock>
|
||||
|
||||
<InputBlock label={"Light intensity"} doc={latest.light.intensity.doc}>
|
||||
<NumberInput
|
||||
{...inputProps}
|
||||
value={light.intensity}
|
||||
default={latest.light.intensity.default}
|
||||
onChange={this.changeLightProperty.bind(this, "intensity")}
|
||||
/>
|
||||
</InputBlock>
|
||||
|
||||
<InputBlock label={"Light position"} doc={latest.light.position.doc}>
|
||||
<ArrayInput
|
||||
{...inputProps}
|
||||
type="number"
|
||||
length={latest.light.position.length}
|
||||
value={light.position}
|
||||
default={latest.light.position.default}
|
||||
onChange={this.changeLightProperty.bind(this, "position")}
|
||||
/>
|
||||
</InputBlock>
|
||||
|
||||
<InputBlock label={"Transition delay"} doc={latest.transition.delay.doc}>
|
||||
<NumberInput
|
||||
{...inputProps}
|
||||
value={transition.delay}
|
||||
default={latest.transition.delay.default}
|
||||
onChange={this.changeTransitionProperty.bind(this, "delay")}
|
||||
/>
|
||||
</InputBlock>
|
||||
|
||||
<InputBlock label={"Transition duration"} doc={latest.transition.duration.doc}>
|
||||
<NumberInput
|
||||
{...inputProps}
|
||||
value={transition.duration}
|
||||
default={latest.transition.duration.default}
|
||||
onChange={this.changeTransitionProperty.bind(this, "duration")}
|
||||
/>
|
||||
</InputBlock>
|
||||
|
||||
<InputBlock label={"Style Renderer"} doc={"Choose the default Maputnik renderer for this style."}>
|
||||
<SelectInput {...inputProps}
|
||||
data-wd-key="modal-settings.maputnik:renderer"
|
||||
|
@ -101,6 +245,8 @@ class SettingsModal extends React.Component {
|
|||
/>
|
||||
</InputBlock>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</Modal>
|
||||
}
|
||||
|
|
|
@ -11,6 +11,11 @@
|
|||
border: none;
|
||||
background-color: $color-gray;
|
||||
color: lighten($color-lowgray, 12);
|
||||
|
||||
&:invalid {
|
||||
border: solid 1px #B71C1C;
|
||||
border-radius: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.maputnik-string {
|
||||
|
|
Loading…
Reference in a new issue