pdyform 2.2.1 → 2.3.0

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/README.md CHANGED
@@ -1,7 +1,8 @@
1
1
  # pdyform
2
2
 
3
3
  [![npm version](https://badge.fury.io/js/pdyform.svg)](https://badge.fury.io/js/pdyform)
4
- [![Tests](https://img.shields.io/badge/tests-27%20passed%20(100%25)-brightgreen.svg)]()
4
+ [![Tests](https://img.shields.io/badge/tests-pass-brightgreen.svg)]()
5
+ [![Coverage](https://img.shields.io/badge/coverage-87%25-brightgreen.svg)]()
5
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
7
 
7
8
  [English](#english) | [中文说明](#中文说明)
@@ -16,10 +17,19 @@ A high-performance, schema-driven dynamic form system with **React** and **Vue**
16
17
 
17
18
  - **Schema-Driven**: Define your forms using a simple and intuitive JSON/JS schema.
18
19
  - **Framework Agnostic Core**: Core logic is entirely framework-free, making it extremely lightweight and portable.
20
+ - **Vanilla Pub-Sub Store**: Built-in 40-line `VanillaStore` ensures high-performance updates without relying on heavy state-management libraries like Zustand or Redux.
19
21
  - **Conditional Logic**: Supports dynamic `hidden` and `disabled` states based on form values (supports both boolean and functions).
20
- - **React & Vue Support**: Out-of-the-box UI components built on top of modern UI libraries (Radix UI / Shadcn).
21
- - **Type Safety**: Built with TypeScript for excellent developer experience and catch errors early.
22
- - **High Performance**: Optimized rendering using store-based state management (Zustand) to minimize re-renders.
22
+ - **React & Vue Support**: Out-of-the-box UI components. (Moving towards a pure Headless approach to decouple from Tailwind/Shadcn).
23
+ - **Type Safety**: Built with strict TypeScript for excellent developer experience and early error catching.
24
+ - **High Test Coverage**: Core logic is heavily tested (>85% coverage) ensuring robustness against edge cases like network-level async validation and race conditions.
25
+ - **Zero Side Effects**: Configured for aggressive tree-shaking with `"sideEffects": false`.
26
+
27
+ ### 🏗 Architecture & Roadmap
28
+
29
+ pdyform is built with a strict separation of concerns:
30
+ 1. **Core Data Engine (`pdyform-core`)**: Maintains the schema structure, parses definitions, runs asynchronous/synchronous validations, and manages state using an internal Vanilla Pub-Sub model.
31
+ 2. **Framework Adapters (`pdyform-react` / `pdyform-vue`)**: Wraps the core engine with localized hooks (e.g. `useSyncExternalStore` for React) and provides base components.
32
+ 3. **Headless Roadmap**: Currently, the React/Vue components bundle specific UI elements (Radix, Tailwind). We are moving towards a true Headless architecture where the packages expose only accessible logic components (`<Field>`) and hooks (`useForm`), leaving the styling implementation entirely up to the user (similar to unstyled Shadcn UI).
23
33
 
24
34
  ### 📦 Packages
25
35
 
@@ -116,10 +126,19 @@ const handleSubmit = (values: any) => console.log(values);
116
126
 
117
127
  - **Schema 驱动**: 使用简单直观的 JSON/JS 对象定义你的表单。
118
128
  - **框架无关核心**: 核心逻辑完全独立于 UI 框架,极其轻量且易于移植。
129
+ - **原生的防抖状态引擎**: 内置不到 40 行的 `VanillaStore` 来完成高性能的局部渲染与订阅,告别由于集成 Zustand 等库带来的体积膨胀。
119
130
  - **联动逻辑**: 支持基于表单实时数值动态控制字段的 `hidden`(隐藏)和 `disabled`(禁用)状态(支持布尔值或函数)。
120
- - **支持 React & Vue**: 提供基于现代 UI 库(Radix UI / Shadcn)的开箱即用组件。
131
+ - **支持 React & Vue**: 提供开箱即用的基础组件 (未来的路线图将向纯 Headless UI 组件过渡,解耦 Tailwind 样式依赖)。
121
132
  - **类型安全**: 全量 TypeScript 编写,提供极佳的开发体验。
122
- - **高性能**: 基于 Zustand 状态管理库优化渲染逻辑,最小化不必要的组件重绘。
133
+ - **高测试覆盖**: 核心逻辑配备了超过 85% 的单元测试与异步并发校验的健壮性控制。
134
+ - **零副作用**: 各包均通过 `"sideEffects": false` 配置,对构建工具进行深度 Tree-Shaking 优化。
135
+
136
+ ### 🏗 架构与路线图设计
137
+
138
+ 整个引擎保持了极其严格的职责划分:
139
+ 1. **核心数据引擎 (`pdyform-core`)**: 管理表单 Schema 结构的解析,处理异步和同步的各项校验机制。利用手写原生 Pub-Sub 处理多级数据变化拦截。
140
+ 2. **框架适配 Hook (`pdyform-react` / `pdyform-vue`)**: 将状态和渲染树绑定(如在 React 中使用 `useSyncExternalStore`)。
141
+ 3. **Headless 演进**: 尽全力提供类似无头表单 (Headless Form) 的钩子调用,不再强绑定各类 UI 组件库和样式设定。
123
142
 
124
143
  ### 📦 包结构
125
144
 
package/package.json CHANGED
@@ -1,5 +1,8 @@
1
1
  {
2
2
  "name": "pdyform",
3
+ "publishConfig": {
4
+ "access": "public"
5
+ },
3
6
  "description": "A high-performance, schema-driven dynamic form system with React and Vue support.",
4
7
  "keywords": [
5
8
  "dynamic-form",
@@ -15,7 +18,28 @@
15
18
  "packages/react/dist/**",
16
19
  "packages/vue/dist/**"
17
20
  ],
21
+ "main": "./packages/core/dist/index.cjs",
22
+ "module": "./packages/core/dist/index.js",
23
+ "types": "./packages/core/dist/index.d.ts",
24
+ "typesVersions": {
25
+ "*": {
26
+ "core": [
27
+ "./packages/core/dist/index.d.ts"
28
+ ],
29
+ "react": [
30
+ "./packages/react/dist/index.d.ts"
31
+ ],
32
+ "vue": [
33
+ "./packages/vue/dist/index.d.ts"
34
+ ]
35
+ }
36
+ },
18
37
  "exports": {
38
+ ".": {
39
+ "types": "./packages/core/dist/index.d.ts",
40
+ "import": "./packages/core/dist/index.js",
41
+ "require": "./packages/core/dist/index.cjs"
42
+ },
19
43
  "./core": {
20
44
  "types": "./packages/core/dist/index.d.ts",
21
45
  "import": "./packages/core/dist/index.js",
@@ -39,17 +63,24 @@
39
63
  "url": "https://github.com/LaoChen1994/pdyform"
40
64
  },
41
65
  "devDependencies": {
66
+ "@changesets/cli": "^2.30.0",
67
+ "@commitlint/cli": "^20.5.0",
68
+ "@commitlint/config-conventional": "^20.5.0",
42
69
  "@eslint/js": "^9.39.3",
70
+ "@size-limit/preset-small-lib": "^12.0.1",
43
71
  "@typescript-eslint/eslint-plugin": "^8.56.1",
44
72
  "@typescript-eslint/parser": "^8.56.1",
73
+ "@vitest/coverage-v8": "^1.6.1",
45
74
  "autoprefixer": "^10.4.27",
46
75
  "eslint": "^9.39.3",
47
76
  "eslint-config-prettier": "^10.1.8",
48
77
  "eslint-plugin-react": "^7.37.5",
49
78
  "eslint-plugin-vue": "^10.8.0",
50
79
  "globals": "^15.15.0",
80
+ "husky": "^9.1.7",
51
81
  "postcss": "^8.5.8",
52
82
  "prettier": "^3.8.1",
83
+ "size-limit": "^12.0.1",
53
84
  "tailwindcss": "^3.4.0",
54
85
  "turbo": "latest",
55
86
  "typescript": "^5.0.0",
@@ -57,16 +88,21 @@
57
88
  "vitest": "^1.0.0",
58
89
  "vue": "^3.5.0"
59
90
  },
60
- "version": "2.2.1",
91
+ "version": "2.3.0",
61
92
  "scripts": {
62
93
  "build:all": "turbo run build",
63
94
  "dev:all": "turbo run dev",
64
95
  "dev:example": "turbo run dev --filter=@example/*",
65
96
  "test:all": "turbo run test",
97
+ "test:coverage:all": "turbo run test:coverage",
66
98
  "lint:all": "turbo run lint",
67
99
  "dev:example:react": "pnpm --filter @example/react-demo dev",
68
100
  "dev:example:vue": "pnpm --filter @example/vue-demo dev",
69
101
  "build:example:react": "pnpm --filter @example/react-demo build",
70
- "build:example:vue": "pnpm --filter @example/vue-demo build"
102
+ "build:example:vue": "pnpm --filter @example/vue-demo build",
103
+ "changeset": "changeset",
104
+ "version-packages": "changeset version",
105
+ "release": "pnpm build:all && changeset publish",
106
+ "size": "size-limit"
71
107
  }
72
108
  }
@@ -14,6 +14,7 @@ var defaultErrorMessages = {
14
14
  custom: "Invalid value"
15
15
  };
16
16
  function formatMessage(template, field, rule) {
17
+ if (!template) return "";
17
18
  return template.replace("{label}", field.label).replace("{value}", String(rule.value || ""));
18
19
  }
19
20
  function get(obj, path, defaultValue) {
@@ -0,0 +1,108 @@
1
+ import {
2
+ get,
3
+ getDefaultValues,
4
+ normalizeFieldValue,
5
+ set,
6
+ validateFieldByName,
7
+ validateForm
8
+ } from "./chunk-T3LQTNYY.js";
9
+
10
+ // src/formState.ts
11
+ function createStore(initialState) {
12
+ let state = initialState;
13
+ const listeners = /* @__PURE__ */ new Set();
14
+ const getState = () => state;
15
+ const setState = (partial) => {
16
+ const nextState = typeof partial === "function" ? partial(state) : partial;
17
+ if (!Object.is(nextState, state)) {
18
+ const prevState = state;
19
+ state = { ...state, ...nextState };
20
+ listeners.forEach((listener) => listener(state, prevState));
21
+ }
22
+ };
23
+ const subscribe = (listener) => {
24
+ listeners.add(listener);
25
+ return () => listeners.delete(listener);
26
+ };
27
+ return { getState, setState, subscribe };
28
+ }
29
+ function createFormEngine(fields, resolver, errorMessages) {
30
+ const store = createStore({
31
+ values: getDefaultValues(fields),
32
+ errors: {},
33
+ validatingFields: [],
34
+ isSubmitting: false
35
+ });
36
+ const { getState, setState } = store;
37
+ const setFieldValue = async (name, rawValue) => {
38
+ const field = fields.find((f) => f.name === name);
39
+ const normalizedValue = field ? normalizeFieldValue(field, rawValue) : rawValue;
40
+ setState((s) => ({
41
+ values: set(s.values, name, normalizedValue)
42
+ }));
43
+ const hasExistingError = !!getState().errors[name];
44
+ const shouldValidateImmediately = field && ["select", "checkbox", "radio", "switch", "date"].includes(field.type);
45
+ if (shouldValidateImmediately || hasExistingError) {
46
+ setState((s) => ({
47
+ validatingFields: [...s.validatingFields, name]
48
+ }));
49
+ try {
50
+ const currentValues = getState().values;
51
+ const error = await validateFieldByName(fields, name, normalizedValue, resolver, currentValues, errorMessages);
52
+ setState((s) => ({
53
+ errors: { ...s.errors, [name]: error || "" },
54
+ validatingFields: s.validatingFields.filter((f) => f !== name)
55
+ }));
56
+ } catch {
57
+ setState((s) => ({
58
+ validatingFields: s.validatingFields.filter((f) => f !== name)
59
+ }));
60
+ }
61
+ }
62
+ };
63
+ const setFieldBlur = async (name) => {
64
+ setState((s) => ({
65
+ validatingFields: [...s.validatingFields, name]
66
+ }));
67
+ try {
68
+ const currentValues = getState().values;
69
+ const value = get(currentValues, name);
70
+ const error = await validateFieldByName(fields, name, value, resolver, currentValues, errorMessages);
71
+ setState((s) => ({
72
+ errors: { ...s.errors, [name]: error || "" },
73
+ validatingFields: s.validatingFields.filter((f) => f !== name)
74
+ }));
75
+ } catch {
76
+ setState((s) => ({
77
+ validatingFields: s.validatingFields.filter((f) => f !== name)
78
+ }));
79
+ }
80
+ };
81
+ const setSubmitting = (isSubmitting) => setState({ isSubmitting });
82
+ const runSubmitValidation = async () => {
83
+ setState({ isSubmitting: true });
84
+ const currentValues = getState().values;
85
+ const errors = await validateForm(fields, currentValues, resolver, errorMessages);
86
+ const hasError = Object.keys(errors).length > 0;
87
+ setState({
88
+ errors,
89
+ isSubmitting: false
90
+ });
91
+ return {
92
+ state: getState(),
93
+ hasError
94
+ };
95
+ };
96
+ return {
97
+ store,
98
+ setFieldValue,
99
+ setFieldBlur,
100
+ setSubmitting,
101
+ runSubmitValidation
102
+ };
103
+ }
104
+
105
+ export {
106
+ createStore,
107
+ createFormEngine
108
+ };
@@ -20,10 +20,10 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/formState.ts
21
21
  var formState_exports = {};
22
22
  __export(formState_exports, {
23
- createFormStore: () => createFormStore
23
+ createFormEngine: () => createFormEngine,
24
+ createStore: () => createStore
24
25
  });
25
26
  module.exports = __toCommonJS(formState_exports);
26
- var import_vanilla = require("zustand/vanilla");
27
27
 
28
28
  // src/utils.ts
29
29
  function parseNumberish(value) {
@@ -41,6 +41,7 @@ var defaultErrorMessages = {
41
41
  custom: "Invalid value"
42
42
  };
43
43
  function formatMessage(template, field, rule) {
44
+ if (!template) return "";
44
45
  return template.replace("{label}", field.label).replace("{value}", String(rule.value || ""));
45
46
  }
46
47
  function get(obj, path, defaultValue) {
@@ -176,74 +177,101 @@ function getDefaultValues(fields) {
176
177
  }
177
178
 
178
179
  // src/formState.ts
179
- function createFormStore(fields, resolver, errorMessages) {
180
- return (0, import_vanilla.createStore)()((set2, getStore) => ({
180
+ function createStore(initialState) {
181
+ let state = initialState;
182
+ const listeners = /* @__PURE__ */ new Set();
183
+ const getState = () => state;
184
+ const setState = (partial) => {
185
+ const nextState = typeof partial === "function" ? partial(state) : partial;
186
+ if (!Object.is(nextState, state)) {
187
+ const prevState = state;
188
+ state = { ...state, ...nextState };
189
+ listeners.forEach((listener) => listener(state, prevState));
190
+ }
191
+ };
192
+ const subscribe = (listener) => {
193
+ listeners.add(listener);
194
+ return () => listeners.delete(listener);
195
+ };
196
+ return { getState, setState, subscribe };
197
+ }
198
+ function createFormEngine(fields, resolver, errorMessages) {
199
+ const store = createStore({
181
200
  values: getDefaultValues(fields),
182
201
  errors: {},
183
202
  validatingFields: [],
184
- isSubmitting: false,
185
- setFieldValue: async (name, rawValue) => {
186
- const field = fields.find((f) => f.name === name);
187
- const normalizedValue = field ? normalizeFieldValue(field, rawValue) : rawValue;
188
- set2((state) => ({
189
- values: set(state.values, name, normalizedValue)
190
- }));
191
- const hasExistingError = !!getStore().errors[name];
192
- const shouldValidateImmediately = field && ["select", "checkbox", "radio", "switch", "date"].includes(field.type);
193
- if (shouldValidateImmediately || hasExistingError) {
194
- set2((state) => ({
195
- validatingFields: [...state.validatingFields, name]
196
- }));
197
- try {
198
- const currentValues = getStore().values;
199
- const error = await validateFieldByName(fields, name, normalizedValue, resolver, currentValues, errorMessages);
200
- set2((state) => ({
201
- errors: { ...state.errors, [name]: error || "" },
202
- validatingFields: state.validatingFields.filter((f) => f !== name)
203
- }));
204
- } catch (err) {
205
- set2((state) => ({
206
- validatingFields: state.validatingFields.filter((f) => f !== name)
207
- }));
208
- }
209
- }
210
- },
211
- setFieldBlur: async (name) => {
212
- set2((state) => ({
213
- validatingFields: [...state.validatingFields, name]
203
+ isSubmitting: false
204
+ });
205
+ const { getState, setState } = store;
206
+ const setFieldValue = async (name, rawValue) => {
207
+ const field = fields.find((f) => f.name === name);
208
+ const normalizedValue = field ? normalizeFieldValue(field, rawValue) : rawValue;
209
+ setState((s) => ({
210
+ values: set(s.values, name, normalizedValue)
211
+ }));
212
+ const hasExistingError = !!getState().errors[name];
213
+ const shouldValidateImmediately = field && ["select", "checkbox", "radio", "switch", "date"].includes(field.type);
214
+ if (shouldValidateImmediately || hasExistingError) {
215
+ setState((s) => ({
216
+ validatingFields: [...s.validatingFields, name]
214
217
  }));
215
218
  try {
216
- const currentValues = getStore().values;
217
- const value = get(currentValues, name);
218
- const error = await validateFieldByName(fields, name, value, resolver, currentValues, errorMessages);
219
- set2((state) => ({
220
- errors: { ...state.errors, [name]: error || "" },
221
- validatingFields: state.validatingFields.filter((f) => f !== name)
219
+ const currentValues = getState().values;
220
+ const error = await validateFieldByName(fields, name, normalizedValue, resolver, currentValues, errorMessages);
221
+ setState((s) => ({
222
+ errors: { ...s.errors, [name]: error || "" },
223
+ validatingFields: s.validatingFields.filter((f) => f !== name)
222
224
  }));
223
- } catch (err) {
224
- set2((state) => ({
225
- validatingFields: state.validatingFields.filter((f) => f !== name)
225
+ } catch {
226
+ setState((s) => ({
227
+ validatingFields: s.validatingFields.filter((f) => f !== name)
226
228
  }));
227
229
  }
228
- },
229
- setSubmitting: (isSubmitting) => set2({ isSubmitting }),
230
- runSubmitValidation: async () => {
231
- set2({ isSubmitting: true });
232
- const state = getStore();
233
- const errors = await validateForm(fields, state.values, resolver, errorMessages);
234
- const hasError = Object.keys(errors).length > 0;
235
- set2({
236
- errors,
237
- isSubmitting: false
238
- });
239
- return {
240
- state: getStore(),
241
- hasError
242
- };
243
230
  }
244
- }));
231
+ };
232
+ const setFieldBlur = async (name) => {
233
+ setState((s) => ({
234
+ validatingFields: [...s.validatingFields, name]
235
+ }));
236
+ try {
237
+ const currentValues = getState().values;
238
+ const value = get(currentValues, name);
239
+ const error = await validateFieldByName(fields, name, value, resolver, currentValues, errorMessages);
240
+ setState((s) => ({
241
+ errors: { ...s.errors, [name]: error || "" },
242
+ validatingFields: s.validatingFields.filter((f) => f !== name)
243
+ }));
244
+ } catch {
245
+ setState((s) => ({
246
+ validatingFields: s.validatingFields.filter((f) => f !== name)
247
+ }));
248
+ }
249
+ };
250
+ const setSubmitting = (isSubmitting) => setState({ isSubmitting });
251
+ const runSubmitValidation = async () => {
252
+ setState({ isSubmitting: true });
253
+ const currentValues = getState().values;
254
+ const errors = await validateForm(fields, currentValues, resolver, errorMessages);
255
+ const hasError = Object.keys(errors).length > 0;
256
+ setState({
257
+ errors,
258
+ isSubmitting: false
259
+ });
260
+ return {
261
+ state: getState(),
262
+ hasError
263
+ };
264
+ };
265
+ return {
266
+ store,
267
+ setFieldValue,
268
+ setFieldBlur,
269
+ setSubmitting,
270
+ runSubmitValidation
271
+ };
245
272
  }
246
273
  // Annotate the CommonJS export names for ESM import in node:
247
274
  0 && (module.exports = {
248
- createFormStore
275
+ createFormEngine,
276
+ createStore
249
277
  });
@@ -1,13 +1,20 @@
1
- import * as zustand_vanilla from 'zustand/vanilla';
2
1
  import { FormField, FormResolver, ErrorMessageTemplates } from './types.cjs';
3
2
 
3
+ type StoreListener<T> = (state: T, prevState: T) => void;
4
+ interface VanillaStore<T> {
5
+ getState: () => T;
6
+ setState: (partial: Partial<T> | ((state: T) => Partial<T>)) => void;
7
+ subscribe: (listener: StoreListener<T>) => () => void;
8
+ }
9
+ declare function createStore<T>(initialState: T): VanillaStore<T>;
4
10
  interface FormRuntimeState {
5
- values: Record<string, any>;
11
+ values: Record<string, unknown>;
6
12
  errors: Record<string, string>;
7
13
  validatingFields: string[];
8
14
  isSubmitting: boolean;
9
15
  }
10
- interface FormStore extends FormRuntimeState {
16
+ interface FormEngine {
17
+ store: VanillaStore<FormRuntimeState>;
11
18
  setFieldValue: (name: string, rawValue: unknown) => Promise<void>;
12
19
  setFieldBlur: (name: string) => Promise<void>;
13
20
  setSubmitting: (isSubmitting: boolean) => void;
@@ -16,6 +23,6 @@ interface FormStore extends FormRuntimeState {
16
23
  hasError: boolean;
17
24
  }>;
18
25
  }
19
- declare function createFormStore(fields: FormField[], resolver?: FormResolver, errorMessages?: ErrorMessageTemplates): zustand_vanilla.StoreApi<FormStore>;
26
+ declare function createFormEngine(fields: FormField[], resolver?: FormResolver, errorMessages?: ErrorMessageTemplates): FormEngine;
20
27
 
21
- export { type FormRuntimeState, type FormStore, createFormStore };
28
+ export { type FormEngine, type FormRuntimeState, type StoreListener, type VanillaStore, createFormEngine, createStore };
@@ -1,13 +1,20 @@
1
- import * as zustand_vanilla from 'zustand/vanilla';
2
1
  import { FormField, FormResolver, ErrorMessageTemplates } from './types.js';
3
2
 
3
+ type StoreListener<T> = (state: T, prevState: T) => void;
4
+ interface VanillaStore<T> {
5
+ getState: () => T;
6
+ setState: (partial: Partial<T> | ((state: T) => Partial<T>)) => void;
7
+ subscribe: (listener: StoreListener<T>) => () => void;
8
+ }
9
+ declare function createStore<T>(initialState: T): VanillaStore<T>;
4
10
  interface FormRuntimeState {
5
- values: Record<string, any>;
11
+ values: Record<string, unknown>;
6
12
  errors: Record<string, string>;
7
13
  validatingFields: string[];
8
14
  isSubmitting: boolean;
9
15
  }
10
- interface FormStore extends FormRuntimeState {
16
+ interface FormEngine {
17
+ store: VanillaStore<FormRuntimeState>;
11
18
  setFieldValue: (name: string, rawValue: unknown) => Promise<void>;
12
19
  setFieldBlur: (name: string) => Promise<void>;
13
20
  setSubmitting: (isSubmitting: boolean) => void;
@@ -16,6 +23,6 @@ interface FormStore extends FormRuntimeState {
16
23
  hasError: boolean;
17
24
  }>;
18
25
  }
19
- declare function createFormStore(fields: FormField[], resolver?: FormResolver, errorMessages?: ErrorMessageTemplates): zustand_vanilla.StoreApi<FormStore>;
26
+ declare function createFormEngine(fields: FormField[], resolver?: FormResolver, errorMessages?: ErrorMessageTemplates): FormEngine;
20
27
 
21
- export { type FormRuntimeState, type FormStore, createFormStore };
28
+ export { type FormEngine, type FormRuntimeState, type StoreListener, type VanillaStore, createFormEngine, createStore };
@@ -1,7 +1,9 @@
1
1
  import {
2
- createFormStore
3
- } from "./chunk-J6ESJZ4U.js";
4
- import "./chunk-B7OMM2UC.js";
2
+ createFormEngine,
3
+ createStore
4
+ } from "./chunk-V4VK2GZU.js";
5
+ import "./chunk-T3LQTNYY.js";
5
6
  export {
6
- createFormStore
7
+ createFormEngine,
8
+ createStore
7
9
  };