@xbeeant/form-engine-designer 0.0.1 → 0.0.3
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 +75 -66
- package/dist/es/Canvas.js +3 -2
- package/dist/es/Canvas.js.map +1 -1
- package/dist/es/PropertyPanel.js +3 -2
- package/dist/es/PropertyPanel.js.map +1 -1
- package/dist/es/catalog.js +2 -1
- package/dist/es/catalog.js.map +1 -1
- package/dist/es/index.css +1 -0
- package/dist/es/react/src/components/FormController.js +6 -0
- package/dist/es/react/src/components/FormController.js.map +1 -1
- package/dist/es/react/src/components/NexusField.js +59 -60
- package/dist/es/react/src/components/NexusField.js.map +1 -1
- package/dist/es/react/src/components/NexusForm.js +82 -75
- package/dist/es/react/src/components/NexusForm.js.map +1 -1
- package/dist/es/react/src/hooks/useForm.js +9 -6
- package/dist/es/react/src/hooks/useForm.js.map +1 -1
- package/package.json +5 -4
- package/src/catalog.ts +1 -0
- package/dist/es/form-engine-designer.css +0 -1
- package/dist/es/schemaUtils.test.js +0 -188
- package/dist/es/schemaUtils.test.js.map +0 -1
- package/dist/es/vite-env.d.js +0 -2
- package/dist/es/vite-env.d.js.map +0 -1
- package/dist/es/widgets/expressionModel.test.js +0 -193
- package/dist/es/widgets/expressionModel.test.js.map +0 -1
|
@@ -1,193 +0,0 @@
|
|
|
1
|
-
import { describe as c, it as o, expect as t } from "/Users/amybee/Codes/xbeeant/nexus-form-engine/node_modules/.bun/vitest@4.1.10+0a9a94c82e2ce81a/node_modules/vitest/dist/index.js";
|
|
2
|
-
import { collectDataFieldPaths as n } from "../schemaUtils.js";
|
|
3
|
-
import { buildExpression as e, parseExpression as i, stripBraces as p, variableToString as s, parseVariable as d } from "./expressionModel.js";
|
|
4
|
-
c("buildExpression", () => {
|
|
5
|
-
o("构建基本比较表达式(文本 / 数字 / 布尔 / 变量右值)", () => {
|
|
6
|
-
t(
|
|
7
|
-
e([
|
|
8
|
-
{
|
|
9
|
-
id: "1",
|
|
10
|
-
logic: "and",
|
|
11
|
-
variable: { source: "formData", path: "usePromo" },
|
|
12
|
-
operator: "eq",
|
|
13
|
-
rightMode: "boolean",
|
|
14
|
-
right: "true"
|
|
15
|
-
}
|
|
16
|
-
])
|
|
17
|
-
).toBe("{{ formData.usePromo === true }}"), t(
|
|
18
|
-
e([
|
|
19
|
-
{
|
|
20
|
-
id: "1",
|
|
21
|
-
logic: "and",
|
|
22
|
-
variable: { source: "formData", path: "amount" },
|
|
23
|
-
operator: "gte",
|
|
24
|
-
rightMode: "number",
|
|
25
|
-
right: "100"
|
|
26
|
-
}
|
|
27
|
-
])
|
|
28
|
-
).toBe("{{ formData.amount >= 100 }}"), t(
|
|
29
|
-
e([
|
|
30
|
-
{
|
|
31
|
-
id: "1",
|
|
32
|
-
logic: "and",
|
|
33
|
-
variable: { source: "self", path: "" },
|
|
34
|
-
operator: "neq",
|
|
35
|
-
rightMode: "string",
|
|
36
|
-
right: "special"
|
|
37
|
-
}
|
|
38
|
-
])
|
|
39
|
-
).toBe("{{ $self.value !== 'special' }}"), t(
|
|
40
|
-
e([
|
|
41
|
-
{
|
|
42
|
-
id: "1",
|
|
43
|
-
logic: "and",
|
|
44
|
-
variable: { source: "formData", path: "amount" },
|
|
45
|
-
operator: "eq",
|
|
46
|
-
rightMode: "variable",
|
|
47
|
-
right: "formData.limit"
|
|
48
|
-
}
|
|
49
|
-
])
|
|
50
|
-
).toBe("{{ formData.amount === formData.limit }}");
|
|
51
|
-
}), o("空右值 / 未选变量视为不完整条件,返回空模板", () => {
|
|
52
|
-
t(
|
|
53
|
-
e([
|
|
54
|
-
{
|
|
55
|
-
id: "1",
|
|
56
|
-
logic: "and",
|
|
57
|
-
variable: { source: "formData", path: "" },
|
|
58
|
-
operator: "eq",
|
|
59
|
-
rightMode: "string",
|
|
60
|
-
right: "x"
|
|
61
|
-
}
|
|
62
|
-
])
|
|
63
|
-
).toBe("{{ }}"), t(
|
|
64
|
-
e([
|
|
65
|
-
{
|
|
66
|
-
id: "1",
|
|
67
|
-
logic: "and",
|
|
68
|
-
variable: { source: "formData", path: "a" },
|
|
69
|
-
operator: "eq",
|
|
70
|
-
rightMode: "string",
|
|
71
|
-
right: ""
|
|
72
|
-
}
|
|
73
|
-
])
|
|
74
|
-
).toBe("{{ }}");
|
|
75
|
-
}), o("无条件时返回空模板", () => {
|
|
76
|
-
t(e([])).toBe("{{ }}");
|
|
77
|
-
}), o("按 and/or 连接多条条件", () => {
|
|
78
|
-
const a = (u, m) => ({
|
|
79
|
-
id: Math.random().toString(),
|
|
80
|
-
logic: "and",
|
|
81
|
-
variable: { source: "formData", path: "a" },
|
|
82
|
-
operator: u,
|
|
83
|
-
rightMode: "string",
|
|
84
|
-
right: m
|
|
85
|
-
}), r = { ...a("eq", "x"), id: "1" }, l = { ...a("neq", "y"), id: "2", logic: "or" };
|
|
86
|
-
t(e([r, l])).toBe(
|
|
87
|
-
"{{ formData.a === 'x' || formData.a !== 'y' }}"
|
|
88
|
-
);
|
|
89
|
-
}), o("contains / startsWith / empty / truthy 等操作符", () => {
|
|
90
|
-
const a = (r, l = "") => ({
|
|
91
|
-
id: "1",
|
|
92
|
-
logic: "and",
|
|
93
|
-
variable: { source: "formData", path: "code" },
|
|
94
|
-
operator: r,
|
|
95
|
-
rightMode: "string",
|
|
96
|
-
right: l
|
|
97
|
-
});
|
|
98
|
-
t(e([a("contains", "CN")])).toBe(
|
|
99
|
-
"{{ String(formData.code).includes('CN') }}"
|
|
100
|
-
), t(e([a("notEmpty")])).toBe(
|
|
101
|
-
"{{ (formData.code != null && String(formData.code).trim() !== '') }}"
|
|
102
|
-
), t(e([a("truthy")])).toBe("{{ !!(formData.code) }}");
|
|
103
|
-
});
|
|
104
|
-
});
|
|
105
|
-
c("parseExpression", () => {
|
|
106
|
-
o("解析基本表达式为行模型", () => {
|
|
107
|
-
const a = i("{{ formData.usePromo === true }}");
|
|
108
|
-
t(a).not.toBeNull(), t(a[0]).toMatchObject({
|
|
109
|
-
variable: { source: "formData", path: "usePromo" },
|
|
110
|
-
operator: "eq",
|
|
111
|
-
rightMode: "boolean",
|
|
112
|
-
right: "true"
|
|
113
|
-
});
|
|
114
|
-
}), o("解析 $deps / $self / 文本字面量", () => {
|
|
115
|
-
const a = i("{{ $deps[0] === true }}");
|
|
116
|
-
t(a[0].variable).toEqual({ source: "deps", path: "0" });
|
|
117
|
-
const r = i("{{ $self.value === 'x' }}");
|
|
118
|
-
t(r[0].variable).toEqual({ source: "self", path: "" }), t(r[0].rightMode).toBe("string"), t(r[0].right).toBe("x");
|
|
119
|
-
}), o("解析 and/or 连接", () => {
|
|
120
|
-
const a = i(
|
|
121
|
-
"{{ formData.a === 'x' && formData.b > 3 || formData.c == 'y' }}"
|
|
122
|
-
);
|
|
123
|
-
t(a.length).toBe(3), t(a[0].logic).toBe("and"), t(a[1].logic).toBe("and"), t(a[2].logic).toBe("or");
|
|
124
|
-
}), o("解析空模板 / 空串为 []", () => {
|
|
125
|
-
t(i("{{ }}")).toEqual([]), t(i("")).toEqual([]), t(i(void 0)).toEqual([]);
|
|
126
|
-
}), o("无法解析的表达式返回 null(回退高级模式)", () => {
|
|
127
|
-
t(i("{{ formData.a.toUpperCase() }}")).toBeNull(), t(i("{{ $deps[0] + 1 > 2 }}")).toBeNull();
|
|
128
|
-
}), o("round-trip:build → parse → build 保持一致", () => {
|
|
129
|
-
const a = "{{ formData.a === 'x' || formData.b >= 3 }}", r = i(a);
|
|
130
|
-
t(r.length).toBe(2);
|
|
131
|
-
const l = e(r);
|
|
132
|
-
t(l).toBe(a);
|
|
133
|
-
});
|
|
134
|
-
});
|
|
135
|
-
c("变量工具", () => {
|
|
136
|
-
o("stripBraces 去除包裹", () => {
|
|
137
|
-
t(p("{{ a === 1 }}")).toBe("a === 1"), t(p("a === 1")).toBe("a === 1");
|
|
138
|
-
}), o("variableToString 各来源", () => {
|
|
139
|
-
t(s({ source: "formData", path: "user.name" })).toBe(
|
|
140
|
-
"formData.user.name"
|
|
141
|
-
), t(s({ source: "deps", path: "2" })).toBe("$deps[2]"), t(s({ source: "self", path: "" })).toBe("$self.value"), t(s({ source: "index", path: "" })).toBe("$index"), t(s({ source: "root", path: "" })).toBe("rootValue");
|
|
142
|
-
}), o("parseVariable 非标识符字段用括号访问", () => {
|
|
143
|
-
t(d("formData['a-b']")).toEqual({
|
|
144
|
-
source: "formData",
|
|
145
|
-
path: "a-b"
|
|
146
|
-
}), t(s(d("formData['a-b']"))).toBe(
|
|
147
|
-
"formData['a-b']"
|
|
148
|
-
);
|
|
149
|
-
});
|
|
150
|
-
});
|
|
151
|
-
c("collectDataFieldPaths", () => {
|
|
152
|
-
o("布局节点 Key 不进路径,对象 / 数组透传", () => {
|
|
153
|
-
t(n({
|
|
154
|
-
properties: {
|
|
155
|
-
card: {
|
|
156
|
-
type: "card",
|
|
157
|
-
title: "卡片",
|
|
158
|
-
properties: {
|
|
159
|
-
name: { type: "string", widget: "input", title: "姓名" },
|
|
160
|
-
address: {
|
|
161
|
-
type: "object",
|
|
162
|
-
properties: {
|
|
163
|
-
city: { type: "string", widget: "input" }
|
|
164
|
-
}
|
|
165
|
-
},
|
|
166
|
-
tags: {
|
|
167
|
-
type: "array",
|
|
168
|
-
widget: "list",
|
|
169
|
-
items: {
|
|
170
|
-
type: "object",
|
|
171
|
-
properties: {
|
|
172
|
-
label: { type: "string", widget: "input" }
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
})).toEqual([
|
|
180
|
-
"name",
|
|
181
|
-
"address.city",
|
|
182
|
-
"tags",
|
|
183
|
-
"tags[0].label"
|
|
184
|
-
]);
|
|
185
|
-
}), o("子表单(带 widget 的 object)视为叶子字段", () => {
|
|
186
|
-
t(n({
|
|
187
|
-
properties: {
|
|
188
|
-
sub: { type: "object", widget: "subForm", properties: {} }
|
|
189
|
-
}
|
|
190
|
-
})).toEqual(["sub"]);
|
|
191
|
-
});
|
|
192
|
-
});
|
|
193
|
-
//# sourceMappingURL=expressionModel.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"expressionModel.test.js","sources":["../../../src/widgets/expressionModel.test.ts"],"sourcesContent":["import type { NexusSchema } from '@xbeeant/form-engine';\nimport { describe, expect, it } from 'vitest';\nimport { collectDataFieldPaths } from '../schemaUtils';\nimport {\n buildExpression,\n type ConditionOperator,\n parseExpression,\n parseVariable,\n stripBraces,\n variableToString,\n} from './expressionModel';\n\ndescribe('buildExpression', () => {\n it('构建基本比较表达式(文本 / 数字 / 布尔 / 变量右值)', () => {\n expect(\n buildExpression([\n {\n id: '1',\n logic: 'and',\n variable: { source: 'formData', path: 'usePromo' },\n operator: 'eq',\n rightMode: 'boolean',\n right: 'true',\n },\n ]),\n ).toBe('{{ formData.usePromo === true }}');\n\n expect(\n buildExpression([\n {\n id: '1',\n logic: 'and',\n variable: { source: 'formData', path: 'amount' },\n operator: 'gte',\n rightMode: 'number',\n right: '100',\n },\n ]),\n ).toBe('{{ formData.amount >= 100 }}');\n\n expect(\n buildExpression([\n {\n id: '1',\n logic: 'and',\n variable: { source: 'self', path: '' },\n operator: 'neq',\n rightMode: 'string',\n right: 'special',\n },\n ]),\n ).toBe(\"{{ $self.value !== 'special' }}\");\n\n expect(\n buildExpression([\n {\n id: '1',\n logic: 'and',\n variable: { source: 'formData', path: 'amount' },\n operator: 'eq',\n rightMode: 'variable',\n right: 'formData.limit',\n },\n ]),\n ).toBe('{{ formData.amount === formData.limit }}');\n });\n\n it('空右值 / 未选变量视为不完整条件,返回空模板', () => {\n expect(\n buildExpression([\n {\n id: '1',\n logic: 'and',\n variable: { source: 'formData', path: '' },\n operator: 'eq',\n rightMode: 'string',\n right: 'x',\n },\n ]),\n ).toBe('{{ }}');\n\n expect(\n buildExpression([\n {\n id: '1',\n logic: 'and',\n variable: { source: 'formData', path: 'a' },\n operator: 'eq',\n rightMode: 'string',\n right: '',\n },\n ]),\n ).toBe('{{ }}');\n });\n\n it('无条件时返回空模板', () => {\n expect(buildExpression([])).toBe('{{ }}');\n });\n\n it('按 and/or 连接多条条件', () => {\n const cond = (op: 'eq' | 'neq', right: string) => ({\n id: Math.random().toString(),\n logic: 'and' as const,\n variable: { source: 'formData' as const, path: 'a' },\n operator: op,\n rightMode: 'string' as const,\n right,\n });\n const c1 = { ...cond('eq', 'x'), id: '1' };\n const c2 = { ...cond('neq', 'y'), id: '2', logic: 'or' as const };\n expect(buildExpression([c1, c2])).toBe(\n \"{{ formData.a === 'x' || formData.a !== 'y' }}\",\n );\n });\n\n it('contains / startsWith / empty / truthy 等操作符', () => {\n const base = (operator: ConditionOperator, right = '') => ({\n id: '1',\n logic: 'and' as const,\n variable: { source: 'formData' as const, path: 'code' },\n operator,\n rightMode: 'string' as const,\n right,\n });\n expect(buildExpression([base('contains', 'CN')])).toBe(\n \"{{ String(formData.code).includes('CN') }}\",\n );\n expect(buildExpression([base('notEmpty')])).toBe(\n \"{{ (formData.code != null && String(formData.code).trim() !== '') }}\",\n );\n expect(buildExpression([base('truthy')])).toBe('{{ !!(formData.code) }}');\n });\n});\n\ndescribe('parseExpression', () => {\n it('解析基本表达式为行模型', () => {\n const conds = parseExpression('{{ formData.usePromo === true }}');\n expect(conds).not.toBeNull();\n expect(conds![0]).toMatchObject({\n variable: { source: 'formData', path: 'usePromo' },\n operator: 'eq',\n rightMode: 'boolean',\n right: 'true',\n });\n });\n\n it('解析 $deps / $self / 文本字面量', () => {\n const conds = parseExpression('{{ $deps[0] === true }}');\n expect(conds![0].variable).toEqual({ source: 'deps', path: '0' });\n\n const self = parseExpression(\"{{ $self.value === 'x' }}\");\n expect(self![0].variable).toEqual({ source: 'self', path: '' });\n expect(self![0].rightMode).toBe('string');\n expect(self![0].right).toBe('x');\n });\n\n it('解析 and/or 连接', () => {\n const conds = parseExpression(\n \"{{ formData.a === 'x' && formData.b > 3 || formData.c == 'y' }}\",\n );\n expect(conds!.length).toBe(3);\n expect(conds![0].logic).toBe('and');\n expect(conds![1].logic).toBe('and');\n expect(conds![2].logic).toBe('or');\n });\n\n it('解析空模板 / 空串为 []', () => {\n expect(parseExpression('{{ }}')).toEqual([]);\n expect(parseExpression('')).toEqual([]);\n expect(parseExpression(undefined)).toEqual([]);\n });\n\n it('无法解析的表达式返回 null(回退高级模式)', () => {\n expect(parseExpression('{{ formData.a.toUpperCase() }}')).toBeNull();\n expect(parseExpression('{{ $deps[0] + 1 > 2 }}')).toBeNull();\n });\n\n it('round-trip:build → parse → build 保持一致', () => {\n const src = \"{{ formData.a === 'x' || formData.b >= 3 }}\";\n const conds = parseExpression(src)!;\n expect(conds.length).toBe(2);\n const rebuilt = buildExpression(conds);\n expect(rebuilt).toBe(src);\n });\n});\n\ndescribe('变量工具', () => {\n it('stripBraces 去除包裹', () => {\n expect(stripBraces('{{ a === 1 }}')).toBe('a === 1');\n expect(stripBraces('a === 1')).toBe('a === 1');\n });\n\n it('variableToString 各来源', () => {\n expect(variableToString({ source: 'formData', path: 'user.name' })).toBe(\n 'formData.user.name',\n );\n expect(variableToString({ source: 'deps', path: '2' })).toBe('$deps[2]');\n expect(variableToString({ source: 'self', path: '' })).toBe('$self.value');\n expect(variableToString({ source: 'index', path: '' })).toBe('$index');\n expect(variableToString({ source: 'root', path: '' })).toBe('rootValue');\n });\n\n it('parseVariable 非标识符字段用括号访问', () => {\n expect(parseVariable(\"formData['a-b']\")).toEqual({\n source: 'formData',\n path: 'a-b',\n });\n expect(variableToString(parseVariable(\"formData['a-b']\"))).toBe(\n \"formData['a-b']\",\n );\n });\n});\n\ndescribe('collectDataFieldPaths', () => {\n it('布局节点 Key 不进路径,对象 / 数组透传', () => {\n const schema = {\n type: 'object',\n properties: {\n card: {\n type: 'card',\n title: '卡片',\n properties: {\n name: { type: 'string', widget: 'input', title: '姓名' },\n address: {\n type: 'object',\n properties: {\n city: { type: 'string', widget: 'input' },\n },\n },\n tags: {\n type: 'array',\n widget: 'list',\n items: {\n type: 'object',\n properties: {\n label: { type: 'string', widget: 'input' },\n },\n },\n },\n },\n },\n },\n } as unknown as NexusSchema;\n\n expect(collectDataFieldPaths(schema)).toEqual([\n 'name',\n 'address.city',\n 'tags',\n 'tags[0].label',\n ]);\n });\n\n it('子表单(带 widget 的 object)视为叶子字段', () => {\n const schema = {\n type: 'object',\n properties: {\n sub: { type: 'object', widget: 'subForm', properties: {} },\n },\n } as unknown as NexusSchema;\n expect(collectDataFieldPaths(schema)).toEqual(['sub']);\n });\n});\n"],"names":["describe","it","expect","buildExpression","cond","op","right","c1","c2","base","operator","conds","parseExpression","self","src","rebuilt","stripBraces","variableToString","parseVariable","collectDataFieldPaths"],"mappings":"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"}
|