@logixjs/form 0.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/dist/Error-VvknI9Wj.d.cts +37 -0
- package/dist/Error-VvknI9Wj.d.ts +37 -0
- package/dist/Error.cjs +46 -0
- package/dist/Error.cjs.map +1 -0
- package/dist/Error.d.cts +1 -0
- package/dist/Error.d.ts +1 -0
- package/dist/Error.js +14 -0
- package/dist/Error.js.map +1 -0
- package/dist/Form.cjs +2455 -0
- package/dist/Form.cjs.map +1 -0
- package/dist/Form.d.cts +64 -0
- package/dist/Form.d.ts +64 -0
- package/dist/Form.js +25 -0
- package/dist/Form.js.map +1 -0
- package/dist/FormView-CAg9LVrf.d.cts +17 -0
- package/dist/FormView-CAg9LVrf.d.ts +17 -0
- package/dist/FormView.cjs +61 -0
- package/dist/FormView.cjs.map +1 -0
- package/dist/FormView.d.cts +1 -0
- package/dist/FormView.d.ts +1 -0
- package/dist/FormView.js +8 -0
- package/dist/FormView.js.map +1 -0
- package/dist/Path-DOjMkAS6.d.cts +42 -0
- package/dist/Path-DOjMkAS6.d.ts +42 -0
- package/dist/Path.cjs +132 -0
- package/dist/Path.cjs.map +1 -0
- package/dist/Path.d.cts +1 -0
- package/dist/Path.d.ts +1 -0
- package/dist/Path.js +22 -0
- package/dist/Path.js.map +1 -0
- package/dist/Rule-BOAiSVz9.d.cts +202 -0
- package/dist/Rule-BOAiSVz9.d.ts +202 -0
- package/dist/Rule.cjs +307 -0
- package/dist/Rule.cjs.map +1 -0
- package/dist/Rule.d.cts +2 -0
- package/dist/Rule.d.ts +2 -0
- package/dist/Rule.js +34 -0
- package/dist/Rule.js.map +1 -0
- package/dist/SchemaErrorMapping-Cu5gl7-Z.d.ts +50 -0
- package/dist/SchemaErrorMapping-DOrgLzii.d.cts +50 -0
- package/dist/SchemaErrorMapping.cjs +305 -0
- package/dist/SchemaErrorMapping.cjs.map +1 -0
- package/dist/SchemaErrorMapping.d.cts +2 -0
- package/dist/SchemaErrorMapping.d.ts +2 -0
- package/dist/SchemaErrorMapping.js +17 -0
- package/dist/SchemaErrorMapping.js.map +1 -0
- package/dist/SchemaPathMapping-BCoUW-_q.d.ts +16 -0
- package/dist/SchemaPathMapping-BUq2zm8W.d.cts +20 -0
- package/dist/SchemaPathMapping-BUq2zm8W.d.ts +20 -0
- package/dist/SchemaPathMapping-DJnExqM3.d.cts +16 -0
- package/dist/SchemaPathMapping.cjs +179 -0
- package/dist/SchemaPathMapping.cjs.map +1 -0
- package/dist/SchemaPathMapping.d.cts +2 -0
- package/dist/SchemaPathMapping.d.ts +2 -0
- package/dist/SchemaPathMapping.js +12 -0
- package/dist/SchemaPathMapping.js.map +1 -0
- package/dist/Trait-Bu794ROY.d.cts +49 -0
- package/dist/Trait-Bu794ROY.d.ts +49 -0
- package/dist/Trait.cjs +48 -0
- package/dist/Trait.cjs.map +1 -0
- package/dist/Trait.d.cts +2 -0
- package/dist/Trait.d.ts +2 -0
- package/dist/Trait.js +12 -0
- package/dist/Trait.js.map +1 -0
- package/dist/chunk-5DRI5UGD.js +105 -0
- package/dist/chunk-5DRI5UGD.js.map +1 -0
- package/dist/chunk-AD2ZA7KA.js +23 -0
- package/dist/chunk-AD2ZA7KA.js.map +1 -0
- package/dist/chunk-EOXJRCM6.js +146 -0
- package/dist/chunk-EOXJRCM6.js.map +1 -0
- package/dist/chunk-JZ5FZKPJ.js +71 -0
- package/dist/chunk-JZ5FZKPJ.js.map +1 -0
- package/dist/chunk-LNJJPZAG.js +46 -0
- package/dist/chunk-LNJJPZAG.js.map +1 -0
- package/dist/chunk-NAR5SIFP.js +22 -0
- package/dist/chunk-NAR5SIFP.js.map +1 -0
- package/dist/chunk-OJVEZKU7.js +117 -0
- package/dist/chunk-OJVEZKU7.js.map +1 -0
- package/dist/chunk-PZ5AY32C.js +10 -0
- package/dist/chunk-PZ5AY32C.js.map +1 -0
- package/dist/chunk-S5JTU2CM.js +31 -0
- package/dist/chunk-S5JTU2CM.js.map +1 -0
- package/dist/chunk-YHDEJ47V.js +1885 -0
- package/dist/chunk-YHDEJ47V.js.map +1 -0
- package/dist/chunk-YVHXLY63.js +315 -0
- package/dist/chunk-YVHXLY63.js.map +1 -0
- package/dist/impl-BfSlyM58.d.ts +225 -0
- package/dist/impl-Ccdm5eDF.d.cts +225 -0
- package/dist/index.cjs +2689 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +12 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +56 -0
- package/dist/index.js.map +1 -0
- package/dist/react/index.cjs +332 -0
- package/dist/react/index.cjs.map +1 -0
- package/dist/react/index.d.cts +43 -0
- package/dist/react/index.d.ts +43 -0
- package/dist/react/index.js +201 -0
- package/dist/react/index.js.map +1 -0
- package/package.json +62 -0
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__export
|
|
3
|
+
} from "./chunk-PZ5AY32C.js";
|
|
4
|
+
|
|
5
|
+
// src/Rule.ts
|
|
6
|
+
var Rule_exports = {};
|
|
7
|
+
__export(Rule_exports, {
|
|
8
|
+
ERROR_VALUE_MAX_BYTES: () => ERROR_VALUE_MAX_BYTES,
|
|
9
|
+
assertErrorValueBudget: () => assertErrorValueBudget,
|
|
10
|
+
field: () => field,
|
|
11
|
+
fields: () => fields,
|
|
12
|
+
list: () => list,
|
|
13
|
+
make: () => make,
|
|
14
|
+
max: () => max,
|
|
15
|
+
maxLength: () => maxLength,
|
|
16
|
+
merge: () => merge,
|
|
17
|
+
min: () => min,
|
|
18
|
+
minLength: () => minLength,
|
|
19
|
+
pattern: () => pattern,
|
|
20
|
+
required: () => required,
|
|
21
|
+
root: () => root
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
// src/internal/validators/index.ts
|
|
25
|
+
import { ParseResult } from "effect";
|
|
26
|
+
var ERROR_VALUE_MAX_BYTES = 256;
|
|
27
|
+
var textEncoder = new TextEncoder();
|
|
28
|
+
var jsonByteSize = (value) => {
|
|
29
|
+
const json = JSON.stringify(value);
|
|
30
|
+
return textEncoder.encode(json).length;
|
|
31
|
+
};
|
|
32
|
+
var truncateToJsonByteBudget = (value, maxBytes) => {
|
|
33
|
+
if (jsonByteSize(value) <= maxBytes) return value;
|
|
34
|
+
let lo = 0;
|
|
35
|
+
let hi = value.length;
|
|
36
|
+
while (lo < hi) {
|
|
37
|
+
const mid = Math.ceil((lo + hi) / 2);
|
|
38
|
+
const slice = value.slice(0, mid);
|
|
39
|
+
if (jsonByteSize(slice) <= maxBytes) lo = mid;
|
|
40
|
+
else hi = mid - 1;
|
|
41
|
+
}
|
|
42
|
+
return value.slice(0, lo);
|
|
43
|
+
};
|
|
44
|
+
var assertErrorValueBudget = (value, label) => {
|
|
45
|
+
const bytes = jsonByteSize(value);
|
|
46
|
+
if (bytes <= ERROR_VALUE_MAX_BYTES) return value;
|
|
47
|
+
throw new Error(`[Form.validators] ErrorValue for "${label}" must be JSON \u2264${ERROR_VALUE_MAX_BYTES}B (got ${bytes}B)`);
|
|
48
|
+
};
|
|
49
|
+
var errorValue = (label, value) => assertErrorValueBudget(value, label);
|
|
50
|
+
var required = (decl) => {
|
|
51
|
+
const trim = typeof decl === "object" && decl !== null ? Boolean(decl.trim) : true;
|
|
52
|
+
const message = typeof decl === "string" ? decl : typeof decl === "object" && decl !== null && typeof decl.message === "string" ? decl.message : "required";
|
|
53
|
+
const err = errorValue("required", message);
|
|
54
|
+
return (value) => {
|
|
55
|
+
if (value === null || value === void 0) return err;
|
|
56
|
+
if (typeof value === "string") {
|
|
57
|
+
const v = trim ? value.trim() : value;
|
|
58
|
+
return v.length > 0 ? void 0 : err;
|
|
59
|
+
}
|
|
60
|
+
if (Array.isArray(value)) return value.length > 0 ? void 0 : err;
|
|
61
|
+
if (typeof value === "boolean") return value ? void 0 : err;
|
|
62
|
+
return void 0;
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
var minLength = (decl) => {
|
|
66
|
+
const min2 = typeof decl === "number" ? decl : decl.min;
|
|
67
|
+
const message = typeof decl === "object" && decl !== null && typeof decl.message === "string" ? decl.message : "minLength";
|
|
68
|
+
const err = errorValue("minLength", message);
|
|
69
|
+
return (value) => {
|
|
70
|
+
if (value === null || value === void 0) return void 0;
|
|
71
|
+
if (typeof value === "string") return value.length >= min2 ? void 0 : err;
|
|
72
|
+
if (Array.isArray(value)) return value.length >= min2 ? void 0 : err;
|
|
73
|
+
return void 0;
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
var maxLength = (decl) => {
|
|
77
|
+
const max2 = typeof decl === "number" ? decl : decl.max;
|
|
78
|
+
const message = typeof decl === "object" && decl !== null && typeof decl.message === "string" ? decl.message : "maxLength";
|
|
79
|
+
const err = errorValue("maxLength", message);
|
|
80
|
+
return (value) => {
|
|
81
|
+
if (value === null || value === void 0) return void 0;
|
|
82
|
+
if (typeof value === "string") return value.length <= max2 ? void 0 : err;
|
|
83
|
+
if (Array.isArray(value)) return value.length <= max2 ? void 0 : err;
|
|
84
|
+
return void 0;
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
var min = (decl) => {
|
|
88
|
+
const minValue = typeof decl === "number" ? decl : decl.min;
|
|
89
|
+
const message = typeof decl === "object" && decl !== null && typeof decl.message === "string" ? decl.message : "min";
|
|
90
|
+
const err = errorValue("min", message);
|
|
91
|
+
return (value) => {
|
|
92
|
+
if (value === null || value === void 0) return void 0;
|
|
93
|
+
if (typeof value === "number" && Number.isFinite(value)) return value >= minValue ? void 0 : err;
|
|
94
|
+
return void 0;
|
|
95
|
+
};
|
|
96
|
+
};
|
|
97
|
+
var max = (decl) => {
|
|
98
|
+
const maxValue = typeof decl === "number" ? decl : decl.max;
|
|
99
|
+
const message = typeof decl === "object" && decl !== null && typeof decl.message === "string" ? decl.message : "max";
|
|
100
|
+
const err = errorValue("max", message);
|
|
101
|
+
return (value) => {
|
|
102
|
+
if (value === null || value === void 0) return void 0;
|
|
103
|
+
if (typeof value === "number" && Number.isFinite(value)) return value <= maxValue ? void 0 : err;
|
|
104
|
+
return void 0;
|
|
105
|
+
};
|
|
106
|
+
};
|
|
107
|
+
var pattern = (decl) => {
|
|
108
|
+
const re = decl instanceof RegExp ? decl : decl.re;
|
|
109
|
+
const message = typeof decl === "object" && decl !== null && typeof decl.message === "string" ? decl.message : "pattern";
|
|
110
|
+
const err = errorValue("pattern", message);
|
|
111
|
+
return (value) => {
|
|
112
|
+
if (value === null || value === void 0) return void 0;
|
|
113
|
+
if (typeof value !== "string") return void 0;
|
|
114
|
+
return re.test(value) ? void 0 : err;
|
|
115
|
+
};
|
|
116
|
+
};
|
|
117
|
+
var schemaErrorMessage = (schemaError) => {
|
|
118
|
+
let message;
|
|
119
|
+
try {
|
|
120
|
+
message = ParseResult.TreeFormatter.formatErrorSync(schemaError);
|
|
121
|
+
} catch {
|
|
122
|
+
message = "schema invalid";
|
|
123
|
+
}
|
|
124
|
+
const truncated = truncateToJsonByteBudget(message, ERROR_VALUE_MAX_BYTES);
|
|
125
|
+
return truncated.length > 0 ? truncated : "schema invalid";
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
// src/Rule.ts
|
|
129
|
+
var uniq = (items) => Array.from(new Set(items));
|
|
130
|
+
var normalizeValidateOn = (input) => {
|
|
131
|
+
if (!Array.isArray(input)) return void 0;
|
|
132
|
+
const out = [];
|
|
133
|
+
for (const x of input) {
|
|
134
|
+
if (x === "onChange" || x === "onBlur") out.push(x);
|
|
135
|
+
}
|
|
136
|
+
return uniq(out);
|
|
137
|
+
};
|
|
138
|
+
var normalizeDeps = (input) => {
|
|
139
|
+
if (!Array.isArray(input)) return void 0;
|
|
140
|
+
const out = [];
|
|
141
|
+
for (const x of input) {
|
|
142
|
+
if (typeof x !== "string") continue;
|
|
143
|
+
const v = x.trim();
|
|
144
|
+
if (!v) continue;
|
|
145
|
+
out.push(v);
|
|
146
|
+
}
|
|
147
|
+
return uniq(out);
|
|
148
|
+
};
|
|
149
|
+
var isPlainObject = (value) => Boolean(value) && typeof value === "object" && value !== null && !Array.isArray(value);
|
|
150
|
+
var make = (input) => {
|
|
151
|
+
if (typeof input === "function") {
|
|
152
|
+
return {
|
|
153
|
+
default: {
|
|
154
|
+
deps: [],
|
|
155
|
+
validate: input
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
if (!isPlainObject(input)) {
|
|
160
|
+
return {};
|
|
161
|
+
}
|
|
162
|
+
const baseDeps = normalizeDeps(input.deps) ?? [];
|
|
163
|
+
const baseValidateOn = normalizeValidateOn(input.validateOn);
|
|
164
|
+
const byName = /* @__PURE__ */ new Map();
|
|
165
|
+
const addRule = (name, raw) => {
|
|
166
|
+
const ruleName = typeof name === "string" ? name.trim() : "";
|
|
167
|
+
if (!ruleName) return;
|
|
168
|
+
if (byName.has(ruleName)) {
|
|
169
|
+
throw new Error(`[Form.Rule.make] Duplicate rule name "${ruleName}"`);
|
|
170
|
+
}
|
|
171
|
+
if (typeof raw === "function") {
|
|
172
|
+
byName.set(ruleName, {
|
|
173
|
+
deps: baseDeps,
|
|
174
|
+
validate: raw,
|
|
175
|
+
...baseValidateOn !== void 0 ? { validateOn: baseValidateOn } : {}
|
|
176
|
+
});
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
if (!raw || typeof raw !== "object") return;
|
|
180
|
+
const entry = raw;
|
|
181
|
+
const deps = normalizeDeps(entry.deps) ?? baseDeps;
|
|
182
|
+
const validateOn = normalizeValidateOn(entry.validateOn) ?? baseValidateOn;
|
|
183
|
+
const validate = entry.validate;
|
|
184
|
+
if (typeof validate !== "function") return;
|
|
185
|
+
byName.set(ruleName, {
|
|
186
|
+
...entry,
|
|
187
|
+
deps,
|
|
188
|
+
validate,
|
|
189
|
+
...validateOn !== void 0 ? { validateOn } : {}
|
|
190
|
+
});
|
|
191
|
+
};
|
|
192
|
+
const requiredDecl = input.required;
|
|
193
|
+
if (requiredDecl !== void 0 && requiredDecl !== false) {
|
|
194
|
+
const validate = required(requiredDecl);
|
|
195
|
+
addRule("required", (value) => validate(value));
|
|
196
|
+
}
|
|
197
|
+
const minLengthDecl = input.minLength;
|
|
198
|
+
if (minLengthDecl !== void 0) {
|
|
199
|
+
const validate = minLength(minLengthDecl);
|
|
200
|
+
addRule("minLength", (value) => validate(value));
|
|
201
|
+
}
|
|
202
|
+
const maxLengthDecl = input.maxLength;
|
|
203
|
+
if (maxLengthDecl !== void 0) {
|
|
204
|
+
const validate = maxLength(maxLengthDecl);
|
|
205
|
+
addRule("maxLength", (value) => validate(value));
|
|
206
|
+
}
|
|
207
|
+
const minDecl = input.min;
|
|
208
|
+
if (minDecl !== void 0) {
|
|
209
|
+
const validate = min(minDecl);
|
|
210
|
+
addRule("min", (value) => validate(value));
|
|
211
|
+
}
|
|
212
|
+
const maxDecl = input.max;
|
|
213
|
+
if (maxDecl !== void 0) {
|
|
214
|
+
const validate = max(maxDecl);
|
|
215
|
+
addRule("max", (value) => validate(value));
|
|
216
|
+
}
|
|
217
|
+
const patternDecl = input.pattern;
|
|
218
|
+
if (patternDecl !== void 0) {
|
|
219
|
+
const validate = pattern(patternDecl);
|
|
220
|
+
addRule("pattern", (value) => validate(value));
|
|
221
|
+
}
|
|
222
|
+
const validateBlock = input.validate;
|
|
223
|
+
if (typeof validateBlock === "function") {
|
|
224
|
+
addRule("validate", validateBlock);
|
|
225
|
+
} else if (isPlainObject(validateBlock)) {
|
|
226
|
+
const names2 = Object.keys(validateBlock).sort((a, b) => a.localeCompare(b));
|
|
227
|
+
for (const name of names2) {
|
|
228
|
+
addRule(name, validateBlock[name]);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
const out = {};
|
|
232
|
+
const names = Array.from(byName.keys()).sort((a, b) => a.localeCompare(b));
|
|
233
|
+
for (const name of names) {
|
|
234
|
+
out[name] = byName.get(name);
|
|
235
|
+
}
|
|
236
|
+
return out;
|
|
237
|
+
};
|
|
238
|
+
var merge = (...rules) => {
|
|
239
|
+
const byName = /* @__PURE__ */ new Map();
|
|
240
|
+
const duplicates = /* @__PURE__ */ new Set();
|
|
241
|
+
for (const ruleSet of rules) {
|
|
242
|
+
for (const name of Object.keys(ruleSet)) {
|
|
243
|
+
if (byName.has(name)) duplicates.add(name);
|
|
244
|
+
else byName.set(name, ruleSet[name]);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
if (duplicates.size > 0) {
|
|
248
|
+
const list2 = Array.from(duplicates).sort((a, b) => a.localeCompare(b)).join(", ");
|
|
249
|
+
throw new Error(`[Form.Rule.merge] Duplicate rule name(s): ${list2}`);
|
|
250
|
+
}
|
|
251
|
+
const merged = {};
|
|
252
|
+
const names = Array.from(byName.keys()).sort((a, b) => a.localeCompare(b));
|
|
253
|
+
for (const name of names) {
|
|
254
|
+
merged[name] = byName.get(name);
|
|
255
|
+
}
|
|
256
|
+
return merged;
|
|
257
|
+
};
|
|
258
|
+
var field = (valuePath, rule, options) => ({
|
|
259
|
+
kind: "field",
|
|
260
|
+
valuePath,
|
|
261
|
+
rule,
|
|
262
|
+
...options?.errorTarget !== void 0 ? { errorTarget: options.errorTarget } : {}
|
|
263
|
+
});
|
|
264
|
+
var root = (rule) => ({
|
|
265
|
+
kind: "root",
|
|
266
|
+
rule
|
|
267
|
+
});
|
|
268
|
+
var list = (listPath, spec) => ({
|
|
269
|
+
kind: "list",
|
|
270
|
+
listPath,
|
|
271
|
+
identity: spec.identity,
|
|
272
|
+
...spec.item !== void 0 ? { item: spec.item } : {},
|
|
273
|
+
...spec.list !== void 0 ? { list: spec.list } : {}
|
|
274
|
+
});
|
|
275
|
+
var fields = (...decls) => {
|
|
276
|
+
const out = {};
|
|
277
|
+
const list2 = [];
|
|
278
|
+
const isDeclArray = (value) => Array.isArray(value);
|
|
279
|
+
for (const item of decls) {
|
|
280
|
+
if (isDeclArray(item)) {
|
|
281
|
+
list2.push(...item);
|
|
282
|
+
continue;
|
|
283
|
+
}
|
|
284
|
+
list2.push(item);
|
|
285
|
+
}
|
|
286
|
+
for (const decl of list2) {
|
|
287
|
+
const path = typeof decl?.valuePath === "string" ? decl.valuePath.trim() : "";
|
|
288
|
+
if (!path) continue;
|
|
289
|
+
if (path in out) {
|
|
290
|
+
throw new Error(`[Form.Rule.fields] Duplicate valuePath "${path}"`);
|
|
291
|
+
}
|
|
292
|
+
out[path] = decl.rule;
|
|
293
|
+
}
|
|
294
|
+
return out;
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
export {
|
|
298
|
+
ERROR_VALUE_MAX_BYTES,
|
|
299
|
+
assertErrorValueBudget,
|
|
300
|
+
required,
|
|
301
|
+
minLength,
|
|
302
|
+
maxLength,
|
|
303
|
+
min,
|
|
304
|
+
max,
|
|
305
|
+
pattern,
|
|
306
|
+
schemaErrorMessage,
|
|
307
|
+
make,
|
|
308
|
+
merge,
|
|
309
|
+
field,
|
|
310
|
+
root,
|
|
311
|
+
list,
|
|
312
|
+
fields,
|
|
313
|
+
Rule_exports
|
|
314
|
+
};
|
|
315
|
+
//# sourceMappingURL=chunk-YVHXLY63.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/Rule.ts","../src/internal/validators/index.ts"],"sourcesContent":["import type * as Logix from '@logixjs/core'\nimport * as Validators from './internal/validators/index.js'\nimport type { CanonicalPath } from './internal/form/types.js'\n\nexport type AutoValidateOn = 'onChange' | 'onBlur'\n\nexport type RuleValidateOn = ReadonlyArray<AutoValidateOn>\n\nexport type RuleFn<Input, Ctx = unknown> = (input: Input, ctx: Ctx) => unknown | undefined\n\ntype RuleDeps<Input> = Input extends object\n ? CanonicalPath<Input> extends never\n ? string\n : CanonicalPath<Input>\n : string\n\nexport type Rule<Input, Ctx = unknown> = Logix.StateTrait.CheckRule<Input, Ctx> & {\n /**\n * validateOn:\n * - Only affects the auto-validation phase (onChange/onBlur); submit/manual always runs.\n * - If an empty array, auto-validation is disabled (only submit/manual runs).\n */\n readonly validateOn?: RuleValidateOn\n}\n\nexport type RuleSet<Input, Ctx = unknown> = Readonly<Record<string, Rule<Input, Ctx>>>\n\nexport type RuleEntry<Input, Ctx = unknown> =\n | RuleFn<Input, Ctx>\n | (Omit<Rule<Input, Ctx>, 'deps'> & {\n readonly deps?: ReadonlyArray<RuleDeps<Input>>\n })\n\nexport type RuleGroup<Input, Ctx = unknown> = Readonly<{\n readonly deps?: ReadonlyArray<RuleDeps<Input>>\n readonly validateOn?: RuleValidateOn\n readonly validate: Readonly<Record<string, RuleEntry<Input, Ctx>>>\n}>\n\nexport type RuleConfig<Input, Ctx = unknown> = Readonly<{\n readonly deps?: ReadonlyArray<RuleDeps<Input>>\n readonly validateOn?: RuleValidateOn\n\n // RHF-like builtins (expanded at build time into equivalent pure functions)\n readonly required?: Validators.RequiredDecl\n readonly minLength?: Validators.MinLengthDecl\n readonly maxLength?: Validators.MaxLengthDecl\n readonly min?: Validators.MinDecl\n readonly max?: Validators.MaxDecl\n readonly pattern?: Validators.PatternDecl\n\n // RHF-like validate: a function or a named map of functions (RuleEntry form is also allowed to override deps/validateOn)\n readonly validate?: RuleFn<Input, Ctx> | Readonly<Record<string, RuleEntry<Input, Ctx>>>\n}>\n\nexport type RuleInput<Input, Ctx = unknown> = RuleFn<Input, Ctx> | RuleGroup<Input, Ctx> | RuleConfig<Input, Ctx>\n\nconst uniq = <T>(items: ReadonlyArray<T>): ReadonlyArray<T> => Array.from(new Set(items))\n\nconst normalizeValidateOn = (input: unknown): RuleValidateOn | undefined => {\n if (!Array.isArray(input)) return undefined\n const out: Array<AutoValidateOn> = []\n for (const x of input) {\n if (x === 'onChange' || x === 'onBlur') out.push(x)\n }\n return uniq(out)\n}\n\nconst normalizeDeps = (input: unknown): ReadonlyArray<string> | undefined => {\n if (!Array.isArray(input)) return undefined\n const out: Array<string> = []\n for (const x of input) {\n if (typeof x !== 'string') continue\n const v = x.trim()\n if (!v) continue\n out.push(v)\n }\n return uniq(out)\n}\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> =>\n Boolean(value) && typeof value === 'object' && value !== null && !Array.isArray(value)\n\n/**\n * make:\n * - The result must be directly attachable to `StateTrait.node({ check })`.\n * - Does not introduce an extra wrapper (e.g. `{ rules: ... }`).\n */\nexport const make = <Input, Ctx = unknown>(input: RuleInput<Input, Ctx>): RuleSet<Input, Ctx> => {\n if (typeof input === 'function') {\n return {\n default: {\n deps: [],\n validate: input,\n },\n }\n }\n\n if (!isPlainObject(input)) {\n return {}\n }\n\n const baseDeps = normalizeDeps((input as any).deps) ?? []\n const baseValidateOn = normalizeValidateOn((input as any).validateOn)\n\n const byName = new Map<string, Rule<Input, Ctx>>()\n\n const addRule = (name: string, raw: unknown): void => {\n const ruleName = typeof name === 'string' ? name.trim() : ''\n if (!ruleName) return\n if (byName.has(ruleName)) {\n throw new Error(`[Form.Rule.make] Duplicate rule name \"${ruleName}\"`)\n }\n\n if (typeof raw === 'function') {\n byName.set(ruleName, {\n deps: baseDeps,\n validate: raw as any,\n ...(baseValidateOn !== undefined ? { validateOn: baseValidateOn } : {}),\n })\n return\n }\n\n if (!raw || typeof raw !== 'object') return\n const entry = raw as any\n const deps = normalizeDeps(entry.deps) ?? baseDeps\n const validateOn = normalizeValidateOn(entry.validateOn) ?? baseValidateOn\n const validate = entry.validate\n if (typeof validate !== 'function') return\n\n byName.set(ruleName, {\n ...entry,\n deps,\n validate,\n ...(validateOn !== undefined ? { validateOn } : {}),\n })\n }\n\n // RHF-like builtins (if declared, it will be expanded into an equivalent pure function)\n const requiredDecl = (input as any).required as Validators.RequiredDecl | undefined\n if (requiredDecl !== undefined && requiredDecl !== false) {\n const validate = Validators.required(requiredDecl)\n addRule('required', (value: Input) => validate(value))\n }\n\n const minLengthDecl = (input as any).minLength as Validators.MinLengthDecl | undefined\n if (minLengthDecl !== undefined) {\n const validate = Validators.minLength(minLengthDecl)\n addRule('minLength', (value: Input) => validate(value))\n }\n\n const maxLengthDecl = (input as any).maxLength as Validators.MaxLengthDecl | undefined\n if (maxLengthDecl !== undefined) {\n const validate = Validators.maxLength(maxLengthDecl)\n addRule('maxLength', (value: Input) => validate(value))\n }\n\n const minDecl = (input as any).min as Validators.MinDecl | undefined\n if (minDecl !== undefined) {\n const validate = Validators.min(minDecl)\n addRule('min', (value: Input) => validate(value))\n }\n\n const maxDecl = (input as any).max as Validators.MaxDecl | undefined\n if (maxDecl !== undefined) {\n const validate = Validators.max(maxDecl)\n addRule('max', (value: Input) => validate(value))\n }\n\n const patternDecl = (input as any).pattern as Validators.PatternDecl | undefined\n if (patternDecl !== undefined) {\n const validate = Validators.pattern(patternDecl)\n addRule('pattern', (value: Input) => validate(value))\n }\n\n // validate: supports both legacy RuleGroup `{ validate: Record<string, RuleEntry> }`\n // and RHF-style `validate: fn | Record<string, fn>`.\n const validateBlock = (input as any).validate as unknown\n if (typeof validateBlock === 'function') {\n addRule('validate', validateBlock)\n } else if (isPlainObject(validateBlock)) {\n const names = Object.keys(validateBlock).sort((a, b) => a.localeCompare(b))\n for (const name of names) {\n addRule(name, (validateBlock as any)[name])\n }\n }\n\n const out: Record<string, Rule<Input, Ctx>> = {}\n const names = Array.from(byName.keys()).sort((a, b) => a.localeCompare(b))\n for (const name of names) {\n out[name] = byName.get(name)!\n }\n return out\n}\n\nexport const merge = <Input, Ctx = unknown>(...rules: ReadonlyArray<RuleSet<Input, Ctx>>): RuleSet<Input, Ctx> => {\n const byName = new Map<string, Rule<Input, Ctx>>()\n const duplicates = new Set<string>()\n\n for (const ruleSet of rules) {\n for (const name of Object.keys(ruleSet)) {\n if (byName.has(name)) duplicates.add(name)\n else byName.set(name, ruleSet[name]!)\n }\n }\n\n if (duplicates.size > 0) {\n const list = Array.from(duplicates)\n .sort((a, b) => a.localeCompare(b))\n .join(', ')\n throw new Error(`[Form.Rule.merge] Duplicate rule name(s): ${list}`)\n }\n\n const merged: Record<string, Rule<Input, Ctx>> = {}\n const names = Array.from(byName.keys()).sort((a, b) => a.localeCompare(b))\n for (const name of names) {\n merged[name] = byName.get(name)!\n }\n\n return merged\n}\n\nexport type ErrorTarget = '$value' | '$self'\n\nexport type ListIdentityPolicy =\n | Readonly<{ readonly mode: 'trackBy'; readonly trackBy: string }>\n | Readonly<{ readonly mode: 'store' }>\n | Readonly<{ readonly mode: 'index' }>\n\nexport type FieldDecl<Input, Ctx = unknown> = Readonly<{\n readonly kind: 'field'\n readonly valuePath: string\n readonly rule: RuleInput<Input, Ctx>\n readonly errorTarget?: ErrorTarget\n}>\n\nexport type RootDecl<Input, Ctx = unknown> = Readonly<{\n readonly kind: 'root'\n readonly rule: RuleInput<Input, Ctx>\n}>\n\nexport type ListDecl<Item, Ctx = unknown> = Readonly<{\n readonly kind: 'list'\n readonly listPath: string\n readonly identity: ListIdentityPolicy\n readonly item?: RuleInput<Item, Ctx>\n readonly list?: RuleInput<ReadonlyArray<Item>, Ctx>\n}>\n\nexport type RulesDecl<TValues extends object = any> = FieldDecl<any> | RootDecl<TValues> | ListDecl<any>\n\nexport const field = <Input, Ctx = unknown>(\n valuePath: string,\n rule: RuleInput<Input, Ctx>,\n options?: { readonly errorTarget?: ErrorTarget },\n): FieldDecl<Input, Ctx> => ({\n kind: 'field',\n valuePath,\n rule,\n ...(options?.errorTarget !== undefined ? { errorTarget: options.errorTarget } : {}),\n})\n\nexport const root = <Input, Ctx = unknown>(rule: RuleInput<Input, Ctx>): RootDecl<Input, Ctx> => ({\n kind: 'root',\n rule,\n})\n\nexport const list = <Item, Ctx = unknown>(\n listPath: string,\n spec: {\n readonly identity: ListIdentityPolicy\n readonly item?: RuleInput<Item, Ctx>\n readonly list?: RuleInput<ReadonlyArray<Item>, Ctx>\n },\n): ListDecl<Item, Ctx> => ({\n kind: 'list',\n listPath,\n identity: spec.identity,\n ...(spec.item !== undefined ? { item: spec.item } : {}),\n ...(spec.list !== undefined ? { list: spec.list } : {}),\n})\n\nexport const fields = <Input, Ctx = unknown>(\n ...decls: ReadonlyArray<FieldDecl<Input, Ctx> | ReadonlyArray<FieldDecl<Input, Ctx>>>\n): Readonly<Record<string, RuleInput<Input, Ctx>>> => {\n const out: Record<string, RuleInput<Input, Ctx>> = {}\n const list: Array<FieldDecl<Input, Ctx>> = []\n\n const isDeclArray = (value: unknown): value is ReadonlyArray<FieldDecl<Input, Ctx>> => Array.isArray(value)\n\n for (const item of decls) {\n if (isDeclArray(item)) {\n list.push(...item)\n continue\n }\n list.push(item)\n }\n\n for (const decl of list) {\n const path = typeof decl?.valuePath === 'string' ? decl.valuePath.trim() : ''\n if (!path) continue\n if (path in out) {\n throw new Error(`[Form.Rule.fields] Duplicate valuePath \"${path}\"`)\n }\n out[path] = decl.rule\n }\n\n return out\n}\n\nexport {\n ERROR_VALUE_MAX_BYTES,\n assertErrorValueBudget,\n required,\n minLength,\n maxLength,\n min,\n max,\n pattern,\n} from './internal/validators/index.js'\n","import { ParseResult } from 'effect'\n\nexport const ERROR_VALUE_MAX_BYTES = 256\n\nconst textEncoder = new TextEncoder()\n\nconst jsonByteSize = (value: unknown): number => {\n const json = JSON.stringify(value)\n return textEncoder.encode(json).length\n}\n\nconst truncateToJsonByteBudget = (value: string, maxBytes: number): string => {\n if (jsonByteSize(value) <= maxBytes) return value\n\n let lo = 0\n let hi = value.length\n while (lo < hi) {\n const mid = Math.ceil((lo + hi) / 2)\n const slice = value.slice(0, mid)\n if (jsonByteSize(slice) <= maxBytes) lo = mid\n else hi = mid - 1\n }\n return value.slice(0, lo)\n}\n\nexport const assertErrorValueBudget = (value: unknown, label: string): unknown => {\n const bytes = jsonByteSize(value)\n if (bytes <= ERROR_VALUE_MAX_BYTES) return value\n throw new Error(`[Form.validators] ErrorValue for \"${label}\" must be JSON ≤${ERROR_VALUE_MAX_BYTES}B (got ${bytes}B)`)\n}\n\nconst errorValue = (label: string, value: unknown): unknown => assertErrorValueBudget(value, label)\n\nexport type RequiredDecl =\n | boolean\n | string\n | Readonly<{\n readonly message?: string\n readonly trim?: boolean\n }>\n\nexport const required = (decl: RequiredDecl): ((value: unknown) => unknown | undefined) => {\n const trim = typeof decl === 'object' && decl !== null ? Boolean((decl as any).trim) : true\n const message =\n typeof decl === 'string'\n ? decl\n : typeof decl === 'object' && decl !== null && typeof (decl as any).message === 'string'\n ? (decl as any).message\n : 'required'\n\n const err = errorValue('required', message)\n\n return (value: unknown) => {\n if (value === null || value === undefined) return err\n if (typeof value === 'string') {\n const v = trim ? value.trim() : value\n return v.length > 0 ? undefined : err\n }\n if (Array.isArray(value)) return value.length > 0 ? undefined : err\n if (typeof value === 'boolean') return value ? undefined : err\n return undefined\n }\n}\n\nexport type MinLengthDecl =\n | number\n | Readonly<{\n readonly min: number\n readonly message?: string\n }>\n\nexport const minLength = (decl: MinLengthDecl): ((value: unknown) => unknown | undefined) => {\n const min = typeof decl === 'number' ? decl : decl.min\n const message =\n typeof decl === 'object' && decl !== null && typeof decl.message === 'string' ? decl.message : 'minLength'\n const err = errorValue('minLength', message)\n\n return (value: unknown) => {\n if (value === null || value === undefined) return undefined\n if (typeof value === 'string') return value.length >= min ? undefined : err\n if (Array.isArray(value)) return value.length >= min ? undefined : err\n return undefined\n }\n}\n\nexport type MaxLengthDecl =\n | number\n | Readonly<{\n readonly max: number\n readonly message?: string\n }>\n\nexport const maxLength = (decl: MaxLengthDecl): ((value: unknown) => unknown | undefined) => {\n const max = typeof decl === 'number' ? decl : decl.max\n const message =\n typeof decl === 'object' && decl !== null && typeof decl.message === 'string' ? decl.message : 'maxLength'\n const err = errorValue('maxLength', message)\n\n return (value: unknown) => {\n if (value === null || value === undefined) return undefined\n if (typeof value === 'string') return value.length <= max ? undefined : err\n if (Array.isArray(value)) return value.length <= max ? undefined : err\n return undefined\n }\n}\n\nexport type MinDecl =\n | number\n | Readonly<{\n readonly min: number\n readonly message?: string\n }>\n\nexport const min = (decl: MinDecl): ((value: unknown) => unknown | undefined) => {\n const minValue = typeof decl === 'number' ? decl : decl.min\n const message = typeof decl === 'object' && decl !== null && typeof decl.message === 'string' ? decl.message : 'min'\n const err = errorValue('min', message)\n\n return (value: unknown) => {\n if (value === null || value === undefined) return undefined\n if (typeof value === 'number' && Number.isFinite(value)) return value >= minValue ? undefined : err\n return undefined\n }\n}\n\nexport type MaxDecl =\n | number\n | Readonly<{\n readonly max: number\n readonly message?: string\n }>\n\nexport const max = (decl: MaxDecl): ((value: unknown) => unknown | undefined) => {\n const maxValue = typeof decl === 'number' ? decl : decl.max\n const message = typeof decl === 'object' && decl !== null && typeof decl.message === 'string' ? decl.message : 'max'\n const err = errorValue('max', message)\n\n return (value: unknown) => {\n if (value === null || value === undefined) return undefined\n if (typeof value === 'number' && Number.isFinite(value)) return value <= maxValue ? undefined : err\n return undefined\n }\n}\n\nexport type PatternDecl =\n | RegExp\n | Readonly<{\n readonly re: RegExp\n readonly message?: string\n }>\n\nexport const pattern = (decl: PatternDecl): ((value: unknown) => unknown | undefined) => {\n const re = decl instanceof RegExp ? decl : decl.re\n const message =\n typeof decl === 'object' && decl !== null && typeof (decl as any).message === 'string'\n ? (decl as any).message\n : 'pattern'\n const err = errorValue('pattern', message)\n\n return (value: unknown) => {\n if (value === null || value === undefined) return undefined\n if (typeof value !== 'string') return undefined\n return re.test(value) ? undefined : err\n }\n}\n\nexport const schemaErrorMessage = (schemaError: unknown): string => {\n let message: string\n try {\n message = ParseResult.TreeFormatter.formatErrorSync(schemaError as any)\n } catch {\n message = 'schema invalid'\n }\n\n const truncated = truncateToJsonByteBudget(message, ERROR_VALUE_MAX_BYTES)\n return truncated.length > 0 ? truncated : 'schema invalid'\n}\n"],"mappings":"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","names":["min","max","names","list"]}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import * as Logix from '@logixjs/core';
|
|
2
|
+
import { Schema, Effect } from 'effect';
|
|
3
|
+
import { e as RulesDecl, f as RuleInput, L as ListIdentityPolicy, g as RootDecl, c as CanonicalListPath, C as CanonicalPath, d as CanonicalListItem, h as ListDecl, b as CanonicalValue, E as ErrorTarget, i as FieldDecl, A as AutoValidateOn } from './Rule-BOAiSVz9.js';
|
|
4
|
+
import { D as DerivedSpec } from './Trait-Bu794ROY.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* RulesSpec: the input shape of `Form.make({ rules })`.
|
|
8
|
+
*
|
|
9
|
+
* - Task 028 compiles `rules` into an equivalent `StateTraitSpec`; `rules` itself does not introduce a second runtime.
|
|
10
|
+
*/
|
|
11
|
+
type RulesSpec<TValues extends object> = Readonly<{
|
|
12
|
+
readonly _tag: 'FormRulesSpec';
|
|
13
|
+
readonly decls: ReadonlyArray<RulesDecl<TValues>>;
|
|
14
|
+
}>;
|
|
15
|
+
type RulesFieldNode = Readonly<{
|
|
16
|
+
readonly _tag: 'FormRulesNodeField';
|
|
17
|
+
readonly rule: RuleInput<any, any>;
|
|
18
|
+
}>;
|
|
19
|
+
type RulesObjectNode = Readonly<{
|
|
20
|
+
readonly _tag: 'FormRulesNodeObject';
|
|
21
|
+
readonly shape: Readonly<Record<string, RulesNode>>;
|
|
22
|
+
readonly refineRule?: RuleInput<any, any>;
|
|
23
|
+
readonly superRefineRule?: RuleInput<any, any>;
|
|
24
|
+
readonly refine: (rule: RuleInput<any, any>) => RulesObjectNode;
|
|
25
|
+
readonly superRefine: (rule: RuleInput<any, any>) => RulesObjectNode;
|
|
26
|
+
}>;
|
|
27
|
+
type RulesArrayNode = Readonly<{
|
|
28
|
+
readonly _tag: 'FormRulesNodeArray';
|
|
29
|
+
readonly item: RulesNode;
|
|
30
|
+
readonly identity: ListIdentityPolicy;
|
|
31
|
+
readonly refineRule?: RuleInput<any, any>;
|
|
32
|
+
readonly superRefineRule?: RuleInput<any, any>;
|
|
33
|
+
readonly refine: (rule: RuleInput<any, any>) => RulesArrayNode;
|
|
34
|
+
readonly superRefine: (rule: RuleInput<any, any>) => RulesArrayNode;
|
|
35
|
+
}>;
|
|
36
|
+
type RulesNode = RulesFieldNode | RulesObjectNode | RulesArrayNode;
|
|
37
|
+
type TrackByKey<Item> = Item extends object ? CanonicalPath<Item> extends never ? string : CanonicalPath<Item> : string;
|
|
38
|
+
type RulesDsl<TValues extends object> = {
|
|
39
|
+
(...decls: ReadonlyArray<RulesDecl<TValues>>): RulesSpec<TValues>;
|
|
40
|
+
(...decls: ReadonlyArray<RulesDecl<TValues> | ReadonlyArray<RulesDecl<TValues>>>): RulesSpec<TValues>;
|
|
41
|
+
readonly schema: (node: RulesNode) => RulesSpec<TValues>;
|
|
42
|
+
readonly at: (prefix: string) => RulesDsl<TValues>;
|
|
43
|
+
readonly root: <Ctx = unknown>(rule: RuleInput<TValues, Ctx>) => RootDecl<TValues, Ctx>;
|
|
44
|
+
readonly list: <P extends CanonicalListPath<TValues>, Ctx = unknown>(listPath: P, spec: {
|
|
45
|
+
readonly identity: Readonly<{
|
|
46
|
+
readonly mode: 'trackBy';
|
|
47
|
+
readonly trackBy: TrackByKey<CanonicalListItem<TValues, P>>;
|
|
48
|
+
}> | Readonly<{
|
|
49
|
+
readonly mode: 'store';
|
|
50
|
+
}> | Readonly<{
|
|
51
|
+
readonly mode: 'index';
|
|
52
|
+
}>;
|
|
53
|
+
readonly item?: RuleInput<CanonicalListItem<TValues, P>, Ctx>;
|
|
54
|
+
readonly list?: RuleInput<ReadonlyArray<CanonicalListItem<TValues, P>>, Ctx>;
|
|
55
|
+
}) => ListDecl<CanonicalListItem<TValues, P>, Ctx>;
|
|
56
|
+
readonly field: {
|
|
57
|
+
<P extends CanonicalPath<TValues>, Ctx = unknown>(valuePath: P, rule: RuleInput<CanonicalValue<TValues, P>, Ctx>, options?: {
|
|
58
|
+
readonly errorTarget?: ErrorTarget;
|
|
59
|
+
}): FieldDecl<CanonicalValue<TValues, P>, Ctx>;
|
|
60
|
+
(schema: Schema.Schema<any, any, never>): RulesFieldNode;
|
|
61
|
+
(rule: RuleInput<any, any>): RulesFieldNode;
|
|
62
|
+
};
|
|
63
|
+
readonly object: (shape: Readonly<Record<string, RulesNode>>) => RulesObjectNode;
|
|
64
|
+
readonly array: (item: RulesNode, options: {
|
|
65
|
+
readonly identity: ListIdentityPolicy;
|
|
66
|
+
}) => RulesArrayNode;
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Form.rules:
|
|
70
|
+
* - `$.rules(...decls)`:decl list(`Form.Rule.field/list/root`)
|
|
71
|
+
* - `$.rules.schema(node)`: zod-like rules authoring (Phase 3 will be filled in gradually)
|
|
72
|
+
* - `$.rules.at(prefix)`: write relative paths under `prefix`
|
|
73
|
+
*/
|
|
74
|
+
declare const rules: <TValues extends object, I>(_valuesSchema: Schema.Schema<TValues, I>) => RulesDsl<TValues>;
|
|
75
|
+
|
|
76
|
+
type RulesManifest = Readonly<{
|
|
77
|
+
readonly moduleId: string;
|
|
78
|
+
readonly lists: ReadonlyArray<Readonly<{
|
|
79
|
+
readonly path: ReadonlyArray<string>;
|
|
80
|
+
readonly identity: ListIdentityPolicy;
|
|
81
|
+
}>>;
|
|
82
|
+
readonly rules: ReadonlyArray<RuleDescriptor>;
|
|
83
|
+
}>;
|
|
84
|
+
type RuleScope = Readonly<{
|
|
85
|
+
readonly kind: 'root' | 'field' | 'list' | 'item';
|
|
86
|
+
readonly fieldPath: ReadonlyArray<string>;
|
|
87
|
+
readonly errorTarget?: ErrorTarget;
|
|
88
|
+
}>;
|
|
89
|
+
type RuleDescriptor = Readonly<{
|
|
90
|
+
readonly ruleId: string;
|
|
91
|
+
readonly scope: RuleScope;
|
|
92
|
+
readonly deps: ReadonlyArray<string>;
|
|
93
|
+
readonly validateOn?: ReadonlyArray<AutoValidateOn>;
|
|
94
|
+
readonly meta?: Logix.Observability.JsonValue;
|
|
95
|
+
}>;
|
|
96
|
+
|
|
97
|
+
type FormErrors = unknown;
|
|
98
|
+
type FormUiState = unknown;
|
|
99
|
+
type FormMeta = {
|
|
100
|
+
readonly submitCount: number;
|
|
101
|
+
readonly isSubmitting: boolean;
|
|
102
|
+
readonly isDirty: boolean;
|
|
103
|
+
/**
|
|
104
|
+
* errorCount:
|
|
105
|
+
* - Used for O(1) reads in `FormView.isValid/canSubmit`.
|
|
106
|
+
* - Semantics: the number of ErrorValue leaf nodes in the errors tree (including `$manual/$schema`).
|
|
107
|
+
*/
|
|
108
|
+
readonly errorCount: number;
|
|
109
|
+
};
|
|
110
|
+
type FormState<TValues extends object> = TValues & {
|
|
111
|
+
readonly errors: FormErrors;
|
|
112
|
+
readonly ui: FormUiState;
|
|
113
|
+
readonly $form: FormMeta;
|
|
114
|
+
};
|
|
115
|
+
declare const FormActions: {
|
|
116
|
+
readonly setValue: Schema.Struct<{
|
|
117
|
+
path: typeof Schema.String;
|
|
118
|
+
value: typeof Schema.Unknown;
|
|
119
|
+
}>;
|
|
120
|
+
readonly blur: Schema.Struct<{
|
|
121
|
+
path: typeof Schema.String;
|
|
122
|
+
}>;
|
|
123
|
+
readonly submit: typeof Schema.Void;
|
|
124
|
+
readonly validate: typeof Schema.Void;
|
|
125
|
+
readonly validatePaths: Schema.Array$<typeof Schema.String>;
|
|
126
|
+
readonly submitAttempt: typeof Schema.Void;
|
|
127
|
+
readonly setSubmitting: typeof Schema.Boolean;
|
|
128
|
+
readonly reset: Schema.UndefinedOr<typeof Schema.Unknown>;
|
|
129
|
+
readonly setError: Schema.Struct<{
|
|
130
|
+
path: typeof Schema.String;
|
|
131
|
+
error: typeof Schema.Unknown;
|
|
132
|
+
}>;
|
|
133
|
+
readonly clearErrors: Schema.UndefinedOr<Schema.Array$<typeof Schema.String>>;
|
|
134
|
+
readonly arrayAppend: Schema.Struct<{
|
|
135
|
+
path: typeof Schema.String;
|
|
136
|
+
value: typeof Schema.Unknown;
|
|
137
|
+
}>;
|
|
138
|
+
readonly arrayPrepend: Schema.Struct<{
|
|
139
|
+
path: typeof Schema.String;
|
|
140
|
+
value: typeof Schema.Unknown;
|
|
141
|
+
}>;
|
|
142
|
+
readonly arrayRemove: Schema.Struct<{
|
|
143
|
+
path: typeof Schema.String;
|
|
144
|
+
index: typeof Schema.Number;
|
|
145
|
+
}>;
|
|
146
|
+
readonly arraySwap: Schema.Struct<{
|
|
147
|
+
path: typeof Schema.String;
|
|
148
|
+
indexA: typeof Schema.Number;
|
|
149
|
+
indexB: typeof Schema.Number;
|
|
150
|
+
}>;
|
|
151
|
+
readonly arrayMove: Schema.Struct<{
|
|
152
|
+
path: typeof Schema.String;
|
|
153
|
+
from: typeof Schema.Number;
|
|
154
|
+
to: typeof Schema.Number;
|
|
155
|
+
}>;
|
|
156
|
+
};
|
|
157
|
+
type FormShapeForActions = FormShape<Record<string, never>>;
|
|
158
|
+
type FormAction = Logix.ActionOf<FormShapeForActions>;
|
|
159
|
+
type FormShape<TValues extends object> = Logix.Shape<Schema.Schema<FormState<TValues>, any>, typeof FormActions>;
|
|
160
|
+
interface FormMakeConfig<TValues extends object> {
|
|
161
|
+
readonly values: Schema.Schema<TValues, any>;
|
|
162
|
+
readonly initialValues: TValues;
|
|
163
|
+
readonly validateOn?: ReadonlyArray<'onSubmit' | 'onChange' | 'onBlur'>;
|
|
164
|
+
readonly reValidateOn?: ReadonlyArray<'onSubmit' | 'onChange' | 'onBlur'>;
|
|
165
|
+
readonly debounceMs?: number;
|
|
166
|
+
/**
|
|
167
|
+
* rules:
|
|
168
|
+
* - Recommended: express validations using rules only (field/list/root rules).
|
|
169
|
+
* - The result will be compiled into an equivalent StateTraitSpec (does not introduce a second runtime).
|
|
170
|
+
*/
|
|
171
|
+
readonly rules?: RulesSpec<TValues>;
|
|
172
|
+
readonly traits?: Logix.StateTrait.StateTraitSpec<TValues>;
|
|
173
|
+
/**
|
|
174
|
+
* derived:
|
|
175
|
+
* - The entry point for domain-level linkage/derivation (by default, only writes back to values/ui are allowed).
|
|
176
|
+
* - The result must be fully reducible to StateTraitSpec/IR (computed/link/source).
|
|
177
|
+
*/
|
|
178
|
+
readonly derived?: DerivedSpec<TValues>;
|
|
179
|
+
}
|
|
180
|
+
type FormExtendDef<TValues extends object> = Omit<Logix.Module.MakeExtendDef<Schema.Schema<FormState<TValues>, any>, typeof FormActions, {}>, 'actions'> & {
|
|
181
|
+
readonly actions?: never;
|
|
182
|
+
};
|
|
183
|
+
interface FormController<TValues extends object> {
|
|
184
|
+
readonly runtime: Logix.ModuleRuntime<FormState<TValues>, FormAction>;
|
|
185
|
+
readonly getState: Effect.Effect<FormState<TValues>>;
|
|
186
|
+
readonly dispatch: (action: FormAction) => Effect.Effect<void>;
|
|
187
|
+
readonly submit: () => Effect.Effect<void>;
|
|
188
|
+
readonly controller: {
|
|
189
|
+
readonly validate: () => Effect.Effect<void, never, any>;
|
|
190
|
+
readonly validatePaths: (paths: ReadonlyArray<string> | string) => Effect.Effect<void, never, any>;
|
|
191
|
+
readonly reset: (values?: TValues) => Effect.Effect<void>;
|
|
192
|
+
readonly setError: (path: string, error: unknown) => Effect.Effect<void>;
|
|
193
|
+
readonly clearErrors: (paths?: ReadonlyArray<string> | string) => Effect.Effect<void>;
|
|
194
|
+
readonly handleSubmit: (handlers: {
|
|
195
|
+
readonly onValid: (values: TValues) => Effect.Effect<void, any, any>;
|
|
196
|
+
readonly onInvalid?: (errors: unknown) => Effect.Effect<void, any, any>;
|
|
197
|
+
}) => Effect.Effect<void, any, any>;
|
|
198
|
+
};
|
|
199
|
+
readonly field: (path: string) => {
|
|
200
|
+
readonly get: Effect.Effect<unknown>;
|
|
201
|
+
readonly set: (value: unknown) => Effect.Effect<void>;
|
|
202
|
+
readonly blur: () => Effect.Effect<void>;
|
|
203
|
+
};
|
|
204
|
+
readonly fieldArray: (path: string) => {
|
|
205
|
+
readonly get: Effect.Effect<ReadonlyArray<unknown>>;
|
|
206
|
+
readonly append: (value: unknown) => Effect.Effect<void>;
|
|
207
|
+
readonly prepend: (value: unknown) => Effect.Effect<void>;
|
|
208
|
+
readonly remove: (index: number) => Effect.Effect<void>;
|
|
209
|
+
readonly swap: (indexA: number, indexB: number) => Effect.Effect<void>;
|
|
210
|
+
readonly move: (from: number, to: number) => Effect.Effect<void>;
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
type FormHandleExt<TValues extends object> = {
|
|
214
|
+
readonly controller: FormController<TValues>['controller'];
|
|
215
|
+
readonly rulesManifest: () => RulesManifest;
|
|
216
|
+
readonly rulesManifestWarnings: () => ReadonlyArray<string>;
|
|
217
|
+
};
|
|
218
|
+
type FormModule<Id extends string, TValues extends object> = Logix.Module.Module<Id, FormShape<TValues>, FormHandleExt<TValues>, any> & {
|
|
219
|
+
readonly controller: {
|
|
220
|
+
readonly make: (runtime: Logix.ModuleRuntime<FormState<TValues>, FormAction>) => FormController<TValues>;
|
|
221
|
+
};
|
|
222
|
+
};
|
|
223
|
+
declare const make: <Id extends string, TValues extends object>(id: Id, config: FormMakeConfig<TValues>, extend?: FormExtendDef<TValues>) => FormModule<Id, TValues>;
|
|
224
|
+
|
|
225
|
+
export { type FormErrors as F, type RulesDsl as R, type RulesNode as a, type RulesSpec as b, type FormUiState as c, type FormMeta as d, type FormState as e, type FormAction as f, type FormShape as g, type FormMakeConfig as h, type FormExtendDef as i, type FormController as j, type FormHandleExt as k, type FormModule as l, make as m, type RuleDescriptor as n, type RuleScope as o, type RulesManifest as p, rules as r };
|