@conform-to/dom
Advanced tools
Comparing version 0.7.0-pre.1 to 0.7.0-pre.2
@@ -52,5 +52,1 @@ export type FormControl = HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement | HTMLButtonElement; | ||
export declare function focusFirstInvalidControl(form: HTMLFormElement): void; | ||
/** | ||
* Focus on the first form control with the provided name | ||
*/ | ||
export declare function focusFormControl(form: HTMLFormElement, name: string): void; |
17
dom.js
@@ -143,21 +143,4 @@ 'use strict'; | ||
/** | ||
* Focus on the first form control with the provided name | ||
*/ | ||
function focusFormControl(form, name) { | ||
var element = form.elements.namedItem(name); | ||
if (!element) { | ||
return; | ||
} | ||
if (element instanceof RadioNodeList) { | ||
element = element.item(0); | ||
} | ||
if (isFocusableFormControl(element)) { | ||
element.focus(); | ||
} | ||
} | ||
exports.createSubmitter = createSubmitter; | ||
exports.focusFirstInvalidControl = focusFirstInvalidControl; | ||
exports.focusFormControl = focusFormControl; | ||
exports.getFormAction = getFormAction; | ||
@@ -164,0 +147,0 @@ exports.getFormControls = getFormControls; |
@@ -31,3 +31,3 @@ /** | ||
*/ | ||
export declare function resolve(payload: FormData | URLSearchParams): {}; | ||
export declare function resolve(payload: FormData | URLSearchParams, ignoreKeys?: string[]): {}; | ||
/** | ||
@@ -34,0 +34,0 @@ * Format the error messages into a validation message |
@@ -85,6 +85,9 @@ 'use strict'; | ||
*/ | ||
function resolve(payload) { | ||
function resolve(payload, ignoreKeys) { | ||
var data = {}; | ||
var _loop = function _loop(value) { | ||
setValue(data, name, prev => { | ||
if (ignoreKeys !== null && ignoreKeys !== void 0 && ignoreKeys.includes(key)) { | ||
return "continue"; | ||
} | ||
setValue(data, key, prev => { | ||
if (!prev) { | ||
@@ -99,4 +102,5 @@ return value; | ||
}; | ||
for (var [name, value] of payload.entries()) { | ||
_loop(value); | ||
for (var [key, value] of payload.entries()) { | ||
var _ret = _loop(value); | ||
if (_ret === "continue") continue; | ||
} | ||
@@ -103,0 +107,0 @@ return data; |
@@ -1,5 +0,5 @@ | ||
export { type FormControl as FieldElement, isFormControl as isFieldElement, isFocusableFormControl, getFormAction, getFormControls, getFormElement, getFormEncType, getFormMethod, focusFirstInvalidControl, focusFormControl, createSubmitter, requestSubmit, } from './dom.js'; | ||
export { type FormControl as FieldElement, isFormControl as isFieldElement, isFocusableFormControl, getFormAction, getFormControls, getFormElement, getFormEncType, getFormMethod, focusFirstInvalidControl, createSubmitter, requestSubmit, } from './dom.js'; | ||
export { formatPaths as getName, getPaths, getFormData, getValidationMessage, getErrors, } from './formdata.js'; | ||
export { type ListCommand, INTENT, getScope, isSubmitting, validate, list, parseListCommand, updateList, requestIntent, } from './intent.js'; | ||
export { INTENT, getIntent, parseIntent, validate, list, updateList, requestIntent, } from './intent.js'; | ||
export { type Submission, parse } from './parse.js'; | ||
export { type FieldConstraint, type FieldsetConstraint, type ResolveType, type KeysOf, } from './types.js'; |
@@ -14,3 +14,2 @@ 'use strict'; | ||
exports.focusFirstInvalidControl = dom.focusFirstInvalidControl; | ||
exports.focusFormControl = dom.focusFormControl; | ||
exports.getFormAction = dom.getFormAction; | ||
@@ -30,6 +29,5 @@ exports.getFormControls = dom.getFormControls; | ||
exports.INTENT = intent.INTENT; | ||
exports.getScope = intent.getScope; | ||
exports.isSubmitting = intent.isSubmitting; | ||
exports.getIntent = intent.getIntent; | ||
exports.list = intent.list; | ||
exports.parseListCommand = intent.parseListCommand; | ||
exports.parseIntent = intent.parseIntent; | ||
exports.requestIntent = intent.requestIntent; | ||
@@ -36,0 +34,0 @@ exports.updateList = intent.updateList; |
108
intent.d.ts
@@ -6,59 +6,53 @@ export interface IntentButtonProps { | ||
} | ||
export type ListCommand<Schema = unknown> = { | ||
type: 'prepend'; | ||
scope: string; | ||
payload: { | ||
defaultValue: Schema; | ||
}; | ||
export type ListIntentPayload<Schema = unknown> = { | ||
name: string; | ||
operation: 'prepend'; | ||
defaultValue?: Schema; | ||
} | { | ||
type: 'append'; | ||
scope: string; | ||
payload: { | ||
defaultValue: Schema; | ||
}; | ||
name: string; | ||
operation: 'append'; | ||
defaultValue?: Schema; | ||
} | { | ||
type: 'replace'; | ||
scope: string; | ||
payload: { | ||
defaultValue: Schema; | ||
index: number; | ||
}; | ||
name: string; | ||
operation: 'replace'; | ||
defaultValue: Schema; | ||
index: number; | ||
} | { | ||
type: 'remove'; | ||
scope: string; | ||
payload: { | ||
index: number; | ||
}; | ||
name: string; | ||
operation: 'remove'; | ||
index: number; | ||
} | { | ||
type: 'reorder'; | ||
scope: string; | ||
payload: { | ||
from: number; | ||
to: number; | ||
}; | ||
name: string; | ||
operation: 'reorder'; | ||
from: number; | ||
to: number; | ||
}; | ||
export interface ListCommandButtonBuilder { | ||
append<Schema>(name: string, payload?: { | ||
defaultValue: Schema; | ||
}): IntentButtonProps; | ||
prepend<Schema>(name: string, payload?: { | ||
defaultValue: Schema; | ||
}): IntentButtonProps; | ||
replace<Schema>(name: string, payload: { | ||
defaultValue: Schema; | ||
/** | ||
* Helpers to configure an intent button for modifying a list | ||
* | ||
* @see https://conform.guide/api/react#list | ||
*/ | ||
export declare const list: { | ||
prepend: <Schema>(name: string, payload?: { | ||
defaultValue?: Schema | undefined; | ||
} | undefined) => IntentButtonProps; | ||
append: <Schema_1>(name: string, payload?: { | ||
defaultValue?: Schema_1 | undefined; | ||
} | undefined) => IntentButtonProps; | ||
replace: <Schema_2>(name: string, payload: { | ||
defaultValue: Schema_2; | ||
index: number; | ||
}): IntentButtonProps; | ||
remove(name: string, payload: { | ||
}) => IntentButtonProps; | ||
remove: <Schema_3>(name: string, payload: { | ||
index: number; | ||
}): IntentButtonProps; | ||
reorder(name: string, payload: { | ||
}) => IntentButtonProps; | ||
reorder: <Schema_4>(name: string, payload: { | ||
from: number; | ||
to: number; | ||
}): IntentButtonProps; | ||
} | ||
}) => IntentButtonProps; | ||
}; | ||
export declare const INTENT = "__intent__"; | ||
/** | ||
* | ||
* @param payload | ||
* @returns | ||
* Returns the intent from the form data or search params. | ||
* It throws an error if multiple intent is set. | ||
*/ | ||
@@ -71,16 +65,14 @@ export declare function getIntent(payload: FormData | URLSearchParams): string; | ||
*/ | ||
export declare function validate(field?: string): IntentButtonProps; | ||
export declare function requestIntent(form: HTMLFormElement | undefined, buttonProps: { | ||
export declare function validate(field: string): IntentButtonProps; | ||
export declare function requestIntent(form: HTMLFormElement | null | undefined, buttonProps: { | ||
value: string; | ||
formNoValidate?: boolean; | ||
}): void; | ||
/** | ||
* Helpers to configure an intent button for modifying a list | ||
* | ||
* @see https://conform.guide/api/react#list | ||
*/ | ||
export declare const list: ListCommandButtonBuilder; | ||
export declare function isSubmitting(intent: string): boolean; | ||
export declare function getScope(intent: string): string | null; | ||
export declare function parseListCommand<Schema = unknown>(intent: string): ListCommand<Schema> | null; | ||
export declare function updateList<Schema>(list: Array<Schema>, command: ListCommand<Schema>): Array<Schema>; | ||
export declare function parseIntent<Schema>(intent: string): { | ||
type: 'validate'; | ||
payload: string; | ||
} | { | ||
type: 'list'; | ||
payload: ListIntentPayload<Schema>; | ||
} | null; | ||
export declare function updateList<Schema>(list: Array<Schema>, payload: ListIntentPayload<Schema>): Array<Schema>; |
126
intent.js
@@ -5,10 +5,30 @@ 'use strict'; | ||
var _rollupPluginBabelHelpers = require('./_virtual/_rollupPluginBabelHelpers.js'); | ||
var dom = require('./dom.js'); | ||
/** | ||
* Helpers to configure an intent button for modifying a list | ||
* | ||
* @see https://conform.guide/api/react#list | ||
*/ | ||
var list = new Proxy({}, { | ||
get(_target, operation) { | ||
return function (name) { | ||
var payload = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
return { | ||
name: INTENT, | ||
value: "list/".concat(JSON.stringify(_rollupPluginBabelHelpers.objectSpread2({ | ||
name, | ||
operation | ||
}, payload))), | ||
formNoValidate: true | ||
}; | ||
}; | ||
} | ||
}); | ||
var INTENT = '__intent__'; | ||
/** | ||
* | ||
* @param payload | ||
* @returns | ||
* Returns the intent from the form data or search params. | ||
* It throws an error if multiple intent is set. | ||
*/ | ||
@@ -19,7 +39,10 @@ function getIntent(payload) { | ||
} | ||
var [intent, ...rest] = payload.getAll(INTENT); | ||
if (typeof intent !== 'string' || rest.length > 0) { | ||
var [intent, secondIntent, ...rest] = payload.getAll(INTENT); | ||
// The submitter value is included in the formData directly on Safari 15.6. | ||
// This causes the intent to be duplicated in the payload. | ||
// We will ignore the second intent if it is the same as the first one. | ||
if (typeof intent !== 'string' || secondIntent && intent !== secondIntent || rest.length > 0) { | ||
throw new Error('The intent could only be set on a button'); | ||
} | ||
payload.delete(INTENT); | ||
return intent; | ||
@@ -36,3 +59,3 @@ } | ||
name: INTENT, | ||
value: field ? "validate/".concat(field) : 'validate', | ||
value: "validate/".concat(field), | ||
formNoValidate: true | ||
@@ -54,72 +77,45 @@ }; | ||
} | ||
/** | ||
* Helpers to configure an intent button for modifying a list | ||
* | ||
* @see https://conform.guide/api/react#list | ||
*/ | ||
var list = new Proxy({}, { | ||
get(_target, type) { | ||
return function (scope) { | ||
var payload = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
return { | ||
name: INTENT, | ||
value: "list/".concat(type, "/").concat(scope, "/").concat(JSON.stringify(payload)), | ||
formNoValidate: true | ||
}; | ||
}; | ||
} | ||
}); | ||
function isSubmitting(intent) { | ||
var [type] = intent.split('/', 1); | ||
return type !== 'validate' && type !== 'list'; | ||
} | ||
function getScope(intent) { | ||
var _parseListCommand$sco, _parseListCommand; | ||
var [type, ...rest] = intent.split('/'); | ||
switch (type) { | ||
case 'validate': | ||
return rest.length > 0 ? rest.join('/') : null; | ||
case 'list': | ||
return (_parseListCommand$sco = (_parseListCommand = parseListCommand(intent)) === null || _parseListCommand === void 0 ? void 0 : _parseListCommand.scope) !== null && _parseListCommand$sco !== void 0 ? _parseListCommand$sco : null; | ||
default: | ||
return null; | ||
} | ||
} | ||
function parseListCommand(intent) { | ||
try { | ||
var [group, type, scope, json] = intent.split('/'); | ||
if (group !== 'list' || !['prepend', 'append', 'replace', 'remove', 'reorder'].includes(type) || !scope) { | ||
return null; | ||
function parseIntent(intent) { | ||
var [type, payload] = intent.split('/', 2); | ||
if (typeof payload !== 'undefined') { | ||
try { | ||
switch (type) { | ||
case 'validate': | ||
return { | ||
type, | ||
payload | ||
}; | ||
case 'list': | ||
return { | ||
type, | ||
payload: JSON.parse(payload) | ||
}; | ||
} | ||
} catch (error) { | ||
throw new Error("Failed parsing intent: ".concat(intent), { | ||
cause: error | ||
}); | ||
} | ||
var _payload = JSON.parse(json); | ||
return { | ||
// @ts-expect-error | ||
type, | ||
scope, | ||
payload: _payload | ||
}; | ||
} catch (error) { | ||
return null; | ||
} | ||
return null; | ||
} | ||
function updateList(list, command) { | ||
switch (command.type) { | ||
function updateList(list, payload) { | ||
switch (payload.operation) { | ||
case 'prepend': | ||
list.unshift(command.payload.defaultValue); | ||
list.unshift(payload.defaultValue); | ||
break; | ||
case 'append': | ||
list.push(command.payload.defaultValue); | ||
list.push(payload.defaultValue); | ||
break; | ||
case 'replace': | ||
list.splice(command.payload.index, 1, command.payload.defaultValue); | ||
list.splice(payload.index, 1, payload.defaultValue); | ||
break; | ||
case 'remove': | ||
list.splice(command.payload.index, 1); | ||
list.splice(payload.index, 1); | ||
break; | ||
case 'reorder': | ||
list.splice(command.payload.to, 0, ...list.splice(command.payload.from, 1)); | ||
list.splice(payload.to, 0, ...list.splice(payload.from, 1)); | ||
break; | ||
default: | ||
throw new Error('Unknown list command received'); | ||
throw new Error('Unknown list intent received'); | ||
} | ||
@@ -131,8 +127,6 @@ return list; | ||
exports.getIntent = getIntent; | ||
exports.getScope = getScope; | ||
exports.isSubmitting = isSubmitting; | ||
exports.list = list; | ||
exports.parseListCommand = parseListCommand; | ||
exports.parseIntent = parseIntent; | ||
exports.requestIntent = requestIntent; | ||
exports.updateList = updateList; | ||
exports.validate = validate; |
@@ -6,3 +6,3 @@ { | ||
"license": "MIT", | ||
"version": "0.7.0-pre.1", | ||
"version": "0.7.0-pre.2", | ||
"main": "index.js", | ||
@@ -9,0 +9,0 @@ "module": "index.mjs", |
12
parse.js
@@ -12,12 +12,12 @@ 'use strict'; | ||
intent: intent.getIntent(payload), | ||
payload: formdata.resolve(payload), | ||
payload: formdata.resolve(payload, [intent.INTENT]), | ||
error: {} | ||
}; | ||
var command = intent.parseListCommand(submission.intent); | ||
if (command) { | ||
formdata.setValue(submission.payload, command.scope, list => { | ||
var intent$1 = intent.parseIntent(submission.intent); | ||
if (intent$1 && intent$1.type === 'list') { | ||
formdata.setValue(submission.payload, intent$1.payload.name, list => { | ||
if (typeof list !== 'undefined' && !Array.isArray(list)) { | ||
throw new Error('The list command can only be applied to a list'); | ||
throw new Error('The list intent can only be applied to a list'); | ||
} | ||
return intent.updateList(list !== null && list !== void 0 ? list : [], command); | ||
return intent.updateList(list !== null && list !== void 0 ? list : [], intent$1.payload); | ||
}); | ||
@@ -24,0 +24,0 @@ } |
@@ -0,1 +1,4 @@ | ||
export type Pretty<T> = { | ||
[K in keyof T]: T[K]; | ||
} & {}; | ||
export type FieldConstraint<Schema = any> = { | ||
@@ -2,0 +5,0 @@ required?: boolean; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
41204
1158