Files
editor/src/components/InputDynamicArray.tsx
T
Harel M a22476cab2 Add lint to CI and fix errors (#853)
Adds lint to CI and fixes errors.
I'm not sure I'm fully proud of all the solutions there.
But there's no lint issues and the lint is being checked as part of the
CI.

---------

Co-authored-by: Yuri Astrakhan <yuriastrakhan@gmail.com>
2023-12-26 23:13:22 +02:00

145 lines
3.8 KiB
TypeScript

import React from 'react'
import capitalize from 'lodash.capitalize'
import {MdDelete} from 'react-icons/md'
import InputString from './InputString'
import InputNumber from './InputNumber'
import InputButton from './InputButton'
import FieldDocLabel from './FieldDocLabel'
import InputEnum from './InputEnum'
import InputUrl from './InputUrl'
export type FieldDynamicArrayProps = {
value?: (string | number | undefined)[]
type?: 'url' | 'number' | 'enum' | 'string'
default?: (string | number | undefined)[]
onChange?(values: (string | number | undefined)[] | undefined): unknown
style?: object
fieldSpec?: {
values?: any
}
'aria-label'?: string
label: string
};
export default class FieldDynamicArray extends React.Component<FieldDynamicArrayProps> {
changeValue(idx: number, newValue: string | number | undefined) {
const values = this.values.slice(0)
values[idx] = newValue
if (this.props.onChange) 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("")
}
if (this.props.onChange) this.props.onChange(values)
}
deleteValue(valueIdx: number) {
const values = this.values.slice(0)
values.splice(valueIdx, 1)
if (this.props.onChange) this.props.onChange(values.length > 0 ? values : undefined);
}
render() {
const inputs = this.values.map((v, i) => {
const deleteValueBtn= <DeleteValueInputButton onClick={this.deleteValue.bind(this, i)} />
let input;
if(this.props.type === 'url') {
input = <InputUrl
value={v as string}
onChange={this.changeValue.bind(this, i)}
aria-label={this.props['aria-label'] || this.props.label}
/>
}
else if (this.props.type === 'number') {
input = <InputNumber
value={v as number}
onChange={this.changeValue.bind(this, i)}
aria-label={this.props['aria-label'] || this.props.label}
/>
}
else if (this.props.type === 'enum') {
const options = Object.keys(this.props.fieldSpec?.values).map(v => [v, capitalize(v)]);
input = <InputEnum
options={options}
value={v as string}
onChange={this.changeValue.bind(this, i)}
aria-label={this.props['aria-label'] || this.props.label}
/>
}
else {
input = <InputString
value={v as string}
onChange={this.changeValue.bind(this, i)}
aria-label={this.props['aria-label'] || this.props.label}
/>
}
return <div
style={this.props.style}
key={i}
className="maputnik-array-block"
>
<div className="maputnik-array-block-action">
{deleteValueBtn}
</div>
<div className="maputnik-array-block-content">
{input}
</div>
</div>
})
return (
<div className="maputnik-array">
{inputs}
<InputButton
className="maputnik-array-add-value"
onClick={this.addValue}
>
Add value
</InputButton>
</div>
);
}
}
type DeleteValueInputButtonProps = {
onClick?(...args: unknown[]): unknown
};
class DeleteValueInputButton extends React.Component<DeleteValueInputButtonProps> {
render() {
return <InputButton
className="maputnik-delete-stop"
onClick={this.props.onClick}
title="Remove array item"
>
<FieldDocLabel
label={<MdDelete />}
/>
</InputButton>
}
}