|
@@ -0,0 +1,87 @@
|
|
|
+import React from 'react';
|
|
|
+import { InputNumber, Select, Space, SpaceProps } from 'antd';
|
|
|
+import type { InputNumberProps } from 'antd/es/input-number';
|
|
|
+import type { SelectProps } from 'antd/es/select';
|
|
|
+
|
|
|
+const { Option } = Select;
|
|
|
+
|
|
|
+export interface NumberUnitOption {
|
|
|
+ label: React.ReactNode;
|
|
|
+ value: string;
|
|
|
+}
|
|
|
+
|
|
|
+export interface NumberUnitValue {
|
|
|
+ number?: number;
|
|
|
+ unit?: string;
|
|
|
+}
|
|
|
+export type NumberWithUnitProps = SpaceProps & {
|
|
|
+ value?: NumberUnitValue;
|
|
|
+ onChange?: (next: NumberUnitValue) => void;
|
|
|
+ numberClassName?: string;
|
|
|
+ unitClassName?: string;
|
|
|
+ className?: string;
|
|
|
+ options: NumberUnitOption[];
|
|
|
+ defaultUnit?: string;
|
|
|
+ defaultNumber?: number;
|
|
|
+ numberProps?: Partial<InputNumberProps>;
|
|
|
+ selectProps?: Partial<SelectProps>;
|
|
|
+};
|
|
|
+
|
|
|
+const NumberWithUnit: React.FC<NumberWithUnitProps> = ({
|
|
|
+ value = {},
|
|
|
+ onChange,
|
|
|
+ numberClassName,
|
|
|
+ unitClassName,
|
|
|
+ className,
|
|
|
+ options,
|
|
|
+ defaultUnit,
|
|
|
+ defaultNumber,
|
|
|
+ numberProps,
|
|
|
+ selectProps,
|
|
|
+ onBlur,
|
|
|
+ ...rest // ← 这里会收到、style 等
|
|
|
+}) => {
|
|
|
+ const unit = value?.unit ?? defaultUnit ?? undefined;
|
|
|
+
|
|
|
+ const triggerChange = (changed: Partial<NumberUnitValue>) => {
|
|
|
+ onChange?.({ ...value, ...changed });
|
|
|
+ };
|
|
|
+
|
|
|
+ return (
|
|
|
+ <>
|
|
|
+ <style>{`
|
|
|
+ .my-space .ant-space-item:nth-child(1) {
|
|
|
+ width: 70%;
|
|
|
+ }
|
|
|
+ .my-space .ant-space-item:nth-child(2) {
|
|
|
+ width: 30%;
|
|
|
+ }
|
|
|
+ `}</style>
|
|
|
+ <Space {...rest} className={`${className} my-space`}>
|
|
|
+ <InputNumber
|
|
|
+ className={numberClassName}
|
|
|
+ value={value?.number}
|
|
|
+ onChange={(n) =>
|
|
|
+ triggerChange({ number: typeof n === 'number' ? n : undefined })
|
|
|
+ }
|
|
|
+ {...numberProps}
|
|
|
+ defaultValue={defaultNumber}
|
|
|
+ onBlur={onBlur}
|
|
|
+ />
|
|
|
+ <Select
|
|
|
+ className={unitClassName}
|
|
|
+ value={unit}
|
|
|
+ onChange={(u) => triggerChange({ unit: u })}
|
|
|
+ {...selectProps}
|
|
|
+ >
|
|
|
+ {options.map((opt) => (
|
|
|
+ <Option key={opt.value} value={opt.value}>
|
|
|
+ {opt.label}
|
|
|
+ </Option>
|
|
|
+ ))}
|
|
|
+ </Select>
|
|
|
+ </Space>
|
|
|
+ </>
|
|
|
+ );
|
|
|
+};
|
|
|
+export default NumberWithUnit;
|