Merge remote-tracking branch 'upstream/master' into feature/add-range-slider

This commit is contained in:
orangemug
2019-10-26 17:22:52 +01:00
54 changed files with 8413 additions and 8594 deletions

View File

@@ -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)}
/>
}

View File

@@ -44,6 +44,10 @@ class AutocompleteInput extends React.Component {
this.calcMaxHeight();
}
onChange (v) {
this.props.onChange(v === "" ? undefined : v);
}
render() {
return <div
ref={(el) => {
@@ -68,8 +72,8 @@ class AutocompleteInput extends React.Component {
value={this.props.value}
items={this.props.options}
getItemValue={(item) => item[0]}
onSelect={v => this.props.onChange(v)}
onChange={(e, v) => this.props.onChange(v)}
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

View File

@@ -5,6 +5,8 @@ import NumberInput from './NumberInput'
import Button from '../Button'
import {MdDelete} from 'react-icons/md'
import DocLabel from '../fields/DocLabel'
import EnumInput from '../inputs/SelectInput'
import capitalize from 'lodash.capitalize'
class DynamicArrayInput extends React.Component {
@@ -14,6 +16,7 @@ class DynamicArrayInput extends React.Component {
default: PropTypes.array,
onChange: PropTypes.func,
style: PropTypes.object,
fieldSpec: PropTypes.object,
}
changeValue(idx, newValue) {
@@ -31,6 +34,11 @@ class DynamicArrayInput extends React.Component {
const values = this.values.slice(0)
if (this.props.type === 'number') {
values.push(0)
}
else if (this.props.type === 'enum') {
const {fieldSpec} = this.props;
const defaultValue = Object.keys(fieldSpec.values)[0];
values.push(defaultValue);
} else {
values.push("")
}
@@ -48,15 +56,28 @@ class DynamicArrayInput extends React.Component {
render() {
const inputs = this.values.map((v, i) => {
const deleteValueBtn= <DeleteValueButton onClick={this.deleteValue.bind(this, i)} />
const input = this.props.type === 'number'
? <NumberInput
let input;
if (this.props.type === 'number') {
input = <NumberInput
value={v}
onChange={this.changeValue.bind(this, i)}
/>
: <StringInput
}
else if (this.props.type === 'enum') {
const options = Object.keys(this.props.fieldSpec.values).map(v => [v, capitalize(v)]);
input = <EnumInput
options={options}
value={v}
onChange={this.changeValue.bind(this, i)}
/>
}
else {
input = <StringInput
value={v}
onChange={this.changeValue.bind(this, i)}
/>
}
return <div
style={this.props.style}

View File

@@ -0,0 +1,45 @@
import React from 'react'
import PropTypes from 'prop-types'
import SelectInput from '../inputs/SelectInput'
import MultiButtonInput from '../inputs/MultiButtonInput'
function optionsLabelLength(options) {
let sum = 0;
options.forEach(([_, label]) => {
sum += label.length
})
return sum
}
class EnumInput extends React.Component {
static propTypes = {
"data-wd-key": PropTypes.string,
value: PropTypes.string,
style: PropTypes.object,
default: PropTypes.string,
onChange: PropTypes.func,
options: PropTypes.array,
}
render() {
const {options, value, onChange} = this.props;
if(options.length <= 3 && optionsLabelLength(options) <= 20) {
return <MultiButtonInput
options={options}
value={value || this.props.default}
onChange={onChange}
/>
} else {
return <SelectInput
options={options}
value={value || this.props.default}
onChange={onChange}
/>
}
}
}
export default EnumInput

View File

@@ -16,13 +16,25 @@ class FontInput extends React.Component {
}
get values() {
return this.props.value || this.props.default.slice(1) || []
const out = this.props.value || this.props.default.slice(1) || [""];
// Always put a "" in the last field to you can keep adding entries
if (out[out.length-1] !== ""){
return out.concat("");
}
else {
return out;
}
}
changeFont(idx, newValue) {
const changedValues = this.values.slice(0)
changedValues[idx] = newValue
this.props.onChange(changedValues)
const filteredValues = changedValues
.filter(v => v !== undefined)
.filter(v => v !== "")
this.props.onChange(filteredValues);
}
render() {

View File

@@ -20,7 +20,7 @@ class InputBlock extends React.Component {
onChange(e) {
const value = e.target.value
return this.props.onChange(value === "" ? null: value)
return this.props.onChange(value === "" ? undefined : value)
}
render() {

View File

@@ -11,6 +11,7 @@ class NumberInput extends React.Component {
allowRange: PropTypes.bool,
rangeStep: PropTypes.number,
wdKey: PropTypes.string,
required: PropTypes.bool,
}
static defaultProps = {
@@ -33,14 +34,14 @@ class NumberInput extends React.Component {
dirtyValue: props.value,
};
}
else {
return null;
}
return {};
}
changeValue(newValue) {
this.setState({editing: true});
const value = parseFloat(newValue)
const value = (newValue === "" || newValue === undefined) ?
undefined :
parseFloat(newValue);
const hasChanged = this.state.value !== value;
if(this.isValid(value) && hasChanged) {
@@ -53,6 +54,10 @@ class NumberInput extends React.Component {
}
isValid(v) {
if (v === undefined) {
return true;
}
const value = parseFloat(v)
if(isNaN(value)) {
return false
@@ -73,7 +78,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
@@ -81,7 +86,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);
}
}
}
@@ -108,6 +113,7 @@ class NumberInput extends React.Component {
}
render() {
<<<<<<< HEAD
if(
this.props.hasOwnProperty("min") && this.props.hasOwnProperty("max") &&
this.props.min !== undefined && this.props.max !== undefined &&
@@ -152,18 +158,15 @@ class NumberInput extends React.Component {
</div>
}
else {
return <div className="maputnik-number-container">
<input
key="text"
type="text"
spellCheck="false"
className="maputnik-number"
placeholder={this.props.default}
value={this.state.value}
onChange={e => this.changeValue(e.target.value)}
onBlur={this.resetValue}
/>
</div>
return <input
spellCheck="false"
className="maputnik-number"
placeholder={this.props.default}
value={this.state.value === undefined ? "" : this.state.value}
onChange={e => this.changeValue(e.target.value)}
onBlur={this.resetValue}
required={this.props.required}
/>
}
}
}

View File

@@ -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,
});
}
}