rtgk-screen-web/components/client/FormItem.js

149 lines
3.6 KiB
JavaScript

import React, {
useMemo,
} from "react";
export const FormItem = React.memo((props) => {
const {
title,
value = "",
readonly = true,
horizontal = true,
type,
...otherProps
} = props;
const valueMemo = useMemo(() => {
if (readonly) {
if (["", undefined, null].includes(value)) return "-";
return value;
}
if (type === "number") {
return <FormItemNumber value={value + ""} {...otherProps} />;
}
return value;
}, [readonly, value, type, otherProps]);
return (
<div className={"form-item " + (horizontal ? "horizontal" : "vertical")}>
<div className="label">{title}</div>
<div className="value">{valueMemo}</div>
<style jsx>{`
.form-item {
line-height: 36px;
margin-bottom: 32px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.form-item.horizontal {
height: 36px;
}
.form-item.horizontal .label,
.form-item.horizontal .value {
display: inline;
vertical-align: middle;
}
.form-item.horizontal .label {
margin-right: 16px;
}
.form-item.vertical {
height: 88px;
}
.form-item.vertical .label,
.form-item.vertical .value {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.form-item.vertical .label {
margin-bottom: 8px;
}
.form-item .label {
font-size: 20px;
color: rgb(0 0 0 / 45%);
}
.form-item .value {
font-size: 24px;
color: rgb(0 0 0 / 85%);
font-weight: bold;
}
`}</style>
</div>
);
});
const FormItemNumber = React.memo((props) => {
const { value, onChange = () => {}, min } = props;
const onInputChange = (e) => {
onChange(e.target.value);
};
const onInputBlur = (e) => {
let res = parseFloat(e.target.value);
if (isNaN(res)) res = "-";
onChange(res + "");
};
const onBtnClick = (add) => {
let res = parseFloat(value);
if (isNaN(res)) res = add;
res = res + add;
if (min !== undefined && res < min) res = min;
onChange(res + "");
};
const btnDisabled = useMemo(() => [value <= min], [value, min]);
return (
<div className="input-number">
<div
className={"btn" + (btnDisabled[0] ? " disabled" : "")}
onClick={() => value > min && onBtnClick(-1)}
>
-
</div>
<input
className="input-number-input"
type="text"
value={value}
onChange={onInputChange}
onBlur={onInputBlur}
/>
<div className="btn" onClick={() => onBtnClick(1)}>
+
</div>
<style jsx>{`
.btn,
.input-number-input {
height: 36px;
line-height: 30px;
display: inline-block;
vertical-align: middle;
text-align: center;
background: #f5f5f5;
}
.input-number-input {
outline: none;
border: 1px solid transparent;
box-shadow: none;
font-size: 24px;
padding: 0 12px;
width: 120px;
margin: 0 3px;
}
.input-number-input:focus {
border-color: #0285ff;
}
.btn {
width: 36px;
font-size: 32px;
color: #999;
cursor: pointer;
user-select: none;
}
.btn.disabled {
color: #ccc;
cursor: not-allowed;
}
`}</style>
</div>
);
});