diff --git a/src/components/fields/PropertyGroup.jsx b/src/components/fields/PropertyGroup.jsx
index efb567b..3557724 100644
--- a/src/components/fields/PropertyGroup.jsx
+++ b/src/components/fields/PropertyGroup.jsx
@@ -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}
/>
})
diff --git a/src/components/inputs/ArrayInput.jsx b/src/components/inputs/ArrayInput.jsx
index 69a01d5..bb406d8 100644
--- a/src/components/inputs/ArrayInput.jsx
+++ b/src/components/inputs/ArrayInput.jsx
@@ -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
} else {
return
}
diff --git a/src/components/inputs/EnumInput.jsx b/src/components/inputs/EnumInput.jsx
index e704110..9472a2f 100644
--- a/src/components/inputs/EnumInput.jsx
+++ b/src/components/inputs/EnumInput.jsx
@@ -29,13 +29,13 @@ class EnumInput extends React.Component {
if(options.length <= 3 && optionsLabelLength(options) <= 20) {
return
} else {
return
}
diff --git a/src/components/inputs/NumberInput.jsx b/src/components/inputs/NumberInput.jsx
index 0de1fa4..b2d7dec 100644
--- a/src/components/inputs/NumberInput.jsx
+++ b/src/components/inputs/NumberInput.jsx
@@ -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}
/>
}
}
diff --git a/src/components/inputs/StringInput.jsx b/src/components/inputs/StringInput.jsx
index 875a454..e160d69 100644
--- a/src/components/inputs/StringInput.jsx
+++ b/src/components/inputs/StringInput.jsx
@@ -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,
});
}
}
diff --git a/src/components/modals/SettingsModal.jsx b/src/components/modals/SettingsModal.jsx
index 04ca51d..de4ced5 100644
--- a/src/components/modals/SettingsModal.jsx
+++ b/src/components/modals/SettingsModal.jsx
@@ -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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
}
diff --git a/src/styles/_input.scss b/src/styles/_input.scss
index 90e84ed..7caaa77 100644
--- a/src/styles/_input.scss
+++ b/src/styles/_input.scss
@@ -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 {