diff --git a/dist/Wrapper.d.ts b/dist/Wrapper.d.ts index cd72bfd0..7e85ebe1 100644 --- a/dist/Wrapper.d.ts +++ b/dist/Wrapper.d.ts @@ -1,50 +1,50 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { RequiredValidation, Validations } from './interfaces'; -declare const propTypes: { - innerRef: PropTypes.Requireable<(...args: any[]) => any>; - name: PropTypes.Validator; - required: PropTypes.Requireable; - validations: PropTypes.Requireable; - value: PropTypes.Requireable; -}; -export interface WrapperProps { - innerRef?: (ref: any) => void; - name: string; - required?: RequiredValidation; - validationError?: any; - validationErrors?: any; - validations?: Validations; - value?: V; -} -export interface WrapperState { - [key: string]: unknown; - externalError: null; - formSubmitted: boolean; - isPristine: boolean; - isRequired: boolean; - isValid: boolean; - pristineValue: any; - validationError: any[]; - value: V; -} -export interface InjectedProps { - errorMessage: any; - errorMessages: any; - hasValue: boolean; - isFormDisabled: boolean; - isFormSubmitted: boolean; - isPristine: boolean; - isRequired: boolean; - isValid: boolean; - isValidValue: (value: V) => boolean; - ref?: any; - resetValue: any; - setValidations: any; - setValue: (value: V) => void; - showError: boolean; - showRequired: boolean; -} -export declare type PassDownProps = WrapperProps & InjectedProps; -export { propTypes }; -export default function (WrappedComponent: React.ComponentType>): React.ComponentType, keyof InjectedProps>>; +import React from 'react'; +import PropTypes from 'prop-types'; +import { RequiredValidation, Validations } from './interfaces'; +declare const propTypes: { + innerRef: PropTypes.Requireable<(...args: any[]) => any>; + name: PropTypes.Validator; + required: PropTypes.Requireable; + validations: PropTypes.Requireable; + value: PropTypes.Requireable; +}; +export interface WrapperProps { + innerRef?: (ref: any) => void; + name: string; + required?: RequiredValidation; + validationError?: any; + validationErrors?: any; + validations?: Validations; + value?: V; +} +export interface WrapperState { + [key: string]: unknown; + externalError: null; + formSubmitted: boolean; + isPristine: boolean; + isRequired: boolean; + isValid: boolean; + pristineValue: any; + validationError: any[]; + value: V; +} +export interface InjectedProps { + errorMessage: any; + errorMessages: any; + hasValue: boolean; + isFormDisabled: boolean; + isFormSubmitted: boolean; + isPristine: boolean; + isRequired: boolean; + isValid: boolean; + isValidValue: (value: V) => boolean; + ref?: any; + resetValue: any; + setValidations: any; + setValue: (value: V) => void; + showError: boolean; + showRequired: boolean; +} +export declare type PassDownProps = WrapperProps & InjectedProps; +export { propTypes }; +export default function (WrappedComponent: React.ComponentType>): React.ComponentType, keyof InjectedProps>>; diff --git a/dist/index.d.ts b/dist/index.d.ts index e553d374..ceaf59e0 100644 --- a/dist/index.d.ts +++ b/dist/index.d.ts @@ -1,385 +1,385 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import validationRules from './validationRules'; -import Wrapper, { propTypes } from './Wrapper'; -import { IModel, InputComponent, IResetModel, IUpdateInputsWithValue, IUpdateInputsWithError, ValidationFunction } from './interfaces'; -declare type FormHTMLAttributesCleaned = Omit, 'onChange' | 'onSubmit'>; -export interface FormsyProps extends FormHTMLAttributesCleaned { - disabled: boolean; - getErrorMessage: any; - getErrorMessages: any; - getValue: any; - hasValue: any; - isFormDisabled: any; - isFormSubmitted: any; - isPristine: any; - isRequired: any; - isValid: any; - isValidValue: any; - mapping: null | ((model: IModel) => IModel); - onChange: (model: IModel, isChanged: boolean) => void; - onError: any; - onInvalid: () => void; - onInvalidSubmit: any; - onReset?: () => void; - onSubmit?: (model: IModel, resetModel: IResetModel, updateInputsWithError: IUpdateInputsWithError) => void; - onValid: () => void; - onValidSubmit?: (model: IModel, resetModel: IResetModel, updateInputsWithError: IUpdateInputsWithError) => void; - preventExternalInvalidation?: boolean; - resetValue: any; - setValidations: any; - setValue: any; - showError: any; - showRequired: any; - validationErrors?: null | object; -} -export interface FormsyState { - canChange: boolean; - formSubmitted?: boolean; - isPristine?: boolean; - isSubmitting: boolean; - isValid: boolean; -} -declare class Formsy extends React.Component { - inputs: any[]; - emptyArray: any[]; - prevInputNames: any[] | null; - static displayName: string; - static propTypes: { - disabled: PropTypes.Requireable; - getErrorMessage: PropTypes.Requireable<(...args: any[]) => any>; - getErrorMessages: PropTypes.Requireable<(...args: any[]) => any>; - getValue: PropTypes.Requireable<(...args: any[]) => any>; - hasValue: PropTypes.Requireable<(...args: any[]) => any>; - isFormDisabled: PropTypes.Requireable<(...args: any[]) => any>; - isFormSubmitted: PropTypes.Requireable<(...args: any[]) => any>; - isPristine: PropTypes.Requireable<(...args: any[]) => any>; - isRequired: PropTypes.Requireable<(...args: any[]) => any>; - isValid: PropTypes.Requireable<(...args: any[]) => any>; - isValidValue: PropTypes.Requireable<(...args: any[]) => any>; - mapping: PropTypes.Requireable<(...args: any[]) => any>; - onChange: PropTypes.Requireable<(...args: any[]) => any>; - onInvalid: PropTypes.Requireable<(...args: any[]) => any>; - onInvalidSubmit: PropTypes.Requireable<(...args: any[]) => any>; - onReset: PropTypes.Requireable<(...args: any[]) => any>; - onSubmit: PropTypes.Requireable<(...args: any[]) => any>; - onValid: PropTypes.Requireable<(...args: any[]) => any>; - onValidSubmit: PropTypes.Requireable<(...args: any[]) => any>; - preventExternalInvalidation: PropTypes.Requireable; - resetValue: PropTypes.Requireable<(...args: any[]) => any>; - setValidations: PropTypes.Requireable<(...args: any[]) => any>; - setValue: PropTypes.Requireable<(...args: any[]) => any>; - showError: PropTypes.Requireable<(...args: any[]) => any>; - showRequired: PropTypes.Requireable<(...args: any[]) => any>; - validationErrors: PropTypes.Requireable; - }; - static childContextTypes: { - formsy: PropTypes.Requireable; - }; - static defaultProps: Partial; - constructor(props: FormsyProps); - getChildContext: () => { - formsy: { - attachToForm: (component: any) => void; - detachFromForm: (component: InputComponent) => void; - isFormDisabled: boolean; - isValidValue: (component: any, value: any) => boolean; - validate: (component: InputComponent) => void; - }; - }; - componentDidMount: () => void; - componentDidUpdate: () => void; - getCurrentValues: () => any; - getModel: () => any; - getPristineValues: () => any; - setFormPristine: (isPristine: boolean) => void; - setInputValidationErrors: (errors: any) => void; - setFormValidState: (allIsValid: boolean) => void; - isValidValue: (component: any, value: any) => boolean; - isFormDisabled: () => boolean; - mapModel: (model: any) => any; - reset: (data?: any) => void; - resetInternal: (event: any) => void; - resetModel: IResetModel; - runValidation: (component: InputComponent, value?: V) => { - isRequired: boolean; - isValid: boolean; - error: any; - }; - attachToForm: (component: any) => void; - detachFromForm: (component: InputComponent) => void; - isChanged: () => boolean; - submit: (event: any) => void; - updateInputsWithError: IUpdateInputsWithError; - updateInputsWithValue: IUpdateInputsWithValue; - validate: (component: InputComponent) => void; - validateForm: () => void; - render: () => React.DetailedReactHTMLElement<{ - disabled: boolean; - onError: any; - hidden?: boolean; - dir?: string; - slot?: string; - style?: React.CSSProperties; - title?: string; - color?: string; - children?: React.ReactNode; - name?: string; - acceptCharset?: string; - action?: string; - autoComplete?: string; - encType?: string; - method?: string; - noValidate?: boolean; - target?: string; - defaultChecked?: boolean; - defaultValue?: string | number | string[]; - suppressContentEditableWarning?: boolean; - suppressHydrationWarning?: boolean; - accessKey?: string; - className?: string; - contentEditable?: boolean | "inherit" | "false" | "true"; - contextMenu?: string; - draggable?: boolean | "false" | "true"; - id?: string; - lang?: string; - placeholder?: string; - spellCheck?: boolean | "false" | "true"; - tabIndex?: number; - translate?: "yes" | "no"; - radioGroup?: string; - role?: string; - about?: string; - datatype?: string; - inlist?: any; - prefix?: string; - property?: string; - resource?: string; - typeof?: string; - vocab?: string; - autoCapitalize?: string; - autoCorrect?: string; - autoSave?: string; - itemProp?: string; - itemScope?: boolean; - itemType?: string; - itemID?: string; - itemRef?: string; - results?: number; - security?: string; - unselectable?: "on" | "off"; - inputMode?: "search" | "none" | "text" | "decimal" | "numeric" | "tel" | "url" | "email"; - is?: string; - 'aria-activedescendant'?: string; - 'aria-atomic'?: boolean | "false" | "true"; - 'aria-autocomplete'?: "none" | "both" | "inline" | "list"; - 'aria-busy'?: boolean | "false" | "true"; - 'aria-checked'?: boolean | "mixed" | "false" | "true"; - 'aria-colcount'?: number; - 'aria-colindex'?: number; - 'aria-colspan'?: number; - 'aria-controls'?: string; - 'aria-current'?: boolean | "time" | "page" | "false" | "true" | "step" | "location" | "date"; - 'aria-describedby'?: string; - 'aria-details'?: string; - 'aria-disabled'?: boolean | "false" | "true"; - 'aria-dropeffect'?: "link" | "none" | "copy" | "move" | "execute" | "popup"; - 'aria-errormessage'?: string; - 'aria-expanded'?: boolean | "false" | "true"; - 'aria-flowto'?: string; - 'aria-grabbed'?: boolean | "false" | "true"; - 'aria-haspopup'?: boolean | "dialog" | "menu" | "listbox" | "grid" | "false" | "true" | "tree"; - 'aria-hidden'?: boolean | "false" | "true"; - 'aria-invalid'?: boolean | "false" | "true" | "grammar" | "spelling"; - 'aria-keyshortcuts'?: string; - 'aria-label'?: string; - 'aria-labelledby'?: string; - 'aria-level'?: number; - 'aria-live'?: "off" | "assertive" | "polite"; - 'aria-modal'?: boolean | "false" | "true"; - 'aria-multiline'?: boolean | "false" | "true"; - 'aria-multiselectable'?: boolean | "false" | "true"; - 'aria-orientation'?: "horizontal" | "vertical"; - 'aria-owns'?: string; - 'aria-placeholder'?: string; - 'aria-posinset'?: number; - 'aria-pressed'?: boolean | "mixed" | "false" | "true"; - 'aria-readonly'?: boolean | "false" | "true"; - 'aria-relevant'?: "all" | "text" | "additions" | "additions text" | "removals"; - 'aria-required'?: boolean | "false" | "true"; - 'aria-roledescription'?: string; - 'aria-rowcount'?: number; - 'aria-rowindex'?: number; - 'aria-rowspan'?: number; - 'aria-selected'?: boolean | "false" | "true"; - 'aria-setsize'?: number; - 'aria-sort'?: "none" | "ascending" | "descending" | "other"; - 'aria-valuemax'?: number; - 'aria-valuemin'?: number; - 'aria-valuenow'?: number; - 'aria-valuetext'?: string; - dangerouslySetInnerHTML?: { - __html: string; - }; - onCopy?: (event: React.ClipboardEvent) => void; - onCopyCapture?: (event: React.ClipboardEvent) => void; - onCut?: (event: React.ClipboardEvent) => void; - onCutCapture?: (event: React.ClipboardEvent) => void; - onPaste?: (event: React.ClipboardEvent) => void; - onPasteCapture?: (event: React.ClipboardEvent) => void; - onCompositionEnd?: (event: React.CompositionEvent) => void; - onCompositionEndCapture?: (event: React.CompositionEvent) => void; - onCompositionStart?: (event: React.CompositionEvent) => void; - onCompositionStartCapture?: (event: React.CompositionEvent) => void; - onCompositionUpdate?: (event: React.CompositionEvent) => void; - onCompositionUpdateCapture?: (event: React.CompositionEvent) => void; - onFocus?: (event: React.FocusEvent) => void; - onFocusCapture?: (event: React.FocusEvent) => void; - onBlur?: (event: React.FocusEvent) => void; - onBlurCapture?: (event: React.FocusEvent) => void; - onChangeCapture?: (event: React.FormEvent) => void; - onBeforeInput?: (event: React.FormEvent) => void; - onBeforeInputCapture?: (event: React.FormEvent) => void; - onInput?: (event: React.FormEvent) => void; - onInputCapture?: (event: React.FormEvent) => void; - onResetCapture?: (event: React.FormEvent) => void; - onSubmitCapture?: (event: React.FormEvent) => void; - onInvalidCapture?: (event: React.FormEvent) => void; - onLoad?: (event: React.SyntheticEvent) => void; - onLoadCapture?: (event: React.SyntheticEvent) => void; - onErrorCapture?: (event: React.SyntheticEvent) => void; - onKeyDown?: (event: React.KeyboardEvent) => void; - onKeyDownCapture?: (event: React.KeyboardEvent) => void; - onKeyPress?: (event: React.KeyboardEvent) => void; - onKeyPressCapture?: (event: React.KeyboardEvent) => void; - onKeyUp?: (event: React.KeyboardEvent) => void; - onKeyUpCapture?: (event: React.KeyboardEvent) => void; - onAbort?: (event: React.SyntheticEvent) => void; - onAbortCapture?: (event: React.SyntheticEvent) => void; - onCanPlay?: (event: React.SyntheticEvent) => void; - onCanPlayCapture?: (event: React.SyntheticEvent) => void; - onCanPlayThrough?: (event: React.SyntheticEvent) => void; - onCanPlayThroughCapture?: (event: React.SyntheticEvent) => void; - onDurationChange?: (event: React.SyntheticEvent) => void; - onDurationChangeCapture?: (event: React.SyntheticEvent) => void; - onEmptied?: (event: React.SyntheticEvent) => void; - onEmptiedCapture?: (event: React.SyntheticEvent) => void; - onEncrypted?: (event: React.SyntheticEvent) => void; - onEncryptedCapture?: (event: React.SyntheticEvent) => void; - onEnded?: (event: React.SyntheticEvent) => void; - onEndedCapture?: (event: React.SyntheticEvent) => void; - onLoadedData?: (event: React.SyntheticEvent) => void; - onLoadedDataCapture?: (event: React.SyntheticEvent) => void; - onLoadedMetadata?: (event: React.SyntheticEvent) => void; - onLoadedMetadataCapture?: (event: React.SyntheticEvent) => void; - onLoadStart?: (event: React.SyntheticEvent) => void; - onLoadStartCapture?: (event: React.SyntheticEvent) => void; - onPause?: (event: React.SyntheticEvent) => void; - onPauseCapture?: (event: React.SyntheticEvent) => void; - onPlay?: (event: React.SyntheticEvent) => void; - onPlayCapture?: (event: React.SyntheticEvent) => void; - onPlaying?: (event: React.SyntheticEvent) => void; - onPlayingCapture?: (event: React.SyntheticEvent) => void; - onProgress?: (event: React.SyntheticEvent) => void; - onProgressCapture?: (event: React.SyntheticEvent) => void; - onRateChange?: (event: React.SyntheticEvent) => void; - onRateChangeCapture?: (event: React.SyntheticEvent) => void; - onSeeked?: (event: React.SyntheticEvent) => void; - onSeekedCapture?: (event: React.SyntheticEvent) => void; - onSeeking?: (event: React.SyntheticEvent) => void; - onSeekingCapture?: (event: React.SyntheticEvent) => void; - onStalled?: (event: React.SyntheticEvent) => void; - onStalledCapture?: (event: React.SyntheticEvent) => void; - onSuspend?: (event: React.SyntheticEvent) => void; - onSuspendCapture?: (event: React.SyntheticEvent) => void; - onTimeUpdate?: (event: React.SyntheticEvent) => void; - onTimeUpdateCapture?: (event: React.SyntheticEvent) => void; - onVolumeChange?: (event: React.SyntheticEvent) => void; - onVolumeChangeCapture?: (event: React.SyntheticEvent) => void; - onWaiting?: (event: React.SyntheticEvent) => void; - onWaitingCapture?: (event: React.SyntheticEvent) => void; - onAuxClick?: (event: React.MouseEvent) => void; - onAuxClickCapture?: (event: React.MouseEvent) => void; - onClick?: (event: React.MouseEvent) => void; - onClickCapture?: (event: React.MouseEvent) => void; - onContextMenu?: (event: React.MouseEvent) => void; - onContextMenuCapture?: (event: React.MouseEvent) => void; - onDoubleClick?: (event: React.MouseEvent) => void; - onDoubleClickCapture?: (event: React.MouseEvent) => void; - onDrag?: (event: React.DragEvent) => void; - onDragCapture?: (event: React.DragEvent) => void; - onDragEnd?: (event: React.DragEvent) => void; - onDragEndCapture?: (event: React.DragEvent) => void; - onDragEnter?: (event: React.DragEvent) => void; - onDragEnterCapture?: (event: React.DragEvent) => void; - onDragExit?: (event: React.DragEvent) => void; - onDragExitCapture?: (event: React.DragEvent) => void; - onDragLeave?: (event: React.DragEvent) => void; - onDragLeaveCapture?: (event: React.DragEvent) => void; - onDragOver?: (event: React.DragEvent) => void; - onDragOverCapture?: (event: React.DragEvent) => void; - onDragStart?: (event: React.DragEvent) => void; - onDragStartCapture?: (event: React.DragEvent) => void; - onDrop?: (event: React.DragEvent) => void; - onDropCapture?: (event: React.DragEvent) => void; - onMouseDown?: (event: React.MouseEvent) => void; - onMouseDownCapture?: (event: React.MouseEvent) => void; - onMouseEnter?: (event: React.MouseEvent) => void; - onMouseLeave?: (event: React.MouseEvent) => void; - onMouseMove?: (event: React.MouseEvent) => void; - onMouseMoveCapture?: (event: React.MouseEvent) => void; - onMouseOut?: (event: React.MouseEvent) => void; - onMouseOutCapture?: (event: React.MouseEvent) => void; - onMouseOver?: (event: React.MouseEvent) => void; - onMouseOverCapture?: (event: React.MouseEvent) => void; - onMouseUp?: (event: React.MouseEvent) => void; - onMouseUpCapture?: (event: React.MouseEvent) => void; - onSelect?: (event: React.SyntheticEvent) => void; - onSelectCapture?: (event: React.SyntheticEvent) => void; - onTouchCancel?: (event: React.TouchEvent) => void; - onTouchCancelCapture?: (event: React.TouchEvent) => void; - onTouchEnd?: (event: React.TouchEvent) => void; - onTouchEndCapture?: (event: React.TouchEvent) => void; - onTouchMove?: (event: React.TouchEvent) => void; - onTouchMoveCapture?: (event: React.TouchEvent) => void; - onTouchStart?: (event: React.TouchEvent) => void; - onTouchStartCapture?: (event: React.TouchEvent) => void; - onPointerDown?: (event: React.PointerEvent) => void; - onPointerDownCapture?: (event: React.PointerEvent) => void; - onPointerMove?: (event: React.PointerEvent) => void; - onPointerMoveCapture?: (event: React.PointerEvent) => void; - onPointerUp?: (event: React.PointerEvent) => void; - onPointerUpCapture?: (event: React.PointerEvent) => void; - onPointerCancel?: (event: React.PointerEvent) => void; - onPointerCancelCapture?: (event: React.PointerEvent) => void; - onPointerEnter?: (event: React.PointerEvent) => void; - onPointerEnterCapture?: (event: React.PointerEvent) => void; - onPointerLeave?: (event: React.PointerEvent) => void; - onPointerLeaveCapture?: (event: React.PointerEvent) => void; - onPointerOver?: (event: React.PointerEvent) => void; - onPointerOverCapture?: (event: React.PointerEvent) => void; - onPointerOut?: (event: React.PointerEvent) => void; - onPointerOutCapture?: (event: React.PointerEvent) => void; - onGotPointerCapture?: (event: React.PointerEvent) => void; - onGotPointerCaptureCapture?: (event: React.PointerEvent) => void; - onLostPointerCapture?: (event: React.PointerEvent) => void; - onLostPointerCaptureCapture?: (event: React.PointerEvent) => void; - onScroll?: (event: React.UIEvent) => void; - onScrollCapture?: (event: React.UIEvent) => void; - onWheel?: (event: React.WheelEvent) => void; - onWheelCapture?: (event: React.WheelEvent) => void; - onAnimationStart?: (event: React.AnimationEvent) => void; - onAnimationStartCapture?: (event: React.AnimationEvent) => void; - onAnimationEnd?: (event: React.AnimationEvent) => void; - onAnimationEndCapture?: (event: React.AnimationEvent) => void; - onAnimationIteration?: (event: React.AnimationEvent) => void; - onAnimationIterationCapture?: (event: React.AnimationEvent) => void; - onTransitionEnd?: (event: React.TransitionEvent) => void; - onTransitionEndCapture?: (event: React.TransitionEvent) => void; - onReset: (event: any) => void; - onSubmit: (event: any) => void; - }, HTMLElement>; -} -declare const addValidationRule: (name: string, func: ValidationFunction) => void; -export { addValidationRule, propTypes, validationRules, Wrapper as withFormsy }; -export default Formsy; +import React from 'react'; +import PropTypes from 'prop-types'; +import validationRules from './validationRules'; +import Wrapper, { propTypes } from './Wrapper'; +import { IModel, InputComponent, IResetModel, IUpdateInputsWithValue, IUpdateInputsWithError, ValidationFunction } from './interfaces'; +declare type FormHTMLAttributesCleaned = Omit, 'onChange' | 'onSubmit'>; +export interface FormsyProps extends FormHTMLAttributesCleaned { + disabled: boolean; + getErrorMessage: any; + getErrorMessages: any; + getValue: any; + hasValue: any; + isFormDisabled: any; + isFormSubmitted: any; + isPristine: any; + isRequired: any; + isValid: any; + isValidValue: any; + mapping: null | ((model: IModel) => IModel); + onChange: (model: IModel, isChanged: boolean) => void; + onError: any; + onInvalid: () => void; + onInvalidSubmit: any; + onReset?: () => void; + onSubmit?: (model: IModel, resetModel: IResetModel, updateInputsWithError: IUpdateInputsWithError) => void; + onValid: () => void; + onValidSubmit?: (model: IModel, resetModel: IResetModel, updateInputsWithError: IUpdateInputsWithError) => void; + preventExternalInvalidation?: boolean; + resetValue: any; + setValidations: any; + setValue: any; + showError: any; + showRequired: any; + validationErrors?: null | object; +} +export interface FormsyState { + canChange: boolean; + formSubmitted?: boolean; + isPristine?: boolean; + isSubmitting: boolean; + isValid: boolean; +} +declare class Formsy extends React.Component { + inputs: any[]; + emptyArray: any[]; + prevInputNames: any[] | null; + static displayName: string; + static propTypes: { + disabled: PropTypes.Requireable; + getErrorMessage: PropTypes.Requireable<(...args: any[]) => any>; + getErrorMessages: PropTypes.Requireable<(...args: any[]) => any>; + getValue: PropTypes.Requireable<(...args: any[]) => any>; + hasValue: PropTypes.Requireable<(...args: any[]) => any>; + isFormDisabled: PropTypes.Requireable<(...args: any[]) => any>; + isFormSubmitted: PropTypes.Requireable<(...args: any[]) => any>; + isPristine: PropTypes.Requireable<(...args: any[]) => any>; + isRequired: PropTypes.Requireable<(...args: any[]) => any>; + isValid: PropTypes.Requireable<(...args: any[]) => any>; + isValidValue: PropTypes.Requireable<(...args: any[]) => any>; + mapping: PropTypes.Requireable<(...args: any[]) => any>; + onChange: PropTypes.Requireable<(...args: any[]) => any>; + onInvalid: PropTypes.Requireable<(...args: any[]) => any>; + onInvalidSubmit: PropTypes.Requireable<(...args: any[]) => any>; + onReset: PropTypes.Requireable<(...args: any[]) => any>; + onSubmit: PropTypes.Requireable<(...args: any[]) => any>; + onValid: PropTypes.Requireable<(...args: any[]) => any>; + onValidSubmit: PropTypes.Requireable<(...args: any[]) => any>; + preventExternalInvalidation: PropTypes.Requireable; + resetValue: PropTypes.Requireable<(...args: any[]) => any>; + setValidations: PropTypes.Requireable<(...args: any[]) => any>; + setValue: PropTypes.Requireable<(...args: any[]) => any>; + showError: PropTypes.Requireable<(...args: any[]) => any>; + showRequired: PropTypes.Requireable<(...args: any[]) => any>; + validationErrors: PropTypes.Requireable; + }; + static childContextTypes: { + formsy: PropTypes.Requireable; + }; + static defaultProps: Partial; + constructor(props: FormsyProps); + getChildContext: () => { + formsy: { + attachToForm: (component: any) => void; + detachFromForm: (component: InputComponent) => void; + isFormDisabled: boolean; + isValidValue: (component: any, value: any) => boolean; + validate: (component: InputComponent) => void; + }; + }; + componentDidMount: () => void; + componentDidUpdate: () => void; + getCurrentValues: () => any; + getModel: () => any; + getPristineValues: () => any; + setFormPristine: (isPristine: boolean) => void; + setInputValidationErrors: (errors: any) => void; + setFormValidState: (allIsValid: boolean) => void; + isValidValue: (component: any, value: any) => boolean; + isFormDisabled: () => boolean; + mapModel: (model: any) => any; + reset: (data?: any) => void; + resetInternal: (event: any) => void; + resetModel: IResetModel; + runValidation: (component: InputComponent, value?: V) => { + isRequired: boolean; + isValid: boolean; + error: any; + }; + attachToForm: (component: any) => void; + detachFromForm: (component: InputComponent) => void; + isChanged: () => boolean; + submit: (event: any) => void; + updateInputsWithError: IUpdateInputsWithError; + updateInputsWithValue: IUpdateInputsWithValue; + validate: (component: InputComponent) => void; + validateForm: () => void; + render: () => React.DetailedReactHTMLElement<{ + disabled: boolean; + onError: any; + hidden?: boolean; + dir?: string; + slot?: string; + style?: React.CSSProperties; + title?: string; + color?: string; + children?: React.ReactNode; + name?: string; + acceptCharset?: string; + action?: string; + autoComplete?: string; + encType?: string; + method?: string; + noValidate?: boolean; + target?: string; + defaultChecked?: boolean; + defaultValue?: string | number | string[]; + suppressContentEditableWarning?: boolean; + suppressHydrationWarning?: boolean; + accessKey?: string; + className?: string; + contentEditable?: boolean | "inherit" | "false" | "true"; + contextMenu?: string; + draggable?: boolean | "false" | "true"; + id?: string; + lang?: string; + placeholder?: string; + spellCheck?: boolean | "false" | "true"; + tabIndex?: number; + translate?: "yes" | "no"; + radioGroup?: string; + role?: string; + about?: string; + datatype?: string; + inlist?: any; + prefix?: string; + property?: string; + resource?: string; + typeof?: string; + vocab?: string; + autoCapitalize?: string; + autoCorrect?: string; + autoSave?: string; + itemProp?: string; + itemScope?: boolean; + itemType?: string; + itemID?: string; + itemRef?: string; + results?: number; + security?: string; + unselectable?: "on" | "off"; + inputMode?: "search" | "none" | "text" | "decimal" | "numeric" | "tel" | "url" | "email"; + is?: string; + 'aria-activedescendant'?: string; + 'aria-atomic'?: boolean | "false" | "true"; + 'aria-autocomplete'?: "none" | "both" | "inline" | "list"; + 'aria-busy'?: boolean | "false" | "true"; + 'aria-checked'?: boolean | "mixed" | "false" | "true"; + 'aria-colcount'?: number; + 'aria-colindex'?: number; + 'aria-colspan'?: number; + 'aria-controls'?: string; + 'aria-current'?: boolean | "time" | "page" | "false" | "true" | "step" | "location" | "date"; + 'aria-describedby'?: string; + 'aria-details'?: string; + 'aria-disabled'?: boolean | "false" | "true"; + 'aria-dropeffect'?: "link" | "none" | "copy" | "move" | "execute" | "popup"; + 'aria-errormessage'?: string; + 'aria-expanded'?: boolean | "false" | "true"; + 'aria-flowto'?: string; + 'aria-grabbed'?: boolean | "false" | "true"; + 'aria-haspopup'?: boolean | "dialog" | "menu" | "listbox" | "grid" | "false" | "true" | "tree"; + 'aria-hidden'?: boolean | "false" | "true"; + 'aria-invalid'?: boolean | "false" | "true" | "grammar" | "spelling"; + 'aria-keyshortcuts'?: string; + 'aria-label'?: string; + 'aria-labelledby'?: string; + 'aria-level'?: number; + 'aria-live'?: "off" | "assertive" | "polite"; + 'aria-modal'?: boolean | "false" | "true"; + 'aria-multiline'?: boolean | "false" | "true"; + 'aria-multiselectable'?: boolean | "false" | "true"; + 'aria-orientation'?: "horizontal" | "vertical"; + 'aria-owns'?: string; + 'aria-placeholder'?: string; + 'aria-posinset'?: number; + 'aria-pressed'?: boolean | "mixed" | "false" | "true"; + 'aria-readonly'?: boolean | "false" | "true"; + 'aria-relevant'?: "all" | "text" | "additions" | "additions text" | "removals"; + 'aria-required'?: boolean | "false" | "true"; + 'aria-roledescription'?: string; + 'aria-rowcount'?: number; + 'aria-rowindex'?: number; + 'aria-rowspan'?: number; + 'aria-selected'?: boolean | "false" | "true"; + 'aria-setsize'?: number; + 'aria-sort'?: "none" | "ascending" | "descending" | "other"; + 'aria-valuemax'?: number; + 'aria-valuemin'?: number; + 'aria-valuenow'?: number; + 'aria-valuetext'?: string; + dangerouslySetInnerHTML?: { + __html: string; + }; + onCopy?: (event: React.ClipboardEvent) => void; + onCopyCapture?: (event: React.ClipboardEvent) => void; + onCut?: (event: React.ClipboardEvent) => void; + onCutCapture?: (event: React.ClipboardEvent) => void; + onPaste?: (event: React.ClipboardEvent) => void; + onPasteCapture?: (event: React.ClipboardEvent) => void; + onCompositionEnd?: (event: React.CompositionEvent) => void; + onCompositionEndCapture?: (event: React.CompositionEvent) => void; + onCompositionStart?: (event: React.CompositionEvent) => void; + onCompositionStartCapture?: (event: React.CompositionEvent) => void; + onCompositionUpdate?: (event: React.CompositionEvent) => void; + onCompositionUpdateCapture?: (event: React.CompositionEvent) => void; + onFocus?: (event: React.FocusEvent) => void; + onFocusCapture?: (event: React.FocusEvent) => void; + onBlur?: (event: React.FocusEvent) => void; + onBlurCapture?: (event: React.FocusEvent) => void; + onChangeCapture?: (event: React.FormEvent) => void; + onBeforeInput?: (event: React.FormEvent) => void; + onBeforeInputCapture?: (event: React.FormEvent) => void; + onInput?: (event: React.FormEvent) => void; + onInputCapture?: (event: React.FormEvent) => void; + onResetCapture?: (event: React.FormEvent) => void; + onSubmitCapture?: (event: React.FormEvent) => void; + onInvalidCapture?: (event: React.FormEvent) => void; + onLoad?: (event: React.SyntheticEvent) => void; + onLoadCapture?: (event: React.SyntheticEvent) => void; + onErrorCapture?: (event: React.SyntheticEvent) => void; + onKeyDown?: (event: React.KeyboardEvent) => void; + onKeyDownCapture?: (event: React.KeyboardEvent) => void; + onKeyPress?: (event: React.KeyboardEvent) => void; + onKeyPressCapture?: (event: React.KeyboardEvent) => void; + onKeyUp?: (event: React.KeyboardEvent) => void; + onKeyUpCapture?: (event: React.KeyboardEvent) => void; + onAbort?: (event: React.SyntheticEvent) => void; + onAbortCapture?: (event: React.SyntheticEvent) => void; + onCanPlay?: (event: React.SyntheticEvent) => void; + onCanPlayCapture?: (event: React.SyntheticEvent) => void; + onCanPlayThrough?: (event: React.SyntheticEvent) => void; + onCanPlayThroughCapture?: (event: React.SyntheticEvent) => void; + onDurationChange?: (event: React.SyntheticEvent) => void; + onDurationChangeCapture?: (event: React.SyntheticEvent) => void; + onEmptied?: (event: React.SyntheticEvent) => void; + onEmptiedCapture?: (event: React.SyntheticEvent) => void; + onEncrypted?: (event: React.SyntheticEvent) => void; + onEncryptedCapture?: (event: React.SyntheticEvent) => void; + onEnded?: (event: React.SyntheticEvent) => void; + onEndedCapture?: (event: React.SyntheticEvent) => void; + onLoadedData?: (event: React.SyntheticEvent) => void; + onLoadedDataCapture?: (event: React.SyntheticEvent) => void; + onLoadedMetadata?: (event: React.SyntheticEvent) => void; + onLoadedMetadataCapture?: (event: React.SyntheticEvent) => void; + onLoadStart?: (event: React.SyntheticEvent) => void; + onLoadStartCapture?: (event: React.SyntheticEvent) => void; + onPause?: (event: React.SyntheticEvent) => void; + onPauseCapture?: (event: React.SyntheticEvent) => void; + onPlay?: (event: React.SyntheticEvent) => void; + onPlayCapture?: (event: React.SyntheticEvent) => void; + onPlaying?: (event: React.SyntheticEvent) => void; + onPlayingCapture?: (event: React.SyntheticEvent) => void; + onProgress?: (event: React.SyntheticEvent) => void; + onProgressCapture?: (event: React.SyntheticEvent) => void; + onRateChange?: (event: React.SyntheticEvent) => void; + onRateChangeCapture?: (event: React.SyntheticEvent) => void; + onSeeked?: (event: React.SyntheticEvent) => void; + onSeekedCapture?: (event: React.SyntheticEvent) => void; + onSeeking?: (event: React.SyntheticEvent) => void; + onSeekingCapture?: (event: React.SyntheticEvent) => void; + onStalled?: (event: React.SyntheticEvent) => void; + onStalledCapture?: (event: React.SyntheticEvent) => void; + onSuspend?: (event: React.SyntheticEvent) => void; + onSuspendCapture?: (event: React.SyntheticEvent) => void; + onTimeUpdate?: (event: React.SyntheticEvent) => void; + onTimeUpdateCapture?: (event: React.SyntheticEvent) => void; + onVolumeChange?: (event: React.SyntheticEvent) => void; + onVolumeChangeCapture?: (event: React.SyntheticEvent) => void; + onWaiting?: (event: React.SyntheticEvent) => void; + onWaitingCapture?: (event: React.SyntheticEvent) => void; + onAuxClick?: (event: React.MouseEvent) => void; + onAuxClickCapture?: (event: React.MouseEvent) => void; + onClick?: (event: React.MouseEvent) => void; + onClickCapture?: (event: React.MouseEvent) => void; + onContextMenu?: (event: React.MouseEvent) => void; + onContextMenuCapture?: (event: React.MouseEvent) => void; + onDoubleClick?: (event: React.MouseEvent) => void; + onDoubleClickCapture?: (event: React.MouseEvent) => void; + onDrag?: (event: React.DragEvent) => void; + onDragCapture?: (event: React.DragEvent) => void; + onDragEnd?: (event: React.DragEvent) => void; + onDragEndCapture?: (event: React.DragEvent) => void; + onDragEnter?: (event: React.DragEvent) => void; + onDragEnterCapture?: (event: React.DragEvent) => void; + onDragExit?: (event: React.DragEvent) => void; + onDragExitCapture?: (event: React.DragEvent) => void; + onDragLeave?: (event: React.DragEvent) => void; + onDragLeaveCapture?: (event: React.DragEvent) => void; + onDragOver?: (event: React.DragEvent) => void; + onDragOverCapture?: (event: React.DragEvent) => void; + onDragStart?: (event: React.DragEvent) => void; + onDragStartCapture?: (event: React.DragEvent) => void; + onDrop?: (event: React.DragEvent) => void; + onDropCapture?: (event: React.DragEvent) => void; + onMouseDown?: (event: React.MouseEvent) => void; + onMouseDownCapture?: (event: React.MouseEvent) => void; + onMouseEnter?: (event: React.MouseEvent) => void; + onMouseLeave?: (event: React.MouseEvent) => void; + onMouseMove?: (event: React.MouseEvent) => void; + onMouseMoveCapture?: (event: React.MouseEvent) => void; + onMouseOut?: (event: React.MouseEvent) => void; + onMouseOutCapture?: (event: React.MouseEvent) => void; + onMouseOver?: (event: React.MouseEvent) => void; + onMouseOverCapture?: (event: React.MouseEvent) => void; + onMouseUp?: (event: React.MouseEvent) => void; + onMouseUpCapture?: (event: React.MouseEvent) => void; + onSelect?: (event: React.SyntheticEvent) => void; + onSelectCapture?: (event: React.SyntheticEvent) => void; + onTouchCancel?: (event: React.TouchEvent) => void; + onTouchCancelCapture?: (event: React.TouchEvent) => void; + onTouchEnd?: (event: React.TouchEvent) => void; + onTouchEndCapture?: (event: React.TouchEvent) => void; + onTouchMove?: (event: React.TouchEvent) => void; + onTouchMoveCapture?: (event: React.TouchEvent) => void; + onTouchStart?: (event: React.TouchEvent) => void; + onTouchStartCapture?: (event: React.TouchEvent) => void; + onPointerDown?: (event: React.PointerEvent) => void; + onPointerDownCapture?: (event: React.PointerEvent) => void; + onPointerMove?: (event: React.PointerEvent) => void; + onPointerMoveCapture?: (event: React.PointerEvent) => void; + onPointerUp?: (event: React.PointerEvent) => void; + onPointerUpCapture?: (event: React.PointerEvent) => void; + onPointerCancel?: (event: React.PointerEvent) => void; + onPointerCancelCapture?: (event: React.PointerEvent) => void; + onPointerEnter?: (event: React.PointerEvent) => void; + onPointerEnterCapture?: (event: React.PointerEvent) => void; + onPointerLeave?: (event: React.PointerEvent) => void; + onPointerLeaveCapture?: (event: React.PointerEvent) => void; + onPointerOver?: (event: React.PointerEvent) => void; + onPointerOverCapture?: (event: React.PointerEvent) => void; + onPointerOut?: (event: React.PointerEvent) => void; + onPointerOutCapture?: (event: React.PointerEvent) => void; + onGotPointerCapture?: (event: React.PointerEvent) => void; + onGotPointerCaptureCapture?: (event: React.PointerEvent) => void; + onLostPointerCapture?: (event: React.PointerEvent) => void; + onLostPointerCaptureCapture?: (event: React.PointerEvent) => void; + onScroll?: (event: React.UIEvent) => void; + onScrollCapture?: (event: React.UIEvent) => void; + onWheel?: (event: React.WheelEvent) => void; + onWheelCapture?: (event: React.WheelEvent) => void; + onAnimationStart?: (event: React.AnimationEvent) => void; + onAnimationStartCapture?: (event: React.AnimationEvent) => void; + onAnimationEnd?: (event: React.AnimationEvent) => void; + onAnimationEndCapture?: (event: React.AnimationEvent) => void; + onAnimationIteration?: (event: React.AnimationEvent) => void; + onAnimationIterationCapture?: (event: React.AnimationEvent) => void; + onTransitionEnd?: (event: React.TransitionEvent) => void; + onTransitionEndCapture?: (event: React.TransitionEvent) => void; + onReset: (event: any) => void; + onSubmit: (event: any) => void; + }, HTMLElement>; +} +declare const addValidationRule: (name: string, func: ValidationFunction) => void; +export { addValidationRule, propTypes, validationRules, Wrapper as withFormsy }; +export default Formsy; diff --git a/dist/interfaces.d.ts b/dist/interfaces.d.ts index e4be621b..098b6204 100644 --- a/dist/interfaces.d.ts +++ b/dist/interfaces.d.ts @@ -1,26 +1,26 @@ -import React, { ComponentClass } from 'react'; -import { WrapperProps, WrapperState } from './Wrapper'; -export interface Values { - [key: string]: any; -} -export declare type IModel = any; -export declare type IData = any; -export declare type IResetModel = (model?: IModel) => void; -export declare type IUpdateInputsWithValue = (values: any, validate?: boolean) => void; -export declare type IUpdateInputsWithError = (errors: any, invalidate?: boolean) => void; -export declare type ValidationFunction = (values: Values, value: V, extra?: any) => boolean | string; -export declare type Validation = string | boolean | ValidationFunction; -export declare type Validations = ValidationsStructure | string | object; -export interface ValidationsStructure { - [key: string]: Validation; -} -export declare type RequiredValidation = boolean | Validations; -export interface ComponentWithStaticAttributes extends ComponentClass { - string?: any; - defaultValue?: any; -} -export declare type WrappedComponentClass = React.FC | ComponentWithStaticAttributes; -export interface InputComponent extends React.Component, WrapperState> { - validations?: Validations; - requiredValidations?: Validations; -} +import React, { ComponentClass } from 'react'; +import { WrapperProps, WrapperState } from './Wrapper'; +export interface Values { + [key: string]: any; +} +export declare type IModel = any; +export declare type IData = any; +export declare type IResetModel = (model?: IModel) => void; +export declare type IUpdateInputsWithValue = (values: any, validate?: boolean) => void; +export declare type IUpdateInputsWithError = (errors: any, invalidate?: boolean) => void; +export declare type ValidationFunction = (values: Values, value: V, extra?: any) => boolean | string; +export declare type Validation = string | boolean | ValidationFunction; +export declare type Validations = ValidationsStructure | string | object; +export interface ValidationsStructure { + [key: string]: Validation; +} +export declare type RequiredValidation = boolean | Validations; +export interface ComponentWithStaticAttributes extends ComponentClass { + string?: any; + defaultValue?: any; +} +export declare type WrappedComponentClass = React.FC | ComponentWithStaticAttributes; +export interface InputComponent extends React.Component, WrapperState> { + validations?: Validations; + requiredValidations?: Validations; +} diff --git a/dist/utils.d.ts b/dist/utils.d.ts index bb926eae..3b4569a5 100644 --- a/dist/utils.d.ts +++ b/dist/utils.d.ts @@ -1,19 +1,19 @@ -import { Validations, Values } from './interfaces'; -export declare function isArray(value: unknown): value is unknown[]; -export declare function isObject(value: unknown): value is object; -export declare function isTypeUndefined(value: unknown): value is undefined; -export declare function isDate(value: unknown): value is Date; -export declare function isFunction(value: unknown): value is Function; -export declare function isString(value: unknown): value is string; -export declare function isNumber(value: unknown): value is number; -export declare function isValueStringEmpty(value: string): boolean; -export declare function isValueNullOrUndefined(value: unknown): boolean; -export declare function isValueUndefined(value: unknown): boolean; -export declare function noop(): void; -export declare function cloneIfObject(value: unknown): unknown; -export declare function isSame(a: unknown, b: unknown): any; -export declare function runRules(value: V, currentValues: Values, validations: Validations, validationRules: Validations): { - errors: string[]; - failed: string[]; - success: string[]; -}; +import { Validations, Values } from './interfaces'; +export declare function isArray(value: unknown): value is unknown[]; +export declare function isObject(value: unknown): value is object; +export declare function isTypeUndefined(value: unknown): value is undefined; +export declare function isDate(value: unknown): value is Date; +export declare function isFunction(value: unknown): value is Function; +export declare function isString(value: unknown): value is string; +export declare function isNumber(value: unknown): value is number; +export declare function isValueStringEmpty(value: string): boolean; +export declare function isValueNullOrUndefined(value: unknown): boolean; +export declare function isValueUndefined(value: unknown): boolean; +export declare function noop(): void; +export declare function cloneIfObject(value: unknown): unknown; +export declare function isSame(a: unknown, b: unknown): any; +export declare function runRules(value: V, currentValues: Values, validations: Validations, validationRules: Validations): { + errors: string[]; + failed: string[]; + success: string[]; +}; diff --git a/dist/validationRules.d.ts b/dist/validationRules.d.ts index f3ee0b1e..2eabe39b 100644 --- a/dist/validationRules.d.ts +++ b/dist/validationRules.d.ts @@ -1,6 +1,6 @@ -import { ValidationFunction } from './interfaces'; -interface Validations { - [key: string]: ValidationFunction; -} -declare const validations: Validations; -export default validations; +import { ValidationFunction } from './interfaces'; +interface Validations { + [key: string]: ValidationFunction; +} +declare const validations: Validations; +export default validations; diff --git a/package.json b/package.json index 7d220380..7d6f626f 100644 --- a/package.json +++ b/package.json @@ -112,7 +112,7 @@ "typescript": "^3.5.3" }, "peerDependencies": { - "react": "^15.6.1 || ^16.0.0", - "react-dom": "^15.6.1 || ^16.0.0" + "react": "^16.0.0", + "react-dom": "^16.0.0" } } diff --git a/src/FormsyContext.ts b/src/FormsyContext.ts new file mode 100644 index 00000000..fd384d8b --- /dev/null +++ b/src/FormsyContext.ts @@ -0,0 +1,18 @@ +import React from 'react'; +import { FormsyContextInterface } from './interfaces'; + +const noFormsyErrorMessage = 'Could not find Formsy Context Provider. Did you use withFormsy outside ?'; + +const throwNoFormsyProvider = () => { + throw new Error(noFormsyErrorMessage); +}; + +const defaultValue = { + attachToForm: throwNoFormsyProvider, + detachFromForm: throwNoFormsyProvider, + isFormDisabled: true, + isValidValue: throwNoFormsyProvider, + validate: throwNoFormsyProvider, +}; + +export default React.createContext(defaultValue); diff --git a/src/Wrapper.ts b/src/Wrapper.ts index 405dfb72..41b8af77 100644 --- a/src/Wrapper.ts +++ b/src/Wrapper.ts @@ -3,6 +3,7 @@ import PropTypes from 'prop-types'; import * as utils from './utils'; import { RequiredValidation, Validations, WrappedComponentClass } from './interfaces'; +import FormsyContext from './FormsyContext'; /* eslint-disable react/default-props-match-prop-types */ @@ -104,18 +105,19 @@ export default function( WrappedComponent: React.ComponentType>, ): React.ComponentType, keyof InjectedProps>> { return class extends React.Component, WrapperState> { + // eslint-disable-next-line react/sort-comp + public static contextType = FormsyContext; + public validations?: Validations; public requiredValidations?: Validations; + public context: React.ContextType; + public static displayName = `Formsy(${getDisplayName(WrappedComponent)})`; public static propTypes: any = propTypes; - public static contextTypes = { - formsy: PropTypes.object, // What about required? - }; - public static defaultProps: any = { innerRef: null, required: false, @@ -141,7 +143,7 @@ export default function( public componentDidMount() { const { validations, required, name } = this.props; - const { formsy } = this.context; + const { attachToForm } = this.context; if (!name) { throw new Error('Form Input requires a name property when used'); @@ -150,27 +152,23 @@ export default function( this.setValidations(validations, required); // Pass a function instead? - formsy.attachToForm(this); + attachToForm(this); } public shouldComponentUpdate(nextProps, nextState, nextContext) { - const { - props, - state, - context: { formsy: formsyContext }, - } = this; + const { props, state, context } = this; const isPropsChanged = Object.keys(props).some(k => props[k] !== nextProps[k]); const isStateChanged = Object.keys(state).some(k => state[k] !== nextState[k]); - const isFormsyContextChanged = Object.keys(formsyContext).some(k => formsyContext[k] !== nextContext.formsy[k]); + const isFormsyContextChanged = Object.keys(context).some(k => context[k] !== nextContext[k]); return isPropsChanged || isStateChanged || isFormsyContextChanged; } public componentDidUpdate(prevProps) { const { value, validations, required } = this.props; - const { formsy } = this.context; + const { validate } = this.context; // If the value passed has changed, set it. If value is not passed it will // internally update, and this will never run @@ -181,15 +179,15 @@ export default function( // If validations or required is changed, run a new validation if (!utils.isSame(validations, prevProps.validations) || !utils.isSame(required, prevProps.required)) { this.setValidations(validations, required); - formsy.validate(this); + validate(this); } } // Detach it when component unmounts // eslint-disable-next-line react/sort-comp public componentWillUnmount() { - const { formsy } = this.context; - formsy.detachFromForm(this); + const { detachFromForm } = this.context; + detachFromForm(this); } public getErrorMessage = () => { @@ -218,9 +216,8 @@ export default function( // By default, we validate after the value has been set. // A user can override this and pass a second parameter of `false` to skip validation. - public setValue = (value, validate = true) => { - const { formsy } = this.context; - + public setValue = (value: any, validate = true) => { + const { validate: validateForm } = this.context; if (!validate) { this.setState({ value, @@ -232,7 +229,7 @@ export default function( isPristine: false, }, () => { - formsy.validate(this); + validateForm(this); }, ); } @@ -248,7 +245,7 @@ export default function( }; // eslint-disable-next-line react/destructuring-assignment - public isFormDisabled = () => this.context.formsy.isFormDisabled; + public isFormDisabled = () => this.context.isFormDisabled; // eslint-disable-next-line react/destructuring-assignment public isFormSubmitted = () => this.state.formSubmitted; @@ -263,11 +260,11 @@ export default function( public isValid = () => this.state.isValid; // eslint-disable-next-line react/destructuring-assignment - public isValidValue = value => this.context.formsy.isValidValue.call(null, this, value); + public isValidValue = value => this.context.isValidValue(this, value); public resetValue = () => { const { pristineValue } = this.state; - const { formsy } = this.context; + const { validate } = this.context; this.setState( { @@ -275,7 +272,7 @@ export default function( isPristine: true, }, () => { - formsy.validate(this); + validate(this); }, ); }; diff --git a/src/index.ts b/src/index.ts index b77aba06..f8c7fa42 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,6 +5,7 @@ import formDataToObject from 'form-data-to-object'; import * as utils from './utils'; import validationRules from './validationRules'; import Wrapper, { propTypes } from './Wrapper'; +import FormsyContext from './FormsyContext'; import { IData, @@ -14,6 +15,7 @@ import { IUpdateInputsWithValue, IUpdateInputsWithError, ValidationFunction, + FormsyContextInterface, } from './interfaces'; type FormHTMLAttributesCleaned = Omit, 'onChange' | 'onSubmit'>; @@ -51,6 +53,7 @@ export interface FormsyProps extends FormHTMLAttributesCleaned { export interface FormsyState { canChange: boolean; + contextValue: FormsyContextInterface; formSubmitted?: boolean; isPristine?: boolean; isSubmitting: boolean; @@ -95,10 +98,6 @@ class Formsy extends React.Component { validationErrors: PropTypes.object, // eslint-disable-line }; - public static childContextTypes = { - formsy: PropTypes.object, - }; - public static defaultProps: Partial = { disabled: false, getErrorMessage: utils.noop, @@ -135,28 +134,25 @@ class Formsy extends React.Component { canChange: false, isSubmitting: false, isValid: true, + contextValue: { + attachToForm: this.attachToForm, + detachFromForm: this.detachFromForm, + isFormDisabled: props.disabled, + isValidValue: this.isValidValue, + validate: this.validate, + }, }; this.inputs = []; this.emptyArray = []; } - public getChildContext = () => ({ - formsy: { - attachToForm: this.attachToForm, - detachFromForm: this.detachFromForm, - isFormDisabled: this.isFormDisabled(), - isValidValue: this.isValidValue, - validate: this.validate, - }, - }); - public componentDidMount = () => { this.prevInputNames = this.inputs.map(component => component.props.name); this.validateForm(); }; - public componentDidUpdate = () => { - const { validationErrors } = this.props; + public componentDidUpdate = (prevProps: FormsyProps) => { + const { validationErrors, disabled } = this.props; if (validationErrors && typeof validationErrors === 'object' && Object.keys(validationErrors).length > 0) { this.setInputValidationErrors(validationErrors); @@ -167,6 +163,18 @@ class Formsy extends React.Component { this.prevInputNames = newInputNames; this.validateForm(); } + + // Keep the disabled value in state/context the same as from props + if (disabled !== prevProps.disabled) { + // eslint-disable-next-line + this.setState(state => ({ + ...state, + contextValue: { + ...state.contextValue, + isFormDisabled: disabled, + }, + })); + } }; public getCurrentValues = () => @@ -497,6 +505,7 @@ class Formsy extends React.Component { this.setState({ canChange: true, }); + onValidationComplete(); } }; @@ -528,20 +537,27 @@ class Formsy extends React.Component { showError, showRequired, validationErrors, + children, /* eslint-enable @typescript-eslint/no-unused-vars */ ...nonFormsyProps } = this.props; + const { contextValue } = this.state; return React.createElement( - 'form', + FormsyContext.Provider, { - onReset: this.resetInternal, - onSubmit: this.submit, - ...nonFormsyProps, - disabled: false, + value: contextValue, }, - // eslint-disable-next-line react/destructuring-assignment - this.props.children, + React.createElement( + 'form', + { + onReset: this.resetInternal, + onSubmit: this.submit, + ...nonFormsyProps, + disabled: false, + }, + children, + ), ); }; } diff --git a/src/interfaces.ts b/src/interfaces.ts index 4be7685a..0fef2a89 100644 --- a/src/interfaces.ts +++ b/src/interfaces.ts @@ -33,3 +33,11 @@ export interface InputComponent extends React.Component, Wrap validations?: Validations; requiredValidations?: Validations; } + +export interface FormsyContextInterface { + attachToForm: (component: InputComponent) => void; + detachFromForm: (component: InputComponent) => void; + isFormDisabled: boolean; + isValidValue: (component: InputComponent, value: any) => boolean; + validate: (component: InputComponent) => void; +}