@conform-to/dom
Advanced tools
Comparing version 0.3.1 to 0.4.0-pre.0
@@ -6,3 +6,3 @@ export declare type Primitive = null | undefined | string | number | boolean | Date; | ||
defaultValue?: FieldValue<Schema>; | ||
initialError?: FieldError<Schema>['details']; | ||
initialError?: Array<[string, string]>; | ||
form?: string; | ||
@@ -13,8 +13,2 @@ } | ||
} : unknown; | ||
export interface FieldError<Schema> { | ||
message?: string; | ||
details?: Schema extends Primitive | File ? never : Schema extends Array<infer InnerType> ? Array<FieldError<InnerType>> : Schema extends Record<string, any> ? { | ||
[Key in keyof Schema]?: FieldError<Schema[Key]>; | ||
} : unknown; | ||
} | ||
export declare type FieldConstraint = { | ||
@@ -33,37 +27,33 @@ required?: boolean; | ||
}; | ||
export declare type Schema<Shape extends Record<string, any>, Source> = { | ||
source: Source; | ||
constraint: FieldsetConstraint<Shape>; | ||
validate: (element: HTMLFormElement, submitter?: HTMLInputElement | HTMLButtonElement | null) => void; | ||
parse: (payload: FormData | URLSearchParams) => Submission<Shape>; | ||
export declare type FormState<Schema = unknown> = { | ||
scope: string[]; | ||
value: FieldValue<Schema>; | ||
error: Array<[string, string]>; | ||
}; | ||
export interface FormState<Schema extends Record<string, any>> { | ||
value: FieldValue<Schema>; | ||
error: FieldError<Schema>; | ||
} | ||
export declare type Submission<T extends Record<string, unknown>> = { | ||
state: 'modified'; | ||
form: FormState<T>; | ||
export declare type Submission<Schema = unknown> = FormState<Schema> & ({ | ||
type?: undefined; | ||
} | { | ||
state: 'rejected'; | ||
form: FormState<T>; | ||
} | { | ||
state: 'accepted'; | ||
data: T; | ||
form: FormState<T>; | ||
}; | ||
type: string; | ||
data: string; | ||
}); | ||
export declare function isFieldElement(element: unknown): element is FieldElement; | ||
export declare function getPaths(name?: string): Array<string | number>; | ||
export declare function getPaths(name: string): Array<string | number>; | ||
export declare function getFormData(form: HTMLFormElement, submitter?: HTMLInputElement | HTMLButtonElement | null): FormData; | ||
export declare function getName(paths: Array<string | number>): string; | ||
export declare function getKey(fieldName: string, fieldsetName?: string): string | null; | ||
export declare function setFormError(form: HTMLFormElement, errors: Array<[string, string]>): void; | ||
export declare function hasError(error: Array<[string, string]>, name: string): boolean; | ||
export declare function reportValidity(form: HTMLFormElement, state: FormState): boolean; | ||
export declare function setValue<T>(target: any, paths: Array<string | number>, valueFn: (prev?: T) => T): void; | ||
export declare function flatten(data: unknown, prefix?: string): Array<[string, FormDataEntryValue]>; | ||
export declare function unflatten(entries: Array<[string, FormDataEntryValue]> | Iterable<[string, FormDataEntryValue]>): Record<string, unknown>; | ||
export declare function createSubmission(payload: FormData | URLSearchParams): Submission<Record<string, unknown>>; | ||
export declare function createValidate(handler: (field: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement | HTMLButtonElement, formData: FormData) => void): (form: HTMLFormElement, submitter?: HTMLInputElement | HTMLButtonElement | null) => void; | ||
export declare function requestSubmit(form: HTMLFormElement, submitter?: HTMLButtonElement | HTMLInputElement): void; | ||
export declare function requestValidate(form: HTMLFormElement, field?: string): void; | ||
export declare function getFormElement(element: HTMLFormElement | HTMLFieldSetElement | HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement | HTMLButtonElement | null): HTMLFormElement | null; | ||
export declare type ListCommand<Schema> = { | ||
export declare function focusFirstInvalidField(form: HTMLFormElement, fields?: string[]): void; | ||
export declare function getSubmissionType(name: string): string | null; | ||
export declare function parse<Schema extends Record<string, any>>(payload: FormData | URLSearchParams): Submission<Schema>; | ||
export declare type Command = { | ||
name: string; | ||
value: string; | ||
}; | ||
export declare type ListCommand<Schema = unknown> = { | ||
type: 'prepend'; | ||
scope: string; | ||
payload: { | ||
@@ -74,2 +64,3 @@ defaultValue: Schema; | ||
type: 'append'; | ||
scope: string; | ||
payload: { | ||
@@ -80,2 +71,3 @@ defaultValue: Schema; | ||
type: 'replace'; | ||
scope: string; | ||
payload: { | ||
@@ -87,2 +79,3 @@ defaultValue: Schema; | ||
type: 'remove'; | ||
scope: string; | ||
payload: { | ||
@@ -93,2 +86,3 @@ index: number; | ||
type: 'reorder'; | ||
scope: string; | ||
payload: { | ||
@@ -99,6 +93,4 @@ from: number; | ||
}; | ||
export declare const listCommandKey = "__conform__"; | ||
export declare function serializeListCommand<Schema>(name: string, { type, payload }: ListCommand<Schema>): string; | ||
export declare function parseListCommand<Schema>(serialized: string): [string, ListCommand<Schema>]; | ||
export declare function updateList<Type>(list: Array<Type>, command: ListCommand<Type>): Array<Type>; | ||
export declare function applyListCommand(payload: FormData | URLSearchParams): FormData | URLSearchParams; | ||
export declare function parseListCommand<Schema = unknown>(data: string): ListCommand<Schema>; | ||
export declare function updateList<Schema>(list: Array<Schema>, command: ListCommand<Schema>): Array<Schema>; | ||
export declare function handleList<Schema>(submission: Submission<Schema>): Submission<Schema>; |
313
index.js
@@ -5,2 +5,4 @@ 'use strict'; | ||
var _rollupPluginBabelHelpers = require('./_virtual/_rollupPluginBabelHelpers.js'); | ||
function isFieldElement(element) { | ||
@@ -10,3 +12,3 @@ return element instanceof Element && (element.tagName === 'INPUT' || element.tagName === 'SELECT' || element.tagName === 'TEXTAREA' || element.tagName === 'BUTTON'); | ||
function getPaths(name) { | ||
var pattern = /(\w+)\[(\d+)\]/; | ||
var pattern = /(\w*)\[(\d+)\]/; | ||
@@ -24,2 +26,6 @@ if (!name) { | ||
if (matches[1] === '') { | ||
return Number(matches[2]); | ||
} | ||
return [matches[1], Number(matches[2])]; | ||
@@ -39,2 +45,6 @@ }); | ||
return paths.reduce((name, path) => { | ||
if (typeof path === 'number') { | ||
return "".concat(name, "[").concat(path, "]"); | ||
} | ||
if (name === '' || path === '') { | ||
@@ -44,32 +54,25 @@ return [name, path].join(''); | ||
if (typeof path === 'number') { | ||
return "".concat(name, "[").concat(path, "]"); | ||
} | ||
return [name, path].join('.'); | ||
}, ''); | ||
} | ||
function getKey(fieldName) { | ||
var fieldsetName = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; | ||
var name = fieldsetName === '' || fieldName.startsWith(fieldsetName) ? fieldName.slice(fieldsetName ? fieldsetName.length + 1 : 0) : ''; | ||
var paths = getPaths(name); | ||
if (paths.length > 1) { | ||
return null; | ||
} | ||
return typeof paths[0] === 'string' ? paths[0] : null; | ||
function hasError(error, name) { | ||
return typeof error.find(_ref => { | ||
var [fieldName, message] = _ref; | ||
return fieldName === name && message !== ''; | ||
}) !== 'undefined'; | ||
} | ||
function setFormError(form, errors) { | ||
var firstErrorByName = Object.fromEntries([...errors].reverse()); | ||
function reportValidity(form, state) { | ||
var firstErrorByName = Object.fromEntries([...state.error].reverse()); | ||
for (var _element of form.elements) { | ||
var _firstErrorByName$_el; | ||
for (var element of form.elements) { | ||
var _firstErrorByName$ele; | ||
if (!isFieldElement(_element)) { | ||
if (!isFieldElement(element) || !state.scope.includes(element.name)) { | ||
continue; | ||
} | ||
_element.setCustomValidity((_firstErrorByName$_el = firstErrorByName[_element.name]) !== null && _firstErrorByName$_el !== void 0 ? _firstErrorByName$_el : ''); | ||
element.setCustomValidity((_firstErrorByName$ele = firstErrorByName[element.name]) !== null && _firstErrorByName$ele !== void 0 ? _firstErrorByName$ele : ''); | ||
} | ||
return form.reportValidity(); | ||
} | ||
@@ -92,112 +95,142 @@ function setValue(target, paths, valueFn) { | ||
} | ||
function flatten(data) { | ||
var prefix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; | ||
var entries = []; | ||
function requestSubmit(form, submitter) { | ||
var submitEvent = new SubmitEvent('submit', { | ||
bubbles: true, | ||
cancelable: true, | ||
submitter | ||
}); | ||
form.dispatchEvent(submitEvent); | ||
} | ||
function requestValidate(form, field) { | ||
var button = document.createElement('button'); | ||
button.name = 'conform/validate'; | ||
button.value = field !== null && field !== void 0 ? field : ''; | ||
button.hidden = true; | ||
form.appendChild(button); | ||
requestSubmit(form, button); | ||
form.removeChild(button); | ||
} | ||
function getFormElement(element) { | ||
var form = element instanceof HTMLFormElement ? element : element === null || element === void 0 ? void 0 : element.form; | ||
if (typeof data === 'string' || typeof data === 'undefined' || data instanceof File) { | ||
entries.push([prefix, data !== null && data !== void 0 ? data : '']); | ||
} else if (Array.isArray(data)) { | ||
for (var i = 0; i < data.length; i++) { | ||
entries.push(...flatten(data[i], "".concat(prefix, "[").concat(i, "]"))); | ||
} | ||
} else { | ||
for (var [key, value] of Object.entries(Object(data))) { | ||
entries.push(...flatten(value, prefix ? "".concat(prefix, ".").concat(key) : key)); | ||
} | ||
if (!form) { | ||
return null; | ||
} | ||
return entries; | ||
return form; | ||
} | ||
function unflatten(entries) { | ||
var result = {}; | ||
function focusFirstInvalidField(form, fields) { | ||
var currentFocus = document.activeElement; | ||
var _loop = function _loop(key, value) { | ||
var paths = getPaths(key); | ||
setValue(result, paths, prev => { | ||
if (prev) { | ||
throw new Error('Entry with the same name is not supported'); | ||
if (!isFieldElement(currentFocus) || currentFocus.tagName !== 'BUTTON' || currentFocus.form !== form) { | ||
return; | ||
} | ||
for (var field of form.elements) { | ||
if (isFieldElement(field)) { | ||
// Focus on the first non button field | ||
if (!field.validity.valid && field.dataset.conformTouched && field.tagName !== 'BUTTON' && (!fields || fields.includes(field.name))) { | ||
field.focus(); | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
function getSubmissionType(name) { | ||
var prefix = 'conform/'; | ||
return value; | ||
}); | ||
}; | ||
for (var [key, value] of entries) { | ||
_loop(key, value); | ||
if (!name.startsWith(prefix) || name.length <= prefix.length) { | ||
return null; | ||
} | ||
return result; | ||
return name.slice(prefix.length); | ||
} | ||
function createSubmission(payload) { | ||
var value = {}; | ||
function parse(payload) { | ||
var submission = { | ||
value: {}, | ||
error: [], | ||
scope: [''] | ||
}; | ||
try { | ||
var modifiedPayload = applyListCommand(payload); | ||
value = unflatten(modifiedPayload.entries()); | ||
var _loop = function _loop(name, value) { | ||
var submissionType = getSubmissionType(name); | ||
if (payload !== modifiedPayload) { | ||
return { | ||
state: 'modified', | ||
form: { | ||
value, | ||
error: {} | ||
if (submissionType) { | ||
if (typeof value !== 'string') { | ||
throw new Error('The conform command could not be used on a file input'); | ||
} | ||
}; | ||
} | ||
} catch (e) { | ||
return { | ||
state: 'rejected', | ||
form: { | ||
value, | ||
error: { | ||
message: e instanceof Error ? e.message : 'Submission failed' | ||
if (typeof submission.type !== 'undefined') { | ||
throw new Error('The conform command could only be set on a button'); | ||
} | ||
submission = _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, submission), {}, { | ||
type: submissionType, | ||
data: value | ||
}); | ||
} else { | ||
var paths = getPaths(name); | ||
var scopes = paths.reduce((result, path) => { | ||
if (result.length === 0) { | ||
if (typeof path !== 'string') { | ||
throw new Error("Invalid name received: ".concat(name)); | ||
} | ||
result.push(path); | ||
} else { | ||
var [lastName] = result.slice(-1); | ||
result.push(getName([lastName, path])); | ||
} | ||
return result; | ||
}, []); | ||
submission.scope.push(...scopes); | ||
setValue(submission.value, paths, prev => { | ||
if (prev) { | ||
throw new Error('Entry with the same name is not supported'); | ||
} | ||
return value; | ||
}); | ||
} | ||
}; | ||
} | ||
return { | ||
state: 'accepted', | ||
data: value, | ||
form: { | ||
value, | ||
error: {} | ||
for (var [name, value] of payload.entries()) { | ||
_loop(name, value); | ||
} | ||
}; | ||
} | ||
function createValidate(handler) { | ||
return (form, submitter) => { | ||
var formData = getFormData(form, submitter); | ||
for (var _field of form.elements) { | ||
if (isFieldElement(_field)) { | ||
handler(_field, formData); | ||
} | ||
switch (submission.type) { | ||
case 'validate': | ||
if (typeof submission.data !== 'undefined' && submission.data !== '') { | ||
submission.scope = [submission.data]; | ||
} | ||
break; | ||
case 'list': | ||
submission = handleList(submission); | ||
break; | ||
} | ||
}; | ||
} catch (e) { | ||
submission.error.push(['', e instanceof Error ? e.message : 'Invalid payload received']); | ||
} // Remove duplicates | ||
submission.scope = Array.from(new Set(submission.scope)); | ||
return submission; | ||
} | ||
function getFormElement(element) { | ||
var form = element instanceof HTMLFormElement ? element : element === null || element === void 0 ? void 0 : element.form; | ||
function parseListCommand(data) { | ||
try { | ||
var command = JSON.parse(data); | ||
if (!form) { | ||
return null; | ||
if (typeof command.type !== 'string' || !['prepend', 'append', 'replace', 'remove', 'reorder'].includes(command.type)) { | ||
throw new Error('Unsupported list command type'); | ||
} | ||
return command; | ||
} catch (error) { | ||
throw new Error("Invalid list command: \"".concat(data, "\"; ").concat(error)); | ||
} | ||
return form; | ||
} | ||
var listCommandKey = '__conform__'; | ||
function serializeListCommand(name, _ref) { | ||
var { | ||
type, | ||
payload | ||
} = _ref; | ||
return [name, type, JSON.stringify(payload)].join('::'); | ||
} | ||
function parseListCommand(serialized) { | ||
var [name, type, json] = serialized.split('::'); | ||
return [name, { | ||
type: type, | ||
payload: JSON.parse(json) | ||
}]; | ||
} | ||
function updateList(list, command) { | ||
@@ -232,3 +265,3 @@ switch (command.type) { | ||
default: | ||
throw new Error('Invalid list command'); | ||
throw new Error('Unknown list command received'); | ||
} | ||
@@ -238,60 +271,36 @@ | ||
} | ||
function applyListCommand(payload) { | ||
var command = payload.get(listCommandKey); | ||
if (!command) { | ||
return payload; | ||
function handleList(submission) { | ||
if (submission.type !== 'list') { | ||
return submission; | ||
} | ||
payload.delete(listCommandKey); | ||
if (command instanceof File) { | ||
throw new Error("The \"".concat(listCommandKey, "\" key could not be used for file upload")); | ||
} | ||
var result = new FormData(); | ||
var entries = []; | ||
var [key, listCommand] = parseListCommand(command); | ||
for (var [name, value] of payload) { | ||
if (name.startsWith(key)) { | ||
entries.push([name.replace(key, 'list'), value]); | ||
} else { | ||
result.append(name, value); | ||
var command = parseListCommand(submission.data); | ||
var paths = getPaths(command.scope); | ||
setValue(submission.value, paths, list => { | ||
if (!Array.isArray(list)) { | ||
throw new Error('The list command can only be applied to a list'); | ||
} | ||
} | ||
var { | ||
list | ||
} = unflatten(entries); | ||
if (!Array.isArray(list)) { | ||
throw new Error('The list command can only be applied to a list'); | ||
} | ||
updateList(list, listCommand); | ||
for (var [_name, _value] of flatten(list, key)) { | ||
result.append(_name, _value); | ||
} | ||
return result; | ||
return updateList(list, command); | ||
}); | ||
return _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, submission), {}, { | ||
scope: [command.scope] | ||
}); | ||
} | ||
exports.applyListCommand = applyListCommand; | ||
exports.createSubmission = createSubmission; | ||
exports.createValidate = createValidate; | ||
exports.flatten = flatten; | ||
exports.focusFirstInvalidField = focusFirstInvalidField; | ||
exports.getFormData = getFormData; | ||
exports.getFormElement = getFormElement; | ||
exports.getKey = getKey; | ||
exports.getName = getName; | ||
exports.getPaths = getPaths; | ||
exports.getSubmissionType = getSubmissionType; | ||
exports.handleList = handleList; | ||
exports.hasError = hasError; | ||
exports.isFieldElement = isFieldElement; | ||
exports.listCommandKey = listCommandKey; | ||
exports.parse = parse; | ||
exports.parseListCommand = parseListCommand; | ||
exports.serializeListCommand = serializeListCommand; | ||
exports.setFormError = setFormError; | ||
exports.reportValidity = reportValidity; | ||
exports.requestSubmit = requestSubmit; | ||
exports.requestValidate = requestValidate; | ||
exports.setValue = setValue; | ||
exports.unflatten = unflatten; | ||
exports.updateList = updateList; |
@@ -0,1 +1,3 @@ | ||
import { objectSpread2 as _objectSpread2 } from './_virtual/_rollupPluginBabelHelpers.js'; | ||
function isFieldElement(element) { | ||
@@ -5,3 +7,3 @@ return element instanceof Element && (element.tagName === 'INPUT' || element.tagName === 'SELECT' || element.tagName === 'TEXTAREA' || element.tagName === 'BUTTON'); | ||
function getPaths(name) { | ||
var pattern = /(\w+)\[(\d+)\]/; | ||
var pattern = /(\w*)\[(\d+)\]/; | ||
@@ -19,2 +21,6 @@ if (!name) { | ||
if (matches[1] === '') { | ||
return Number(matches[2]); | ||
} | ||
return [matches[1], Number(matches[2])]; | ||
@@ -34,2 +40,6 @@ }); | ||
return paths.reduce((name, path) => { | ||
if (typeof path === 'number') { | ||
return "".concat(name, "[").concat(path, "]"); | ||
} | ||
if (name === '' || path === '') { | ||
@@ -39,32 +49,25 @@ return [name, path].join(''); | ||
if (typeof path === 'number') { | ||
return "".concat(name, "[").concat(path, "]"); | ||
} | ||
return [name, path].join('.'); | ||
}, ''); | ||
} | ||
function getKey(fieldName) { | ||
var fieldsetName = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; | ||
var name = fieldsetName === '' || fieldName.startsWith(fieldsetName) ? fieldName.slice(fieldsetName ? fieldsetName.length + 1 : 0) : ''; | ||
var paths = getPaths(name); | ||
if (paths.length > 1) { | ||
return null; | ||
} | ||
return typeof paths[0] === 'string' ? paths[0] : null; | ||
function hasError(error, name) { | ||
return typeof error.find(_ref => { | ||
var [fieldName, message] = _ref; | ||
return fieldName === name && message !== ''; | ||
}) !== 'undefined'; | ||
} | ||
function setFormError(form, errors) { | ||
var firstErrorByName = Object.fromEntries([...errors].reverse()); | ||
function reportValidity(form, state) { | ||
var firstErrorByName = Object.fromEntries([...state.error].reverse()); | ||
for (var _element of form.elements) { | ||
var _firstErrorByName$_el; | ||
for (var element of form.elements) { | ||
var _firstErrorByName$ele; | ||
if (!isFieldElement(_element)) { | ||
if (!isFieldElement(element) || !state.scope.includes(element.name)) { | ||
continue; | ||
} | ||
_element.setCustomValidity((_firstErrorByName$_el = firstErrorByName[_element.name]) !== null && _firstErrorByName$_el !== void 0 ? _firstErrorByName$_el : ''); | ||
element.setCustomValidity((_firstErrorByName$ele = firstErrorByName[element.name]) !== null && _firstErrorByName$ele !== void 0 ? _firstErrorByName$ele : ''); | ||
} | ||
return form.reportValidity(); | ||
} | ||
@@ -87,112 +90,142 @@ function setValue(target, paths, valueFn) { | ||
} | ||
function flatten(data) { | ||
var prefix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; | ||
var entries = []; | ||
function requestSubmit(form, submitter) { | ||
var submitEvent = new SubmitEvent('submit', { | ||
bubbles: true, | ||
cancelable: true, | ||
submitter | ||
}); | ||
form.dispatchEvent(submitEvent); | ||
} | ||
function requestValidate(form, field) { | ||
var button = document.createElement('button'); | ||
button.name = 'conform/validate'; | ||
button.value = field !== null && field !== void 0 ? field : ''; | ||
button.hidden = true; | ||
form.appendChild(button); | ||
requestSubmit(form, button); | ||
form.removeChild(button); | ||
} | ||
function getFormElement(element) { | ||
var form = element instanceof HTMLFormElement ? element : element === null || element === void 0 ? void 0 : element.form; | ||
if (typeof data === 'string' || typeof data === 'undefined' || data instanceof File) { | ||
entries.push([prefix, data !== null && data !== void 0 ? data : '']); | ||
} else if (Array.isArray(data)) { | ||
for (var i = 0; i < data.length; i++) { | ||
entries.push(...flatten(data[i], "".concat(prefix, "[").concat(i, "]"))); | ||
} | ||
} else { | ||
for (var [key, value] of Object.entries(Object(data))) { | ||
entries.push(...flatten(value, prefix ? "".concat(prefix, ".").concat(key) : key)); | ||
} | ||
if (!form) { | ||
return null; | ||
} | ||
return entries; | ||
return form; | ||
} | ||
function unflatten(entries) { | ||
var result = {}; | ||
function focusFirstInvalidField(form, fields) { | ||
var currentFocus = document.activeElement; | ||
var _loop = function _loop(key, value) { | ||
var paths = getPaths(key); | ||
setValue(result, paths, prev => { | ||
if (prev) { | ||
throw new Error('Entry with the same name is not supported'); | ||
if (!isFieldElement(currentFocus) || currentFocus.tagName !== 'BUTTON' || currentFocus.form !== form) { | ||
return; | ||
} | ||
for (var field of form.elements) { | ||
if (isFieldElement(field)) { | ||
// Focus on the first non button field | ||
if (!field.validity.valid && field.dataset.conformTouched && field.tagName !== 'BUTTON' && (!fields || fields.includes(field.name))) { | ||
field.focus(); | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
function getSubmissionType(name) { | ||
var prefix = 'conform/'; | ||
return value; | ||
}); | ||
}; | ||
for (var [key, value] of entries) { | ||
_loop(key, value); | ||
if (!name.startsWith(prefix) || name.length <= prefix.length) { | ||
return null; | ||
} | ||
return result; | ||
return name.slice(prefix.length); | ||
} | ||
function createSubmission(payload) { | ||
var value = {}; | ||
function parse(payload) { | ||
var submission = { | ||
value: {}, | ||
error: [], | ||
scope: [''] | ||
}; | ||
try { | ||
var modifiedPayload = applyListCommand(payload); | ||
value = unflatten(modifiedPayload.entries()); | ||
var _loop = function _loop(name, value) { | ||
var submissionType = getSubmissionType(name); | ||
if (payload !== modifiedPayload) { | ||
return { | ||
state: 'modified', | ||
form: { | ||
value, | ||
error: {} | ||
if (submissionType) { | ||
if (typeof value !== 'string') { | ||
throw new Error('The conform command could not be used on a file input'); | ||
} | ||
}; | ||
} | ||
} catch (e) { | ||
return { | ||
state: 'rejected', | ||
form: { | ||
value, | ||
error: { | ||
message: e instanceof Error ? e.message : 'Submission failed' | ||
if (typeof submission.type !== 'undefined') { | ||
throw new Error('The conform command could only be set on a button'); | ||
} | ||
submission = _objectSpread2(_objectSpread2({}, submission), {}, { | ||
type: submissionType, | ||
data: value | ||
}); | ||
} else { | ||
var paths = getPaths(name); | ||
var scopes = paths.reduce((result, path) => { | ||
if (result.length === 0) { | ||
if (typeof path !== 'string') { | ||
throw new Error("Invalid name received: ".concat(name)); | ||
} | ||
result.push(path); | ||
} else { | ||
var [lastName] = result.slice(-1); | ||
result.push(getName([lastName, path])); | ||
} | ||
return result; | ||
}, []); | ||
submission.scope.push(...scopes); | ||
setValue(submission.value, paths, prev => { | ||
if (prev) { | ||
throw new Error('Entry with the same name is not supported'); | ||
} | ||
return value; | ||
}); | ||
} | ||
}; | ||
} | ||
return { | ||
state: 'accepted', | ||
data: value, | ||
form: { | ||
value, | ||
error: {} | ||
for (var [name, value] of payload.entries()) { | ||
_loop(name, value); | ||
} | ||
}; | ||
} | ||
function createValidate(handler) { | ||
return (form, submitter) => { | ||
var formData = getFormData(form, submitter); | ||
for (var _field of form.elements) { | ||
if (isFieldElement(_field)) { | ||
handler(_field, formData); | ||
} | ||
switch (submission.type) { | ||
case 'validate': | ||
if (typeof submission.data !== 'undefined' && submission.data !== '') { | ||
submission.scope = [submission.data]; | ||
} | ||
break; | ||
case 'list': | ||
submission = handleList(submission); | ||
break; | ||
} | ||
}; | ||
} catch (e) { | ||
submission.error.push(['', e instanceof Error ? e.message : 'Invalid payload received']); | ||
} // Remove duplicates | ||
submission.scope = Array.from(new Set(submission.scope)); | ||
return submission; | ||
} | ||
function getFormElement(element) { | ||
var form = element instanceof HTMLFormElement ? element : element === null || element === void 0 ? void 0 : element.form; | ||
function parseListCommand(data) { | ||
try { | ||
var command = JSON.parse(data); | ||
if (!form) { | ||
return null; | ||
if (typeof command.type !== 'string' || !['prepend', 'append', 'replace', 'remove', 'reorder'].includes(command.type)) { | ||
throw new Error('Unsupported list command type'); | ||
} | ||
return command; | ||
} catch (error) { | ||
throw new Error("Invalid list command: \"".concat(data, "\"; ").concat(error)); | ||
} | ||
return form; | ||
} | ||
var listCommandKey = '__conform__'; | ||
function serializeListCommand(name, _ref) { | ||
var { | ||
type, | ||
payload | ||
} = _ref; | ||
return [name, type, JSON.stringify(payload)].join('::'); | ||
} | ||
function parseListCommand(serialized) { | ||
var [name, type, json] = serialized.split('::'); | ||
return [name, { | ||
type: type, | ||
payload: JSON.parse(json) | ||
}]; | ||
} | ||
function updateList(list, command) { | ||
@@ -227,3 +260,3 @@ switch (command.type) { | ||
default: | ||
throw new Error('Invalid list command'); | ||
throw new Error('Unknown list command received'); | ||
} | ||
@@ -233,44 +266,21 @@ | ||
} | ||
function applyListCommand(payload) { | ||
var command = payload.get(listCommandKey); | ||
if (!command) { | ||
return payload; | ||
function handleList(submission) { | ||
if (submission.type !== 'list') { | ||
return submission; | ||
} | ||
payload.delete(listCommandKey); | ||
if (command instanceof File) { | ||
throw new Error("The \"".concat(listCommandKey, "\" key could not be used for file upload")); | ||
} | ||
var result = new FormData(); | ||
var entries = []; | ||
var [key, listCommand] = parseListCommand(command); | ||
for (var [name, value] of payload) { | ||
if (name.startsWith(key)) { | ||
entries.push([name.replace(key, 'list'), value]); | ||
} else { | ||
result.append(name, value); | ||
var command = parseListCommand(submission.data); | ||
var paths = getPaths(command.scope); | ||
setValue(submission.value, paths, list => { | ||
if (!Array.isArray(list)) { | ||
throw new Error('The list command can only be applied to a list'); | ||
} | ||
} | ||
var { | ||
list | ||
} = unflatten(entries); | ||
if (!Array.isArray(list)) { | ||
throw new Error('The list command can only be applied to a list'); | ||
} | ||
updateList(list, listCommand); | ||
for (var [_name, _value] of flatten(list, key)) { | ||
result.append(_name, _value); | ||
} | ||
return result; | ||
return updateList(list, command); | ||
}); | ||
return _objectSpread2(_objectSpread2({}, submission), {}, { | ||
scope: [command.scope] | ||
}); | ||
} | ||
export { applyListCommand, createSubmission, createValidate, flatten, getFormData, getFormElement, getKey, getName, getPaths, isFieldElement, listCommandKey, parseListCommand, serializeListCommand, setFormError, setValue, unflatten, updateList }; | ||
export { focusFirstInvalidField, getFormData, getFormElement, getName, getPaths, getSubmissionType, handleList, hasError, isFieldElement, parse, parseListCommand, reportValidity, requestSubmit, requestValidate, setValue, updateList }; |
@@ -5,3 +5,3 @@ { | ||
"license": "MIT", | ||
"version": "0.3.1", | ||
"version": "0.4.0-pre.0", | ||
"main": "index.js", | ||
@@ -8,0 +8,0 @@ "module": "module/index.js", |
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
24779
644