@goodie-forms/react 1.2.1-alpha → 1.2.3-alpha
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/components/FieldRenderer.d.ts +5 -4
- package/dist/components/FieldRenderer.d.ts.map +1 -1
- package/dist/hooks/useFieldErrors.d.ts +4 -0
- package/dist/hooks/useFieldErrors.d.ts.map +1 -0
- package/dist/hooks/useFieldValue.d.ts +4 -0
- package/dist/hooks/useFieldValue.d.ts.map +1 -0
- package/dist/hooks/useFormErrorObserver.d.ts +1 -0
- package/dist/hooks/useFormErrorObserver.d.ts.map +1 -1
- package/dist/hooks/useFormValuesObserver.d.ts +1 -0
- package/dist/hooks/useFormValuesObserver.d.ts.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +122 -91
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/components/FieldRenderer.tsx +22 -18
- package/src/hooks/useFieldErrors.ts +31 -0
- package/src/hooks/useFieldValue.ts +31 -0
- package/src/hooks/useFormErrorObserver.ts +1 -0
- package/src/hooks/useFormValuesObserver.ts +1 -0
- package/src/index.ts +2 -0
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { FieldPath, FormField, NonnullFormField } from '../../../core/src';
|
|
2
|
-
import { ChangeEvent,
|
|
2
|
+
import { ChangeEvent, ReactNode, Ref } from 'react';
|
|
3
3
|
import { UseForm } from '../hooks/useForm';
|
|
4
4
|
export interface RenderParams<TOutput extends object, TValue> {
|
|
5
5
|
ref: Ref<any | null>;
|
|
6
6
|
value: TValue | undefined;
|
|
7
7
|
handlers: {
|
|
8
|
-
onChange: (event: ChangeEvent<EventTarget>) => void;
|
|
9
|
-
onFocus: (
|
|
10
|
-
onBlur: (
|
|
8
|
+
onChange: (event: ChangeEvent<EventTarget> | TValue) => void;
|
|
9
|
+
onFocus: () => void;
|
|
10
|
+
onBlur: () => void;
|
|
11
11
|
};
|
|
12
12
|
field: undefined extends TValue ? FormField<TOutput, TValue> : NonnullFormField<TOutput, TValue>;
|
|
13
|
+
form: UseForm<TOutput>;
|
|
13
14
|
}
|
|
14
15
|
type DefaultValueProps<TValue> = undefined extends TValue ? {
|
|
15
16
|
defaultValue?: TValue | (() => TValue);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FieldRenderer.d.ts","sourceRoot":"","sources":["../../src/components/FieldRenderer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC5E,OAAO,
|
|
1
|
+
{"version":3,"file":"FieldRenderer.d.ts","sourceRoot":"","sources":["../../src/components/FieldRenderer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC5E,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,GAAG,EAAqB,MAAM,OAAO,CAAC;AACvE,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAI3C,MAAM,WAAW,YAAY,CAAC,OAAO,SAAS,MAAM,EAAE,MAAM;IAC1D,GAAG,EAAE,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;IAErB,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAE1B,QAAQ,EAAE;QACR,QAAQ,EAAE,CAAC,KAAK,EAAE,WAAW,CAAC,WAAW,CAAC,GAAG,MAAM,KAAK,IAAI,CAAC;QAC7D,OAAO,EAAE,MAAM,IAAI,CAAC;QACpB,MAAM,EAAE,MAAM,IAAI,CAAC;KACpB,CAAC;IAEF,KAAK,EAAE,SAAS,SAAS,MAAM,GAC3B,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC,GAC1B,gBAAgB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAEtC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;CACxB;AAED,KAAK,iBAAiB,CAAC,MAAM,IAAI,SAAS,SAAS,MAAM,GACrD;IAAE,YAAY,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC,CAAA;CAAE,GAC1C;IAAE,YAAY,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC,CAAA;CAAE,CAAC;AAE9C,MAAM,MAAM,kBAAkB,CAC5B,OAAO,SAAS,MAAM,EACtB,KAAK,SAAS,SAAS,CAAC,QAAQ,IAC9B;IACF,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IACvB,IAAI,EAAE,KAAK,CAAC;IACZ,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,MAAM,EAAE,CACN,MAAM,EAAE,YAAY,CAAC,OAAO,EAAE,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,KACtE,SAAS,CAAC;CAChB,GAAG,iBAAiB,CAAC,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAElE,wBAAgB,aAAa,CAC3B,OAAO,SAAS,MAAM,EACtB,KAAK,CAAC,KAAK,SAAS,SAAS,CAAC,QAAQ,EACtC,KAAK,EAAE,kBAAkB,CAAC,OAAO,EAAE,KAAK,CAAC,2CAqF1C"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { FieldPath } from '../../../core/src';
|
|
2
|
+
import { UseForm } from '../hooks/useForm';
|
|
3
|
+
export declare function useFieldErrors<TOutput extends object, TPath extends FieldPath.Segments>(form: UseForm<TOutput>, path: TPath): import("@standard-schema/spec").StandardSchemaV1.Issue[] | undefined;
|
|
4
|
+
//# sourceMappingURL=useFieldErrors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useFieldErrors.d.ts","sourceRoot":"","sources":["../../src/hooks/useFieldErrors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAI3C,wBAAgB,cAAc,CAC5B,OAAO,SAAS,MAAM,EACtB,KAAK,SAAS,SAAS,CAAC,QAAQ,EAChC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,KAAK,wEAqBpC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { FieldPath } from '../../../core/src';
|
|
2
|
+
import { UseForm } from '../hooks/useForm';
|
|
3
|
+
export declare function useFieldValue<TOutput extends object, TPath extends FieldPath.Segments>(form: UseForm<TOutput>, path: TPath): FieldPath.Resolve<TOutput, TPath> | undefined;
|
|
4
|
+
//# sourceMappingURL=useFieldValue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useFieldValue.d.ts","sourceRoot":"","sources":["../../src/hooks/useFieldValue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAI3C,wBAAgB,aAAa,CAC3B,OAAO,SAAS,MAAM,EACtB,KAAK,SAAS,SAAS,CAAC,QAAQ,EAChC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,KAAK,iDAqBpC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { FieldPath } from '../../../core/src';
|
|
2
2
|
import { UseForm } from './useForm';
|
|
3
|
+
/** @deprecated */
|
|
3
4
|
export declare function useFormErrorObserver<TOutput extends object, TInclude extends FieldPath.Segments[] | undefined = undefined>(form: UseForm<TOutput>, options?: {
|
|
4
5
|
include?: TInclude;
|
|
5
6
|
}): Record<string, import("@standard-schema/spec").StandardSchemaV1.Issue[]>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFormErrorObserver.d.ts","sourceRoot":"","sources":["../../src/hooks/useFormErrorObserver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAI/C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGzC,wBAAgB,oBAAoB,CAClC,OAAO,SAAS,MAAM,EACtB,QAAQ,SAAS,SAAS,CAAC,QAAQ,EAAE,GAAG,SAAS,GAAG,SAAS,EAE7D,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,EACtB,OAAO,CAAC,EAAE;IACR,OAAO,CAAC,EAAE,QAAQ,CAAC;CACpB,4EA6BF"}
|
|
1
|
+
{"version":3,"file":"useFormErrorObserver.d.ts","sourceRoot":"","sources":["../../src/hooks/useFormErrorObserver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAI/C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGzC,kBAAkB;AAClB,wBAAgB,oBAAoB,CAClC,OAAO,SAAS,MAAM,EACtB,QAAQ,SAAS,SAAS,CAAC,QAAQ,EAAE,GAAG,SAAS,GAAG,SAAS,EAE7D,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,EACtB,OAAO,CAAC,EAAE;IACR,OAAO,CAAC,EAAE,QAAQ,CAAC;CACpB,4EA6BF"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { FieldPath } from '../../../core/src';
|
|
2
2
|
import { UseForm } from './useForm';
|
|
3
|
+
/** @deprecated */
|
|
3
4
|
export declare function useFormValuesObserver<TOutput extends object, TPaths extends FieldPath.Segments[] | undefined = undefined>(form: UseForm<TOutput>, options?: {
|
|
4
5
|
include?: TPaths;
|
|
5
6
|
}): import('../../../core/src').DeepPartial<TOutput>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFormValuesObserver.d.ts","sourceRoot":"","sources":["../../src/hooks/useFormValuesObserver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAG/C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGzC,wBAAgB,qBAAqB,CACnC,OAAO,SAAS,MAAM,EACtB,MAAM,SAAS,SAAS,CAAC,QAAQ,EAAE,GAAG,SAAS,GAAG,SAAS,EAE3D,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,EACtB,OAAO,CAAC,EAAE;IACR,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,qDAmCF"}
|
|
1
|
+
{"version":3,"file":"useFormValuesObserver.d.ts","sourceRoot":"","sources":["../../src/hooks/useFormValuesObserver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAG/C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGzC,kBAAkB;AAClB,wBAAgB,qBAAqB,CACnC,OAAO,SAAS,MAAM,EACtB,MAAM,SAAS,SAAS,CAAC,QAAQ,EAAE,GAAG,SAAS,GAAG,SAAS,EAE3D,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,EACtB,OAAO,CAAC,EAAE;IACR,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,qDAmCF"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export * from './hooks/useForm';
|
|
2
2
|
export * from './hooks/useFormField';
|
|
3
|
+
export * from './hooks/useFieldValue';
|
|
4
|
+
export * from './hooks/useFieldErrors';
|
|
3
5
|
export * from './hooks/useFormValuesObserver';
|
|
4
6
|
export * from './hooks/useFormErrorObserver';
|
|
5
7
|
export * from './hooks/useRenderControl';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,sBAAsB,CAAC;AACrC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,0BAA0B,CAAC;AAEzC,cAAc,4BAA4B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC;AACvC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,0BAA0B,CAAC;AAEzC,cAAc,4BAA4B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,169 +1,200 @@
|
|
|
1
|
-
import { FormController as
|
|
2
|
-
import { useState as
|
|
3
|
-
import { jsx as g, Fragment as
|
|
4
|
-
function
|
|
5
|
-
const [, e] =
|
|
1
|
+
import { FormController as F, FieldPathBuilder as m, FieldPath as u } from "@goodie-forms/core";
|
|
2
|
+
import { useState as f, useRef as v, startTransition as C, useEffect as c } from "react";
|
|
3
|
+
import { jsx as g, Fragment as h } from "react/jsx-runtime";
|
|
4
|
+
function a() {
|
|
5
|
+
const [, e] = f(0), n = v(0), t = v(!1);
|
|
6
6
|
n.current++;
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
e((
|
|
11
|
-
}),
|
|
7
|
+
const o = () => {
|
|
8
|
+
t.current || (t.current = !0, queueMicrotask(() => {
|
|
9
|
+
C(() => {
|
|
10
|
+
e((r) => r + 1);
|
|
11
|
+
}), t.current = !1;
|
|
12
12
|
}));
|
|
13
13
|
};
|
|
14
14
|
return {
|
|
15
15
|
renderCount: n.current,
|
|
16
|
-
forceRerender:
|
|
16
|
+
forceRerender: o
|
|
17
17
|
};
|
|
18
18
|
}
|
|
19
|
-
function
|
|
19
|
+
function i(...e) {
|
|
20
20
|
return () => {
|
|
21
21
|
for (const n of e)
|
|
22
22
|
n();
|
|
23
23
|
};
|
|
24
24
|
}
|
|
25
25
|
function U(e, n) {
|
|
26
|
-
const [
|
|
27
|
-
return
|
|
26
|
+
const [t] = f(() => new F(e)), [o] = f(() => new m()), r = a();
|
|
27
|
+
return c(() => {
|
|
28
28
|
const l = () => {
|
|
29
29
|
};
|
|
30
|
-
return
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
return i(
|
|
31
|
+
t.events.on("submissionStatusChange", () => {
|
|
32
|
+
r.forceRerender();
|
|
33
33
|
}),
|
|
34
|
-
n?.watchIssues ?
|
|
34
|
+
n?.watchIssues ? t.events.on(
|
|
35
35
|
"fieldIssuesUpdated",
|
|
36
|
-
() =>
|
|
36
|
+
() => r.forceRerender()
|
|
37
37
|
) : l,
|
|
38
|
-
n?.watchValues ?
|
|
38
|
+
n?.watchValues ? t.events.on(
|
|
39
39
|
"valueChanged",
|
|
40
|
-
() =>
|
|
40
|
+
() => r.forceRerender()
|
|
41
41
|
) : l
|
|
42
42
|
);
|
|
43
|
-
}, [
|
|
43
|
+
}, [t]), {
|
|
44
44
|
formConfigs: e,
|
|
45
|
-
paths:
|
|
45
|
+
paths: o,
|
|
46
46
|
hookConfigs: n,
|
|
47
|
-
controller:
|
|
47
|
+
controller: t
|
|
48
48
|
};
|
|
49
49
|
}
|
|
50
|
-
function R(e, n,
|
|
51
|
-
const
|
|
50
|
+
function R(e, n, t) {
|
|
51
|
+
const o = a(), [r, l] = f(() => {
|
|
52
52
|
let d = e.controller.getField(n);
|
|
53
|
-
return d == null &&
|
|
53
|
+
return d == null && t != null && (d = e.controller.bindField(n, t)), d;
|
|
54
54
|
});
|
|
55
|
-
return
|
|
55
|
+
return c(() => {
|
|
56
56
|
const { events: d } = e.controller;
|
|
57
|
-
return l(e.controller.getField(n)),
|
|
58
|
-
d.on("fieldBound", (
|
|
59
|
-
|
|
57
|
+
return l(e.controller.getField(n)), i(
|
|
58
|
+
d.on("fieldBound", (s) => {
|
|
59
|
+
u.equals(s, n) && l(e.controller.getField(n));
|
|
60
60
|
}),
|
|
61
|
-
d.on("fieldUnbound", (
|
|
62
|
-
|
|
61
|
+
d.on("fieldUnbound", (s) => {
|
|
62
|
+
u.equals(s, n) && l(void 0);
|
|
63
63
|
}),
|
|
64
|
-
d.on("valueChanged", (
|
|
65
|
-
(
|
|
64
|
+
d.on("valueChanged", (s) => {
|
|
65
|
+
(u.equals(s, n) || u.isDescendant(s, n)) && o.forceRerender();
|
|
66
66
|
}),
|
|
67
|
-
d.on("fieldTouchUpdated", (
|
|
68
|
-
|
|
67
|
+
d.on("fieldTouchUpdated", (s) => {
|
|
68
|
+
u.equals(s, n) && o.forceRerender();
|
|
69
69
|
}),
|
|
70
|
-
d.on("fieldDirtyUpdated", (
|
|
71
|
-
|
|
70
|
+
d.on("fieldDirtyUpdated", (s) => {
|
|
71
|
+
u.equals(s, n) && o.forceRerender();
|
|
72
72
|
}),
|
|
73
|
-
d.on("fieldIssuesUpdated", (
|
|
74
|
-
|
|
73
|
+
d.on("fieldIssuesUpdated", (s) => {
|
|
74
|
+
u.equals(s, n) && o.forceRerender();
|
|
75
75
|
})
|
|
76
76
|
);
|
|
77
|
-
}, []),
|
|
77
|
+
}, []), r;
|
|
78
78
|
}
|
|
79
79
|
function w(e, n) {
|
|
80
|
-
const
|
|
81
|
-
|
|
80
|
+
const t = a(), o = e.controller.getField(n)?.value;
|
|
81
|
+
return c(() => i(
|
|
82
|
+
e.controller.events.on("fieldBound", (r) => {
|
|
83
|
+
u.equals(n, r) && t.forceRerender();
|
|
84
|
+
}),
|
|
85
|
+
e.controller.events.on("valueChanged", (r) => {
|
|
86
|
+
u.equals(n, r) && t.forceRerender();
|
|
87
|
+
})
|
|
88
|
+
), []), o;
|
|
89
|
+
}
|
|
90
|
+
function B(e, n) {
|
|
91
|
+
const t = a(), o = e.controller.getField(n)?.issues;
|
|
92
|
+
return c(() => i(
|
|
93
|
+
e.controller.events.on("fieldBound", (r) => {
|
|
94
|
+
u.equals(n, r) && t.forceRerender();
|
|
95
|
+
}),
|
|
96
|
+
e.controller.events.on("fieldIssuesUpdated", (r) => {
|
|
97
|
+
u.equals(n, r) && t.forceRerender();
|
|
98
|
+
})
|
|
99
|
+
), []), o;
|
|
100
|
+
}
|
|
101
|
+
function y(e, n) {
|
|
102
|
+
const t = a(), o = n?.include == null ? e.controller._data : n.include.reduce((r, l) => {
|
|
103
|
+
const d = u.getValue(
|
|
82
104
|
e.controller._data,
|
|
83
105
|
l
|
|
84
106
|
);
|
|
85
|
-
return
|
|
107
|
+
return u.setValue(r, l, d), r;
|
|
86
108
|
}, {});
|
|
87
|
-
return
|
|
88
|
-
const { events:
|
|
89
|
-
return
|
|
90
|
-
|
|
109
|
+
return c(() => {
|
|
110
|
+
const { events: r } = e.controller;
|
|
111
|
+
return i(
|
|
112
|
+
r.on("valueChanged", (l) => {
|
|
91
113
|
(n?.include == null || n.include.some(
|
|
92
|
-
(
|
|
93
|
-
)) &&
|
|
114
|
+
(s) => u.equals(s, l) || u.isDescendant(s, l)
|
|
115
|
+
)) && t.forceRerender();
|
|
94
116
|
})
|
|
95
117
|
);
|
|
96
|
-
}, []),
|
|
118
|
+
}, []), o;
|
|
97
119
|
}
|
|
98
|
-
function
|
|
99
|
-
const
|
|
100
|
-
for (const
|
|
101
|
-
const
|
|
102
|
-
(r
|
|
120
|
+
function q(e, n) {
|
|
121
|
+
const t = {};
|
|
122
|
+
for (const o of e) {
|
|
123
|
+
const r = n(o);
|
|
124
|
+
(t[r] ??= []).push(o);
|
|
103
125
|
}
|
|
104
|
-
return
|
|
126
|
+
return t;
|
|
105
127
|
}
|
|
106
|
-
function
|
|
107
|
-
const
|
|
128
|
+
function D(e, n) {
|
|
129
|
+
const t = a(), o = e.controller._issues.filter((r) => {
|
|
108
130
|
if (n?.include == null) return !0;
|
|
109
|
-
const l =
|
|
131
|
+
const l = u.normalize(r.path);
|
|
110
132
|
return n.include.some(
|
|
111
|
-
(d) =>
|
|
133
|
+
(d) => u.equals(d, l)
|
|
112
134
|
);
|
|
113
135
|
});
|
|
114
|
-
return
|
|
115
|
-
const { events:
|
|
116
|
-
return
|
|
117
|
-
|
|
118
|
-
(n?.include?.includes?.(l) ?? !0) &&
|
|
136
|
+
return c(() => {
|
|
137
|
+
const { events: r } = e.controller;
|
|
138
|
+
return i(
|
|
139
|
+
r.on("fieldIssuesUpdated", (l) => {
|
|
140
|
+
(n?.include?.includes?.(l) ?? !0) && t.forceRerender();
|
|
119
141
|
})
|
|
120
142
|
);
|
|
121
|
-
}, []),
|
|
122
|
-
|
|
123
|
-
(
|
|
143
|
+
}, []), q(
|
|
144
|
+
o,
|
|
145
|
+
(r) => r.path == null ? "$" : u.toStringPath(u.normalize(r.path))
|
|
124
146
|
);
|
|
125
147
|
}
|
|
126
|
-
function
|
|
127
|
-
const n = v(null),
|
|
148
|
+
function E(e) {
|
|
149
|
+
const n = v(null), t = R(e.form, e.path, {
|
|
128
150
|
overrideInitialValue: e.overrideInitialValue ?? !0,
|
|
129
151
|
defaultValue: typeof e.defaultValue == "function" ? e.defaultValue() : e.defaultValue
|
|
130
|
-
}),
|
|
131
|
-
onChange(
|
|
132
|
-
|
|
133
|
-
|
|
152
|
+
}), o = {
|
|
153
|
+
onChange(r) {
|
|
154
|
+
let l;
|
|
155
|
+
if ("target" in r) {
|
|
156
|
+
const { target: d } = r;
|
|
157
|
+
if (d !== t.boundElement || !("value" in d) || typeof d.value != "string") return;
|
|
158
|
+
l = d.value;
|
|
159
|
+
} else
|
|
160
|
+
l = r;
|
|
161
|
+
t.setValue(l, {
|
|
134
162
|
shouldTouch: !0,
|
|
135
163
|
shouldMarkDirty: !0
|
|
136
164
|
});
|
|
137
165
|
},
|
|
138
166
|
onFocus() {
|
|
139
|
-
|
|
167
|
+
t.touch();
|
|
140
168
|
},
|
|
141
169
|
onBlur() {
|
|
142
170
|
(e.form.hookConfigs?.validateMode === "onBlur" || e.form.hookConfigs?.validateMode === "onChange") && e.form.controller.validateField(e.path);
|
|
143
171
|
}
|
|
144
172
|
};
|
|
145
|
-
return
|
|
146
|
-
const { events:
|
|
147
|
-
return
|
|
148
|
-
|
|
149
|
-
!
|
|
173
|
+
return c(() => {
|
|
174
|
+
const { events: r } = e.form.controller;
|
|
175
|
+
return i(
|
|
176
|
+
r.on("valueChanged", (l) => {
|
|
177
|
+
!u.equals(l, e.path) && !u.isDescendant(l, e.path) || e.form.hookConfigs?.validateMode === "onChange" && e.form.controller.validateField(e.path);
|
|
150
178
|
})
|
|
151
179
|
);
|
|
152
|
-
}, []),
|
|
180
|
+
}, []), c(() => (t.bindElement(n.current), () => {
|
|
153
181
|
e.unbindOnUnmount && e.form.controller.unbindField(e.path);
|
|
154
|
-
}), []), /* @__PURE__ */ g(
|
|
182
|
+
}), []), /* @__PURE__ */ g(h, { children: e.render({
|
|
155
183
|
ref: n,
|
|
156
|
-
value:
|
|
157
|
-
handlers:
|
|
158
|
-
field:
|
|
184
|
+
value: t.value,
|
|
185
|
+
handlers: o,
|
|
186
|
+
field: t,
|
|
187
|
+
form: e.form
|
|
159
188
|
}) });
|
|
160
189
|
}
|
|
161
190
|
export {
|
|
162
|
-
|
|
191
|
+
E as FieldRenderer,
|
|
192
|
+
B as useFieldErrors,
|
|
193
|
+
w as useFieldValue,
|
|
163
194
|
U as useForm,
|
|
164
|
-
|
|
195
|
+
D as useFormErrorObserver,
|
|
165
196
|
R as useFormField,
|
|
166
|
-
|
|
167
|
-
|
|
197
|
+
y as useFormValuesObserver,
|
|
198
|
+
a as useRenderControl
|
|
168
199
|
};
|
|
169
200
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/hooks/useRenderControl.tsx","../src/utils/composeFns.ts","../src/hooks/useForm.tsx","../src/hooks/useFormField.tsx","../src/hooks/useFormValuesObserver.ts","../src/utils/groupBy.ts","../src/hooks/useFormErrorObserver.ts","../src/components/FieldRenderer.tsx"],"sourcesContent":["import { startTransition, useRef, useState } from \"react\";\r\n\r\nexport function useRenderControl() {\r\n const [, rerender] = useState(0);\r\n const renderCount = useRef(0);\r\n const renderScheduled = useRef(false);\r\n renderCount.current++;\r\n\r\n const scheduleRerender = () => {\r\n if (renderScheduled.current) return;\r\n renderScheduled.current = true;\r\n\r\n queueMicrotask(() => {\r\n startTransition(() => {\r\n rerender((i) => i + 1);\r\n });\r\n\r\n renderScheduled.current = false;\r\n });\r\n };\r\n\r\n return {\r\n renderCount: renderCount.current,\r\n forceRerender: scheduleRerender,\r\n };\r\n}\r\n","export function composeFns<TFns extends (() => void)[]>(...fns: TFns) {\r\n return () => {\r\n for (const fn of fns) {\r\n fn();\r\n }\r\n };\r\n}\r\n","import { FieldPathBuilder, FormController } from \"@goodie-forms/core\";\r\nimport { useEffect, useState } from \"react\";\r\nimport { useRenderControl } from \"../hooks/useRenderControl\";\r\nimport { composeFns } from \"../utils/composeFns\";\r\n\r\nexport function useForm<TOutput extends object>(\r\n formConfigs: FormController.Configs<TOutput>,\r\n hookConfigs?: {\r\n validateMode?: \"onChange\" | \"onBlur\" | \"onSubmit\";\r\n revalidateMode?: \"onChange\" | \"onBlur\" | \"onSubmit\";\r\n watchIssues?: boolean;\r\n watchValues?: boolean;\r\n },\r\n) {\r\n const [controller] = useState(() => new FormController(formConfigs));\r\n const [paths] = useState(() => new FieldPathBuilder<TOutput>());\r\n\r\n const renderControl = useRenderControl();\r\n\r\n useEffect(() => {\r\n const noop = () => {};\r\n\r\n return composeFns(\r\n controller.events.on(\"submissionStatusChange\", () => {\r\n renderControl.forceRerender();\r\n }),\r\n hookConfigs?.watchIssues\r\n ? controller.events.on(\"fieldIssuesUpdated\", () =>\r\n renderControl.forceRerender(),\r\n )\r\n : noop,\r\n hookConfigs?.watchValues\r\n ? controller.events.on(\"valueChanged\", () =>\r\n renderControl.forceRerender(),\r\n )\r\n : noop,\r\n );\r\n }, [controller]);\r\n\r\n return {\r\n formConfigs,\r\n paths,\r\n hookConfigs,\r\n controller,\r\n };\r\n}\r\n\r\nexport type UseForm<TOutput extends object> = ReturnType<\r\n typeof useForm<TOutput>\r\n>;\r\n","import { FieldPath } from \"@goodie-forms/core\";\r\nimport { useEffect, useState } from \"react\";\r\nimport { UseForm } from \"../hooks/useForm\";\r\nimport { useRenderControl } from \"../hooks/useRenderControl\";\r\nimport { composeFns } from \"../utils/composeFns\";\r\n\r\nexport function useFormField<\r\n TOutput extends object,\r\n TPath extends FieldPath.Segments,\r\n>(\r\n form: UseForm<TOutput>,\r\n path: TPath,\r\n bindingConfig?: Parameters<typeof form.controller.bindField<TPath>>[1],\r\n) {\r\n const renderControl = useRenderControl();\r\n\r\n const [field, setField] = useState(() => {\r\n let field = form.controller.getField(path);\r\n if (field == null && bindingConfig != null) {\r\n field = form.controller.bindField(path, bindingConfig);\r\n }\r\n return field;\r\n });\r\n\r\n useEffect(() => {\r\n const { events } = form.controller;\r\n\r\n setField(form.controller.getField(path));\r\n\r\n return composeFns(\r\n events.on(\"fieldBound\", (_path) => {\r\n if (!FieldPath.equals(_path, path)) return;\r\n setField(form.controller.getField(path));\r\n }),\r\n events.on(\"fieldUnbound\", (_path) => {\r\n if (!FieldPath.equals(_path, path)) return;\r\n setField(undefined);\r\n }),\r\n events.on(\"valueChanged\", (changedPath) => {\r\n if (\r\n FieldPath.equals(changedPath, path) ||\r\n FieldPath.isDescendant(changedPath, path)\r\n ) {\r\n renderControl.forceRerender();\r\n }\r\n }),\r\n events.on(\"fieldTouchUpdated\", (_path) => {\r\n if (!FieldPath.equals(_path, path)) return;\r\n renderControl.forceRerender();\r\n }),\r\n events.on(\"fieldDirtyUpdated\", (_path) => {\r\n if (!FieldPath.equals(_path, path)) return;\r\n renderControl.forceRerender();\r\n }),\r\n events.on(\"fieldIssuesUpdated\", (_path) => {\r\n if (!FieldPath.equals(_path, path)) return;\r\n renderControl.forceRerender();\r\n }),\r\n );\r\n }, []);\r\n\r\n return field;\r\n}\r\n","import { FieldPath } from \"@goodie-forms/core\";\r\nimport { useEffect } from \"react\";\r\nimport { composeFns } from \"../utils/composeFns\";\r\nimport type { UseForm } from \"./useForm\";\r\nimport { useRenderControl } from \"./useRenderControl\";\r\n\r\nexport function useFormValuesObserver<\r\n TOutput extends object,\r\n TPaths extends FieldPath.Segments[] | undefined = undefined,\r\n>(\r\n form: UseForm<TOutput>,\r\n options?: {\r\n include?: TPaths;\r\n },\r\n) {\r\n const renderControl = useRenderControl();\r\n\r\n const observedValues =\r\n options?.include == null\r\n ? form.controller._data\r\n : options.include.reduce((data, path) => {\r\n const value = FieldPath.getValue(\r\n form.controller._data as TOutput,\r\n path,\r\n )!;\r\n FieldPath.setValue(data, path, value);\r\n return data;\r\n }, {} as TOutput);\r\n\r\n useEffect(() => {\r\n const { events } = form.controller;\r\n\r\n return composeFns(\r\n events.on(\"valueChanged\", (changedPath) => {\r\n const watchingChange =\r\n options?.include == null\r\n ? true\r\n : options.include.some(\r\n (path) =>\r\n FieldPath.equals(path, changedPath) ||\r\n FieldPath.isDescendant(path, changedPath),\r\n );\r\n if (watchingChange) renderControl.forceRerender();\r\n }),\r\n );\r\n }, []);\r\n\r\n return observedValues;\r\n}\r\n","export function groupBy<T, K extends PropertyKey>(\r\n items: readonly T[],\r\n key: (item: T) => K,\r\n): Record<K, T[]> {\r\n const result = {} as Record<K, T[]>;\r\n\r\n for (const item of items) {\r\n const k = key(item);\r\n (result[k] ??= []).push(item);\r\n }\r\n\r\n return result;\r\n}\r\n","import { FieldPath } from \"@goodie-forms/core\";\r\nimport { groupBy } from \"../utils/groupBy\";\r\nimport { useEffect } from \"react\";\r\nimport { composeFns } from \"../utils/composeFns\";\r\nimport type { UseForm } from \"./useForm\";\r\nimport { useRenderControl } from \"./useRenderControl\";\r\n\r\nexport function useFormErrorObserver<\r\n TOutput extends object,\r\n TInclude extends FieldPath.Segments[] | undefined = undefined,\r\n>(\r\n form: UseForm<TOutput>,\r\n options?: {\r\n include?: TInclude;\r\n },\r\n) {\r\n const renderControl = useRenderControl();\r\n\r\n const observedIssues = form.controller._issues.filter((issue) => {\r\n if (options?.include == null) return true;\r\n const normalizedIssuePath = FieldPath.normalize(issue.path);\r\n return options.include.some((path) =>\r\n FieldPath.equals(path, normalizedIssuePath),\r\n );\r\n });\r\n\r\n useEffect(() => {\r\n const { events } = form.controller;\r\n\r\n return composeFns(\r\n events.on(\"fieldIssuesUpdated\", (path) => {\r\n if (options?.include?.includes?.(path) ?? true) {\r\n renderControl.forceRerender();\r\n }\r\n }),\r\n );\r\n }, []);\r\n\r\n return groupBy(observedIssues, (issue) =>\r\n issue.path == null\r\n ? \"$\"\r\n : FieldPath.toStringPath(FieldPath.normalize(issue.path)),\r\n );\r\n}\r\n","import { FieldPath, FormField, NonnullFormField } from \"@goodie-forms/core\";\r\nimport {\r\n ChangeEvent,\r\n FocusEvent,\r\n ReactNode,\r\n Ref,\r\n useEffect,\r\n useRef,\r\n} from \"react\";\r\nimport { useForm, UseForm } from \"../hooks/useForm\";\r\nimport { useFormField } from \"../hooks/useFormField\";\r\nimport { composeFns } from \"../utils/composeFns\";\r\n\r\nexport interface RenderParams<TOutput extends object, TValue> {\r\n ref: Ref<any | null>;\r\n\r\n value: TValue | undefined;\r\n\r\n handlers: {\r\n onChange: (event: ChangeEvent<EventTarget>) => void;\r\n onFocus: (event: FocusEvent) => void;\r\n onBlur: (event: FocusEvent) => void;\r\n };\r\n\r\n field: undefined extends TValue\r\n ? FormField<TOutput, TValue>\r\n : NonnullFormField<TOutput, TValue>;\r\n}\r\n\r\ntype DefaultValueProps<TValue> = undefined extends TValue\r\n ? { defaultValue?: TValue | (() => TValue) }\r\n : { defaultValue: TValue | (() => TValue) };\r\n\r\nexport type FieldRendererProps<\r\n TOutput extends object,\r\n TPath extends FieldPath.Segments,\r\n> = {\r\n form: UseForm<TOutput>;\r\n path: TPath;\r\n overrideInitialValue?: boolean;\r\n unbindOnUnmount?: boolean;\r\n render: (\r\n params: RenderParams<TOutput, FieldPath.Resolve<TOutput, NoInfer<TPath>>>,\r\n ) => ReactNode;\r\n} & DefaultValueProps<FieldPath.Resolve<TOutput, NoInfer<TPath>>>;\r\n\r\nexport function FieldRenderer<\r\n TOutput extends object,\r\n const TPath extends FieldPath.Segments,\r\n>(props: FieldRendererProps<TOutput, TPath>) {\r\n type TValue = FieldPath.Resolve<TOutput, TPath>;\r\n\r\n const elementRef = useRef<HTMLElement>(null);\r\n\r\n const field = useFormField(props.form, props.path, {\r\n overrideInitialValue: props.overrideInitialValue ?? true,\r\n defaultValue:\r\n typeof props.defaultValue === \"function\"\r\n ? (props.defaultValue as any)()\r\n : props.defaultValue,\r\n })!;\r\n\r\n const handlers: RenderParams<TOutput, TValue>[\"handlers\"] = {\r\n onChange(event) {\r\n const { target } = event;\r\n if (target !== field.boundElement) return;\r\n if (!(\"value\" in target)) return;\r\n if (typeof target.value !== \"string\") return;\r\n field.setValue(target.value as TValue, {\r\n shouldTouch: true,\r\n shouldMarkDirty: true,\r\n });\r\n },\r\n onFocus() {\r\n field.touch();\r\n },\r\n onBlur() {\r\n if (\r\n props.form.hookConfigs?.validateMode === \"onBlur\" ||\r\n props.form.hookConfigs?.validateMode === \"onChange\"\r\n ) {\r\n props.form.controller.validateField(props.path);\r\n }\r\n },\r\n };\r\n\r\n useEffect(() => {\r\n const { events } = props.form.controller;\r\n\r\n return composeFns(\r\n events.on(\"valueChanged\", (_path) => {\r\n if (\r\n !FieldPath.equals(_path, props.path) &&\r\n !FieldPath.isDescendant(_path, props.path)\r\n ) {\r\n return;\r\n }\r\n\r\n if (props.form.hookConfigs?.validateMode === \"onChange\") {\r\n props.form.controller.validateField(props.path);\r\n }\r\n }),\r\n );\r\n }, []);\r\n\r\n useEffect(() => {\r\n field.bindElement(elementRef.current!);\r\n\r\n return () => {\r\n if (props.unbindOnUnmount) {\r\n props.form.controller.unbindField(props.path);\r\n }\r\n };\r\n }, []);\r\n\r\n return (\r\n <>\r\n {props.render({\r\n ref: elementRef,\r\n value: field.value,\r\n handlers: handlers,\r\n field: field as any,\r\n })}\r\n </>\r\n );\r\n}\r\n\r\n/* ---- TESTS ---------------- */\r\n\r\n// function TestComp() {\r\n// const form = useForm<{ a?: { b: 99 } }>({});\r\n\r\n// const jsx = (\r\n// <>\r\n// <FieldRenderer\r\n// form={form}\r\n// path={form.paths.fromProxy((data) => data.a.b)}\r\n// defaultValue={() => 99 as const}\r\n// render={({ ref, value, handlers, field }) => {\r\n// // ^?\r\n// return <></>;\r\n// }}\r\n// />\r\n\r\n// {/* defaultField olmayabilir, çünkü \"a\" nullable */}\r\n// <FieldRenderer\r\n// form={form}\r\n// path={form.paths.fromProxy((data) => data.a)}\r\n// render={({ ref, value, handlers, field }) => {\r\n// // ^?\r\n// return <></>;\r\n// }}\r\n// />\r\n\r\n// <FieldRenderer\r\n// form={form}\r\n// path={form.paths.fromStringPath(\"a.b\")}\r\n// defaultValue={() => 99 as const}\r\n// render={({ ref, value, handlers, field }) => {\r\n// // ^?\r\n// return <></>;\r\n// }}\r\n// />\r\n// </>\r\n// );\r\n// }\r\n"],"names":["useRenderControl","rerender","useState","renderCount","useRef","renderScheduled","scheduleRerender","startTransition","i","composeFns","fns","fn","useForm","formConfigs","hookConfigs","controller","FormController","paths","FieldPathBuilder","renderControl","useEffect","noop","useFormField","form","path","bindingConfig","field","setField","events","_path","FieldPath","changedPath","useFormValuesObserver","options","observedValues","data","value","groupBy","items","key","result","item","k","useFormErrorObserver","observedIssues","issue","normalizedIssuePath","FieldRenderer","props","elementRef","handlers","event","target","jsx","Fragment"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/hooks/useRenderControl.tsx","../src/utils/composeFns.ts","../src/hooks/useForm.tsx","../src/hooks/useFormField.tsx","../src/hooks/useFieldValue.ts","../src/hooks/useFieldErrors.ts","../src/hooks/useFormValuesObserver.ts","../src/utils/groupBy.ts","../src/hooks/useFormErrorObserver.ts","../src/components/FieldRenderer.tsx"],"sourcesContent":["import { startTransition, useRef, useState } from \"react\";\r\n\r\nexport function useRenderControl() {\r\n const [, rerender] = useState(0);\r\n const renderCount = useRef(0);\r\n const renderScheduled = useRef(false);\r\n renderCount.current++;\r\n\r\n const scheduleRerender = () => {\r\n if (renderScheduled.current) return;\r\n renderScheduled.current = true;\r\n\r\n queueMicrotask(() => {\r\n startTransition(() => {\r\n rerender((i) => i + 1);\r\n });\r\n\r\n renderScheduled.current = false;\r\n });\r\n };\r\n\r\n return {\r\n renderCount: renderCount.current,\r\n forceRerender: scheduleRerender,\r\n };\r\n}\r\n","export function composeFns<TFns extends (() => void)[]>(...fns: TFns) {\r\n return () => {\r\n for (const fn of fns) {\r\n fn();\r\n }\r\n };\r\n}\r\n","import { FieldPathBuilder, FormController } from \"@goodie-forms/core\";\r\nimport { useEffect, useState } from \"react\";\r\nimport { useRenderControl } from \"../hooks/useRenderControl\";\r\nimport { composeFns } from \"../utils/composeFns\";\r\n\r\nexport function useForm<TOutput extends object>(\r\n formConfigs: FormController.Configs<TOutput>,\r\n hookConfigs?: {\r\n validateMode?: \"onChange\" | \"onBlur\" | \"onSubmit\";\r\n revalidateMode?: \"onChange\" | \"onBlur\" | \"onSubmit\";\r\n watchIssues?: boolean;\r\n watchValues?: boolean;\r\n },\r\n) {\r\n const [controller] = useState(() => new FormController(formConfigs));\r\n const [paths] = useState(() => new FieldPathBuilder<TOutput>());\r\n\r\n const renderControl = useRenderControl();\r\n\r\n useEffect(() => {\r\n const noop = () => {};\r\n\r\n return composeFns(\r\n controller.events.on(\"submissionStatusChange\", () => {\r\n renderControl.forceRerender();\r\n }),\r\n hookConfigs?.watchIssues\r\n ? controller.events.on(\"fieldIssuesUpdated\", () =>\r\n renderControl.forceRerender(),\r\n )\r\n : noop,\r\n hookConfigs?.watchValues\r\n ? controller.events.on(\"valueChanged\", () =>\r\n renderControl.forceRerender(),\r\n )\r\n : noop,\r\n );\r\n }, [controller]);\r\n\r\n return {\r\n formConfigs,\r\n paths,\r\n hookConfigs,\r\n controller,\r\n };\r\n}\r\n\r\nexport type UseForm<TOutput extends object> = ReturnType<\r\n typeof useForm<TOutput>\r\n>;\r\n","import { FieldPath } from \"@goodie-forms/core\";\r\nimport { useEffect, useState } from \"react\";\r\nimport { UseForm } from \"../hooks/useForm\";\r\nimport { useRenderControl } from \"../hooks/useRenderControl\";\r\nimport { composeFns } from \"../utils/composeFns\";\r\n\r\nexport function useFormField<\r\n TOutput extends object,\r\n TPath extends FieldPath.Segments,\r\n>(\r\n form: UseForm<TOutput>,\r\n path: TPath,\r\n bindingConfig?: Parameters<typeof form.controller.bindField<TPath>>[1],\r\n) {\r\n const renderControl = useRenderControl();\r\n\r\n const [field, setField] = useState(() => {\r\n let field = form.controller.getField(path);\r\n if (field == null && bindingConfig != null) {\r\n field = form.controller.bindField(path, bindingConfig);\r\n }\r\n return field;\r\n });\r\n\r\n useEffect(() => {\r\n const { events } = form.controller;\r\n\r\n setField(form.controller.getField(path));\r\n\r\n return composeFns(\r\n events.on(\"fieldBound\", (_path) => {\r\n if (!FieldPath.equals(_path, path)) return;\r\n setField(form.controller.getField(path));\r\n }),\r\n events.on(\"fieldUnbound\", (_path) => {\r\n if (!FieldPath.equals(_path, path)) return;\r\n setField(undefined);\r\n }),\r\n events.on(\"valueChanged\", (changedPath) => {\r\n if (\r\n FieldPath.equals(changedPath, path) ||\r\n FieldPath.isDescendant(changedPath, path)\r\n ) {\r\n renderControl.forceRerender();\r\n }\r\n }),\r\n events.on(\"fieldTouchUpdated\", (_path) => {\r\n if (!FieldPath.equals(_path, path)) return;\r\n renderControl.forceRerender();\r\n }),\r\n events.on(\"fieldDirtyUpdated\", (_path) => {\r\n if (!FieldPath.equals(_path, path)) return;\r\n renderControl.forceRerender();\r\n }),\r\n events.on(\"fieldIssuesUpdated\", (_path) => {\r\n if (!FieldPath.equals(_path, path)) return;\r\n renderControl.forceRerender();\r\n }),\r\n );\r\n }, []);\r\n\r\n return field;\r\n}\r\n","import { FieldPath } from \"@goodie-forms/core\";\r\nimport { useEffect } from \"react\";\r\nimport { UseForm } from \"../hooks/useForm\";\r\nimport { useRenderControl } from \"../hooks/useRenderControl\";\r\nimport { composeFns } from \"../utils/composeFns\";\r\n\r\nexport function useFieldValue<\r\n TOutput extends object,\r\n TPath extends FieldPath.Segments,\r\n>(form: UseForm<TOutput>, path: TPath) {\r\n const renderControl = useRenderControl();\r\n\r\n const value = form.controller.getField(path)?.value;\r\n\r\n useEffect(() => {\r\n return composeFns(\r\n form.controller.events.on(\"fieldBound\", (fieldPath) => {\r\n if (FieldPath.equals(path, fieldPath)) {\r\n renderControl.forceRerender();\r\n }\r\n }),\r\n form.controller.events.on(\"valueChanged\", (fieldPath) => {\r\n if (FieldPath.equals(path, fieldPath)) {\r\n renderControl.forceRerender();\r\n }\r\n }),\r\n );\r\n }, []);\r\n\r\n return value;\r\n}\r\n","import { FieldPath } from \"@goodie-forms/core\";\r\nimport { useEffect } from \"react\";\r\nimport { UseForm } from \"../hooks/useForm\";\r\nimport { useRenderControl } from \"../hooks/useRenderControl\";\r\nimport { composeFns } from \"../utils/composeFns\";\r\n\r\nexport function useFieldErrors<\r\n TOutput extends object,\r\n TPath extends FieldPath.Segments,\r\n>(form: UseForm<TOutput>, path: TPath) {\r\n const renderControl = useRenderControl();\r\n\r\n const issues = form.controller.getField(path)?.issues;\r\n\r\n useEffect(() => {\r\n return composeFns(\r\n form.controller.events.on(\"fieldBound\", (fieldPath) => {\r\n if (FieldPath.equals(path, fieldPath)) {\r\n renderControl.forceRerender();\r\n }\r\n }),\r\n form.controller.events.on(\"fieldIssuesUpdated\", (fieldPath) => {\r\n if (FieldPath.equals(path, fieldPath)) {\r\n renderControl.forceRerender();\r\n }\r\n }),\r\n );\r\n }, []);\r\n\r\n return issues;\r\n}\r\n","import { FieldPath } from \"@goodie-forms/core\";\r\nimport { useEffect } from \"react\";\r\nimport { composeFns } from \"../utils/composeFns\";\r\nimport type { UseForm } from \"./useForm\";\r\nimport { useRenderControl } from \"./useRenderControl\";\r\n\r\n/** @deprecated */\r\nexport function useFormValuesObserver<\r\n TOutput extends object,\r\n TPaths extends FieldPath.Segments[] | undefined = undefined,\r\n>(\r\n form: UseForm<TOutput>,\r\n options?: {\r\n include?: TPaths;\r\n },\r\n) {\r\n const renderControl = useRenderControl();\r\n\r\n const observedValues =\r\n options?.include == null\r\n ? form.controller._data\r\n : options.include.reduce((data, path) => {\r\n const value = FieldPath.getValue(\r\n form.controller._data as TOutput,\r\n path,\r\n )!;\r\n FieldPath.setValue(data, path, value);\r\n return data;\r\n }, {} as TOutput);\r\n\r\n useEffect(() => {\r\n const { events } = form.controller;\r\n\r\n return composeFns(\r\n events.on(\"valueChanged\", (changedPath) => {\r\n const watchingChange =\r\n options?.include == null\r\n ? true\r\n : options.include.some(\r\n (path) =>\r\n FieldPath.equals(path, changedPath) ||\r\n FieldPath.isDescendant(path, changedPath),\r\n );\r\n if (watchingChange) renderControl.forceRerender();\r\n }),\r\n );\r\n }, []);\r\n\r\n return observedValues;\r\n}\r\n","export function groupBy<T, K extends PropertyKey>(\r\n items: readonly T[],\r\n key: (item: T) => K,\r\n): Record<K, T[]> {\r\n const result = {} as Record<K, T[]>;\r\n\r\n for (const item of items) {\r\n const k = key(item);\r\n (result[k] ??= []).push(item);\r\n }\r\n\r\n return result;\r\n}\r\n","import { FieldPath } from \"@goodie-forms/core\";\r\nimport { groupBy } from \"../utils/groupBy\";\r\nimport { useEffect } from \"react\";\r\nimport { composeFns } from \"../utils/composeFns\";\r\nimport type { UseForm } from \"./useForm\";\r\nimport { useRenderControl } from \"./useRenderControl\";\r\n\r\n/** @deprecated */\r\nexport function useFormErrorObserver<\r\n TOutput extends object,\r\n TInclude extends FieldPath.Segments[] | undefined = undefined,\r\n>(\r\n form: UseForm<TOutput>,\r\n options?: {\r\n include?: TInclude;\r\n },\r\n) {\r\n const renderControl = useRenderControl();\r\n\r\n const observedIssues = form.controller._issues.filter((issue) => {\r\n if (options?.include == null) return true;\r\n const normalizedIssuePath = FieldPath.normalize(issue.path);\r\n return options.include.some((path) =>\r\n FieldPath.equals(path, normalizedIssuePath),\r\n );\r\n });\r\n\r\n useEffect(() => {\r\n const { events } = form.controller;\r\n\r\n return composeFns(\r\n events.on(\"fieldIssuesUpdated\", (path) => {\r\n if (options?.include?.includes?.(path) ?? true) {\r\n renderControl.forceRerender();\r\n }\r\n }),\r\n );\r\n }, []);\r\n\r\n return groupBy(observedIssues, (issue) =>\r\n issue.path == null\r\n ? \"$\"\r\n : FieldPath.toStringPath(FieldPath.normalize(issue.path)),\r\n );\r\n}\r\n","import { FieldPath, FormField, NonnullFormField } from \"@goodie-forms/core\";\r\nimport { ChangeEvent, ReactNode, Ref, useEffect, useRef } from \"react\";\r\nimport { UseForm } from \"../hooks/useForm\";\r\nimport { useFormField } from \"../hooks/useFormField\";\r\nimport { composeFns } from \"../utils/composeFns\";\r\n\r\nexport interface RenderParams<TOutput extends object, TValue> {\r\n ref: Ref<any | null>;\r\n\r\n value: TValue | undefined;\r\n\r\n handlers: {\r\n onChange: (event: ChangeEvent<EventTarget> | TValue) => void;\r\n onFocus: () => void;\r\n onBlur: () => void;\r\n };\r\n\r\n field: undefined extends TValue\r\n ? FormField<TOutput, TValue>\r\n : NonnullFormField<TOutput, TValue>;\r\n\r\n form: UseForm<TOutput>;\r\n}\r\n\r\ntype DefaultValueProps<TValue> = undefined extends TValue\r\n ? { defaultValue?: TValue | (() => TValue) }\r\n : { defaultValue: TValue | (() => TValue) };\r\n\r\nexport type FieldRendererProps<\r\n TOutput extends object,\r\n TPath extends FieldPath.Segments,\r\n> = {\r\n form: UseForm<TOutput>;\r\n path: TPath;\r\n overrideInitialValue?: boolean;\r\n unbindOnUnmount?: boolean;\r\n render: (\r\n params: RenderParams<TOutput, FieldPath.Resolve<TOutput, NoInfer<TPath>>>,\r\n ) => ReactNode;\r\n} & DefaultValueProps<FieldPath.Resolve<TOutput, NoInfer<TPath>>>;\r\n\r\nexport function FieldRenderer<\r\n TOutput extends object,\r\n const TPath extends FieldPath.Segments,\r\n>(props: FieldRendererProps<TOutput, TPath>) {\r\n type TValue = FieldPath.Resolve<TOutput, TPath>;\r\n\r\n const elementRef = useRef<HTMLElement>(null);\r\n\r\n const field = useFormField(props.form, props.path, {\r\n overrideInitialValue: props.overrideInitialValue ?? true,\r\n defaultValue:\r\n typeof props.defaultValue === \"function\"\r\n ? (props.defaultValue as any)()\r\n : props.defaultValue,\r\n })!;\r\n\r\n const handlers: RenderParams<TOutput, TValue>[\"handlers\"] = {\r\n onChange(arg) {\r\n let newValue: TValue;\r\n\r\n if (\"target\" in arg) {\r\n const { target } = arg;\r\n if (target !== field.boundElement) return;\r\n if (!(\"value\" in target)) return;\r\n if (typeof target.value !== \"string\") return;\r\n newValue = target.value as TValue;\r\n } else {\r\n newValue = arg;\r\n }\r\n\r\n field.setValue(newValue, {\r\n shouldTouch: true,\r\n shouldMarkDirty: true,\r\n });\r\n },\r\n onFocus() {\r\n field.touch();\r\n },\r\n onBlur() {\r\n if (\r\n props.form.hookConfigs?.validateMode === \"onBlur\" ||\r\n props.form.hookConfigs?.validateMode === \"onChange\"\r\n ) {\r\n props.form.controller.validateField(props.path);\r\n }\r\n },\r\n };\r\n\r\n useEffect(() => {\r\n const { events } = props.form.controller;\r\n\r\n return composeFns(\r\n events.on(\"valueChanged\", (_path) => {\r\n if (\r\n !FieldPath.equals(_path, props.path) &&\r\n !FieldPath.isDescendant(_path, props.path)\r\n ) {\r\n return;\r\n }\r\n\r\n if (props.form.hookConfigs?.validateMode === \"onChange\") {\r\n props.form.controller.validateField(props.path);\r\n }\r\n }),\r\n );\r\n }, []);\r\n\r\n useEffect(() => {\r\n field.bindElement(elementRef.current!);\r\n\r\n return () => {\r\n if (props.unbindOnUnmount) {\r\n props.form.controller.unbindField(props.path);\r\n }\r\n };\r\n }, []);\r\n\r\n return (\r\n <>\r\n {props.render({\r\n ref: elementRef,\r\n value: field.value,\r\n handlers: handlers,\r\n field: field as any,\r\n form: props.form,\r\n })}\r\n </>\r\n );\r\n}\r\n\r\n/* ---- TESTS ---------------- */\r\n\r\n// function TestComp() {\r\n// const form = useForm<{ a?: { b: 99 } }>({});\r\n\r\n// const jsx = (\r\n// <>\r\n// <FieldRenderer\r\n// form={form}\r\n// path={form.paths.fromProxy((data) => data.a.b)}\r\n// defaultValue={() => 99 as const}\r\n// render={({ ref, value, handlers, field }) => {\r\n// // ^?\r\n// return <></>;\r\n// }}\r\n// />\r\n\r\n// {/* defaultField olmayabilir, çünkü \"a\" nullable */}\r\n// <FieldRenderer\r\n// form={form}\r\n// path={form.paths.fromProxy((data) => data.a)}\r\n// render={({ ref, value, handlers, field }) => {\r\n// // ^?\r\n// return <></>;\r\n// }}\r\n// />\r\n\r\n// <FieldRenderer\r\n// form={form}\r\n// path={form.paths.fromStringPath(\"a.b\")}\r\n// defaultValue={() => 99 as const}\r\n// render={({ ref, value, handlers, field }) => {\r\n// // ^?\r\n// return <></>;\r\n// }}\r\n// />\r\n// </>\r\n// );\r\n// }\r\n"],"names":["useRenderControl","rerender","useState","renderCount","useRef","renderScheduled","scheduleRerender","startTransition","i","composeFns","fns","fn","useForm","formConfigs","hookConfigs","controller","FormController","paths","FieldPathBuilder","renderControl","useEffect","noop","useFormField","form","path","bindingConfig","field","setField","events","_path","FieldPath","changedPath","useFieldValue","value","fieldPath","useFieldErrors","issues","useFormValuesObserver","options","observedValues","data","groupBy","items","key","result","item","k","useFormErrorObserver","observedIssues","issue","normalizedIssuePath","FieldRenderer","props","elementRef","handlers","arg","newValue","target","jsx","Fragment"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@goodie-forms/react",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.3-alpha",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"react-dom": "^18 || ^19"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@goodie-forms/core": "1.2.
|
|
21
|
+
"@goodie-forms/core": "1.2.3-alpha"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
24
|
"@types/react": "^19.2.9",
|
|
@@ -1,13 +1,6 @@
|
|
|
1
1
|
import { FieldPath, FormField, NonnullFormField } from "@goodie-forms/core";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
FocusEvent,
|
|
5
|
-
ReactNode,
|
|
6
|
-
Ref,
|
|
7
|
-
useEffect,
|
|
8
|
-
useRef,
|
|
9
|
-
} from "react";
|
|
10
|
-
import { useForm, UseForm } from "../hooks/useForm";
|
|
2
|
+
import { ChangeEvent, ReactNode, Ref, useEffect, useRef } from "react";
|
|
3
|
+
import { UseForm } from "../hooks/useForm";
|
|
11
4
|
import { useFormField } from "../hooks/useFormField";
|
|
12
5
|
import { composeFns } from "../utils/composeFns";
|
|
13
6
|
|
|
@@ -17,14 +10,16 @@ export interface RenderParams<TOutput extends object, TValue> {
|
|
|
17
10
|
value: TValue | undefined;
|
|
18
11
|
|
|
19
12
|
handlers: {
|
|
20
|
-
onChange: (event: ChangeEvent<EventTarget>) => void;
|
|
21
|
-
onFocus: (
|
|
22
|
-
onBlur: (
|
|
13
|
+
onChange: (event: ChangeEvent<EventTarget> | TValue) => void;
|
|
14
|
+
onFocus: () => void;
|
|
15
|
+
onBlur: () => void;
|
|
23
16
|
};
|
|
24
17
|
|
|
25
18
|
field: undefined extends TValue
|
|
26
19
|
? FormField<TOutput, TValue>
|
|
27
20
|
: NonnullFormField<TOutput, TValue>;
|
|
21
|
+
|
|
22
|
+
form: UseForm<TOutput>;
|
|
28
23
|
}
|
|
29
24
|
|
|
30
25
|
type DefaultValueProps<TValue> = undefined extends TValue
|
|
@@ -61,12 +56,20 @@ export function FieldRenderer<
|
|
|
61
56
|
})!;
|
|
62
57
|
|
|
63
58
|
const handlers: RenderParams<TOutput, TValue>["handlers"] = {
|
|
64
|
-
onChange(
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
if (
|
|
68
|
-
|
|
69
|
-
|
|
59
|
+
onChange(arg) {
|
|
60
|
+
let newValue: TValue;
|
|
61
|
+
|
|
62
|
+
if ("target" in arg) {
|
|
63
|
+
const { target } = arg;
|
|
64
|
+
if (target !== field.boundElement) return;
|
|
65
|
+
if (!("value" in target)) return;
|
|
66
|
+
if (typeof target.value !== "string") return;
|
|
67
|
+
newValue = target.value as TValue;
|
|
68
|
+
} else {
|
|
69
|
+
newValue = arg;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
field.setValue(newValue, {
|
|
70
73
|
shouldTouch: true,
|
|
71
74
|
shouldMarkDirty: true,
|
|
72
75
|
});
|
|
@@ -120,6 +123,7 @@ export function FieldRenderer<
|
|
|
120
123
|
value: field.value,
|
|
121
124
|
handlers: handlers,
|
|
122
125
|
field: field as any,
|
|
126
|
+
form: props.form,
|
|
123
127
|
})}
|
|
124
128
|
</>
|
|
125
129
|
);
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { FieldPath } from "@goodie-forms/core";
|
|
2
|
+
import { useEffect } from "react";
|
|
3
|
+
import { UseForm } from "../hooks/useForm";
|
|
4
|
+
import { useRenderControl } from "../hooks/useRenderControl";
|
|
5
|
+
import { composeFns } from "../utils/composeFns";
|
|
6
|
+
|
|
7
|
+
export function useFieldErrors<
|
|
8
|
+
TOutput extends object,
|
|
9
|
+
TPath extends FieldPath.Segments,
|
|
10
|
+
>(form: UseForm<TOutput>, path: TPath) {
|
|
11
|
+
const renderControl = useRenderControl();
|
|
12
|
+
|
|
13
|
+
const issues = form.controller.getField(path)?.issues;
|
|
14
|
+
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
return composeFns(
|
|
17
|
+
form.controller.events.on("fieldBound", (fieldPath) => {
|
|
18
|
+
if (FieldPath.equals(path, fieldPath)) {
|
|
19
|
+
renderControl.forceRerender();
|
|
20
|
+
}
|
|
21
|
+
}),
|
|
22
|
+
form.controller.events.on("fieldIssuesUpdated", (fieldPath) => {
|
|
23
|
+
if (FieldPath.equals(path, fieldPath)) {
|
|
24
|
+
renderControl.forceRerender();
|
|
25
|
+
}
|
|
26
|
+
}),
|
|
27
|
+
);
|
|
28
|
+
}, []);
|
|
29
|
+
|
|
30
|
+
return issues;
|
|
31
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { FieldPath } from "@goodie-forms/core";
|
|
2
|
+
import { useEffect } from "react";
|
|
3
|
+
import { UseForm } from "../hooks/useForm";
|
|
4
|
+
import { useRenderControl } from "../hooks/useRenderControl";
|
|
5
|
+
import { composeFns } from "../utils/composeFns";
|
|
6
|
+
|
|
7
|
+
export function useFieldValue<
|
|
8
|
+
TOutput extends object,
|
|
9
|
+
TPath extends FieldPath.Segments,
|
|
10
|
+
>(form: UseForm<TOutput>, path: TPath) {
|
|
11
|
+
const renderControl = useRenderControl();
|
|
12
|
+
|
|
13
|
+
const value = form.controller.getField(path)?.value;
|
|
14
|
+
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
return composeFns(
|
|
17
|
+
form.controller.events.on("fieldBound", (fieldPath) => {
|
|
18
|
+
if (FieldPath.equals(path, fieldPath)) {
|
|
19
|
+
renderControl.forceRerender();
|
|
20
|
+
}
|
|
21
|
+
}),
|
|
22
|
+
form.controller.events.on("valueChanged", (fieldPath) => {
|
|
23
|
+
if (FieldPath.equals(path, fieldPath)) {
|
|
24
|
+
renderControl.forceRerender();
|
|
25
|
+
}
|
|
26
|
+
}),
|
|
27
|
+
);
|
|
28
|
+
}, []);
|
|
29
|
+
|
|
30
|
+
return value;
|
|
31
|
+
}
|
|
@@ -5,6 +5,7 @@ import { composeFns } from "../utils/composeFns";
|
|
|
5
5
|
import type { UseForm } from "./useForm";
|
|
6
6
|
import { useRenderControl } from "./useRenderControl";
|
|
7
7
|
|
|
8
|
+
/** @deprecated */
|
|
8
9
|
export function useFormErrorObserver<
|
|
9
10
|
TOutput extends object,
|
|
10
11
|
TInclude extends FieldPath.Segments[] | undefined = undefined,
|
|
@@ -4,6 +4,7 @@ import { composeFns } from "../utils/composeFns";
|
|
|
4
4
|
import type { UseForm } from "./useForm";
|
|
5
5
|
import { useRenderControl } from "./useRenderControl";
|
|
6
6
|
|
|
7
|
+
/** @deprecated */
|
|
7
8
|
export function useFormValuesObserver<
|
|
8
9
|
TOutput extends object,
|
|
9
10
|
TPaths extends FieldPath.Segments[] | undefined = undefined,
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export * from "./hooks/useForm";
|
|
2
2
|
export * from "./hooks/useFormField";
|
|
3
|
+
export * from "./hooks/useFieldValue";
|
|
4
|
+
export * from "./hooks/useFieldErrors";
|
|
3
5
|
export * from "./hooks/useFormValuesObserver";
|
|
4
6
|
export * from "./hooks/useFormErrorObserver";
|
|
5
7
|
export * from "./hooks/useRenderControl";
|