Files
vscode-front-matter/src/panelWebView/components/Fields/ListField.tsx
T
2022-06-03 15:58:19 +02:00

135 lines
3.9 KiB
TypeScript

import { PencilIcon, TrashIcon, ViewListIcon } from '@heroicons/react/outline';
import * as React from 'react';
import { useCallback, useEffect, useRef } from 'react';
import { VsLabel } from '../VscodeComponents';
export interface IListFieldProps {
label: string;
value: string[] | null;
onChange: (value: string | string[]) => void;
}
export const ListField: React.FunctionComponent<IListFieldProps> = ({ label, value, onChange }: React.PropsWithChildren<IListFieldProps>) => {
const [ text, setText ] = React.useState<string | null>("");
const [ list, setList ] = React.useState<string[] | null>(null);
const [ itemToEdit, setItemToEdit ] = React.useState<number | null>(null);
const inputRef = useRef<HTMLInputElement>(null);
const onTextChange = (txtValue: string) => {
setText(txtValue);
};
const onSaveForm = useCallback(() => {
if (itemToEdit !== null) {
if (list && text) {
const newList = [...(list || [])];
newList[itemToEdit] = text;
setList(newList);
onChange(newList);
}
} else {
if (text) {
const newList = list ? [ ...list, text ] : [ text ];
setList(newList);
onChange(newList);
}
}
onCancelForm();
}, [list, text]);
const onEdit = useCallback((index: number) => {
setItemToEdit(index);
setText(list ? list[index] : "");
inputRef.current?.focus();
}, [list]);
const onCancelForm = useCallback(() => {
setText("");
setItemToEdit(null);
}, []);
const onDelete = useCallback((index: number) => {
if (list) {
const newList = [...list];
newList.splice(index, 1);
setList(newList);
onChange(newList);
}
}, [list]);
useEffect(() => {
if (value) {
if (typeof value === "string") {
setList([value]);
} else {
setList(value);
}
}
}, [value]);
let isValid = true;
return (
<div className={`list_field`}>
<VsLabel>
<div className={`metadata_field__label`}>
<ViewListIcon style={{ width: "16px", height: "16px" }} /> <span style={{ lineHeight: "16px"}}>{label}</span>
</div>
</VsLabel>
<input
ref={inputRef}
className={`metadata_field__input`}
value={text || ""}
onChange={(e) => onTextChange(e.currentTarget.value)}
onKeyDown={(e) => {
if (e.key === "Enter") {
onSaveForm();
}
}}
style={{
border: "1px solid var(--vscode-inputValidation-infoBorder)"
}} />
<div className={`list_field__form__buttons`}>
<button
className={`list_field__form__button__save`}
title={`Save`}
onClick={onSaveForm}
disabled={!text}>
{itemToEdit !== null ? `Update` : `Add`}
</button>
<button
className={`list_field__form__button__cancel`}
title={`Cancel`}
onClick={onCancelForm}>
Cancel
</button>
</div>
<ul className='list_field__list'>
{
list && list.length > 0 && list.map((item, index) => (
<li className='list_field__list__item' key={index}>
<div>
{item}
</div>
<div>
<button title='Edit record' className='list_field__list__button list_field__list__button_edit' onClick={() => onEdit(index)}>
<PencilIcon className='list_field__list__button_icon' />
<span className='sr-only'>Edit</span>
</button>
<button title='Delete record' className='list_field__list__button list_field__list__button_delete' onClick={() => onDelete(index)}>
<TrashIcon className='list_field__list__button_icon' />
<span className='sr-only'>Delete</span>
</button>
</div>
</li>
))
}
</ul>
</div>
);
};