@conform-to/react 0.7.0-pre.1 → 0.7.0-pre.2
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 +3 -3
- package/hooks.d.ts +2 -5
- package/hooks.js +53 -47
- package/hooks.mjs +54 -48
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -507,7 +507,7 @@ export default function SignupForm() {
|
|
|
507
507
|
|
|
508
508
|
### list
|
|
509
509
|
|
|
510
|
-
It provides serveral helpers to configure an intent button for [modifying a list](/docs/
|
|
510
|
+
It provides serveral helpers to configure an intent button for [modifying a list](/docs/intent-button.md#modifying-a-list).
|
|
511
511
|
|
|
512
512
|
```tsx
|
|
513
513
|
import { list } from '@conform-to/react';
|
|
@@ -540,7 +540,7 @@ function Example() {
|
|
|
540
540
|
|
|
541
541
|
### validate
|
|
542
542
|
|
|
543
|
-
It returns the properties required to configure an intent button for [validation](/docs/
|
|
543
|
+
It returns the properties required to configure an intent button for [validation](/docs/intent-button.md#validation).
|
|
544
544
|
|
|
545
545
|
```tsx
|
|
546
546
|
import { validate } from '@conform-to/react';
|
|
@@ -562,7 +562,7 @@ function Example() {
|
|
|
562
562
|
|
|
563
563
|
### requestIntent
|
|
564
564
|
|
|
565
|
-
It lets you [trigger an intent](/docs/
|
|
565
|
+
It lets you [trigger an intent](/docs/intent-button.md#triggering-an-intent) without requiring users to click on a button. It supports both [list](#list) and [validate](#validate) intent.
|
|
566
566
|
|
|
567
567
|
```tsx
|
|
568
568
|
import {
|
package/hooks.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type FieldConstraint, type FieldElement, type FieldsetConstraint, type Submission, type KeysOf, type ResolveType, getFormEncType, getFormMethod } from '@conform-to/dom';
|
|
1
|
+
import { type FieldConstraint, type FieldElement, type FieldsetConstraint, type Submission, type KeysOf, type ResolveType, getFormEncType, getFormMethod, parseIntent } from '@conform-to/dom';
|
|
2
2
|
import { type FormEvent, type RefObject } from 'react';
|
|
3
3
|
export type Primitive = null | undefined | string | number | boolean | Date;
|
|
4
4
|
export interface FieldConfig<Schema> extends FieldConstraint<Schema> {
|
|
@@ -211,8 +211,5 @@ export declare function validateConstraint(options: {
|
|
|
211
211
|
}) => string[];
|
|
212
212
|
}): Submission;
|
|
213
213
|
export declare function reportSubmission(form: HTMLFormElement, submission: Submission): void;
|
|
214
|
-
|
|
215
|
-
* Check if the current focus is on a intent button.
|
|
216
|
-
*/
|
|
217
|
-
export declare function isFocusedOnIntentButton(form: HTMLFormElement, intent: string): boolean;
|
|
214
|
+
export declare function getScope(intent: ReturnType<typeof parseIntent>): string | null;
|
|
218
215
|
export {};
|
package/hooks.js
CHANGED
|
@@ -144,7 +144,8 @@ function useForm() {
|
|
|
144
144
|
if (!submission) {
|
|
145
145
|
return {};
|
|
146
146
|
}
|
|
147
|
-
var
|
|
147
|
+
var intent = dom.parseIntent(submission.intent);
|
|
148
|
+
var scope = getScope(intent);
|
|
148
149
|
return scope === null ? submission.error : {
|
|
149
150
|
[scope]: submission.error[scope]
|
|
150
151
|
};
|
|
@@ -230,15 +231,30 @@ function useForm() {
|
|
|
230
231
|
form,
|
|
231
232
|
formData
|
|
232
233
|
})) !== null && _config$onValidate !== void 0 ? _config$onValidate : dom.parse(formData);
|
|
233
|
-
var
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
},
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
234
|
+
var {
|
|
235
|
+
errors: _errors,
|
|
236
|
+
shouldServerValidate
|
|
237
|
+
} = Object.entries(submission.error).reduce((result, _ref2) => {
|
|
238
|
+
var [, error] = _ref2;
|
|
239
|
+
for (var message of normalizeError(error)) {
|
|
240
|
+
if (message === VALIDATION_UNDEFINED) {
|
|
241
|
+
result.shouldServerValidate = true;
|
|
242
|
+
} else if (message !== VALIDATION_SKIPPED) {
|
|
243
|
+
result.errors.push(message);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
return result;
|
|
247
|
+
}, {
|
|
248
|
+
errors: [],
|
|
249
|
+
shouldServerValidate: false
|
|
250
|
+
});
|
|
251
|
+
if (
|
|
252
|
+
// has client validation
|
|
253
|
+
typeof config.onValidate !== 'undefined' &&
|
|
254
|
+
// not necessary to validate on the server
|
|
255
|
+
!shouldServerValidate && (
|
|
256
|
+
// client validation failed or non submit intent
|
|
257
|
+
!config.noValidate && !(submitter !== null && submitter !== void 0 && submitter.formNoValidate) && _errors.length > 0 || dom.parseIntent(submission.intent) !== null)) {
|
|
242
258
|
report(form, submission);
|
|
243
259
|
event.preventDefault();
|
|
244
260
|
} else {
|
|
@@ -341,27 +357,23 @@ function useFieldList(ref, config) {
|
|
|
341
357
|
if (!form || event.target !== form) {
|
|
342
358
|
return;
|
|
343
359
|
}
|
|
344
|
-
var
|
|
345
|
-
if ((
|
|
346
|
-
// Ensure the scope of the listener are limited to specific field name
|
|
360
|
+
var intent = dom.parseIntent(event.detail);
|
|
361
|
+
if ((intent === null || intent === void 0 ? void 0 : intent.type) !== 'list' || (intent === null || intent === void 0 ? void 0 : intent.payload.name) !== configRef.current.name) {
|
|
347
362
|
return;
|
|
348
363
|
}
|
|
349
364
|
setEntries(entries => {
|
|
350
|
-
|
|
365
|
+
var list = [...entries];
|
|
366
|
+
switch (intent.payload.operation) {
|
|
351
367
|
case 'append':
|
|
352
368
|
case 'prepend':
|
|
353
369
|
case 'replace':
|
|
354
|
-
return dom.updateList(
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
command.payload.defaultValue]
|
|
359
|
-
})
|
|
370
|
+
return dom.updateList(list, _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, intent.payload), {}, {
|
|
371
|
+
defaultValue: [
|
|
372
|
+
// Generate a random key to avoid conflicts
|
|
373
|
+
crypto.getRandomValues(new Uint32Array(1))[0].toString(36), intent.payload.defaultValue]
|
|
360
374
|
}));
|
|
361
375
|
default:
|
|
362
|
-
|
|
363
|
-
return dom.updateList([...(entries !== null && entries !== void 0 ? entries : [])], command);
|
|
364
|
-
}
|
|
376
|
+
return dom.updateList(list, intent.payload);
|
|
365
377
|
}
|
|
366
378
|
});
|
|
367
379
|
setError(error => {
|
|
@@ -371,21 +383,17 @@ function useFieldList(ref, config) {
|
|
|
371
383
|
errorList[key] = messages;
|
|
372
384
|
}
|
|
373
385
|
}
|
|
374
|
-
switch (
|
|
386
|
+
switch (intent.payload.operation) {
|
|
375
387
|
case 'append':
|
|
376
388
|
case 'prepend':
|
|
377
389
|
case 'replace':
|
|
378
|
-
errorList = dom.updateList(errorList, _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({},
|
|
379
|
-
|
|
380
|
-
defaultValue: undefined
|
|
381
|
-
})
|
|
390
|
+
errorList = dom.updateList(errorList, _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, intent.payload), {}, {
|
|
391
|
+
defaultValue: undefined
|
|
382
392
|
}));
|
|
383
393
|
break;
|
|
384
394
|
default:
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
break;
|
|
388
|
-
}
|
|
395
|
+
errorList = dom.updateList(errorList, intent.payload);
|
|
396
|
+
break;
|
|
389
397
|
}
|
|
390
398
|
return Object.assign({}, errorList);
|
|
391
399
|
});
|
|
@@ -722,7 +730,8 @@ function reportSubmission(form, submission) {
|
|
|
722
730
|
form.appendChild(button);
|
|
723
731
|
}
|
|
724
732
|
}
|
|
725
|
-
var
|
|
733
|
+
var intent = dom.parseIntent(submission.intent);
|
|
734
|
+
var scope = getScope(intent);
|
|
726
735
|
for (var element of dom.getFormControls(form)) {
|
|
727
736
|
var _elementName = element.name !== FORM_ERROR_ELEMENT_NAME ? element.name : '';
|
|
728
737
|
var messages = normalizeError(submission.error[_elementName]);
|
|
@@ -737,27 +746,24 @@ function reportSubmission(form, submission) {
|
|
|
737
746
|
element.dispatchEvent(invalidEvent);
|
|
738
747
|
}
|
|
739
748
|
}
|
|
740
|
-
if (
|
|
741
|
-
|
|
742
|
-
dom.focusFormControl(form, scope);
|
|
743
|
-
} else {
|
|
744
|
-
dom.focusFirstInvalidControl(form);
|
|
745
|
-
}
|
|
749
|
+
if (!intent) {
|
|
750
|
+
dom.focusFirstInvalidControl(form);
|
|
746
751
|
}
|
|
747
752
|
}
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
753
|
+
function getScope(intent) {
|
|
754
|
+
switch (intent === null || intent === void 0 ? void 0 : intent.type) {
|
|
755
|
+
case 'validate':
|
|
756
|
+
return intent.payload;
|
|
757
|
+
case 'list':
|
|
758
|
+
return intent.payload.name;
|
|
759
|
+
}
|
|
760
|
+
return null;
|
|
755
761
|
}
|
|
756
762
|
|
|
757
763
|
exports.FORM_ERROR_ELEMENT_NAME = FORM_ERROR_ELEMENT_NAME;
|
|
758
764
|
exports.VALIDATION_SKIPPED = VALIDATION_SKIPPED;
|
|
759
765
|
exports.VALIDATION_UNDEFINED = VALIDATION_UNDEFINED;
|
|
760
|
-
exports.
|
|
766
|
+
exports.getScope = getScope;
|
|
761
767
|
exports.reportSubmission = reportSubmission;
|
|
762
768
|
exports.useFieldList = useFieldList;
|
|
763
769
|
exports.useFieldset = useFieldset;
|
package/hooks.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { objectSpread2 as _objectSpread2 } from './_virtual/_rollupPluginBabelHelpers.mjs';
|
|
2
|
-
import {
|
|
2
|
+
import { parseIntent, getFormData, parse, getFormAction, getFormEncType, getFormMethod, getPaths, getName, isFieldElement, getErrors, getFormControls, getFormElement, updateList, getValidationMessage, focusFirstInvalidControl, isFocusableFormControl, requestIntent, validate } from '@conform-to/dom';
|
|
3
3
|
import { useState, useMemo, useEffect, useRef, useCallback, useLayoutEffect } from 'react';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -140,7 +140,8 @@ function useForm() {
|
|
|
140
140
|
if (!submission) {
|
|
141
141
|
return {};
|
|
142
142
|
}
|
|
143
|
-
var
|
|
143
|
+
var intent = parseIntent(submission.intent);
|
|
144
|
+
var scope = getScope(intent);
|
|
144
145
|
return scope === null ? submission.error : {
|
|
145
146
|
[scope]: submission.error[scope]
|
|
146
147
|
};
|
|
@@ -226,15 +227,30 @@ function useForm() {
|
|
|
226
227
|
form,
|
|
227
228
|
formData
|
|
228
229
|
})) !== null && _config$onValidate !== void 0 ? _config$onValidate : parse(formData);
|
|
229
|
-
var
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
},
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
230
|
+
var {
|
|
231
|
+
errors: _errors,
|
|
232
|
+
shouldServerValidate
|
|
233
|
+
} = Object.entries(submission.error).reduce((result, _ref2) => {
|
|
234
|
+
var [, error] = _ref2;
|
|
235
|
+
for (var message of normalizeError(error)) {
|
|
236
|
+
if (message === VALIDATION_UNDEFINED) {
|
|
237
|
+
result.shouldServerValidate = true;
|
|
238
|
+
} else if (message !== VALIDATION_SKIPPED) {
|
|
239
|
+
result.errors.push(message);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return result;
|
|
243
|
+
}, {
|
|
244
|
+
errors: [],
|
|
245
|
+
shouldServerValidate: false
|
|
246
|
+
});
|
|
247
|
+
if (
|
|
248
|
+
// has client validation
|
|
249
|
+
typeof config.onValidate !== 'undefined' &&
|
|
250
|
+
// not necessary to validate on the server
|
|
251
|
+
!shouldServerValidate && (
|
|
252
|
+
// client validation failed or non submit intent
|
|
253
|
+
!config.noValidate && !(submitter !== null && submitter !== void 0 && submitter.formNoValidate) && _errors.length > 0 || parseIntent(submission.intent) !== null)) {
|
|
238
254
|
report(form, submission);
|
|
239
255
|
event.preventDefault();
|
|
240
256
|
} else {
|
|
@@ -337,27 +353,23 @@ function useFieldList(ref, config) {
|
|
|
337
353
|
if (!form || event.target !== form) {
|
|
338
354
|
return;
|
|
339
355
|
}
|
|
340
|
-
var
|
|
341
|
-
if ((
|
|
342
|
-
// Ensure the scope of the listener are limited to specific field name
|
|
356
|
+
var intent = parseIntent(event.detail);
|
|
357
|
+
if ((intent === null || intent === void 0 ? void 0 : intent.type) !== 'list' || (intent === null || intent === void 0 ? void 0 : intent.payload.name) !== configRef.current.name) {
|
|
343
358
|
return;
|
|
344
359
|
}
|
|
345
360
|
setEntries(entries => {
|
|
346
|
-
|
|
361
|
+
var list = [...entries];
|
|
362
|
+
switch (intent.payload.operation) {
|
|
347
363
|
case 'append':
|
|
348
364
|
case 'prepend':
|
|
349
365
|
case 'replace':
|
|
350
|
-
return updateList(
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
command.payload.defaultValue]
|
|
355
|
-
})
|
|
366
|
+
return updateList(list, _objectSpread2(_objectSpread2({}, intent.payload), {}, {
|
|
367
|
+
defaultValue: [
|
|
368
|
+
// Generate a random key to avoid conflicts
|
|
369
|
+
crypto.getRandomValues(new Uint32Array(1))[0].toString(36), intent.payload.defaultValue]
|
|
356
370
|
}));
|
|
357
371
|
default:
|
|
358
|
-
|
|
359
|
-
return updateList([...(entries !== null && entries !== void 0 ? entries : [])], command);
|
|
360
|
-
}
|
|
372
|
+
return updateList(list, intent.payload);
|
|
361
373
|
}
|
|
362
374
|
});
|
|
363
375
|
setError(error => {
|
|
@@ -367,21 +379,17 @@ function useFieldList(ref, config) {
|
|
|
367
379
|
errorList[key] = messages;
|
|
368
380
|
}
|
|
369
381
|
}
|
|
370
|
-
switch (
|
|
382
|
+
switch (intent.payload.operation) {
|
|
371
383
|
case 'append':
|
|
372
384
|
case 'prepend':
|
|
373
385
|
case 'replace':
|
|
374
|
-
errorList = updateList(errorList, _objectSpread2(_objectSpread2({},
|
|
375
|
-
|
|
376
|
-
defaultValue: undefined
|
|
377
|
-
})
|
|
386
|
+
errorList = updateList(errorList, _objectSpread2(_objectSpread2({}, intent.payload), {}, {
|
|
387
|
+
defaultValue: undefined
|
|
378
388
|
}));
|
|
379
389
|
break;
|
|
380
390
|
default:
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
break;
|
|
384
|
-
}
|
|
391
|
+
errorList = updateList(errorList, intent.payload);
|
|
392
|
+
break;
|
|
385
393
|
}
|
|
386
394
|
return Object.assign({}, errorList);
|
|
387
395
|
});
|
|
@@ -718,7 +726,8 @@ function reportSubmission(form, submission) {
|
|
|
718
726
|
form.appendChild(button);
|
|
719
727
|
}
|
|
720
728
|
}
|
|
721
|
-
var
|
|
729
|
+
var intent = parseIntent(submission.intent);
|
|
730
|
+
var scope = getScope(intent);
|
|
722
731
|
for (var element of getFormControls(form)) {
|
|
723
732
|
var _elementName = element.name !== FORM_ERROR_ELEMENT_NAME ? element.name : '';
|
|
724
733
|
var messages = normalizeError(submission.error[_elementName]);
|
|
@@ -733,21 +742,18 @@ function reportSubmission(form, submission) {
|
|
|
733
742
|
element.dispatchEvent(invalidEvent);
|
|
734
743
|
}
|
|
735
744
|
}
|
|
736
|
-
if (
|
|
737
|
-
|
|
738
|
-
focusFormControl(form, scope);
|
|
739
|
-
} else {
|
|
740
|
-
focusFirstInvalidControl(form);
|
|
741
|
-
}
|
|
745
|
+
if (!intent) {
|
|
746
|
+
focusFirstInvalidControl(form);
|
|
742
747
|
}
|
|
743
748
|
}
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
749
|
+
function getScope(intent) {
|
|
750
|
+
switch (intent === null || intent === void 0 ? void 0 : intent.type) {
|
|
751
|
+
case 'validate':
|
|
752
|
+
return intent.payload;
|
|
753
|
+
case 'list':
|
|
754
|
+
return intent.payload.name;
|
|
755
|
+
}
|
|
756
|
+
return null;
|
|
751
757
|
}
|
|
752
758
|
|
|
753
|
-
export { FORM_ERROR_ELEMENT_NAME, VALIDATION_SKIPPED, VALIDATION_UNDEFINED,
|
|
759
|
+
export { FORM_ERROR_ELEMENT_NAME, VALIDATION_SKIPPED, VALIDATION_UNDEFINED, getScope, reportSubmission, useFieldList, useFieldset, useForm, useInputEvent, validateConstraint };
|
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": "0.7.0-pre.
|
|
6
|
+
"version": "0.7.0-pre.2",
|
|
7
7
|
"main": "index.js",
|
|
8
8
|
"module": "index.mjs",
|
|
9
9
|
"types": "index.d.ts",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"url": "https://github.com/edmundhung/conform/issues"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@conform-to/dom": "0.7.0-pre.
|
|
33
|
+
"@conform-to/dom": "0.7.0-pre.2"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
36
|
"react": ">=16.8"
|