styled-hook-form
Version:
React form library for styled-components based on grommet and react-hook-form
167 lines (166 loc) • 8.34 kB
JavaScript
;
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("react");
const react_hook_form_1 = require("react-hook-form");
const use_debounce_1 = require("use-debounce");
const es6_1 = __importDefault(require("fast-deep-equal/es6"));
const comp_1 = require("../../components/utils/comp");
const change_event_store_1 = require("./change-event-store");
const internal_form_context_1 = require("./internal-form-context");
const types_1 = require("../../components/utils/types");
const Form = (props) => {
const { methodsRef, onSubmit, children, changeHandlers: changeHandlersProp, submitTreshould, autoSubmit: autoSubmitProp, autoSubmitFields: autoSubmitFieldsProp, formMethods, options } = props, rest = __rest(props, ["methodsRef", "onSubmit", "children", "changeHandlers", "submitTreshould", "autoSubmit", "autoSubmitFields", "formMethods", "options"]);
//call useForm regardless of formMethods being none null, cause conditionaly calling hook would violate react hook rules
let methods = react_hook_form_1.useForm(Object.assign({ mode: "onTouched" }, options));
if (formMethods) {
methods = formMethods;
}
const changeHandlers = react_1.useRef([]);
const autoSubmitFields = react_1.useRef([]);
const [autoSubmit, updateAutoSubmit] = react_1.useState(autoSubmitProp);
const updateChangeHandlers = react_1.useCallback((newHandlers) => (changeHandlers.current = [...changeHandlers.current, ...newHandlers]), []);
const updateAutoSubmitFields = react_1.useCallback((newFields) => (autoSubmitFields.current = [...autoSubmitFields.current, ...newFields]), []);
react_1.useEffect(() => {
if (changeHandlersProp) {
updateChangeHandlers(changeHandlersProp);
}
}, [changeHandlersProp, updateChangeHandlers]);
react_1.useEffect(() => {
if (autoSubmitFieldsProp) {
updateAutoSubmitFields(autoSubmitFieldsProp);
}
}, [autoSubmitFieldsProp, updateAutoSubmitFields]);
react_1.useEffect(() => {
updateAutoSubmit(autoSubmitProp);
}, [autoSubmitProp]);
let refObj = {
methods,
changeHandlers: new change_event_store_1.ChangeEventStore(),
};
const internalMethodsRef = react_1.useRef(refObj);
if (methodsRef && methods) {
if (typeof methodsRef === "function") {
methodsRef(refObj);
}
else {
methodsRef.current = refObj;
}
}
const { handleSubmit, reset, control } = methods;
const valuesRef = react_1.useRef(null);
let defaultValues = props.options.defaultValues;
react_1.useEffect(() => {
var _a;
const values = methods.getValues();
const newValues = formMethods ? !comp_1.isEmptyObject(values) ? values : defaultValues : defaultValues;
if (!methods.formState.isDirty &&
((comp_1.isEmptyObject(valuesRef.current) && !comp_1.isEmptyObject(newValues)) ||
(Object.keys((_a = valuesRef.current) !== null && _a !== void 0 ? _a : {}).length ===
Object.keys(newValues !== null && newValues !== void 0 ? newValues : {}).length &&
!es6_1.default(valuesRef.current, newValues)))) {
reset(newValues);
valuesRef.current = newValues;
}
}, [defaultValues, formMethods, methods, methods.formState.isDirty, reset]);
const onFormSubmit = (values) => {
onSubmit && onSubmit(values);
return true;
};
const debuncedSubmit = use_debounce_1.useDebouncedCallback((values) => {
onFormSubmit(values);
}, submitTreshould);
react_1.useEffect(() => {
let watchSubscriptions = control._subjects.watch.subscribe({
next: ({ name: ChangingName }) => {
var _a, _b, _c;
const getLiveValue = (name, defaultValues) => control._getWatch(name, defaultValues, false);
//@ts-ignore
if (!control._avoidNotify) {
if (autoSubmit) {
let shouldSubmit = ChangingName
? !autoSubmitFields.current.length ||
(autoSubmitFields &&
autoSubmitFields.current.some((f) => f.name === ChangingName))
: true;
if (shouldSubmit) {
debuncedSubmit(getLiveValue());
}
}
const fieldsToNotify = new Set(ChangingName
? [ChangingName]
: [
...((_a = changeHandlers.current.map((h) => h.name)) !== null && _a !== void 0 ? _a : []),
...((_b = internalMethodsRef.current.changeHandlers.getObservers().map((o) => o.name)) !== null && _b !== void 0 ? _b : []),
]).values();
for (const fieldName of fieldsToNotify) {
const _value = getLiveValue(fieldName, props.options.defaultValues
? props.options.defaultValues[fieldName]
: undefined);
if (methodsRef) {
(_c = internalMethodsRef.current.changeHandlers) === null || _c === void 0 ? void 0 : _c.emitChange(fieldName, _value);
}
let listener = changeHandlers.current.find((f) => f.name === fieldName);
if (listener) {
listener.handler(_value);
}
}
}
else {
//@ts-ignore
control._avoidNotify = null;
}
},
});
return () => watchSubscriptions.unsubscribe();
}, [
autoSubmit,
props.options.defaultValues,
changeHandlers,
autoSubmitFields,
debuncedSubmit,
control,
refObj.changeHandlers,
methodsRef,
]);
const handleFormSubmit = (e) => {
e.stopPropagation();
handleSubmit(onFormSubmit)(e);
};
const registerAutoSubmitField = react_1.useCallback((field) => {
const _autoSubmitFields = autoSubmitFields.current;
const fieldValues = types_1.makeArray(field).filter((f) => _autoSubmitFields.findIndex((inf) => inf.name === f.name) === -1);
if (fieldValues.length) {
updateAutoSubmitFields(fieldValues);
}
}, [updateAutoSubmitFields, autoSubmitFields]);
const registerChangeHandler = react_1.useCallback((handler) => {
const _changeHandlers = changeHandlers.current;
const handlerValues = types_1.makeArray(handler).filter((h) => _changeHandlers.findIndex((inh) => inh.name === h.name) === -1);
if (handlerValues.length) {
updateChangeHandlers(handlerValues);
}
}, [changeHandlers, updateChangeHandlers]);
return (jsx_runtime_1.jsx("form", Object.assign({ onSubmit: handleFormSubmit }, rest, { children: jsx_runtime_1.jsx(react_hook_form_1.FormProvider, Object.assign({}, methods, { children: jsx_runtime_1.jsx(internal_form_context_1.InternalFormContextProvider, Object.assign({ registerAutoSubmitField: registerAutoSubmitField, registerChangeHandler: registerChangeHandler }, { children: children && children(Object.assign({}, methods)) }), void 0) }), void 0) }), void 0));
};
exports.default = Form;
Form.defaultProps = {
autoSubmit: false,
autoSubmitFields: [],
submitTreshould: 500,
};