@flowgram.ai/form 0.1.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/dist/index.js ADDED
@@ -0,0 +1,1607 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var src_exports = {};
32
+ __export(src_exports, {
33
+ Field: () => Field,
34
+ FieldArray: () => FieldArray,
35
+ FieldArrayModel: () => FieldArrayModel,
36
+ FieldModel: () => FieldModel,
37
+ Form: () => Form,
38
+ FormModel: () => FormModel,
39
+ Glob: () => Glob,
40
+ Path: () => Path,
41
+ ValidateTrigger: () => ValidateTrigger,
42
+ createForm: () => createForm,
43
+ toField: () => toField,
44
+ toFieldArray: () => toFieldArray,
45
+ toFieldState: () => toFieldState,
46
+ toForm: () => toForm,
47
+ toFormState: () => toFormState,
48
+ useCurrentField: () => useCurrentField,
49
+ useCurrentFieldState: () => useCurrentFieldState,
50
+ useField: () => useField,
51
+ useFieldValidate: () => useFieldValidate,
52
+ useForm: () => useForm,
53
+ useFormErrors: () => useFormErrors,
54
+ useFormState: () => useFormState,
55
+ useFormWarnings: () => useFormWarnings,
56
+ useWatch: () => useWatch
57
+ });
58
+ module.exports = __toCommonJS(src_exports);
59
+
60
+ // src/react/field.tsx
61
+ var React2 = __toESM(require("react"));
62
+ var import_lodash5 = require("lodash");
63
+ var import_utils4 = require("@flowgram.ai/utils");
64
+ var import_reactive = require("@flowgram.ai/reactive");
65
+
66
+ // src/utils/object.ts
67
+ var import_lodash = require("lodash");
68
+ var isObject = (obj) => obj !== null && typeof obj === "object";
69
+ var isInteger = (obj) => String(Math.floor(Number(obj))) === obj;
70
+ function getIn(obj, key, def, p = 0) {
71
+ const path = (0, import_lodash.toPath)(key);
72
+ while (obj && p < path.length) {
73
+ obj = obj[path[p++]];
74
+ }
75
+ if (p !== path.length && !obj) {
76
+ return def;
77
+ }
78
+ return obj === void 0 ? def : obj;
79
+ }
80
+ function shallowSetIn(obj, path, value) {
81
+ let res = (0, import_lodash.clone)(obj);
82
+ let resVal = res;
83
+ let i = 0;
84
+ let pathArray = (0, import_lodash.toPath)(path);
85
+ for (; i < pathArray.length - 1; i++) {
86
+ const currentPath = pathArray[i];
87
+ let currentObj = getIn(obj, pathArray.slice(0, i + 1));
88
+ if (currentObj && (isObject(currentObj) || Array.isArray(currentObj))) {
89
+ resVal = resVal[currentPath] = (0, import_lodash.clone)(currentObj);
90
+ } else {
91
+ const nextPath = pathArray[i + 1];
92
+ resVal = resVal[currentPath] = isInteger(nextPath) && Number(nextPath) >= 0 ? [] : {};
93
+ }
94
+ }
95
+ if ((i === 0 ? obj : resVal)[pathArray[i]] === value) {
96
+ return obj;
97
+ }
98
+ if (value === void 0) {
99
+ delete resVal[pathArray[i]];
100
+ } else {
101
+ resVal[pathArray[i]] = value;
102
+ }
103
+ if (i === 0 && value === void 0) {
104
+ delete res[pathArray[i]];
105
+ }
106
+ return res;
107
+ }
108
+
109
+ // src/utils/dom.ts
110
+ function isReactChangeEvent(e) {
111
+ return typeof e === "object" && e !== null && "target" in e && typeof e.target === "object";
112
+ }
113
+ function isCheckBoxEvent(e) {
114
+ return typeof e === "object" && e !== null && "target" in e && typeof e.target === "object" && e.target.type === "checkbox";
115
+ }
116
+
117
+ // src/utils/glob.ts
118
+ var import_lodash2 = require("lodash");
119
+ var Glob;
120
+ ((Glob2) => {
121
+ Glob2.DIVIDER = ".";
122
+ Glob2.ALL = "*";
123
+ function isMatch(pattern, path) {
124
+ const patternArr = pattern.split(Glob2.DIVIDER);
125
+ const pathArr = path.split(Glob2.DIVIDER);
126
+ if (patternArr.length !== pathArr.length) {
127
+ return false;
128
+ }
129
+ return patternArr.every((pattern2, index) => {
130
+ if (pattern2 === Glob2.ALL) {
131
+ return true;
132
+ }
133
+ return pattern2 === pathArr[index];
134
+ });
135
+ }
136
+ Glob2.isMatch = isMatch;
137
+ function isMatchOrParent(pattern, path) {
138
+ if (pattern === "") {
139
+ return true;
140
+ }
141
+ const patternArr = pattern.split(Glob2.DIVIDER);
142
+ const pathArr = path.split(Glob2.DIVIDER);
143
+ if (patternArr.length > pathArr.length) {
144
+ return false;
145
+ }
146
+ for (let i = 0; i < patternArr.length; i++) {
147
+ if (patternArr[i] !== Glob2.ALL && patternArr[i] !== pathArr[i]) {
148
+ return false;
149
+ }
150
+ }
151
+ return true;
152
+ }
153
+ Glob2.isMatchOrParent = isMatchOrParent;
154
+ function getParentPathByPattern(pattern, path) {
155
+ const patternArr = pattern.split(Glob2.DIVIDER);
156
+ const pathArr = path.split(Glob2.DIVIDER);
157
+ return pathArr.slice(0, patternArr.length).join(Glob2.DIVIDER);
158
+ }
159
+ Glob2.getParentPathByPattern = getParentPathByPattern;
160
+ function concatPath(p1, ...pathArr) {
161
+ const p2 = pathArr.shift();
162
+ if (p2 === void 0) return p1.toString();
163
+ let resultPath = "";
164
+ if (p1 === "" && p2 === "") {
165
+ resultPath = "";
166
+ } else if (p1 !== "" && p2 === "") {
167
+ resultPath = p1.toString();
168
+ } else if (p1 === "" && p2 !== "") {
169
+ resultPath = p2.toString();
170
+ } else {
171
+ resultPath = `${p1}${Glob2.DIVIDER}${p2}`;
172
+ }
173
+ if (pathArr.length > 0) {
174
+ return concatPath(resultPath, ...pathArr);
175
+ }
176
+ return resultPath;
177
+ }
178
+ function getSubPaths(paths, obj) {
179
+ if (!obj || typeof obj !== "object") {
180
+ return [];
181
+ }
182
+ return (0, import_lodash2.flatten)(
183
+ paths.map((path) => {
184
+ const value = path === "" ? obj : (0, import_lodash2.get)(obj, path);
185
+ if ((0, import_lodash2.isArray)(value)) {
186
+ return value.map((_, index) => concatPath(path, index));
187
+ } else if ((0, import_lodash2.isObject)(value)) {
188
+ return Object.keys(value).map((key) => concatPath(path, key));
189
+ }
190
+ return [];
191
+ })
192
+ );
193
+ }
194
+ Glob2.getSubPaths = getSubPaths;
195
+ function splitPattern(pattern) {
196
+ const parts = pattern.split(Glob2.DIVIDER);
197
+ const res = [];
198
+ let i = 0;
199
+ let curPath = [];
200
+ while (i < parts.length) {
201
+ if (parts[i] === Glob2.ALL) {
202
+ if (curPath.length) {
203
+ res.push(curPath.join(Glob2.DIVIDER));
204
+ }
205
+ res.push(Glob2.ALL);
206
+ curPath = [];
207
+ } else {
208
+ curPath.push(parts[i]);
209
+ }
210
+ i += 1;
211
+ }
212
+ if (curPath.length) {
213
+ res.push(curPath.join(Glob2.DIVIDER));
214
+ }
215
+ return res;
216
+ }
217
+ Glob2.splitPattern = splitPattern;
218
+ function findMatchPaths2(obj, pattern) {
219
+ if (!obj || !pattern) {
220
+ return [];
221
+ }
222
+ const nextPaths = pattern.split(Glob2.DIVIDER);
223
+ let curKey = nextPaths.shift();
224
+ let curPaths = [];
225
+ let curValue = obj;
226
+ while (curKey) {
227
+ let isObject3 = typeof curValue === "object";
228
+ if (!isObject3) return [];
229
+ if (curKey === Glob2.ALL) {
230
+ const parentPath = curPaths.join(Glob2.DIVIDER);
231
+ return (0, import_lodash2.flatten)(
232
+ Object.keys(curValue).map((key) => {
233
+ if (nextPaths.length === 0) {
234
+ return concatPath(parentPath, key);
235
+ }
236
+ return findMatchPaths2(curValue[key], `${nextPaths.join(Glob2.DIVIDER)}`).map(
237
+ (p) => concatPath(parentPath, key, p)
238
+ );
239
+ })
240
+ );
241
+ }
242
+ if (!(curKey in curValue)) return [];
243
+ curValue = curValue[curKey];
244
+ curPaths.push(curKey);
245
+ curKey = nextPaths.shift();
246
+ }
247
+ return [pattern];
248
+ }
249
+ Glob2.findMatchPaths = findMatchPaths2;
250
+ })(Glob || (Glob = {}));
251
+
252
+ // src/types/validate.ts
253
+ function isFieldWarning(f) {
254
+ if (f.level === "warning" /* Warning */) {
255
+ return true;
256
+ }
257
+ return false;
258
+ }
259
+ var ValidateTrigger = /* @__PURE__ */ ((ValidateTrigger2) => {
260
+ ValidateTrigger2["onChange"] = "onChange";
261
+ ValidateTrigger2["onBlur"] = "onBlur";
262
+ return ValidateTrigger2;
263
+ })(ValidateTrigger || {});
264
+
265
+ // src/core/utils.ts
266
+ var import_lodash4 = require("lodash");
267
+
268
+ // src/core/path.ts
269
+ var import_lodash3 = require("lodash");
270
+ var Path = class _Path {
271
+ constructor(path) {
272
+ this._path = [];
273
+ this._path = (0, import_lodash3.toPath)(path);
274
+ }
275
+ get parent() {
276
+ if (this._path.length < 2) {
277
+ return void 0;
278
+ }
279
+ return new _Path(this._path.slice(0, -1));
280
+ }
281
+ toString() {
282
+ return this._path.join(".");
283
+ }
284
+ get value() {
285
+ return this._path;
286
+ }
287
+ /**
288
+ * 仅计直系child
289
+ * @param path
290
+ */
291
+ isChild(path) {
292
+ const target = new _Path(path).value;
293
+ const self = this.value;
294
+ if (target.length - self.length !== 1) {
295
+ return false;
296
+ }
297
+ for (let i = 0; i < self.length; i++) {
298
+ if (target[i] !== self[i]) {
299
+ return false;
300
+ }
301
+ }
302
+ return true;
303
+ }
304
+ /**
305
+ * 比较两个数组path大小
306
+ * 返回小于0则path1<path2, 大于0 则path1>path2, 等于0则相等
307
+ * @param path1
308
+ * @param path2
309
+ */
310
+ static compareArrayPath(path1, path2) {
311
+ let i = 0;
312
+ while (path1.value[i] && path2.value[i]) {
313
+ const index1 = parseInt(path1.value[i]);
314
+ const index2 = parseInt(path2.value[i]);
315
+ if (!isNaN(index1) && !isNaN(index2)) {
316
+ return index1 - index2;
317
+ } else if (path1.value[i] !== path2.value[i]) {
318
+ throw new Error(
319
+ `[Form] Path.compareArrayPath invalid input Error: two path should refers to the same array, but got path1: ${path1.toString()}, path2: ${path2.toString()}`
320
+ );
321
+ }
322
+ i++;
323
+ }
324
+ throw new Error(
325
+ `[Form] Path.compareArrayPath invalid input Error: got path1: ${path1.toString()}, path2: ${path2.toString()}`
326
+ );
327
+ }
328
+ isChildOrGrandChild(path) {
329
+ const target = new _Path(path).value;
330
+ const self = this.value;
331
+ if (target.length - self.length < 1) {
332
+ return false;
333
+ }
334
+ for (let i = 0; i < self.length; i++) {
335
+ if (target[i] !== self[i]) {
336
+ return false;
337
+ }
338
+ }
339
+ return true;
340
+ }
341
+ getArrayIndex(parent) {
342
+ return parseInt(this._path[parent.value.length]);
343
+ }
344
+ concat(name) {
345
+ if (typeof name === "string" || typeof name === "number") {
346
+ return new _Path(this._path.concat(new _Path(name.toString())._path));
347
+ }
348
+ throw new Error(
349
+ `[Form] Error in Path.concat: invalid param type, require number or string, but got ${typeof name}`
350
+ );
351
+ }
352
+ replaceParent(parent, newParent) {
353
+ if (parent.value.length > this.value.length) {
354
+ throw new Error(
355
+ `[Form] Error in Path.getChildSuffixByParent: invalid parent param: ${parent}, parent length should not greater than current length.`
356
+ );
357
+ }
358
+ const rest = [];
359
+ for (let i = 0; i < this.value.length; i++) {
360
+ if (i < parent.value.length && parent.value[i] !== this.value[i]) {
361
+ throw new Error(
362
+ `[Form] Error in Path.getChildSuffixByParent: invalid parent param: ${parent}`
363
+ );
364
+ }
365
+ if (i >= parent.value.length) {
366
+ rest.push(this.value[i]);
367
+ }
368
+ }
369
+ return new _Path(newParent.value.concat(rest));
370
+ }
371
+ };
372
+
373
+ // src/core/utils.ts
374
+ function updateFeedbacksName(feedbacks, name) {
375
+ return feedbacks.map((f) => ({
376
+ ...f,
377
+ name
378
+ }));
379
+ }
380
+ function mergeFeedbacks(origin, source) {
381
+ if (!source) {
382
+ return origin;
383
+ }
384
+ if (!origin) {
385
+ return { ...source };
386
+ }
387
+ const changed = Object.keys(source).some(
388
+ (sourceKey) => !(0, import_lodash4.isEqual)(origin[sourceKey], source[sourceKey])
389
+ );
390
+ if (changed) {
391
+ return {
392
+ ...origin,
393
+ ...source
394
+ };
395
+ }
396
+ return origin;
397
+ }
398
+ function clearFeedbacks(name, origin) {
399
+ if (!origin) {
400
+ return origin;
401
+ }
402
+ if (name in origin) {
403
+ delete origin[name];
404
+ }
405
+ return origin;
406
+ }
407
+ function shouldValidate(currentTrigger, formTrigger) {
408
+ return currentTrigger === formTrigger;
409
+ }
410
+ function getValidByErrors(errors) {
411
+ return errors ? Object.keys(errors).every((name) => (0, import_lodash4.isEmpty)(errors[name])) : true;
412
+ }
413
+ var FieldEventUtils;
414
+ ((FieldEventUtils2) => {
415
+ function shouldTriggerFieldChangeEvent(payload, fieldName) {
416
+ const { name: changedName, options } = payload;
417
+ if (Glob.isMatchOrParent(fieldName, changedName)) {
418
+ return true;
419
+ }
420
+ if (new Path(changedName).isChildOrGrandChild(fieldName)) {
421
+ if (options?.action === "array-append") {
422
+ return !new Path(changedName).isChildOrGrandChild(fieldName);
423
+ } else if (options?.action === "array-splice" && options?.indexes?.length) {
424
+ return Path.compareArrayPath(
425
+ new Path(fieldName),
426
+ new Path(changedName).concat(options.indexes[0])
427
+ ) >= 0;
428
+ }
429
+ return true;
430
+ }
431
+ return false;
432
+ }
433
+ FieldEventUtils2.shouldTriggerFieldChangeEvent = shouldTriggerFieldChangeEvent;
434
+ function shouldTriggerFieldValidateWhenChange(payload, fieldName) {
435
+ const { name: changedName, options } = payload;
436
+ if (options?.action === "array-splice") {
437
+ return fieldName === changedName;
438
+ }
439
+ return FieldEventUtils2.shouldTriggerFieldChangeEvent(payload, fieldName);
440
+ }
441
+ FieldEventUtils2.shouldTriggerFieldValidateWhenChange = shouldTriggerFieldValidateWhenChange;
442
+ })(FieldEventUtils || (FieldEventUtils = {}));
443
+
444
+ // src/core/to-field.ts
445
+ function toField(model) {
446
+ const res = {
447
+ get name() {
448
+ return model.name;
449
+ },
450
+ get value() {
451
+ return model.value;
452
+ },
453
+ onChange: (e) => {
454
+ if (isReactChangeEvent(e)) {
455
+ model.value = isCheckBoxEvent(e) ? e.target.checked : e.target.value;
456
+ } else {
457
+ model.value = e;
458
+ }
459
+ },
460
+ onBlur() {
461
+ if (shouldValidate("onBlur" /* onBlur */, model.form.validationTrigger)) {
462
+ model.validate();
463
+ }
464
+ },
465
+ onFocus() {
466
+ model.state.isTouched = true;
467
+ }
468
+ };
469
+ Object.defineProperty(res, "key", {
470
+ enumerable: false,
471
+ get() {
472
+ return model.id;
473
+ }
474
+ });
475
+ Object.defineProperty(res, "_fieldModel", {
476
+ enumerable: false,
477
+ get() {
478
+ return model;
479
+ }
480
+ });
481
+ return res;
482
+ }
483
+ function toFieldState(modelState) {
484
+ return {
485
+ get isTouched() {
486
+ return modelState.isTouched;
487
+ },
488
+ get invalid() {
489
+ return modelState.invalid;
490
+ },
491
+ get isDirty() {
492
+ return modelState.isDirty;
493
+ },
494
+ get isValidating() {
495
+ return modelState.isValidating;
496
+ },
497
+ get errors() {
498
+ if (modelState.errors) {
499
+ return Object.values(modelState.errors).reduce((acc, arr) => acc.concat(arr), []);
500
+ }
501
+ return;
502
+ },
503
+ get warnings() {
504
+ if (modelState.warnings) {
505
+ return Object.values(modelState.warnings).reduce((acc, arr) => acc.concat(arr), []);
506
+ }
507
+ return;
508
+ }
509
+ };
510
+ }
511
+
512
+ // src/core/to-form.ts
513
+ function toForm(model) {
514
+ const res = {
515
+ initialValues: model.initialValues,
516
+ get values() {
517
+ return model.values;
518
+ },
519
+ state: toFormState(model.state),
520
+ getValueIn: (name) => model.getValueIn(name),
521
+ setValueIn: (name, value) => model.setValueIn(name, value)
522
+ };
523
+ Object.defineProperty(res, "_formModel", {
524
+ enumerable: false,
525
+ get() {
526
+ return model;
527
+ }
528
+ });
529
+ return res;
530
+ }
531
+ function toFormState(modelState) {
532
+ return {
533
+ get isTouched() {
534
+ return modelState.isTouched;
535
+ },
536
+ get invalid() {
537
+ return modelState.invalid;
538
+ },
539
+ get isDirty() {
540
+ return modelState.isDirty;
541
+ },
542
+ get isValidating() {
543
+ return modelState.isValidating;
544
+ },
545
+ // get dirtyFields() {
546
+ // return modelState.dirtyFields;
547
+ // },
548
+ // get isLoading() {
549
+ // return modelState.isLoading;
550
+ // },
551
+ // get touchedFields() {
552
+ // return modelState.touchedFields;
553
+ // },
554
+ get errors() {
555
+ return modelState.errors;
556
+ },
557
+ get warnings() {
558
+ return modelState.warnings;
559
+ }
560
+ };
561
+ }
562
+
563
+ // src/react/utils.ts
564
+ var import_react2 = require("react");
565
+
566
+ // src/react/context.ts
567
+ var import_react = __toESM(require("react"));
568
+ var FormModelContext = import_react.default.createContext({});
569
+ var FieldModelContext = import_react.default.createContext({});
570
+
571
+ // src/react/utils.ts
572
+ function useFormModel() {
573
+ return (0, import_react2.useContext)(FormModelContext);
574
+ }
575
+
576
+ // src/react/field.tsx
577
+ function Field({
578
+ name,
579
+ defaultValue,
580
+ render,
581
+ children,
582
+ deps
583
+ }) {
584
+ const formModel = useFormModel();
585
+ const fieldModel = formModel.getField(name) || formModel.createField(name);
586
+ const field = React2.useMemo(() => toField(fieldModel), [fieldModel]);
587
+ const fieldModelState = (0, import_reactive.useReadonlyReactiveState)(fieldModel.reactiveState);
588
+ const formModelState = (0, import_reactive.useReadonlyReactiveState)(formModel.reactiveState);
589
+ const fieldState = React2.useMemo(() => toFieldState(fieldModelState), [fieldModelState]);
590
+ const formState = toFormState(formModelState);
591
+ const refresh = (0, import_utils4.useRefresh)();
592
+ React2.useEffect(() => {
593
+ fieldModel.renderCount = fieldModel.renderCount + 1;
594
+ if (!formModel.getValueIn(name) !== void 0 && defaultValue !== void 0) {
595
+ formModel.setInitValueIn(name, defaultValue);
596
+ refresh();
597
+ }
598
+ const disposableCollection = new import_utils4.DisposableCollection();
599
+ disposableCollection.push(
600
+ fieldModel.onValueChange(() => {
601
+ refresh();
602
+ })
603
+ );
604
+ if (deps) {
605
+ deps.forEach((dep) => {
606
+ const disposable = formModel.getField(dep)?.onValueChange(() => {
607
+ refresh();
608
+ });
609
+ if (disposable) {
610
+ disposableCollection.push(disposable);
611
+ }
612
+ });
613
+ }
614
+ return () => {
615
+ disposableCollection.dispose();
616
+ if (fieldModel.renderCount > 1) {
617
+ fieldModel.renderCount = fieldModel.renderCount - 1;
618
+ } else {
619
+ fieldModel.dispose();
620
+ }
621
+ };
622
+ }, [fieldModel]);
623
+ const renderInner = () => {
624
+ if (render) {
625
+ return render({ field, fieldState, formState });
626
+ }
627
+ if ((0, import_lodash5.isFunction)(children)) {
628
+ return children({ field, fieldState, formState });
629
+ }
630
+ return React2.cloneElement(children, { ...field });
631
+ };
632
+ return /* @__PURE__ */ React2.createElement(FieldModelContext.Provider, { value: fieldModel }, renderInner());
633
+ }
634
+
635
+ // src/react/form.tsx
636
+ var import_react3 = __toESM(require("react"));
637
+ var import_lodash9 = require("lodash");
638
+
639
+ // src/core/to-field-array.ts
640
+ function toFieldArray(model) {
641
+ const res = {
642
+ get key() {
643
+ return model.id;
644
+ },
645
+ get name() {
646
+ return model.path.toString();
647
+ },
648
+ get value() {
649
+ return model.value;
650
+ },
651
+ onChange: (value) => {
652
+ model.value = value;
653
+ },
654
+ map: (cb) => model.map((f, index) => cb(toField(f), index)),
655
+ append: (value) => toField(model.append(value)),
656
+ delete: (index) => model.delete(index),
657
+ swap: (from, to) => model.swap(from, to),
658
+ move: (from, to) => model.move(from, to)
659
+ };
660
+ Object.defineProperty(res, "_fieldModel", {
661
+ enumerable: false,
662
+ get() {
663
+ return model;
664
+ }
665
+ });
666
+ return res;
667
+ }
668
+
669
+ // src/core/form-model.ts
670
+ var import_lodash8 = require("lodash");
671
+ var import_utils10 = require("@flowgram.ai/utils");
672
+ var import_reactive3 = require("@flowgram.ai/reactive");
673
+
674
+ // src/utils/validate.ts
675
+ function toFeedback(result, name) {
676
+ if (typeof result === "string") {
677
+ return {
678
+ name,
679
+ message: result,
680
+ level: "error" /* Error */
681
+ };
682
+ } else if (result?.message) {
683
+ return {
684
+ ...result,
685
+ name
686
+ };
687
+ }
688
+ }
689
+ function feedbackToFieldErrorsOrWarnings(name, feedback) {
690
+ return {
691
+ [name]: feedback ? [feedback] : []
692
+ };
693
+ }
694
+
695
+ // src/constants.ts
696
+ var DEFAULT_FIELD_STATE = {
697
+ invalid: false,
698
+ isDirty: false,
699
+ isTouched: false,
700
+ isValidating: false
701
+ };
702
+ var DEFAULT_FORM_STATE = {
703
+ invalid: false,
704
+ isDirty: false,
705
+ isTouched: false,
706
+ isValidating: false
707
+ };
708
+ function createFormModelState(initialState) {
709
+ if (!initialState) {
710
+ return { ...DEFAULT_FORM_STATE };
711
+ }
712
+ return { ...DEFAULT_FORM_STATE, ...initialState };
713
+ }
714
+ function createFieldModelState(initialState) {
715
+ if (!initialState) {
716
+ return { ...DEFAULT_FIELD_STATE };
717
+ }
718
+ return { ...DEFAULT_FIELD_STATE, ...initialState };
719
+ }
720
+
721
+ // src/core/store.ts
722
+ var import_lodash6 = require("lodash");
723
+ var Store = class {
724
+ get values() {
725
+ return this._values;
726
+ }
727
+ setInitialValues(values) {
728
+ this._values = values;
729
+ }
730
+ setIn(path, value) {
731
+ this._values = shallowSetIn(this._values || {}, path.toString(), value);
732
+ }
733
+ getIn(path) {
734
+ return (0, import_lodash6.get)(this._values, path.value);
735
+ }
736
+ dispose() {
737
+ }
738
+ };
739
+
740
+ // src/core/field-model.ts
741
+ var import_nanoid = require("nanoid");
742
+ var import_lodash7 = require("lodash");
743
+ var import_utils7 = require("@flowgram.ai/utils");
744
+ var import_reactive2 = require("@flowgram.ai/reactive");
745
+ var FieldModel = class {
746
+ constructor(path, form) {
747
+ this.onValueChangeEmitter = new import_utils7.Emitter();
748
+ this.onValueChange = this.onValueChangeEmitter.event;
749
+ this.toDispose = new import_utils7.DisposableCollection();
750
+ this._state = new import_reactive2.ReactiveState(
751
+ createFieldModelState()
752
+ );
753
+ this._renderCount = 0;
754
+ this._mount = false;
755
+ this._path = path;
756
+ this.form = form;
757
+ this.id = (0, import_nanoid.nanoid)();
758
+ const changeDisposable = this.form.onFormValuesChange((payload) => {
759
+ const { values, prevValues } = payload;
760
+ if (FieldEventUtils.shouldTriggerFieldChangeEvent(payload, this.name)) {
761
+ this.onValueChangeEmitter.fire({
762
+ value: (0, import_lodash7.get)(values, this.name),
763
+ prevValue: (0, import_lodash7.get)(prevValues, this.name),
764
+ formValues: values,
765
+ prevFormValues: prevValues
766
+ });
767
+ if (shouldValidate("onChange" /* onChange */, this.form.validationTrigger) && FieldEventUtils.shouldTriggerFieldValidateWhenChange(payload, this.name)) {
768
+ this.validate();
769
+ }
770
+ }
771
+ });
772
+ this.toDispose.push(changeDisposable);
773
+ this.toDispose.push(this.onValueChangeEmitter);
774
+ this.initState();
775
+ }
776
+ get renderCount() {
777
+ return this._renderCount;
778
+ }
779
+ set renderCount(n) {
780
+ this._renderCount = n;
781
+ }
782
+ initState() {
783
+ const initialErrors = (0, import_lodash7.get)(this.form.state.errors, this.name);
784
+ const initialWarnings = (0, import_lodash7.get)(this.form.state.warnings, this.name);
785
+ if (initialErrors) {
786
+ this.state.errors = {
787
+ [this.name]: initialErrors
788
+ };
789
+ }
790
+ if (initialWarnings) {
791
+ this.state.warnings = {
792
+ [this.name]: initialWarnings
793
+ };
794
+ }
795
+ }
796
+ get path() {
797
+ return this._path;
798
+ }
799
+ get name() {
800
+ return this._path.toString();
801
+ }
802
+ set name(name) {
803
+ this._path = new Path(name);
804
+ }
805
+ get ref() {
806
+ return this._ref;
807
+ }
808
+ set ref(ref) {
809
+ this._ref = ref;
810
+ }
811
+ get state() {
812
+ return this._state.value;
813
+ }
814
+ get reactiveState() {
815
+ return this._state;
816
+ }
817
+ get value() {
818
+ return this.form.getValueIn(this.name);
819
+ }
820
+ set value(value) {
821
+ this.form.setValueIn(this.name, value);
822
+ if (!this.state.isTouched) {
823
+ this.state.isTouched = true;
824
+ this.bubbleState();
825
+ }
826
+ }
827
+ updateNameForLeafState(newName) {
828
+ const { errors, warnings } = this.state;
829
+ const nameInErrors = errors ? Object.keys(errors)?.[0] : void 0;
830
+ if (nameInErrors && errors?.[nameInErrors] && nameInErrors !== newName) {
831
+ this.state.errors = {
832
+ [newName]: errors?.[nameInErrors] ? updateFeedbacksName(errors?.[nameInErrors], newName) : errors?.[nameInErrors]
833
+ };
834
+ }
835
+ const nameInWarnings = warnings ? Object.keys(warnings)?.[0] : void 0;
836
+ if (nameInWarnings && warnings?.[nameInWarnings] && nameInWarnings !== newName) {
837
+ this.state.warnings = {
838
+ [newName]: warnings?.[nameInWarnings] ? updateFeedbacksName(warnings?.[nameInWarnings], newName) : warnings?.[nameInWarnings]
839
+ };
840
+ }
841
+ }
842
+ // recursiveUpdateName(name: FieldName) {
843
+ // if (this.children?.length) {
844
+ // this.children.forEach(c => {
845
+ // c.recursiveUpdateName(c.path.replaceParent(this.path, new Path(name)).toString());
846
+ // });
847
+ // } else {
848
+ // this.updateNameForLeafState(name);
849
+ // this.bubbleState();
850
+ // }
851
+ // this.name = name;
852
+ // }
853
+ /**
854
+ * @deprecated
855
+ * @param validate
856
+ * @param from
857
+ */
858
+ updateValidate(validate, from) {
859
+ if (from === "ui") {
860
+ if (!this.originalValidate) {
861
+ this.originalValidate = validate;
862
+ }
863
+ } else {
864
+ this.originalValidate = validate;
865
+ }
866
+ }
867
+ bubbleState() {
868
+ const { errors, warnings } = this.state;
869
+ if (this.parent) {
870
+ this.parent.state.isTouched = (0, import_lodash7.some)(
871
+ this.parent.children.map((c) => c.state.isTouched),
872
+ Boolean
873
+ );
874
+ this.parent.state.invalid = (0, import_lodash7.some)(
875
+ this.parent.children.map((c) => c.state.invalid),
876
+ Boolean
877
+ );
878
+ this.parent.state.isDirty = (0, import_lodash7.some)(
879
+ this.parent.children.map((c) => c.state.isDirty),
880
+ Boolean
881
+ );
882
+ this.parent.state.isValidating = (0, import_lodash7.some)(
883
+ this.parent.children.map((c) => c.state.isValidating),
884
+ Boolean
885
+ );
886
+ this.parent.state.errors = errors ? mergeFeedbacks(this.parent.state.errors, errors) : clearFeedbacks(this.name, this.parent.state.errors);
887
+ this.parent.state.warnings = warnings ? mergeFeedbacks(this.parent.state.warnings, warnings) : clearFeedbacks(this.name, this.parent.state.warnings);
888
+ this.parent.bubbleState();
889
+ return;
890
+ }
891
+ this.form.state.isTouched = (0, import_lodash7.some)(
892
+ this.form.fields.map((f) => f.state.isTouched),
893
+ Boolean
894
+ );
895
+ this.form.state.invalid = (0, import_lodash7.some)(
896
+ this.form.fields.map((f) => f.state.invalid),
897
+ Boolean
898
+ );
899
+ this.form.state.isDirty = (0, import_lodash7.some)(
900
+ this.form.fields.map((f) => f.state.isDirty),
901
+ Boolean
902
+ );
903
+ this.form.state.isValidating = (0, import_lodash7.some)(
904
+ this.form.fields.map((f) => f.state.isValidating),
905
+ Boolean
906
+ );
907
+ this.form.state.errors = errors ? mergeFeedbacks(this.form.state.errors, errors) : clearFeedbacks(this.name, this.form.state.errors);
908
+ this.form.state.warnings = warnings ? mergeFeedbacks(this.form.state.warnings, warnings) : clearFeedbacks(this.name, this.form.state.warnings);
909
+ }
910
+ clearState() {
911
+ this.state.errors = DEFAULT_FIELD_STATE.errors;
912
+ this.state.warnings = DEFAULT_FIELD_STATE.warnings;
913
+ this.state.isTouched = DEFAULT_FIELD_STATE.isTouched;
914
+ this.state.isDirty = DEFAULT_FIELD_STATE.isDirty;
915
+ this.bubbleState();
916
+ }
917
+ get children() {
918
+ const res = [];
919
+ this.form.fieldMap.forEach((field, path) => {
920
+ if (this.path.isChild(path)) {
921
+ res.push(field);
922
+ }
923
+ });
924
+ return res;
925
+ }
926
+ get parent() {
927
+ const parentPath = this.path.parent;
928
+ if (!parentPath) {
929
+ return void 0;
930
+ }
931
+ return this.form.fieldMap.get(parentPath.toString());
932
+ }
933
+ clear() {
934
+ if (!this.value) {
935
+ return;
936
+ }
937
+ this.value = void 0;
938
+ }
939
+ async validate() {
940
+ await this.validateSelf();
941
+ }
942
+ async validateSelf() {
943
+ this.state.isValidating = true;
944
+ this.bubbleState();
945
+ const { errors, warnings } = await this._runAsyncValidate();
946
+ if (errors?.length) {
947
+ this.state.errors = (0, import_lodash7.groupBy)(errors, "name");
948
+ this.state.invalid = true;
949
+ } else {
950
+ this.state.errors = { [this.name]: [] };
951
+ this.state.invalid = false;
952
+ }
953
+ if (warnings?.length) {
954
+ this.state.warnings = (0, import_lodash7.groupBy)(warnings, "name");
955
+ } else {
956
+ this.state.warnings = { [this.name]: [] };
957
+ }
958
+ this.state.isValidating = false;
959
+ this.bubbleState();
960
+ this.form.onValidateEmitter.fire(this.form.state);
961
+ }
962
+ async _runAsyncValidate() {
963
+ const errors = [];
964
+ const warnings = [];
965
+ const result = await this.form.validateIn(this.name);
966
+ if (!result) {
967
+ return {};
968
+ } else {
969
+ const feedback = toFeedback(result, this.name);
970
+ if (!feedback) {
971
+ return {};
972
+ }
973
+ if (isFieldWarning(feedback)) {
974
+ warnings.push(feedback);
975
+ } else {
976
+ errors.push(feedback);
977
+ }
978
+ }
979
+ return { errors, warnings };
980
+ }
981
+ updateState(s) {
982
+ }
983
+ dispose() {
984
+ this.children.map((c) => c.dispose());
985
+ this.toDispose.dispose();
986
+ this.form.fieldMap.delete(this.path.toString());
987
+ }
988
+ onDispose(fn) {
989
+ this.toDispose.onDispose(fn);
990
+ }
991
+ };
992
+
993
+ // src/core/field-array-model.ts
994
+ var import_utils9 = require("@flowgram.ai/utils");
995
+ var FieldArrayModel = class extends FieldModel {
996
+ constructor() {
997
+ super(...arguments);
998
+ this.onAppendEmitter = new import_utils9.Emitter();
999
+ this.onAppend = this.onAppendEmitter.event;
1000
+ this.onDeleteEmitter = new import_utils9.Emitter();
1001
+ this.onDelete = this.onDeleteEmitter.event;
1002
+ }
1003
+ get children() {
1004
+ const fields = [];
1005
+ this.form.fieldMap.forEach((field, name) => {
1006
+ if (this.path.isChild(name)) {
1007
+ fields.push(field);
1008
+ }
1009
+ });
1010
+ return fields.sort((f1, f2) => {
1011
+ const p1 = f1.path.value;
1012
+ const p2 = f2.path.value;
1013
+ const i1 = parseInt(p1[p1.length - 1]);
1014
+ const i2 = parseInt(p1[p2.length - 1]);
1015
+ return i1 - i2;
1016
+ });
1017
+ }
1018
+ map(cb) {
1019
+ const fields = (this.value || []).map((v, i) => {
1020
+ const pathString = this.path.concat(i).toString();
1021
+ let field = this.form.getField(pathString);
1022
+ if (!field) {
1023
+ field = this.form.createField(pathString);
1024
+ }
1025
+ return field;
1026
+ });
1027
+ return fields.map(cb);
1028
+ }
1029
+ append(value) {
1030
+ const curLength = this.value?.length || 0;
1031
+ const newElemPath = this.path.concat(curLength).toString();
1032
+ const newElemField = this.form.createField(newElemPath);
1033
+ const newArrayValue = this.value ? [...this.value, value] : [value];
1034
+ const prevFormValues = this.form.values;
1035
+ this.form.store.setIn(new Path(this.name), newArrayValue);
1036
+ this.form.fireOnFormValuesChange({
1037
+ values: this.form.values,
1038
+ prevValues: prevFormValues,
1039
+ name: this.name,
1040
+ options: {
1041
+ action: "array-append",
1042
+ indexes: [curLength]
1043
+ }
1044
+ });
1045
+ this.form.fireOnFormValuesInit({
1046
+ values: this.form.values,
1047
+ prevValues: prevFormValues,
1048
+ name: newElemPath
1049
+ });
1050
+ this.onAppendEmitter.fire({
1051
+ value,
1052
+ arrayValue: this.value,
1053
+ index: this.value.length - 1
1054
+ });
1055
+ return newElemField;
1056
+ }
1057
+ /**
1058
+ * 删除数组项,该操作会删除数组项的值并销毁数组项的Field模型
1059
+ * @param index
1060
+ */
1061
+ delete(index) {
1062
+ this._splice(index, 1);
1063
+ this.onDeleteEmitter.fire({ arrayValue: this.value, index });
1064
+ }
1065
+ _splice(start, deleteCount = 1) {
1066
+ if (start < 0 || deleteCount < 0) {
1067
+ throw new Error(
1068
+ `[Form] Error in FieldArrayModel.splice: Invalid Params, start and deleteCount should > 0`
1069
+ );
1070
+ }
1071
+ if (!this.value || this.value.length === 0 || deleteCount > this.value.length) {
1072
+ throw new Error(
1073
+ `[Form] Error in FieldArrayModel.splice: delete count exceeds array length, tried to delete ${deleteCount} elements, but array length is ${this.value?.length || 0}`
1074
+ );
1075
+ }
1076
+ const oldFormValues = this.form.values;
1077
+ const tempValue = [...this.value];
1078
+ tempValue.splice(start, deleteCount);
1079
+ this.form.store.setIn(new Path(this.name), tempValue);
1080
+ this.form.fireOnFormValuesChange({
1081
+ values: this.form.values,
1082
+ prevValues: oldFormValues,
1083
+ name: this.name,
1084
+ options: {
1085
+ action: "array-splice",
1086
+ indexes: Array.from({ length: deleteCount }, (_, i) => i + start)
1087
+ }
1088
+ });
1089
+ const children = this.children;
1090
+ if (start + deleteCount >= children.length) {
1091
+ for (let i = start; i < children.length; i++) {
1092
+ this.form.disposeField(children[i].name);
1093
+ }
1094
+ }
1095
+ const toDispose = [];
1096
+ const newFieldMap = new Map(this.form.fieldMap);
1097
+ const recursiveHandleChildField = (field, index) => {
1098
+ if (field.children?.length) {
1099
+ field.children.forEach((cField) => {
1100
+ recursiveHandleChildField(cField, index);
1101
+ });
1102
+ }
1103
+ if (index < start) {
1104
+ newFieldMap.set(field.name, field);
1105
+ } else if (index < start + deleteCount) {
1106
+ toDispose.push(field);
1107
+ } else {
1108
+ const originName = field.name;
1109
+ const targetName = field.path.replaceParent(this.path.concat(index), this.path.concat(index - deleteCount)).toString();
1110
+ newFieldMap.set(targetName, field);
1111
+ if (!field.children.length) {
1112
+ field.updateNameForLeafState(targetName);
1113
+ field.bubbleState();
1114
+ }
1115
+ field.name = targetName;
1116
+ if (index > children.length - deleteCount - 1) {
1117
+ newFieldMap.delete(originName);
1118
+ }
1119
+ }
1120
+ };
1121
+ children.map((field, index) => {
1122
+ recursiveHandleChildField(field, index);
1123
+ });
1124
+ toDispose.forEach((f) => {
1125
+ f.dispose();
1126
+ });
1127
+ this.form.fieldMap = newFieldMap;
1128
+ }
1129
+ swap(from, to) {
1130
+ if (!this.value) {
1131
+ return;
1132
+ }
1133
+ if (from < 0 || to < 0 || from > this.value.length - 1 || to > this.value.length - 1) {
1134
+ throw new Error(
1135
+ `[Form]: FieldArrayModel.swap Error: invalid params 'form' and 'to', form=${from} to=${to}. expect the value between 0 to ${length - 1}`
1136
+ );
1137
+ }
1138
+ const tempValue = [...this.value];
1139
+ const fromValue = tempValue[from];
1140
+ const toValue = tempValue[to];
1141
+ tempValue[to] = fromValue;
1142
+ tempValue[from] = toValue;
1143
+ this.form.setValueIn(this.name, tempValue);
1144
+ }
1145
+ move(from, to) {
1146
+ if (!this.value) {
1147
+ return;
1148
+ }
1149
+ if (from < 0 || to < 0 || from > this.value.length - 1 || to > this.value.length - 1) {
1150
+ throw new Error(
1151
+ `[Form]: FieldArrayModel.move Error: invalid params 'form' and 'to', form=${from} to=${to}. expect the value between 0 to ${length - 1}`
1152
+ );
1153
+ }
1154
+ const tempValue = [...this.value];
1155
+ const fromValue = tempValue[from];
1156
+ tempValue.splice(from, 1);
1157
+ tempValue.splice(to, 0, fromValue);
1158
+ this.form.setValueIn(this.name, tempValue);
1159
+ }
1160
+ };
1161
+
1162
+ // src/core/form-model.ts
1163
+ var findMatchPaths = Glob.findMatchPaths;
1164
+ var FormModel = class {
1165
+ constructor() {
1166
+ this._fieldMap = /* @__PURE__ */ new Map();
1167
+ this.store = new Store();
1168
+ this._options = {};
1169
+ this.onFieldModelCreateEmitter = new import_utils10.Emitter();
1170
+ this.onFieldModelCreate = this.onFieldModelCreateEmitter.event;
1171
+ this.onFormValuesChangeEmitter = new import_utils10.Emitter();
1172
+ this.onFormValuesChange = this.onFormValuesChangeEmitter.event;
1173
+ this.onFormValuesInitEmitter = new import_utils10.Emitter();
1174
+ this.onFormValuesInit = this.onFormValuesInitEmitter.event;
1175
+ this.onFormValuesUpdatedEmitter = new import_utils10.Emitter();
1176
+ this.onFormValuesUpdated = this.onFormValuesUpdatedEmitter.event;
1177
+ this.onValidateEmitter = new import_utils10.Emitter();
1178
+ this.onValidate = this.onValidateEmitter.event;
1179
+ this._state = new import_reactive3.ReactiveState(
1180
+ createFormModelState()
1181
+ );
1182
+ this._initialized = false;
1183
+ }
1184
+ set fieldMap(map) {
1185
+ this._fieldMap = map;
1186
+ }
1187
+ /**
1188
+ * 表单初始值,初始化设置后不可修改
1189
+ * @protected
1190
+ */
1191
+ // protected _initialValues?: TValues;
1192
+ get fieldMap() {
1193
+ return this._fieldMap;
1194
+ }
1195
+ get context() {
1196
+ return this._options.context;
1197
+ }
1198
+ get initialValues() {
1199
+ return this._options.initialValues;
1200
+ }
1201
+ get values() {
1202
+ return (0, import_lodash8.cloneDeep)(this.store.values) || (0, import_lodash8.cloneDeep)(this.initialValues);
1203
+ }
1204
+ get validationTrigger() {
1205
+ return this._options.validateTrigger;
1206
+ }
1207
+ get state() {
1208
+ return this._state.value;
1209
+ }
1210
+ get reactiveState() {
1211
+ return this._state;
1212
+ }
1213
+ get fields() {
1214
+ return Array.from(this.fieldMap.values());
1215
+ }
1216
+ updateState(state) {
1217
+ }
1218
+ get initialized() {
1219
+ return this._initialized;
1220
+ }
1221
+ fireOnFormValuesChange(payload) {
1222
+ this.onFormValuesChangeEmitter.fire(payload);
1223
+ this.onFormValuesUpdatedEmitter.fire(payload);
1224
+ }
1225
+ fireOnFormValuesInit(payload) {
1226
+ this.onFormValuesInitEmitter.fire(payload);
1227
+ this.onFormValuesUpdatedEmitter.fire(payload);
1228
+ }
1229
+ init(options) {
1230
+ this._options = options;
1231
+ if (options.initialValues) {
1232
+ const prevValues = this.store.values;
1233
+ this.store.setInitialValues(options.initialValues);
1234
+ this.fireOnFormValuesInit({
1235
+ values: options.initialValues,
1236
+ prevValues,
1237
+ name: ""
1238
+ });
1239
+ }
1240
+ this._initialized = true;
1241
+ }
1242
+ createField(name, isArray2) {
1243
+ const path = new Path(name);
1244
+ const pathString = path.toString();
1245
+ if (this.fieldMap.get(pathString)) {
1246
+ return this.fieldMap.get(pathString);
1247
+ }
1248
+ const field = isArray2 ? new FieldArrayModel(path, this) : new FieldModel(path, this);
1249
+ this.fieldMap.set(pathString, field);
1250
+ field.onDispose(() => {
1251
+ this.fieldMap.delete(pathString);
1252
+ });
1253
+ this.onFieldModelCreateEmitter.fire(field);
1254
+ return field;
1255
+ }
1256
+ createFieldArray(name, value) {
1257
+ return this.createField(name, true);
1258
+ }
1259
+ /**
1260
+ * 销毁Field 模型和子模型,但不会删除field的值
1261
+ * @param name
1262
+ */
1263
+ disposeField(name) {
1264
+ const field = this.fieldMap.get(name);
1265
+ if (field) {
1266
+ field.dispose();
1267
+ }
1268
+ }
1269
+ /**
1270
+ * 删除field, 会删除值和 Field 模型, 以及对应的子模型
1271
+ * @param name
1272
+ */
1273
+ deleteField(name) {
1274
+ const field = this.fieldMap.get(name);
1275
+ if (field) {
1276
+ field.clear();
1277
+ field.dispose();
1278
+ }
1279
+ }
1280
+ getField(name) {
1281
+ return this.fieldMap.get(new Path(name).toString());
1282
+ }
1283
+ getValueIn(name) {
1284
+ return this.store.getIn(new Path(name));
1285
+ }
1286
+ setValueIn(name, value) {
1287
+ const prevValues = this.values;
1288
+ this.store.setIn(new Path(name), value);
1289
+ this.fireOnFormValuesChange({
1290
+ values: this.values,
1291
+ prevValues,
1292
+ name
1293
+ });
1294
+ }
1295
+ setInitValueIn(name, value) {
1296
+ const path = new Path(name);
1297
+ const prevValue = this.store.getIn(path);
1298
+ if (prevValue === void 0) {
1299
+ const prevValues = this.values;
1300
+ this.store.setIn(new Path(name), value);
1301
+ this.fireOnFormValuesInit({
1302
+ values: this.values,
1303
+ prevValues,
1304
+ name
1305
+ });
1306
+ }
1307
+ }
1308
+ clearValueIn(name) {
1309
+ this.setValueIn(name, void 0);
1310
+ }
1311
+ async validateIn(name) {
1312
+ if (!this._options.validate) {
1313
+ return;
1314
+ }
1315
+ const validateKey = Object.keys(this._options.validate).find(
1316
+ (pattern) => Glob.isMatch(pattern, name)
1317
+ );
1318
+ if (validateKey) {
1319
+ const validate = this._options.validate[validateKey];
1320
+ return validate({
1321
+ value: this.getValueIn(name),
1322
+ formValues: this.values,
1323
+ context: this.context,
1324
+ name
1325
+ });
1326
+ }
1327
+ }
1328
+ async validate() {
1329
+ if (!this._options.validate) {
1330
+ return [];
1331
+ }
1332
+ const feedbacksArrPromises = Object.keys(this._options.validate).map(async (nameRule) => {
1333
+ const validate = this._options.validate[nameRule];
1334
+ const paths = findMatchPaths(this.values, nameRule);
1335
+ return Promise.all(
1336
+ paths.map(async (path) => {
1337
+ const result = await validate({
1338
+ value: (0, import_lodash8.get)(this.values, path),
1339
+ formValues: this.values,
1340
+ context: this.context,
1341
+ name: path
1342
+ });
1343
+ const feedback = toFeedback(result, path);
1344
+ const field = this.getField(path);
1345
+ const errors = feedbackToFieldErrorsOrWarnings(path, feedback);
1346
+ const warnings = feedbackToFieldErrorsOrWarnings(path, feedback);
1347
+ if (field) {
1348
+ field.state.errors = errors;
1349
+ field.state.warnings = warnings;
1350
+ field.bubbleState();
1351
+ }
1352
+ this.state.errors = mergeFeedbacks(this.state.errors, errors);
1353
+ this.state.warnings = mergeFeedbacks(this.state.warnings, warnings);
1354
+ this.state.invalid = !getValidByErrors(this.state.errors);
1355
+ return feedback;
1356
+ })
1357
+ );
1358
+ });
1359
+ this.state.isValidating = true;
1360
+ const feedbacksArr = await Promise.all(feedbacksArrPromises);
1361
+ this.state.isValidating = false;
1362
+ this.onValidateEmitter.fire(this.state);
1363
+ return (0, import_lodash8.flatten)(feedbacksArr).filter(Boolean);
1364
+ }
1365
+ dispose() {
1366
+ this.fieldMap.forEach((f) => f.dispose());
1367
+ this.store.dispose();
1368
+ this._initialized = false;
1369
+ }
1370
+ };
1371
+
1372
+ // src/core/create-form.ts
1373
+ function createForm(options) {
1374
+ const { disableAutoInit = false, ...formOptions } = options || {};
1375
+ const formModel = new FormModel();
1376
+ if (!disableAutoInit) {
1377
+ formModel.init(formOptions || {});
1378
+ }
1379
+ return {
1380
+ form: toForm(formModel),
1381
+ control: {
1382
+ _formModel: formModel,
1383
+ getField: (name) => {
1384
+ const fieldModel = formModel.getField(name);
1385
+ if (fieldModel) {
1386
+ return fieldModel instanceof FieldArrayModel ? toFieldArray(fieldModel) : toField(fieldModel);
1387
+ }
1388
+ },
1389
+ init: () => formModel.init(formOptions || {})
1390
+ }
1391
+ };
1392
+ }
1393
+
1394
+ // src/react/form.tsx
1395
+ function Form(props) {
1396
+ const { children, keepModelOnUnMount = false, control, ...restOptions } = props;
1397
+ const { _formModel: formModel } = (0, import_react3.useMemo)(
1398
+ () => control ? control : createForm(restOptions).control,
1399
+ [control]
1400
+ );
1401
+ (0, import_react3.useEffect)(
1402
+ () => () => {
1403
+ if (!keepModelOnUnMount) {
1404
+ formModel.dispose();
1405
+ }
1406
+ },
1407
+ []
1408
+ );
1409
+ const form = (0, import_react3.useMemo)(() => toForm(formModel), [formModel]);
1410
+ return /* @__PURE__ */ import_react3.default.createElement(FormModelContext.Provider, { value: formModel }, children ? (0, import_lodash9.isFunction)(children) ? children({ form }) : import_react3.Children.only(children) : null);
1411
+ }
1412
+
1413
+ // src/react/use-form.ts
1414
+ function useForm() {
1415
+ const formModel = useFormModel();
1416
+ return toForm(formModel);
1417
+ }
1418
+
1419
+ // src/react/use-watch.ts
1420
+ var import_react4 = require("react");
1421
+ var import_utils13 = require("@flowgram.ai/utils");
1422
+ function useWatch(name) {
1423
+ const refresh = (0, import_utils13.useRefresh)();
1424
+ const formModel = useFormModel();
1425
+ if (!formModel) {
1426
+ throw new Error("[Form] error in useWatch, formModel not found");
1427
+ }
1428
+ const value = formModel.getValueIn(name);
1429
+ (0, import_react4.useEffect)(() => {
1430
+ const disposable = formModel.onFormValuesUpdated(({ name: updatedName }) => {
1431
+ if (updatedName === name) {
1432
+ refresh();
1433
+ }
1434
+ });
1435
+ return () => disposable.dispose();
1436
+ }, [name, formModel]);
1437
+ return value;
1438
+ }
1439
+
1440
+ // src/react/field-array.tsx
1441
+ var React4 = __toESM(require("react"));
1442
+ var import_lodash10 = require("lodash");
1443
+ var import_utils15 = require("@flowgram.ai/utils");
1444
+ var import_reactive4 = require("@flowgram.ai/reactive");
1445
+ function FieldArray({
1446
+ name,
1447
+ defaultValue,
1448
+ deps,
1449
+ render,
1450
+ children
1451
+ }) {
1452
+ const formModel = useFormModel();
1453
+ const fieldModel = React4.useMemo(
1454
+ () => formModel.getField(name) || formModel.createFieldArray(name),
1455
+ []
1456
+ );
1457
+ const field = React4.useMemo(() => toFieldArray(fieldModel), [fieldModel]);
1458
+ const refresh = (0, import_utils15.useRefresh)();
1459
+ const fieldModelState = (0, import_reactive4.useReadonlyReactiveState)(fieldModel.reactiveState);
1460
+ const formModelState = (0, import_reactive4.useReadonlyReactiveState)(formModel.reactiveState);
1461
+ const fieldState = toFieldState(fieldModelState);
1462
+ const formState = React4.useMemo(() => toFormState(formModelState), [formModelState]);
1463
+ React4.useEffect(() => {
1464
+ fieldModel.renderCount = fieldModel.renderCount + 1;
1465
+ if (!formModel.getValueIn(name) !== void 0 && defaultValue !== void 0) {
1466
+ formModel.setInitValueIn(name, defaultValue);
1467
+ refresh();
1468
+ }
1469
+ const disposableCollection = new import_utils15.DisposableCollection();
1470
+ disposableCollection.push(
1471
+ fieldModel.onValueChange(() => {
1472
+ refresh();
1473
+ })
1474
+ );
1475
+ if (deps) {
1476
+ deps.forEach((dep) => {
1477
+ const disposable = formModel.getField(dep)?.onValueChange(() => {
1478
+ refresh();
1479
+ });
1480
+ if (disposable) {
1481
+ disposableCollection.push(disposable);
1482
+ }
1483
+ });
1484
+ }
1485
+ return () => {
1486
+ disposableCollection.dispose();
1487
+ if (fieldModel.renderCount > 1) {
1488
+ fieldModel.renderCount = fieldModel.renderCount - 1;
1489
+ } else {
1490
+ fieldModel.dispose();
1491
+ }
1492
+ };
1493
+ }, [fieldModel]);
1494
+ const renderInner = () => {
1495
+ if (render && (0, import_lodash10.isFunction)(render)) {
1496
+ return render({ field, fieldState, formState });
1497
+ }
1498
+ if ((0, import_lodash10.isFunction)(children)) {
1499
+ return children({ field, fieldState, formState });
1500
+ }
1501
+ return /* @__PURE__ */ React4.createElement(React4.Fragment, null, "Invalid Array render");
1502
+ };
1503
+ return /* @__PURE__ */ React4.createElement(FieldModelContext.Provider, { value: fieldModel }, renderInner());
1504
+ }
1505
+
1506
+ // src/react/use-field.ts
1507
+ var import_react5 = require("react");
1508
+ var import_utils17 = require("@flowgram.ai/utils");
1509
+ function useField(name) {
1510
+ const currentFieldModel = (0, import_react5.useContext)(FieldModelContext);
1511
+ const formModel = useFormModel();
1512
+ const refresh = (0, import_utils17.useRefresh)();
1513
+ const fieldModel = name ? formModel.getField(name) : currentFieldModel;
1514
+ (0, import_react5.useEffect)(() => {
1515
+ let disposable;
1516
+ if (fieldModel) {
1517
+ disposable = fieldModel.onValueChange(() => refresh());
1518
+ }
1519
+ return () => {
1520
+ disposable?.dispose();
1521
+ };
1522
+ }, [fieldModel]);
1523
+ if (!fieldModel) {
1524
+ return void 0;
1525
+ }
1526
+ if (fieldModel.map) {
1527
+ return toFieldArray(fieldModel);
1528
+ }
1529
+ return toField(fieldModel);
1530
+ }
1531
+
1532
+ // src/react/use-form-state.ts
1533
+ var import_reactive5 = require("@flowgram.ai/reactive");
1534
+ function useFormState(control) {
1535
+ return (0, import_reactive5.useObserve)(control?._formModel.reactiveState.value || {});
1536
+ }
1537
+ function useFormErrors(control) {
1538
+ return (0, import_reactive5.useObserve)(control?._formModel.reactiveState.value || {})?.errors;
1539
+ }
1540
+ function useFormWarnings(control) {
1541
+ return (0, import_reactive5.useObserve)(control?._formModel.reactiveState.value || {})?.warnings;
1542
+ }
1543
+
1544
+ // src/react/use-field-validate.ts
1545
+ var import_react6 = require("react");
1546
+ function useFieldValidate(name) {
1547
+ const currentFieldModel = (0, import_react6.useContext)(FieldModelContext);
1548
+ const formModel = useFormModel();
1549
+ return (0, import_react6.useCallback)(() => {
1550
+ const fieldModel = name ? formModel.getField(name) : currentFieldModel;
1551
+ fieldModel?.validate();
1552
+ }, [currentFieldModel]);
1553
+ }
1554
+
1555
+ // src/react/use-current-field.ts
1556
+ var import_react7 = require("react");
1557
+ function useCurrentField() {
1558
+ const fieldModel = (0, import_react7.useContext)(FieldModelContext);
1559
+ if (!fieldModel) {
1560
+ throw new Error(
1561
+ `[Form] useCurrentField Error: field not found, make sure that you are using this hook in a child Component of a Field`
1562
+ );
1563
+ }
1564
+ return fieldModel.map ? toFieldArray(fieldModel) : toField(fieldModel);
1565
+ }
1566
+
1567
+ // src/react/use-current-field-state.ts
1568
+ var import_react8 = require("react");
1569
+ var import_reactive6 = require("@flowgram.ai/reactive");
1570
+ function useCurrentFieldState() {
1571
+ const fieldModel = (0, import_react8.useContext)(FieldModelContext);
1572
+ if (!fieldModel) {
1573
+ throw new Error(
1574
+ `[Form] useCurrentField Error: field not found, make sure that you are using this hook in a child Component of a Field`
1575
+ );
1576
+ }
1577
+ const fieldModelState = (0, import_reactive6.useReadonlyReactiveState)(fieldModel.reactiveState);
1578
+ return (0, import_react8.useMemo)(() => toFieldState(fieldModelState), [fieldModelState]);
1579
+ }
1580
+ // Annotate the CommonJS export names for ESM import in node:
1581
+ 0 && (module.exports = {
1582
+ Field,
1583
+ FieldArray,
1584
+ FieldArrayModel,
1585
+ FieldModel,
1586
+ Form,
1587
+ FormModel,
1588
+ Glob,
1589
+ Path,
1590
+ ValidateTrigger,
1591
+ createForm,
1592
+ toField,
1593
+ toFieldArray,
1594
+ toFieldState,
1595
+ toForm,
1596
+ toFormState,
1597
+ useCurrentField,
1598
+ useCurrentFieldState,
1599
+ useField,
1600
+ useFieldValidate,
1601
+ useForm,
1602
+ useFormErrors,
1603
+ useFormState,
1604
+ useFormWarnings,
1605
+ useWatch
1606
+ });
1607
+ //# sourceMappingURL=index.js.map