Line data Source code
1 : import * as React from 'react';
2 : import * as styles from './value_list.module.css';
3 :
4 : import { PlusIcon, XIcon } from './symbol_icon.js';
5 :
6 : import { Dispatch } from '../../utils/variant.js';
7 : import { classNames } from '../../utils/classnames.js';
8 : import { TextInput } from './text_input.js';
9 : import { TextInputAction } from './text_input_action.js';
10 : import { ButtonSize, IconButton } from './button.js';
11 :
12 : export type ValueListElement = string;
13 :
14 : export type UpdateValueList = (prev: ValueListElement[]) => ValueListElement[];
15 :
16 : interface Props {
17 : className?: string;
18 : title: string;
19 : caption?: string;
20 : valueIcon?: React.ElementType;
21 : addButtonLabel: string;
22 : elements: ValueListElement[];
23 : modifyElements: Dispatch<UpdateValueList>;
24 : disabled?: boolean;
25 : readOnly?: boolean;
26 : }
27 :
28 1 : export const ValueListBuilder: React.FC<Props> = (props: Props) => {
29 1 : const appendElement = () => props.modifyElements(list => {
30 1 : const copy = [...list];
31 1 : copy.push("");
32 1 : return copy;
33 1 : });
34 1 : const deleteIndex = (index: number) => props.modifyElements(list => {
35 1 : const copy = [...list];
36 1 : copy.splice(index, 1);
37 1 : return copy;
38 1 : });
39 1 : const modifyElement = (index: number, value: string) => props.modifyElements(list => {
40 1 : const copy = [...list];
41 1 : copy[index] = value;
42 1 : return copy;
43 1 : });
44 :
45 1 : return (
46 1 : <div className={classNames(props.className, styles.list)}>
47 1 : <div className={styles.list_name}>
48 1 : {props.title}
49 1 : </div>
50 1 : {props.caption && (
51 1 : <div className={styles.list_caption}>
52 1 : {props.caption}
53 1 : </div>
54 : )}
55 1 : <IconButton
56 1 : className={styles.add_button}
57 1 : aria-label="Add Entry"
58 1 : onClick={appendElement}
59 1 : disabled={props.disabled}
60 1 : size={ButtonSize.Small}
61 : >
62 1 : <PlusIcon />
63 1 : </IconButton>
64 1 : <div className={styles.list_elements}>
65 1 : {props.elements.map((elem, i) => (
66 1 : <div key={i} className={styles.element}>
67 1 : <TextInput
68 1 : block
69 1 : className={styles.path}
70 1 : value={elem}
71 1 : onChange={(ev: any) => modifyElement(i, ev.target.value)}
72 1 : leadingVisual={props.valueIcon}
73 1 : trailingAction={
74 1 : <TextInputAction
75 1 : aria-label="Clear input"
76 1 : aria-labelledby=""
77 1 : onClick={() => deleteIndex(i)}
78 : >
79 1 : <XIcon />
80 1 : </TextInputAction>
81 : }
82 1 : disabled={props.disabled}
83 1 : readOnly={props.disabled}
84 1 : />
85 1 : </div>))}
86 1 : </div>
87 1 : </div>
88 : );
89 1 : };
|