litmoss-form 0.0.0-stage → 5.0.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.
package/LICENSE ADDED
@@ -0,0 +1,201 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright [yyyy] [name of copyright owner]
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
package/README.md CHANGED
@@ -1,3 +1,220 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
1
+ # litmoss-form
2
+
3
+ ![GitHub](https://img.shields.io/github/license/liuxian496/litmoss-form)
4
+ ![GitHub Workflow Status (with event)](https://img.shields.io/github/actions/workflow/status/liuxian496/litmoss-form/test.yml)
5
+ [![Coverage Status](https://coveralls.io/repos/github/liuxian496/litmoss/badge.svg)](https://coveralls.io/github/liuxian496/litmoss)
6
+ ![GitHub Repo stars](https://img.shields.io/github/stars/liuxian496/litmoss-form)
7
+
8
+ litmoss-form 是一个基于 React 的轻量表单库,提供跨组件的表单数据管理能力。核心理念是将**表单数据的状态管理**与**表单UI控制**解耦。
9
+
10
+ - **跨组件收集表单数据**:表单项通过 `path` 自动注册到 `Form` 上下文,无需逐层传递 props
11
+ - **一次受控**:只要**表单组件**封装时实现一次受控逻辑,页面开发即可免去重复的受控代码编写,使开发者专注于业务逻辑的编排。
12
+ - **命令式 API**:通过 `useForm`暴露`getValues`、`setValues`、`validate` 等方法
13
+ - **可扩展的校验体系**:通过 `initLittenForm` 全局注入通用校验断言和默认提示文案,同时支持自定义校验
14
+ - **两种校验模式**:全部校验(`all`)与分步校验(`step`)
15
+ - **校验失败时**,自动聚焦到第一个出错的表单项
16
+ - **UI无关**:不依赖与任何UI库,任何UI库都能通过封装**表单组件**继承
17
+
18
+ ## 在线文档
19
+
20
+ [github pages:https://liuxian496.github.io/litmoss-form/](https://liuxian496.github.io/litmoss-form/)
21
+
22
+ [chromatic:https://6ac70cb7870df8e554fb05ff-jcxiqbiehx.chromatic.com/](https://6ac70cb7870df8e554fb05ff-jcxiqbiehx.chromatic.com/)
23
+
24
+ ## 安装
25
+
26
+ ```bash
27
+ npm i litmoss-form
28
+ ```
29
+
30
+ 以下依赖为 `peerDependencies`,打包时不包含,需要在使用的项目中自行安装:
31
+
32
+ | 依赖 | 版本 |
33
+ |----------------------|------------|
34
+ | `react` | `^18.2.0` |
35
+ | `react-dom` | `^18.2.0` |
36
+ | `classnames` | `^2.5.1` |
37
+ | `cyndi` | `^1.0.0` |
38
+ | `exception-boundary` | `^2.0.1` |
39
+ | `litmoss-hooks` | `^1.1.0` |
40
+ | `lodash` | `^4.17.21` |
41
+
42
+ ## 快速开始
43
+
44
+ ### 1. 在工程入口全局初始化
45
+
46
+ 在应用启动时调用一次 `initLittenForm`,注入通用校验断言与默认提示文案:
47
+
48
+ ```ts
49
+ import { BaseValidationType, initLittenForm } from 'litmoss-form';
50
+
51
+ export const ValidationType = {
52
+ ...BaseValidationType,
53
+ StringRequired: 'stringRequired',
54
+ } as const;
55
+
56
+ export type ValidationType =
57
+ (typeof ValidationType)[keyof typeof ValidationType];
58
+
59
+ initLittenForm<ValidationType, string, unknown>({
60
+ commonValidationAssert: (value, type) => {
61
+ switch (type) {
62
+ case ValidationType.StringRequired:
63
+ return typeof value === 'string' && value.trim() !== '';
64
+ default:
65
+ return true;
66
+ }
67
+ },
68
+ getDefaultHelperInfo: (type) => {
69
+ switch (type) {
70
+ case ValidationType.StringRequired:
71
+ return '该项为必填项';
72
+ default:
73
+ return '';
74
+ }
75
+ },
76
+ });
77
+ ```
78
+
79
+ ### 2. 使用表单
80
+
81
+ ```tsx
82
+ import { Form, useForm } from 'litmoss-form';
83
+
84
+ function Demo() {
85
+ const [formRef, form] = useForm();
86
+
87
+ function handleSubmit() {
88
+ const errors = form?.validate({ focusOnError: true }) ?? [];
89
+ if (errors.length > 0) return;
90
+
91
+ console.log(form?.getValues());
92
+ }
93
+
94
+ return (
95
+ <>
96
+ <Form ref={formRef}>
97
+ {/* 使用 useFormItemValue 封装的表单项组件 */}
98
+ <MyTextField
99
+ path="name"
100
+ validations={[{ type: ValidationType.StringRequired }]}
101
+ />
102
+ </Form>
103
+ <button onClick={handleSubmit}>提交</button>
104
+ </>
105
+ );
106
+ }
107
+ ```
108
+
109
+ ## API 概览
110
+
111
+ ### 组件
112
+
113
+ | 组件 | 说明 |
114
+ |-----------|--------------------------------------------------------------------|
115
+ | `Form` | 表单容器,通过 `ref` 暴露 `FormRef`。`validationMode` 默认为 `all` |
116
+ | `Mounter` | 挂载完成后触发一次 `onDidMount` 回调,可用于级联表单等场景的初始化 |
117
+
118
+ ### Hooks
119
+
120
+ | Hook | 说明 |
121
+ |--------------------|-----------------------------------------------------------------|
122
+ | `useForm` | 返回 `[ref, form]`,`ref` 传给 `Form`,`form` 为 `FormRef` 实例 |
123
+ | `useFormItemValue` | 管理表单项的值,并向 `Form` 上下文注册 / 卸载该表单项 |
124
+ | `useHelperInfo` | 根据 `validations` 执行校验,管理校验提示文本 |
125
+
126
+ ### FormRef
127
+
128
+ | 方法 | 说明 |
129
+ |---------------------------------|---------------------------------------------------|
130
+ | `getValues()` | 获取表单当前全部数据 |
131
+ | `setValues(args)` | 批量设置表单数据,`args` 形如 `[{ path, value }]` |
132
+ | `getValueByPath(path)` | 获取指定表单项的值 |
133
+ | `setValueByPath(path, value)` | 设置指定表单项的值 |
134
+ | `setHelpTextByPath(path, text)` | 设置指定表单项的提示信息 |
135
+ | `validate({ focusOnError? })` | 校验表单,返回失败项的 `{ path, helpInfo }` 数组 |
136
+ | `focusFieldByPath(path)` | 聚焦指定表单项 |
137
+
138
+ ### 常量
139
+
140
+ | 常量 | 说明 |
141
+ |--------------------------------|--------------------------------------------------|
142
+ | `ValidationMode.all` | 全部校验,收集所有失败项 |
143
+ | `ValidationMode.step` | 分步校验,按注册顺序校验,遇到第一个失败项即停止 |
144
+ | `BaseValidationType.Customize` | 自定义校验类型,需配合 `validationAssert` 使用 |
145
+
146
+ ### 初始化
147
+
148
+ | 方法 | 说明 |
149
+ |----------------------------|--------------------------------------------------------------------------------------|
150
+ | `initLittenForm(injector)` | 全局注入 `commonValidationAssert`、`getDefaultHelperInfo`、`getInitialValue`(可选) |
151
+
152
+ ## 自定义表单组件
153
+
154
+ 组合使用 `useHelperInfo` 与 `useFormItemValue` 即可封装一个受控、支持校验提示的表单组件:
155
+
156
+ ```tsx
157
+ import { useRef } from 'react';
158
+ import { useFormItemValue, useHelperInfo } from 'litmoss-form';
159
+ import type { FormItemProps } from 'litmoss-form';
160
+
161
+ export const MyTextField = ({
162
+ path,
163
+ initialValue,
164
+ validations = [],
165
+ }: FormItemProps<string, ValidationType>) => {
166
+ const inputRef = useRef<HTMLInputElement>(null);
167
+
168
+ const [helperText, verifyFormItem, setHelperText] = useHelperInfo<
169
+ string,
170
+ ValidationType
171
+ >(validations);
172
+
173
+ const [value, setValue] = useFormItemValue<string>(
174
+ path,
175
+ initialValue,
176
+ verifyFormItem,
177
+ setHelperText,
178
+ inputRef
179
+ );
180
+
181
+ return (
182
+ <div>
183
+ <input
184
+ ref={inputRef}
185
+ value={value ?? ''}
186
+ onChange={(e) => setValue(e.target.value)}
187
+ onBlur={() => verifyFormItem(value)}
188
+ />
189
+ <div>{helperText}</div>
190
+ </div>
191
+ );
192
+ };
193
+ ```
194
+
195
+ 更多细节见 [自定义表单组件封装指南](./docs/custom-form-component-guide.md)。
196
+
197
+ ## 文档
198
+
199
+ - [接入文档](./docs/integration.md)
200
+ - [自定义表单组件封装指南](./docs/custom-form-component-guide.md)
201
+
202
+ ## 本地开发
203
+
204
+ ```bash
205
+ npm i # 安装依赖
206
+ npm run storybook # 启动 Storybook(端口 6006)
207
+ npm test # 运行测试
208
+ npm run test-storybook -- --coverage # 运行 Storybook 测试并生成覆盖率
209
+ npm run lint # 代码检查
210
+ npm run build # 构建
211
+ ```
212
+
213
+ ## License
214
+
215
+ [Apache-2.0](./LICENSE)
216
+
217
+ ## 如果你想请我喝一咖啡(Buy Me a Coffee)
218
+
219
+ <img src=".\\public\\wechat.jpg" height="360">
220
+ <img src=".\\public\\alipay.jpg" height="360">
@@ -0,0 +1,15 @@
1
+ import { FormContextProps, FormRegister } from './form.types';
2
+ /**
3
+ * 用于管理表单状态和操作的 React Context
4
+ * 通过 `FormContextProps` 提供表单相关的属性和方法
5
+ * @see FormContextProps
6
+ */
7
+ export declare const FormContext: import('react').Context<FormContextProps | undefined>;
8
+ /**
9
+ * 初始化表单上下文
10
+ *
11
+ * @param formRegister - 用于存储表单项注册信息的对象,以 valuePath 作为键
12
+ * @param setErrorMsg - 用于更新错误信息的 React 状态设置函数
13
+ * @returns {FormContextProps} 返回包含注册、检查和卸载表单项方法的表单上下文
14
+ */
15
+ export declare function initContext(formRegister: FormRegister, setErrorMsg: React.Dispatch<React.SetStateAction<string | undefined>>): FormContextProps;
@@ -0,0 +1,28 @@
1
+ /**
2
+ * 当在表单中无法找到对应的值路径时的警告信息
3
+ * @param path 表单项的值在表单数据中的属性路径
4
+ * @returns 警告信息字符串
5
+ */
6
+ export declare function valuePathNotFoundEntry(path: string): string;
7
+ /**
8
+ * 当setValues函数的第一个参数不是FormArgs数组时的警告信息
9
+ * @returns 警告信息字符串
10
+ */
11
+ export declare function setValuesFirstParamNotArray(): string;
12
+ /**
13
+ * 当在表单项注册器中找不到set方法时的警告信息
14
+ * @returns 警告信息字符串
15
+ */
16
+ export declare function setMethodNotFound(): string;
17
+ /**
18
+ * 当在表单项注册器中找不到commonValidationAssert方法时的警告信息
19
+ * @returns
20
+ */
21
+ export declare function commonValidationAssertNotFound(): string;
22
+ /**
23
+ * 当尝试聚焦一个不存在的表单项时的警告信息
24
+ * @param path 表单项的唯一路径(path)
25
+ * @returns 警告信息字符串
26
+ */
27
+ export declare function focusNotFound(path: string): string;
28
+ export declare function validationAssertNotFoundEntry(path: string): string;
@@ -0,0 +1,10 @@
1
+ import { FormProps } from './form.types';
2
+ /**
3
+ * Form 是一个 React 组件,提供基于React Context的表单管理系统
4
+ * 通过 `ref` 暴露命令式方法,用于操作表单状态,如清空、获取、设置和校验表单值。
5
+ *
6
+ * @param {FormProps} props - 表单组件的属性
7
+ * @param {React.Ref<FormRef>} ref - 用于访问命令式表单方法的 ref
8
+ * @returns {JSX.Element} 渲染后的表单组件
9
+ */
10
+ export declare const Form: import('react').ForwardRefExoticComponent<FormProps & import('react').RefAttributes<unknown>>;
@@ -0,0 +1,280 @@
1
+ import { Dispatch, ReactNode, SetStateAction } from 'react';
2
+ import { UserControlProps } from 'litmoss-hooks/dist/control/userControl/userControl.types';
3
+ /**
4
+ * 表单组件属性
5
+ * @property children - 表单组件的子组件
6
+ * @property {ValidationMode} validationMode - 表单验证模式,支持分步验证或全部验证。默认全部验证(暂时只支持全部验证)
7
+ */
8
+ export interface FormProps extends UserControlProps {
9
+ /**
10
+ * 表单组件的子组件
11
+ */
12
+ children?: ReactNode;
13
+ /**
14
+ * 表单验证模式,支持分步验证或全部验证。默认全部验证(暂时只支持全部验证)
15
+ */
16
+ validationMode?: ValidationMode;
17
+ }
18
+ /**
19
+ * 表单项验证后的提示信息,可以是string, JSX.Element,或者Undefined
20
+ * 通常使用string就可以满足基本的验证提示需求
21
+ */
22
+ export type FormHelperInfo = string | JSX.Element | undefined;
23
+ /**
24
+ * 表单验证模式常量
25
+ *
26
+ * @property {"all"} all - 全部验证,验证所有表单项并收集所有无效项的提示信息
27
+ * @property {"step"} step - 分步验证,按注册顺序验证表单项,遇到第一个无效项时停止验证并返回提示信息
28
+ *
29
+ * 用于 FormProps.validationMode 属性,或表单相关 API 的验证模式参数。
30
+ *
31
+ * 示例:
32
+ * validationMode={ValidationMode.all}
33
+ * validationMode={ValidationMode.step}
34
+ */
35
+ export declare const ValidationMode: {
36
+ /**
37
+ * 全部验证,验证所有表单项并收集所有无效项的提示信息
38
+ */
39
+ readonly all: "all";
40
+ /**
41
+ * 分步验证,按注册顺序验证表单项,遇到第一个无效项时停止验证并返回提示信息
42
+ */
43
+ readonly step: "step";
44
+ };
45
+ export type ValidationMode = (typeof ValidationMode)[keyof typeof ValidationMode];
46
+ /**
47
+ * 表单数据
48
+ */
49
+ export interface FormValues {
50
+ [index: string]: unknown;
51
+ }
52
+ /**
53
+ * 可聚焦的表单控件接口
54
+ * 任何实现了该接口的表单控件都应提供一个 focus 方法,用于将焦点设置到该控件上
55
+ * 这对于表单验证失败时自动聚焦非常有用
56
+ * @property focus - 将焦点设置到该控件的方法
57
+ */
58
+ export interface FocusableField {
59
+ focus: () => void;
60
+ }
61
+ /**
62
+ * 表单项注册器
63
+ * @property path - 表单项的值路径,值路径需要唯一
64
+ * @property get - 获取表单项值的方法
65
+ * @property set - 设置表单项值的方法
66
+ * @property validate - 可选的验证函数,接受表单项值作为参数,返回一个字符串或JSX元素表示验证结果
67
+ * @property setHelperText - 可选的设置帮助信息的方法,接受一个字符串或JSX元素作为参数
68
+ * @property fieldRef - 可选的表单控件引用,用于访问控件的实例方法,如 focus
69
+ */
70
+ export interface FormItemRegister {
71
+ path: string;
72
+ get?: <V>() => V | undefined;
73
+ set?: <T>(value: T) => void;
74
+ validate?: <V>(value: V) => FormHelperInfo;
75
+ setHelperText?: Dispatch<SetStateAction<FormHelperInfo>>;
76
+ fieldRef?: React.RefObject<FocusableField | null>;
77
+ }
78
+ /**
79
+ * 表单注册器
80
+ * @property [index: string] - 以表单项的值路径作为键,值为对应的表单项注册器
81
+ */
82
+ export interface FormRegister {
83
+ [index: string]: FormItemRegister;
84
+ }
85
+ /**
86
+ * 表单上下文属性
87
+ * @property register - 注册表单项
88
+ * @property checkValuePath - 检查指定路径的表单项值
89
+ * @property uninstall - 卸载指定路径的表单项
90
+ */
91
+ export interface FormContextProps {
92
+ /**
93
+ * 注册表单项
94
+ * @param props 表单项注册器
95
+ * @returns void
96
+ */
97
+ register: (props: FormItemRegister) => void;
98
+ /**
99
+ * 检查表单项的值路径是否唯一
100
+ * @param path - 要校验的表单项的值路径
101
+ */
102
+ checkValuePath: (path: string) => void;
103
+ /**
104
+ * 卸载表单项
105
+ * @param path - 要卸载的表单项的值路径
106
+ * @returns void
107
+ */
108
+ uninstall: (path: string) => void;
109
+ }
110
+ /**
111
+ * 表单控件属性
112
+ */
113
+ export interface FormControlProps {
114
+ /**
115
+ * 设置用于获取value属性的属性路径
116
+ */
117
+ valuePath: string;
118
+ /**
119
+ * 子组件
120
+ */
121
+ children: JSX.Element;
122
+ }
123
+ /**
124
+ * 表单项属性
125
+ * @property path - 表单项的唯一路径
126
+ * @property initialValue - 表单项的初始值, 不是默认值
127
+ * @property validations - 表单项的验证规则
128
+ */
129
+ export interface FormItemProps<T, V> {
130
+ path: string;
131
+ initialValue?: T;
132
+ validations?: FormItemValidations<V>;
133
+ }
134
+ /**
135
+ * 表单项参数
136
+ * 用于设置表单项的值
137
+ * 包含属性路径和对应的值
138
+ * @property path - 表单项的唯一路径
139
+ * @property value - 表单项的值
140
+ */
141
+ export interface FormItemArgs {
142
+ path: string;
143
+ value: unknown;
144
+ }
145
+ /**
146
+ * 表单参数
147
+ * 包含一个数组,每个元素是一个[表单项参数](#FormItemArgs)
148
+ */
149
+ export type FormArgs = FormItemArgs[];
150
+ /**
151
+ * 包含表单组件基础校验类型的对象。
152
+ *
153
+ * @property {string} Customize - 表示自定义校验类型。
154
+ */
155
+ export declare const BaseValidationType: {
156
+ /**
157
+ * 表示自定义校验类型
158
+ */
159
+ readonly Customize: "customize";
160
+ };
161
+ /**
162
+ * 表单默认验证类型
163
+ */
164
+ export type BaseValidationType = (typeof BaseValidationType)[keyof typeof BaseValidationType];
165
+ /**
166
+ * 扩展验证类型
167
+ */
168
+ export interface ExtendedValidation {
169
+ [key: string]: string;
170
+ }
171
+ /**
172
+ * 表单项的验证对象
173
+ * 包含帮助信息、验证类型和可选的验证断言函数,一个表单项可以包含多个验证对象
174
+ * @property helpInfo - 帮助信息,可以是字符串或JSX元素
175
+ * @property type - 验证类型,使用[ValidationType](#ValidationType)枚举
176
+ * @property validationAssert - 可选的验证断言函数,接受表单项值作为参数,返回一个布尔值表示验证是否通过
177
+ */
178
+ export interface FormItemValidation<T> {
179
+ helpInfo?: FormHelperInfo;
180
+ type: T;
181
+ validationAssert?: (value: unknown) => boolean;
182
+ }
183
+ export type FormItemValidations<T> = FormItemValidation<T>[];
184
+ /**
185
+ * 表单项帮助信息
186
+ * @package helpInfo - 帮助信息,可以是字符串或JSX元素
187
+ * @property path - 表单项的值路径
188
+ */
189
+ export interface FormItemHelper {
190
+ helpInfo?: FormHelperInfo;
191
+ path: string;
192
+ }
193
+ /**
194
+ * 表单ref对象
195
+ * 包含操作表单的方法
196
+ * @property getValues - 获取表单当前数据的方法,返回一个包含所有表单项数据的对象
197
+ * @property setValues - 设置表单数据的方法,接受一个包含表单项路径和值的数组作为参数
198
+ * @property getValueByPath - 通过属性路径获取表单项对应控件的值的方法,接受一个字符串类型的路径作为参数,返回对应的值
199
+ * @property setValueByPath - 通过属性路径设置表单项对应控件的值的方法,接受一个字符串类型的路径和一个值作为参数
200
+ * @property setHelpTextByPath - 通过属性路径设置表单项的帮助信息的方法,接受一个字符串类型的路径和一个错误消息(字符串或JSX元素)作为参数
201
+ */
202
+ export interface FormRef {
203
+ /**
204
+ * 获取表单当前数据
205
+ * @returns 表单当前数据对象
206
+ */
207
+ getValues: () => FormValues;
208
+ /**
209
+ * 设置表单数据
210
+ * @param {FormArgs} args 表单项参数数组
211
+ * @returns void
212
+ * @example
213
+ * ```ts
214
+ * myForm.setValues([{ path: "name", value: "Tom" }, { path: "age", value: 18 }]);
215
+ * ```
216
+ */
217
+ setValues: (args: FormArgs) => FormItemHelper[];
218
+ /**
219
+ * 通过属性路径获取表单项对应控件的值的方法
220
+ * @param path 表单项的值路径
221
+ * @returns 表单项的值
222
+ */
223
+ getValueByPath: (path: string) => unknown;
224
+ /**
225
+ * 通过属性路径设置表单项对应控件的值的方法
226
+ * @param path 表单项的值路径
227
+ * @param value 表单项对应控件的值
228
+ * @returns void
229
+ */
230
+ setValueByPath: (path: string, value: unknown) => FormHelperInfo;
231
+ /**
232
+ * 通过属性路径设置表单项对应控件的帮助信息的方法
233
+ * @param path 表单项的值路径
234
+ * @param {FormHelperInfo} helpText 帮助信息
235
+ * @returns void
236
+ */
237
+ setHelpTextByPath: (path: string, helpText: FormHelperInfo) => void;
238
+ /**
239
+ * 表单验证
240
+ * @param options - 验证选项
241
+ * @param options.focusOnError - 验证失败时是否自动聚焦到第一个错误表单项(可选,默认为 false)
242
+ * @returns 表单验证结果数组,包含每个验证失败表项的帮助信息和路径
243
+ */
244
+ validate: (options?: {
245
+ focusOnError?: boolean;
246
+ }) => FormItemHelper[];
247
+ /**
248
+ * 通过属性路径聚焦表单项对应控件的方法
249
+ * @param path 表单项的值路径
250
+ * @returns void
251
+ */
252
+ focusFieldByPath: (path: string) => void;
253
+ }
254
+ /**
255
+ * 表单注入器
256
+ * @property commonValidationAssert - 可选的公共验证断言函数,接受一个值和一个验证类型作为参数,返回一个布尔值表示验证是否通过
257
+ * @property getDefaultHelperInfo - 可选的获取默认帮助信息的方法,接受一个值和一个验证类型作为参数,返回一个字符串或JSX元素表示默认帮助信息
258
+ * @property getInitialValue - 可选的获取初始值的方法,接受一个控件类型作为参数,返回对应的初始值
259
+ */
260
+ export interface FormInjector<VT = unknown, CT = unknown, T = unknown> {
261
+ /**
262
+ * 公共验证断言函数,接受一个值和一个验证类型作为参数,返回一个布尔值表示验证是否通过
263
+ * @param value - 要验证的值
264
+ * @param validationType - 验证类型
265
+ * @returns 验证结果,true表示验证通过,false表示验证失败
266
+ */
267
+ commonValidationAssert?(value: unknown, validationType: VT): boolean;
268
+ /**
269
+ * 获取默认帮助信息的方法,接受一个验证类型作为参数,返回一个字符串或JSX元素表示默认帮助信息
270
+ * @param validationType - 验证类型
271
+ * @returns 默认帮助信息,字符串或JSX元素
272
+ */
273
+ getDefaultHelperInfo?(validationType: VT): FormHelperInfo;
274
+ /**
275
+ * 获取初始值的方法,接受一个控件类型作为参数,返回对应的初始值
276
+ * @param controlType - 控件类型
277
+ * @returns 控件的初始值
278
+ */
279
+ getInitialValue?(controlType: CT): T;
280
+ }
@@ -0,0 +1 @@
1
+ export declare function getVisualStates(cls?: string): string;
@@ -0,0 +1,41 @@
1
+ import { FormArgs, FormHelperInfo, FormItemHelper, FormRegister, FormValues } from './form.types';
2
+ /**
3
+ * 获取表单当前数据
4
+ * @param {FormRegister} formRegister 表单注册器
5
+ * @returns 表单当前数据对象
6
+ */
7
+ export declare function getValues(formRegister: FormRegister): FormValues;
8
+ /**
9
+ * 通过属性路径获取表单项对应控件的值的方法
10
+ * @param path 表单项的值在表单数据中的属性路径
11
+ * @param {FormRegister} formRegister 表单注册器
12
+ * @returns 表单项对应控件的值
13
+ */
14
+ export declare function getValueByPath(path: string, formRegister: FormRegister): unknown;
15
+ /**
16
+ * 设置表单项的帮助信息
17
+ * @param path 表单项的值在表单数据中的属性路径
18
+ * @param helperText 帮助信息
19
+ * @param formRegister 表单注册器
20
+ */
21
+ export declare function setHelpTextByPath(path: string, helperText: FormHelperInfo, formRegister: FormRegister): void;
22
+ /**
23
+ * 设置表单数据
24
+ * @param {FormArgs} args 表单项参数数组
25
+ * @param {FormRegister} formRegister 表单注册器
26
+ */
27
+ export declare function setValues(args: FormArgs, formRegister: FormRegister): FormItemHelper[];
28
+ /**
29
+ * 通过属性路径设置指定表单项的值,并自动触发该表单项的验证逻辑。
30
+ *
31
+ * @param path 表单项的唯一路径(valuePath)
32
+ * @param value 需要设置的新值
33
+ * @param formRegister 当前表单的注册器对象
34
+ */
35
+ export declare function setValueByPath(path: string, value: unknown, formRegister: FormRegister): FormHelperInfo;
36
+ /**
37
+ * 聚焦指定表单项
38
+ * @param path 表单项的唯一路径(valuePath)
39
+ * @param formRegister 当前表单的注册器对象
40
+ */
41
+ export declare function focusFieldByPath(path: string, formRegister: FormRegister): void;
@@ -0,0 +1,12 @@
1
+ import { FormRef } from './form.types';
2
+ /**
3
+ * 获取表单ref的自定义hook
4
+ *
5
+ * @returns {[React.MutableRefObject<FormRef | undefined>, FormRef | undefined]} 返回一个元组:
6
+ * - ref:表单的可变 ref 对象
7
+ * - myForm:`FormRef` 类型的表单对象,包含操作表单的方法
8
+ *
9
+ * @example
10
+ * const [ref, myForm] = useForm();
11
+ */
12
+ export declare function useForm(): [React.MutableRefObject<FormRef | undefined>, FormRef | undefined];
@@ -0,0 +1,16 @@
1
+ import { Dispatch, SetStateAction } from 'react';
2
+ import { FocusableField, FormHelperInfo } from './form.types';
3
+ /**
4
+ * 提供一个自定义hook, 用来实现表单项的受控逻辑
5
+ *
6
+ * @template T - 表单项值的类型,默认FormItemValue
7
+ * @template V - 传递给校验函数的值类型,默认string
8
+ *
9
+ * @param valuePath - 唯一标识表单项的路径
10
+ * @param initialValue - 表单项的初始值
11
+ * @param onGetErrorMessage - 可选,校验值并返回错误信息或 JSX 元素的函数
12
+ * @param setHelperText - 可选,用于设置校验提示文本的 setter
13
+ *
14
+ * @returns 包含当前值和用于更新值的 setter 的元组
15
+ */
16
+ export declare function useFormItemValue<T, V = string>(valuePath: string, initialValue?: T, onGetErrorMessage?: (value: V, path: string) => FormHelperInfo, setHelperText?: Dispatch<SetStateAction<FormHelperInfo>>, fieldRef?: React.RefObject<FocusableField | null>): [T, Dispatch<SetStateAction<T>>];
@@ -0,0 +1,14 @@
1
+ import { Dispatch, SetStateAction } from 'react';
2
+ import { FormHelperInfo, FormItemValidation } from './form.types';
3
+ /**
4
+ * 提供一个自定义hook,管理表单项的帮助信息
5
+ *
6
+ * @template T - 帮助信息的类型,默认为 `FormHelperInfo`
7
+ * @template VT - 验证类型,默认为 `ValidationType`
8
+ * @template V - 需要校验的值类型,默认为 `string`
9
+ * @param validations - 需要应用于值的校验规则数组。
10
+ * @returns 返回一个元组,包含:
11
+ * - 校验并更新帮助信息的函数 (`(value: V) => T`),
12
+ * - 更新帮助信息状态的set函数 (`Dispatch<SetStateAction<FormHelperInfo>>`)。
13
+ */
14
+ export declare function useHelperInfo<V, VT>(validations: FormItemValidation<VT>[]): [FormHelperInfo, (value: V) => FormHelperInfo, Dispatch<SetStateAction<FormHelperInfo>>];
@@ -0,0 +1,11 @@
1
+ import { FormInjector } from './form/form.types';
2
+ /**
3
+ * 表单能力注入对象。
4
+ * 目的是扩展Litten Form的能力,并将具体的功能实现解耦,使得Litten Form可以适配不同的组件库或者自定义的表单实现(比如验证)。
5
+ */
6
+ export declare const formInjector: FormInjector;
7
+ /**
8
+ * 为litten form注入一些定制能力。
9
+ * @param args 注入实现集合,包含公共校验断言、默认帮助信息和初始值处理方法。
10
+ */
11
+ export declare function initLittenForm<VT, CT, T>(args: FormInjector<VT, CT, T>): void;
@@ -0,0 +1,2 @@
1
+ export { Mounter } from './mounter';
2
+ export type { MounterProps } from './mounter.types';
@@ -0,0 +1,2 @@
1
+ import { MounterProps } from './mounter.types';
2
+ export declare const Mounter: ({ onDidMount }: MounterProps) => null;
@@ -0,0 +1,4 @@
1
+ import { UserControlProps } from 'litmoss-hooks/dist/control/userControl/userControl.types';
2
+ export interface MounterProps extends UserControlProps {
3
+ onDidMount: () => void;
4
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * 输出控制台警告信息
3
+ * @param msg 警告信息
4
+ */
5
+ export declare function warn(msg: string): void;
@@ -0,0 +1 @@
1
+ export { validate } from '../validation/validate';
@@ -0,0 +1,8 @@
1
+ import { ValidationMode, FormItemHelper, FormRegister } from '../form/form.types';
2
+ /**
3
+ * 验证所有注册的表单项,并收集验证后的提示信息
4
+ *
5
+ * @param {FormRegister} formRegister - 表单注册器
6
+ * @returns {FormItemHelper[]} 验证后的提示信息
7
+ */
8
+ export declare function validate(formRegister: FormRegister, validationMode: ValidationMode): FormItemHelper[];
@@ -0,0 +1,9 @@
1
+ export { Form } from './components/form/form';
2
+ export { useForm } from './components/form/useForm';
3
+ export { useFormItemValue } from './components/form/useFormItemValue';
4
+ export { useHelperInfo } from './components/form/useHelperInfo';
5
+ export { initLittenForm } from './components/inject';
6
+ export { BaseValidationType, ValidationMode, } from './components/form/form.types';
7
+ export { Mounter } from './components/mounter';
8
+ export type { FormProps, FormRef, FormHelperInfo, FormItemProps, } from './components/form/form.types';
9
+ export type { MounterProps } from './components/mounter/mounter.types';
package/dist/index.js ADDED
@@ -0,0 +1,259 @@
1
+ import { createContext as e, forwardRef as t, useContext as n, useEffect as r, useImperativeHandle as i, useRef as a, useState as o } from "react";
2
+ import { ExceptionBoundary as s } from "exception-boundary";
3
+ import { ControlType as c } from "litmoss-hooks/dist/enum";
4
+ import l from "classnames";
5
+ import { getPrefixNs as u } from "cyndi/dist/getPrefixNs";
6
+ import { jsx as d } from "react/jsx-runtime";
7
+ //#region src/components/form/form.types.ts
8
+ var f = {
9
+ all: "all",
10
+ step: "step"
11
+ }, p = { Customize: "customize" };
12
+ //#endregion
13
+ //#region src/components/validation/validate.ts
14
+ function m(e) {
15
+ let t = [];
16
+ return Object.keys(e).forEach((n) => {
17
+ let r = e[n], i = r?.validate, a = r?.get;
18
+ if (i && a) {
19
+ let e = i(a());
20
+ e !== void 0 && t.push({
21
+ helpInfo: e,
22
+ path: n
23
+ });
24
+ }
25
+ }), t;
26
+ }
27
+ function h(e) {
28
+ let t = [], n = Object.keys(e), r = n.length;
29
+ for (let i = 0; i < r; i++) {
30
+ let r = n[i], a = e[r], o = a?.validate, s = a?.get;
31
+ if (o && s) {
32
+ let e = o(s());
33
+ if (e !== void 0) {
34
+ t.push({
35
+ helpInfo: e,
36
+ path: r
37
+ });
38
+ break;
39
+ }
40
+ }
41
+ }
42
+ return t;
43
+ }
44
+ function g(e, t) {
45
+ let n = [];
46
+ return n = t === f.all ? m(e) : h(e), n;
47
+ }
48
+ //#endregion
49
+ //#region src/components/form/context.ts
50
+ var _ = e(void 0);
51
+ function v(e, t) {
52
+ return {
53
+ register: (t) => {
54
+ let { path: n } = t;
55
+ e[n] = { ...t };
56
+ },
57
+ uninstall: (t) => {
58
+ delete e[t];
59
+ },
60
+ checkValuePath: (n) => {
61
+ Object.prototype.hasOwnProperty.call(e, n) === !1 ? e[n] = { path: n } : t(`The valuePath "${n}" is used by other FormControl, Please check your form.`);
62
+ }
63
+ };
64
+ }
65
+ //#endregion
66
+ //#region src/components/form/formBase.ts
67
+ function y(e, t) {
68
+ return u(e, t, "litten");
69
+ }
70
+ function b(e) {
71
+ let t = y("form", e);
72
+ return l(t);
73
+ }
74
+ //#endregion
75
+ //#region src/components/util.ts
76
+ function x(e) {
77
+ console.warn(`[litten warning]: ${e}`);
78
+ }
79
+ //#endregion
80
+ //#region src/components/form/entries.ts
81
+ function S(e) {
82
+ return `Can not find the path "${e}" in form. Please check if the form item is registered.`;
83
+ }
84
+ function C() {
85
+ return "The first parameter of setValues should be an array of FormArgs";
86
+ }
87
+ function w() {
88
+ return "Can not find set method in form item register.";
89
+ }
90
+ function T() {
91
+ return "Can not find commonValidationAssert in formInjector, please provide it to support validation types other than Customize.";
92
+ }
93
+ function E(e) {
94
+ return `The fieldRef for path "${e}" does not have a focus method.`;
95
+ }
96
+ function D(e) {
97
+ return `When using custom validation, validationAssert must be configured. The path missing this setting is: ${e}`;
98
+ }
99
+ //#endregion
100
+ //#region src/components/form/formUtil.ts
101
+ function O(e) {
102
+ let t = {};
103
+ return Object.keys(e).forEach((n) => {
104
+ let r = e[n]?.get;
105
+ r && (t[n] = r());
106
+ }), t;
107
+ }
108
+ function k(e, t) {
109
+ let n = t[e], r;
110
+ if (n !== void 0) {
111
+ let e = n.get;
112
+ e && (r = e());
113
+ } else x(S(e));
114
+ return r;
115
+ }
116
+ function A(e, t, n) {
117
+ let r = n[e];
118
+ r === void 0 ? x(S(e)) : r.setHelperText?.(t);
119
+ }
120
+ function j(e, t) {
121
+ let n = [];
122
+ return Array.isArray(e) ? (e.forEach((e) => {
123
+ let { path: r, value: i } = e, a = t[r]?.set, o = t[r]?.validate;
124
+ if (a) {
125
+ a(i);
126
+ let e = o?.(i);
127
+ e !== void 0 && n.push({
128
+ helpInfo: e,
129
+ path: r
130
+ });
131
+ } else x(w());
132
+ }), n) : (x(C()), n);
133
+ }
134
+ function M(e, t, n) {
135
+ let r = n[e];
136
+ if (r !== void 0) {
137
+ let { set: e, validate: n } = r;
138
+ if (e) return e(t), n?.(t);
139
+ x(w());
140
+ } else x(S(e));
141
+ }
142
+ function N(e, t) {
143
+ let n = t[e];
144
+ n ? n.fieldRef?.current?.focus ? n.fieldRef.current.focus() : x(E(e)) : x(S(e));
145
+ }
146
+ //#endregion
147
+ //#region src/components/form/form.tsx
148
+ var P = t(({ children: e, prefixCls: t, validationMode: n = f.all, ...r }, a) => {
149
+ let [c] = o({}), [l, u] = o(), [p] = o(() => v(c, u));
150
+ return i(a, () => ({
151
+ getValues: () => O(c),
152
+ getValueByPath: (e) => k(e, c),
153
+ setHelpTextByPath: (e, t) => {
154
+ A(e, t, c);
155
+ },
156
+ setValues: (e) => j(e, c),
157
+ setValueByPath: (e, t) => M(e, t, c),
158
+ validate: (e) => {
159
+ let { focusOnError: t } = e || {}, r = g(c, n);
160
+ if (t !== !1 && r.length > 0) {
161
+ let e = r[0];
162
+ N(e.path, c);
163
+ }
164
+ return r;
165
+ },
166
+ focusFieldByPath: (e) => {
167
+ N(e, c);
168
+ }
169
+ }), [c, n]), /* @__PURE__ */ d(s, {
170
+ errorMsg: l,
171
+ children: /* @__PURE__ */ d(_.Provider, {
172
+ value: p,
173
+ children: /* @__PURE__ */ d("div", {
174
+ className: b(t),
175
+ ...r,
176
+ children: e
177
+ })
178
+ })
179
+ });
180
+ });
181
+ P.displayName = c.Form;
182
+ //#endregion
183
+ //#region src/components/form/useForm.ts
184
+ function F() {
185
+ let e = a(), [t, n] = o();
186
+ return r(() => (n(e.current), () => {
187
+ e.current = void 0;
188
+ }), [e]), [e, t];
189
+ }
190
+ //#endregion
191
+ //#region src/components/form/useFormItemValue.ts
192
+ function I(e, t, i, a, s) {
193
+ let c = n(_), [l, u] = o(t);
194
+ return r(() => (c?.checkValuePath(e), () => {
195
+ c?.uninstall(e);
196
+ }), [c, e]), r(() => {
197
+ c?.register({
198
+ path: e,
199
+ get: () => l,
200
+ set: u,
201
+ validate: (t) => i?.(t, e),
202
+ setHelperText: a,
203
+ fieldRef: s
204
+ });
205
+ }, [
206
+ c,
207
+ i,
208
+ l,
209
+ e,
210
+ a,
211
+ s
212
+ ]), [l, u];
213
+ }
214
+ //#endregion
215
+ //#region src/components/inject.ts
216
+ var L = {};
217
+ function R(e) {
218
+ let { commonValidationAssert: t, getDefaultHelperInfo: n, getInitialValue: r } = e;
219
+ L.commonValidationAssert = t, L.getDefaultHelperInfo = n, L.getInitialValue = r;
220
+ }
221
+ //#endregion
222
+ //#region src/components/form/useHelperInfo.ts
223
+ function z(e) {
224
+ let [t, n] = o();
225
+ function r(t, r) {
226
+ let i, a = !1, o = e.length;
227
+ for (let n = 0; n < o; n++) {
228
+ let { helpInfo: o, type: s, validationAssert: c } = e[n];
229
+ if (s === p.Customize) {
230
+ if (c !== void 0) a = c(t) === !1;
231
+ else {
232
+ x(D(r));
233
+ break;
234
+ }
235
+ } else if (L.commonValidationAssert) a = L.commonValidationAssert(t, s) === !1;
236
+ else {
237
+ x(T());
238
+ break;
239
+ }
240
+ if (a) {
241
+ i = o ?? (L.getDefaultHelperInfo ? L.getDefaultHelperInfo(s) : void 0);
242
+ break;
243
+ }
244
+ }
245
+ return n(i), i;
246
+ }
247
+ return [
248
+ t,
249
+ r,
250
+ n
251
+ ];
252
+ }
253
+ //#endregion
254
+ //#region src/components/mounter/mounter.tsx
255
+ var B = ({ onDidMount: e }) => (r(() => {
256
+ e?.();
257
+ }, []), null);
258
+ //#endregion
259
+ export { p as BaseValidationType, P as Form, B as Mounter, f as ValidationMode, R as initLittenForm, F as useForm, I as useFormItemValue, z as useHelperInfo };
package/package.json CHANGED
@@ -1,6 +1,101 @@
1
- {
2
- "name": "litmoss-form",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
1
+ {
2
+ "name": "litmoss-form",
3
+ "private": false,
4
+ "version": "5.0.1",
5
+ "type": "module",
6
+ "module": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "files": [
9
+ "dist"
10
+ ],
11
+ "keywords": [
12
+ "react",
13
+ "javascript",
14
+ "typescript",
15
+ "component",
16
+ "form"
17
+ ],
18
+ "scripts": {
19
+ "dev": "vite",
20
+ "build": "tsc && vite build",
21
+ "check-type": "tsc -b",
22
+ "lint": "eslint . --report-unused-disable-directives --max-warnings 0",
23
+ "lint:fix": "eslint --fix src/",
24
+ "preview": "vite preview",
25
+ "storybook": "storybook dev -p 6006",
26
+ "test": "vitest",
27
+ "test-storybook": "vitest --project=storybook",
28
+ "changelog": "conventional-changelog -p angular -i CHANGELOG.md -w -s -r 0",
29
+ "build-storybook": "storybook build",
30
+ "prepare": "husky"
31
+ },
32
+ "peerDependencies": {
33
+ "classnames": "^2.5.1",
34
+ "cyndi": "^1.0.0",
35
+ "exception-boundary": "^2.0.1",
36
+ "litmoss-hooks": "^3.0.0",
37
+ "number-precision": "^1.6.0",
38
+ "react": "^18.2.0",
39
+ "react-dom": "^18.2.0"
40
+ },
41
+ "devDependencies": {
42
+ "@chromatic-com/storybook": "^5.1.1",
43
+ "@commitlint/cli": "^19.3.0",
44
+ "@commitlint/config-conventional": "^19.2.2",
45
+ "@storybook/addon-docs": "^10.3.3",
46
+ "@storybook/addon-vitest": "^10.3.3",
47
+ "@storybook/react-vite": "^10.3.3",
48
+ "@types/react": "^18.2.66",
49
+ "@types/react-dom": "^18.2.22",
50
+ "@vitejs/plugin-react": "^6.0.0",
51
+ "@vitest/browser-playwright": "^4.1.2",
52
+ "@vitest/coverage-istanbul": "^4.1.2",
53
+ "@vitest/coverage-v8": "^4.1.2",
54
+ "classnames": "^2.5.1",
55
+ "conventional-changelog": "^6.0.0",
56
+ "cyndi": "^1.0.0",
57
+ "cz-conventional-changelog": "^3.3.0",
58
+ "eslint": "^9.39.4",
59
+ "eslint-import-resolver-typescript": "^4.4.4",
60
+ "eslint-plugin-import": "^2.32.0",
61
+ "eslint-plugin-react-hooks": "^5.2.0",
62
+ "eslint-plugin-react-refresh": "^0.4.6",
63
+ "eslint-plugin-storybook": "^10.3.3",
64
+ "exception-boundary": "^2.0.1",
65
+ "husky": "^9.0.11",
66
+ "less": "^4.2.0",
67
+ "litmoss": "^3.0.0",
68
+ "litmoss-hooks": "^3.0.0",
69
+ "number-precision": "^1.6.0",
70
+ "playwright": "^1.59.0",
71
+ "react": "^18.2.0",
72
+ "react-dom": "^18.2.0",
73
+ "rollup-plugin-visualizer": "^5.12.0",
74
+ "storybook": "^10.3.3",
75
+ "typescript": "~5.9.3",
76
+ "typescript-eslint": "^8.56.1",
77
+ "vite": "^8.0.0",
78
+ "vite-plugin-dts": "^4.5.4",
79
+ "vitest": "^4.1.2"
80
+ },
81
+ "husky": {
82
+ "hooks": {
83
+ "pre-commit": "npm run test",
84
+ "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
85
+ }
86
+ },
87
+ "commitlint": {
88
+ "extends": [
89
+ "@commitlint/config-conventional"
90
+ ]
91
+ },
92
+ "config": {
93
+ "commitizen": {
94
+ "path": "./node_modules/cz-conventional-changelog"
95
+ }
96
+ },
97
+ "repository": {
98
+ "type": "git",
99
+ "url": "git+https://github.com/liuxian496/litmoss-form.git"
100
+ }
6
101
  }