@conform-to/react 1.19.4 → 1.20.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.
@@ -1,72 +1,116 @@
1
1
  import { objectSpread2 as _objectSpread2 } from '../_virtual/_rollupPluginBabelHelpers.mjs';
2
- import { parsePath, getRelativePath, isPlainObject, appendPath, getPathValue } from '@conform-to/dom/future';
3
- import { isOptional, isUndefined, isNullable, appendUniqueItem, merge, updatePathValue, isString, getPathArray, createPathIndexUpdater, compactMap, generateUniqueKey, isNumber, transformKeys } from './util.mjs';
4
- import { getDefaultListKey } from './state.mjs';
2
+ import { getRelativePath, isPlainObject, appendPath, getPathValue } from '@conform-to/dom/future';
3
+ import { isOptional, isUndefined, isNullable, updatePathValue, isString, getPathArray, updatePathIndex, isNumber } from './util.mjs';
4
+
5
+ function defineIntent(definition) {
6
+ var _definition$parse;
7
+ return _objectSpread2(_objectSpread2({}, definition), {}, {
8
+ parse: (_definition$parse = definition === null || definition === void 0 ? void 0 : definition.parse) !== null && _definition$parse !== void 0 ? _definition$parse : function () {
9
+ if (arguments.length > 1) {
10
+ throw new Error('Invalid intent arguments');
11
+ }
12
+ return arguments.length <= 0 ? undefined : arguments[0];
13
+ }
14
+ });
15
+ }
16
+ function mergeIntentHandlers(defaultHandlers, customHandlers) {
17
+ return _objectSpread2(_objectSpread2({}, defaultHandlers), customHandlers);
18
+ }
19
+ var undefinedArg = '$$__undefined__$$';
20
+ function deserializeIntentArgs(value) {
21
+ return JSON.parse("[".concat(value, "]"), (_, value) => value === undefinedArg ? undefined : value);
22
+ }
5
23
 
6
24
  /**
7
- * Serializes intent to string format: "type" or "type(payload)".
25
+ * Serializes a transport intent to string format.
8
26
  */
