@felte/react
Advanced tools
Comparing version 1.0.0-next.0 to 1.0.0-next.1
@@ -32,4 +32,3 @@ import { Obj, Errors, Touched, TransWritable, CreateSubmitHandlerConfig, KnownHelpers, UnknownHelpers, FormConfigWithTransformFn, FormConfigWithoutTransformFn } from "@felte/core"; | ||
declare function useForm<Data extends Obj = Obj, Ext extends Obj = Obj>(config?: FormConfigWithoutTransformFn<Data> & Ext): Form<Data> & KnownHelpers<Data> & KnownStores<Data>; | ||
export { FelteSubmitError } from '@felte/core'; | ||
export { useAccessor, useForm }; | ||
//# sourceMappingURL=index.d.ts.map |
@@ -7,2 +7,67 @@ 'use strict'; | ||
function noop() { } | ||
function safe_not_equal(a, b) { | ||
return a != a ? b == b : a !== b || ((a && typeof a === 'object') || typeof a === 'function'); | ||
} | ||
function subscribe$1(store, ...callbacks) { | ||
if (store == null) { | ||
return noop; | ||
} | ||
const unsub = store.subscribe(...callbacks); | ||
return unsub.unsubscribe ? () => unsub.unsubscribe() : unsub; | ||
} | ||
function get_store_value(store) { | ||
let value; | ||
subscribe$1(store, _ => value = _)(); | ||
return value; | ||
} | ||
const subscriber_queue = []; | ||
/** | ||
* Create a `Writable` store that allows both updating and reading by subscription. | ||
* @param {*=}value initial value | ||
* @param {StartStopNotifier=}start start and stop notifications for subscriptions | ||
*/ | ||
function writable(value, start = noop) { | ||
let stop; | ||
const subscribers = new Set(); | ||
function set(new_value) { | ||
if (safe_not_equal(value, new_value)) { | ||
value = new_value; | ||
if (stop) { // store is ready | ||
const run_queue = !subscriber_queue.length; | ||
for (const subscriber of subscribers) { | ||
subscriber[1](); | ||
subscriber_queue.push(subscriber, value); | ||
} | ||
if (run_queue) { | ||
for (let i = 0; i < subscriber_queue.length; i += 2) { | ||
subscriber_queue[i][0](subscriber_queue[i + 1]); | ||
} | ||
subscriber_queue.length = 0; | ||
} | ||
} | ||
} | ||
} | ||
function update(fn) { | ||
set(fn(value)); | ||
} | ||
function subscribe(run, invalidate = noop) { | ||
const subscriber = [run, invalidate]; | ||
subscribers.add(subscriber); | ||
if (subscribers.size === 1) { | ||
stop = start(set) || noop; | ||
} | ||
run(value); | ||
return () => { | ||
subscribers.delete(subscriber); | ||
if (subscribers.size === 0) { | ||
stop(); | ||
stop = null; | ||
} | ||
}; | ||
} | ||
return { set, update, subscribe }; | ||
} | ||
/** @ignore */ | ||
@@ -489,3 +554,3 @@ function _some(obj, pred) { | ||
function subscribe$1(store, ...callbacks) { | ||
function subscribe(store, ...callbacks) { | ||
const unsub = store.subscribe(...callbacks); | ||
@@ -496,24 +561,130 @@ return unsub.unsubscribe ? () => unsub.unsubscribe() : unsub; | ||
let value = undefined; | ||
subscribe$1(store, (_) => (value = _))(); | ||
subscribe(store, (_) => (value = _))(); | ||
return value; | ||
} | ||
class FelteSubmitError extends Error { | ||
constructor(message, response) { | ||
super(message); | ||
this.name = 'FelteSubmitError'; | ||
this.response = response; | ||
function isUpdater(value) { | ||
return typeof value === 'function'; | ||
} | ||
function createSetHelper(storeSetter) { | ||
const setHelper = (pathOrValue, valueOrUpdater) => { | ||
if (typeof pathOrValue === 'string') { | ||
const path = pathOrValue; | ||
storeSetter((oldValue) => { | ||
const newValue = isUpdater(valueOrUpdater) | ||
? valueOrUpdater(_get(oldValue, path)) | ||
: valueOrUpdater; | ||
return _set(oldValue, path, newValue); | ||
}); | ||
} | ||
else { | ||
storeSetter((oldValue) => isUpdater(pathOrValue) ? pathOrValue(oldValue) : pathOrValue); | ||
} | ||
}; | ||
return setHelper; | ||
} | ||
function createHelpers({ stores, config, }) { | ||
var _a; | ||
const { data, touched, errors, warnings, isDirty, isSubmitting } = stores; | ||
const setData = createSetHelper(data.update); | ||
const setTouched = createSetHelper(touched.update); | ||
const setErrors = createSetHelper(errors.update); | ||
const setWarnings = createSetHelper(warnings.update); | ||
function updateFields(updater) { | ||
setData((oldData) => { | ||
const newData = updater(oldData); | ||
if (formNode) | ||
setForm(formNode, newData); | ||
return newData; | ||
}); | ||
} | ||
const setFields = (pathOrValue, valueOrUpdater, shouldTouch) => { | ||
const fieldsSetter = createSetHelper(updateFields); | ||
fieldsSetter(pathOrValue, valueOrUpdater); | ||
if (typeof pathOrValue === 'string' && shouldTouch) { | ||
setTouched(pathOrValue, true); | ||
} | ||
}; | ||
function unsetField(path) { | ||
data.update(($data) => { | ||
const newData = _unset($data, path); | ||
if (formNode) | ||
setForm(formNode, newData); | ||
return newData; | ||
}); | ||
touched.update(($touched) => { | ||
return _unset($touched, path); | ||
}); | ||
errors.update(($errors) => { | ||
return _unset($errors, path); | ||
}); | ||
warnings.update(($warnings) => { | ||
return _unset($warnings, path); | ||
}); | ||
} | ||
function resetField(path) { | ||
const initialValue = _get(initialValues, path); | ||
data.update(($data) => { | ||
const newData = _set($data, path, initialValue); | ||
if (formNode) | ||
setForm(formNode, newData); | ||
return newData; | ||
}); | ||
touched.update(($touched) => { | ||
return _set($touched, path, false); | ||
}); | ||
errors.update(($errors) => { | ||
return _set($errors, path, null); | ||
}); | ||
warnings.update(($warnings) => { | ||
return _set($warnings, path, null); | ||
}); | ||
} | ||
const setIsSubmitting = createSetHelper(isSubmitting.update); | ||
const setIsDirty = createSetHelper(isDirty.update); | ||
async function validate() { | ||
const currentData = get(data); | ||
setTouched((t) => { | ||
return deepSet(t, true); | ||
}); | ||
const currentErrors = await executeValidation(currentData, config.validate); | ||
const currentWarnings = await executeValidation(currentData, config.warn); | ||
warnings.set(_merge(deepSet(currentData, null), currentWarnings || {})); | ||
errors.set(currentErrors || {}); | ||
return currentErrors; | ||
} | ||
let formNode; | ||
let initialValues = ((_a = config.initialValues) !== null && _a !== void 0 ? _a : {}); | ||
function reset() { | ||
setFields(_cloneDeep(initialValues)); | ||
setTouched(($touched) => deepSet($touched, false)); | ||
isDirty.set(false); | ||
} | ||
return { | ||
public: { | ||
setData, | ||
setFields, | ||
setTouched, | ||
setErrors, | ||
setWarnings, | ||
setIsSubmitting, | ||
setIsDirty, | ||
validate, | ||
reset, | ||
unsetField, | ||
resetField, | ||
setInitialValues: (values) => { | ||
initialValues = values; | ||
}, | ||
}, | ||
private: { | ||
_setFormNode: (node) => { | ||
formNode = node; | ||
}, | ||
_getFormNode: () => formNode, | ||
_getInitialValues: () => initialValues, | ||
}, | ||
}; | ||
} | ||
async function defaultOnSubmit(form, values) { | ||
const { action, method } = form; | ||
const response = await fetch(action, { | ||
method, | ||
body: JSON.stringify(values), | ||
headers: { 'Content-Type': 'application/json' }, | ||
}); | ||
if (response.ok) | ||
return; | ||
throw new FelteSubmitError('An error occurred while the form was being submitted.', await response.json().catch(() => undefined)); | ||
} | ||
function createFormAction({ helpers, stores, config, extender, _setFormNode, _getFormNode, _getInitialValues, _setCurrentExtenders, _getCurrentExtenders, }) { | ||
@@ -529,5 +700,5 @@ const { setFields, setTouched, reset, validate, addValidator, addWarnValidator, addTransformer, setInitialValues, } = helpers; | ||
return async function handleSubmit(event) { | ||
if (!onSubmit) | ||
return; | ||
const formNode = _getFormNode(); | ||
if (!formNode && !onSubmit) | ||
return; | ||
event === null || event === void 0 ? void 0 : event.preventDefault(); | ||
@@ -559,12 +730,7 @@ isSubmitting.set(true); | ||
try { | ||
if (onSubmit) { | ||
await onSubmit(currentData, { | ||
form: formNode, | ||
controls: formNode && Array.from(formNode.elements).filter(isFormControl), | ||
config: Object.assign(Object.assign({}, config), altConfig), | ||
}); | ||
} | ||
else if (formNode) { | ||
await defaultOnSubmit(formNode, currentData); | ||
} | ||
await onSubmit(currentData, { | ||
form: formNode, | ||
controls: formNode && Array.from(formNode.elements).filter(isFormControl), | ||
config: Object.assign(Object.assign({}, config), altConfig), | ||
}); | ||
} | ||
@@ -862,126 +1028,2 @@ catch (e) { | ||
function isUpdater(value) { | ||
return typeof value === 'function'; | ||
} | ||
function createSetHelper(storeSetter) { | ||
const setHelper = (pathOrValue, valueOrUpdater) => { | ||
if (typeof pathOrValue === 'string') { | ||
const path = pathOrValue; | ||
storeSetter((oldValue) => { | ||
const newValue = isUpdater(valueOrUpdater) | ||
? valueOrUpdater(_get(oldValue, path)) | ||
: valueOrUpdater; | ||
return _set(oldValue, path, newValue); | ||
}); | ||
} | ||
else { | ||
storeSetter((oldValue) => isUpdater(pathOrValue) ? pathOrValue(oldValue) : pathOrValue); | ||
} | ||
}; | ||
return setHelper; | ||
} | ||
function createHelpers({ stores, config, }) { | ||
var _a; | ||
const { data, touched, errors, warnings, isDirty, isSubmitting } = stores; | ||
const setData = createSetHelper(data.update); | ||
const setTouched = createSetHelper(touched.update); | ||
const setErrors = createSetHelper(errors.update); | ||
const setWarnings = createSetHelper(warnings.update); | ||
function updateFields(updater) { | ||
setData((oldData) => { | ||
const newData = updater(oldData); | ||
if (formNode) | ||
setForm(formNode, newData); | ||
return newData; | ||
}); | ||
} | ||
const setFields = (pathOrValue, valueOrUpdater, shouldTouch) => { | ||
const fieldsSetter = createSetHelper(updateFields); | ||
fieldsSetter(pathOrValue, valueOrUpdater); | ||
if (typeof pathOrValue === 'string' && shouldTouch) { | ||
setTouched(pathOrValue, true); | ||
} | ||
}; | ||
function unsetField(path) { | ||
data.update(($data) => { | ||
const newData = _unset($data, path); | ||
if (formNode) | ||
setForm(formNode, newData); | ||
return newData; | ||
}); | ||
touched.update(($touched) => { | ||
return _unset($touched, path); | ||
}); | ||
errors.update(($errors) => { | ||
return _unset($errors, path); | ||
}); | ||
warnings.update(($warnings) => { | ||
return _unset($warnings, path); | ||
}); | ||
} | ||
function resetField(path) { | ||
const initialValue = _get(initialValues, path); | ||
data.update(($data) => { | ||
const newData = _set($data, path, initialValue); | ||
if (formNode) | ||
setForm(formNode, newData); | ||
return newData; | ||
}); | ||
touched.update(($touched) => { | ||
return _set($touched, path, false); | ||
}); | ||
errors.update(($errors) => { | ||
return _set($errors, path, null); | ||
}); | ||
warnings.update(($warnings) => { | ||
return _set($warnings, path, null); | ||
}); | ||
} | ||
const setIsSubmitting = createSetHelper(isSubmitting.update); | ||
const setIsDirty = createSetHelper(isDirty.update); | ||
async function validate() { | ||
const currentData = get(data); | ||
setTouched((t) => { | ||
return deepSet(t, true); | ||
}); | ||
const currentErrors = await executeValidation(currentData, config.validate); | ||
const currentWarnings = await executeValidation(currentData, config.warn); | ||
warnings.set(_merge(deepSet(currentData, null), currentWarnings || {})); | ||
errors.set(currentErrors || {}); | ||
return currentErrors; | ||
} | ||
let formNode; | ||
let initialValues = ((_a = config.initialValues) !== null && _a !== void 0 ? _a : {}); | ||
function reset() { | ||
setFields(_cloneDeep(initialValues)); | ||
setTouched(($touched) => deepSet($touched, false)); | ||
isDirty.set(false); | ||
} | ||
return { | ||
public: { | ||
setData, | ||
setFields, | ||
setTouched, | ||
setErrors, | ||
setWarnings, | ||
setIsSubmitting, | ||
setIsDirty, | ||
validate, | ||
reset, | ||
unsetField, | ||
resetField, | ||
setInitialValues: (values) => { | ||
initialValues = values; | ||
}, | ||
}, | ||
private: { | ||
_setFormNode: (node) => { | ||
formNode = node; | ||
}, | ||
_getFormNode: () => formNode, | ||
_getInitialValues: () => initialValues, | ||
}, | ||
}; | ||
} | ||
function errorFilterer(errValue, touchValue) { | ||
@@ -1201,67 +1243,2 @@ if (_isPlainObject(touchValue)) | ||
function noop() { } | ||
function safe_not_equal(a, b) { | ||
return a != a ? b == b : a !== b || ((a && typeof a === 'object') || typeof a === 'function'); | ||
} | ||
function subscribe(store, ...callbacks) { | ||
if (store == null) { | ||
return noop; | ||
} | ||
const unsub = store.subscribe(...callbacks); | ||
return unsub.unsubscribe ? () => unsub.unsubscribe() : unsub; | ||
} | ||
function get_store_value(store) { | ||
let value; | ||
subscribe(store, _ => value = _)(); | ||
return value; | ||
} | ||
const subscriber_queue = []; | ||
/** | ||
* Create a `Writable` store that allows both updating and reading by subscription. | ||
* @param {*=}value initial value | ||
* @param {StartStopNotifier=}start start and stop notifications for subscriptions | ||
*/ | ||
function writable(value, start = noop) { | ||
let stop; | ||
const subscribers = new Set(); | ||
function set(new_value) { | ||
if (safe_not_equal(value, new_value)) { | ||
value = new_value; | ||
if (stop) { // store is ready | ||
const run_queue = !subscriber_queue.length; | ||
for (const subscriber of subscribers) { | ||
subscriber[1](); | ||
subscriber_queue.push(subscriber, value); | ||
} | ||
if (run_queue) { | ||
for (let i = 0; i < subscriber_queue.length; i += 2) { | ||
subscriber_queue[i][0](subscriber_queue[i + 1]); | ||
} | ||
subscriber_queue.length = 0; | ||
} | ||
} | ||
} | ||
} | ||
function update(fn) { | ||
set(fn(value)); | ||
} | ||
function subscribe(run, invalidate = noop) { | ||
const subscriber = [run, invalidate]; | ||
subscribers.add(subscriber); | ||
if (subscribers.size === 1) { | ||
stop = start(set) || noop; | ||
} | ||
run(value); | ||
return () => { | ||
subscribers.delete(subscriber); | ||
if (subscribers.size === 0) { | ||
stop(); | ||
stop = null; | ||
} | ||
}; | ||
} | ||
return { set, update, subscribe }; | ||
} | ||
function isWritable(store) { | ||
@@ -1395,5 +1372,4 @@ return !!store.set; | ||
exports.FelteSubmitError = FelteSubmitError; | ||
exports.useAccessor = useAccessor; | ||
exports.useForm = useForm; | ||
//# sourceMappingURL=index.js.map |
{ | ||
"name": "@felte/react", | ||
"version": "1.0.0-next.0", | ||
"version": "1.0.0-next.1", | ||
"description": "An extensible form library for ReactJS", | ||
@@ -29,3 +29,3 @@ "main": "dist/index.js", | ||
"dependencies": { | ||
"@felte/core": "1.0.0-next.0", | ||
"@felte/core": "1.0.0-next.1", | ||
"svelte": "^3.44.3" | ||
@@ -63,3 +63,3 @@ }, | ||
}, | ||
"readme": "# @felte/react\n\n[](https://bundlephobia.com/result?p=@felte/react)\n[](https://www.npmjs.com/package/@felte/react)\n\nFelte is an extensible form library originally built for Svelte but easily integrated with React using this package. Felte, on its most simple form, only requires you to set a `ref` to your form element to work. No custom `Field`or `Form` components are needed, making custom styles really easy to do. You can see it in action in this [CodeSandbox demo](https://codesandbox.io/s/felte-react-demo-q2xxw?file=/src/App.js)\n\n## Features\n\n- Single action to make your form reactive.\n- Use HTML5 native elements to create your form. (Only the `name` attribute is necessary).\n- No re-renders at all unless you need to use a specific field's value within your component.\n- Provides stores and helper functions to handle more complex use cases.\n- No assumptions on your validation strategy. Use any validation library you want or write your own strategy.\n- Handles addition and removal of form controls during runtime.\n- Official solutions for error reporting using `reporter` packages.\n- Well tested. Currently at [99% code coverage](https://app.codecov.io/gh/pablo-abc/felte) and constantly working on improving test quality.\n- Supports validation with [yup](./packages/validator-yup/README.md), [zod](./packages/validator-zod/README.md) and [superstruct](./packages/validator-superstruct/README.md).\n- Easily [extend its functionality](https://felte.dev/docs/react/extending-felte).\n\n## Simple ussage example\n\n```jsx\nimport React, { useEffect } from 'react';\nimport { useForm } from '@felte/react';\n\nfunction Form() {\n const { form } = useForm({\n onSubmit: (values) => console.log(values),\n });\n\n return (\n <form ref={form}>\n <input name=\"email\" />\n <input name=\"password\" type=\"password\" />\n <button type=\"submit\">Submit</button>\n </form>\n );\n}\n```\n\nIf your `onSubmit` would only require you to send your data to a server (either via `POST` or `GET`) you don't even need an `onSubmit` handler by using the `action` and `method` attributes:\n\n```jsx\nimport React, { useEffect } from 'react';\nimport { useForm } from '@felte/react';\n\nfunction Form() {\n const { form } = useForm();\n\n return (\n <form ref={form} action=\"/example-signin\" method=\"post\">\n <input name=\"email\" />\n <input name=\"password\" type=\"password\" />\n <button type=\"submit\">Submit</button>\n </form>\n );\n}\n```\n\n## Installation\n\n```sh\nnpm install --save @felte/react\n\n# Or, if you use yarn\n\nyarn add @felte/react\n```\n\n## Usage\n\nTo learn more about how to use `@felte/react` to handle your forms, check the [official documentation](https://felte.dev/docs/react/getting-started).\n" | ||
"readme": "# @felte/react\n\n[](https://bundlephobia.com/result?p=@felte/react)\n[](https://www.npmjs.com/package/@felte/react)\n\nFelte is an extensible form library originally built for Svelte but easily integrated with React using this package. Felte, on its most simple form, only requires you to set a `ref` to your form element to work. No custom `Field`or `Form` components are needed, making custom styles really easy to do. You can see it in action in this [CodeSandbox demo](https://codesandbox.io/s/felte-react-demo-q2xxw?file=/src/App.js)\n\n## Features\n\n- Single action to make your form reactive.\n- Use HTML5 native elements to create your form. (Only the `name` attribute is necessary).\n- No re-renders at all unless you need to use a specific field's value within your component.\n- Provides stores and helper functions to handle more complex use cases.\n- No assumptions on your validation strategy. Use any validation library you want or write your own strategy.\n- Handles addition and removal of form controls during runtime.\n- Official solutions for error reporting using `reporter` packages.\n- Well tested. Currently at [99% code coverage](https://app.codecov.io/gh/pablo-abc/felte) and constantly working on improving test quality.\n- Supports validation with [yup](./packages/validator-yup/README.md), [zod](./packages/validator-zod/README.md) and [superstruct](./packages/validator-superstruct/README.md).\n- Easily [extend its functionality](https://felte.dev/docs/react/extending-felte).\n\n## Simple ussage example\n\n```jsx\nimport React, { useEffect } from 'react';\nimport { useForm } from '@felte/react';\n\nfunction Form() {\n const { form } = useForm({\n onSubmit: (values) => console.log(values),\n });\n\n return (\n <form ref={form}>\n <input name=\"email\" />\n <input name=\"password\" type=\"password\" />\n <button type=\"submit\">Submit</button>\n </form>\n );\n}\n```\n\n## Installation\n\n```sh\nnpm install --save @felte/react\n\n# Or, if you use yarn\n\nyarn add @felte/react\n```\n\n## Usage\n\nTo learn more about how to use `@felte/react` to handle your forms, check the [official documentation](https://felte.dev/docs/react/getting-started).\n" | ||
} |
@@ -42,21 +42,2 @@ # @felte/react | ||
If your `onSubmit` would only require you to send your data to a server (either via `POST` or `GET`) you don't even need an `onSubmit` handler by using the `action` and `method` attributes: | ||
```jsx | ||
import React, { useEffect } from 'react'; | ||
import { useForm } from '@felte/react'; | ||
function Form() { | ||
const { form } = useForm(); | ||
return ( | ||
<form ref={form} action="/example-signin" method="post"> | ||
<input name="email" /> | ||
<input name="password" type="password" /> | ||
<button type="submit">Submit</button> | ||
</form> | ||
); | ||
} | ||
``` | ||
## Installation | ||
@@ -63,0 +44,0 @@ |
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
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
0
493956
2691
55
+ Added@felte/core@1.0.0-next.1(transitive)
- Removed@felte/core@1.0.0-next.0(transitive)
Updated@felte/core@1.0.0-next.1