@conform-to/react 1.13.3 → 1.14.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/future/dom.d.ts +5 -4
- package/dist/future/dom.js +22 -8
- package/dist/future/dom.mjs +23 -10
- package/dist/future/hooks.d.ts +56 -11
- package/dist/future/hooks.js +120 -68
- package/dist/future/hooks.mjs +121 -69
- package/dist/future/intent.d.ts +1 -1
- package/dist/future/intent.js +10 -14
- package/dist/future/intent.mjs +12 -16
- package/dist/future/state.d.ts +23 -15
- package/dist/future/state.js +53 -20
- package/dist/future/state.mjs +53 -21
- package/dist/future/types.d.ts +63 -46
- package/package.json +2 -2
package/dist/future/state.js
CHANGED
|
@@ -6,12 +6,14 @@ var _rollupPluginBabelHelpers = require('../_virtual/_rollupPluginBabelHelpers.j
|
|
|
6
6
|
var future = require('@conform-to/dom/future');
|
|
7
7
|
var util = require('./util.js');
|
|
8
8
|
|
|
9
|
-
function initializeState(
|
|
9
|
+
function initializeState(options) {
|
|
10
|
+
var _options$resetKey, _options$defaultValue;
|
|
10
11
|
return {
|
|
11
|
-
resetKey: resetKey !== null && resetKey !== void 0 ? resetKey : util.generateUniqueKey(),
|
|
12
|
+
resetKey: (_options$resetKey = options === null || options === void 0 ? void 0 : options.resetKey) !== null && _options$resetKey !== void 0 ? _options$resetKey : util.generateUniqueKey(),
|
|
12
13
|
listKeys: {},
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
defaultValue: (_options$defaultValue = options === null || options === void 0 ? void 0 : options.defaultValue) !== null && _options$defaultValue !== void 0 ? _options$defaultValue : {},
|
|
15
|
+
targetValue: null,
|
|
16
|
+
serverValue: null,
|
|
15
17
|
serverError: null,
|
|
16
18
|
clientError: null,
|
|
17
19
|
touchedFields: []
|
|
@@ -20,33 +22,35 @@ function initializeState(resetKey) {
|
|
|
20
22
|
|
|
21
23
|
/**
|
|
22
24
|
* Updates form state based on action type:
|
|
23
|
-
* - Client actions: update
|
|
24
|
-
* - Server actions: update server errors and clear client errors
|
|
25
|
-
* - Initialize: set initial
|
|
25
|
+
* - Client actions: update target value and client errors
|
|
26
|
+
* - Server actions: update server errors and clear client errors, with optional target value
|
|
27
|
+
* - Initialize: set initial server value
|
|
26
28
|
*/
|
|
27
29
|
function updateState(state, action) {
|
|
28
|
-
var _action$
|
|
29
|
-
if (action.
|
|
30
|
-
return action.ctx.reset();
|
|
30
|
+
var _action$targetValue, _action$targetValue2, _action$intent, _action$ctx$handlers;
|
|
31
|
+
if (action.reset) {
|
|
32
|
+
return action.ctx.reset(action.targetValue);
|
|
31
33
|
}
|
|
32
|
-
var value = (_action$
|
|
34
|
+
var value = (_action$targetValue = action.targetValue) !== null && _action$targetValue !== void 0 ? _action$targetValue : action.submission.payload;
|
|
33
35
|
|
|
34
|
-
// Apply the form error and
|
|
36
|
+
// Apply the form error and target value from the result first
|
|
35
37
|
state = action.type === 'client' ? util.merge(state, {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
+
targetValue: (_action$targetValue2 = action.targetValue) !== null && _action$targetValue2 !== void 0 ? _action$targetValue2 : state.targetValue,
|
|
39
|
+
serverValue: action.targetValue ? null : state.serverValue,
|
|
38
40
|
// Update client error only if the error is different from the previous one to minimize unnecessary re-renders
|
|
39
41
|
clientError: typeof action.error !== 'undefined' && !future.deepEqual(state.clientError, action.error) ? action.error : state.clientError,
|
|
40
42
|
// Reset server error if form value is changed
|
|
41
|
-
serverError: typeof action.error !== 'undefined' && !future.deepEqual(state.
|
|
43
|
+
serverError: typeof action.error !== 'undefined' && !future.deepEqual(state.serverValue, value) ? null : state.serverError
|
|
42
44
|
}) : util.merge(state, {
|
|
43
45
|
// Clear client error to avoid showing stale errors
|
|
44
46
|
clientError: null,
|
|
45
47
|
// Update server error if the error is defined.
|
|
46
48
|
// There is no need to check if the error is different as we are updating other states as well
|
|
47
49
|
serverError: typeof action.error !== 'undefined' ? action.error : state.serverError,
|
|
50
|
+
listKeys: action.type === 'server' && action.targetValue ? pruneListKeys(state.listKeys, action.targetValue) : state.listKeys,
|
|
51
|
+
targetValue: action.type === 'server' && action.targetValue ? action.targetValue : state.targetValue,
|
|
48
52
|
// Keep track of the value that the serverError is based on
|
|
49
|
-
|
|
53
|
+
serverValue: !future.deepEqual(state.serverValue, value) ? value : state.serverValue
|
|
50
54
|
});
|
|
51
55
|
// Validate the whole form if no intent is provided (default submission)
|
|
52
56
|
var intent = (_action$intent = action.intent) !== null && _action$intent !== void 0 ? _action$intent : {
|
|
@@ -57,6 +61,9 @@ function updateState(state, action) {
|
|
|
57
61
|
var _handler$validatePayl, _handler$validatePayl2;
|
|
58
62
|
if ((_handler$validatePayl = (_handler$validatePayl2 = handler.validatePayload) === null || _handler$validatePayl2 === void 0 ? void 0 : _handler$validatePayl2.call(handler, intent.payload)) !== null && _handler$validatePayl !== void 0 ? _handler$validatePayl : true) {
|
|
59
63
|
return handler.onUpdate(state, _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, action), {}, {
|
|
64
|
+
ctx: {
|
|
65
|
+
reset: action.ctx.reset
|
|
66
|
+
},
|
|
60
67
|
intent: {
|
|
61
68
|
type: intent.type,
|
|
62
69
|
payload: intent.payload
|
|
@@ -66,10 +73,34 @@ function updateState(state, action) {
|
|
|
66
73
|
}
|
|
67
74
|
return state;
|
|
68
75
|
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Removes list keys where array length has changed to force regeneration.
|
|
79
|
+
* Minimizes UI state loss by only invalidating keys when necessary.
|
|
80
|
+
*/
|
|
81
|
+
function pruneListKeys(listKeys, targetValue) {
|
|
82
|
+
var result = listKeys;
|
|
83
|
+
for (var [name, keys] of Object.entries(listKeys)) {
|
|
84
|
+
var list = util.getArrayAtPath(targetValue, name);
|
|
85
|
+
|
|
86
|
+
// Reset list keys only if the length has changed
|
|
87
|
+
// to minimize potential UI state loss due to key changes
|
|
88
|
+
if (keys.length !== list.length) {
|
|
89
|
+
// Create a shallow copy to avoid mutating the original object
|
|
90
|
+
if (result === listKeys) {
|
|
91
|
+
result = _rollupPluginBabelHelpers.objectSpread2({}, result);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Remove the list key to force regeneration
|
|
95
|
+
delete result[name];
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return result;
|
|
99
|
+
}
|
|
69
100
|
function getDefaultValue(context, name) {
|
|
70
101
|
var _ref, _context$state$server;
|
|
71
102
|
var serialize = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : future.serialize;
|
|
72
|
-
var value = future.getValueAtPath((_ref = (_context$state$server = context.state.
|
|
103
|
+
var value = future.getValueAtPath((_ref = (_context$state$server = context.state.serverValue) !== null && _context$state$server !== void 0 ? _context$state$server : context.state.targetValue) !== null && _ref !== void 0 ? _ref : context.state.defaultValue, name);
|
|
73
104
|
var serializedValue = serialize(value);
|
|
74
105
|
if (typeof serializedValue === 'string') {
|
|
75
106
|
return serializedValue;
|
|
@@ -79,7 +110,7 @@ function getDefaultValue(context, name) {
|
|
|
79
110
|
function getDefaultOptions(context, name) {
|
|
80
111
|
var _ref2, _context$state$server2;
|
|
81
112
|
var serialize = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : future.serialize;
|
|
82
|
-
var value = future.getValueAtPath((_ref2 = (_context$state$server2 = context.state.
|
|
113
|
+
var value = future.getValueAtPath((_ref2 = (_context$state$server2 = context.state.serverValue) !== null && _context$state$server2 !== void 0 ? _context$state$server2 : context.state.targetValue) !== null && _ref2 !== void 0 ? _ref2 : context.state.defaultValue, name);
|
|
83
114
|
var serializedValue = serialize(value);
|
|
84
115
|
if (Array.isArray(serializedValue) && serializedValue.every(item => typeof item === 'string')) {
|
|
85
116
|
return serializedValue;
|
|
@@ -92,7 +123,7 @@ function getDefaultOptions(context, name) {
|
|
|
92
123
|
function isDefaultChecked(context, name) {
|
|
93
124
|
var _ref3, _context$state$server3;
|
|
94
125
|
var serialize = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : future.serialize;
|
|
95
|
-
var value = future.getValueAtPath((_ref3 = (_context$state$server3 = context.state.
|
|
126
|
+
var value = future.getValueAtPath((_ref3 = (_context$state$server3 = context.state.serverValue) !== null && _context$state$server3 !== void 0 ? _context$state$server3 : context.state.targetValue) !== null && _ref3 !== void 0 ? _ref3 : context.state.defaultValue, name);
|
|
96
127
|
var serializedValue = serialize(value);
|
|
97
128
|
if (typeof serializedValue === 'string') {
|
|
98
129
|
return serializedValue === 'on';
|
|
@@ -119,7 +150,7 @@ function getDefaultListKey(prefix, initialValue, name) {
|
|
|
119
150
|
}
|
|
120
151
|
function getListKey(context, name) {
|
|
121
152
|
var _context$state$listKe, _context$state$listKe2, _ref4, _context$state$server4;
|
|
122
|
-
return (_context$state$listKe = (_context$state$listKe2 = context.state.listKeys) === null || _context$state$listKe2 === void 0 ? void 0 : _context$state$listKe2[name]) !== null && _context$state$listKe !== void 0 ? _context$state$listKe : getDefaultListKey(context.state.resetKey, (_ref4 = (_context$state$server4 = context.state.
|
|
153
|
+
return (_context$state$listKe = (_context$state$listKe2 = context.state.listKeys) === null || _context$state$listKe2 === void 0 ? void 0 : _context$state$listKe2[name]) !== null && _context$state$listKe !== void 0 ? _context$state$listKe : getDefaultListKey(context.state.resetKey, (_ref4 = (_context$state$server4 = context.state.serverValue) !== null && _context$state$server4 !== void 0 ? _context$state$server4 : context.state.targetValue) !== null && _ref4 !== void 0 ? _ref4 : context.state.defaultValue, name);
|
|
123
154
|
}
|
|
124
155
|
function getErrors(state, name) {
|
|
125
156
|
var _state$serverError;
|
|
@@ -215,6 +246,7 @@ function getFormMetadata(context, options) {
|
|
|
215
246
|
id: context.formId,
|
|
216
247
|
errorId: "".concat(context.formId, "-form-error"),
|
|
217
248
|
descriptionId: "".concat(context.formId, "-form-description"),
|
|
249
|
+
defaultValue: context.state.defaultValue,
|
|
218
250
|
get errors() {
|
|
219
251
|
return getErrors(context.state);
|
|
220
252
|
},
|
|
@@ -403,4 +435,5 @@ exports.initializeState = initializeState;
|
|
|
403
435
|
exports.isDefaultChecked = isDefaultChecked;
|
|
404
436
|
exports.isTouched = isTouched;
|
|
405
437
|
exports.isValid = isValid;
|
|
438
|
+
exports.pruneListKeys = pruneListKeys;
|
|
406
439
|
exports.updateState = updateState;
|
package/dist/future/state.mjs
CHANGED
|
@@ -2,12 +2,14 @@ import { objectSpread2 as _objectSpread2 } from '../_virtual/_rollupPluginBabelH
|
|
|
2
2
|
import { getPathSegments, getRelativePath, appendPathSegment, deepEqual, getValueAtPath, formatPathSegments, serialize } from '@conform-to/dom/future';
|
|
3
3
|
import { generateUniqueKey, merge, getArrayAtPath } from './util.mjs';
|
|
4
4
|
|
|
5
|
-
function initializeState(
|
|
5
|
+
function initializeState(options) {
|
|
6
|
+
var _options$resetKey, _options$defaultValue;
|
|
6
7
|
return {
|
|
7
|
-
resetKey: resetKey !== null && resetKey !== void 0 ? resetKey : generateUniqueKey(),
|
|
8
|
+
resetKey: (_options$resetKey = options === null || options === void 0 ? void 0 : options.resetKey) !== null && _options$resetKey !== void 0 ? _options$resetKey : generateUniqueKey(),
|
|
8
9
|
listKeys: {},
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
defaultValue: (_options$defaultValue = options === null || options === void 0 ? void 0 : options.defaultValue) !== null && _options$defaultValue !== void 0 ? _options$defaultValue : {},
|
|
11
|
+
targetValue: null,
|
|
12
|
+
serverValue: null,
|
|
11
13
|
serverError: null,
|
|
12
14
|
clientError: null,
|
|
13
15
|
touchedFields: []
|
|
@@ -16,33 +18,35 @@ function initializeState(resetKey) {
|
|
|
16
18
|
|
|
17
19
|
/**
|
|
18
20
|
* Updates form state based on action type:
|
|
19
|
-
* - Client actions: update
|
|
20
|
-
* - Server actions: update server errors and clear client errors
|
|
21
|
-
* - Initialize: set initial
|
|
21
|
+
* - Client actions: update target value and client errors
|
|
22
|
+
* - Server actions: update server errors and clear client errors, with optional target value
|
|
23
|
+
* - Initialize: set initial server value
|
|
22
24
|
*/
|
|
23
25
|
function updateState(state, action) {
|
|
24
|
-
var _action$
|
|
25
|
-
if (action.
|
|
26
|
-
return action.ctx.reset();
|
|
26
|
+
var _action$targetValue, _action$targetValue2, _action$intent, _action$ctx$handlers;
|
|
27
|
+
if (action.reset) {
|
|
28
|
+
return action.ctx.reset(action.targetValue);
|
|
27
29
|
}
|
|
28
|
-
var value = (_action$
|
|
30
|
+
var value = (_action$targetValue = action.targetValue) !== null && _action$targetValue !== void 0 ? _action$targetValue : action.submission.payload;
|
|
29
31
|
|
|
30
|
-
// Apply the form error and
|
|
32
|
+
// Apply the form error and target value from the result first
|
|
31
33
|
state = action.type === 'client' ? merge(state, {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
+
targetValue: (_action$targetValue2 = action.targetValue) !== null && _action$targetValue2 !== void 0 ? _action$targetValue2 : state.targetValue,
|
|
35
|
+
serverValue: action.targetValue ? null : state.serverValue,
|
|
34
36
|
// Update client error only if the error is different from the previous one to minimize unnecessary re-renders
|
|
35
37
|
clientError: typeof action.error !== 'undefined' && !deepEqual(state.clientError, action.error) ? action.error : state.clientError,
|
|
36
38
|
// Reset server error if form value is changed
|
|
37
|
-
serverError: typeof action.error !== 'undefined' && !deepEqual(state.
|
|
39
|
+
serverError: typeof action.error !== 'undefined' && !deepEqual(state.serverValue, value) ? null : state.serverError
|
|
38
40
|
}) : merge(state, {
|
|
39
41
|
// Clear client error to avoid showing stale errors
|
|
40
42
|
clientError: null,
|
|
41
43
|
// Update server error if the error is defined.
|
|
42
44
|
// There is no need to check if the error is different as we are updating other states as well
|
|
43
45
|
serverError: typeof action.error !== 'undefined' ? action.error : state.serverError,
|
|
46
|
+
listKeys: action.type === 'server' && action.targetValue ? pruneListKeys(state.listKeys, action.targetValue) : state.listKeys,
|
|
47
|
+
targetValue: action.type === 'server' && action.targetValue ? action.targetValue : state.targetValue,
|
|
44
48
|
// Keep track of the value that the serverError is based on
|
|
45
|
-
|
|
49
|
+
serverValue: !deepEqual(state.serverValue, value) ? value : state.serverValue
|
|
46
50
|
});
|
|
47
51
|
// Validate the whole form if no intent is provided (default submission)
|
|
48
52
|
var intent = (_action$intent = action.intent) !== null && _action$intent !== void 0 ? _action$intent : {
|
|
@@ -53,6 +57,9 @@ function updateState(state, action) {
|
|
|
53
57
|
var _handler$validatePayl, _handler$validatePayl2;
|
|
54
58
|
if ((_handler$validatePayl = (_handler$validatePayl2 = handler.validatePayload) === null || _handler$validatePayl2 === void 0 ? void 0 : _handler$validatePayl2.call(handler, intent.payload)) !== null && _handler$validatePayl !== void 0 ? _handler$validatePayl : true) {
|
|
55
59
|
return handler.onUpdate(state, _objectSpread2(_objectSpread2({}, action), {}, {
|
|
60
|
+
ctx: {
|
|
61
|
+
reset: action.ctx.reset
|
|
62
|
+
},
|
|
56
63
|
intent: {
|
|
57
64
|
type: intent.type,
|
|
58
65
|
payload: intent.payload
|
|
@@ -62,10 +69,34 @@ function updateState(state, action) {
|
|
|
62
69
|
}
|
|
63
70
|
return state;
|
|
64
71
|
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Removes list keys where array length has changed to force regeneration.
|
|
75
|
+
* Minimizes UI state loss by only invalidating keys when necessary.
|
|
76
|
+
*/
|
|
77
|
+
function pruneListKeys(listKeys, targetValue) {
|
|
78
|
+
var result = listKeys;
|
|
79
|
+
for (var [name, keys] of Object.entries(listKeys)) {
|
|
80
|
+
var list = getArrayAtPath(targetValue, name);
|
|
81
|
+
|
|
82
|
+
// Reset list keys only if the length has changed
|
|
83
|
+
// to minimize potential UI state loss due to key changes
|
|
84
|
+
if (keys.length !== list.length) {
|
|
85
|
+
// Create a shallow copy to avoid mutating the original object
|
|
86
|
+
if (result === listKeys) {
|
|
87
|
+
result = _objectSpread2({}, result);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Remove the list key to force regeneration
|
|
91
|
+
delete result[name];
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return result;
|
|
95
|
+
}
|
|
65
96
|
function getDefaultValue(context, name) {
|
|
66
97
|
var _ref, _context$state$server;
|
|
67
98
|
var serialize$1 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : serialize;
|
|
68
|
-
var value = getValueAtPath((_ref = (_context$state$server = context.state.
|
|
99
|
+
var value = getValueAtPath((_ref = (_context$state$server = context.state.serverValue) !== null && _context$state$server !== void 0 ? _context$state$server : context.state.targetValue) !== null && _ref !== void 0 ? _ref : context.state.defaultValue, name);
|
|
69
100
|
var serializedValue = serialize$1(value);
|
|
70
101
|
if (typeof serializedValue === 'string') {
|
|
71
102
|
return serializedValue;
|
|
@@ -75,7 +106,7 @@ function getDefaultValue(context, name) {
|
|
|
75
106
|
function getDefaultOptions(context, name) {
|
|
76
107
|
var _ref2, _context$state$server2;
|
|
77
108
|
var serialize$1 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : serialize;
|
|
78
|
-
var value = getValueAtPath((_ref2 = (_context$state$server2 = context.state.
|
|
109
|
+
var value = getValueAtPath((_ref2 = (_context$state$server2 = context.state.serverValue) !== null && _context$state$server2 !== void 0 ? _context$state$server2 : context.state.targetValue) !== null && _ref2 !== void 0 ? _ref2 : context.state.defaultValue, name);
|
|
79
110
|
var serializedValue = serialize$1(value);
|
|
80
111
|
if (Array.isArray(serializedValue) && serializedValue.every(item => typeof item === 'string')) {
|
|
81
112
|
return serializedValue;
|
|
@@ -88,7 +119,7 @@ function getDefaultOptions(context, name) {
|
|
|
88
119
|
function isDefaultChecked(context, name) {
|
|
89
120
|
var _ref3, _context$state$server3;
|
|
90
121
|
var serialize$1 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : serialize;
|
|
91
|
-
var value = getValueAtPath((_ref3 = (_context$state$server3 = context.state.
|
|
122
|
+
var value = getValueAtPath((_ref3 = (_context$state$server3 = context.state.serverValue) !== null && _context$state$server3 !== void 0 ? _context$state$server3 : context.state.targetValue) !== null && _ref3 !== void 0 ? _ref3 : context.state.defaultValue, name);
|
|
92
123
|
var serializedValue = serialize$1(value);
|
|
93
124
|
if (typeof serializedValue === 'string') {
|
|
94
125
|
return serializedValue === 'on';
|
|
@@ -115,7 +146,7 @@ function getDefaultListKey(prefix, initialValue, name) {
|
|
|
115
146
|
}
|
|
116
147
|
function getListKey(context, name) {
|
|
117
148
|
var _context$state$listKe, _context$state$listKe2, _ref4, _context$state$server4;
|
|
118
|
-
return (_context$state$listKe = (_context$state$listKe2 = context.state.listKeys) === null || _context$state$listKe2 === void 0 ? void 0 : _context$state$listKe2[name]) !== null && _context$state$listKe !== void 0 ? _context$state$listKe : getDefaultListKey(context.state.resetKey, (_ref4 = (_context$state$server4 = context.state.
|
|
149
|
+
return (_context$state$listKe = (_context$state$listKe2 = context.state.listKeys) === null || _context$state$listKe2 === void 0 ? void 0 : _context$state$listKe2[name]) !== null && _context$state$listKe !== void 0 ? _context$state$listKe : getDefaultListKey(context.state.resetKey, (_ref4 = (_context$state$server4 = context.state.serverValue) !== null && _context$state$server4 !== void 0 ? _context$state$server4 : context.state.targetValue) !== null && _ref4 !== void 0 ? _ref4 : context.state.defaultValue, name);
|
|
119
150
|
}
|
|
120
151
|
function getErrors(state, name) {
|
|
121
152
|
var _state$serverError;
|
|
@@ -211,6 +242,7 @@ function getFormMetadata(context, options) {
|
|
|
211
242
|
id: context.formId,
|
|
212
243
|
errorId: "".concat(context.formId, "-form-error"),
|
|
213
244
|
descriptionId: "".concat(context.formId, "-form-description"),
|
|
245
|
+
defaultValue: context.state.defaultValue,
|
|
214
246
|
get errors() {
|
|
215
247
|
return getErrors(context.state);
|
|
216
248
|
},
|
|
@@ -384,4 +416,4 @@ function getFieldList(context, options) {
|
|
|
384
416
|
});
|
|
385
417
|
}
|
|
386
418
|
|
|
387
|
-
export { getConstraint, getDefaultListKey, getDefaultOptions, getDefaultValue, getErrors, getField, getFieldErrors, getFieldList, getFieldset, getFormMetadata, getListKey, initializeState, isDefaultChecked, isTouched, isValid, updateState };
|
|
419
|
+
export { getConstraint, getDefaultListKey, getDefaultOptions, getDefaultValue, getErrors, getField, getFieldErrors, getFieldList, getFieldset, getFormMetadata, getListKey, initializeState, isDefaultChecked, isTouched, isValid, pruneListKeys, updateState };
|
package/dist/future/types.d.ts
CHANGED
|
@@ -6,10 +6,10 @@ export type Prettify<T> = {
|
|
|
6
6
|
/** Reference to a form element. Can be either a React ref object or a form ID string. */
|
|
7
7
|
export type FormRef = React.RefObject<HTMLFormElement | HTMLFieldSetElement | HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement | HTMLButtonElement | null> | string;
|
|
8
8
|
export type InputSnapshot = {
|
|
9
|
-
value?: string;
|
|
10
|
-
options?: string[];
|
|
11
|
-
checked?: boolean;
|
|
12
|
-
files?: File[];
|
|
9
|
+
value?: string | undefined;
|
|
10
|
+
options?: string[] | undefined;
|
|
11
|
+
checked?: boolean | undefined;
|
|
12
|
+
files?: File[] | undefined;
|
|
13
13
|
};
|
|
14
14
|
export type Control = {
|
|
15
15
|
/**
|
|
@@ -75,10 +75,12 @@ export type DefaultValue<Shape> = Shape extends Record<string, any> ? {
|
|
|
75
75
|
export type FormState<ErrorShape extends BaseErrorShape = DefaultErrorShape> = {
|
|
76
76
|
/** Unique identifier that changes on form reset to trigger reset side effects */
|
|
77
77
|
resetKey: string;
|
|
78
|
-
/**
|
|
79
|
-
|
|
78
|
+
/** Initial form values */
|
|
79
|
+
defaultValue: Record<string, unknown>;
|
|
80
|
+
/** Form values that will be synced to the DOM */
|
|
81
|
+
targetValue: Record<string, unknown> | null;
|
|
80
82
|
/** Form values from server actions, or submitted values when no server intent exists */
|
|
81
|
-
|
|
83
|
+
serverValue: Record<string, unknown> | null;
|
|
82
84
|
/** Validation errors from server-side processing */
|
|
83
85
|
serverError: FormError<ErrorShape> | null;
|
|
84
86
|
/** Validation errors from client-side validation */
|
|
@@ -122,55 +124,55 @@ export type GlobalFormOptions = {
|
|
|
122
124
|
*/
|
|
123
125
|
defineCustomMetadata?: CustomMetadataDefinition;
|
|
124
126
|
};
|
|
125
|
-
export type
|
|
127
|
+
export type NonPartial<T> = {
|
|
128
|
+
[K in keyof Required<T>]: T[K];
|
|
129
|
+
};
|
|
130
|
+
export type RequireKey<T, K extends keyof T> = Prettify<T & Pick<NonPartial<T>, K>>;
|
|
131
|
+
export type BaseSchemaType = StandardSchemaV1<any, any>;
|
|
132
|
+
export type InferInput<Schema> = Schema extends StandardSchemaV1<infer input, any> ? input : unknown;
|
|
133
|
+
export type InferOutput<Schema> = Schema extends StandardSchemaV1<any, infer output> ? output : undefined;
|
|
134
|
+
export type BaseFormOptions<FormShape extends Record<string, any> = Record<string, any>, ErrorShape extends BaseErrorShape = string extends BaseErrorShape ? string : BaseErrorShape, Value = undefined, Schema = undefined> = {
|
|
126
135
|
/** Optional form identifier. If not provided, a unique ID is automatically generated. */
|
|
127
|
-
id?: string;
|
|
136
|
+
id?: string | undefined;
|
|
128
137
|
/** Optional key for form state reset. When the key changes, the form resets to its initial state. */
|
|
129
|
-
key?: string;
|
|
130
|
-
/**
|
|
131
|
-
|
|
138
|
+
key?: string | undefined;
|
|
139
|
+
/** Server-side submission result for form state synchronization. */
|
|
140
|
+
lastResult?: SubmissionResult<ErrorShape> | null | undefined;
|
|
141
|
+
/** Form submission handler called when the form is submitted with no validation errors. */
|
|
142
|
+
onSubmit?: SubmitHandler<FormShape, NoInfer<ErrorShape>, NoInfer<Value>> | undefined;
|
|
132
143
|
/** Initial form values. Can be a partial object matching your form structure. */
|
|
133
|
-
defaultValue?:
|
|
144
|
+
defaultValue?: DefaultValue<FormShape> | undefined;
|
|
134
145
|
/** HTML validation attributes for fields (required, minLength, pattern, etc.). */
|
|
135
|
-
constraint?: Record<string, ValidationAttributes
|
|
146
|
+
constraint?: Record<string, ValidationAttributes> | undefined;
|
|
136
147
|
/**
|
|
137
148
|
* Determines when validation should run for the first time on a field.
|
|
138
149
|
* Overrides the global default set by FormOptionsProvider if provided.
|
|
139
150
|
*
|
|
140
151
|
* @default Inherits from FormOptionsProvider, or "onSubmit" if not configured
|
|
141
152
|
*/
|
|
142
|
-
shouldValidate?: 'onSubmit' | 'onBlur' | 'onInput';
|
|
153
|
+
shouldValidate?: 'onSubmit' | 'onBlur' | 'onInput' | undefined;
|
|
143
154
|
/**
|
|
144
155
|
* Determines when validation should run again after the field has been validated once.
|
|
145
156
|
* Overrides the global default set by FormOptionsProvider if provided.
|
|
146
157
|
*
|
|
147
158
|
* @default Inherits from FormOptionsProvider, or same as shouldValidate
|
|
148
159
|
*/
|
|
149
|
-
shouldRevalidate?: 'onSubmit' | 'onBlur' | 'onInput';
|
|
150
|
-
/** Server-side submission result for form state synchronization. */
|
|
151
|
-
lastResult?: SubmissionResult<NoInfer<ErrorShape>> | null;
|
|
160
|
+
shouldRevalidate?: 'onSubmit' | 'onBlur' | 'onInput' | undefined;
|
|
152
161
|
/** Error handling callback triggered when validation errors occur. By default, it focuses the first invalid field. */
|
|
153
|
-
onError?: ErrorHandler<ErrorShape
|
|
154
|
-
/** Form submission handler called when the form is submitted with no validation errors. */
|
|
155
|
-
onSubmit?: SubmitHandler<NoInfer<ErrorShape>, NoInfer<Value>>;
|
|
162
|
+
onError?: ErrorHandler<NoInfer<ErrorShape>> | undefined;
|
|
156
163
|
/** Input event handler for custom input event logic. */
|
|
157
|
-
onInput?: InputHandler;
|
|
164
|
+
onInput?: InputHandler | undefined;
|
|
158
165
|
/** Blur event handler for custom focus handling logic. */
|
|
159
|
-
onBlur?: BlurHandler;
|
|
160
|
-
} & (string extends ErrorShape ? {
|
|
161
|
-
/** Custom validation handler. Can be skipped if using the schema property, or combined with schema to customize validation errors. */
|
|
162
|
-
onValidate?: ValidateHandler<ErrorShape, Value>;
|
|
163
|
-
} : {
|
|
166
|
+
onBlur?: BlurHandler | undefined;
|
|
164
167
|
/** Custom validation handler. Can be skipped if using the schema property, or combined with schema to customize validation errors. */
|
|
165
|
-
onValidate
|
|
166
|
-
}
|
|
168
|
+
onValidate?: ValidateHandler<ErrorShape, Value, InferOutput<Schema>> | undefined;
|
|
169
|
+
};
|
|
170
|
+
export type FormOptions<FormShape extends Record<string, any> = Record<string, any>, ErrorShape extends BaseErrorShape = string extends BaseErrorShape ? string : BaseErrorShape, Value = undefined, Schema = undefined, RequiredKeys extends keyof BaseFormOptions<FormShape, ErrorShape, Value, Schema> = never> = RequireKey<BaseFormOptions<FormShape, ErrorShape, Value, Schema>, RequiredKeys>;
|
|
167
171
|
export interface FormContext<ErrorShape extends BaseErrorShape = DefaultErrorShape> {
|
|
168
172
|
/** The form's unique identifier */
|
|
169
173
|
formId: string;
|
|
170
174
|
/** Internal form state with validation results and field data */
|
|
171
175
|
state: FormState<ErrorShape>;
|
|
172
|
-
/** Initial form values */
|
|
173
|
-
defaultValue: Record<string, any> | null;
|
|
174
176
|
/** HTML validation attributes for fields */
|
|
175
177
|
constraint: Record<string, ValidationAttributes> | null;
|
|
176
178
|
/** Form submission event handler */
|
|
@@ -231,11 +233,25 @@ export interface IntentDispatcher<FormShape extends Record<string, any> = Record
|
|
|
231
233
|
/**
|
|
232
234
|
* Specify the index of the item to update if the field is an array.
|
|
233
235
|
*/
|
|
234
|
-
index?:
|
|
236
|
+
index?: undefined;
|
|
235
237
|
/**
|
|
236
238
|
* The new value for the field or fieldset.
|
|
237
239
|
*/
|
|
238
240
|
value: DefaultValue<FieldShape>;
|
|
241
|
+
} | {
|
|
242
|
+
/**
|
|
243
|
+
* The name of the field. If you provide a fieldset name, it will update all fields within that fieldset.
|
|
244
|
+
*/
|
|
245
|
+
name: FieldName<FieldShape>;
|
|
246
|
+
/**
|
|
247
|
+
* Specify the index of the item to update if the field is an array.
|
|
248
|
+
*/
|
|
249
|
+
index: number;
|
|
250
|
+
/**
|
|
251
|
+
* The new value for the field or fieldset.
|
|
252
|
+
* When index is specified, this should be the item type, not the array type.
|
|
253
|
+
*/
|
|
254
|
+
value: unknown extends FieldShape ? any : FieldShape extends Array<infer ItemShape> ? ItemShape : any;
|
|
239
255
|
}): void;
|
|
240
256
|
/**
|
|
241
257
|
* Insert a new item into an array field.
|
|
@@ -285,10 +301,12 @@ export type FormIntent<Dispatcher extends IntentDispatcher = IntentDispatcher> =
|
|
|
285
301
|
}[keyof Dispatcher];
|
|
286
302
|
export type ActionHandler<Signature extends (payload: any) => void = (payload: any) => void> = {
|
|
287
303
|
validatePayload?(...args: UnknownArgs<Parameters<Signature>>): boolean;
|
|
288
|
-
onApply?(value: Record<string, FormValue>, ...args: Parameters<Signature>): Record<string, FormValue> |
|
|
304
|
+
onApply?(value: Record<string, FormValue>, ...args: Parameters<Signature>): Record<string, FormValue> | undefined;
|
|
289
305
|
onUpdate?<ErrorShape extends BaseErrorShape>(state: FormState<ErrorShape>, action: FormAction<ErrorShape, {
|
|
290
306
|
type: string;
|
|
291
307
|
payload: Signature extends (payload: infer Payload) => void ? Payload : undefined;
|
|
308
|
+
}, {
|
|
309
|
+
reset: (defaultValue?: Record<string, unknown> | null) => FormState<ErrorShape>;
|
|
292
310
|
}>): FormState<ErrorShape>;
|
|
293
311
|
};
|
|
294
312
|
type BaseCombine<T, K extends PropertyKey = T extends unknown ? keyof T : never> = T extends unknown ? T & Partial<Record<Exclude<K, keyof T>, never>> : never;
|
|
@@ -366,9 +384,7 @@ export type BaseMetadata<FieldShape, ErrorShape extends BaseErrorShape> = Valida
|
|
|
366
384
|
/** String value for the `aria-describedby` attribute. Contains the errorId when invalid, undefined otherwise. Merge with descriptionId manually if needed (e.g. `${metadata.descriptionId} ${metadata.ariaDescribedBy}`). */
|
|
367
385
|
ariaDescribedBy: string | undefined;
|
|
368
386
|
/** Method to get nested fieldset for object fields under this field. */
|
|
369
|
-
getFieldset<FieldsetShape =
|
|
370
|
-
Record<string, unknown> | null | undefined
|
|
371
|
-
] ? FieldShape : unknown>(): Fieldset<FieldsetShape, ErrorShape>;
|
|
387
|
+
getFieldset<FieldsetShape = keyof NonNullable<FieldShape> extends never ? unknown : FieldShape>(): Fieldset<FieldsetShape, ErrorShape>;
|
|
372
388
|
/** Method to get array of fields for list/array fields under this field. */
|
|
373
389
|
getFieldList<FieldItemShape = [FieldShape] extends [
|
|
374
390
|
Array<infer ItemShape> | null | undefined
|
|
@@ -407,6 +423,8 @@ export type FormMetadata<ErrorShape extends BaseErrorShape = DefaultErrorShape>
|
|
|
407
423
|
errors: ErrorShape[] | undefined;
|
|
408
424
|
/** Object containing errors for all touched fields. */
|
|
409
425
|
fieldErrors: Record<string, ErrorShape[]>;
|
|
426
|
+
/** The form's initial default values. */
|
|
427
|
+
defaultValue: Record<string, unknown>;
|
|
410
428
|
/** Form props object for spreading onto the <form> element. */
|
|
411
429
|
props: Readonly<{
|
|
412
430
|
id: string;
|
|
@@ -420,9 +438,7 @@ export type FormMetadata<ErrorShape extends BaseErrorShape = DefaultErrorShape>
|
|
|
420
438
|
/** Method to get metadata for a specific field by name. */
|
|
421
439
|
getField<FieldShape>(name: FieldName<FieldShape>): FieldMetadata<FieldShape, ErrorShape>;
|
|
422
440
|
/** Method to get a fieldset object for nested object fields. */
|
|
423
|
-
getFieldset<FieldShape>(name?: FieldName<FieldShape>): Fieldset<
|
|
424
|
-
FieldShape
|
|
425
|
-
] extends [Record<string, unknown> | null | undefined] ? FieldShape : unknown, ErrorShape>;
|
|
441
|
+
getFieldset<FieldShape>(name?: FieldName<FieldShape>): Fieldset<keyof NonNullable<FieldShape> extends never ? unknown : FieldShape, ErrorShape>;
|
|
426
442
|
/** Method to get an array of field objects for array fields. */
|
|
427
443
|
getFieldList<FieldShape>(name: FieldName<FieldShape>): Array<FieldMetadata<[
|
|
428
444
|
FieldShape
|
|
@@ -432,7 +448,7 @@ export type ValidateResult<ErrorShape, Value> = FormError<ErrorShape> | null | {
|
|
|
432
448
|
error: FormError<ErrorShape> | null;
|
|
433
449
|
value?: Value;
|
|
434
450
|
};
|
|
435
|
-
export type ValidateContext<
|
|
451
|
+
export type ValidateContext<SchemaValue> = {
|
|
436
452
|
/**
|
|
437
453
|
* The submitted values mapped by field name.
|
|
438
454
|
* Supports nested names like `user.email` and indexed names like `items[0].id`.
|
|
@@ -463,9 +479,9 @@ export type ValidateContext<Value> = {
|
|
|
463
479
|
* The validated value from schema validation. Only defined when a schema is provided
|
|
464
480
|
* and the validation succeeds. Undefined if no schema is provided or validation fails.
|
|
465
481
|
*/
|
|
466
|
-
schemaValue:
|
|
482
|
+
schemaValue: SchemaValue;
|
|
467
483
|
};
|
|
468
|
-
export type ValidateHandler<ErrorShape, Value> = (ctx: ValidateContext<
|
|
484
|
+
export type ValidateHandler<ErrorShape, Value, SchemaValue = undefined> = (ctx: ValidateContext<SchemaValue>) => ValidateResult<ErrorShape, Value> | Promise<ValidateResult<ErrorShape, Value>> | [
|
|
469
485
|
ValidateResult<ErrorShape, Value> | undefined,
|
|
470
486
|
Promise<ValidateResult<ErrorShape, Value>> | undefined
|
|
471
487
|
] | undefined;
|
|
@@ -486,14 +502,15 @@ export type ErrorContext<ErrorShape> = {
|
|
|
486
502
|
export type ErrorHandler<ErrorShape> = (ctx: ErrorContext<ErrorShape>) => void;
|
|
487
503
|
export type InputHandler = (event: FormInputEvent) => void;
|
|
488
504
|
export type BlurHandler = (event: FormFocusEvent) => void;
|
|
489
|
-
export type SubmitContext<ErrorShape extends BaseErrorShape = DefaultErrorShape, Value = undefined> = {
|
|
505
|
+
export type SubmitContext<FormShape extends Record<string, any> = Record<string, any>, ErrorShape extends BaseErrorShape = DefaultErrorShape, Value = undefined> = {
|
|
490
506
|
formData: FormData;
|
|
491
507
|
value: Value;
|
|
492
508
|
update: (options: {
|
|
493
|
-
error?: Partial<FormError<ErrorShape>> | null;
|
|
494
|
-
|
|
509
|
+
error?: Partial<FormError<ErrorShape>> | null | undefined;
|
|
510
|
+
value?: FormShape | null | undefined;
|
|
511
|
+
reset?: boolean | undefined;
|
|
495
512
|
}) => void;
|
|
496
513
|
};
|
|
497
|
-
export type SubmitHandler<ErrorShape extends BaseErrorShape = DefaultErrorShape, Value = undefined> = (event: React.FormEvent<HTMLFormElement>, ctx: SubmitContext<ErrorShape, Value>) => void | Promise<void>;
|
|
514
|
+
export type SubmitHandler<FormShape extends Record<string, any> = Record<string, any>, ErrorShape extends BaseErrorShape = DefaultErrorShape, Value = undefined> = (event: React.FormEvent<HTMLFormElement>, ctx: SubmitContext<FormShape, ErrorShape, Value>) => void | Promise<void>;
|
|
498
515
|
export {};
|
|
499
516
|
//# sourceMappingURL=types.d.ts.map
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "Conform view adapter for react",
|
|
4
4
|
"homepage": "https://conform.guide",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"version": "1.
|
|
6
|
+
"version": "1.14.1",
|
|
7
7
|
"main": "./dist/index.js",
|
|
8
8
|
"module": "./dist/index.mjs",
|
|
9
9
|
"types": "./dist/index.d.ts",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"url": "https://github.com/edmundhung/conform/issues"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@conform-to/dom": "1.
|
|
44
|
+
"@conform-to/dom": "1.14.1"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@babel/core": "^7.17.8",
|