+ onClick={this.onLabelClick}
+ >
{this.props.fieldSpec &&
-
+
this._blockEl = el}>
{this.props.children}
- {errors.length > 0 &&
-
- {[].concat(this.props.error).map((error, idx) => {
- return
{error.message}
- })}
+ {this.props.fieldSpec &&
+
+
}
- {this.props.fieldSpec &&
-
-
-
- }
-
+
}
}
diff --git a/src/components/FieldArray.jsx b/src/components/FieldArray.jsx
index 7c78961..00103fc 100644
--- a/src/components/FieldArray.jsx
+++ b/src/components/FieldArray.jsx
@@ -1,108 +1,21 @@
import React from 'react'
import PropTypes from 'prop-types'
-import FieldString from './FieldString'
-import FieldNumber from './FieldNumber'
+import Block from './Block'
+import InputArray from './InputArray'
+import Fieldset from './Fieldset'
export default class FieldArray extends React.Component {
static propTypes = {
- value: PropTypes.array,
- type: PropTypes.string,
- length: PropTypes.number,
- default: PropTypes.array,
- onChange: PropTypes.func,
- }
-
- static defaultProps = {
- value: [],
- 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);
- }
- });
+ ...InputArray.propTypes,
+ name: PropTypes.string,
}
render() {
- const {value} = this.state;
+ const {props} = this;
- 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
- }
- })
-
- return
- {inputs}
-
+ return
+
+
}
}
diff --git a/src/components/FieldAutocomplete.jsx b/src/components/FieldAutocomplete.jsx
index 47c4864..da63105 100644
--- a/src/components/FieldAutocomplete.jsx
+++ b/src/components/FieldAutocomplete.jsx
@@ -1,97 +1,20 @@
import React from 'react'
import PropTypes from 'prop-types'
-import classnames from 'classnames'
-import Autocomplete from 'react-autocomplete'
+import Block from './Block'
+import InputAutocomplete from './InputAutocomplete'
-const MAX_HEIGHT = 140;
-
export default class FieldAutocomplete extends React.Component {
static propTypes = {
- value: PropTypes.string,
- options: PropTypes.array,
- onChange: PropTypes.func,
- keepMenuWithinWindowBounds: PropTypes.bool
- }
-
- state = {
- maxHeight: MAX_HEIGHT
- }
-
- static defaultProps = {
- onChange: () => {},
- options: [],
- }
-
- calcMaxHeight() {
- if(this.props.keepMenuWithinWindowBounds) {
- const maxHeight = window.innerHeight - this.autocompleteMenuEl.getBoundingClientRect().top;
- const limitedMaxHeight = Math.min(maxHeight, MAX_HEIGHT);
-
- if(limitedMaxHeight != this.state.maxHeight) {
- this.setState({
- maxHeight: limitedMaxHeight
- })
- }
- }
- }
-
- componentDidMount() {
- this.calcMaxHeight();
- }
-
- componentDidUpdate() {
- this.calcMaxHeight();
- }
-
- onChange (v) {
- this.props.onChange(v === "" ? undefined : v);
+ ...InputAutocomplete.propTypes,
}
render() {
- return
{
- this.autocompleteMenuEl = el;
- }}
- >
-
item[0]}
- onSelect={v => this.onChange(v)}
- onChange={(e, v) => this.onChange(v)}
- shouldItemRender={(item, value="") => {
- if (typeof(value) === "string") {
- return item[0].toLowerCase().indexOf(value.toLowerCase()) > -1
- }
- }}
- renderItem={(item, isHighlighted) => (
-
- {item[1]}
-
- )}
- />
-
+ const {props} = this;
+
+ return
+
+
}
}
diff --git a/src/components/FieldCheckbox.jsx b/src/components/FieldCheckbox.jsx
index 066f3c8..7cdc08b 100644
--- a/src/components/FieldCheckbox.jsx
+++ b/src/components/FieldCheckbox.jsx
@@ -1,34 +1,20 @@
import React from 'react'
import PropTypes from 'prop-types'
+import Block from './Block'
+import InputCheckbox from './InputCheckbox'
+
export default class FieldCheckbox extends React.Component {
static propTypes = {
- value: PropTypes.bool,
- style: PropTypes.object,
- onChange: PropTypes.func,
- }
-
- static defaultProps = {
- value: false,
+ ...InputCheckbox.propTypes,
}
render() {
- return
- this.props.onChange(!this.props.value)}
- checked={this.props.value}
- />
-
-
+ const {props} = this;
+
+ return
+
+
}
}
diff --git a/src/components/FieldColor.jsx b/src/components/FieldColor.jsx
index 1f73b4e..2e9067b 100644
--- a/src/components/FieldColor.jsx
+++ b/src/components/FieldColor.jsx
@@ -1,132 +1,20 @@
import React from 'react'
-import Color from 'color'
-import ChromePicker from 'react-color/lib/components/chrome/Chrome'
import PropTypes from 'prop-types'
-import lodash from 'lodash';
+import Block from './Block'
+import InputColor from './InputColor'
-function formatColor(color) {
- const rgb = color.rgb
- return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${rgb.a})`
-}
-/*** Number fields with support for min, max and units and documentation*/
export default class FieldColor extends React.Component {
static propTypes = {
- onChange: PropTypes.func.isRequired,
- name: PropTypes.string,
- value: PropTypes.string,
- doc: PropTypes.string,
- style: PropTypes.object,
- default: PropTypes.string,
- }
-
- state = {
- pickerOpened: false
- }
-
- constructor () {
- super();
- this.onChangeNoCheck = lodash.throttle(this.onChangeNoCheck, 1000/30);
- }
-
- onChangeNoCheck (v) {
- this.props.onChange(v);
- }
-
- //TODO: I much rather would do this with absolute positioning
- //but I am too stupid to get it to work together with fixed position
- //and scrollbars so I have to fallback to JavaScript
- calcPickerOffset = () => {
- const elem = this.colorInput
- if(elem) {
- const pos = elem.getBoundingClientRect()
- return {
- top: pos.top,
- left: pos.left + 196,
- }
- } else {
- return {
- top: 160,
- left: 555,
- }
- }
- }
-
- togglePicker = () => {
- this.setState({ pickerOpened: !this.state.pickerOpened })
- }
-
- get color() {
- // Catch invalid color.
- try {
- return Color(this.props.value).rgb()
- }
- catch(err) {
- console.warn("Error parsing color: ", err);
- return Color("rgb(255,255,255)");
- }
- }
-
- onChange (v) {
- this.props.onChange(v === "" ? undefined : v);
+ ...InputColor.propTypes,
}
render() {
- const offset = this.calcPickerOffset()
- var currentColor = this.color.object()
- currentColor = {
- r: currentColor.r,
- g: currentColor.g,
- b: currentColor.b,
- // Rename alpha -> a for ChromePicker
- a: currentColor.alpha
- }
+ const {props} = this;
- const picker =
-
this.onChangeNoCheck(formatColor(c))}
- />
-
-
-
- var swatchStyle = {
- backgroundColor: this.props.value
- };
-
- return
- {this.state.pickerOpened && picker}
-
-
this.colorInput = input}
- onClick={this.togglePicker}
- style={this.props.style}
- name={this.props.name}
- placeholder={this.props.default}
- value={this.props.value ? this.props.value : ""}
- onChange={(e) => this.onChange(e.target.value)}
- />
-
+ return
+
+
}
}
diff --git a/src/components/FieldComment.jsx b/src/components/FieldComment.jsx
new file mode 100644
index 0000000..9c6125e
--- /dev/null
+++ b/src/components/FieldComment.jsx
@@ -0,0 +1,31 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+
+import Block from './Block'
+import InputString from './InputString'
+
+export default class FieldComment extends React.Component {
+ static propTypes = {
+ value: PropTypes.string,
+ onChange: PropTypes.func.isRequired,
+ }
+
+ render() {
+ const fieldSpec = {
+ doc: "Comments for the current layer. This is non-standard and not in the spec."
+ };
+
+ return
+
+
+ }
+}
diff --git a/src/components/FieldDynamicArray.jsx b/src/components/FieldDynamicArray.jsx
index c8f3b71..47bbbaf 100644
--- a/src/components/FieldDynamicArray.jsx
+++ b/src/components/FieldDynamicArray.jsx
@@ -1,136 +1,21 @@
import React from 'react'
import PropTypes from 'prop-types'
-import FieldString from './FieldString'
-import FieldNumber from './FieldNumber'
-import Button from './Button'
-import {MdDelete} from 'react-icons/md'
-import FieldDocLabel from './FieldDocLabel'
-import FieldEnum from './FieldEnum'
-import capitalize from 'lodash.capitalize'
-import FieldUrl from './FieldUrl'
-
+import Block from './Block'
+import InputDynamicArray from './InputDynamicArray'
+import Fieldset from './Fieldset'
export default class FieldDynamicArray extends React.Component {
static propTypes = {
- value: PropTypes.array,
- type: PropTypes.string,
- default: PropTypes.array,
- onChange: PropTypes.func,
- style: PropTypes.object,
- fieldSpec: PropTypes.object,
- }
-
- changeValue(idx, newValue) {
- console.log(idx, newValue)
- const values = this.values.slice(0)
- values[idx] = newValue
- this.props.onChange(values)
- }
-
- get values() {
- return this.props.value || this.props.default || []
- }
-
- addValue = () => {
- const values = this.values.slice(0)
- if (this.props.type === 'number') {
- values.push(0)
- }
- else if (this.props.type === 'url') {
- values.push("");
- }
- else if (this.props.type === 'enum') {
- const {fieldSpec} = this.props;
- const defaultValue = Object.keys(fieldSpec.values)[0];
- values.push(defaultValue);
- } else {
- values.push("")
- }
-
- this.props.onChange(values)
- }
-
- deleteValue(valueIdx) {
- const values = this.values.slice(0)
- values.splice(valueIdx, 1)
-
- this.props.onChange(values)
+ ...InputDynamicArray.propTypes,
+ name: PropTypes.string,
}
render() {
- const inputs = this.values.map((v, i) => {
- const deleteValueBtn=
- let input;
- if(this.props.type === 'url') {
- input =
- }
- else if (this.props.type === 'number') {
- input =
- }
- else if (this.props.type === 'enum') {
- const options = Object.keys(this.props.fieldSpec.values).map(v => [v, capitalize(v)]);
+ const {props} = this;
- input =
- }
- else {
- input =
- }
-
- return
-
- {deleteValueBtn}
-
-
- {input}
-
-
- })
-
- return
- {inputs}
-
- Add value
-
-
- }
-}
-
-class DeleteValueButton extends React.Component {
- static propTypes = {
- onClick: PropTypes.func,
- }
-
- render() {
- return
- }
- doc={"Remove array item."}
- />
-
+ return
+
+
}
}
diff --git a/src/components/FieldEnum.jsx b/src/components/FieldEnum.jsx
index a9e89a0..f4268ec 100644
--- a/src/components/FieldEnum.jsx
+++ b/src/components/FieldEnum.jsx
@@ -1,45 +1,20 @@
import React from 'react'
import PropTypes from 'prop-types'
-import FieldSelect from './FieldSelect'
-import FieldMultiInput from './FieldMultiInput'
-
-
-function optionsLabelLength(options) {
- let sum = 0;
- options.forEach(([_, label]) => {
- sum += label.length
- })
- return sum
-}
+import InputEnum from './InputEnum'
+import Block from './Block';
+import Fieldset from './Fieldset';
export default class FieldEnum extends React.Component {
static propTypes = {
- "data-wd-key": PropTypes.string,
- value: PropTypes.string,
- style: PropTypes.object,
- default: PropTypes.string,
- name: PropTypes.string,
- onChange: PropTypes.func,
- options: PropTypes.array,
+ ...InputEnum.propTypes,
}
render() {
- const {options, value, onChange, name} = this.props;
+ const {props} = this;
- if(options.length <= 3 && optionsLabelLength(options) <= 20) {
- return
- } else {
- return
- }
+ return
+
+
}
}
diff --git a/src/components/FieldFunction.jsx b/src/components/FieldFunction.jsx
index 3cb25a2..0174f93 100644
--- a/src/components/FieldFunction.jsx
+++ b/src/components/FieldFunction.jsx
@@ -200,12 +200,35 @@ export default class FieldFunction extends React.Component {
}
makeZoomFunction = () => {
- const zoomFunc = {
- stops: [
- [6, this.props.value || findDefaultFromSpec(this.props.fieldSpec)],
- [10, this.props.value || findDefaultFromSpec(this.props.fieldSpec)]
- ]
+ const {value} = this.props;
+
+ let zoomFunc;
+ if (typeof(value) === "object") {
+ if (value.stops) {
+ zoomFunc = {
+ stops: value.stops.map(stop => {
+ return [stop[0].zoom, stop[1] || findDefaultFromSpec(this.props.fieldSpec)];
+ })
+ }
+ }
+ else {
+ zoomFunc = {
+ stops: [
+ [6, findDefaultFromSpec(this.props.fieldSpec)],
+ [10, findDefaultFromSpec(this.props.fieldSpec)]
+ ]
+ }
+ }
}
+ else {
+ zoomFunc = {
+ stops: [
+ [6, value || findDefaultFromSpec(this.props.fieldSpec)],
+ [10, value || findDefaultFromSpec(this.props.fieldSpec)]
+ ]
+ }
+ }
+
this.props.onChange(this.props.fieldName, zoomFunc)
}
@@ -258,14 +281,41 @@ export default class FieldFunction extends React.Component {
makeDataFunction = () => {
const functionType = this.getFieldFunctionType(this.props.fieldSpec);
const stopValue = functionType === 'categorical' ? '' : 0;
- const dataFunc = {
- property: "",
- type: functionType,
- stops: [
- [{zoom: 6, value: stopValue}, this.props.value || findDefaultFromSpec(this.props.fieldSpec)],
- [{zoom: 10, value: stopValue}, this.props.value || findDefaultFromSpec(this.props.fieldSpec)]
- ]
+ const {value} = this.props;
+ let dataFunc;
+
+ if (typeof(value) === "object") {
+ if (value.stops) {
+ dataFunc = {
+ property: "",
+ type: functionType,
+ stops: value.stops.map(stop => {
+ return [{zoom: stop[0], value: stopValue}, stop[1] || findDefaultFromSpec(this.props.fieldSpec)];
+ })
+ }
+ }
+ else {
+ dataFunc = {
+ property: "",
+ type: functionType,
+ stops: [
+ [{zoom: 6, value: stopValue}, findDefaultFromSpec(this.props.fieldSpec)],
+ [{zoom: 10, value: stopValue}, findDefaultFromSpec(this.props.fieldSpec)]
+ ]
+ }
+ }
}
+ else {
+ dataFunc = {
+ property: "",
+ type: functionType,
+ stops: [
+ [{zoom: 6, value: stopValue}, this.props.value || findDefaultFromSpec(this.props.fieldSpec)],
+ [{zoom: 10, value: stopValue}, this.props.value || findDefaultFromSpec(this.props.fieldSpec)]
+ ]
+ }
+ }
+
this.props.onChange(this.props.fieldName, dataFunc)
}
@@ -310,11 +360,13 @@ export default class FieldFunction extends React.Component {
value={this.props.value}
onDeleteStop={this.deleteStop}
onAddStop={this.addStop}
+ onChangeToDataFunction={this.makeDataFunction}
onExpressionClick={this.makeExpression}
/>
)
}
else if (dataType === "data_function") {
+ // TODO: Rename to FieldFunction **this file** shouldn't be called that
specField = (
)
diff --git a/src/components/FieldId.jsx b/src/components/FieldId.jsx
new file mode 100644
index 0000000..6a857f9
--- /dev/null
+++ b/src/components/FieldId.jsx
@@ -0,0 +1,27 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+
+import {latest} from '@mapbox/mapbox-gl-style-spec'
+import Block from './Block'
+import InputString from './InputString'
+
+export default class FieldId extends React.Component {
+ static propTypes = {
+ value: PropTypes.string.isRequired,
+ wdKey: PropTypes.string.isRequired,
+ onChange: PropTypes.func.isRequired,
+ error: PropTypes.object,
+ }
+
+ render() {
+ return
+
+
+ }
+}
diff --git a/src/components/FieldJson.jsx b/src/components/FieldJson.jsx
new file mode 100644
index 0000000..1f6ccea
--- /dev/null
+++ b/src/components/FieldJson.jsx
@@ -0,0 +1,16 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import InputJson from './InputJson'
+
+
+export default class FieldJson extends React.Component {
+ static propTypes = {
+ ...InputJson.propTypes,
+ }
+
+ render() {
+ const {props} = this;
+ return
+ }
+}
+
diff --git a/src/components/FieldMaxZoom.jsx b/src/components/FieldMaxZoom.jsx
new file mode 100644
index 0000000..2d38ad3
--- /dev/null
+++ b/src/components/FieldMaxZoom.jsx
@@ -0,0 +1,30 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+
+import {latest} from '@mapbox/mapbox-gl-style-spec'
+import Block from './Block'
+import InputNumber from './InputNumber'
+
+export default class FieldMaxZoom extends React.Component {
+ static propTypes = {
+ value: PropTypes.number,
+ onChange: PropTypes.func.isRequired,
+ error: PropTypes.object,
+ }
+
+ render() {
+ return
+
+
+ }
+}
diff --git a/src/components/FieldMinZoom.jsx b/src/components/FieldMinZoom.jsx
new file mode 100644
index 0000000..f0252d7
--- /dev/null
+++ b/src/components/FieldMinZoom.jsx
@@ -0,0 +1,30 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+
+import {latest} from '@mapbox/mapbox-gl-style-spec'
+import Block from './Block'
+import InputNumber from './InputNumber'
+
+export default class FieldMinZoom extends React.Component {
+ static propTypes = {
+ value: PropTypes.number,
+ onChange: PropTypes.func.isRequired,
+ error: PropTypes.object,
+ }
+
+ render() {
+ return
+
+
+ }
+}
diff --git a/src/components/FieldMultiInput.jsx b/src/components/FieldMultiInput.jsx
index 94d7ba9..ae5daf6 100644
--- a/src/components/FieldMultiInput.jsx
+++ b/src/components/FieldMultiInput.jsx
@@ -1,41 +1,21 @@
import React from 'react'
import PropTypes from 'prop-types'
-import classnames from 'classnames'
-import Button from './Button'
+import Block from './Block'
+import InputMultiInput from './InputMultiInput'
+import Fieldset from './Fieldset'
+
export default class FieldMultiInput extends React.Component {
static propTypes = {
- name: PropTypes.string.isRequired,
- value: PropTypes.string.isRequired,
- options: PropTypes.array.isRequired,
- onChange: PropTypes.func.isRequired,
+ ...InputMultiInput.propTypes,
}
render() {
- let options = this.props.options
- if(options.length > 0 && !Array.isArray(options[0])) {
- options = options.map(v => [v, v])
- }
+ const {props} = this;
- const selectedValue = this.props.value || options[0][0]
- const radios = options.map(([val, label])=> {
- return
- this.props.onChange(val)}
- value={val}
- checked={val === selectedValue}
- />
- {label}
-
- })
-
- return
- {radios}
-
+ return
+
+
}
}
diff --git a/src/components/FieldNumber.jsx b/src/components/FieldNumber.jsx
index a74bb08..0d42ddf 100644
--- a/src/components/FieldNumber.jsx
+++ b/src/components/FieldNumber.jsx
@@ -1,232 +1,19 @@
import React from 'react'
import PropTypes from 'prop-types'
+import InputNumber from './InputNumber'
+import Block from './Block'
-let IDX = 0;
export default class FieldNumber extends React.Component {
static propTypes = {
- value: PropTypes.number,
- default: PropTypes.number,
- min: PropTypes.number,
- max: PropTypes.number,
- onChange: PropTypes.func,
- allowRange: PropTypes.bool,
- rangeStep: PropTypes.number,
- wdKey: PropTypes.string,
- required: PropTypes.bool,
- }
-
- static defaultProps = {
- rangeStep: 1
- }
-
- constructor(props) {
- super(props)
- this.state = {
- uuid: IDX++,
- editing: false,
- value: props.value,
- dirtyValue: props.value,
- }
- }
-
- static getDerivedStateFromProps(props, state) {
- if (!state.editing && props.value !== state.value) {
- return {
- value: props.value,
- dirtyValue: props.value,
- };
- }
- return null;
- }
-
- changeValue(newValue) {
- const value = (newValue === "" || newValue === undefined) ?
- undefined :
- parseFloat(newValue);
-
- const hasChanged = this.props.value !== value;
- if(this.isValid(value) && hasChanged) {
- this.props.onChange(value)
- this.setState({
- value: newValue,
- });
- }
- else if (!this.isValid(value) && hasChanged) {
- this.setState({
- value: undefined,
- });
- }
-
- this.setState({
- dirtyValue: newValue === "" ? undefined : newValue,
- })
- }
-
- isValid(v) {
- if (v === undefined) {
- return true;
- }
-
- const value = parseFloat(v)
- if(isNaN(value)) {
- return false
- }
-
- if(!isNaN(this.props.min) && value < this.props.min) {
- return false
- }
-
- if(!isNaN(this.props.max) && value > this.props.max) {
- return false
- }
-
- return true
- }
-
- resetValue = () => {
- this.setState({editing: false});
- // Reset explicitly to default value if value has been cleared
- if(this.state.value === "") {
- return;
- }
-
- // If set value is invalid fall back to the last valid value from props or at last resort the default value
- if (!this.isValid(this.state.value)) {
- if(this.isValid(this.props.value)) {
- this.changeValue(this.props.value)
- this.setState({dirtyValue: this.props.value});
- } else {
- this.changeValue(undefined);
- this.setState({dirtyValue: undefined});
- }
- }
- }
-
- onChangeRange = (e) => {
- let value = parseFloat(e.target.value, 10);
- const step = this.props.rangeStep;
- let dirtyValue = value;
-
- if(step) {
- // Can't do this with the
range step attribute else we won't be able to set a high precision value via the text input.
- const snap = value % step;
-
- // Round up/down to step
- if (this._keyboardEvent) {
- // If it's keyboard event we might get a low positive/negative value,
- // for example we might go from 13 to 13.23, however because we know
- // that came from a keyboard event we always want to increase by a
- // single step value.
- if (value < this.state.dirtyValue) {
- value = this.state.value - step;
- }
- else {
- value = this.state.value + step
- }
- dirtyValue = value;
- }
- else {
- if (snap < step/2) {
- value = value - snap;
- }
- else {
- value = value + (step - snap);
- };
- }
- }
-
- this._keyboardEvent = false;
-
- // Clamp between min/max
- value = Math.max(this.props.min, Math.min(this.props.max, value));
-
- this.setState({value, dirtyValue});
- this.props.onChange(value);
+ ...InputNumber.propTypes,
}
render() {
- if(
- this.props.hasOwnProperty("min") && this.props.hasOwnProperty("max") &&
- this.props.min !== undefined && this.props.max !== undefined &&
- this.props.allowRange
- ) {
- const value = this.state.editing ? this.state.dirtyValue : this.state.value;
- const defaultValue = this.props.default === undefined ? "" : this.props.default;
- let inputValue;
- if (this.state.editingRange) {
- inputValue = this.state.value;
- }
- else {
- inputValue = value;
- }
-
- return
- {
- this._keyboardEvent = true;
- }}
- onPointerDown={() => {
- this.setState({editing: true, editingRange: true});
- }}
- onPointerUp={() => {
- // Safari doesn't get onBlur event
- this.setState({editing: false, editingRange: false});
- }}
- onBlur={() => {
- this.setState({
- editing: false,
- editingRange: false,
- dirtyValue: this.state.value,
- });
- }}
- />
- {
- this.setState({editing: true});
- }}
- onChange={e => {
- this.changeValue(e.target.value);
- }}
- onBlur={e => {
- this.setState({editing: false});
- this.resetValue()
- }}
- />
-
- }
- else {
- const value = this.state.editing ? this.state.dirtyValue : this.state.value;
-
- return
this.changeValue(e.target.value)}
- onFocus={() => {
- this.setState({editing: true});
- }}
- onBlur={this.resetValue}
- required={this.props.required}
- />
- }
+ const {props} = this;
+ return
+
+
}
}
diff --git a/src/components/FieldSelect.jsx b/src/components/FieldSelect.jsx
index fc54eee..1d279c6 100644
--- a/src/components/FieldSelect.jsx
+++ b/src/components/FieldSelect.jsx
@@ -1,33 +1,20 @@
import React from 'react'
import PropTypes from 'prop-types'
+import Block from './Block'
+import InputSelect from './InputSelect'
+
export default class FieldSelect extends React.Component {
static propTypes = {
- value: PropTypes.string.isRequired,
- "data-wd-key": PropTypes.string,
- options: PropTypes.array.isRequired,
- style: PropTypes.object,
- onChange: PropTypes.func.isRequired,
- title: PropTypes.string,
+ ...InputSelect.propTypes,
}
-
render() {
- let options = this.props.options
- if(options.length > 0 && !Array.isArray(options[0])) {
- options = options.map(v => [v, v])
- }
+ const {props} = this;
- return
this.props.onChange(e.target.value)}
- >
- { options.map(([val, label]) => {label} ) }
-
+ return
+
+
}
}
diff --git a/src/components/FieldSource.jsx b/src/components/FieldSource.jsx
new file mode 100644
index 0000000..7dcc96d
--- /dev/null
+++ b/src/components/FieldSource.jsx
@@ -0,0 +1,36 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+
+import {latest} from '@mapbox/mapbox-gl-style-spec'
+import Block from './Block'
+import InputAutocomplete from './InputAutocomplete'
+
+export default class FieldSource extends React.Component {
+ static propTypes = {
+ value: PropTypes.string,
+ wdKey: PropTypes.string,
+ onChange: PropTypes.func,
+ sourceIds: PropTypes.array,
+ error: PropTypes.object,
+ }
+
+ static defaultProps = {
+ onChange: () => {},
+ sourceIds: [],
+ }
+
+ render() {
+ return
+ [src, src])}
+ />
+
+ }
+}
diff --git a/src/components/FieldSourceLayer.jsx b/src/components/FieldSourceLayer.jsx
new file mode 100644
index 0000000..895d43d
--- /dev/null
+++ b/src/components/FieldSourceLayer.jsx
@@ -0,0 +1,34 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+
+import {latest} from '@mapbox/mapbox-gl-style-spec'
+import Block from './Block'
+import InputAutocomplete from './InputAutocomplete'
+
+export default class FieldSourceLayer extends React.Component {
+ static propTypes = {
+ value: PropTypes.string,
+ onChange: PropTypes.func,
+ sourceLayerIds: PropTypes.array,
+ isFixed: PropTypes.bool,
+ }
+
+ static defaultProps = {
+ onChange: () => {},
+ sourceLayerIds: [],
+ isFixed: false
+ }
+
+ render() {
+ return
+ [l, l])}
+ />
+
+ }
+}
diff --git a/src/components/FieldString.jsx b/src/components/FieldString.jsx
index d061d81..89d9327 100644
--- a/src/components/FieldString.jsx
+++ b/src/components/FieldString.jsx
@@ -1,92 +1,20 @@
import React from 'react'
import PropTypes from 'prop-types'
+import Block from './Block'
+import InputString from './InputString'
export default class FieldString extends React.Component {
static propTypes = {
- "data-wd-key": PropTypes.string,
- value: PropTypes.string,
- style: PropTypes.object,
- default: PropTypes.string,
- onChange: PropTypes.func,
- onInput: PropTypes.func,
- multi: PropTypes.bool,
- required: PropTypes.bool,
- disabled: PropTypes.bool,
- spellCheck: PropTypes.bool,
- }
-
- static defaultProps = {
- onInput: () => {},
- }
-
- constructor(props) {
- super(props)
- this.state = {
- editing: false,
- value: props.value || ''
- }
- }
-
- static getDerivedStateFromProps(props, state) {
- if (!state.editing) {
- return {
- value: props.value
- };
- }
- return {};
+ ...InputString.propTypes,
+ name: PropTypes.string,
}
render() {
- let tag;
- let classes;
+ const {props} = this;
- if(!!this.props.multi) {
- tag = "textarea"
- classes = [
- "maputnik-string",
- "maputnik-string--multi"
- ]
- }
- else {
- tag = "input"
- classes = [
- "maputnik-string"
- ]
- }
-
- if(!!this.props.disabled) {
- classes.push("maputnik-string--disabled");
- }
-
- return React.createElement(tag, {
- "data-wd-key": this.props["data-wd-key"],
- spellCheck: this.props.hasOwnProperty("spellCheck") ? this.props.spellCheck : !(tag === "input"),
- disabled: this.props.disabled,
- className: classes.join(" "),
- style: this.props.style,
- value: this.state.value === undefined ? "" : this.state.value,
- placeholder: this.props.default,
- onChange: e => {
- this.setState({
- editing: true,
- value: e.target.value
- }, () => {
- this.props.onInput(this.state.value);
- });
- },
- onBlur: () => {
- if(this.state.value!==this.props.value) {
- this.setState({editing: false});
- this.props.onChange(this.state.value);
- }
- },
- onKeyDown: (e) => {
- if (e.keyCode === 13) {
- this.props.onChange(this.state.value);
- }
- },
- required: this.props.required,
- });
+ return
+
+
}
}
diff --git a/src/components/FieldType.jsx b/src/components/FieldType.jsx
new file mode 100644
index 0000000..d95c1c2
--- /dev/null
+++ b/src/components/FieldType.jsx
@@ -0,0 +1,52 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+
+import {latest} from '@mapbox/mapbox-gl-style-spec'
+import Block from './Block'
+import InputSelect from './InputSelect'
+import InputString from './InputString'
+
+export default class FieldType extends React.Component {
+ static propTypes = {
+ value: PropTypes.string.isRequired,
+ wdKey: PropTypes.string,
+ onChange: PropTypes.func.isRequired,
+ error: PropTypes.object,
+ disabled: PropTypes.bool,
+ }
+
+ static defaultProps = {
+ disabled: false,
+ }
+
+ render() {
+ return
+ {this.props.disabled &&
+
+ }
+ {!this.props.disabled &&
+
+ }
+
+ }
+}
diff --git a/src/components/FieldUrl.jsx b/src/components/FieldUrl.jsx
index 8132eb8..3c53b19 100644
--- a/src/components/FieldUrl.jsx
+++ b/src/components/FieldUrl.jsx
@@ -1,100 +1,21 @@
import React, {Fragment} from 'react'
import PropTypes from 'prop-types'
-import FieldString from './FieldString'
-import SmallError from './SmallError'
+import InputUrl from './InputUrl'
+import Block from './Block'
-function validate (url) {
- if (url === "") {
- return;
- }
-
- let error;
- const getProtocol = (url) => {
- try {
- const urlObj = new URL(url);
- return urlObj.protocol;
- }
- catch (err) {
- return undefined;
- }
- };
- const protocol = getProtocol(url);
- const isSsl = window.location.protocol === "https:";
-
- if (!protocol) {
- error = (
-
- Must provide protocol {
- isSsl
- ? https://
- : <>http://
or https://
>
- }
-
- );
- }
- else if (
- protocol &&
- protocol === "http:" &&
- window.location.protocol === "https:"
- ) {
- error = (
-
- CORS policy won't allow fetching resources served over http from https, use a https://
domain
-
- );
- }
-
- return error;
-}
-
export default class FieldUrl extends React.Component {
static propTypes = {
- "data-wd-key": PropTypes.string,
- value: PropTypes.string,
- style: PropTypes.object,
- default: PropTypes.string,
- onChange: PropTypes.func,
- onInput: PropTypes.func,
- multi: PropTypes.bool,
- required: PropTypes.bool,
- }
-
- static defaultProps = {
- onInput: () => {},
- }
-
- constructor (props) {
- super(props);
- this.state = {
- error: validate(props.value)
- };
- }
-
- onInput = (url) => {
- this.setState({
- error: validate(url)
- });
- this.props.onInput(url);
- }
-
- onChange = (url) => {
- this.setState({
- error: validate(url)
- });
- this.props.onChange(url);
+ ...InputUrl.propTypes,
}
render () {
+ const {props} = this;
+
return (
-
-
- {this.state.error}
-
+
+
+
);
}
}
diff --git a/src/components/Fieldset.jsx b/src/components/Fieldset.jsx
new file mode 100644
index 0000000..e6308b9
--- /dev/null
+++ b/src/components/Fieldset.jsx
@@ -0,0 +1,58 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import FieldDocLabel from './FieldDocLabel'
+import Doc from './Doc'
+
+
+let IDX = 0;
+
+export default class Fieldset extends React.Component {
+ constructor (props) {
+ super(props);
+ this._labelId = `fieldset_label_${(IDX++)}`;
+ this.state = {
+ showDoc: false,
+ }
+ }
+
+ onToggleDoc = (val) => {
+ this.setState({
+ showDoc: val
+ });
+ }
+
+ render () {
+ const {props} = this;
+
+ return
+ {this.props.fieldSpec &&
+
+
+
+ }
+ {!this.props.fieldSpec &&
+
+ {props.label}
+
+ }
+
+ {this.props.action}
+
+
+ {props.children}
+
+ {this.props.fieldSpec &&
+
+
+
+ }
+
+ }
+}
diff --git a/src/components/FilterEditor.jsx b/src/components/FilterEditor.jsx
index 55a04fd..d99d8a9 100644
--- a/src/components/FilterEditor.jsx
+++ b/src/components/FilterEditor.jsx
@@ -4,11 +4,11 @@ import { combiningFilterOps } from '../libs/filterops.js'
import {mdiTableRowPlusAfter} from '@mdi/js';
import {latest, validate, migrate} from '@mapbox/mapbox-gl-style-spec'
-import FieldSelect from './FieldSelect'
+import InputSelect from './InputSelect'
import Block from './Block'
import SingleFilterEditor from './SingleFilterEditor'
import FilterEditorBlock from './FilterEditorBlock'
-import Button from './Button'
+import InputButton from './InputButton'
import Doc from './Doc'
import ExpressionProperty from './_ExpressionProperty';
import {mdiFunctionVariant} from '@mdi/js';
@@ -191,7 +191,7 @@ export default class FilterEditor extends React.Component {
Nested filters are not supported.
-
@@ -199,7 +199,7 @@ export default class FilterEditor extends React.Component {
Upgrade to expression
-
+
}
else if (displaySimpleFilter) {
@@ -209,7 +209,7 @@ export default class FilterEditor extends React.Component {
const actions = (
);
@@ -249,7 +249,7 @@ export default class FilterEditor extends React.Component {
label={"Filter"}
action={actions}
>
-