Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@blockle/form

Package Overview
Dependencies
Maintainers
1
Versions
21
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@blockle/form - npm Package Compare versions

Comparing version 0.0.1-alpha.5 to 0.0.1-alpha.6

dist/Form.spec.d.ts

318

dist/blockle-form.cjs.js

@@ -15,163 +15,201 @@ /**

var FormContext = React__default.createContext({
register: function () {
throw new Error('Forgot to wrap form element in <Form /> component?');
},
subscribe: function () {
throw new Error('Forgot to wrap form element in <Form /> component?');
},
notify: function () {
throw new Error('Forgot to wrap form element in <Form /> component?');
},
const FormContext = React__default.createContext({
getState: () => ({}),
dispatch: () => { },
subscribe: () => () => { },
});
//# sourceMappingURL=context.js.map
var Form = function (_a) {
var autocomplete = _a.autocomplete, children = _a.children, className = _a.className, _b = _a.noValidate, noValidate = _b === void 0 ? true : _b, onSubmit = _a.onSubmit;
// Create mutatable state
var state = React.useMemo(function () { return new Map(); }, []);
var listeners = React.useMemo(function () { return []; }, []);
var context = {
register: function (_a) {
var name = _a.name, stateRef = _a.stateRef, validate = _a.validate;
state.set(name, [stateRef, validate]);
return function () {
state.delete(name);
const initialState = {};
const formReducer = (state = initialState, action) => {
switch (action.type) {
case 'INIT':
return {
...state,
[action.payload.name]: {
name: action.payload.name,
dirty: false,
touched: false,
validationMessage: action.payload.state.validationMessage,
value: action.payload.state.value,
},
};
},
subscribe: function (listener) {
listeners.push(listener);
return function () {
var index = listeners.indexOf(listener);
listeners.splice(index, 1);
case 'UPDATE_FIELD':
return {
...state,
[action.payload.name]: {
...state[action.payload.name],
...action.payload.state,
},
};
},
notify: function (name, state) {
listeners.forEach(function (listener) { return listener(name, state); });
},
case 'SET_TOUCHED':
return {
...state,
[action.payload.name]: {
...state[action.payload.name],
touched: true,
},
};
case 'REMOVE_FIELD':
const nextState = { ...state };
delete nextState[action.payload];
return nextState;
default:
return state;
}
};
//# sourceMappingURL=reducer.js.map
const createStore = () => {
let currentState = {};
const listeners = [];
const getState = () => currentState;
const subscribe = (listener) => {
listeners.push(listener);
return () => {
const index = listeners.indexOf(listener);
listeners.splice(index, 1);
};
};
var submit = function (event) {
var isValid = true;
event.preventDefault();
state.forEach(function (_a) {
var validate = _a[1];
if (!validate()) {
isValid = false;
}
});
if (!isValid) {
console.log('Form invalid');
return;
}
var formData = {};
state.forEach(function (_a, name) {
var stateRef = _a[0];
formData[name] = stateRef.current.value;
});
onSubmit(formData);
const dispatch = (action) => {
currentState = formReducer(currentState, action);
listeners.forEach(listener => listener());
};
return (React__default.createElement(FormContext.Provider, { value: context },
React__default.createElement("form", { className: className, onSubmit: submit, autoComplete: autocomplete ? 'on' : 'off', noValidate: noValidate }, children)));
return {
getState,
subscribe,
dispatch,
};
};
//# sourceMappingURL=createStore.js.map
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
var __assign = function() {
__assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
const getFormData = (state) => {
const values = Object.values(state).map(({ name, value }) => ({ name, value }));
const formData = {};
values.forEach(({ name, value }) => {
formData[name] = value;
});
return formData;
};
const isFormInvalid = (state) => Object.values(state).some(({ validationMessage }) => validationMessage !== null);
//# sourceMappingURL=selectors.js.map
var createInitialState = function (value) { return ({
dirty: false,
invalid: false,
touched: false,
validationMessage: '',
value: value,
}); };
var useForm = function (_a) {
var name = _a.name, value = _a.value, validate = _a.validate;
var form = React.useContext(FormContext);
var _b = React.useState(createInitialState(value)), state = _b[0], setState = _b[1];
var stateRef = React.useRef(state);
stateRef.current = state;
React.useEffect(function () {
return form.register({
name: name,
stateRef: stateRef,
validate: function () {
var state = stateRef.current;
var validity = validator(state.value, true);
var nextState = __assign({}, state, { touched: true, invalid: !!validity, validationMessage: validity || '' });
setState(nextState);
form.notify(name, nextState);
return !validity;
},
});
}, [name]);
React.useEffect(function () {
setValue(value);
}, [JSON.stringify(value)]);
function validator(value, force) {
if (force === void 0) { force = false; }
if (!validate) {
return null;
const Form = ({ render, className, autocomplete, onSubmit, noValidate = true }) => {
const store = React.useMemo(() => createStore(), []);
const [submitting, setSubmitting] = React.useState(false);
const [invalid, setInvalid] = React.useState(false);
// Listen to store updates to set validity
React.useEffect(() => {
const listener = () => {
const state = store.getState();
const isInvalid = isFormInvalid(state);
setInvalid(isInvalid);
};
listener();
return store.subscribe(() => listener());
}, []);
function submit(event) {
event.preventDefault();
const state = store.getState();
const formData = getFormData(state);
const isInvalid = isFormInvalid(state);
if (isInvalid) {
setInvalid(true);
return;
}
if (force) {
return validate ? validate(value) : null;
setSubmitting(true);
const result = onSubmit(formData);
// TODO Use await and ship without polyfill?
if (result && result.then) {
result.then(() => setSubmitting(false));
}
return (state.touched || state.dirty) && validate ? validate(value) : null;
else {
setSubmitting(false);
}
}
function setValue(value) {
var validity = validator(value);
var nextState = __assign({}, state, { value: value, invalid: !!validity, validationMessage: validity || '', dirty: value !== state.value });
setState(nextState);
// Emit change
form.notify(name, nextState);
return (React__default.createElement(FormContext.Provider, { value: store },
React__default.createElement("form", { className: className, onSubmit: submit, autoComplete: autocomplete ? 'on' : 'off', noValidate: noValidate }, render({ submitting, invalid }))));
};
//# sourceMappingURL=Form.js.map
const createActionWithPayload = (type, payload) => ({
type,
payload,
});
// Initialize field state
const initField = (name, state) => createActionWithPayload('INIT', { name, state });
// Update field state
const updateField = (name, state) => createActionWithPayload('UPDATE_FIELD', { name, state });
// Field is touched
const setTouched = (name) => createActionWithPayload('SET_TOUCHED', { name });
// Remove field state
const removeField = (name) => createActionWithPayload('REMOVE_FIELD', name);
//# sourceMappingURL=actions.js.map
const stateDidChange = (state, prevState) => {
if (state.value !== prevState.value ||
state.dirty !== prevState.dirty ||
state.touched !== prevState.touched ||
state.validationMessage !== prevState.validationMessage) {
return true;
}
function setTouched() {
setState(__assign({}, state, { touched: true }));
}
return __assign({}, state, { setValue: setValue, setTouched: setTouched });
return false;
};
var useFormField = function (target) {
var context = React.useContext(FormContext);
var _a = React.useState({
const useField = (name, options) => {
const store = React.useContext(FormContext);
const [state, setState] = React.useState({
name,
dirty: false,
invalid: false,
touched: false,
validationMessage: '',
value: null,
}), state = _a[0], setState = _a[1];
React.useEffect(function () {
return context.subscribe(function (name, state) {
if (name !== target) {
return;
validationMessage: null,
value: options.value,
});
const currentState = React.useRef(state);
// Update value whenever value (given by props) changes
React.useEffect(() => {
store.dispatch(updateField(name, {
value: options.value,
dirty: false,
validationMessage: options.validate(options.value),
}));
}, [options.value]);
React.useEffect(() => {
// Update local state
const unsubscribe = store.subscribe(() => {
const prevState = currentState.current;
const nextState = store.getState()[name];
if (prevState && nextState && stateDidChange(nextState, prevState)) {
setState(nextState);
currentState.current = nextState;
}
setState(state);
});
}, []);
return state;
store.dispatch(initField(name, {
value: options.value,
validationMessage: options.validate(options.value),
}));
return () => {
unsubscribe();
store.dispatch(removeField(name));
};
}, [name]);
return {
...state,
invalid: state.validationMessage !== null,
setValue(value) {
store.dispatch(updateField(name, {
value,
dirty: value !== options.value,
validationMessage: options.validate(value),
}));
},
setTouched() {
store.dispatch(setTouched(name));
},
};
};
//# sourceMappingURL=useField.js.map
//# sourceMappingURL=index.js.map
exports.Form = Form;
exports.useForm = useForm;
exports.useFormField = useFormField;
exports.useField = useField;

@@ -6,163 +6,202 @@ /**

*/
import React, { useMemo, useContext, useState, useRef, useEffect } from 'react';
import React, { useMemo, useState, useEffect, useContext, useRef } from 'react';
var FormContext = React.createContext({
register: function () {
throw new Error('Forgot to wrap form element in <Form /> component?');
},
subscribe: function () {
throw new Error('Forgot to wrap form element in <Form /> component?');
},
notify: function () {
throw new Error('Forgot to wrap form element in <Form /> component?');
},
const FormContext = React.createContext({
getState: () => ({}),
dispatch: () => { },
subscribe: () => () => { },
});
//# sourceMappingURL=context.js.map
var Form = function (_a) {
var autocomplete = _a.autocomplete, children = _a.children, className = _a.className, _b = _a.noValidate, noValidate = _b === void 0 ? true : _b, onSubmit = _a.onSubmit;
// Create mutatable state
var state = useMemo(function () { return new Map(); }, []);
var listeners = useMemo(function () { return []; }, []);
var context = {
register: function (_a) {
var name = _a.name, stateRef = _a.stateRef, validate = _a.validate;
state.set(name, [stateRef, validate]);
return function () {
state.delete(name);
const initialState = {};
const formReducer = (state = initialState, action) => {
switch (action.type) {
case 'INIT':
return {
...state,
[action.payload.name]: {
name: action.payload.name,
dirty: false,
touched: false,
validationMessage: action.payload.state.validationMessage,
value: action.payload.state.value,
},
};
},
subscribe: function (listener) {
listeners.push(listener);
return function () {
var index = listeners.indexOf(listener);
listeners.splice(index, 1);
case 'UPDATE_FIELD':
return {
...state,
[action.payload.name]: {
...state[action.payload.name],
...action.payload.state,
},
};
},
notify: function (name, state) {
listeners.forEach(function (listener) { return listener(name, state); });
},
case 'SET_TOUCHED':
return {
...state,
[action.payload.name]: {
...state[action.payload.name],
touched: true,
},
};
case 'REMOVE_FIELD':
const nextState = { ...state };
delete nextState[action.payload];
return nextState;
default:
return state;
}
};
//# sourceMappingURL=reducer.js.map
const createStore = () => {
let currentState = {};
const listeners = [];
const getState = () => currentState;
const subscribe = (listener) => {
listeners.push(listener);
return () => {
const index = listeners.indexOf(listener);
listeners.splice(index, 1);
};
};
var submit = function (event) {
var isValid = true;
event.preventDefault();
state.forEach(function (_a) {
var validate = _a[1];
if (!validate()) {
isValid = false;
}
});
if (!isValid) {
console.log('Form invalid');
return;
}
var formData = {};
state.forEach(function (_a, name) {
var stateRef = _a[0];
formData[name] = stateRef.current.value;
});
onSubmit(formData);
const dispatch = (action) => {
currentState = formReducer(currentState, action);
listeners.forEach(listener => listener());
};
return (React.createElement(FormContext.Provider, { value: context },
React.createElement("form", { className: className, onSubmit: submit, autoComplete: autocomplete ? 'on' : 'off', noValidate: noValidate }, children)));
return {
getState,
subscribe,
dispatch,
};
};
//# sourceMappingURL=createStore.js.map
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
var __assign = function() {
__assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
const getFormData = (state) => {
const values = Object.values(state).map(({ name, value }) => ({ name, value }));
const formData = {};
values.forEach(({ name, value }) => {
formData[name] = value;
});
return formData;
};
const isFormInvalid = (state) => Object.values(state).some(({ validationMessage }) => validationMessage !== null);
//# sourceMappingURL=selectors.js.map
var createInitialState = function (value) { return ({
dirty: false,
invalid: false,
touched: false,
validationMessage: '',
value: value,
}); };
var useForm = function (_a) {
var name = _a.name, value = _a.value, validate = _a.validate;
var form = useContext(FormContext);
var _b = useState(createInitialState(value)), state = _b[0], setState = _b[1];
var stateRef = useRef(state);
stateRef.current = state;
useEffect(function () {
return form.register({
name: name,
stateRef: stateRef,
validate: function () {
var state = stateRef.current;
var validity = validator(state.value, true);
var nextState = __assign({}, state, { touched: true, invalid: !!validity, validationMessage: validity || '' });
setState(nextState);
form.notify(name, nextState);
return !validity;
},
});
}, [name]);
useEffect(function () {
setValue(value);
}, [JSON.stringify(value)]);
function validator(value, force) {
if (force === void 0) { force = false; }
if (!validate) {
return null;
const Form = ({ render, className, autocomplete, onSubmit, noValidate = true }) => {
const store = useMemo(() => createStore(), []);
const [submitting, setSubmitting] = useState(false);
const [invalid, setInvalid] = useState(false);
// Listen to store updates to set validity
useEffect(() => {
const listener = () => {
const state = store.getState();
const isInvalid = isFormInvalid(state);
setInvalid(isInvalid);
};
listener();
return store.subscribe(() => listener());
}, []);
function submit(event) {
event.preventDefault();
const state = store.getState();
const formData = getFormData(state);
const isInvalid = isFormInvalid(state);
if (isInvalid) {
setInvalid(true);
return;
}
if (force) {
return validate ? validate(value) : null;
setSubmitting(true);
const result = onSubmit(formData);
// TODO Use await and ship without polyfill?
if (result && result.then) {
result.then(() => setSubmitting(false));
}
return (state.touched || state.dirty) && validate ? validate(value) : null;
else {
setSubmitting(false);
}
}
function setValue(value) {
var validity = validator(value);
var nextState = __assign({}, state, { value: value, invalid: !!validity, validationMessage: validity || '', dirty: value !== state.value });
setState(nextState);
// Emit change
form.notify(name, nextState);
return (React.createElement(FormContext.Provider, { value: store },
React.createElement("form", { className: className, onSubmit: submit, autoComplete: autocomplete ? 'on' : 'off', noValidate: noValidate }, render({ submitting, invalid }))));
};
//# sourceMappingURL=Form.js.map
const createActionWithPayload = (type, payload) => ({
type,
payload,
});
// Initialize field state
const initField = (name, state) => createActionWithPayload('INIT', { name, state });
// Update field state
const updateField = (name, state) => createActionWithPayload('UPDATE_FIELD', { name, state });
// Field is touched
const setTouched = (name) => createActionWithPayload('SET_TOUCHED', { name });
// Remove field state
const removeField = (name) => createActionWithPayload('REMOVE_FIELD', name);
//# sourceMappingURL=actions.js.map
const stateDidChange = (state, prevState) => {
if (state.value !== prevState.value ||
state.dirty !== prevState.dirty ||
state.touched !== prevState.touched ||
state.validationMessage !== prevState.validationMessage) {
return true;
}
function setTouched() {
setState(__assign({}, state, { touched: true }));
}
return __assign({}, state, { setValue: setValue, setTouched: setTouched });
return false;
};
var useFormField = function (target) {
var context = useContext(FormContext);
var _a = useState({
const useField = (name, options) => {
const store = useContext(FormContext);
const [state, setState] = useState({
name,
dirty: false,
invalid: false,
touched: false,
validationMessage: '',
value: null,
}), state = _a[0], setState = _a[1];
useEffect(function () {
return context.subscribe(function (name, state) {
if (name !== target) {
return;
validationMessage: null,
value: options.value,
});
const currentState = useRef(state);
// Update value whenever value (given by props) changes
useEffect(() => {
store.dispatch(updateField(name, {
value: options.value,
dirty: false,
validationMessage: options.validate(options.value),
}));
}, [options.value]);
useEffect(() => {
// Update local state
const unsubscribe = store.subscribe(() => {
const prevState = currentState.current;
const nextState = store.getState()[name];
if (prevState && nextState && stateDidChange(nextState, prevState)) {
setState(nextState);
currentState.current = nextState;
}
setState(state);
});
}, []);
return state;
store.dispatch(initField(name, {
value: options.value,
validationMessage: options.validate(options.value),
}));
return () => {
unsubscribe();
store.dispatch(removeField(name));
};
}, [name]);
return {
...state,
invalid: state.validationMessage !== null,
setValue(value) {
store.dispatch(updateField(name, {
value,
dirty: value !== options.value,
validationMessage: options.validate(value),
}));
},
setTouched() {
store.dispatch(setTouched(name));
},
};
};
//# sourceMappingURL=useField.js.map
export { Form, useForm, useFormField };
//# sourceMappingURL=index.js.map
export { Form, useField };
import React from 'react';
import { FormContext as Context } from 'types';
export declare const FormContext: React.Context<Context>;
export declare const FormContext: React.Context<{
getState: () => import("./store/reducer").FormReducer;
subscribe: (listener: () => void) => () => void;
dispatch: (action: import("./store/actions").ActionWithPayload<"INIT", {
name: string;
state: Pick<import("./types").FieldState<unknown>, "value" | "validationMessage">;
}> | import("./store/actions").ActionWithPayload<"UPDATE_FIELD", {
name: string;
state: Partial<import("./types").FieldState<unknown>>;
}> | import("./store/actions").ActionWithPayload<"SET_TOUCHED", {
name: string;
}> | import("./store/actions").ActionWithPayload<"REMOVE_FIELD", string>) => void;
}>;
import React from 'react';
import { FormData } from 'types';
interface Props {
autocomplete?: boolean;
children: React.ReactNode;
className?: string;
noValidate?: boolean;
onSubmit: (formData: FormData) => void;
}
declare const Form: ({ autocomplete, children, className, noValidate, onSubmit, }: Props) => JSX.Element;
import { FormData } from './types';
declare type Props = {
onSubmit: (formData: FormData) => void | Promise<void>;
className?: string;
autocomplete?: boolean;
noValidate?: boolean;
render: (form: { invalid: boolean; submitting: boolean }) => React.ReactNode;
};
declare const Form: ({
render,
className,
autocomplete,
onSubmit,
noValidate,
}: Props) => JSX.Element;
export default Form;

@@ -1,4 +0,3 @@

export { BaseFieldProps, FormData } from './types';
export { default as Form } from './Form';
export { useForm } from './hooks/useForm';
export { useFormField } from './hooks/useFormField';
export { useField } from './useField';
export { FieldProps } from './types';

@@ -1,27 +0,14 @@

import { MutableRefObject } from 'react';
export declare type FormFieldListener = (name: string, state: FormFieldState) => void;
export interface BaseFieldProps<V> {
name: string;
value?: V;
}
interface Register {
name: string;
stateRef: MutableRefObject<any>;
validate: () => boolean;
}
export interface FormContext {
register: (config: Register) => () => void;
subscribe: (listener: FormFieldListener) => void;
notify: (name: string, state: FormFieldState) => void;
}
export interface FormFieldState {
dirty: boolean;
invalid: boolean;
touched: boolean;
validationMessage: string;
value: any;
}
export interface FormData {
[key: string]: any;
}
export {};
export declare type FieldState<V> = {
name: string;
dirty: boolean;
touched: boolean;
validationMessage: null | string;
value: V;
};
export declare type FieldProps<V> = {
name: string;
value?: V;
};
export declare type FormData = {
[key: string]: unknown;
};
{
"name": "@blockle/form",
"version": "0.0.1-alpha.5",
"version": "0.0.1-alpha.6",
"description": "Blockle Form",

@@ -30,6 +30,14 @@ "scripts": {

"devDependencies": {
"@testing-library/jest-dom": "^4.1.2",
"@testing-library/react": "^9.3.0",
"@types/jest": "^24.0.11",
"@types/react": "^16.7.18",
"@types/react-dom": "^16.0.11",
"eslint-plugin-prettier": "^3.1.0",
"@typescript-eslint/eslint-plugin": "^2.4.0",
"@typescript-eslint/parser": "^2.4.0",
"eslint": "^6.5.1",
"eslint-config-prettier": "^6.4.0",
"eslint-plugin-prettier": "^3.1.1",
"eslint-plugin-react": "^7.16.0",
"eslint-plugin-react-hooks": "^2.1.2",
"husky": "^3.0.4",

@@ -42,5 +50,4 @@ "jest": "^24.5.0",

"pretty-quick": "^1.11.1",
"react": "^16.7.0",
"react-dom": "^16.7.0",
"react-testing-library": "^6.0.0",
"react": "^16.10.2",
"react-dom": "^16.10.2",
"rollup": "^1.0.0",

@@ -47,0 +54,0 @@ "rollup-plugin-commonjs": "^9.2.0",

@@ -13,3 +13,3 @@ # @blockle/form

import React, { useState } from 'react';
import Form, { BaseFieldProps } from '@blockle/form';
import { Form, useField, FieldProps } from '@blockle/form';

@@ -21,7 +21,4 @@ interface FormData {

const MyForm = () => {
const [sending, setSending] = useState(false);
const [errorMessage, setErrorMessage] = useState(null);
const submit = async (formData: FormData) => {
setSending(true);
try {

@@ -32,17 +29,21 @@ await xhr.send(formData);

}
setSending(false);
}
return (
<Form onSubmit={submit}>
<Input name="name" type="text" required />
<ValidationWarning target="name" />
<Form
onSubmit={submit}
render={({ invalid, submitting }) => (
<Input name="name" type="text" required />
<button disabled={sending}>Submit</button>
</Form>
{errorMessage
&& <div>{errorMessage}</div>}
<button disabled={invalid || submitting}>Submit</button>
)}
/>
);
}
interface InputProps extends BaseFieldProps<string> {
// Input.tsx
interface InputProps extends FieldProps<string> {
type: 'text' | 'password';

@@ -52,6 +53,4 @@ required: boolean;

// --
const Input = ({ name, value, type, required }: InputProps) => {
const {value, touched, dirty, valid, validationMessage, setValue} = useForm({
name,
const field = useField<string>(name, {
value,

@@ -64,34 +63,14 @@ validate(value) {

return null;
},
computeValue(value) {
return value;
}
});
// Update value
return (<input type={type} value={value} onInput={(event) => setValue(event.currentTarget.value)} />);
return (
<input
type={type}
value={field.value}
onChange={(event) => field.setValue(event.currentTarget.value)}
onFocus={field.setTouched}
/>
);
}
interface ValidationWarningProps {
target: string;
}
// --
const ValidationWarning = ({ target }: ValidationWarningProps) => {
const { value, touched, dirty, valid, validationMessage } = useFormField(target);
if(valid) {
return null;
}
return <div>{validationMessage}</div>
}
```
```ts
interface BaseFieldProps<V> {
value: V;
name: string;
}
```
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc