@rjsf/utils 6.0.0-alpha.0 → 6.0.0-beta.10
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/dist/index.js +1347 -642
- package/dist/index.js.map +4 -4
- package/dist/utils.esm.js +1324 -619
- package/dist/utils.esm.js.map +4 -4
- package/dist/utils.umd.js +1266 -590
- package/lib/ErrorSchemaBuilder.d.ts +8 -4
- package/lib/ErrorSchemaBuilder.js +10 -8
- package/lib/ErrorSchemaBuilder.js.map +1 -1
- package/lib/allowAdditionalItems.d.ts +1 -1
- package/lib/allowAdditionalItems.js +1 -1
- package/lib/allowAdditionalItems.js.map +1 -1
- package/lib/asNumber.js.map +1 -1
- package/lib/canExpand.d.ts +2 -2
- package/lib/canExpand.js +2 -2
- package/lib/canExpand.js.map +1 -1
- package/lib/constIsAjvDataReference.d.ts +9 -0
- package/lib/constIsAjvDataReference.js +15 -0
- package/lib/constIsAjvDataReference.js.map +1 -0
- package/lib/constants.d.ts +15 -3
- package/lib/constants.js +15 -3
- package/lib/constants.js.map +1 -1
- package/lib/createErrorHandler.d.ts +1 -1
- package/lib/createErrorHandler.js +2 -2
- package/lib/createErrorHandler.js.map +1 -1
- package/lib/createSchemaUtils.d.ts +3 -2
- package/lib/createSchemaUtils.js +56 -46
- package/lib/createSchemaUtils.js.map +1 -1
- package/lib/dataURItoBlob.js.map +1 -1
- package/lib/dateRangeOptions.d.ts +1 -1
- package/lib/dateRangeOptions.js +1 -1
- package/lib/dateRangeOptions.js.map +1 -1
- package/lib/deepEquals.js +1 -1
- package/lib/deepEquals.js.map +1 -1
- package/lib/englishStringTranslator.d.ts +1 -1
- package/lib/englishStringTranslator.js +1 -1
- package/lib/enumOptionsDeselectValue.d.ts +1 -1
- package/lib/enumOptionsDeselectValue.js +4 -4
- package/lib/enumOptionsDeselectValue.js.map +1 -1
- package/lib/enumOptionsIndexForValue.d.ts +1 -1
- package/lib/enumOptionsIndexForValue.js +1 -1
- package/lib/enumOptionsIndexForValue.js.map +1 -1
- package/lib/enumOptionsIsSelected.d.ts +1 -1
- package/lib/enumOptionsIsSelected.js +3 -3
- package/lib/enumOptionsIsSelected.js.map +1 -1
- package/lib/enumOptionsSelectValue.d.ts +1 -1
- package/lib/enumOptionsSelectValue.js +2 -2
- package/lib/enumOptionsSelectValue.js.map +1 -1
- package/lib/enumOptionsValueForIndex.d.ts +1 -1
- package/lib/enumOptionsValueForIndex.js.map +1 -1
- package/lib/enums.d.ts +2 -0
- package/lib/enums.js +2 -0
- package/lib/enums.js.map +1 -1
- package/lib/findSchemaDefinition.d.ts +5 -3
- package/lib/findSchemaDefinition.js +54 -11
- package/lib/findSchemaDefinition.js.map +1 -1
- package/lib/getChangedFields.d.ts +17 -0
- package/lib/getChangedFields.js +42 -0
- package/lib/getChangedFields.js.map +1 -0
- package/lib/getDateElementProps.d.ts +1 -1
- package/lib/getDateElementProps.js.map +1 -1
- package/lib/getDiscriminatorFieldFromSchema.d.ts +1 -1
- package/lib/getDiscriminatorFieldFromSchema.js +4 -3
- package/lib/getDiscriminatorFieldFromSchema.js.map +1 -1
- package/lib/getInputProps.d.ts +1 -1
- package/lib/getInputProps.js +4 -1
- package/lib/getInputProps.js.map +1 -1
- package/lib/getOptionMatchingSimpleDiscriminator.d.ts +1 -1
- package/lib/getOptionMatchingSimpleDiscriminator.js +2 -2
- package/lib/getOptionMatchingSimpleDiscriminator.js.map +1 -1
- package/lib/getSchemaType.d.ts +2 -1
- package/lib/getSchemaType.js +3 -2
- package/lib/getSchemaType.js.map +1 -1
- package/lib/getSubmitButtonOptions.d.ts +1 -1
- package/lib/getSubmitButtonOptions.js +2 -2
- package/lib/getSubmitButtonOptions.js.map +1 -1
- package/lib/getTemplate.d.ts +1 -1
- package/lib/getTemplate.js +9 -0
- package/lib/getTemplate.js.map +1 -1
- package/lib/getTestIds.d.ts +17 -0
- package/lib/getTestIds.js +34 -0
- package/lib/getTestIds.js.map +1 -0
- package/lib/getUiOptions.d.ts +1 -1
- package/lib/getUiOptions.js +2 -2
- package/lib/getUiOptions.js.map +1 -1
- package/lib/getWidget.d.ts +1 -1
- package/lib/getWidget.js +3 -3
- package/lib/getWidget.js.map +1 -1
- package/lib/guessType.d.ts +1 -1
- package/lib/guessType.js.map +1 -1
- package/lib/hasWidget.d.ts +1 -1
- package/lib/hasWidget.js +1 -1
- package/lib/hasWidget.js.map +1 -1
- package/lib/hashForSchema.d.ts +23 -1
- package/lib/hashForSchema.js +24 -6
- package/lib/hashForSchema.js.map +1 -1
- package/lib/idGenerators.d.ts +8 -1
- package/lib/idGenerators.js +11 -2
- package/lib/idGenerators.js.map +1 -1
- package/lib/index.d.ts +63 -60
- package/lib/index.js +63 -60
- package/lib/index.js.map +1 -1
- package/lib/isConstant.d.ts +1 -1
- package/lib/isConstant.js +1 -1
- package/lib/isCustomWidget.d.ts +1 -1
- package/lib/isCustomWidget.js +1 -1
- package/lib/isFixedItems.d.ts +1 -1
- package/lib/isFixedItems.js +1 -1
- package/lib/isObject.d.ts +2 -2
- package/lib/isObject.js +11 -4
- package/lib/isObject.js.map +1 -1
- package/lib/lookupFromFormContext.d.ts +11 -0
- package/lib/lookupFromFormContext.js +20 -0
- package/lib/lookupFromFormContext.js.map +1 -0
- package/lib/mergeDefaultsWithFormData.d.ts +8 -2
- package/lib/mergeDefaultsWithFormData.js +39 -10
- package/lib/mergeDefaultsWithFormData.js.map +1 -1
- package/lib/mergeObjects.d.ts +1 -1
- package/lib/mergeObjects.js +1 -1
- package/lib/mergeObjects.js.map +1 -1
- package/lib/mergeSchemas.d.ts +1 -1
- package/lib/mergeSchemas.js +4 -4
- package/lib/mergeSchemas.js.map +1 -1
- package/lib/optionsList.d.ts +9 -7
- package/lib/optionsList.js +30 -19
- package/lib/optionsList.js.map +1 -1
- package/lib/orderProperties.js.map +1 -1
- package/lib/pad.js.map +1 -1
- package/lib/parseDateString.d.ts +1 -1
- package/lib/parseDateString.js +1 -1
- package/lib/parseDateString.js.map +1 -1
- package/lib/parser/ParserValidator.d.ts +1 -1
- package/lib/parser/ParserValidator.js +6 -6
- package/lib/parser/ParserValidator.js.map +1 -1
- package/lib/parser/index.d.ts +2 -2
- package/lib/parser/index.js +1 -1
- package/lib/parser/schemaParser.d.ts +2 -2
- package/lib/parser/schemaParser.js +6 -6
- package/lib/parser/schemaParser.js.map +1 -1
- package/lib/rangeSpec.d.ts +2 -2
- package/lib/rangeSpec.js.map +1 -1
- package/lib/replaceStringParameters.js.map +1 -1
- package/lib/schema/findFieldInSchema.d.ts +19 -0
- package/lib/schema/findFieldInSchema.js +61 -0
- package/lib/schema/findFieldInSchema.js.map +1 -0
- package/lib/schema/findSelectedOptionInXxxOf.d.ts +16 -0
- package/lib/schema/findSelectedOptionInXxxOf.js +34 -0
- package/lib/schema/findSelectedOptionInXxxOf.js.map +1 -0
- package/lib/schema/getClosestMatchingOption.d.ts +5 -3
- package/lib/schema/getClosestMatchingOption.js +28 -20
- package/lib/schema/getClosestMatchingOption.js.map +1 -1
- package/lib/schema/getDefaultFormState.d.ts +60 -13
- package/lib/schema/getDefaultFormState.js +316 -167
- package/lib/schema/getDefaultFormState.js.map +1 -1
- package/lib/schema/getDisplayLabel.d.ts +3 -2
- package/lib/schema/getDisplayLabel.js +10 -9
- package/lib/schema/getDisplayLabel.js.map +1 -1
- package/lib/schema/getFirstMatchingOption.d.ts +1 -1
- package/lib/schema/getFirstMatchingOption.js +70 -2
- package/lib/schema/getFirstMatchingOption.js.map +1 -1
- package/lib/schema/getFromSchema.d.ts +14 -0
- package/lib/schema/getFromSchema.js +39 -0
- package/lib/schema/getFromSchema.js.map +1 -0
- package/lib/schema/index.d.ts +15 -14
- package/lib/schema/index.js +15 -14
- package/lib/schema/index.js.map +1 -1
- package/lib/schema/isFilesArray.d.ts +3 -2
- package/lib/schema/isFilesArray.js +5 -4
- package/lib/schema/isFilesArray.js.map +1 -1
- package/lib/schema/isMultiSelect.d.ts +3 -2
- package/lib/schema/isMultiSelect.js +4 -3
- package/lib/schema/isMultiSelect.js.map +1 -1
- package/lib/schema/isSelect.d.ts +3 -2
- package/lib/schema/isSelect.js +5 -4
- package/lib/schema/isSelect.js.map +1 -1
- package/lib/schema/retrieveSchema.d.ts +30 -12
- package/lib/schema/retrieveSchema.js +153 -70
- package/lib/schema/retrieveSchema.js.map +1 -1
- package/lib/schema/sanitizeDataForNewSchema.d.ts +3 -2
- package/lib/schema/sanitizeDataForNewSchema.js +12 -11
- package/lib/schema/sanitizeDataForNewSchema.js.map +1 -1
- package/lib/schema/toIdSchema.d.ts +3 -2
- package/lib/schema/toIdSchema.js +30 -27
- package/lib/schema/toIdSchema.js.map +1 -1
- package/lib/schema/toPathSchema.d.ts +3 -2
- package/lib/schema/toPathSchema.js +22 -20
- package/lib/schema/toPathSchema.js.map +1 -1
- package/lib/schemaRequiresTrueValue.d.ts +1 -1
- package/lib/schemaRequiresTrueValue.js.map +1 -1
- package/lib/shouldRender.js +1 -1
- package/lib/toConstant.d.ts +1 -1
- package/lib/toConstant.js +1 -1
- package/lib/toConstant.js.map +1 -1
- package/lib/toDateString.d.ts +1 -1
- package/lib/toErrorList.d.ts +1 -1
- package/lib/toErrorList.js +2 -2
- package/lib/toErrorList.js.map +1 -1
- package/lib/toErrorSchema.d.ts +1 -1
- package/lib/toErrorSchema.js +2 -2
- package/lib/toErrorSchema.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/lib/types.d.ts +172 -142
- package/lib/unwrapErrorHandler.d.ts +1 -1
- package/lib/unwrapErrorHandler.js +1 -1
- package/lib/unwrapErrorHandler.js.map +1 -1
- package/lib/utcToLocal.js +1 -1
- package/lib/utcToLocal.js.map +1 -1
- package/lib/validationDataMerge.d.ts +1 -1
- package/lib/validationDataMerge.js +3 -3
- package/lib/validationDataMerge.js.map +1 -1
- package/lib/withIdRefPrefix.d.ts +1 -1
- package/lib/withIdRefPrefix.js +2 -2
- package/lib/withIdRefPrefix.js.map +1 -1
- package/package.json +37 -26
- package/src/ErrorSchemaBuilder.ts +15 -8
- package/src/canExpand.ts +2 -2
- package/src/constIsAjvDataReference.ts +17 -0
- package/src/constants.ts +17 -3
- package/src/createSchemaUtils.ts +140 -50
- package/src/dataURItoBlob.ts +1 -1
- package/src/dateRangeOptions.ts +1 -1
- package/src/enumOptionsDeselectValue.ts +4 -5
- package/src/enumOptionsIndexForValue.ts +1 -1
- package/src/enumOptionsIsSelected.ts +4 -5
- package/src/enumOptionsSelectValue.ts +1 -1
- package/src/enumOptionsValueForIndex.ts +1 -1
- package/src/enums.ts +2 -0
- package/src/findSchemaDefinition.ts +55 -10
- package/src/getChangedFields.ts +40 -0
- package/src/getDateElementProps.ts +2 -2
- package/src/getDiscriminatorFieldFromSchema.ts +2 -1
- package/src/getInputProps.ts +6 -2
- package/src/getOptionMatchingSimpleDiscriminator.ts +2 -2
- package/src/getSchemaType.ts +3 -2
- package/src/getSubmitButtonOptions.ts +1 -1
- package/src/getTemplate.ts +12 -1
- package/src/getTestIds.ts +40 -0
- package/src/getUiOptions.ts +2 -2
- package/src/getWidget.tsx +2 -2
- package/src/hasWidget.ts +1 -1
- package/src/hashForSchema.ts +26 -6
- package/src/idGenerators.ts +10 -0
- package/src/index.ts +21 -2
- package/src/isCustomWidget.ts +1 -1
- package/src/isObject.ts +12 -5
- package/src/labelValue.ts +2 -2
- package/src/lookupFromFormContext.ts +26 -0
- package/src/mergeDefaultsWithFormData.ts +54 -9
- package/src/mergeObjects.ts +24 -21
- package/src/optionsList.ts +31 -22
- package/src/parser/ParserValidator.ts +5 -5
- package/src/parser/schemaParser.ts +6 -6
- package/src/schema/findFieldInSchema.ts +138 -0
- package/src/schema/findSelectedOptionInXxxOf.ts +53 -0
- package/src/schema/getClosestMatchingOption.ts +38 -11
- package/src/schema/getDefaultFormState.ts +461 -193
- package/src/schema/getDisplayLabel.ts +7 -4
- package/src/schema/getFirstMatchingOption.ts +79 -4
- package/src/schema/getFromSchema.ts +100 -0
- package/src/schema/index.ts +6 -4
- package/src/schema/isFilesArray.ts +18 -3
- package/src/schema/isMultiSelect.ts +10 -4
- package/src/schema/isSelect.ts +5 -3
- package/src/schema/retrieveSchema.ts +268 -78
- package/src/schema/sanitizeDataForNewSchema.ts +52 -11
- package/src/schema/toIdSchema.ts +69 -43
- package/src/schema/toPathSchema.ts +49 -16
- package/src/toErrorList.ts +2 -2
- package/src/types.ts +278 -184
- package/src/validationDataMerge.ts +1 -1
- package/src/withIdRefPrefix.ts +1 -1
- package/LICENSE.md +0 -201
- package/lib/schema/getMatchingOption.d.ts +0 -14
- package/lib/schema/getMatchingOption.js +0 -85
- package/lib/schema/getMatchingOption.js.map +0 -1
- package/lib/schema/mergeValidationData.d.ts +0 -14
- package/lib/schema/mergeValidationData.js +0 -28
- package/lib/schema/mergeValidationData.js.map +0 -1
- package/src/schema/getMatchingOption.ts +0 -103
- package/src/schema/mergeValidationData.ts +0 -38
package/src/getInputProps.ts
CHANGED
|
@@ -12,12 +12,12 @@ import { FormContextType, InputPropsType, RJSFSchema, StrictRJSFSchema, UIOption
|
|
|
12
12
|
export default function getInputProps<
|
|
13
13
|
T = any,
|
|
14
14
|
S extends StrictRJSFSchema = RJSFSchema,
|
|
15
|
-
F extends FormContextType = any
|
|
15
|
+
F extends FormContextType = any,
|
|
16
16
|
>(
|
|
17
17
|
schema: RJSFSchema,
|
|
18
18
|
defaultType?: string,
|
|
19
19
|
options: UIOptionsType<T, S, F> = {},
|
|
20
|
-
autoDefaultStepAny = true
|
|
20
|
+
autoDefaultStepAny = true,
|
|
21
21
|
): InputPropsType {
|
|
22
22
|
const inputProps: InputPropsType = {
|
|
23
23
|
type: defaultType || 'text',
|
|
@@ -51,5 +51,9 @@ export default function getInputProps<
|
|
|
51
51
|
inputProps.autoComplete = options.autocomplete;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
if (options.accept) {
|
|
55
|
+
inputProps.accept = options.accept as string;
|
|
56
|
+
}
|
|
57
|
+
|
|
54
58
|
return inputProps;
|
|
55
59
|
}
|
|
@@ -15,7 +15,7 @@ import { RJSFSchema, StrictRJSFSchema } from './types';
|
|
|
15
15
|
export default function getOptionMatchingSimpleDiscriminator<T = any, S extends StrictRJSFSchema = RJSFSchema>(
|
|
16
16
|
formData: T | undefined,
|
|
17
17
|
options: S[],
|
|
18
|
-
discriminatorField?: string
|
|
18
|
+
discriminatorField?: string,
|
|
19
19
|
): number | undefined {
|
|
20
20
|
if (formData && discriminatorField) {
|
|
21
21
|
const value = get(formData, discriminatorField);
|
|
@@ -26,7 +26,7 @@ export default function getOptionMatchingSimpleDiscriminator<T = any, S extends
|
|
|
26
26
|
|
|
27
27
|
for (let i = 0; i < options.length; i++) {
|
|
28
28
|
const option = options[i];
|
|
29
|
-
const discriminator = get(option, [PROPERTIES_KEY, discriminatorField], {});
|
|
29
|
+
const discriminator: S = get(option, [PROPERTIES_KEY, discriminatorField], {}) as S;
|
|
30
30
|
|
|
31
31
|
if (discriminator.type === 'object' || discriminator.type === 'array') {
|
|
32
32
|
continue;
|
package/src/getSchemaType.ts
CHANGED
|
@@ -7,13 +7,14 @@ import { RJSFSchema, StrictRJSFSchema } from './types';
|
|
|
7
7
|
* - schema.enum: Returns `string`
|
|
8
8
|
* - schema.properties: Returns `object`
|
|
9
9
|
* - schema.additionalProperties: Returns `object`
|
|
10
|
+
* - schema.patternProperties: Returns `object`
|
|
10
11
|
* - type is an array with a length of 2 and one type is 'null': Returns the other type
|
|
11
12
|
*
|
|
12
13
|
* @param schema - The schema for which to get the type
|
|
13
14
|
* @returns - The type of the schema
|
|
14
15
|
*/
|
|
15
16
|
export default function getSchemaType<S extends StrictRJSFSchema = RJSFSchema>(
|
|
16
|
-
schema: S
|
|
17
|
+
schema: S,
|
|
17
18
|
): string | string[] | undefined {
|
|
18
19
|
let { type } = schema;
|
|
19
20
|
|
|
@@ -25,7 +26,7 @@ export default function getSchemaType<S extends StrictRJSFSchema = RJSFSchema>(
|
|
|
25
26
|
return 'string';
|
|
26
27
|
}
|
|
27
28
|
|
|
28
|
-
if (!type && (schema.properties || schema.additionalProperties)) {
|
|
29
|
+
if (!type && (schema.properties || schema.additionalProperties || schema.patternProperties)) {
|
|
29
30
|
return 'object';
|
|
30
31
|
}
|
|
31
32
|
|
|
@@ -20,7 +20,7 @@ export const DEFAULT_OPTIONS: UISchemaSubmitButtonOptions = {
|
|
|
20
20
|
export default function getSubmitButtonOptions<
|
|
21
21
|
T = any,
|
|
22
22
|
S extends StrictRJSFSchema = RJSFSchema,
|
|
23
|
-
F extends FormContextType = any
|
|
23
|
+
F extends FormContextType = any,
|
|
24
24
|
>(uiSchema: UiSchema<T, S, F> = {}): UISchemaSubmitButtonOptions {
|
|
25
25
|
const uiOptions = getUiOptions<T, S, F>(uiSchema);
|
|
26
26
|
if (uiOptions && uiOptions[SUBMIT_BTN_OPTIONS_KEY]) {
|
package/src/getTemplate.ts
CHANGED
|
@@ -12,12 +12,23 @@ export default function getTemplate<
|
|
|
12
12
|
Name extends keyof TemplatesType<T, S, F>,
|
|
13
13
|
T = any,
|
|
14
14
|
S extends StrictRJSFSchema = RJSFSchema,
|
|
15
|
-
F extends FormContextType = any
|
|
15
|
+
F extends FormContextType = any,
|
|
16
16
|
>(name: Name, registry: Registry<T, S, F>, uiOptions: UIOptionsType<T, S, F> = {}): TemplatesType<T, S, F>[Name] {
|
|
17
17
|
const { templates } = registry;
|
|
18
18
|
if (name === 'ButtonTemplates') {
|
|
19
19
|
return templates[name];
|
|
20
20
|
}
|
|
21
|
+
// Allow templates to be customized per-field by using string keys from the registry
|
|
22
|
+
if (
|
|
23
|
+
Object.hasOwn(uiOptions, name) &&
|
|
24
|
+
typeof uiOptions[name] === 'string' &&
|
|
25
|
+
Object.hasOwn(templates, uiOptions[name] as string)
|
|
26
|
+
) {
|
|
27
|
+
const key = uiOptions[name];
|
|
28
|
+
// Evaluating templates[key] results in TS2590: Expression produces a union type that is too complex to represent
|
|
29
|
+
// To avoid that, we cast templates to `any` before accessing the key field
|
|
30
|
+
return (templates as any)[key];
|
|
31
|
+
}
|
|
21
32
|
return (
|
|
22
33
|
// Evaluating uiOptions[name] results in TS2590: Expression produces a union type that is too complex to represent
|
|
23
34
|
// To avoid that, we cast uiOptions to `any` before accessing the name field
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { nanoid } from 'nanoid';
|
|
2
|
+
import get from 'lodash/get';
|
|
3
|
+
|
|
4
|
+
import { TestIdShape } from './types';
|
|
5
|
+
|
|
6
|
+
/** Returns an object of test IDs that can only be used in test mode. If the function is called in a test environment
|
|
7
|
+
* (`NODE_ENV === 'test'`, this is set by jest) then a Proxy object will be returned. If a key within the returned
|
|
8
|
+
* object is accessed, if the value already exists the object will return that value, otherwise it will create that key
|
|
9
|
+
* with a generated `uuid` value and return the generated ID. If it is called outside of a test environment, the
|
|
10
|
+
* function will return an empty object, therefore returning `undefined` for any property within the object and
|
|
11
|
+
* excluding the prop from the rendered output of the component in which it is used.
|
|
12
|
+
* This implementation was adapted from the following blog post: https://www.matthewsessions.com/blog/react-test-id/
|
|
13
|
+
* To use this helper, you will want to generate a separate object for each component to avoid potential overlapping of
|
|
14
|
+
* ID names. You will also want to export the object for use in tests, because the keys will be generated in the
|
|
15
|
+
* component file, and used in the test file. Within the component file, add:
|
|
16
|
+
* `export const TEST_IDS = getTestIds();`
|
|
17
|
+
* Then pass `TEST_IDS.examplePropertyName` as the value of the test ID attribute of the intended component. This will
|
|
18
|
+
* allow you to use `TEST_IDS.examplePropertyName` within your tests, while keeping the test IDs out of your rendered
|
|
19
|
+
* output.
|
|
20
|
+
*/
|
|
21
|
+
export default function getTestIds(): TestIdShape {
|
|
22
|
+
// For some reason, even though process.env contains the value of `test` for NODE_ENV, accessing it directly returns
|
|
23
|
+
// 'development'. Using `get()` does, in fact, return test so sticking with it
|
|
24
|
+
if (typeof process === 'undefined' || get(process, 'env.NODE_ENV') !== 'test') {
|
|
25
|
+
return {};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const ids = new Map();
|
|
29
|
+
return new Proxy(
|
|
30
|
+
{},
|
|
31
|
+
{
|
|
32
|
+
get(_obj, prop) {
|
|
33
|
+
if (!ids.has(prop)) {
|
|
34
|
+
ids.set(prop, nanoid());
|
|
35
|
+
}
|
|
36
|
+
return ids.get(prop);
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
);
|
|
40
|
+
}
|
package/src/getUiOptions.ts
CHANGED
|
@@ -11,7 +11,7 @@ import { FormContextType, GlobalUISchemaOptions, RJSFSchema, StrictRJSFSchema, U
|
|
|
11
11
|
*/
|
|
12
12
|
export default function getUiOptions<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
|
|
13
13
|
uiSchema: UiSchema<T, S, F> = {},
|
|
14
|
-
globalOptions: GlobalUISchemaOptions = {}
|
|
14
|
+
globalOptions: GlobalUISchemaOptions = {},
|
|
15
15
|
): UIOptionsType<T, S, F> {
|
|
16
16
|
return Object.keys(uiSchema)
|
|
17
17
|
.filter((key) => key.indexOf('ui:') === 0)
|
|
@@ -27,6 +27,6 @@ export default function getUiOptions<T = any, S extends StrictRJSFSchema = RJSFS
|
|
|
27
27
|
}
|
|
28
28
|
return { ...options, [key.substring(3)]: value };
|
|
29
29
|
},
|
|
30
|
-
{ ...globalOptions }
|
|
30
|
+
{ ...globalOptions },
|
|
31
31
|
);
|
|
32
32
|
}
|
package/src/getWidget.tsx
CHANGED
|
@@ -69,7 +69,7 @@ const widgetMap: { [k: string]: { [j: string]: string } } = {
|
|
|
69
69
|
* @returns - The wrapper widget
|
|
70
70
|
*/
|
|
71
71
|
function mergeWidgetOptions<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
|
|
72
|
-
AWidget: Widget<T, S, F
|
|
72
|
+
AWidget: Widget<T, S, F>,
|
|
73
73
|
) {
|
|
74
74
|
let MergedWidget: Widget<T, S, F> | undefined = get(AWidget, 'MergedWidget');
|
|
75
75
|
// cache return value as property of widget for proper react reconciliation
|
|
@@ -97,7 +97,7 @@ function mergeWidgetOptions<T = any, S extends StrictRJSFSchema = RJSFSchema, F
|
|
|
97
97
|
export default function getWidget<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
|
|
98
98
|
schema: RJSFSchema,
|
|
99
99
|
widget?: Widget<T, S, F> | string,
|
|
100
|
-
registeredWidgets: RegistryWidgetsType<T, S, F> = {}
|
|
100
|
+
registeredWidgets: RegistryWidgetsType<T, S, F> = {},
|
|
101
101
|
): Widget<T, S, F> {
|
|
102
102
|
const type = getSchemaType(schema);
|
|
103
103
|
|
package/src/hasWidget.ts
CHANGED
|
@@ -12,7 +12,7 @@ import { FormContextType, RegistryWidgetsType, RJSFSchema, StrictRJSFSchema, Wid
|
|
|
12
12
|
export default function hasWidget<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
|
|
13
13
|
schema: RJSFSchema,
|
|
14
14
|
widget: Widget<T, S, F> | string,
|
|
15
|
-
registeredWidgets: RegistryWidgetsType<T, S, F> = {}
|
|
15
|
+
registeredWidgets: RegistryWidgetsType<T, S, F> = {},
|
|
16
16
|
) {
|
|
17
17
|
try {
|
|
18
18
|
getWidget(schema, widget, registeredWidgets);
|
package/src/hashForSchema.ts
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { RJSFSchema, StrictRJSFSchema } from './types';
|
|
2
2
|
|
|
3
|
-
/**
|
|
3
|
+
/** Hashes a string using the algorithm based on Java's hashing function.
|
|
4
|
+
* JS has no built-in hashing function, so rolling our own
|
|
4
5
|
* based on Java's hashing fn:
|
|
5
6
|
* http://www.java2s.com/example/nodejs-utility-method/string-hash/hashcode-4dc2b.html
|
|
6
7
|
*
|
|
7
8
|
* @param string - The string for which to get the hash
|
|
8
9
|
* @returns - The resulting hash of the string in hex format
|
|
9
10
|
*/
|
|
10
|
-
function hashString(string: string): string {
|
|
11
|
+
export function hashString(string: string): string {
|
|
11
12
|
let hash = 0;
|
|
12
13
|
for (let i = 0; i < string.length; i += 1) {
|
|
13
14
|
const chr = string.charCodeAt(i);
|
|
@@ -17,6 +18,28 @@ function hashString(string: string): string {
|
|
|
17
18
|
return hash.toString(16);
|
|
18
19
|
}
|
|
19
20
|
|
|
21
|
+
/** Stringifies an `object`, sorts object fields in consistent order before stringifying it.
|
|
22
|
+
*
|
|
23
|
+
* @param object - The object for which the sorted stringify is desired
|
|
24
|
+
* @returns - The stringified object with keys sorted in a consistent order
|
|
25
|
+
*/
|
|
26
|
+
export function sortedJSONStringify(object: unknown): string {
|
|
27
|
+
const allKeys = new Set<string>();
|
|
28
|
+
// solution source: https://stackoverflow.com/questions/16167581/sort-object-properties-and-json-stringify/53593328#53593328
|
|
29
|
+
JSON.stringify(object, (key, value) => (allKeys.add(key), value));
|
|
30
|
+
return JSON.stringify(object, Array.from(allKeys).sort());
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Stringifies an `object` and returns the hash of the resulting string. Sorts object fields
|
|
34
|
+
* in consistent order before stringify to prevent different hash ids for the same object.
|
|
35
|
+
*
|
|
36
|
+
* @param object - The object for which the hash is desired
|
|
37
|
+
* @returns - The string obtained from the hash of the stringified object
|
|
38
|
+
*/
|
|
39
|
+
export function hashObject(object: unknown): string {
|
|
40
|
+
return hashString(sortedJSONStringify(object));
|
|
41
|
+
}
|
|
42
|
+
|
|
20
43
|
/** Stringifies the schema and returns the hash of the resulting string. Sorts schema fields
|
|
21
44
|
* in consistent order before stringify to prevent different hash ids for the same schema.
|
|
22
45
|
*
|
|
@@ -24,8 +47,5 @@ function hashString(string: string): string {
|
|
|
24
47
|
* @returns - The string obtained from the hash of the stringified schema
|
|
25
48
|
*/
|
|
26
49
|
export default function hashForSchema<S extends StrictRJSFSchema = RJSFSchema>(schema: S) {
|
|
27
|
-
|
|
28
|
-
// solution source: https://stackoverflow.com/questions/16167581/sort-object-properties-and-json-stringify/53593328#53593328
|
|
29
|
-
JSON.stringify(schema, (key, value) => (allKeys.add(key), value));
|
|
30
|
-
return hashString(JSON.stringify(schema, Array.from(allKeys).sort()));
|
|
50
|
+
return hashObject(schema);
|
|
31
51
|
}
|
package/src/idGenerators.ts
CHANGED
|
@@ -79,3 +79,13 @@ export function ariaDescribedByIds<T = any>(id: IdSchema<T> | string, includeExa
|
|
|
79
79
|
export function optionId(id: string, optionIndex: number) {
|
|
80
80
|
return `${id}-${optionIndex}`;
|
|
81
81
|
}
|
|
82
|
+
|
|
83
|
+
/** Return a consistent `id` for the `btn` button element
|
|
84
|
+
*
|
|
85
|
+
* @param id - Either simple string id or an IdSchema from which to extract it
|
|
86
|
+
* @param btn - The button type for which to generate the id
|
|
87
|
+
* @returns - The consistent id for the button from the given `id` and `btn` type
|
|
88
|
+
*/
|
|
89
|
+
export function buttonId<T = any>(id: IdSchema<T> | string, btn: 'add' | 'copy' | 'moveDown' | 'moveUp' | 'remove') {
|
|
90
|
+
return idGenerator<T>(id, btn);
|
|
91
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -20,18 +20,29 @@ import getInputProps from './getInputProps';
|
|
|
20
20
|
import getSchemaType from './getSchemaType';
|
|
21
21
|
import getSubmitButtonOptions from './getSubmitButtonOptions';
|
|
22
22
|
import getTemplate from './getTemplate';
|
|
23
|
+
import getTestIds from './getTestIds';
|
|
23
24
|
import getUiOptions from './getUiOptions';
|
|
24
25
|
import getWidget from './getWidget';
|
|
25
26
|
import guessType from './guessType';
|
|
26
|
-
import hashForSchema from './hashForSchema';
|
|
27
|
+
import hashForSchema, { hashObject, hashString, sortedJSONStringify } from './hashForSchema';
|
|
27
28
|
import hasWidget from './hasWidget';
|
|
28
|
-
import {
|
|
29
|
+
import {
|
|
30
|
+
ariaDescribedByIds,
|
|
31
|
+
buttonId,
|
|
32
|
+
descriptionId,
|
|
33
|
+
errorId,
|
|
34
|
+
examplesId,
|
|
35
|
+
helpId,
|
|
36
|
+
optionId,
|
|
37
|
+
titleId,
|
|
38
|
+
} from './idGenerators';
|
|
29
39
|
import isConstant from './isConstant';
|
|
30
40
|
import isCustomWidget from './isCustomWidget';
|
|
31
41
|
import isFixedItems from './isFixedItems';
|
|
32
42
|
import isObject from './isObject';
|
|
33
43
|
import labelValue from './labelValue';
|
|
34
44
|
import localToUTC from './localToUTC';
|
|
45
|
+
import lookupFromFormContext from './lookupFromFormContext';
|
|
35
46
|
import mergeDefaultsWithFormData from './mergeDefaultsWithFormData';
|
|
36
47
|
import mergeObjects from './mergeObjects';
|
|
37
48
|
import mergeSchemas from './mergeSchemas';
|
|
@@ -52,6 +63,7 @@ import utcToLocal from './utcToLocal';
|
|
|
52
63
|
import validationDataMerge from './validationDataMerge';
|
|
53
64
|
import withIdRefPrefix from './withIdRefPrefix';
|
|
54
65
|
import getOptionMatchingSimpleDiscriminator from './getOptionMatchingSimpleDiscriminator';
|
|
66
|
+
import getChangedFields from './getChangedFields';
|
|
55
67
|
|
|
56
68
|
export * from './types';
|
|
57
69
|
export * from './enums';
|
|
@@ -64,6 +76,7 @@ export {
|
|
|
64
76
|
allowAdditionalItems,
|
|
65
77
|
ariaDescribedByIds,
|
|
66
78
|
asNumber,
|
|
79
|
+
buttonId,
|
|
67
80
|
canExpand,
|
|
68
81
|
createErrorHandler,
|
|
69
82
|
createSchemaUtils,
|
|
@@ -82,6 +95,7 @@ export {
|
|
|
82
95
|
examplesId,
|
|
83
96
|
ErrorSchemaBuilder,
|
|
84
97
|
findSchemaDefinition,
|
|
98
|
+
getChangedFields,
|
|
85
99
|
getDateElementProps,
|
|
86
100
|
getDiscriminatorFieldFromSchema,
|
|
87
101
|
getInputProps,
|
|
@@ -89,11 +103,14 @@ export {
|
|
|
89
103
|
getSchemaType,
|
|
90
104
|
getSubmitButtonOptions,
|
|
91
105
|
getTemplate,
|
|
106
|
+
getTestIds,
|
|
92
107
|
getUiOptions,
|
|
93
108
|
getWidget,
|
|
94
109
|
guessType,
|
|
95
110
|
hasWidget,
|
|
96
111
|
hashForSchema,
|
|
112
|
+
hashObject,
|
|
113
|
+
hashString,
|
|
97
114
|
helpId,
|
|
98
115
|
isConstant,
|
|
99
116
|
isCustomWidget,
|
|
@@ -101,6 +118,7 @@ export {
|
|
|
101
118
|
isObject,
|
|
102
119
|
labelValue,
|
|
103
120
|
localToUTC,
|
|
121
|
+
lookupFromFormContext,
|
|
104
122
|
mergeDefaultsWithFormData,
|
|
105
123
|
mergeObjects,
|
|
106
124
|
mergeSchemas,
|
|
@@ -113,6 +131,7 @@ export {
|
|
|
113
131
|
replaceStringParameters,
|
|
114
132
|
schemaRequiresTrueValue,
|
|
115
133
|
shouldRender,
|
|
134
|
+
sortedJSONStringify,
|
|
116
135
|
titleId,
|
|
117
136
|
toConstant,
|
|
118
137
|
toDateString,
|
package/src/isCustomWidget.ts
CHANGED
|
@@ -9,7 +9,7 @@ import { FormContextType, RJSFSchema, StrictRJSFSchema, UiSchema } from './types
|
|
|
9
9
|
export default function isCustomWidget<
|
|
10
10
|
T = any,
|
|
11
11
|
S extends StrictRJSFSchema = RJSFSchema,
|
|
12
|
-
F extends FormContextType = any
|
|
12
|
+
F extends FormContextType = any,
|
|
13
13
|
>(uiSchema: UiSchema<T, S, F> = {}) {
|
|
14
14
|
return (
|
|
15
15
|
// TODO: Remove the `&& uiSchema['ui:widget'] !== 'hidden'` once we support hidden widgets for arrays.
|
package/src/isObject.ts
CHANGED
|
@@ -1,15 +1,22 @@
|
|
|
1
|
-
/** Determines whether a `thing` is an object for the purposes of
|
|
1
|
+
/** Determines whether a `thing` is an object for the purposes of RJSF. In this case, `thing` is an object if it has
|
|
2
2
|
* the type `object` but is NOT null, an array or a File.
|
|
3
3
|
*
|
|
4
4
|
* @param thing - The thing to check to see whether it is an object
|
|
5
5
|
* @returns - True if it is a non-null, non-array, non-File object
|
|
6
6
|
*/
|
|
7
|
-
export default function isObject(thing: any) {
|
|
8
|
-
if (typeof
|
|
7
|
+
export default function isObject(thing: any): thing is object {
|
|
8
|
+
if (typeof thing !== 'object' || thing === null) {
|
|
9
9
|
return false;
|
|
10
10
|
}
|
|
11
|
-
|
|
11
|
+
// lastModified is guaranteed to be a number on a File instance
|
|
12
|
+
// as per https://w3c.github.io/FileAPI/#dfn-lastModified
|
|
13
|
+
if (typeof thing.lastModified === 'number' && typeof File !== 'undefined' && thing instanceof File) {
|
|
12
14
|
return false;
|
|
13
15
|
}
|
|
14
|
-
|
|
16
|
+
// getMonth is guaranteed to be a method on a Date instance
|
|
17
|
+
// as per https://tc39.es/ecma262/multipage/numbers-and-dates.html#sec-date.prototype.getmonth
|
|
18
|
+
if (typeof thing.getMonth === 'function' && typeof Date !== 'undefined' && thing instanceof Date) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
return !Array.isArray(thing);
|
|
15
22
|
}
|
package/src/labelValue.ts
CHANGED
|
@@ -17,12 +17,12 @@ export default function labelValue(label?: ReactElement, hideLabel?: boolean, fa
|
|
|
17
17
|
export default function labelValue(
|
|
18
18
|
label?: ReactElement,
|
|
19
19
|
hideLabel?: boolean,
|
|
20
|
-
fallback?: false
|
|
20
|
+
fallback?: false,
|
|
21
21
|
): undefined | false | ReactElement;
|
|
22
22
|
export default function labelValue(
|
|
23
23
|
label?: string | ReactElement,
|
|
24
24
|
hideLabel?: boolean,
|
|
25
|
-
fallback?: false | ''
|
|
25
|
+
fallback?: false | '',
|
|
26
26
|
): undefined | false | string | ReactElement {
|
|
27
27
|
return hideLabel ? fallback : label;
|
|
28
28
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import get from 'lodash/get';
|
|
2
|
+
import has from 'lodash/has';
|
|
3
|
+
|
|
4
|
+
import { FORM_CONTEXT_NAME, LOOKUP_MAP_NAME } from './constants';
|
|
5
|
+
import { FormContextType, RJSFSchema, Registry, StrictRJSFSchema } from './types';
|
|
6
|
+
|
|
7
|
+
/** Given a React JSON Schema Form registry or formContext object, return the value associated with `toLookup`. This
|
|
8
|
+
* might be contained within the lookup map in the formContext. If no such value exists, return the `fallback`
|
|
9
|
+
* value.
|
|
10
|
+
*
|
|
11
|
+
* @param regOrFc - The @rjsf registry or form context in which the lookup will occur
|
|
12
|
+
* @param toLookup - The name of the field in the lookup map in the form context to get the value for
|
|
13
|
+
* @param [fallback] - The fallback value to use if the form context does not contain a value for `toLookup`
|
|
14
|
+
* @returns - The value associated with `toLookup` in the form context or `fallback`
|
|
15
|
+
*/
|
|
16
|
+
export default function lookupFromFormContext<
|
|
17
|
+
T = any,
|
|
18
|
+
S extends StrictRJSFSchema = RJSFSchema,
|
|
19
|
+
F extends FormContextType = any,
|
|
20
|
+
>(regOrFc: Registry<T, S, F> | Registry<T, S, F>['formContext'], toLookup: string, fallback?: unknown) {
|
|
21
|
+
const lookupPath = [LOOKUP_MAP_NAME];
|
|
22
|
+
if (has(regOrFc, FORM_CONTEXT_NAME)) {
|
|
23
|
+
lookupPath.unshift(FORM_CONTEXT_NAME);
|
|
24
|
+
}
|
|
25
|
+
return get(regOrFc, [...lookupPath, toLookup], fallback);
|
|
26
|
+
}
|
|
@@ -2,6 +2,7 @@ import get from 'lodash/get';
|
|
|
2
2
|
|
|
3
3
|
import isObject from './isObject';
|
|
4
4
|
import { GenericObjectType } from '../src';
|
|
5
|
+
import isNil from 'lodash/isNil';
|
|
5
6
|
|
|
6
7
|
/** Merges the `defaults` object of type `T` into the `formData` of type `T`
|
|
7
8
|
*
|
|
@@ -12,42 +13,86 @@ import { GenericObjectType } from '../src';
|
|
|
12
13
|
* are deeply merged; additional entries from the defaults are ignored unless `mergeExtraArrayDefaults` is true, in
|
|
13
14
|
* which case the extras are appended onto the end of the form data
|
|
14
15
|
* - when the array is not set in form data, the default is copied over
|
|
15
|
-
* - scalars are overwritten/set by form data
|
|
16
|
+
* - scalars are overwritten/set by form data unless undefined and there is a default AND `defaultSupercedesUndefined`
|
|
17
|
+
* is true
|
|
16
18
|
*
|
|
17
19
|
* @param [defaults] - The defaults to merge
|
|
18
20
|
* @param [formData] - The form data into which the defaults will be merged
|
|
19
21
|
* @param [mergeExtraArrayDefaults=false] - If true, any additional default array entries are appended onto the formData
|
|
22
|
+
* @param [defaultSupercedesUndefined=false] - If true, an explicit undefined value will be overwritten by the default value
|
|
23
|
+
* @param [overrideFormDataWithDefaults=false] - If true, the default value will overwrite the form data value. If the value
|
|
24
|
+
* doesn't exist in the default, we take it from formData and in the case where the value is set to undefined in formData.
|
|
25
|
+
* This is useful when we have already merged formData with defaults and want to add an additional field from formData
|
|
26
|
+
* that does not exist in defaults.
|
|
20
27
|
* @returns - The resulting merged form data with defaults
|
|
21
28
|
*/
|
|
22
29
|
export default function mergeDefaultsWithFormData<T = any>(
|
|
23
30
|
defaults?: T,
|
|
24
31
|
formData?: T,
|
|
25
|
-
mergeExtraArrayDefaults = false
|
|
32
|
+
mergeExtraArrayDefaults = false,
|
|
33
|
+
defaultSupercedesUndefined = false,
|
|
34
|
+
overrideFormDataWithDefaults = false,
|
|
26
35
|
): T | undefined {
|
|
27
36
|
if (Array.isArray(formData)) {
|
|
28
37
|
const defaultsArray = Array.isArray(defaults) ? defaults : [];
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
38
|
+
|
|
39
|
+
// If overrideFormDataWithDefaults is true, we want to override the formData with the defaults
|
|
40
|
+
const overrideArray = overrideFormDataWithDefaults ? defaultsArray : formData;
|
|
41
|
+
const overrideOppositeArray = overrideFormDataWithDefaults ? formData : defaultsArray;
|
|
42
|
+
|
|
43
|
+
const mapped = overrideArray.map((value, idx) => {
|
|
44
|
+
// We want to explicitly make sure that the value is NOT undefined since null, 0 and empty space are valid values
|
|
45
|
+
if (overrideOppositeArray[idx] !== undefined) {
|
|
46
|
+
return mergeDefaultsWithFormData<any>(
|
|
47
|
+
defaultsArray[idx],
|
|
48
|
+
formData[idx],
|
|
49
|
+
mergeExtraArrayDefaults,
|
|
50
|
+
defaultSupercedesUndefined,
|
|
51
|
+
overrideFormDataWithDefaults,
|
|
52
|
+
);
|
|
32
53
|
}
|
|
33
54
|
return value;
|
|
34
55
|
});
|
|
56
|
+
|
|
35
57
|
// Merge any extra defaults when mergeExtraArrayDefaults is true
|
|
36
|
-
|
|
37
|
-
|
|
58
|
+
// Or when overrideFormDataWithDefaults is true and the default array is shorter than the formData array
|
|
59
|
+
if ((mergeExtraArrayDefaults || overrideFormDataWithDefaults) && mapped.length < overrideOppositeArray.length) {
|
|
60
|
+
mapped.push(...overrideOppositeArray.slice(mapped.length));
|
|
38
61
|
}
|
|
39
62
|
return mapped as unknown as T;
|
|
40
63
|
}
|
|
41
64
|
if (isObject(formData)) {
|
|
42
65
|
const acc: { [key in keyof T]: any } = Object.assign({}, defaults); // Prevent mutation of source object.
|
|
43
66
|
return Object.keys(formData as GenericObjectType).reduce((acc, key) => {
|
|
67
|
+
const keyValue = get(formData, key);
|
|
68
|
+
const keyExistsInDefaults = isObject(defaults) && key in (defaults as GenericObjectType);
|
|
69
|
+
const keyExistsInFormData = key in (formData as GenericObjectType);
|
|
44
70
|
acc[key as keyof T] = mergeDefaultsWithFormData<T>(
|
|
45
71
|
defaults ? get(defaults, key) : {},
|
|
46
|
-
|
|
47
|
-
mergeExtraArrayDefaults
|
|
72
|
+
keyValue,
|
|
73
|
+
mergeExtraArrayDefaults,
|
|
74
|
+
defaultSupercedesUndefined,
|
|
75
|
+
// overrideFormDataWithDefaults can be true only when the key value exists in defaults
|
|
76
|
+
// Or if the key value doesn't exist in formData
|
|
77
|
+
overrideFormDataWithDefaults && (keyExistsInDefaults || !keyExistsInFormData),
|
|
48
78
|
);
|
|
49
79
|
return acc;
|
|
50
80
|
}, acc);
|
|
51
81
|
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* If the defaultSupercedesUndefined flag is true
|
|
85
|
+
* And formData is set to undefined or null and defaults are defined
|
|
86
|
+
* Or if formData is a number and is NaN return defaults
|
|
87
|
+
* Or if overrideFormDataWithDefaults flag is true and formData is set to not undefined/null return defaults
|
|
88
|
+
*/
|
|
89
|
+
if (
|
|
90
|
+
(defaultSupercedesUndefined &&
|
|
91
|
+
((!isNil(defaults) && isNil(formData)) || (typeof formData === 'number' && isNaN(formData)))) ||
|
|
92
|
+
(overrideFormDataWithDefaults && !isNil(formData))
|
|
93
|
+
) {
|
|
94
|
+
return defaults;
|
|
95
|
+
}
|
|
96
|
+
|
|
52
97
|
return formData;
|
|
53
98
|
}
|
package/src/mergeObjects.ts
CHANGED
|
@@ -13,27 +13,30 @@ import { GenericObjectType } from './types';
|
|
|
13
13
|
export default function mergeObjects(
|
|
14
14
|
obj1: GenericObjectType,
|
|
15
15
|
obj2: GenericObjectType,
|
|
16
|
-
concatArrays: boolean | 'preventDuplicates' = false
|
|
16
|
+
concatArrays: boolean | 'preventDuplicates' = false,
|
|
17
17
|
) {
|
|
18
|
-
return Object.keys(obj2).reduce(
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
18
|
+
return Object.keys(obj2).reduce(
|
|
19
|
+
(acc, key) => {
|
|
20
|
+
const left = obj1 ? obj1[key] : {},
|
|
21
|
+
right = obj2[key];
|
|
22
|
+
if (obj1 && key in obj1 && isObject(right)) {
|
|
23
|
+
acc[key] = mergeObjects(left, right, concatArrays);
|
|
24
|
+
} else if (concatArrays && Array.isArray(left) && Array.isArray(right)) {
|
|
25
|
+
let toMerge = right;
|
|
26
|
+
if (concatArrays === 'preventDuplicates') {
|
|
27
|
+
toMerge = right.reduce((result, value) => {
|
|
28
|
+
if (!left.includes(value)) {
|
|
29
|
+
result.push(value);
|
|
30
|
+
}
|
|
31
|
+
return result;
|
|
32
|
+
}, []);
|
|
33
|
+
}
|
|
34
|
+
acc[key] = left.concat(toMerge);
|
|
35
|
+
} else {
|
|
36
|
+
acc[key] = right;
|
|
32
37
|
}
|
|
33
|
-
acc
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
return acc;
|
|
38
|
-
}, Object.assign({}, obj1)); // Prevent mutation of source object.
|
|
38
|
+
return acc;
|
|
39
|
+
},
|
|
40
|
+
Object.assign({}, obj1),
|
|
41
|
+
); // Prevent mutation of source object.
|
|
39
42
|
}
|