Files
element-web/src/components/views/elements/EditableItemList.tsx
Michael Telatynski 01304439ee Make tsc faster again (#28678)
* Stash initial work to bring TSC from over 6 mins to under 1 minute

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Stabilise types

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Fix incorrect props to AccessibleButton

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Swap AccessibleButton element types to match the props they provide

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Changed my mind, remove spurious previously ignored props

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Update snapshots

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

---------

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2024-12-06 17:49:32 +00:00

164 lines
5.0 KiB
TypeScript

/*
Copyright 2024 New Vector Ltd.
Copyright 2017-2021 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
Please see LICENSE files in the repository root for full details.
*/
import React, { ChangeEvent } from "react";
import { _t } from "../../../languageHandler";
import Field from "./Field";
import AccessibleButton, { ButtonEvent } from "./AccessibleButton";
interface IItemProps {
index: number;
value?: string;
onRemove?(index: number): void;
}
interface IItemState {
verifyRemove: boolean;
}
export class EditableItem extends React.Component<IItemProps, IItemState> {
public state = {
verifyRemove: false,
};
private onRemove = (e: ButtonEvent): void => {
e.stopPropagation();
e.preventDefault();
this.setState({ verifyRemove: true });
};
private onDontRemove = (e: ButtonEvent): void => {
e.stopPropagation();
e.preventDefault();
this.setState({ verifyRemove: false });
};
private onActuallyRemove = (e: ButtonEvent): void => {
e.stopPropagation();
e.preventDefault();
if (this.props.onRemove) this.props.onRemove(this.props.index);
this.setState({ verifyRemove: false });
};
public render(): React.ReactNode {
if (this.state.verifyRemove) {
return (
<div className="mx_EditableItem">
<span className="mx_EditableItem_promptText">{_t("common|are_you_sure")}</span>
<AccessibleButton
onClick={this.onActuallyRemove}
kind="primary_sm"
className="mx_EditableItem_confirmBtn"
>
{_t("action|yes")}
</AccessibleButton>
<AccessibleButton
onClick={this.onDontRemove}
kind="danger_sm"
className="mx_EditableItem_confirmBtn"
>
{_t("action|no")}
</AccessibleButton>
</div>
);
}
return (
<div className="mx_EditableItem">
<div
onClick={this.onRemove}
className="mx_EditableItem_delete"
title={_t("action|remove")}
role="button"
/>
<span className="mx_EditableItem_item">{this.props.value}</span>
</div>
);
}
}
interface IProps {
id: string;
items: string[];
itemsLabel?: string;
noItemsLabel?: string;
placeholder?: string;
newItem?: string;
canEdit?: boolean;
canRemove?: boolean;
suggestionsListId?: string;
onItemAdded?(item?: string): void;
onItemRemoved?(index: number): void;
onNewItemChanged?(item: string): void;
}
export default class EditableItemList<P = {}> extends React.PureComponent<IProps & P> {
protected onItemAdded = (e: ButtonEvent): void => {
e.stopPropagation();
e.preventDefault();
this.props.onItemAdded?.(this.props.newItem);
};
protected onItemRemoved = (index: number): void => {
this.props.onItemRemoved?.(index);
};
protected onNewItemChanged = (e: ChangeEvent<HTMLInputElement>): void => {
this.props.onNewItemChanged?.(e.target.value);
};
protected renderNewItemField(): JSX.Element {
return (
<form
onSubmit={this.onItemAdded}
autoComplete="off"
noValidate={true}
className="mx_EditableItemList_newItem"
>
<Field
label={this.props.placeholder}
type="text"
autoComplete="off"
value={this.props.newItem || ""}
onChange={this.onNewItemChanged}
list={this.props.suggestionsListId}
/>
<AccessibleButton onClick={this.onItemAdded} kind="primary" disabled={!this.props.newItem}>
{_t("action|add")}
</AccessibleButton>
</form>
);
}
public render(): React.ReactNode {
const editableItems = this.props.items.map((item, index) => {
if (!this.props.canRemove) {
return <li key={item}>{item}</li>;
}
return <EditableItem key={item} index={index} value={item} onRemove={this.onItemRemoved} />;
});
const editableItemsSection = this.props.canRemove ? editableItems : <ul>{editableItems}</ul>;
const label = this.props.items.length > 0 ? this.props.itemsLabel : this.props.noItemsLabel;
return (
<div className="mx_EditableItemList" id={this.props.id}>
<div className="mx_EditableItemList_label">{label}</div>
{editableItemsSection}
{this.props.canEdit ? this.renderNewItemField() : <div />}
</div>
);
}
}