@ldkj/web-ui 0.15.0 → 0.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,9 +1,106 @@
1
+ import * as React from "react";
1
2
  import { type InputProps } from "@/components/form/input";
3
+ import { type SxProps } from "@/styling";
2
4
  export type AutoCompleteOption = {
3
- label: string;
5
+ label: React.ReactNode;
4
6
  value: string;
7
+ disabled?: boolean;
8
+ description?: React.ReactNode;
9
+ keywords?: string[];
10
+ textValue?: string;
5
11
  };
6
- export type AutoCompleteProps = Omit<InputProps, "list"> & {
12
+ export type AutoCompleteValueChangeReason = "input" | "select";
13
+ export type AutoCompleteValueChangeMeta = {
14
+ reason: AutoCompleteValueChangeReason;
15
+ option?: AutoCompleteOption;
16
+ event: React.ChangeEvent<HTMLInputElement>;
17
+ };
18
+ export type AutoCompleteFilterOption = (option: AutoCompleteOption, keyword: string) => boolean;
19
+ export type AutoCompleteRenderOptionState = {
20
+ active: boolean;
21
+ disabled: boolean;
22
+ inputValue: string;
23
+ selected: boolean;
24
+ };
25
+ export type AutoCompleteProps = Omit<InputProps, "defaultValue" | "list" | "onChange" | "value"> & {
7
26
  options?: AutoCompleteOption[];
27
+ value?: string | number;
28
+ defaultValue?: string | number;
29
+ onChange?: React.ChangeEventHandler<HTMLInputElement>;
30
+ /**
31
+ * 返回输入值变化。`reason` 为 `select` 时表示来自建议项选择。
32
+ */
33
+ onValueChange?: (value: string, meta: AutoCompleteValueChangeMeta) => void;
34
+ /**
35
+ * 点击或键盘确认建议项时触发。
36
+ */
37
+ onOptionSelect?: (option: AutoCompleteOption, event: React.KeyboardEvent<HTMLInputElement> | React.MouseEvent<HTMLDivElement>) => void;
38
+ /**
39
+ * 自定义过滤逻辑。传入 `false` 时不做本地过滤。
40
+ */
41
+ filterOption?: AutoCompleteFilterOption | false;
42
+ /**
43
+ * 输入框聚焦时是否立即展示建议面板。
44
+ */
45
+ openOnFocus?: boolean;
46
+ /**
47
+ * 没有匹配项时的提示内容。传入 `null` 可隐藏空状态面板。
48
+ */
49
+ emptyText?: React.ReactNode;
50
+ /**
51
+ * 自定义建议项渲染。
52
+ */
53
+ renderOption?: (option: AutoCompleteOption, state: AutoCompleteRenderOptionState) => React.ReactNode;
54
+ rootClassName?: string;
55
+ rootStyle?: React.CSSProperties;
56
+ rootSx?: SxProps;
57
+ dropdownClassName?: string;
58
+ dropdownStyle?: React.CSSProperties;
59
+ dropdownSx?: SxProps;
60
+ optionClassName?: string;
61
+ optionStyle?: React.CSSProperties;
62
+ optionSx?: SxProps;
8
63
  };
9
- export declare function AutoComplete(props: AutoCompleteProps): import("react/jsx-runtime").JSX.Element;
64
+ /**
65
+ * AutoComplete 是带建议面板的文本输入组件。组件使用自绘 listbox 替代原生
66
+ * datalist,使下拉样式、键盘交互和空状态与本库表单组件保持一致。
67
+ */
68
+ export declare const AutoComplete: React.ForwardRefExoticComponent<Omit<InputProps, "value" | "list" | "defaultValue" | "onChange"> & {
69
+ options?: AutoCompleteOption[];
70
+ value?: string | number;
71
+ defaultValue?: string | number;
72
+ onChange?: React.ChangeEventHandler<HTMLInputElement>;
73
+ /**
74
+ * 返回输入值变化。`reason` 为 `select` 时表示来自建议项选择。
75
+ */
76
+ onValueChange?: (value: string, meta: AutoCompleteValueChangeMeta) => void;
77
+ /**
78
+ * 点击或键盘确认建议项时触发。
79
+ */
80
+ onOptionSelect?: (option: AutoCompleteOption, event: React.KeyboardEvent<HTMLInputElement> | React.MouseEvent<HTMLDivElement>) => void;
81
+ /**
82
+ * 自定义过滤逻辑。传入 `false` 时不做本地过滤。
83
+ */
84
+ filterOption?: AutoCompleteFilterOption | false;
85
+ /**
86
+ * 输入框聚焦时是否立即展示建议面板。
87
+ */
88
+ openOnFocus?: boolean;
89
+ /**
90
+ * 没有匹配项时的提示内容。传入 `null` 可隐藏空状态面板。
91
+ */
92
+ emptyText?: React.ReactNode;
93
+ /**
94
+ * 自定义建议项渲染。
95
+ */
96
+ renderOption?: (option: AutoCompleteOption, state: AutoCompleteRenderOptionState) => React.ReactNode;
97
+ rootClassName?: string;
98
+ rootStyle?: React.CSSProperties;
99
+ rootSx?: SxProps;
100
+ dropdownClassName?: string;
101
+ dropdownStyle?: React.CSSProperties;
102
+ dropdownSx?: SxProps;
103
+ optionClassName?: string;
104
+ optionStyle?: React.CSSProperties;
105
+ optionSx?: SxProps;
106
+ } & React.RefAttributes<HTMLInputElement>>;
@@ -1,12 +1,133 @@
1
+ import * as React from "react";
2
+ import { type PopoverContentProps } from "@/components/interact/popover";
3
+ import { type SxProps } from "@/styling";
4
+ export type CascaderFieldNames = {
5
+ label?: string;
6
+ value?: string;
7
+ children?: string;
8
+ disabled?: string;
9
+ isLeaf?: string;
10
+ loading?: string;
11
+ };
1
12
  export type CascaderOption = {
2
- label: string;
3
- value: string;
13
+ label?: React.ReactNode;
14
+ value?: string;
4
15
  children?: CascaderOption[];
16
+ disabled?: boolean;
17
+ isLeaf?: boolean;
18
+ loading?: boolean;
19
+ className?: string;
20
+ class?: string;
21
+ style?: React.CSSProperties;
22
+ sx?: SxProps;
23
+ } & Record<string, unknown>;
24
+ export type CascaderValue = string[];
25
+ export type CascaderValueChangeReason = "select" | "clear";
26
+ export type CascaderValueChangeMeta = {
27
+ reason: CascaderValueChangeReason;
28
+ path: string[];
29
+ options: CascaderOption[];
30
+ option?: CascaderOption;
31
+ labels: React.ReactNode[];
32
+ event?: React.SyntheticEvent;
33
+ };
34
+ export type CascaderLoadDataMeta = {
35
+ option: CascaderOption;
36
+ path: string[];
37
+ options: CascaderOption[];
5
38
  };
6
- export type CascaderProps = {
39
+ export type CascaderRenderOptionState = {
40
+ active: boolean;
41
+ checked: boolean;
42
+ disabled: boolean;
43
+ hasChildren: boolean;
44
+ isLeaf: boolean;
45
+ level: number;
46
+ loading: boolean;
47
+ path: string[];
48
+ selected: boolean;
49
+ };
50
+ export type CascaderRef = {
51
+ focus: () => void;
52
+ blur: () => void;
53
+ open: () => void;
54
+ close: () => void;
55
+ clear: () => void;
56
+ getValue: () => CascaderValue;
57
+ };
58
+ export type CascaderProps = Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "children" | "value" | "defaultValue" | "onChange"> & {
59
+ class?: string;
60
+ sx?: SxProps;
7
61
  options?: CascaderOption[];
8
- value?: string;
9
- placeholder?: string;
10
- onValueChange?: (value: string) => void;
62
+ value?: CascaderValue;
63
+ defaultValue?: CascaderValue;
64
+ onValueChange?: (value: CascaderValue, meta: CascaderValueChangeMeta) => void;
65
+ onOpenChange?: (open: boolean) => void;
66
+ open?: boolean;
67
+ defaultOpen?: boolean;
68
+ placeholder?: React.ReactNode;
69
+ separator?: React.ReactNode;
70
+ displayRender?: (labels: React.ReactNode[], options: CascaderOption[]) => React.ReactNode;
71
+ renderOption?: (option: CascaderOption, state: CascaderRenderOptionState) => React.ReactNode;
72
+ fieldNames?: CascaderFieldNames;
73
+ changeOnSelect?: boolean;
74
+ expandTrigger?: "click" | "hover";
75
+ clearable?: boolean;
76
+ readOnly?: boolean;
77
+ required?: boolean;
78
+ loadData?: (selectedOptions: CascaderOption[], meta: CascaderLoadDataMeta) => void | Promise<void>;
79
+ contentWidth?: number | string;
80
+ maxPanelHeight?: number | string;
81
+ side?: PopoverContentProps["side"];
82
+ align?: PopoverContentProps["align"];
83
+ sideOffset?: number;
84
+ contentClassName?: string;
85
+ contentClass?: string;
86
+ contentStyle?: React.CSSProperties;
87
+ contentSx?: SxProps;
88
+ optionClassName?: string;
89
+ optionClass?: string;
90
+ optionStyle?: React.CSSProperties;
91
+ optionSx?: SxProps;
11
92
  };
12
- export declare function Cascader(props: CascaderProps): import("react/jsx-runtime").JSX.Element;
93
+ /**
94
+ * Cascader 是多级联动选择器,支持受控/非受控、路径值、清除、懒加载与自定义选项渲染。
95
+ *
96
+ * 组件默认按路径数组提交值,例如 `["zhejiang", "hangzhou"]`。
97
+ * 如果开启 `changeOnSelect`,选择中间层节点也会立即提交当前路径。
98
+ */
99
+ export declare const Cascader: React.ForwardRefExoticComponent<Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "value" | "children" | "defaultValue" | "onChange"> & {
100
+ class?: string;
101
+ sx?: SxProps;
102
+ options?: CascaderOption[];
103
+ value?: CascaderValue;
104
+ defaultValue?: CascaderValue;
105
+ onValueChange?: (value: CascaderValue, meta: CascaderValueChangeMeta) => void;
106
+ onOpenChange?: (open: boolean) => void;
107
+ open?: boolean;
108
+ defaultOpen?: boolean;
109
+ placeholder?: React.ReactNode;
110
+ separator?: React.ReactNode;
111
+ displayRender?: (labels: React.ReactNode[], options: CascaderOption[]) => React.ReactNode;
112
+ renderOption?: (option: CascaderOption, state: CascaderRenderOptionState) => React.ReactNode;
113
+ fieldNames?: CascaderFieldNames;
114
+ changeOnSelect?: boolean;
115
+ expandTrigger?: "click" | "hover";
116
+ clearable?: boolean;
117
+ readOnly?: boolean;
118
+ required?: boolean;
119
+ loadData?: (selectedOptions: CascaderOption[], meta: CascaderLoadDataMeta) => void | Promise<void>;
120
+ contentWidth?: number | string;
121
+ maxPanelHeight?: number | string;
122
+ side?: PopoverContentProps["side"];
123
+ align?: PopoverContentProps["align"];
124
+ sideOffset?: number;
125
+ contentClassName?: string;
126
+ contentClass?: string;
127
+ contentStyle?: React.CSSProperties;
128
+ contentSx?: SxProps;
129
+ optionClassName?: string;
130
+ optionClass?: string;
131
+ optionStyle?: React.CSSProperties;
132
+ optionSx?: SxProps;
133
+ } & React.RefAttributes<CascaderRef>>;
@@ -0,0 +1,67 @@
1
+ import * as React from "react";
2
+ import { type SxProps } from "@/styling";
3
+ import { type FormCallbacks, type FormInstance, type FormNamePath, type FormRule, type FormValidateTrigger, type FormValues, useForm, useFormInstance, useFormValue, useFormWatch } from "./useForm";
4
+ type AnyRecord = Record<string, unknown>;
5
+ /**
6
+ * Form 组件属性。默认保持原生 `form` 语义,传入增强回调或 `form` 实例后启用状态管理提交链路。
7
+ */
8
+ export type FormProps<TValues extends FormValues = FormValues> = Omit<React.FormHTMLAttributes<HTMLFormElement>, "onSubmit"> & FormCallbacks<TValues> & {
9
+ class?: string;
10
+ form?: FormInstance<TValues>;
11
+ initialValues?: Partial<TValues>;
12
+ nativeSubmit?: boolean;
13
+ onSubmit?: React.FormEventHandler<HTMLFormElement>;
14
+ sx?: SxProps;
15
+ };
16
+ /**
17
+ * `Form.Item` render props,用于自定义字段渲染时读取当前值、meta 和表单实例。
18
+ */
19
+ export type FormItemRenderProps<TValues extends FormValues = FormValues> = {
20
+ form: FormInstance<TValues>;
21
+ value: unknown;
22
+ values: TValues;
23
+ meta: ReturnType<FormInstance<TValues>["getFieldMeta"]>;
24
+ };
25
+ /**
26
+ * `Form.Item` 属性。通过 `name` 注册字段,并把子控件自动接入 `useForm` 状态层。
27
+ */
28
+ export type FormItemProps<TValues extends FormValues = FormValues> = Omit<React.HTMLAttributes<HTMLDivElement>, "children" | "onChange"> & {
29
+ children?: React.ReactNode | ((props: FormItemRenderProps<TValues>) => React.ReactNode);
30
+ class?: string;
31
+ controlClassName?: string;
32
+ controlStyle?: React.CSSProperties;
33
+ dependencies?: FormNamePath[];
34
+ extra?: React.ReactNode;
35
+ getValueFromEvent?: (...args: unknown[]) => unknown;
36
+ getValueProps?: (value: unknown) => AnyRecord;
37
+ help?: React.ReactNode;
38
+ initialValue?: unknown;
39
+ label?: React.ReactNode;
40
+ labelClassName?: string;
41
+ labelStyle?: React.CSSProperties;
42
+ name?: FormNamePath;
43
+ noStyle?: boolean;
44
+ preserve?: boolean;
45
+ required?: boolean;
46
+ rules?: FormRule<TValues>[];
47
+ sx?: SxProps;
48
+ trigger?: string;
49
+ validateFirst?: boolean;
50
+ validateStatus?: "error" | "success" | "warning" | "validating";
51
+ validateTrigger?: FormValidateTrigger;
52
+ valuePropName?: string;
53
+ };
54
+ declare function FormItem<TValues extends FormValues = FormValues>(props: FormItemProps<TValues>): import("react/jsx-runtime").JSX.Element;
55
+ declare namespace FormItem {
56
+ var displayName: string;
57
+ }
58
+ type FormComponent = (<TValues extends FormValues = FormValues>(props: FormProps<TValues>) => React.ReactElement) & {
59
+ displayName?: string;
60
+ Item: typeof FormItem;
61
+ useForm: typeof useForm;
62
+ useFormInstance: typeof useFormInstance;
63
+ useFormValue: typeof useFormValue;
64
+ useFormWatch: typeof useFormWatch;
65
+ };
66
+ declare const Form: FormComponent;
67
+ export { Form, FormItem, useForm, useFormInstance, useFormValue, useFormWatch, };
@@ -0,0 +1,2 @@
1
+ export * from "./Form";
2
+ export type { FormCallbacks, FormErrorField, FormFieldData, FormFieldMeta, FormFinishFailedInfo, FormInstance, FormNamePath, FormRule, FormValidateOptions, FormValidateTrigger, FormValues, } from "./useForm";
@@ -0,0 +1,157 @@
1
+ import * as React from "react";
2
+ /**
3
+ * 表单字段路径,支持字符串、数字或数组路径,例如 `user.name` 或 `["user", "name"]`。
4
+ */
5
+ export type FormNamePath = string | number | readonly (string | number)[];
6
+ /**
7
+ * 表单值对象类型。
8
+ */
9
+ export type FormValues = Record<string, unknown>;
10
+ /**
11
+ * 字段校验触发器名称,通常是 `onChange`、`onBlur` 或控件自定义事件。
12
+ */
13
+ export type FormValidateTrigger = string | readonly string[];
14
+ /**
15
+ * 字段校验规则,支持必填、值转换和同步/异步自定义校验。
16
+ */
17
+ export type FormRule<TValues extends FormValues = FormValues> = {
18
+ required?: boolean;
19
+ message?: React.ReactNode;
20
+ validateTrigger?: FormValidateTrigger;
21
+ transform?: (value: unknown) => unknown;
22
+ validator?: (value: unknown, values: TValues, form: FormInstance<TValues>) => void | boolean | React.ReactNode | Promise<void | boolean | React.ReactNode>;
23
+ };
24
+ /**
25
+ * 字段状态信息,用于展示 touched、validating 与错误文案。
26
+ */
27
+ export type FormFieldMeta = {
28
+ touched: boolean;
29
+ validating: boolean;
30
+ errors: React.ReactNode[];
31
+ };
32
+ /**
33
+ * 字段数据快照,用于 `setFields` 与 `onFieldsChange`。
34
+ */
35
+ export type FormFieldData = {
36
+ name: FormNamePath;
37
+ value?: unknown;
38
+ touched?: boolean;
39
+ validating?: boolean;
40
+ errors?: React.ReactNode[];
41
+ };
42
+ /**
43
+ * 校验失败字段信息。
44
+ */
45
+ export type FormErrorField = {
46
+ name: FormNamePath;
47
+ errors: React.ReactNode[];
48
+ };
49
+ /**
50
+ * 表单提交失败回调参数。
51
+ */
52
+ export type FormFinishFailedInfo<TValues extends FormValues = FormValues> = {
53
+ values: TValues;
54
+ errorFields: FormErrorField[];
55
+ outOfDate: boolean;
56
+ };
57
+ /**
58
+ * 表单增强回调集合。
59
+ */
60
+ export type FormCallbacks<TValues extends FormValues = FormValues> = {
61
+ onValuesChange?: (changedValues: Partial<TValues>, values: TValues) => void;
62
+ onFieldsChange?: (changedFields: FormFieldData[], fields: FormFieldData[]) => void;
63
+ onFinish?: (values: TValues) => void;
64
+ onFinishFailed?: (info: FormFinishFailedInfo<TValues>) => void;
65
+ };
66
+ /**
67
+ * 校验选项,内部校验可指定字段、触发器和仅校验模式。
68
+ */
69
+ export type FormValidateOptions = {
70
+ names?: FormNamePath[];
71
+ trigger?: string;
72
+ validateOnly?: boolean;
73
+ };
74
+ type FormFieldEntity<TValues extends FormValues = FormValues> = {
75
+ name: FormNamePath;
76
+ rules: FormRule<TValues>[];
77
+ validateTrigger?: FormValidateTrigger;
78
+ dependencies: FormNamePath[];
79
+ validateFirst?: boolean;
80
+ };
81
+ type FormSetValueOptions = {
82
+ touched?: boolean;
83
+ trigger?: string;
84
+ source?: "internal" | "external";
85
+ };
86
+ type FormInternalHooks<TValues extends FormValues = FormValues> = {
87
+ getStoreSnapshot: () => TValues;
88
+ getMetaSnapshot: (name: FormNamePath) => FormFieldMeta;
89
+ setCallbacks: (callbacks: FormCallbacks<TValues>) => void;
90
+ setInitialValues: (values: Partial<TValues> | undefined, init: boolean) => void;
91
+ registerField: (entity: FormFieldEntity<TValues>) => (options?: {
92
+ preserve?: boolean;
93
+ }) => void;
94
+ setFieldValue: (name: FormNamePath, value: unknown, options?: FormSetValueOptions) => void;
95
+ validateFields: (names?: FormNamePath[], options?: Pick<FormValidateOptions, "trigger" | "validateOnly">) => Promise<TValues>;
96
+ };
97
+ /**
98
+ * 表单实例 API,用于读取、写入、重置、校验、提交和订阅表单状态。
99
+ */
100
+ export type FormInstance<TValues extends FormValues = FormValues> = {
101
+ getFieldValue: (name: FormNamePath) => unknown;
102
+ getFieldsValue: (names?: FormNamePath[]) => TValues;
103
+ getFieldError: (name: FormNamePath) => React.ReactNode[];
104
+ getFieldsError: (names?: FormNamePath[]) => FormErrorField[];
105
+ getFieldMeta: (name: FormNamePath) => FormFieldMeta;
106
+ isFieldTouched: (name: FormNamePath) => boolean;
107
+ isFieldsTouched: (names?: FormNamePath[]) => boolean;
108
+ setFieldValue: (name: FormNamePath, value: unknown) => void;
109
+ setFieldsValue: (values: Partial<TValues>) => void;
110
+ setFields: (fields: FormFieldData[]) => void;
111
+ resetFields: (names?: FormNamePath[]) => void;
112
+ validateFields: (names?: FormNamePath[]) => Promise<TValues>;
113
+ submit: () => Promise<void>;
114
+ subscribe: (listener: () => void) => () => void;
115
+ __INTERNAL__: FormInternalHooks<TValues>;
116
+ };
117
+ /**
118
+ * Form 内部上下文,供 `Form.Item` 和表单 hooks 读取当前表单实例。
119
+ */
120
+ export declare const FormContext: React.Context<FormInstance<FormValues> | null>;
121
+ /**
122
+ * 将字段路径统一转换为数组路径。
123
+ */
124
+ export declare function toNamePath(name: FormNamePath): (string | number)[];
125
+ /**
126
+ * 获取字段路径的稳定 key,用于字段注册表和 meta 映射。
127
+ */
128
+ export declare function getNamePathKey(name: FormNamePath): string;
129
+ /**
130
+ * 获取字段路径字符串,用于透传原生控件 `name` 属性。
131
+ */
132
+ export declare function getNamePathString(name: FormNamePath): string;
133
+ /**
134
+ * 创建独立表单实例。通常优先使用 `useForm`,测试或外部 store 场景可直接使用。
135
+ */
136
+ export declare function createForm<TValues extends FormValues = FormValues>(initialValues?: Partial<TValues>): FormInstance<TValues>;
137
+ /**
138
+ * 创建或复用表单实例,返回值结构与 Ant Design 的 `Form.useForm()` 保持一致。
139
+ */
140
+ export declare function useForm<TValues extends FormValues = FormValues>(form?: FormInstance<TValues>): readonly [FormInstance<TValues>];
141
+ /**
142
+ * 从当前 Form 上下文读取表单实例。
143
+ */
144
+ export declare function useFormInstance<TValues extends FormValues = FormValues>(): FormInstance<TValues>;
145
+ /**
146
+ * 订阅并读取字段值;不传 `name` 时返回整份表单值。
147
+ */
148
+ export declare function useFormValue<TValue = unknown>(name?: FormNamePath, form?: FormInstance): TValue;
149
+ /**
150
+ * `useFormValue` 的语义化别名,用于表达字段监听场景。
151
+ */
152
+ export declare function useFormWatch<TValue = unknown>(name?: FormNamePath, form?: FormInstance): TValue;
153
+ /**
154
+ * 订阅字段 meta,用于 `Form.Item` 内部和高级自定义字段状态展示。
155
+ */
156
+ export declare function useFormFieldMeta(name: FormNamePath, form?: FormInstance): FormFieldMeta;
157
+ export {};
@@ -1 +1,2 @@
1
1
  export * from "./input";
2
+ export * from "./useInputValue";
@@ -0,0 +1,27 @@
1
+ import * as React from "react";
2
+ export type InputValueChangeReason = "input" | "commit" | "set";
3
+ export type InputValueChangeMeta = {
4
+ reason: InputValueChangeReason;
5
+ valueAsString: string;
6
+ event?: React.ChangeEvent<HTMLInputElement> | React.FocusEvent<HTMLInputElement>;
7
+ };
8
+ export type UseInputValueOptions = {
9
+ value?: string;
10
+ defaultValue?: string;
11
+ onValueChange?: (value: string, meta: InputValueChangeMeta) => void;
12
+ formatOnBlur?: (value: string) => string;
13
+ };
14
+ export type UseInputValueResult = {
15
+ value: string;
16
+ setValue: (value: string) => void;
17
+ inputProps: {
18
+ value: string;
19
+ onChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
20
+ onBlur: (event: React.FocusEvent<HTMLInputElement>) => void;
21
+ };
22
+ };
23
+ /**
24
+ * 管理文本输入的字符串状态,并可在失焦时统一格式化。
25
+ * 适合需要 trim、大小写转换、简单掩码前置处理等场景。
26
+ */
27
+ export declare function useInputValue(options?: UseInputValueOptions): UseInputValueResult;
@@ -1,7 +1,51 @@
1
+ import * as React from "react";
1
2
  import { type InputProps } from "@/components/form/input";
3
+ export type InputNumberValueChangeReason = "input" | "commit";
4
+ export type InputNumberValueChangeMeta = {
5
+ reason: InputNumberValueChangeReason;
6
+ valueAsString: string;
7
+ event: React.ChangeEvent<HTMLInputElement> | React.FocusEvent<HTMLInputElement>;
8
+ };
2
9
  export type InputNumberProps = Omit<InputProps, "type" | "inputMode"> & {
3
10
  min?: number;
4
11
  max?: number;
5
12
  step?: number;
13
+ /** 失焦时是否将输入值修正到 `min/max/step` 描述的合法区间。 */
14
+ clampOnBlur?: boolean;
15
+ /** 失焦归一化后的固定小数位数。 */
16
+ precision?: number;
17
+ /** 返回解析后的数值;空值或非法临时值返回 `null`。 */
18
+ onValueChange?: (value: number | null, meta: InputNumberValueChangeMeta) => void;
19
+ };
20
+ export type UseInputNumberStateOptions = NormalizeOptions & {
21
+ defaultValue?: string | number | null;
22
+ onValueChange?: (value: number | null, meta: InputNumberValueChangeMeta) => void;
23
+ };
24
+ export type UseInputNumberStateResult = {
25
+ value: string;
26
+ numberValue: number | null;
27
+ setValue: (value: string | number | null) => void;
28
+ inputProps: Pick<InputNumberProps, "clampOnBlur" | "max" | "min" | "onChange" | "onValueChange" | "precision" | "step" | "value">;
6
29
  };
7
- export declare function InputNumber(props: InputNumberProps): import("react/jsx-runtime").JSX.Element;
30
+ type NormalizeOptions = Pick<InputNumberProps, "clampOnBlur" | "max" | "min" | "precision" | "step">;
31
+ /**
32
+ * 管理 InputNumber 的字符串输入态与解析后的数字值。
33
+ * 它会自动同步 `clampOnBlur` 产生的提交值,避免业务侧手写 commit 分支。
34
+ */
35
+ export declare function useInputNumberState(options?: UseInputNumberStateOptions): UseInputNumberStateResult;
36
+ /**
37
+ * InputNumber 是数字输入框组件。默认保留原生 number 输入行为;
38
+ * 需要强业务约束时可开启 `clampOnBlur`,在失焦时归一化到合法数值。
39
+ */
40
+ export declare const InputNumber: React.ForwardRefExoticComponent<Omit<InputProps, "type" | "inputMode"> & {
41
+ min?: number;
42
+ max?: number;
43
+ step?: number;
44
+ /** 失焦时是否将输入值修正到 `min/max/step` 描述的合法区间。 */
45
+ clampOnBlur?: boolean;
46
+ /** 失焦归一化后的固定小数位数。 */
47
+ precision?: number;
48
+ /** 返回解析后的数值;空值或非法临时值返回 `null`。 */
49
+ onValueChange?: (value: number | null, meta: InputNumberValueChangeMeta) => void;
50
+ } & React.RefAttributes<HTMLInputElement>>;
51
+ export {};
@@ -1,9 +1,103 @@
1
- export type InputOPTProps = {
1
+ import * as React from "react";
2
+ import { type SxProps } from "@/styling";
3
+ export type InputOPTValueType = "numeric" | "alphabetic" | "alphanumeric";
4
+ export type InputOPTSize = "sm" | "md" | "lg";
5
+ export type InputOPTVariant = "outline" | "filled" | "underline";
6
+ type NativeInputProps = Omit<React.ComponentPropsWithoutRef<"input">, "autoFocus" | "children" | "className" | "defaultValue" | "maxLength" | "onChange" | "pattern" | "placeholder" | "size" | "style" | "type" | "value">;
7
+ export type InputOPTProps = NativeInputProps & {
8
+ /** 受控验证码值。 */
2
9
  value?: string;
10
+ /** 非受控默认验证码值。 */
11
+ defaultValue?: string;
12
+ /** 验证码位数。 */
3
13
  length?: number;
4
- disabled?: boolean;
14
+ /** 值变化回调,返回过滤后的完整验证码字符串。 */
15
+ onChange?: (value: string) => void;
16
+ /** 填满所有位后触发。 */
17
+ onComplete?: (value: string) => void;
18
+ /** 字符类型过滤规则。 */
19
+ type?: InputOPTValueType;
20
+ /** 自定义单字符过滤规则。 */
21
+ pattern?: RegExp | string;
22
+ /** 粘贴内容进入过滤前的转换函数。 */
23
+ pasteTransformer?: (value: string) => string;
24
+ /** 是否视觉掩码展示,传入字符串可自定义掩码字符。 */
25
+ mask?: boolean | string;
26
+ /** 空槽位占位字符。 */
27
+ placeholder?: string;
28
+ /** 首次挂载时是否自动聚焦输入。 */
29
+ autoFocus?: boolean;
30
+ /** 是否启用一次性验证码自动填充语义。 */
31
+ oneTimeCode?: boolean;
32
+ /** 槽位尺寸。 */
33
+ size?: InputOPTSize;
34
+ /** 槽位视觉风格。 */
35
+ variant?: InputOPTVariant;
36
+ /** 是否展示错误态。 */
37
+ invalid?: boolean;
38
+ /** 根节点类名。 */
5
39
  className?: string;
40
+ /** 兼容旧写法的根节点类名。 */
6
41
  class?: string;
7
- onChange?: (value: string) => void;
42
+ /** 真实 input 的类名。 */
43
+ inputClassName?: string;
44
+ /** 单个槽位类名。 */
45
+ slotClassName?: string;
46
+ /** 槽位之间的分隔内容。 */
47
+ separator?: React.ReactNode | ((index: number) => React.ReactNode);
48
+ /** 根节点样式。 */
49
+ style?: React.CSSProperties;
50
+ /** CSS-in-JS 样式入口。 */
51
+ sx?: SxProps;
8
52
  };
9
- export declare function InputOPT(props: InputOPTProps): import("react/jsx-runtime").JSX.Element;
53
+ /**
54
+ * InputOPT 是一次性验证码输入组件。它使用一个真实 input 承接输入、自动填充和表单提交,
55
+ * 再用槽位展示验证码字符,确保线性输入、连续删除和粘贴分发行为稳定一致。
56
+ */
57
+ export declare const InputOPT: React.ForwardRefExoticComponent<NativeInputProps & {
58
+ /** 受控验证码值。 */
59
+ value?: string;
60
+ /** 非受控默认验证码值。 */
61
+ defaultValue?: string;
62
+ /** 验证码位数。 */
63
+ length?: number;
64
+ /** 值变化回调,返回过滤后的完整验证码字符串。 */
65
+ onChange?: (value: string) => void;
66
+ /** 填满所有位后触发。 */
67
+ onComplete?: (value: string) => void;
68
+ /** 字符类型过滤规则。 */
69
+ type?: InputOPTValueType;
70
+ /** 自定义单字符过滤规则。 */
71
+ pattern?: RegExp | string;
72
+ /** 粘贴内容进入过滤前的转换函数。 */
73
+ pasteTransformer?: (value: string) => string;
74
+ /** 是否视觉掩码展示,传入字符串可自定义掩码字符。 */
75
+ mask?: boolean | string;
76
+ /** 空槽位占位字符。 */
77
+ placeholder?: string;
78
+ /** 首次挂载时是否自动聚焦输入。 */
79
+ autoFocus?: boolean;
80
+ /** 是否启用一次性验证码自动填充语义。 */
81
+ oneTimeCode?: boolean;
82
+ /** 槽位尺寸。 */
83
+ size?: InputOPTSize;
84
+ /** 槽位视觉风格。 */
85
+ variant?: InputOPTVariant;
86
+ /** 是否展示错误态。 */
87
+ invalid?: boolean;
88
+ /** 根节点类名。 */
89
+ className?: string;
90
+ /** 兼容旧写法的根节点类名。 */
91
+ class?: string;
92
+ /** 真实 input 的类名。 */
93
+ inputClassName?: string;
94
+ /** 单个槽位类名。 */
95
+ slotClassName?: string;
96
+ /** 槽位之间的分隔内容。 */
97
+ separator?: React.ReactNode | ((index: number) => React.ReactNode);
98
+ /** 根节点样式。 */
99
+ style?: React.CSSProperties;
100
+ /** CSS-in-JS 样式入口。 */
101
+ sx?: SxProps;
102
+ } & React.RefAttributes<HTMLInputElement>>;
103
+ export {};