diff --git a/src/components/fields/FunctionSpecField.jsx b/src/components/fields/FunctionSpecField.jsx
index cc8fb16..38304c4 100644
--- a/src/components/fields/FunctionSpecField.jsx
+++ b/src/components/fields/FunctionSpecField.jsx
@@ -6,12 +6,21 @@ import DataProperty from './_DataProperty'
import ZoomProperty from './_ZoomProperty'
import ExpressionProperty from './_ExpressionProperty'
import {function as styleFunction} from '@mapbox/mapbox-gl-style-spec';
+import {findDefaultFromSpec} from '../util/spec-helper';
function isLiteralExpression (value) {
return (Array.isArray(value) && value.length === 2 && value[0] === "literal");
}
+function isGetExpression (value) {
+ return (
+ Array.isArray(value) &&
+ value.length === 2 &&
+ value[0] === "get"
+ );
+}
+
function isZoomField(value) {
return (
typeof(value) === 'object' &&
@@ -28,7 +37,15 @@ function isZoomField(value) {
);
}
-function isDataField(value) {
+function isIdentityProperty (value) {
+ return (
+ typeof(value) === 'object' &&
+ value.type === "identity" &&
+ value.hasOwnProperty("property")
+ );
+}
+
+function isDataStopProperty (value) {
return (
typeof(value) === 'object' &&
value.stops &&
@@ -45,6 +62,13 @@ function isDataField(value) {
);
}
+function isDataField(value) {
+ return (
+ isIdentityProperty(value) ||
+ isDataStopProperty(value)
+ );
+}
+
function isPrimative (value) {
const valid = ["string", "boolean", "number"];
return valid.includes(typeof(value));
@@ -78,24 +102,6 @@ function getDataType (value, fieldSpec={}) {
}
}
-/**
- * If we don't have a default value just make one up
- */
-function findDefaultFromSpec (spec) {
- if (spec.hasOwnProperty('default')) {
- return spec.default;
- }
-
- const defaults = {
- 'color': '#000000',
- 'string': '',
- 'boolean': false,
- 'number': 0,
- 'array': [],
- }
-
- return defaults[spec.type] || '';
-}
/** Supports displaying spec field for zoom function objects
* https://www.mapbox.com/mapbox-gl-style-spec/#types-function-zoom-property
@@ -206,7 +212,16 @@ export default class FunctionSpecProperty extends React.Component {
undoExpression = () => {
const {value, fieldName} = this.props;
- if (isLiteralExpression(value)) {
+ if (isGetExpression(value)) {
+ this.props.onChange(fieldName, {
+ "type": "identity",
+ "property": value[1]
+ });
+ this.setState({
+ dataType: "value",
+ });
+ }
+ else if (isLiteralExpression(value)) {
this.props.onChange(fieldName, value[1]);
this.setState({
dataType: "value",
@@ -217,6 +232,7 @@ export default class FunctionSpecProperty extends React.Component {
canUndo = () => {
const {value, fieldSpec} = this.props;
return (
+ isGetExpression(value) ||
isLiteralExpression(value) ||
isPrimative(value) ||
(Array.isArray(value) && fieldSpec.type === "array")
@@ -230,6 +246,9 @@ export default class FunctionSpecProperty extends React.Component {
if (typeof(value) === "object" && 'stops' in value) {
expression = styleFunction.convertFunction(value, fieldSpec);
}
+ else if (isIdentityProperty(value)) {
+ expression = ["get", value.property];
+ }
else {
expression = ["literal", value || this.props.fieldSpec.default];
}
diff --git a/src/components/fields/_DataProperty.jsx b/src/components/fields/_DataProperty.jsx
index 80961b7..f2f4e64 100644
--- a/src/components/fields/_DataProperty.jsx
+++ b/src/components/fields/_DataProperty.jsx
@@ -1,5 +1,6 @@
import React from 'react'
import PropTypes from 'prop-types'
+import {mdiFunctionVariant, mdiTableRowPlusAfter} from '@mdi/js';
import Button from '../Button'
import SpecField from './SpecField'
@@ -10,6 +11,7 @@ import DocLabel from './DocLabel'
import InputBlock from '../inputs/InputBlock'
import docUid from '../../libs/document-uid'
import sortNumerically from '../../libs/sort-numerically'
+import {findDefaultFromSpec} from '../util/spec-helper';
import labelFromFieldName from './_labelFromFieldName'
import DeleteStopButton from './_DeleteStopButton'
@@ -89,10 +91,10 @@ export default class DataProperty extends React.Component {
getDataFunctionTypes(fieldSpec) {
if (fieldSpec.expression.interpolated) {
- return ["categorical", "interval", "exponential"]
+ return ["categorical", "interval", "exponential", "identity"]
}
else {
- return ["categorical", "interval"]
+ return ["categorical", "interval", "identity"]
}
}
@@ -122,6 +124,29 @@ export default class DataProperty extends React.Component {
return mappedWithRef.map((item) => item.data);
}
+ onChange = (fieldName, value) => {
+ if (value.type === "identity") {
+ value = {
+ type: value.type,
+ property: value.property,
+ };
+ }
+ else {
+ const stopValue = value.type === 'categorical' ? '' : 0;
+ value = {
+ property: "",
+ type: value.type,
+ // Default props if they don't already exist.
+ stops: [
+ [{zoom: 6, value: stopValue}, findDefaultFromSpec(this.props.fieldSpec)],
+ [{zoom: 10, value: stopValue}, findDefaultFromSpec(this.props.fieldSpec)]
+ ],
+ ...value,
+ }
+ }
+ this.props.onChange(fieldName, value);
+ }
+
changeStop(changeIdx, stopData, value) {
const stops = this.props.value.stops.slice(0)
const changedStop = stopData.zoom === undefined ? stopData.value : stopData
@@ -133,7 +158,7 @@ export default class DataProperty extends React.Component {
...this.props.value,
stops: orderedStops,
}
- this.props.onChange(this.props.fieldName, changedValue)
+ this.onChange(this.props.fieldName, changedValue)
}
changeDataProperty(propName, propVal) {
@@ -143,7 +168,7 @@ export default class DataProperty extends React.Component {
else {
delete this.props.value[propName]
}
- this.props.onChange(this.props.fieldName, this.props.value)
+ this.onChange(this.props.fieldName, this.props.value)
}
render() {
@@ -153,69 +178,72 @@ export default class DataProperty extends React.Component {
this.props.value.type = this.getFieldFunctionType(this.props.fieldSpec)
}
- const dataFields = this.props.value.stops.map((stop, idx) => {
- const zoomLevel = typeof stop[0] === 'object' ? stop[0].zoom : undefined;
- const key = this.state.refs[idx];
- const dataLevel = typeof stop[0] === 'object' ? stop[0].value : stop[0];
- const value = stop[1]
- const deleteStopBtn =