diff --git a/src/component/elements/EditableColumn.tsx b/src/component/elements/EditableColumn.tsx index bf4e13eb2..f16ef1ab2 100644 --- a/src/component/elements/EditableColumn.tsx +++ b/src/component/elements/EditableColumn.tsx @@ -1,4 +1,6 @@ -import type { CSSProperties, ChangeEvent, KeyboardEvent } from 'react'; +import { Button } from '@blueprintjs/core'; +import styled from '@emotion/styled'; +import type { CSSProperties, KeyboardEvent } from 'react'; import { forwardRef, useCallback, @@ -7,8 +9,41 @@ import { useState, } from 'react'; -import type { InputProps } from './Input.js'; -import Input from './Input.js'; +import { Input2 } from './Input2.js'; +import { NumberInput2 } from './NumberInput2.js'; + +interface OverflowProps { + textOverflowEllipses: boolean; +} + +const Text = styled.span` + display: table-cell; + vertical-align: middle; + width: 100%; + height: 100%; + ${({ textOverflowEllipses }) => + textOverflowEllipses && + ` + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + `} +`; +const Container = styled.span` + display: table; + width: 100%; + min-height: 22px; + height: 100%; + ${({ textOverflowEllipses }) => + textOverflowEllipses && + ` + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + display: inline-flex; + align-items:end; + `} +`; function extractNumber(val: string | number, type: string) { if (type === 'number' && typeof val !== 'number') { @@ -18,37 +53,45 @@ function extractNumber(val: string | number, type: string) { return val; } -interface EditableColumnProps - extends Omit { +function handleMousedown(event) { + event.stopPropagation(); +} + +const style: CSSProperties = { minWidth: 60 }; +const className = 'editable-column'; + +interface BaseEditableColumnProps { + type: 'number' | 'text'; + value: number | string; + validate?: (value?: string | number) => boolean; +} + +interface EditableColumnProps extends BaseEditableColumnProps { onSave?: (element: KeyboardEvent) => void; onEditStart?: (element: boolean) => void; - type?: 'number' | 'text'; editStatus?: boolean; - value: string | number; style?: CSSProperties; - validate?: (value?: string | number) => boolean; - textOverFlowEllipses?: boolean; + textOverflowEllipses?: boolean; + clickType?: 'single' | 'double'; } -const EditableColumn = forwardRef(function EditableColumn( +export const EditableColumn = forwardRef(function EditableColumn( props: EditableColumnProps, ref: any, ) { const { - onSave = () => null, + onSave, value, - type = 'text', + type, style, - onEditStart = () => null, + onEditStart, editStatus = false, - validate = () => true, - textOverFlowEllipses = false, - ...InputProps + validate, + textOverflowEllipses = false, + clickType = 'single', } = props; const [enabled, enableEdit] = useState(); - const [isValid, setValid] = useState(true); - const [val, setVal] = useState(extractNumber(value, type)); useEffect(() => { enableEdit(editStatus); }, [editStatus]); @@ -71,85 +114,131 @@ const EditableColumn = forwardRef(function EditableColumn( function startEditHandler() { globalThis.addEventListener('mousedown', mouseClickCallback); - onEditStart(true); + onEditStart?.(true); enableEdit(true); } - function saveHandler(event: KeyboardEvent) { - const valid = validate(val); - setValid(valid); - // when press Enter or Tab - if (valid && ['Enter', 'Tab'].includes(event.key)) { - onSave(event); - enableEdit(false); - globalThis.removeEventListener('mousedown', mouseClickCallback); - } - // close edit mode if press Enter, Tab or Escape - if (['Escape'].includes(event.key)) { - enableEdit(false); - globalThis.removeEventListener('mousedown', mouseClickCallback); - } + function onConfirm(event: KeyboardEvent) { + onSave?.(event); + enableEdit(false); + globalThis.removeEventListener('mousedown', mouseClickCallback); + } + + function onCancel() { + enableEdit(false); + globalThis.removeEventListener('mousedown', mouseClickCallback); } - function handleChange(e: ChangeEvent) { - setVal(e.target.value); + let clickHandler = {}; + + if (clickType === 'single' && !enabled) { + clickHandler = { onClick: startEditHandler }; + } + + if (clickType === 'double' && !enabled) { + clickHandler = { onDoubleClick: startEditHandler }; } return ( -
{!enabled && ( - - {value}   - + + {value ?? ' '} + )} {enabled && (
- e.stopPropagation()} - {...InputProps} + onConfirm={onConfirm} + onCancel={onCancel} + validate={validate} />
)} -
+ ); }); -export default EditableColumn; +interface EditFiledProps extends BaseEditableColumnProps { + onConfirm: (event: KeyboardEvent) => void; + onCancel: (event?: KeyboardEvent) => void; +} + +function EditFiled(props: EditFiledProps) { + const { value: externalValue, type, onConfirm, onCancel, validate } = props; + + const [isValid, setValid] = useState(true); + const [value, setVal] = useState(extractNumber(externalValue, type)); + + function handleKeydown(event: KeyboardEvent) { + const valid = typeof validate === 'function' ? validate(value) : true; + setValid(valid); + // when press Enter or Tab + if (valid && ['Enter', 'Tab'].includes(event.key)) { + onConfirm(event); + } + // close edit mode if press Enter, Tab or Escape + if (['Escape'].includes(event.key)) { + onCancel(event); + } + } + + function handleChange(value: string | number) { + setVal(value); + } + + const intent = !isValid ? 'danger' : 'none'; + + const rightElement = ( +