9
27
  function serializeIntent(intent) {
10
- if (!intent.payload) {
28
+ var args = intent.args.slice();
29
+ while (args.length > 0 && args[args.length - 1] === undefined) {
30
+ args.pop();
31
+ }
32
+ if (args.length === 0) {
11
33
  return intent.type;
12
34
  }
13
- return "".concat(intent.type, "(").concat(JSON.stringify(intent.payload), ")");
35
+ var serializedArgs = JSON.stringify(args, function (_, value) {
36
+ if (value === undefined && Array.isArray(this)) {
37
+ return undefinedArg;
38
+ }
39
+ return value;
40
+ });
41
+ return "".concat(intent.type, "(").concat(serializedArgs.slice(1, -1), ")");
14
42
  }
15
43
 
16
44
  /**
17
- * Parses serialized intent string back to intent object.
45
+ * Parses the serialized intent string into a transport intent.
18
46
  */
19
- function deserializeIntent(value) {
20
- var type = value;
21
- var payload;
22
- var serializedPayload;
23
- var openParenIndex = value.indexOf('(');
24
- if (openParenIndex > 0 && value[value.length - 1] === ')') {
25
- type = value.slice(0, openParenIndex);
26
- serializedPayload = value.slice(openParenIndex + 1, -1);
47
+ function deserializeIntent(serializedIntent) {
48
+ if (serializedIntent === '') {
49
+ return undefined;
27
50
  }
28
- if (serializedPayload) {
29
- try {
30
- payload = JSON.parse(serializedPayload);
31
- } catch (_unused) {
32
- // Ignore the error
51
+ var type = serializedIntent;
52
+ var args = [];
53
+ var openParenIndex = serializedIntent.indexOf('(');
54
+ if (openParenIndex > 0 && serializedIntent[serializedIntent.length - 1] === ')') {
55
+ type = serializedIntent.slice(0, openParenIndex);
56
+ var serializedArgs = serializedIntent.slice(openParenIndex + 1, -1);
57
+ if (serializedArgs !== '') {
58
+ try {
59
+ args = deserializeIntentArgs(serializedArgs);
60
+ } catch (_unused) {
61
+ return undefined;
62
+ }
33
63
  }
34
64
  }
35
65
  return {
36
66
  type,
37
- payload
67
+ args
38
68
  };
39
69
  }
40
-
41
- /**
42
- * Applies intent transformation to submission payload.
43
- * Returns modified payload or null for reset intent.
44
- */
70
+ function parseIntent(intentValue, options) {
71
+ if (intentValue === null) {
72
+ return {
73
+ type: 'submit',
74
+ payload: undefined
75
+ };
76
+ }
77
+ var transportIntent = deserializeIntent(intentValue);
78
+ if (!transportIntent) {
79
+ return undefined;
80
+ }
81
+ var handler = options.handlers[transportIntent.type];
82
+ if (!handler) {
83
+ return undefined;
84
+ }
85
+ try {
86
+ return {
87
+ type: transportIntent.type,
88
+ payload: handler.parse(...transportIntent.args)
89
+ };
90
+ } catch (_unused2) {
91
+ return undefined;
92
+ }
93
+ }
45
94
  function resolveIntent(submission, options) {
46
- var _options$handlers, _handler$validate, _handler$validate2;
47
- if (!submission.intent) {
95
+ var handlers = options.handlers;
96
+ var intent = options.intent;
97
+ var handler = intent ? handlers[intent.type] : null;
98
+ if (!intent || !(handler !== null && handler !== void 0 && handler.resolve)) {
48
99
  return submission.payload;
49
100
  }
50
- var intent = deserializeIntent(submission.intent);
51
- var handlers = (_options$handlers = options === null || options === void 0 ? void 0 : options.handlers) !== null && _options$handlers !== void 0 ? _options$handlers : intentHandlers;
52
- var handler = handlers[intent.type];
53
- if (handler !== null && handler !== void 0 && handler.resolve && ((_handler$validate = (_handler$validate2 = handler.validate) === null || _handler$validate2 === void 0 ? void 0 : _handler$validate2.call(handler, intent.payload)) !== null && _handler$validate !== void 0 ? _handler$validate : true)) {
54
- return handler.resolve(submission.payload, intent.payload);
55
- }
56
- return submission.payload;
101
+ return handler.resolve({
102
+ value: submission.payload,
103
+ payload: intent.payload
104
+ });
57
105
  }
58
-
59
- /**
60
- * Resolves an intent after validation by calling the handler's onResolve.
61
- * Mutates the result with updated value/error and returns whether the intent was cancelled.
62
- */
63
106
  function applyIntent(result, intent, options) {
64
107
  if (intent) {
65
- var _options$handlers2, _handler$validate3, _handler$validate4;
66
- var handlers = (_options$handlers2 = options === null || options === void 0 ? void 0 : options.handlers) !== null && _options$handlers2 !== void 0 ? _options$handlers2 : intentHandlers;
67
- var handler = handlers[intent.type];
68
- if (handler !== null && handler !== void 0 && handler.apply && ((_handler$validate3 = (_handler$validate4 = handler.validate) === null || _handler$validate4 === void 0 ? void 0 : _handler$validate4.call(handler, intent.payload)) !== null && _handler$validate3 !== void 0 ? _handler$validate3 : true)) {
69
- return handler.apply(result, intent.payload);
108
+ var handler = options.handlers[intent.type];
109
+ if (handler !== null && handler !== void 0 && handler.apply) {
110
+ return handler.apply({
111
+ result,
112
+ payload: intent.payload
113
+ });
70
114
  }
71
115
  }
72
116
  return result;
@@ -80,354 +124,299 @@ function removeItem(list, index) {
80
124
  function reorderItems(list, fromIndex, toIndex) {
81
125
  list.splice(toIndex, 0, ...list.splice(fromIndex, 1));
82
126
  }
83
-
84
- /**
85
- * Updates list keys by removing child keys and optionally transforming remaining keys.
86
- */
87
- function updateListKeys() {
88
- var keys = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
89
- var keyToBeRemoved = arguments.length > 1 ? arguments[1] : undefined;
90
- var updateKey = arguments.length > 2 ? arguments[2] : undefined;
91
- var basePath = parsePath(keyToBeRemoved);
92
- return transformKeys(keys, field => {
93
- var _updateKey;
94
- return getRelativePath(field, basePath) !== null ? null : (_updateKey = updateKey === null || updateKey === void 0 ? void 0 : updateKey(field)) !== null && _updateKey !== void 0 ? _updateKey : field;
95
- });
96
- }
97
-
98
- /**
99
- * Built-in action handlers for form intents:
100
- * - reset: clears form data
101
- * - validate: marks fields as touched for validation display
102
- * - update: updates specific field values
103
- * - insert/remove/reorder: manages array field operations
104
- */
105
- var intentHandlers = {
106
- reset: {
107
- validate(options) {
108
- return isOptional(options, isPlainObject) && (isUndefined(options === null || options === void 0 ? void 0 : options.defaultValue) || isNullable(options === null || options === void 0 ? void 0 : options.defaultValue, isPlainObject));
109
- },
110
- resolve(_, options) {
111
- if ((options === null || options === void 0 ? void 0 : options.defaultValue) === null) {
112
- return {};
113
- }
114
- return options === null || options === void 0 ? void 0 : options.defaultValue;
115
- },
116
- apply(result) {
117
- return _objectSpread2(_objectSpread2({}, result), {}, {
118
- reset: true
119
- });
127
+ var submit = defineIntent({
128
+ touch() {
129
+ return true;
130
+ }
131
+ });
132
+ var reset = defineIntent({
133
+ parse(options) {
134
+ if (!isOptional(options, isPlainObject) || !isUndefined(options === null || options === void 0 ? void 0 : options.defaultValue) && !isNullable(options === null || options === void 0 ? void 0 : options.defaultValue, isPlainObject)) {
135
+ throw new Error('Invalid reset intent arguments');
120
136
  }
137
+ return options;
121
138
  },
122
- validate: {
123
- validate(name) {
124
- return isOptional(name, isString);
125
- },
126
- update(state, _ref) {
127
- var _intent$payload;
128
- var {
129
- submission,
130
- intent,
131
- error
132
- } = _ref;
133
- var name = (_intent$payload = intent.payload) !== null && _intent$payload !== void 0 ? _intent$payload : '';
134
- var basePath = parsePath(name);
135
- var allFields = error ?
136
- // Consider fields / fieldset with errors as touched too
137
- submission.fields.concat(Object.keys(error.fieldErrors)) : submission.fields;
138
- var touchedFields = appendUniqueItem(state.touchedFields, name);
139
- for (var field of allFields) {
140
- // Add all child fields to the touched fields too
141
- if (getRelativePath(field, basePath) !== null) {
142
- touchedFields = appendUniqueItem(touchedFields, field);
143
- }
144
- }
145
- return merge(state, {
146
- touchedFields
147
- });
139
+ resolve(_ref) {
140
+ var {
141
+ payload
142
+ } = _ref;
143
+ if ((payload === null || payload === void 0 ? void 0 : payload.defaultValue) === null) {
144
+ return {};
148
145
  }
146
+ return payload === null || payload === void 0 ? void 0 : payload.defaultValue;
149
147
  },
150
- update: {
151
- validate(options) {
152
- return isPlainObject(options) && isOptional(options.name, isString) && isOptional(options.index, isNumber) && !isUndefined(options.value);
153
- },
154
- resolve(value, options) {
155
- var _options$value;
156
- var name = appendPath(options.name, options.index);
157
- return updatePathValue(value, name, (_options$value = options.value) !== null && _options$value !== void 0 ? _options$value : name === '' ? {} : null);
158
- },
159
- update(state, _ref2) {
160
- var {
161
- type,
162
- submission,
163
- intent
164
- } = _ref2;
165
- if (type === 'server') {
166
- return state;
167
- }
168
- var listKeys = state.listKeys;
169
-
170
- // Update the keys only for client updates to avoid double updates if there is no client validation
171
- if (type === 'client') {
172
- // TODO: Do we really need to update the keys here?
173
- var name = appendPath(intent.payload.name, intent.payload.index);
174
- // Remove all child keys
175
- listKeys = name === '' ? {} : updateListKeys(state.listKeys, name);
176
- }
177
- var basePath = parsePath(intent.payload.name);
178
- var touchedFields = state.touchedFields;
179
- for (var field of submission.fields) {
180
- if (basePath.length === 0 || getRelativePath(field, basePath) !== null) {
181
- touchedFields = appendUniqueItem(touchedFields, field);
182
- }
183
- }
184
- return _objectSpread2(_objectSpread2({}, state), {}, {
185
- listKeys,
186
- touchedFields
187
- });
148
+ apply(_ref2) {
149
+ var {
150
+ result
151
+ } = _ref2;
152
+ return _objectSpread2(_objectSpread2({}, result), {}, {
153
+ reset: true
154
+ });
155
+ }
156
+ });
157
+ var validate = defineIntent({
158
+ parse(name) {
159
+ if (!isOptional(name, isString)) {
160
+ throw new Error('Invalid validate intent arguments');
188
161
  }
162
+ return name;
189
163
  },
190
- insert: {
191
- validate(options) {
192
- return isPlainObject(options) && isString(options.name) && isOptional(options.index, isNumber) && isOptional(options.from, isString) && isOptional(options.onInvalid, mode => mode === 'revert');
193
- },
194
- resolve(value, options) {
195
- var _options$index;
196
- var result = value;
197
- var itemValue = options.defaultValue;
198
- if (options.from !== undefined) {
199
- itemValue = getPathValue(result, options.from);
200
- result = updatePathValue(result, options.from, '');
201
- }
202
- var list = Array.from(getPathArray(result, options.name));
203
- insertItem(list, itemValue, (_options$index = options.index) !== null && _options$index !== void 0 ? _options$index : list.length);
204
- return updatePathValue(result, options.name, list);
205
- },
206
- apply(result, options) {
207
- var _result$error;
208
- // Warn if validation result is not yet available
209
- if (typeof result.error === 'undefined' && (options.onInvalid || options.from)) {
210
- // eslint-disable-next-line no-console
211
- console.warn('intent.insert() with `onInvalid` or `from` requires the validation result to be available synchronously. ' + 'These options are ignored because the error is not yet known.');
212
- return result;
213
- }
214
- var listError = (_result$error = result.error) === null || _result$error === void 0 ? void 0 : _result$error.fieldErrors[options.name];
215
- if (options.onInvalid === 'revert' && listError != null) {
164
+ touch(_ref3) {
165
+ var {
166
+ name,
167
+ payload
168
+ } = _ref3;
169
+ return getRelativePath(name, payload !== null && payload !== void 0 ? payload : '') !== null;
170
+ }
171
+ });
172
+ var update = defineIntent({
173
+ parse(options) {
174
+ if (!isPlainObject(options) || !isOptional(options.name, isString) || !isOptional(options.index, isNumber) || isUndefined(options.value)) {
175
+ throw new Error('Invalid update intent arguments');
176
+ }
177
+ return options;
178
+ },
179
+ resolve(_ref4) {
180
+ var _payload$value;
181
+ var {
182
+ value,
183
+ payload
184
+ } = _ref4;
185
+ var fieldName = appendPath(payload.name, payload.index);
186
+ var nextValue = (_payload$value = payload.value) !== null && _payload$value !== void 0 ? _payload$value : fieldName === '' ? {} : null;
187
+ return updatePathValue(value, fieldName, nextValue);
188
+ },
189
+ touch(_ref5) {
190
+ var {
191
+ name,
192
+ payload
193
+ } = _ref5;
194
+ var fieldName = appendPath(payload.name, payload.index);
195
+ return getRelativePath(name, fieldName) !== null;
196
+ }
197
+ });
198
+ var insert = defineIntent({
199
+ parse(options) {
200
+ if (!isPlainObject(options) || !isString(options.name) || !isOptional(options.index, isNumber) || !isOptional(options.from, isString) || !isOptional(options.onInvalid, mode => mode === 'revert')) {
201
+ throw new Error('Invalid insert intent arguments');
202
+ }
203
+ return options;
204
+ },
205
+ resolve(_ref6) {
206
+ var _payload$index;
207
+ var {
208
+ value,
209
+ payload
210
+ } = _ref6;
211
+ var result = value;
212
+ var itemValue = payload.defaultValue;
213
+ if (payload.from !== undefined) {
214
+ itemValue = getPathValue(result, payload.from);
215
+ result = updatePathValue(result, payload.from, '');
216
+ }
217
+ var list = Array.from(getPathArray(result, payload.name));
218
+ insertItem(list, itemValue, (_payload$index = payload.index) !== null && _payload$index !== void 0 ? _payload$index : list.length);
219
+ return updatePathValue(result, payload.name, list);
220
+ },
221
+ apply(_ref7) {
222
+ var _result$error;
223
+ var {
224
+ result,
225
+ payload
226
+ } = _ref7;
227
+ // Warn if validation result is not yet available
228
+ if (typeof result.error === 'undefined' && (payload.onInvalid || payload.from)) {
229
+ // eslint-disable-next-line no-console
230
+ console.warn('intent.insert() with `onInvalid` or `from` requires the validation result to be available synchronously. ' + 'These options are ignored because the error is not yet known.');
231
+ return result;
232
+ }
233
+ var listError = (_result$error = result.error) === null || _result$error === void 0 ? void 0 : _result$error.fieldErrors[payload.name];
234
+ if (payload.onInvalid === 'revert' && listError != null) {
235
+ return _objectSpread2(_objectSpread2({}, result), {}, {
236
+ targetValue: undefined
237
+ });
238
+ }
239
+ if (payload.from !== undefined) {
240
+ var _payload$index2, _result$error2, _result$error3;
241
+ var index = (_payload$index2 = payload.index) !== null && _payload$index2 !== void 0 ? _payload$index2 : getPathArray(result.submission.payload, payload.name).length;
242
+ var insertedItemPath = appendPath(payload.name, index);
243
+ var insertedItemError = (_result$error2 = result.error) === null || _result$error2 === void 0 ? void 0 : _result$error2.fieldErrors[insertedItemPath];
244
+ var fromFieldError = (_result$error3 = result.error) === null || _result$error3 === void 0 ? void 0 : _result$error3.fieldErrors[payload.from];
245
+ if (fromFieldError != null) {
246
+ var _result$error$formErr, _result$error4, _result$error5;
216
247
  return _objectSpread2(_objectSpread2({}, result), {}, {
217
- targetValue: undefined
248
+ targetValue: undefined,
249
+ error: {
250
+ formErrors: (_result$error$formErr = (_result$error4 = result.error) === null || _result$error4 === void 0 ? void 0 : _result$error4.formErrors) !== null && _result$error$formErr !== void 0 ? _result$error$formErr : null,
251
+ fieldErrors: _objectSpread2(_objectSpread2({}, (_result$error5 = result.error) === null || _result$error5 === void 0 ? void 0 : _result$error5.fieldErrors), {}, {
252
+ [insertedItemPath]: null
253
+ })
254
+ }
218
255
  });
219
256
  }
220
- if (options.from !== undefined) {
221
- var _options$index2, _result$error2, _result$error3;
222
- var index = (_options$index2 = options.index) !== null && _options$index2 !== void 0 ? _options$index2 : getPathArray(result.submission.payload, options.name).length;
223
- var insertedItemPath = appendPath(options.name, index);
224
- var insertedItemError = (_result$error2 = result.error) === null || _result$error2 === void 0 ? void 0 : _result$error2.fieldErrors[insertedItemPath];
225
- var fromFieldError = (_result$error3 = result.error) === null || _result$error3 === void 0 ? void 0 : _result$error3.fieldErrors[options.from];
226
- if (fromFieldError != null) {
227
- var _result$error$formErr, _result$error4, _result$error5;
228
- return _objectSpread2(_objectSpread2({}, result), {}, {
229
- targetValue: undefined,
230
- error: {
231
- formErrors: (_result$error$formErr = (_result$error4 = result.error) === null || _result$error4 === void 0 ? void 0 : _result$error4.formErrors) !== null && _result$error$formErr !== void 0 ? _result$error$formErr : null,
232
- fieldErrors: _objectSpread2(_objectSpread2({}, (_result$error5 = result.error) === null || _result$error5 === void 0 ? void 0 : _result$error5.fieldErrors), {}, {
233
- [insertedItemPath]: null
234
- })
235
- }
236
- });
237
- }
238
- if (insertedItemError != null) {
239
- var _result$error$formErr2, _result$error6, _result$error7;
240
- return _objectSpread2(_objectSpread2({}, result), {}, {
241
- targetValue: undefined,
242
- error: {
243
- formErrors: (_result$error$formErr2 = (_result$error6 = result.error) === null || _result$error6 === void 0 ? void 0 : _result$error6.formErrors) !== null && _result$error$formErr2 !== void 0 ? _result$error$formErr2 : null,
244
- fieldErrors: _objectSpread2(_objectSpread2({}, (_result$error7 = result.error) === null || _result$error7 === void 0 ? void 0 : _result$error7.fieldErrors), {}, {
245
- [options.from]: insertedItemError,
246
- [insertedItemPath]: null
247
- })
248
- }
249
- });
250
- }
251
- }
252
- return result;
253
- },
254
- update(state, _ref3) {
255
- var _intent$payload$index;
256
- var {
257
- type,
258
- submission,
259
- intent,
260
- ctx
261
- } = _ref3;
262
- if (type === 'server') {
263
- return state;
264
- }
265
- var from = intent.payload.from;
266
- var index = (_intent$payload$index = intent.payload.index) !== null && _intent$payload$index !== void 0 ? _intent$payload$index : getPathArray(submission.payload, intent.payload.name).length;
267
- var updateListIndex = createPathIndexUpdater(intent.payload.name, currentIndex => index <= currentIndex ? currentIndex + 1 : currentIndex);
268
- var touchedFields = state.touchedFields;
269
- var listKeys = state.listKeys;
270
- if (!ctx.cancelled) {
271
- touchedFields = compactMap(state.touchedFields, updateListIndex);
272
-
273
- // Update the keys only for client updates to avoid double updates if there is no client validation
274
- if (type === 'client') {
275
- var _state$listKeys$inten;
276
- var selectedListKeys = Array.from((_state$listKeys$inten = state.listKeys[intent.payload.name]) !== null && _state$listKeys$inten !== void 0 ? _state$listKeys$inten : getDefaultListKey(state.resetKey, submission.payload, intent.payload.name));
277
- insertItem(selectedListKeys, generateUniqueKey(), index);
278
- listKeys = _objectSpread2(_objectSpread2({}, updateListKeys(state.listKeys, appendPath(intent.payload.name, index), updateListIndex)), {}, {
279
- // Update existing list keys
280
- [intent.payload.name]: selectedListKeys
281
- });
282
- }
283
- }
284
- touchedFields = appendUniqueItem(touchedFields, intent.payload.name);
285
- if (from !== undefined) {
286
- touchedFields = appendUniqueItem(touchedFields, from);
257
+ if (insertedItemError != null) {
258
+ var _result$error$formErr2, _result$error6, _result$error7;
259
+ return _objectSpread2(_objectSpread2({}, result), {}, {
260
+ targetValue: undefined,
261
+ error: {
262
+ formErrors: (_result$error$formErr2 = (_result$error6 = result.error) === null || _result$error6 === void 0 ? void 0 : _result$error6.formErrors) !== null && _result$error$formErr2 !== void 0 ? _result$error$formErr2 : null,
263
+ fieldErrors: _objectSpread2(_objectSpread2({}, (_result$error7 = result.error) === null || _result$error7 === void 0 ? void 0 : _result$error7.fieldErrors), {}, {
264
+ [payload.from]: insertedItemError,
265
+ [insertedItemPath]: null
266
+ })
267
+ }
268
+ });
287
269
  }
288
- return _objectSpread2(_objectSpread2({}, state), {}, {
289
- listKeys,
290
- touchedFields
291
- });
292
270
  }
271
+ return result;
293
272
  },
294
- remove: {
295
- validate(options) {
296
- return isPlainObject(options) && isString(options.name) && isNumber(options.index) && isOptional(options.onInvalid, v => v === 'revert' || v === 'insert');
297
- },
298
- resolve(value, options) {
299
- var list = Array.from(getPathArray(value, options.name));
300
- removeItem(list, options.index);
301
- return updatePathValue(value, options.name, list);
302
- },
303
- apply(result, options) {
304
- var _result$error8;
305
- // Warn if validation result is not yet available
306
- if (typeof result.error === 'undefined' && options.onInvalid) {
307
- if (process.env.NODE_ENV !== 'production') {
308
- // eslint-disable-next-line no-console
309
- console.warn('intent.remove() with `onInvalid` requires the validation result to be available synchronously. ' + 'This option is ignored because the error is not yet known.');
310
- }
311
- return result;
312
- }
313
- if (result.targetValue && (_result$error8 = result.error) !== null && _result$error8 !== void 0 && _result$error8.fieldErrors[options.name]) {
314
- switch (options.onInvalid) {
315
- case 'revert':
316
- return _objectSpread2(_objectSpread2({}, result), {}, {
317
- targetValue: undefined
318
- });
319
- case 'insert':
320
- {
321
- var list = Array.from(getPathArray(result.targetValue, options.name));
322
- insertItem(list, options.defaultValue, list.length);
323
- return _objectSpread2(_objectSpread2({}, result), {}, {
324
- targetValue: updatePathValue(result.targetValue, options.name, list)
325
- });
326
- }
327
- }
328
- }
273
+ touch(_ref8) {
274
+ var {
275
+ name,
276
+ payload
277
+ } = _ref8;
278
+ return name === payload.name || name === payload.from;
279
+ },
280
+ move(_ref9) {
281
+ var {
282
+ name,
283
+ payload,
284
+ status
285
+ } = _ref9;
286
+ if (status !== 'applied' || typeof payload.index === 'undefined') {
287
+ return name;
288
+ }
289
+ return updatePathIndex(name, payload.name, currentIndex => payload.index !== undefined && payload.index <= currentIndex ? currentIndex + 1 : currentIndex);
290
+ }
291
+ });
292
+ var remove = defineIntent({
293
+ parse(options) {
294
+ if (!isPlainObject(options) || !isString(options.name) || !isNumber(options.index) || !isOptional(options.onInvalid, v => v === 'revert' || v === 'insert')) {
295
+ throw new Error('Invalid remove intent arguments');
296
+ }
297
+ return options;
298
+ },
299
+ resolve(_ref10) {
300
+ var {
301
+ value,
302
+ payload
303
+ } = _ref10;
304
+ var list = Array.from(getPathArray(value, payload.name));
305
+ removeItem(list, payload.index);
306
+ return updatePathValue(value, payload.name, list);
307
+ },
308
+ apply(_ref11) {
309
+ var _result$error8;
310
+ var {
311
+ result,
312
+ payload
313
+ } = _ref11;
314
+ // Warn if validation result is not yet available
315
+ if (typeof result.error === 'undefined' && payload.onInvalid) {
316
+ // eslint-disable-next-line no-console
317
+ console.warn('intent.remove() with `onInvalid` requires the validation result to be available synchronously. ' + 'This option is ignored because the error is not yet known.');
329
318
  return result;
330
- },
331
- update(state, _ref4) {
332
- var {
333
- type,
334
- submission,
335
- intent,
336
- ctx
337
- } = _ref4;
338
- if (type === 'server') {
339
- return state;
340
- }
341
- var currentValue = submission.payload;
342
- var updateListIndex = createPathIndexUpdater(intent.payload.name, currentIndex => {
343
- if (intent.payload.index === currentIndex) {
344
- return null;
345
- }
346
- return intent.payload.index < currentIndex ? currentIndex - 1 : currentIndex;
347
- });
348
- var touchedFields = state.touchedFields;
349
- var listKeys = state.listKeys;
350
-
351
- // If onInvalid is 'insert', we still remove the item and then insert a new item at the end
352
- if (!ctx.cancelled || intent.payload.onInvalid === 'insert') {
353
- touchedFields = compactMap(touchedFields, updateListIndex);
354
-
355
- // Update the keys only for client updates to avoid double updates if there is no client validation
356
- if (type === 'client') {
357
- var _state$listKeys$inten2;
358
- var selectedListKeys = Array.from((_state$listKeys$inten2 = state.listKeys[intent.payload.name]) !== null && _state$listKeys$inten2 !== void 0 ? _state$listKeys$inten2 : getDefaultListKey(state.resetKey, currentValue, intent.payload.name));
359
- removeItem(selectedListKeys, intent.payload.index);
360
- listKeys = _objectSpread2(_objectSpread2({}, updateListKeys(state.listKeys, appendPath(intent.payload.name, intent.payload.index), updateListIndex)), {}, {
361
- // Update existing list keys
362
- [intent.payload.name]: selectedListKeys
319
+ }
320
+ if (result.targetValue && (_result$error8 = result.error) !== null && _result$error8 !== void 0 && _result$error8.fieldErrors[payload.name]) {
321
+ switch (payload.onInvalid) {
322
+ case 'revert':
323
+ return _objectSpread2(_objectSpread2({}, result), {}, {
324
+ targetValue: undefined
363
325
  });
364
- if (ctx.cancelled) {
365
- var index = selectedListKeys.length;
366
- insertItem(selectedListKeys, generateUniqueKey(), index);
367
- listKeys = _objectSpread2(_objectSpread2({}, updateListKeys(state.listKeys, appendPath(intent.payload.name, index), updateListIndex)), {}, {
368
- // Update existing list keys
369
- [intent.payload.name]: selectedListKeys
326
+ case 'insert':
327
+ {
328
+ var list = Array.from(getPathArray(result.targetValue, payload.name));
329
+ insertItem(list, payload.defaultValue, list.length);
330
+ return _objectSpread2(_objectSpread2({}, result), {}, {
331
+ targetValue: updatePathValue(result.targetValue, payload.name, list)
370
332
  });
371
333
  }
372
- }
373
334
  }
374
- touchedFields = appendUniqueItem(touchedFields, intent.payload.name);
375
- return _objectSpread2(_objectSpread2({}, state), {}, {
376
- listKeys: listKeys,
377
- touchedFields
378
- });
379
335
  }
336
+ return result;
380
337
  },
381
- reorder: {
382
- validate(options) {
383
- return isPlainObject(options) && isString(options.name) && isNumber(options.from) && isNumber(options.to);
384
- },
385
- resolve(value, options) {
386
- var list = Array.from(getPathArray(value, options.name));
387
- reorderItems(list, options.from, options.to);
388
- return updatePathValue(value, options.name, list);
389
- },
390
- update(state, _ref5) {
391
- var {
392
- type,
393
- submission,
394
- intent
395
- } = _ref5;
396
- if (type === 'server') {
397
- return state;
398
- }
399
- var currentValue = submission.payload;
400
- var updateListIndex = createPathIndexUpdater(intent.payload.name, currentIndex => {
401
- if (intent.payload.from === intent.payload.to) {
402
- return currentIndex;
403
- }
404
- if (currentIndex === intent.payload.from) {
405
- return intent.payload.to;
406
- }
407
- if (intent.payload.from < intent.payload.to) {
408
- return currentIndex > intent.payload.from && currentIndex <= intent.payload.to ? currentIndex - 1 : currentIndex;
409
- }
410
- return currentIndex >= intent.payload.to && currentIndex < intent.payload.from ? currentIndex + 1 : currentIndex;
411
- });
412
- var touchedFields = appendUniqueItem(compactMap(state.touchedFields, updateListIndex), intent.payload.name);
413
- var keys = state.listKeys;
414
-
415
- // Update the keys only for client updates to avoid double updates if there is no client validation
416
- if (type === 'client') {
417
- var _state$listKeys$inten3;
418
- var listKeys = Array.from((_state$listKeys$inten3 = state.listKeys[intent.payload.name]) !== null && _state$listKeys$inten3 !== void 0 ? _state$listKeys$inten3 : getDefaultListKey(state.resetKey, currentValue, intent.payload.name));
419
- reorderItems(listKeys, intent.payload.from, intent.payload.to);
420
- keys = _objectSpread2(_objectSpread2({}, updateListKeys(state.listKeys, appendPath(intent.payload.name, intent.payload.from), updateListIndex)), {}, {
421
- // Update existing list keys
422
- [intent.payload.name]: listKeys
423
- });
338
+ touch(_ref12) {
339
+ var {
340
+ name,
341
+ payload
342
+ } = _ref12;
343
+ return name === payload.name;
344
+ },
345
+ move(_ref13) {
346
+ var {
347
+ name,
348
+ payload,
349
+ status
350
+ } = _ref13;
351
+ if (status === 'reverted') {
352
+ return name;
353
+ }
354
+ return updatePathIndex(name, payload.name, currentIndex => {
355
+ if (payload.index === currentIndex) {
356
+ return null;
424
357
  }
425
- return _objectSpread2(_objectSpread2({}, state), {}, {
426
- listKeys: keys,
427
- touchedFields
428
- });
358
+ return payload.index < currentIndex ? currentIndex - 1 : currentIndex;
359
+ });
360
+ }
361
+ });
362
+ var reorder = defineIntent({
363
+ parse(options) {
364
+ if (!isPlainObject(options) || !isString(options.name) || !isNumber(options.from) || !isNumber(options.to)) {
365
+ throw new Error('Invalid reorder intent arguments');
429
366
  }
367
+ return options;
368
+ },
369
+ resolve(_ref14) {
370
+ var {
371
+ value,
372
+ payload
373
+ } = _ref14;
374
+ var list = Array.from(getPathArray(value, payload.name));
375
+ reorderItems(list, payload.from, payload.to);
376
+ return updatePathValue(value, payload.name, list);
377
+ },
378
+ touch(_ref15) {
379
+ var {
380
+ name,
381
+ payload
382
+ } = _ref15;
383
+ return name === payload.name;
384
+ },
385
+ move(_ref16) {
386
+ var {
387
+ name,
388
+ payload
389
+ } = _ref16;
390
+ return updatePathIndex(name, payload.name, currentIndex => {
391
+ if (payload.from === payload.to) {
392
+ return currentIndex;
393
+ }
394
+ if (currentIndex === payload.from) {
395
+ return payload.to;
396
+ }
397
+ if (payload.from < payload.to) {
398
+ return currentIndex > payload.from && currentIndex <= payload.to ? currentIndex - 1 : currentIndex;
399
+ }
400
+ return currentIndex >= payload.to && currentIndex < payload.from ? currentIndex + 1 : currentIndex;
401
+ });
430
402
  }
403
+ });
404
+
405
+ /**
406
+ * Default Intent handlers
407
+ * - reset: clears form data
408
+ * - validate: marks fields as touched for validation display
409
+ * - update: updates specific field values
410
+ * - insert/remove/reorder: manages array field operations
411
+ */
412
+ var defaultIntentHandlers = {
413
+ submit,
414
+ reset,
415
+ validate,
416
+ update,
417
+ insert,
418
+ remove,
419
+ reorder
431
420
  };
432
421
 
433
- export { applyIntent, deserializeIntent, insertItem, intentHandlers, removeItem, reorderItems, resolveIntent, serializeIntent, updateListKeys };
422
+ export { applyIntent, defaultIntentHandlers, defineIntent, deserializeIntent, insert, insertItem, mergeIntentHandlers, parseIntent, remove, removeItem, reorder, reorderItems, reset, resolveIntent, serializeIntent, submit, update, validate };