@os-design/form 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENCE.md +1 -0
- package/README.md +458 -0
- package/dist/cjs/SubscribableData.js +52 -0
- package/dist/cjs/SubscribableData.js.map +1 -0
- package/dist/cjs/SubscriptionManager.js +83 -0
- package/dist/cjs/SubscriptionManager.js.map +1 -0
- package/dist/cjs/index.js +242 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/utils/clone.js +36 -0
- package/dist/cjs/utils/clone.js.map +1 -0
- package/dist/cjs/utils/isEqual.js +44 -0
- package/dist/cjs/utils/isEqual.js.map +1 -0
- package/dist/cjs/utils/useDeepEqualMemo.js +25 -0
- package/dist/cjs/utils/useDeepEqualMemo.js.map +1 -0
- package/dist/esm/SubscribableData.js +23 -0
- package/dist/esm/SubscribableData.js.map +1 -0
- package/dist/esm/SubscriptionManager.js +46 -0
- package/dist/esm/SubscriptionManager.js.map +1 -0
- package/dist/esm/index.js +157 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/utils/clone.js +17 -0
- package/dist/esm/utils/clone.js.map +1 -0
- package/dist/esm/utils/isEqual.js +27 -0
- package/dist/esm/utils/isEqual.js.map +1 -0
- package/dist/esm/utils/useDeepEqualMemo.js +15 -0
- package/dist/esm/utils/useDeepEqualMemo.js.map +1 -0
- package/dist/types/SubscribableData.d.ts +11 -0
- package/dist/types/SubscribableData.d.ts.map +1 -0
- package/dist/types/SubscriptionManager.d.ts +19 -0
- package/dist/types/SubscriptionManager.d.ts.map +1 -0
- package/dist/types/index.d.ts +57 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/utils/clone.d.ts +3 -0
- package/dist/types/utils/clone.d.ts.map +1 -0
- package/dist/types/utils/isEqual.d.ts +3 -0
- package/dist/types/utils/isEqual.d.ts.map +1 -0
- package/dist/types/utils/useDeepEqualMemo.d.ts +4 -0
- package/dist/types/utils/useDeepEqualMemo.d.ts.map +1 -0
- package/package.json +38 -0
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
var _exportNames = {
|
|
8
|
+
FormProvider: true,
|
|
9
|
+
useError: true,
|
|
10
|
+
useForm: true,
|
|
11
|
+
useExistingForm: true
|
|
12
|
+
};
|
|
13
|
+
exports.FormProvider = FormProvider;
|
|
14
|
+
exports.useForm = exports.useExistingForm = exports.useError = void 0;
|
|
15
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
16
|
+
var _SubscribableData = _interopRequireDefault(require("./SubscribableData"));
|
|
17
|
+
var _clone = _interopRequireDefault(require("./utils/clone"));
|
|
18
|
+
var _isEqual = _interopRequireDefault(require("./utils/isEqual"));
|
|
19
|
+
var _useDeepEqualMemo = _interopRequireDefault(require("./utils/useDeepEqualMemo"));
|
|
20
|
+
var _SubscriptionManager = require("./SubscriptionManager");
|
|
21
|
+
Object.keys(_SubscriptionManager).forEach(function (key) {
|
|
22
|
+
if (key === "default" || key === "__esModule") return;
|
|
23
|
+
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
|
24
|
+
if (key in exports && exports[key] === _SubscriptionManager[key]) return;
|
|
25
|
+
Object.defineProperty(exports, key, {
|
|
26
|
+
enumerable: true,
|
|
27
|
+
get: function get() {
|
|
28
|
+
return _SubscriptionManager[key];
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
|
|
33
|
+
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
34
|
+
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
35
|
+
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
|
|
36
|
+
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
37
|
+
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
|
|
38
|
+
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
|
|
39
|
+
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
|
|
40
|
+
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
41
|
+
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
42
|
+
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
|
|
43
|
+
function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
|
|
44
|
+
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
45
|
+
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
|
|
46
|
+
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
|
|
47
|
+
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
48
|
+
var Form = /*#__PURE__*/_createClass(function Form(initValues) {
|
|
49
|
+
_classCallCheck(this, Form);
|
|
50
|
+
this.initValues = void 0;
|
|
51
|
+
this.values = void 0;
|
|
52
|
+
this.errors = void 0;
|
|
53
|
+
this.initValues = initValues;
|
|
54
|
+
this.values = new _SubscribableData["default"]((0, _clone["default"])(initValues));
|
|
55
|
+
this.errors = new _SubscribableData["default"]({});
|
|
56
|
+
});
|
|
57
|
+
var FormContext = /*#__PURE__*/(0, _react.createContext)(null);
|
|
58
|
+
// eslint-disable-next-line react/function-component-definition
|
|
59
|
+
function FormProvider(_ref) {
|
|
60
|
+
var form = _ref.form,
|
|
61
|
+
children = _ref.children;
|
|
62
|
+
return /*#__PURE__*/_react["default"].createElement(FormContext.Provider, {
|
|
63
|
+
value: form
|
|
64
|
+
}, children);
|
|
65
|
+
}
|
|
66
|
+
var createUseValueHook = function createUseValueHook(form) {
|
|
67
|
+
return function (name) {
|
|
68
|
+
var _useState = (0, _react.useState)(form.values.get(name)),
|
|
69
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
70
|
+
value = _useState2[0],
|
|
71
|
+
setValue = _useState2[1];
|
|
72
|
+
(0, _react.useEffect)(function () {
|
|
73
|
+
var subscription = form.values.subscribeToField(name, function (v) {
|
|
74
|
+
setValue(v);
|
|
75
|
+
});
|
|
76
|
+
return function () {
|
|
77
|
+
return subscription.unsubscribe();
|
|
78
|
+
};
|
|
79
|
+
}, [name]);
|
|
80
|
+
return value;
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
var useError = function useError(name, form) {
|
|
84
|
+
var currentForm = (0, _react.useContext)(FormContext) || form;
|
|
85
|
+
if (!currentForm) throw new Error('Specify the form');
|
|
86
|
+
var _useState3 = (0, _react.useState)(currentForm.errors.get(name)),
|
|
87
|
+
_useState4 = _slicedToArray(_useState3, 2),
|
|
88
|
+
value = _useState4[0],
|
|
89
|
+
setValue = _useState4[1];
|
|
90
|
+
(0, _react.useEffect)(function () {
|
|
91
|
+
var subscription = currentForm.errors.subscribeToField(name, function (v) {
|
|
92
|
+
setValue(v);
|
|
93
|
+
});
|
|
94
|
+
return function () {
|
|
95
|
+
return subscription.unsubscribe();
|
|
96
|
+
};
|
|
97
|
+
}, [currentForm.errors, name]);
|
|
98
|
+
return value;
|
|
99
|
+
};
|
|
100
|
+
exports.useError = useError;
|
|
101
|
+
var createUseTransformerHook = function createUseTransformerHook(form) {
|
|
102
|
+
var useValue = createUseValueHook(form);
|
|
103
|
+
return function (name, transformer) {
|
|
104
|
+
var value = useValue(name);
|
|
105
|
+
var transformerRef = (0, _react.useRef)(transformer);
|
|
106
|
+
(0, _react.useEffect)(function () {
|
|
107
|
+
transformerRef.current = transformer;
|
|
108
|
+
}, [transformer]);
|
|
109
|
+
(0, _react.useEffect)(function () {
|
|
110
|
+
var partialValues = transformerRef.current(value);
|
|
111
|
+
Object.entries(partialValues).forEach(function (_ref2) {
|
|
112
|
+
var _ref3 = _slicedToArray(_ref2, 2),
|
|
113
|
+
n = _ref3[0],
|
|
114
|
+
v = _ref3[1];
|
|
115
|
+
form.values.set(n, v);
|
|
116
|
+
});
|
|
117
|
+
}, [value]);
|
|
118
|
+
};
|
|
119
|
+
};
|
|
120
|
+
var createFieldComponent = function createFieldComponent(form) {
|
|
121
|
+
var useValue = createUseValueHook(form);
|
|
122
|
+
return function (props) {
|
|
123
|
+
var name = props.name,
|
|
124
|
+
toValue = props.toValue,
|
|
125
|
+
fromValue = props.fromValue,
|
|
126
|
+
render = props.render;
|
|
127
|
+
var value = useValue(name);
|
|
128
|
+
var transformedValue = (0, _react.useMemo)(function () {
|
|
129
|
+
return toValue ? toValue(value) : value;
|
|
130
|
+
}, [toValue, value]);
|
|
131
|
+
var error = useError(name, form);
|
|
132
|
+
var modified = (0, _react.useMemo)(function () {
|
|
133
|
+
return !(0, _isEqual["default"])(value, form.initValues[name]);
|
|
134
|
+
}, [name, value]);
|
|
135
|
+
var reset = (0, _react.useCallback)(function () {
|
|
136
|
+
return form.values.set(name, form.initValues[name]);
|
|
137
|
+
}, [name]);
|
|
138
|
+
var fromValueRef = (0, _react.useRef)(fromValue);
|
|
139
|
+
(0, _react.useEffect)(function () {
|
|
140
|
+
fromValueRef.current = fromValue;
|
|
141
|
+
}, [fromValue]);
|
|
142
|
+
var onChange = (0, _react.useCallback)(function (v) {
|
|
143
|
+
form.values.set(name, fromValueRef.current ? fromValueRef.current(v) : v);
|
|
144
|
+
form.errors.set(name, undefined);
|
|
145
|
+
}, [name]);
|
|
146
|
+
var renderRef = (0, _react.useRef)(render);
|
|
147
|
+
(0, _react.useEffect)(function () {
|
|
148
|
+
renderRef.current = render;
|
|
149
|
+
}, [render]);
|
|
150
|
+
var inputProps = (0, _react.useMemo)(function () {
|
|
151
|
+
return {
|
|
152
|
+
value: transformedValue,
|
|
153
|
+
onChange: onChange
|
|
154
|
+
};
|
|
155
|
+
}, [onChange, transformedValue]);
|
|
156
|
+
var fieldState = (0, _react.useMemo)(function () {
|
|
157
|
+
return {
|
|
158
|
+
error: error,
|
|
159
|
+
modified: modified,
|
|
160
|
+
reset: reset
|
|
161
|
+
};
|
|
162
|
+
}, [error, modified, reset]);
|
|
163
|
+
return (0, _react.useMemo)(function () {
|
|
164
|
+
return renderRef.current(inputProps, fieldState);
|
|
165
|
+
}, [fieldState, inputProps]);
|
|
166
|
+
};
|
|
167
|
+
};
|
|
168
|
+
var useModifiedFields = function useModifiedFields(form) {
|
|
169
|
+
var _useState5 = (0, _react.useState)([]),
|
|
170
|
+
_useState6 = _slicedToArray(_useState5, 2),
|
|
171
|
+
modifiedFields = _useState6[0],
|
|
172
|
+
setModifiedFields = _useState6[1];
|
|
173
|
+
var modifiedFieldsRef = (0, _react.useRef)(modifiedFields);
|
|
174
|
+
(0, _react.useEffect)(function () {
|
|
175
|
+
modifiedFieldsRef.current = modifiedFields;
|
|
176
|
+
}, [modifiedFields]);
|
|
177
|
+
var initValuesRef = (0, _react.useRef)(form.initValues);
|
|
178
|
+
(0, _react.useEffect)(function () {
|
|
179
|
+
initValuesRef.current = form.initValues;
|
|
180
|
+
}, [form.initValues]);
|
|
181
|
+
(0, _react.useEffect)(function () {
|
|
182
|
+
var subscription = form.values.subscribeToAllFields(function (name, value) {
|
|
183
|
+
var isInitValue = (0, _isEqual["default"])(value, initValuesRef.current[name]);
|
|
184
|
+
var fields = modifiedFieldsRef.current;
|
|
185
|
+
if (fields.includes(name)) {
|
|
186
|
+
if (isInitValue) {
|
|
187
|
+
setModifiedFields(fields.filter(function (field) {
|
|
188
|
+
return field !== name;
|
|
189
|
+
}));
|
|
190
|
+
}
|
|
191
|
+
} else if (!isInitValue) {
|
|
192
|
+
setModifiedFields([].concat(_toConsumableArray(fields), [name]));
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
return function () {
|
|
196
|
+
return subscription.unsubscribe();
|
|
197
|
+
};
|
|
198
|
+
}, [form.values]);
|
|
199
|
+
return modifiedFields;
|
|
200
|
+
};
|
|
201
|
+
var useFormResponse = function useFormResponse(form) {
|
|
202
|
+
var useValue = (0, _react.useMemo)(function () {
|
|
203
|
+
return createUseValueHook(form);
|
|
204
|
+
}, [form]);
|
|
205
|
+
var useTransformer = (0, _react.useMemo)(function () {
|
|
206
|
+
return createUseTransformerHook(form);
|
|
207
|
+
}, [form]);
|
|
208
|
+
var Field = (0, _react.useMemo)(function () {
|
|
209
|
+
return createFieldComponent(form);
|
|
210
|
+
}, [form]);
|
|
211
|
+
var modifiedFields = useModifiedFields(form);
|
|
212
|
+
var modified = (0, _react.useMemo)(function () {
|
|
213
|
+
return modifiedFields.length > 0;
|
|
214
|
+
}, [modifiedFields.length]);
|
|
215
|
+
return (0, _react.useMemo)(function () {
|
|
216
|
+
return {
|
|
217
|
+
form: form,
|
|
218
|
+
Field: Field,
|
|
219
|
+
useValue: useValue,
|
|
220
|
+
useTransformer: useTransformer,
|
|
221
|
+
modifiedFields: modifiedFields,
|
|
222
|
+
modified: modified
|
|
223
|
+
};
|
|
224
|
+
}, [Field, form, modified, modifiedFields, useTransformer, useValue]);
|
|
225
|
+
};
|
|
226
|
+
var useForm = function useForm(initValues) {
|
|
227
|
+
var memoizedInitValues = (0, _useDeepEqualMemo["default"])(function () {
|
|
228
|
+
return initValues;
|
|
229
|
+
}, [initValues]);
|
|
230
|
+
var form = (0, _react.useMemo)(function () {
|
|
231
|
+
return new Form(memoizedInitValues);
|
|
232
|
+
}, [memoizedInitValues]);
|
|
233
|
+
return useFormResponse(form);
|
|
234
|
+
};
|
|
235
|
+
exports.useForm = useForm;
|
|
236
|
+
var useExistingForm = function useExistingForm() {
|
|
237
|
+
var form = (0, _react.useContext)(FormContext);
|
|
238
|
+
if (!form) throw new Error('Wrap your form in a FormProvider');
|
|
239
|
+
return useFormResponse(form);
|
|
240
|
+
};
|
|
241
|
+
exports.useExistingForm = useExistingForm;
|
|
242
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["Form","initValues","values","errors","SubscribableData","clone","FormContext","createContext","FormProvider","form","children","createUseValueHook","name","useState","get","value","setValue","useEffect","subscription","subscribeToField","v","unsubscribe","useError","currentForm","useContext","Error","createUseTransformerHook","useValue","transformer","transformerRef","useRef","current","partialValues","Object","entries","forEach","n","set","createFieldComponent","props","toValue","fromValue","render","transformedValue","useMemo","error","modified","isEqual","reset","useCallback","fromValueRef","onChange","undefined","renderRef","inputProps","fieldState","useModifiedFields","modifiedFields","setModifiedFields","modifiedFieldsRef","initValuesRef","subscribeToAllFields","isInitValue","fields","includes","filter","field","useFormResponse","useTransformer","Field","length","useForm","memoizedInitValues","useDeepEqualMemo","useExistingForm"],"sources":["../../src/index.tsx"],"sourcesContent":["import React, {\n createContext,\n ReactNode,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport SubscribableData from './SubscribableData';\nimport clone from './utils/clone';\nimport isEqual from './utils/isEqual';\nimport useDeepEqualMemo from './utils/useDeepEqualMemo';\n\nexport * from './SubscriptionManager';\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\ntype Values = Record<string, any>;\ntype Errors<TValues extends Values> = Record<keyof TValues, string | undefined>;\n\nclass Form<\n TValues extends Values,\n TErrors extends Errors<TValues> = Errors<TValues>\n> {\n public readonly initValues: TValues;\n\n public readonly values: SubscribableData<TValues>;\n\n public readonly errors: SubscribableData<TErrors>;\n\n public constructor(initValues: TValues) {\n this.initValues = initValues;\n this.values = new SubscribableData(clone(initValues));\n this.errors = new SubscribableData({} as TErrors);\n }\n}\n\nconst FormContext = createContext<any>(null);\n\ninterface FormProviderProps<TValues extends Values> {\n form: Form<TValues>;\n children?: ReactNode;\n}\n\n// eslint-disable-next-line react/function-component-definition\nexport function FormProvider<TValues extends Values>({\n form,\n children,\n}: FormProviderProps<TValues>) {\n return <FormContext.Provider value={form}>{children}</FormContext.Provider>;\n}\n\nconst createUseValueHook =\n <TValues extends Values>(form: Form<TValues>) =>\n <TName extends keyof TValues>(name: TName) => {\n const [value, setValue] = useState<TValues[TName]>(form.values.get(name));\n\n useEffect(() => {\n const subscription = form.values.subscribeToField(name, (v) => {\n setValue(v);\n });\n return () => subscription.unsubscribe();\n }, [name]);\n\n return value;\n };\n\nexport const useError = <\n TValues extends Values = Values,\n TName extends keyof TValues = keyof TValues\n>(\n name: TName,\n form?: Form<TValues>\n) => {\n const currentForm = useContext(FormContext) || form;\n if (!currentForm) throw new Error('Specify the form');\n const [value, setValue] = useState<string | undefined>(\n currentForm.errors.get(name)\n );\n\n useEffect(() => {\n const subscription = currentForm.errors.subscribeToField(name, (v) => {\n setValue(v);\n });\n return () => subscription.unsubscribe();\n }, [currentForm.errors, name]);\n\n return value;\n};\n\nexport type Transformer<TValues extends Values, TName extends keyof TValues> = (\n value: TValues[TName]\n) => Partial<TValues>;\n\nconst createUseTransformerHook = <TValues extends Values>(\n form: Form<TValues>\n) => {\n const useValue = createUseValueHook(form);\n return <TName extends keyof TValues>(\n name: TName,\n transformer: Transformer<TValues, TName>\n ) => {\n const value = useValue(name);\n\n const transformerRef = useRef(transformer);\n useEffect(() => {\n transformerRef.current = transformer;\n }, [transformer]);\n\n useEffect(() => {\n const partialValues = transformerRef.current(value);\n Object.entries(partialValues).forEach(([n, v]) => {\n form.values.set(n, v);\n });\n }, [value]);\n };\n};\n\ninterface InputProps<T> {\n value: T;\n onChange: (value: T) => void;\n}\ninterface FieldState {\n error?: string;\n modified: boolean;\n reset: () => void;\n}\ninterface FieldPropsWithoutTransformers<TName, TStateValue> {\n name: TName;\n toValue?: never;\n fromValue?: never;\n render: (\n inputProps: InputProps<TStateValue>,\n fieldState: FieldState\n ) => React.ReactElement;\n}\ninterface FieldPropsWithTransformers<TName, TStateValue, TInputValue> {\n name: TName;\n toValue: (value: TStateValue) => TInputValue;\n fromValue?: (value: TInputValue) => TStateValue;\n render: (\n inputProps: InputProps<TInputValue>,\n fieldState: FieldState\n ) => React.ReactElement;\n}\ntype FieldProps<TName, TStateValue, TInputValue> =\n | FieldPropsWithoutTransformers<TName, TStateValue>\n | FieldPropsWithTransformers<TName, TStateValue, TInputValue>;\n\nconst createFieldComponent = <TValues extends Values>(form: Form<TValues>) => {\n const useValue = createUseValueHook(form);\n return <TName extends keyof TValues>(\n props: FieldProps<TName, TValues[TName], any>\n ) => {\n const { name, toValue, fromValue, render } = props;\n\n const value = useValue(name);\n const transformedValue = useMemo<any>(\n () => (toValue ? toValue(value) : value),\n [toValue, value]\n );\n const error = useError<TValues>(name, form);\n\n const modified = useMemo(\n () => !isEqual(value, form.initValues[name]),\n [name, value]\n );\n const reset = useCallback(\n () => form.values.set(name, form.initValues[name]),\n [name]\n );\n\n const fromValueRef = useRef(fromValue);\n useEffect(() => {\n fromValueRef.current = fromValue;\n }, [fromValue]);\n\n const onChange = useCallback(\n (v: any) => {\n form.values.set(\n name,\n fromValueRef.current ? fromValueRef.current(v) : (v as TValues[TName])\n );\n form.errors.set(name, undefined);\n },\n [name]\n );\n\n const renderRef = useRef(render);\n useEffect(() => {\n renderRef.current = render;\n }, [render]);\n\n const inputProps = useMemo(\n () => ({ value: transformedValue, onChange }),\n [onChange, transformedValue]\n );\n const fieldState = useMemo(\n () => ({ error, modified, reset }),\n [error, modified, reset]\n );\n\n return useMemo(\n () => renderRef.current(inputProps, fieldState),\n [fieldState, inputProps]\n );\n };\n};\n\nconst useModifiedFields = <TValues extends Values>(form: Form<TValues>) => {\n const [modifiedFields, setModifiedFields] = useState<Array<keyof TValues>>(\n []\n );\n\n const modifiedFieldsRef = useRef(modifiedFields);\n useEffect(() => {\n modifiedFieldsRef.current = modifiedFields;\n }, [modifiedFields]);\n\n const initValuesRef = useRef(form.initValues);\n useEffect(() => {\n initValuesRef.current = form.initValues;\n }, [form.initValues]);\n\n useEffect(() => {\n const subscription = form.values.subscribeToAllFields((name, value) => {\n const isInitValue = isEqual(value, initValuesRef.current[name]);\n const fields = modifiedFieldsRef.current;\n\n if (fields.includes(name)) {\n if (isInitValue) {\n setModifiedFields(fields.filter((field) => field !== name));\n }\n } else if (!isInitValue) {\n setModifiedFields([...fields, name]);\n }\n });\n return () => subscription.unsubscribe();\n }, [form.values]);\n\n return modifiedFields;\n};\n\nconst useFormResponse = <TValues extends Values>(form: Form<TValues>) => {\n const useValue = useMemo(() => createUseValueHook(form), [form]);\n const useTransformer = useMemo(() => createUseTransformerHook(form), [form]);\n const Field = useMemo(() => createFieldComponent(form), [form]);\n\n const modifiedFields = useModifiedFields(form);\n const modified = useMemo(\n () => modifiedFields.length > 0,\n [modifiedFields.length]\n );\n\n return useMemo(\n () => ({\n form,\n Field,\n useValue,\n useTransformer,\n modifiedFields,\n modified,\n }),\n [Field, form, modified, modifiedFields, useTransformer, useValue]\n );\n};\n\nexport const useForm = <TValues extends Values = Values>(\n initValues: TValues\n) => {\n const memoizedInitValues = useDeepEqualMemo<TValues>(\n () => initValues,\n [initValues]\n );\n const form = useMemo(\n () => new Form<TValues>(memoizedInitValues),\n [memoizedInitValues]\n );\n return useFormResponse(form);\n};\n\nexport const useExistingForm = <TValues extends Values = Values>() => {\n const form = useContext<Form<TValues> | null>(FormContext);\n if (!form) throw new Error('Wrap your form in a FormProvider');\n return useFormResponse(form);\n};\n"],"mappings":";;;;;;;;;;;;;;AAAA;AAUA;AACA;AACA;AACA;AAEA;AAAA;EAAA;EAAA;EAAA;EAAA;IAAA;IAAA;MAAA;IAAA;EAAA;AAAA;AAAsC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOhCA,IAAI,6BAUR,cAAmBC,UAAmB,EAAE;EAAA;EAAA,KANxBA,UAAU;EAAA,KAEVC,MAAM;EAAA,KAENC,MAAM;EAGpB,IAAI,CAACF,UAAU,GAAGA,UAAU;EAC5B,IAAI,CAACC,MAAM,GAAG,IAAIE,4BAAgB,CAAC,IAAAC,iBAAK,EAACJ,UAAU,CAAC,CAAC;EACrD,IAAI,CAACE,MAAM,GAAG,IAAIC,4BAAgB,CAAC,CAAC,CAAC,CAAY;AACnD,CAAC;AAGH,IAAME,WAAW,gBAAG,IAAAC,oBAAa,EAAM,IAAI,CAAC;AAO5C;AACO,SAASC,YAAY,OAGG;EAAA,IAF7BC,IAAI,QAAJA,IAAI;IACJC,QAAQ,QAARA,QAAQ;EAER,oBAAO,gCAAC,WAAW,CAAC,QAAQ;IAAC,KAAK,EAAED;EAAK,GAAEC,QAAQ,CAAwB;AAC7E;AAEA,IAAMC,kBAAkB,GACtB,SADIA,kBAAkB,CACGF,IAAmB;EAAA,OAC5C,UAA8BG,IAAW,EAAK;IAC5C,gBAA0B,IAAAC,eAAQ,EAAiBJ,IAAI,CAACP,MAAM,CAACY,GAAG,CAACF,IAAI,CAAC,CAAC;MAAA;MAAlEG,KAAK;MAAEC,QAAQ;IAEtB,IAAAC,gBAAS,EAAC,YAAM;MACd,IAAMC,YAAY,GAAGT,IAAI,CAACP,MAAM,CAACiB,gBAAgB,CAACP,IAAI,EAAE,UAACQ,CAAC,EAAK;QAC7DJ,QAAQ,CAACI,CAAC,CAAC;MACb,CAAC,CAAC;MACF,OAAO;QAAA,OAAMF,YAAY,CAACG,WAAW,EAAE;MAAA;IACzC,CAAC,EAAE,CAACT,IAAI,CAAC,CAAC;IAEV,OAAOG,KAAK;EACd,CAAC;AAAA;AAEI,IAAMO,QAAQ,GAAG,SAAXA,QAAQ,CAInBV,IAAW,EACXH,IAAoB,EACjB;EACH,IAAMc,WAAW,GAAG,IAAAC,iBAAU,EAAClB,WAAW,CAAC,IAAIG,IAAI;EACnD,IAAI,CAACc,WAAW,EAAE,MAAM,IAAIE,KAAK,CAAC,kBAAkB,CAAC;EACrD,iBAA0B,IAAAZ,eAAQ,EAChCU,WAAW,CAACpB,MAAM,CAACW,GAAG,CAACF,IAAI,CAAC,CAC7B;IAAA;IAFMG,KAAK;IAAEC,QAAQ;EAItB,IAAAC,gBAAS,EAAC,YAAM;IACd,IAAMC,YAAY,GAAGK,WAAW,CAACpB,MAAM,CAACgB,gBAAgB,CAACP,IAAI,EAAE,UAACQ,CAAC,EAAK;MACpEJ,QAAQ,CAACI,CAAC,CAAC;IACb,CAAC,CAAC;IACF,OAAO;MAAA,OAAMF,YAAY,CAACG,WAAW,EAAE;IAAA;EACzC,CAAC,EAAE,CAACE,WAAW,CAACpB,MAAM,EAAES,IAAI,CAAC,CAAC;EAE9B,OAAOG,KAAK;AACd,CAAC;AAAC;AAMF,IAAMW,wBAAwB,GAAG,SAA3BA,wBAAwB,CAC5BjB,IAAmB,EAChB;EACH,IAAMkB,QAAQ,GAAGhB,kBAAkB,CAACF,IAAI,CAAC;EACzC,OAAO,UACLG,IAAW,EACXgB,WAAwC,EACrC;IACH,IAAMb,KAAK,GAAGY,QAAQ,CAACf,IAAI,CAAC;IAE5B,IAAMiB,cAAc,GAAG,IAAAC,aAAM,EAACF,WAAW,CAAC;IAC1C,IAAAX,gBAAS,EAAC,YAAM;MACdY,cAAc,CAACE,OAAO,GAAGH,WAAW;IACtC,CAAC,EAAE,CAACA,WAAW,CAAC,CAAC;IAEjB,IAAAX,gBAAS,EAAC,YAAM;MACd,IAAMe,aAAa,GAAGH,cAAc,CAACE,OAAO,CAAChB,KAAK,CAAC;MACnDkB,MAAM,CAACC,OAAO,CAACF,aAAa,CAAC,CAACG,OAAO,CAAC,iBAAY;QAAA;UAAVC,CAAC;UAAEhB,CAAC;QAC1CX,IAAI,CAACP,MAAM,CAACmC,GAAG,CAACD,CAAC,EAAEhB,CAAC,CAAC;MACvB,CAAC,CAAC;IACJ,CAAC,EAAE,CAACL,KAAK,CAAC,CAAC;EACb,CAAC;AACH,CAAC;AAiCD,IAAMuB,oBAAoB,GAAG,SAAvBA,oBAAoB,CAA4B7B,IAAmB,EAAK;EAC5E,IAAMkB,QAAQ,GAAGhB,kBAAkB,CAACF,IAAI,CAAC;EACzC,OAAO,UACL8B,KAA6C,EAC1C;IACH,IAAQ3B,IAAI,GAAiC2B,KAAK,CAA1C3B,IAAI;MAAE4B,OAAO,GAAwBD,KAAK,CAApCC,OAAO;MAAEC,SAAS,GAAaF,KAAK,CAA3BE,SAAS;MAAEC,MAAM,GAAKH,KAAK,CAAhBG,MAAM;IAExC,IAAM3B,KAAK,GAAGY,QAAQ,CAACf,IAAI,CAAC;IAC5B,IAAM+B,gBAAgB,GAAG,IAAAC,cAAO,EAC9B;MAAA,OAAOJ,OAAO,GAAGA,OAAO,CAACzB,KAAK,CAAC,GAAGA,KAAK;IAAA,CAAC,EACxC,CAACyB,OAAO,EAAEzB,KAAK,CAAC,CACjB;IACD,IAAM8B,KAAK,GAAGvB,QAAQ,CAAUV,IAAI,EAAEH,IAAI,CAAC;IAE3C,IAAMqC,QAAQ,GAAG,IAAAF,cAAO,EACtB;MAAA,OAAM,CAAC,IAAAG,mBAAO,EAAChC,KAAK,EAAEN,IAAI,CAACR,UAAU,CAACW,IAAI,CAAC,CAAC;IAAA,GAC5C,CAACA,IAAI,EAAEG,KAAK,CAAC,CACd;IACD,IAAMiC,KAAK,GAAG,IAAAC,kBAAW,EACvB;MAAA,OAAMxC,IAAI,CAACP,MAAM,CAACmC,GAAG,CAACzB,IAAI,EAAEH,IAAI,CAACR,UAAU,CAACW,IAAI,CAAC,CAAC;IAAA,GAClD,CAACA,IAAI,CAAC,CACP;IAED,IAAMsC,YAAY,GAAG,IAAApB,aAAM,EAACW,SAAS,CAAC;IACtC,IAAAxB,gBAAS,EAAC,YAAM;MACdiC,YAAY,CAACnB,OAAO,GAAGU,SAAS;IAClC,CAAC,EAAE,CAACA,SAAS,CAAC,CAAC;IAEf,IAAMU,QAAQ,GAAG,IAAAF,kBAAW,EAC1B,UAAC7B,CAAM,EAAK;MACVX,IAAI,CAACP,MAAM,CAACmC,GAAG,CACbzB,IAAI,EACJsC,YAAY,CAACnB,OAAO,GAAGmB,YAAY,CAACnB,OAAO,CAACX,CAAC,CAAC,GAAIA,CAAoB,CACvE;MACDX,IAAI,CAACN,MAAM,CAACkC,GAAG,CAACzB,IAAI,EAAEwC,SAAS,CAAC;IAClC,CAAC,EACD,CAACxC,IAAI,CAAC,CACP;IAED,IAAMyC,SAAS,GAAG,IAAAvB,aAAM,EAACY,MAAM,CAAC;IAChC,IAAAzB,gBAAS,EAAC,YAAM;MACdoC,SAAS,CAACtB,OAAO,GAAGW,MAAM;IAC5B,CAAC,EAAE,CAACA,MAAM,CAAC,CAAC;IAEZ,IAAMY,UAAU,GAAG,IAAAV,cAAO,EACxB;MAAA,OAAO;QAAE7B,KAAK,EAAE4B,gBAAgB;QAAEQ,QAAQ,EAARA;MAAS,CAAC;IAAA,CAAC,EAC7C,CAACA,QAAQ,EAAER,gBAAgB,CAAC,CAC7B;IACD,IAAMY,UAAU,GAAG,IAAAX,cAAO,EACxB;MAAA,OAAO;QAAEC,KAAK,EAALA,KAAK;QAAEC,QAAQ,EAARA,QAAQ;QAAEE,KAAK,EAALA;MAAM,CAAC;IAAA,CAAC,EAClC,CAACH,KAAK,EAAEC,QAAQ,EAAEE,KAAK,CAAC,CACzB;IAED,OAAO,IAAAJ,cAAO,EACZ;MAAA,OAAMS,SAAS,CAACtB,OAAO,CAACuB,UAAU,EAAEC,UAAU,CAAC;IAAA,GAC/C,CAACA,UAAU,EAAED,UAAU,CAAC,CACzB;EACH,CAAC;AACH,CAAC;AAED,IAAME,iBAAiB,GAAG,SAApBA,iBAAiB,CAA4B/C,IAAmB,EAAK;EACzE,iBAA4C,IAAAI,eAAQ,EAClD,EAAE,CACH;IAAA;IAFM4C,cAAc;IAAEC,iBAAiB;EAIxC,IAAMC,iBAAiB,GAAG,IAAA7B,aAAM,EAAC2B,cAAc,CAAC;EAChD,IAAAxC,gBAAS,EAAC,YAAM;IACd0C,iBAAiB,CAAC5B,OAAO,GAAG0B,cAAc;EAC5C,CAAC,EAAE,CAACA,cAAc,CAAC,CAAC;EAEpB,IAAMG,aAAa,GAAG,IAAA9B,aAAM,EAACrB,IAAI,CAACR,UAAU,CAAC;EAC7C,IAAAgB,gBAAS,EAAC,YAAM;IACd2C,aAAa,CAAC7B,OAAO,GAAGtB,IAAI,CAACR,UAAU;EACzC,CAAC,EAAE,CAACQ,IAAI,CAACR,UAAU,CAAC,CAAC;EAErB,IAAAgB,gBAAS,EAAC,YAAM;IACd,IAAMC,YAAY,GAAGT,IAAI,CAACP,MAAM,CAAC2D,oBAAoB,CAAC,UAACjD,IAAI,EAAEG,KAAK,EAAK;MACrE,IAAM+C,WAAW,GAAG,IAAAf,mBAAO,EAAChC,KAAK,EAAE6C,aAAa,CAAC7B,OAAO,CAACnB,IAAI,CAAC,CAAC;MAC/D,IAAMmD,MAAM,GAAGJ,iBAAiB,CAAC5B,OAAO;MAExC,IAAIgC,MAAM,CAACC,QAAQ,CAACpD,IAAI,CAAC,EAAE;QACzB,IAAIkD,WAAW,EAAE;UACfJ,iBAAiB,CAACK,MAAM,CAACE,MAAM,CAAC,UAACC,KAAK;YAAA,OAAKA,KAAK,KAAKtD,IAAI;UAAA,EAAC,CAAC;QAC7D;MACF,CAAC,MAAM,IAAI,CAACkD,WAAW,EAAE;QACvBJ,iBAAiB,8BAAKK,MAAM,IAAEnD,IAAI,GAAE;MACtC;IACF,CAAC,CAAC;IACF,OAAO;MAAA,OAAMM,YAAY,CAACG,WAAW,EAAE;IAAA;EACzC,CAAC,EAAE,CAACZ,IAAI,CAACP,MAAM,CAAC,CAAC;EAEjB,OAAOuD,cAAc;AACvB,CAAC;AAED,IAAMU,eAAe,GAAG,SAAlBA,eAAe,CAA4B1D,IAAmB,EAAK;EACvE,IAAMkB,QAAQ,GAAG,IAAAiB,cAAO,EAAC;IAAA,OAAMjC,kBAAkB,CAACF,IAAI,CAAC;EAAA,GAAE,CAACA,IAAI,CAAC,CAAC;EAChE,IAAM2D,cAAc,GAAG,IAAAxB,cAAO,EAAC;IAAA,OAAMlB,wBAAwB,CAACjB,IAAI,CAAC;EAAA,GAAE,CAACA,IAAI,CAAC,CAAC;EAC5E,IAAM4D,KAAK,GAAG,IAAAzB,cAAO,EAAC;IAAA,OAAMN,oBAAoB,CAAC7B,IAAI,CAAC;EAAA,GAAE,CAACA,IAAI,CAAC,CAAC;EAE/D,IAAMgD,cAAc,GAAGD,iBAAiB,CAAC/C,IAAI,CAAC;EAC9C,IAAMqC,QAAQ,GAAG,IAAAF,cAAO,EACtB;IAAA,OAAMa,cAAc,CAACa,MAAM,GAAG,CAAC;EAAA,GAC/B,CAACb,cAAc,CAACa,MAAM,CAAC,CACxB;EAED,OAAO,IAAA1B,cAAO,EACZ;IAAA,OAAO;MACLnC,IAAI,EAAJA,IAAI;MACJ4D,KAAK,EAALA,KAAK;MACL1C,QAAQ,EAARA,QAAQ;MACRyC,cAAc,EAAdA,cAAc;MACdX,cAAc,EAAdA,cAAc;MACdX,QAAQ,EAARA;IACF,CAAC;EAAA,CAAC,EACF,CAACuB,KAAK,EAAE5D,IAAI,EAAEqC,QAAQ,EAAEW,cAAc,EAAEW,cAAc,EAAEzC,QAAQ,CAAC,CAClE;AACH,CAAC;AAEM,IAAM4C,OAAO,GAAG,SAAVA,OAAO,CAClBtE,UAAmB,EAChB;EACH,IAAMuE,kBAAkB,GAAG,IAAAC,4BAAgB,EACzC;IAAA,OAAMxE,UAAU;EAAA,GAChB,CAACA,UAAU,CAAC,CACb;EACD,IAAMQ,IAAI,GAAG,IAAAmC,cAAO,EAClB;IAAA,OAAM,IAAI5C,IAAI,CAAUwE,kBAAkB,CAAC;EAAA,GAC3C,CAACA,kBAAkB,CAAC,CACrB;EACD,OAAOL,eAAe,CAAC1D,IAAI,CAAC;AAC9B,CAAC;AAAC;AAEK,IAAMiE,eAAe,GAAG,SAAlBA,eAAe,GAA0C;EACpE,IAAMjE,IAAI,GAAG,IAAAe,iBAAU,EAAuBlB,WAAW,CAAC;EAC1D,IAAI,CAACG,IAAI,EAAE,MAAM,IAAIgB,KAAK,CAAC,kCAAkC,CAAC;EAC9D,OAAO0C,eAAe,CAAC1D,IAAI,CAAC;AAC9B,CAAC;AAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports["default"] = void 0;
|
|
7
|
+
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
|
|
8
|
+
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
9
|
+
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
10
|
+
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
|
|
11
|
+
function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
|
|
12
|
+
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
13
|
+
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
|
|
14
|
+
var clone = function clone(value) {
|
|
15
|
+
if (_typeof(value) === 'object') {
|
|
16
|
+
if (Array.isArray(value)) {
|
|
17
|
+
return value.map(function (item) {
|
|
18
|
+
return clone(item);
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
if (value !== null) {
|
|
22
|
+
var clonedObj = {};
|
|
23
|
+
Object.entries(value).forEach(function (_ref) {
|
|
24
|
+
var _ref2 = _slicedToArray(_ref, 2),
|
|
25
|
+
objKey = _ref2[0],
|
|
26
|
+
objValue = _ref2[1];
|
|
27
|
+
clonedObj[objKey] = clone(objValue);
|
|
28
|
+
});
|
|
29
|
+
return clonedObj;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return value;
|
|
33
|
+
};
|
|
34
|
+
var _default = clone;
|
|
35
|
+
exports["default"] = _default;
|
|
36
|
+
//# sourceMappingURL=clone.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clone.js","names":["clone","value","Array","isArray","map","item","clonedObj","Object","entries","forEach","objKey","objValue"],"sources":["../../../src/utils/clone.ts"],"sourcesContent":["const clone = <T>(value: T): T => {\n if (typeof value === 'object') {\n if (Array.isArray(value)) {\n return value.map((item) => clone(item)) as T;\n }\n\n if (value !== null) {\n const clonedObj = {};\n Object.entries(value).forEach(([objKey, objValue]) => {\n clonedObj[objKey] = clone(objValue);\n });\n return clonedObj as T;\n }\n }\n\n return value;\n};\n\nexport default clone;\n"],"mappings":";;;;;;;;;;;;;AAAA,IAAMA,KAAK,GAAG,SAARA,KAAK,CAAOC,KAAQ,EAAQ;EAChC,IAAI,QAAOA,KAAK,MAAK,QAAQ,EAAE;IAC7B,IAAIC,KAAK,CAACC,OAAO,CAACF,KAAK,CAAC,EAAE;MACxB,OAAOA,KAAK,CAACG,GAAG,CAAC,UAACC,IAAI;QAAA,OAAKL,KAAK,CAACK,IAAI,CAAC;MAAA,EAAC;IACzC;IAEA,IAAIJ,KAAK,KAAK,IAAI,EAAE;MAClB,IAAMK,SAAS,GAAG,CAAC,CAAC;MACpBC,MAAM,CAACC,OAAO,CAACP,KAAK,CAAC,CAACQ,OAAO,CAAC,gBAAwB;QAAA;UAAtBC,MAAM;UAAEC,QAAQ;QAC9CL,SAAS,CAACI,MAAM,CAAC,GAAGV,KAAK,CAACW,QAAQ,CAAC;MACrC,CAAC,CAAC;MACF,OAAOL,SAAS;IAClB;EACF;EAEA,OAAOL,KAAK;AACd,CAAC;AAAC,eAEaD,KAAK;AAAA"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports["default"] = void 0;
|
|
7
|
+
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
|
|
8
|
+
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
9
|
+
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
10
|
+
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
|
|
11
|
+
function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
|
|
12
|
+
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
13
|
+
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
|
|
14
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
15
|
+
var isEqual = function isEqual(value1, value2) {
|
|
16
|
+
if (_typeof(value1) !== _typeof(value2)) return false;
|
|
17
|
+
if (_typeof(value1) === 'object') {
|
|
18
|
+
if (Array.isArray(value1) !== Array.isArray(value2)) return false;
|
|
19
|
+
if (Array.isArray(value1)) {
|
|
20
|
+
if (value1.length !== value2.length) return false;
|
|
21
|
+
return value1.every(function (item1, index) {
|
|
22
|
+
var item2 = value2[index];
|
|
23
|
+
return isEqual(item1, item2);
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
if (value1 !== null && value2 !== null) {
|
|
27
|
+
if (Object.keys(value1).length !== Object.keys(value2).length) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
return Object.entries(value1).every(function (_ref) {
|
|
31
|
+
var _ref2 = _slicedToArray(_ref, 2),
|
|
32
|
+
objKey = _ref2[0],
|
|
33
|
+
objValue1 = _ref2[1];
|
|
34
|
+
if (!Object.hasOwn(value2, objKey)) return false;
|
|
35
|
+
var objValue2 = value2[objKey];
|
|
36
|
+
return isEqual(objValue1, objValue2);
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return Object.is(value1, value2);
|
|
41
|
+
};
|
|
42
|
+
var _default = isEqual;
|
|
43
|
+
exports["default"] = _default;
|
|
44
|
+
//# sourceMappingURL=isEqual.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"isEqual.js","names":["isEqual","value1","value2","Array","isArray","length","every","item1","index","item2","Object","keys","entries","objKey","objValue1","hasOwn","objValue2","is"],"sources":["../../../src/utils/isEqual.ts"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst isEqual = (value1: any, value2: any): boolean => {\n if (typeof value1 !== typeof value2) return false;\n\n if (typeof value1 === 'object') {\n if (Array.isArray(value1) !== Array.isArray(value2)) return false;\n\n if (Array.isArray(value1)) {\n if (value1.length !== value2.length) return false;\n\n return value1.every((item1, index) => {\n const item2 = value2[index];\n return isEqual(item1, item2);\n });\n }\n\n if (value1 !== null && value2 !== null) {\n if (Object.keys(value1).length !== Object.keys(value2).length) {\n return false;\n }\n\n return Object.entries(value1).every(([objKey, objValue1]) => {\n if (!Object.hasOwn(value2, objKey)) return false;\n const objValue2 = value2[objKey];\n return isEqual(objValue1, objValue2);\n });\n }\n }\n\n return Object.is(value1, value2);\n};\n\nexport default isEqual;\n"],"mappings":";;;;;;;;;;;;;AAAA;AACA,IAAMA,OAAO,GAAG,SAAVA,OAAO,CAAIC,MAAW,EAAEC,MAAW,EAAc;EACrD,IAAI,QAAOD,MAAM,cAAYC,MAAM,GAAE,OAAO,KAAK;EAEjD,IAAI,QAAOD,MAAM,MAAK,QAAQ,EAAE;IAC9B,IAAIE,KAAK,CAACC,OAAO,CAACH,MAAM,CAAC,KAAKE,KAAK,CAACC,OAAO,CAACF,MAAM,CAAC,EAAE,OAAO,KAAK;IAEjE,IAAIC,KAAK,CAACC,OAAO,CAACH,MAAM,CAAC,EAAE;MACzB,IAAIA,MAAM,CAACI,MAAM,KAAKH,MAAM,CAACG,MAAM,EAAE,OAAO,KAAK;MAEjD,OAAOJ,MAAM,CAACK,KAAK,CAAC,UAACC,KAAK,EAAEC,KAAK,EAAK;QACpC,IAAMC,KAAK,GAAGP,MAAM,CAACM,KAAK,CAAC;QAC3B,OAAOR,OAAO,CAACO,KAAK,EAAEE,KAAK,CAAC;MAC9B,CAAC,CAAC;IACJ;IAEA,IAAIR,MAAM,KAAK,IAAI,IAAIC,MAAM,KAAK,IAAI,EAAE;MACtC,IAAIQ,MAAM,CAACC,IAAI,CAACV,MAAM,CAAC,CAACI,MAAM,KAAKK,MAAM,CAACC,IAAI,CAACT,MAAM,CAAC,CAACG,MAAM,EAAE;QAC7D,OAAO,KAAK;MACd;MAEA,OAAOK,MAAM,CAACE,OAAO,CAACX,MAAM,CAAC,CAACK,KAAK,CAAC,gBAAyB;QAAA;UAAvBO,MAAM;UAAEC,SAAS;QACrD,IAAI,CAACJ,MAAM,CAACK,MAAM,CAACb,MAAM,EAAEW,MAAM,CAAC,EAAE,OAAO,KAAK;QAChD,IAAMG,SAAS,GAAGd,MAAM,CAACW,MAAM,CAAC;QAChC,OAAOb,OAAO,CAACc,SAAS,EAAEE,SAAS,CAAC;MACtC,CAAC,CAAC;IACJ;EACF;EAEA,OAAON,MAAM,CAACO,EAAE,CAAChB,MAAM,EAAEC,MAAM,CAAC;AAClC,CAAC;AAAC,eAEaF,OAAO;AAAA"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports["default"] = void 0;
|
|
7
|
+
var _react = require("react");
|
|
8
|
+
var _clone = _interopRequireDefault(require("./clone"));
|
|
9
|
+
var _isEqual = _interopRequireDefault(require("./isEqual"));
|
|
10
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
|
|
11
|
+
var useDeepEqualMemoize = function useDeepEqualMemoize(value) {
|
|
12
|
+
var ref = (0, _react.useRef)(undefined);
|
|
13
|
+
if (!(0, _isEqual["default"])(ref.current, value)) {
|
|
14
|
+
ref.current = (0, _clone["default"])(value);
|
|
15
|
+
}
|
|
16
|
+
return ref.current;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/* eslint-disable react-hooks/exhaustive-deps */
|
|
20
|
+
var useDeepEqualMemo = function useDeepEqualMemo(factory, deps) {
|
|
21
|
+
return (0, _react.useMemo)(factory, deps ? deps.map(useDeepEqualMemoize) : undefined);
|
|
22
|
+
};
|
|
23
|
+
var _default = useDeepEqualMemo;
|
|
24
|
+
exports["default"] = _default;
|
|
25
|
+
//# sourceMappingURL=useDeepEqualMemo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDeepEqualMemo.js","names":["useDeepEqualMemoize","value","ref","useRef","undefined","isEqual","current","clone","useDeepEqualMemo","factory","deps","useMemo","map"],"sources":["../../../src/utils/useDeepEqualMemo.ts"],"sourcesContent":["import { DependencyList, useMemo, useRef } from 'react';\nimport clone from './clone';\nimport isEqual from './isEqual';\n\nconst useDeepEqualMemoize = <T>(value: T) => {\n const ref = useRef<T | undefined>(undefined);\n if (!isEqual(ref.current, value)) {\n ref.current = clone(value);\n }\n return ref.current;\n};\n\n/* eslint-disable react-hooks/exhaustive-deps */\nconst useDeepEqualMemo = <T>(\n factory: () => T,\n deps: DependencyList | undefined\n): T => useMemo(factory, deps ? deps.map(useDeepEqualMemoize) : undefined);\n\nexport default useDeepEqualMemo;\n"],"mappings":";;;;;;AAAA;AACA;AACA;AAAgC;AAEhC,IAAMA,mBAAmB,GAAG,SAAtBA,mBAAmB,CAAOC,KAAQ,EAAK;EAC3C,IAAMC,GAAG,GAAG,IAAAC,aAAM,EAAgBC,SAAS,CAAC;EAC5C,IAAI,CAAC,IAAAC,mBAAO,EAACH,GAAG,CAACI,OAAO,EAAEL,KAAK,CAAC,EAAE;IAChCC,GAAG,CAACI,OAAO,GAAG,IAAAC,iBAAK,EAACN,KAAK,CAAC;EAC5B;EACA,OAAOC,GAAG,CAACI,OAAO;AACpB,CAAC;;AAED;AACA,IAAME,gBAAgB,GAAG,SAAnBA,gBAAgB,CACpBC,OAAgB,EAChBC,IAAgC;EAAA,OAC1B,IAAAC,cAAO,EAACF,OAAO,EAAEC,IAAI,GAAGA,IAAI,CAACE,GAAG,CAACZ,mBAAmB,CAAC,GAAGI,SAAS,CAAC;AAAA;AAAC,eAE5DI,gBAAgB;AAAA"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import SubscriptionManager from './SubscriptionManager';
|
|
2
|
+
|
|
3
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
4
|
+
|
|
5
|
+
class SubscribableData extends SubscriptionManager {
|
|
6
|
+
constructor(data) {
|
|
7
|
+
super();
|
|
8
|
+
this.data = void 0;
|
|
9
|
+
this.data = data;
|
|
10
|
+
}
|
|
11
|
+
get(name) {
|
|
12
|
+
return this.data[name];
|
|
13
|
+
}
|
|
14
|
+
getAll() {
|
|
15
|
+
return this.data;
|
|
16
|
+
}
|
|
17
|
+
set(name, value) {
|
|
18
|
+
this.data[name] = value;
|
|
19
|
+
this.call(name, value);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export default SubscribableData;
|
|
23
|
+
//# sourceMappingURL=SubscribableData.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SubscribableData.js","names":["SubscriptionManager","SubscribableData","constructor","data","get","name","getAll","set","value","call"],"sources":["../../src/SubscribableData.ts"],"sourcesContent":["import SubscriptionManager from './SubscriptionManager';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype Data = Record<string, any>;\n\nclass SubscribableData<\n TData extends Data,\n TDataName extends keyof TData = keyof TData\n> extends SubscriptionManager<TData> {\n private data: TData;\n\n public constructor(data: TData) {\n super();\n this.data = data;\n }\n\n public get<TName extends TDataName>(name: TName): TData[TName] {\n return this.data[name];\n }\n\n public getAll(): TData {\n return this.data;\n }\n\n public set<TName extends TDataName>(name: TName, value: TData[TName]): void {\n this.data[name] = value;\n this.call(name, value);\n }\n}\n\nexport default SubscribableData;\n"],"mappings":"AAAA,OAAOA,mBAAmB,MAAM,uBAAuB;;AAEvD;;AAGA,MAAMC,gBAAgB,SAGZD,mBAAmB,CAAQ;EAG5BE,WAAW,CAACC,IAAW,EAAE;IAC9B,KAAK,EAAE;IAAC,KAHFA,IAAI;IAIV,IAAI,CAACA,IAAI,GAAGA,IAAI;EAClB;EAEOC,GAAG,CAA0BC,IAAW,EAAgB;IAC7D,OAAO,IAAI,CAACF,IAAI,CAACE,IAAI,CAAC;EACxB;EAEOC,MAAM,GAAU;IACrB,OAAO,IAAI,CAACH,IAAI;EAClB;EAEOI,GAAG,CAA0BF,IAAW,EAAEG,KAAmB,EAAQ;IAC1E,IAAI,CAACL,IAAI,CAACE,IAAI,CAAC,GAAGG,KAAK;IACvB,IAAI,CAACC,IAAI,CAACJ,IAAI,EAAEG,KAAK,CAAC;EACxB;AACF;AAEA,eAAeP,gBAAgB"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2
|
+
|
|
3
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
4
|
+
const deleteFromArray = (arr, item) => {
|
|
5
|
+
const index = arr.findIndex(i => i === item);
|
|
6
|
+
if (index === -1) return;
|
|
7
|
+
arr.splice(index, 1);
|
|
8
|
+
};
|
|
9
|
+
class SubscriptionManager {
|
|
10
|
+
constructor() {
|
|
11
|
+
this.observers = void 0;
|
|
12
|
+
this.fieldObservers = void 0;
|
|
13
|
+
this.observers = [];
|
|
14
|
+
this.fieldObservers = {};
|
|
15
|
+
}
|
|
16
|
+
getFieldObservers(name) {
|
|
17
|
+
if (!this.fieldObservers[name]) {
|
|
18
|
+
this.fieldObservers[name] = [];
|
|
19
|
+
}
|
|
20
|
+
return this.fieldObservers[name];
|
|
21
|
+
}
|
|
22
|
+
subscribeToAllFields(observer) {
|
|
23
|
+
this.observers.push(observer);
|
|
24
|
+
return {
|
|
25
|
+
unsubscribe: () => this.unsubscribeFromAllFields(observer)
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
unsubscribeFromAllFields(observer) {
|
|
29
|
+
deleteFromArray(this.observers, observer);
|
|
30
|
+
}
|
|
31
|
+
subscribeToField(name, observer) {
|
|
32
|
+
this.getFieldObservers(name).push(observer);
|
|
33
|
+
return {
|
|
34
|
+
unsubscribe: () => this.unsubscribeFromField(name, observer)
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
unsubscribeFromField(name, observer) {
|
|
38
|
+
deleteFromArray(this.getFieldObservers(name), observer);
|
|
39
|
+
}
|
|
40
|
+
call(name, value) {
|
|
41
|
+
this.observers.forEach(observer => observer(name, value));
|
|
42
|
+
this.getFieldObservers(name).forEach(observer => observer(value));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
export default SubscriptionManager;
|
|
46
|
+
//# sourceMappingURL=SubscriptionManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SubscriptionManager.js","names":["deleteFromArray","arr","item","index","findIndex","i","splice","SubscriptionManager","constructor","observers","fieldObservers","getFieldObservers","name","subscribeToAllFields","observer","push","unsubscribe","unsubscribeFromAllFields","subscribeToField","unsubscribeFromField","call","value","forEach"],"sources":["../../src/SubscriptionManager.ts"],"sourcesContent":["export type Observer<K, V> = (name: K, value: V) => void;\nexport type FieldObserver<V> = (value: V) => void;\n\nexport interface Subscription {\n unsubscribe: () => void;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype Data = Record<string, any>;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst deleteFromArray = (arr: any[], item: any) => {\n const index = arr.findIndex((i) => i === item);\n if (index === -1) return;\n arr.splice(index, 1);\n};\n\nclass SubscriptionManager<\n TData extends Data,\n TDataName extends keyof TData = keyof TData\n> {\n private observers: Array<Observer<TDataName, TData[TDataName]>>;\n\n private fieldObservers: {\n [TName in TDataName]?: Array<FieldObserver<TData[TName]>>;\n };\n\n public constructor() {\n this.observers = [];\n this.fieldObservers = {};\n }\n\n private getFieldObservers<TName extends TDataName>(\n name: TName\n ): Array<FieldObserver<TData[TName]>> {\n if (!this.fieldObservers[name]) {\n this.fieldObservers[name] = [];\n }\n return this.fieldObservers[name] as Array<FieldObserver<TData[TName]>>;\n }\n\n public subscribeToAllFields(\n observer: Observer<TDataName, TData[TDataName]>\n ): Subscription {\n this.observers.push(observer);\n return { unsubscribe: () => this.unsubscribeFromAllFields(observer) };\n }\n\n private unsubscribeFromAllFields(\n observer: Observer<TDataName, TData[TDataName]>\n ): void {\n deleteFromArray(this.observers, observer);\n }\n\n public subscribeToField<TName extends TDataName>(\n name: TName,\n observer: FieldObserver<TData[TName]>\n ): Subscription {\n this.getFieldObservers(name).push(observer);\n return { unsubscribe: () => this.unsubscribeFromField(name, observer) };\n }\n\n private unsubscribeFromField<TName extends TDataName>(\n name: TName,\n observer: FieldObserver<TData[TName]>\n ): void {\n deleteFromArray(this.getFieldObservers(name), observer);\n }\n\n protected call<TName extends TDataName>(\n name: TName,\n value: TData[TName]\n ): void {\n this.observers.forEach((observer) => observer(name, value));\n this.getFieldObservers(name).forEach((observer) => observer(value));\n }\n}\n\nexport default SubscriptionManager;\n"],"mappings":"AAOA;;AAGA;AACA,MAAMA,eAAe,GAAG,CAACC,GAAU,EAAEC,IAAS,KAAK;EACjD,MAAMC,KAAK,GAAGF,GAAG,CAACG,SAAS,CAAEC,CAAC,IAAKA,CAAC,KAAKH,IAAI,CAAC;EAC9C,IAAIC,KAAK,KAAK,CAAC,CAAC,EAAE;EAClBF,GAAG,CAACK,MAAM,CAACH,KAAK,EAAE,CAAC,CAAC;AACtB,CAAC;AAED,MAAMI,mBAAmB,CAGvB;EAOOC,WAAW,GAAG;IAAA,KANbC,SAAS;IAAA,KAETC,cAAc;IAKpB,IAAI,CAACD,SAAS,GAAG,EAAE;IACnB,IAAI,CAACC,cAAc,GAAG,CAAC,CAAC;EAC1B;EAEQC,iBAAiB,CACvBC,IAAW,EACyB;IACpC,IAAI,CAAC,IAAI,CAACF,cAAc,CAACE,IAAI,CAAC,EAAE;MAC9B,IAAI,CAACF,cAAc,CAACE,IAAI,CAAC,GAAG,EAAE;IAChC;IACA,OAAO,IAAI,CAACF,cAAc,CAACE,IAAI,CAAC;EAClC;EAEOC,oBAAoB,CACzBC,QAA+C,EACjC;IACd,IAAI,CAACL,SAAS,CAACM,IAAI,CAACD,QAAQ,CAAC;IAC7B,OAAO;MAAEE,WAAW,EAAE,MAAM,IAAI,CAACC,wBAAwB,CAACH,QAAQ;IAAE,CAAC;EACvE;EAEQG,wBAAwB,CAC9BH,QAA+C,EACzC;IACNd,eAAe,CAAC,IAAI,CAACS,SAAS,EAAEK,QAAQ,CAAC;EAC3C;EAEOI,gBAAgB,CACrBN,IAAW,EACXE,QAAqC,EACvB;IACd,IAAI,CAACH,iBAAiB,CAACC,IAAI,CAAC,CAACG,IAAI,CAACD,QAAQ,CAAC;IAC3C,OAAO;MAAEE,WAAW,EAAE,MAAM,IAAI,CAACG,oBAAoB,CAACP,IAAI,EAAEE,QAAQ;IAAE,CAAC;EACzE;EAEQK,oBAAoB,CAC1BP,IAAW,EACXE,QAAqC,EAC/B;IACNd,eAAe,CAAC,IAAI,CAACW,iBAAiB,CAACC,IAAI,CAAC,EAAEE,QAAQ,CAAC;EACzD;EAEUM,IAAI,CACZR,IAAW,EACXS,KAAmB,EACb;IACN,IAAI,CAACZ,SAAS,CAACa,OAAO,CAAER,QAAQ,IAAKA,QAAQ,CAACF,IAAI,EAAES,KAAK,CAAC,CAAC;IAC3D,IAAI,CAACV,iBAAiB,CAACC,IAAI,CAAC,CAACU,OAAO,CAAER,QAAQ,IAAKA,QAAQ,CAACO,KAAK,CAAC,CAAC;EACrE;AACF;AAEA,eAAed,mBAAmB"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import React, { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';
|
|
2
|
+
import SubscribableData from './SubscribableData';
|
|
3
|
+
import clone from './utils/clone';
|
|
4
|
+
import isEqual from './utils/isEqual';
|
|
5
|
+
import useDeepEqualMemo from './utils/useDeepEqualMemo';
|
|
6
|
+
export * from './SubscriptionManager';
|
|
7
|
+
|
|
8
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
9
|
+
|
|
10
|
+
class Form {
|
|
11
|
+
constructor(initValues) {
|
|
12
|
+
this.initValues = void 0;
|
|
13
|
+
this.values = void 0;
|
|
14
|
+
this.errors = void 0;
|
|
15
|
+
this.initValues = initValues;
|
|
16
|
+
this.values = new SubscribableData(clone(initValues));
|
|
17
|
+
this.errors = new SubscribableData({});
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
const FormContext = /*#__PURE__*/createContext(null);
|
|
21
|
+
// eslint-disable-next-line react/function-component-definition
|
|
22
|
+
export function FormProvider({
|
|
23
|
+
form,
|
|
24
|
+
children
|
|
25
|
+
}) {
|
|
26
|
+
return /*#__PURE__*/React.createElement(FormContext.Provider, {
|
|
27
|
+
value: form
|
|
28
|
+
}, children);
|
|
29
|
+
}
|
|
30
|
+
const createUseValueHook = form => name => {
|
|
31
|
+
const [value, setValue] = useState(form.values.get(name));
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
const subscription = form.values.subscribeToField(name, v => {
|
|
34
|
+
setValue(v);
|
|
35
|
+
});
|
|
36
|
+
return () => subscription.unsubscribe();
|
|
37
|
+
}, [name]);
|
|
38
|
+
return value;
|
|
39
|
+
};
|
|
40
|
+
export const useError = (name, form) => {
|
|
41
|
+
const currentForm = useContext(FormContext) || form;
|
|
42
|
+
if (!currentForm) throw new Error('Specify the form');
|
|
43
|
+
const [value, setValue] = useState(currentForm.errors.get(name));
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
const subscription = currentForm.errors.subscribeToField(name, v => {
|
|
46
|
+
setValue(v);
|
|
47
|
+
});
|
|
48
|
+
return () => subscription.unsubscribe();
|
|
49
|
+
}, [currentForm.errors, name]);
|
|
50
|
+
return value;
|
|
51
|
+
};
|
|
52
|
+
const createUseTransformerHook = form => {
|
|
53
|
+
const useValue = createUseValueHook(form);
|
|
54
|
+
return (name, transformer) => {
|
|
55
|
+
const value = useValue(name);
|
|
56
|
+
const transformerRef = useRef(transformer);
|
|
57
|
+
useEffect(() => {
|
|
58
|
+
transformerRef.current = transformer;
|
|
59
|
+
}, [transformer]);
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
const partialValues = transformerRef.current(value);
|
|
62
|
+
Object.entries(partialValues).forEach(([n, v]) => {
|
|
63
|
+
form.values.set(n, v);
|
|
64
|
+
});
|
|
65
|
+
}, [value]);
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
const createFieldComponent = form => {
|
|
69
|
+
const useValue = createUseValueHook(form);
|
|
70
|
+
return props => {
|
|
71
|
+
const {
|
|
72
|
+
name,
|
|
73
|
+
toValue,
|
|
74
|
+
fromValue,
|
|
75
|
+
render
|
|
76
|
+
} = props;
|
|
77
|
+
const value = useValue(name);
|
|
78
|
+
const transformedValue = useMemo(() => toValue ? toValue(value) : value, [toValue, value]);
|
|
79
|
+
const error = useError(name, form);
|
|
80
|
+
const modified = useMemo(() => !isEqual(value, form.initValues[name]), [name, value]);
|
|
81
|
+
const reset = useCallback(() => form.values.set(name, form.initValues[name]), [name]);
|
|
82
|
+
const fromValueRef = useRef(fromValue);
|
|
83
|
+
useEffect(() => {
|
|
84
|
+
fromValueRef.current = fromValue;
|
|
85
|
+
}, [fromValue]);
|
|
86
|
+
const onChange = useCallback(v => {
|
|
87
|
+
form.values.set(name, fromValueRef.current ? fromValueRef.current(v) : v);
|
|
88
|
+
form.errors.set(name, undefined);
|
|
89
|
+
}, [name]);
|
|
90
|
+
const renderRef = useRef(render);
|
|
91
|
+
useEffect(() => {
|
|
92
|
+
renderRef.current = render;
|
|
93
|
+
}, [render]);
|
|
94
|
+
const inputProps = useMemo(() => ({
|
|
95
|
+
value: transformedValue,
|
|
96
|
+
onChange
|
|
97
|
+
}), [onChange, transformedValue]);
|
|
98
|
+
const fieldState = useMemo(() => ({
|
|
99
|
+
error,
|
|
100
|
+
modified,
|
|
101
|
+
reset
|
|
102
|
+
}), [error, modified, reset]);
|
|
103
|
+
return useMemo(() => renderRef.current(inputProps, fieldState), [fieldState, inputProps]);
|
|
104
|
+
};
|
|
105
|
+
};
|
|
106
|
+
const useModifiedFields = form => {
|
|
107
|
+
const [modifiedFields, setModifiedFields] = useState([]);
|
|
108
|
+
const modifiedFieldsRef = useRef(modifiedFields);
|
|
109
|
+
useEffect(() => {
|
|
110
|
+
modifiedFieldsRef.current = modifiedFields;
|
|
111
|
+
}, [modifiedFields]);
|
|
112
|
+
const initValuesRef = useRef(form.initValues);
|
|
113
|
+
useEffect(() => {
|
|
114
|
+
initValuesRef.current = form.initValues;
|
|
115
|
+
}, [form.initValues]);
|
|
116
|
+
useEffect(() => {
|
|
117
|
+
const subscription = form.values.subscribeToAllFields((name, value) => {
|
|
118
|
+
const isInitValue = isEqual(value, initValuesRef.current[name]);
|
|
119
|
+
const fields = modifiedFieldsRef.current;
|
|
120
|
+
if (fields.includes(name)) {
|
|
121
|
+
if (isInitValue) {
|
|
122
|
+
setModifiedFields(fields.filter(field => field !== name));
|
|
123
|
+
}
|
|
124
|
+
} else if (!isInitValue) {
|
|
125
|
+
setModifiedFields([...fields, name]);
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
return () => subscription.unsubscribe();
|
|
129
|
+
}, [form.values]);
|
|
130
|
+
return modifiedFields;
|
|
131
|
+
};
|
|
132
|
+
const useFormResponse = form => {
|
|
133
|
+
const useValue = useMemo(() => createUseValueHook(form), [form]);
|
|
134
|
+
const useTransformer = useMemo(() => createUseTransformerHook(form), [form]);
|
|
135
|
+
const Field = useMemo(() => createFieldComponent(form), [form]);
|
|
136
|
+
const modifiedFields = useModifiedFields(form);
|
|
137
|
+
const modified = useMemo(() => modifiedFields.length > 0, [modifiedFields.length]);
|
|
138
|
+
return useMemo(() => ({
|
|
139
|
+
form,
|
|
140
|
+
Field,
|
|
141
|
+
useValue,
|
|
142
|
+
useTransformer,
|
|
143
|
+
modifiedFields,
|
|
144
|
+
modified
|
|
145
|
+
}), [Field, form, modified, modifiedFields, useTransformer, useValue]);
|
|
146
|
+
};
|
|
147
|
+
export const useForm = initValues => {
|
|
148
|
+
const memoizedInitValues = useDeepEqualMemo(() => initValues, [initValues]);
|
|
149
|
+
const form = useMemo(() => new Form(memoizedInitValues), [memoizedInitValues]);
|
|
150
|
+
return useFormResponse(form);
|
|
151
|
+
};
|
|
152
|
+
export const useExistingForm = () => {
|
|
153
|
+
const form = useContext(FormContext);
|
|
154
|
+
if (!form) throw new Error('Wrap your form in a FormProvider');
|
|
155
|
+
return useFormResponse(form);
|
|
156
|
+
};
|
|
157
|
+
//# sourceMappingURL=index.js.map
|