More components migration

This commit is contained in:
HarelM
2023-12-21 13:14:34 +02:00
parent 50226a9b2e
commit f435ab79c1
9 changed files with 136 additions and 128 deletions
-20
View File
@@ -1,20 +0,0 @@
import React from 'react'
import PropTypes from 'prop-types'
import InputEnum from './InputEnum'
import Block from './Block';
import Fieldset from './Fieldset';
export default class FieldEnum extends React.Component {
static propTypes = {
...InputEnum.propTypes,
}
render() {
const {props} = this;
return <Fieldset label={props.label}>
<InputEnum {...props} />
</Fieldset>
}
}
+17
View File
@@ -0,0 +1,17 @@
import React from 'react'
import InputEnum, {InputEnumProps} from './InputEnum'
import Fieldset from './Fieldset';
type FieldEnumProps = InputEnumProps & { label : string };
export default class FieldEnum extends React.Component<FieldEnumProps> {
render() {
const {props} = this;
return <Fieldset label={props.label}>
<InputEnum {...props} />
</Fieldset>
}
}
@@ -1,18 +1,17 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
import {latest} from '@maplibre/maplibre-gl-style-spec' import {latest} from '@maplibre/maplibre-gl-style-spec'
import Block from './Block' import Block from './Block'
import InputString from './InputString' import InputString from './InputString'
export default class FieldId extends React.Component { type FieldIdProps = {
static propTypes = { value: string
value: PropTypes.string.isRequired, wdKey: string
wdKey: PropTypes.string.isRequired, onChange(...args: unknown[]): unknown
onChange: PropTypes.func.isRequired, error?: unknown[]
error: PropTypes.object, };
}
export default class FieldId extends React.Component<FieldIdProps> {
render() { render() {
return <Block label={"ID"} fieldSpec={latest.layer.id} return <Block label={"ID"} fieldSpec={latest.layer.id}
data-wd-key={this.props.wdKey} data-wd-key={this.props.wdKey}
@@ -1,24 +1,29 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
import InputString from './InputString' import InputString from './InputString'
import InputNumber from './InputNumber' import InputNumber from './InputNumber'
export default class FieldArray extends React.Component { type FieldArrayProps = {
static propTypes = { value: string[]
value: PropTypes.array, type?: string
type: PropTypes.string, length?: number
length: PropTypes.number, default?: string[] | number[]
default: PropTypes.array, onChange?(...args: unknown[]): unknown
onChange: PropTypes.func, 'aria-label'?: string
'aria-label': PropTypes.string, label?: string
} };
type FieldArrayState = {
value: string[] | number[]
initialPropsValue: unknown[]
}
export default class FieldArray extends React.Component<FieldArrayProps, FieldArrayState> {
static defaultProps = { static defaultProps = {
value: [], value: [],
default: [], default: [],
} }
constructor (props) { constructor (props: FieldArrayProps) {
super(props); super(props);
this.state = { this.state = {
value: this.props.value.slice(0), value: this.props.value.slice(0),
@@ -27,8 +32,8 @@ export default class FieldArray extends React.Component {
}; };
} }
static getDerivedStateFromProps(props, state) { static getDerivedStateFromProps(props: FieldArrayProps, state: FieldArrayState) {
const value = []; const value: any[] = [];
const initialPropsValue = state.initialPropsValue.slice(0); const initialPropsValue = state.initialPropsValue.slice(0);
Array(props.length).fill(null).map((_, i) => { Array(props.length).fill(null).map((_, i) => {
@@ -47,24 +52,24 @@ export default class FieldArray extends React.Component {
}; };
} }
isComplete (value) { isComplete(value: unknown[]) {
return Array(this.props.length).fill(null).every((_, i) => { return Array(this.props.length).fill(null).every((_, i) => {
const val = value[i] const val = value[i]
return !(val === undefined || val === ""); return !(val === undefined || val === "");
}); });
} }
changeValue(idx, newValue) { changeValue(idx: number, newValue: string) {
const value = this.state.value.slice(0); const value = this.state.value.slice(0);
value[idx] = newValue; value[idx] = newValue;
this.setState({ this.setState({
value, value,
}, () => { }, () => {
if (this.isComplete(value)) { if (this.isComplete(value) && this.props.onChange) {
this.props.onChange(value); this.props.onChange(value);
} }
else { else if (this.props.onChange){
// Unset until complete // Unset until complete
this.props.onChange(undefined); this.props.onChange(undefined);
} }
@@ -85,8 +90,8 @@ export default class FieldArray extends React.Component {
if(this.props.type === 'number') { if(this.props.type === 'number') {
return <InputNumber return <InputNumber
key={i} key={i}
default={containsValues ? undefined : this.props.default[i]} default={containsValues || !this.props.default ? undefined : this.props.default[i] as number}
value={value[i]} value={value[i] as number}
required={containsValues ? true : false} required={containsValues ? true : false}
onChange={this.changeValue.bind(this, i)} onChange={this.changeValue.bind(this, i)}
aria-label={this.props['aria-label'] || this.props.label} aria-label={this.props['aria-label'] || this.props.label}
@@ -94,8 +99,8 @@ export default class FieldArray extends React.Component {
} else { } else {
return <InputString return <InputString
key={i} key={i}
default={containsValues ? undefined : this.props.default[i]} default={containsValues || !this.props.default ? undefined : this.props.default[i] as string}
value={value[i]} value={value[i] as string}
required={containsValues ? true : false} required={containsValues ? true : false}
onChange={this.changeValue.bind(this, i)} onChange={this.changeValue.bind(this, i)}
aria-label={this.props['aria-label'] || this.props.label} aria-label={this.props['aria-label'] || this.props.label}
@@ -1,10 +1,9 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
import InputSelect from './InputSelect' import InputSelect from './InputSelect'
import InputMultiInput from './InputMultiInput' import InputMultiInput from './InputMultiInput'
function optionsLabelLength(options) { function optionsLabelLength(options: any[]) {
let sum = 0; let sum = 0;
options.forEach(([_, label]) => { options.forEach(([_, label]) => {
sum += label.length sum += label.length
@@ -13,18 +12,20 @@ function optionsLabelLength(options) {
} }
export default class InputEnum extends React.Component { export type InputEnumProps = {
static propTypes = { "data-wd-key"?: string
"data-wd-key": PropTypes.string, value?: string
value: PropTypes.string, style?: object
style: PropTypes.object, default?: string
default: PropTypes.string, name: string
name: PropTypes.string, onChange(...args: unknown[]): unknown
onChange: PropTypes.func, options: any[]
options: PropTypes.array, 'aria-label'?: string
'aria-label': PropTypes.string, label?: string
} };
export default class InputEnum extends React.Component<InputEnumProps> {
render() { render() {
const {options, value, onChange, name, label} = this.props; const {options, value, onChange, name, label} = this.props;
@@ -32,14 +33,14 @@ export default class InputEnum extends React.Component {
return <InputMultiInput return <InputMultiInput
name={name} name={name}
options={options} options={options}
value={value || this.props.default} value={(value || this.props.default)!}
onChange={onChange} onChange={onChange}
aria-label={this.props['aria-label'] || label} aria-label={this.props['aria-label'] || label}
/> />
} else { } else {
return <InputSelect return <InputSelect
options={options} options={options}
value={value || this.props.default} value={(value || this.props.default)!}
onChange={onChange} onChange={onChange}
aria-label={this.props['aria-label'] || label} aria-label={this.props['aria-label'] || label}
/> />
@@ -1,17 +1,17 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
import InputAutocomplete from './InputAutocomplete' import InputAutocomplete from './InputAutocomplete'
export default class FieldFont extends React.Component { type FieldFontProps = {
static propTypes = { name: string
value: PropTypes.array, value?: string[]
default: PropTypes.array, default?: string[]
fonts: PropTypes.array, fonts?: unknown[]
style: PropTypes.object, style?: object
onChange: PropTypes.func.isRequired, onChange(...args: unknown[]): unknown
'aria-label': PropTypes.string, 'aria-label'?: string
} };
export default class FieldFont extends React.Component<FieldFontProps> {
static defaultProps = { static defaultProps = {
fonts: [] fonts: []
} }
@@ -28,7 +28,7 @@ export default class FieldFont extends React.Component {
} }
} }
changeFont(idx, newValue) { changeFont(idx: number, newValue: string) {
const changedValues = this.values.slice(0) const changedValues = this.values.slice(0)
changedValues[idx] = newValue changedValues[idx] = newValue
const filteredValues = changedValues const filteredValues = changedValues
@@ -46,7 +46,7 @@ export default class FieldFont extends React.Component {
<InputAutocomplete <InputAutocomplete
aria-label={this.props['aria-label'] || this.props.name} aria-label={this.props['aria-label'] || this.props.name}
value={value} value={value}
options={this.props.fonts.map(f => [f, f])} options={this.props.fonts?.map(f => [f, f])}
onChange={this.changeFont.bind(this, i)} onChange={this.changeFont.bind(this, i)}
/> />
</li> </li>
@@ -1,16 +1,15 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
import classnames from 'classnames' import classnames from 'classnames'
import InputButton from './InputButton'
export default class InputMultiInput extends React.Component { type InputMultiInputProps = {
static propTypes = { name: string
name: PropTypes.string.isRequired, value: string
value: PropTypes.string.isRequired, options: any[]
options: PropTypes.array.isRequired, onChange(...args: unknown[]): unknown
onChange: PropTypes.func.isRequired, 'aria-label'?: string
} };
export default class InputMultiInput extends React.Component<InputMultiInputProps> {
render() { render() {
let options = this.props.options let options = this.props.options
if(options.length > 0 && !Array.isArray(options[0])) { if(options.length > 0 && !Array.isArray(options[0])) {
@@ -25,7 +24,7 @@ export default class InputMultiInput extends React.Component {
> >
<input type="radio" <input type="radio"
name={this.props.name} name={this.props.name}
onChange={e => this.props.onChange(val)} onChange={_e => this.props.onChange(val)}
value={val} value={val}
checked={val === selectedValue} checked={val === selectedValue}
/> />
@@ -1,27 +1,35 @@
import React from 'react' import React, { BaseSyntheticEvent } from 'react'
import PropTypes from 'prop-types'
let IDX = 0; let IDX = 0;
export default class InputNumber extends React.Component { type InputNumberProps = {
static propTypes = { value?: number
value: PropTypes.number, default?: number
default: PropTypes.number, min?: number
min: PropTypes.number, max?: number
max: PropTypes.number, onChange?(...args: unknown[]): unknown
onChange: PropTypes.func, allowRange?: boolean
allowRange: PropTypes.bool, rangeStep?: number
rangeStep: PropTypes.number, wdKey?: string
wdKey: PropTypes.string, required?: boolean
required: PropTypes.bool, "aria-label"?: string
"aria-label": PropTypes.string, };
}
type InputNumberState = {
uuid: number
editing: boolean
editingRange?: boolean
value?: number
dirtyValue?: number
}
export default class InputNumber extends React.Component<InputNumberProps, InputNumberState> {
static defaultProps = { static defaultProps = {
rangeStep: 1 rangeStep: 1
} }
_keyboardEvent: boolean = false;
constructor(props) { constructor(props: InputNumberProps) {
super(props) super(props)
this.state = { this.state = {
uuid: IDX++, uuid: IDX++,
@@ -31,7 +39,7 @@ export default class InputNumber extends React.Component {
} }
} }
static getDerivedStateFromProps(props, state) { static getDerivedStateFromProps(props: InputNumberProps, state: InputNumberState) {
if (!state.editing && props.value !== state.value) { if (!state.editing && props.value !== state.value) {
return { return {
value: props.value, value: props.value,
@@ -41,16 +49,15 @@ export default class InputNumber extends React.Component {
return null; return null;
} }
changeValue(newValue) { changeValue(newValue: number | string | undefined) {
const value = (newValue === "" || newValue === undefined) ? const value = (newValue === "" || newValue === undefined) ?
undefined : undefined : +newValue;
parseFloat(newValue);
const hasChanged = this.props.value !== value; const hasChanged = this.props.value !== value;
if(this.isValid(value) && hasChanged) { if(this.isValid(value) && hasChanged) {
this.props.onChange(value) if (this.props.onChange) this.props.onChange(value)
this.setState({ this.setState({
value: newValue, value: value,
}); });
} }
else if (!this.isValid(value) && hasChanged) { else if (!this.isValid(value) && hasChanged) {
@@ -60,25 +67,25 @@ export default class InputNumber extends React.Component {
} }
this.setState({ this.setState({
dirtyValue: newValue === "" ? undefined : newValue, dirtyValue: newValue === "" ? undefined : value,
}) })
} }
isValid(v) { isValid(v: number | string | undefined) {
if (v === undefined) { if (v === undefined) {
return true; return true;
} }
const value = parseFloat(v) const value = +v;
if(isNaN(value)) { if(isNaN(value)) {
return false return false
} }
if(!isNaN(this.props.min) && value < this.props.min) { if(!isNaN(this.props.min!) && value < this.props.min!) {
return false return false
} }
if(!isNaN(this.props.max) && value > this.props.max) { if(!isNaN(this.props.max!) && value > this.props.max!) {
return false return false
} }
@@ -88,7 +95,7 @@ export default class InputNumber extends React.Component {
resetValue = () => { resetValue = () => {
this.setState({editing: false}); this.setState({editing: false});
// Reset explicitly to default value if value has been cleared // Reset explicitly to default value if value has been cleared
if(this.state.value === "") { if(!this.state.value) {
return; return;
} }
@@ -104,8 +111,8 @@ export default class InputNumber extends React.Component {
} }
} }
onChangeRange = (e) => { onChangeRange = (e: BaseSyntheticEvent<Event, HTMLInputElement, HTMLInputElement>) => {
let value = parseFloat(e.target.value, 10); let value = parseFloat(e.target.value);
const step = this.props.rangeStep; const step = this.props.rangeStep;
let dirtyValue = value; let dirtyValue = value;
@@ -119,11 +126,11 @@ export default class InputNumber extends React.Component {
// for example we might go from 13 to 13.23, however because we know // 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 // that came from a keyboard event we always want to increase by a
// single step value. // single step value.
if (value < this.state.dirtyValue) { if (value < this.state.dirtyValue!) {
value = this.state.value - step; value = this.state.value! - step;
} }
else { else {
value = this.state.value + step value = this.state.value! + step
} }
dirtyValue = value; dirtyValue = value;
} }
@@ -140,10 +147,10 @@ export default class InputNumber extends React.Component {
this._keyboardEvent = false; this._keyboardEvent = false;
// Clamp between min/max // Clamp between min/max
value = Math.max(this.props.min, Math.min(this.props.max, value)); value = Math.max(this.props.min!, Math.min(this.props.max!, value));
this.setState({value, dirtyValue}); this.setState({value, dirtyValue});
this.props.onChange(value); if (this.props.onChange) this.props.onChange(value);
} }
render() { render() {
@@ -196,15 +203,15 @@ export default class InputNumber extends React.Component {
type="text" type="text"
spellCheck="false" spellCheck="false"
className="maputnik-number" className="maputnik-number"
placeholder={this.props.default} placeholder={this.props.default?.toString()}
value={inputValue === undefined ? "" : inputValue} value={inputValue === undefined ? "" : inputValue}
onFocus={e => { onFocus={_e => {
this.setState({editing: true}); this.setState({editing: true});
}} }}
onChange={e => { onChange={e => {
this.changeValue(e.target.value); this.changeValue(e.target.value);
}} }}
onBlur={e => { onBlur={_e => {
this.setState({editing: false}); this.setState({editing: false});
this.resetValue() this.resetValue()
}} }}
@@ -218,7 +225,7 @@ export default class InputNumber extends React.Component {
aria-label={this.props['aria-label']} aria-label={this.props['aria-label']}
spellCheck="false" spellCheck="false"
className="maputnik-number" className="maputnik-number"
placeholder={this.props.default} placeholder={this.props.default?.toString()}
value={value === undefined ? "" : value} value={value === undefined ? "" : value}
onChange={e => this.changeValue(e.target.value)} onChange={e => this.changeValue(e.target.value)}
onFocus={() => { onFocus={() => {
+3 -3
View File
@@ -5,7 +5,7 @@ type InputStringProps = {
value?: string value?: string
style?: object style?: object
default?: string default?: string
onChange(...args: unknown[]): unknown onChange?(...args: unknown[]): unknown
onInput(...args: unknown[]): unknown onInput(...args: unknown[]): unknown
multi?: boolean multi?: boolean
required?: boolean required?: boolean
@@ -83,11 +83,11 @@ export default class InputString extends React.Component<InputStringProps, Input
onBlur: () => { onBlur: () => {
if(this.state.value!==this.props.value) { if(this.state.value!==this.props.value) {
this.setState({editing: false}); this.setState({editing: false});
this.props.onChange(this.state.value); if (this.props.onChange) this.props.onChange(this.state.value);
} }
}, },
onKeyDown: (e) => { onKeyDown: (e) => {
if (e.keyCode === 13) { if (e.keyCode === 13 && this.props.onChange) {
this.props.onChange(this.state.value); this.props.onChange(this.state.value);
} }
}, },