@rjsf/utils
Version:
Utility functions for @rjsf/core
4 lines • 431 kB
Source Map (JSON)
{
"version": 3,
"sources": ["../src/index.ts", "../src/isObject.ts", "../src/allowAdditionalItems.ts", "../src/asNumber.ts", "../src/constants.ts", "../src/getUiOptions.ts", "../src/canExpand.ts", "../src/createErrorHandler.ts", "../src/createSchemaUtils.ts", "../src/deepEquals.ts", "../src/findSchemaDefinition.ts", "../src/schema/findFieldInSchema.ts", "../src/schema/findSelectedOptionInXxxOf.ts", "../src/getDiscriminatorFieldFromSchema.ts", "../src/schema/retrieveSchema.ts", "../src/guessType.ts", "../src/mergeSchemas.ts", "../src/getSchemaType.ts", "../src/schema/getFirstMatchingOption.ts", "../src/getOptionMatchingSimpleDiscriminator.ts", "../src/schema/shallowAllOfMerge.ts", "../src/schema/getFromSchema.ts", "../src/schema/getClosestMatchingOption.ts", "../src/schema/getDefaultFormState.ts", "../src/constIsAjvDataReference.ts", "../src/isConstant.ts", "../src/isFixedItems.ts", "../src/mergeDefaultsWithFormData.ts", "../src/mergeObjects.ts", "../src/optionsList.ts", "../src/toConstant.ts", "../src/schema/isSelect.ts", "../src/schema/isMultiSelect.ts", "../src/schema/getDisplayLabel.ts", "../src/isCustomWidget.ts", "../src/schema/isFilesArray.ts", "../src/schema/omitExtraData.ts", "../src/schema/sanitizeDataForNewSchema.ts", "../src/schema/toPathSchema.ts", "../src/dataURItoBlob.ts", "../src/pad.ts", "../src/dateRangeOptions.ts", "../src/replaceStringParameters.ts", "../src/englishStringTranslator.ts", "../src/enumOptionsValueForIndex.ts", "../src/enumOptionsDeselectValue.ts", "../src/enumOptionsIsSelected.ts", "../src/enumOptionsIndexForValue.ts", "../src/enumOptionSelectedValue.ts", "../src/enumOptionsSelectValue.ts", "../src/enumOptionValueDecoder.ts", "../src/enumOptionValueEncoder.ts", "../src/ErrorSchemaBuilder.ts", "../src/getChangedFields.ts", "../src/getDateElementProps.ts", "../src/rangeSpec.ts", "../src/getInputProps.ts", "../src/getOptionValueFormat.ts", "../src/getSubmitButtonOptions.ts", "../src/getTemplate.ts", "../src/getTestIds.ts", "../src/getWidget.tsx", "../src/hashForSchema.ts", "../src/hasWidget.ts", "../src/idGenerators.ts", "../src/isFormDataAvailable.ts", "../src/isRootSchema.ts", "../src/labelValue.ts", "../src/localToUTC.ts", "../src/lookupFromFormContext.ts", "../src/nameGenerators.ts", "../src/orderProperties.ts", "../src/parseDateString.ts", "../src/removeOptionalEmptyObjects.ts", "../src/resolveUiSchema.ts", "../src/schemaRequiresTrueValue.ts", "../src/shallowEquals.ts", "../src/shouldRender.ts", "../src/shouldRenderOptionalField.ts", "../src/toDateString.ts", "../src/toErrorList.ts", "../src/toErrorSchema.ts", "../src/toFieldPathId.ts", "../src/unwrapErrorHandler.ts", "../src/useAltDateWidgetProps.tsx", "../src/useDeepCompareMemo.ts", "../src/useFileWidgetProps.ts", "../src/utcToLocal.ts", "../src/validationDataMerge.ts", "../src/withIdRefPrefix.ts", "../src/enums.ts", "../src/parser/schemaParser.ts", "../src/parser/ParserValidator.ts"],
"sourcesContent": ["import allowAdditionalItems from './allowAdditionalItems';\nimport asNumber from './asNumber';\nimport canExpand from './canExpand';\nimport createErrorHandler from './createErrorHandler';\nimport createSchemaUtils from './createSchemaUtils';\nimport dataURItoBlob from './dataURItoBlob';\nimport dateRangeOptions from './dateRangeOptions';\nimport deepEquals from './deepEquals';\nimport englishStringTranslator from './englishStringTranslator';\nimport enumOptionsDeselectValue from './enumOptionsDeselectValue';\nimport enumOptionSelectedValue from './enumOptionSelectedValue';\nimport enumOptionsIndexForValue from './enumOptionsIndexForValue';\nimport enumOptionsIsSelected from './enumOptionsIsSelected';\nimport enumOptionsSelectValue from './enumOptionsSelectValue';\nimport enumOptionsValueForIndex from './enumOptionsValueForIndex';\nimport enumOptionValueDecoder from './enumOptionValueDecoder';\nimport enumOptionValueEncoder from './enumOptionValueEncoder';\nimport ErrorSchemaBuilder from './ErrorSchemaBuilder';\nimport findSchemaDefinition from './findSchemaDefinition';\nimport getChangedFields from './getChangedFields';\nimport type { DateElementFormat, DateElementProp } from './getDateElementProps';\nimport getDateElementProps from './getDateElementProps';\nimport getDiscriminatorFieldFromSchema from './getDiscriminatorFieldFromSchema';\nimport getInputProps from './getInputProps';\nimport getOptionMatchingSimpleDiscriminator from './getOptionMatchingSimpleDiscriminator';\nimport getOptionValueFormat from './getOptionValueFormat';\nimport getSchemaType from './getSchemaType';\nimport getSubmitButtonOptions from './getSubmitButtonOptions';\nimport getTemplate from './getTemplate';\nimport getTestIds from './getTestIds';\nimport getUiOptions from './getUiOptions';\nimport getWidget from './getWidget';\nimport guessType from './guessType';\nimport hashForSchema, { hashObject, hashString, sortedJSONStringify } from './hashForSchema';\nimport hasWidget from './hasWidget';\nimport {\n ariaDescribedByIds,\n buttonId,\n descriptionId,\n errorId,\n examplesId,\n helpId,\n optionalControlsId,\n optionId,\n titleId,\n} from './idGenerators';\nimport isConstant from './isConstant';\nimport isCustomWidget from './isCustomWidget';\nimport isFixedItems from './isFixedItems';\nimport isFormDataAvailable from './isFormDataAvailable';\nimport isObject from './isObject';\nimport isRootSchema from './isRootSchema';\nimport labelValue from './labelValue';\nimport localToUTC from './localToUTC';\nimport lookupFromFormContext from './lookupFromFormContext';\nimport mergeDefaultsWithFormData from './mergeDefaultsWithFormData';\nimport mergeObjects from './mergeObjects';\nimport mergeSchemas from './mergeSchemas';\nimport { bracketNameGenerator, dotNotationNameGenerator } from './nameGenerators';\nimport optionsList from './optionsList';\nimport orderProperties from './orderProperties';\nimport pad from './pad';\nimport parseDateString from './parseDateString';\nimport rangeSpec from './rangeSpec';\nimport removeOptionalEmptyObjects from './removeOptionalEmptyObjects';\nimport replaceStringParameters from './replaceStringParameters';\nimport resolveUiSchema from './resolveUiSchema';\nimport schemaRequiresTrueValue from './schemaRequiresTrueValue';\nimport shallowEquals from './shallowEquals';\nimport type { ComponentUpdateStrategy } from './shouldRender';\nimport shouldRender from './shouldRender';\nimport shouldRenderOptionalField from './shouldRenderOptionalField';\nimport toConstant from './toConstant';\nimport toDateString from './toDateString';\nimport toErrorList from './toErrorList';\nimport toErrorSchema from './toErrorSchema';\nimport toFieldPathId from './toFieldPathId';\nimport unwrapErrorHandler from './unwrapErrorHandler';\nimport type { DateElementProps, UseAltDateWidgetResult } from './useAltDateWidgetProps';\nimport useAltDateWidgetProps, { DateElement } from './useAltDateWidgetProps';\nimport useDeepCompareMemo from './useDeepCompareMemo';\nimport type { FileInfoType, UseFileWidgetPropsResult } from './useFileWidgetProps';\nimport useFileWidgetProps from './useFileWidgetProps';\nimport utcToLocal from './utcToLocal';\nimport validationDataMerge from './validationDataMerge';\nimport withIdRefPrefix from './withIdRefPrefix';\n\nexport type * from './types';\nexport * from './enums';\n\nexport * from './constants';\nexport * from './parser';\nexport * from './schema';\n\nexport type {\n ComponentUpdateStrategy,\n DateElementFormat,\n DateElementProp,\n DateElementProps,\n FileInfoType,\n UseAltDateWidgetResult,\n UseFileWidgetPropsResult,\n};\n\nexport {\n allowAdditionalItems,\n ariaDescribedByIds,\n asNumber,\n buttonId,\n canExpand,\n createErrorHandler,\n createSchemaUtils,\n DateElement,\n dataURItoBlob,\n dateRangeOptions,\n deepEquals,\n descriptionId,\n englishStringTranslator,\n enumOptionSelectedValue,\n enumOptionValueDecoder,\n enumOptionValueEncoder,\n enumOptionsDeselectValue,\n enumOptionsIndexForValue,\n enumOptionsIsSelected,\n enumOptionsSelectValue,\n enumOptionsValueForIndex,\n errorId,\n examplesId,\n ErrorSchemaBuilder,\n findSchemaDefinition,\n getChangedFields,\n getDateElementProps,\n getDiscriminatorFieldFromSchema,\n getInputProps,\n getOptionMatchingSimpleDiscriminator,\n getOptionValueFormat,\n getSchemaType,\n getSubmitButtonOptions,\n getTemplate,\n getTestIds,\n getUiOptions,\n getWidget,\n guessType,\n hasWidget,\n hashForSchema,\n hashObject,\n hashString,\n helpId,\n isConstant,\n isCustomWidget,\n isFixedItems,\n isFormDataAvailable,\n isObject,\n isRootSchema,\n labelValue,\n localToUTC,\n lookupFromFormContext,\n mergeDefaultsWithFormData,\n mergeObjects,\n mergeSchemas,\n optionalControlsId,\n optionId,\n optionsList,\n orderProperties,\n pad,\n parseDateString,\n rangeSpec,\n // oxlint-disable-next-line typescript/no-deprecated\n removeOptionalEmptyObjects,\n replaceStringParameters,\n resolveUiSchema,\n schemaRequiresTrueValue,\n shallowEquals,\n shouldRender,\n shouldRenderOptionalField,\n sortedJSONStringify,\n titleId,\n toConstant,\n toDateString,\n toErrorList,\n toErrorSchema,\n toFieldPathId,\n unwrapErrorHandler,\n useAltDateWidgetProps,\n useDeepCompareMemo,\n useFileWidgetProps,\n utcToLocal,\n validationDataMerge,\n withIdRefPrefix,\n bracketNameGenerator,\n dotNotationNameGenerator,\n};\n", "/** Determines whether a `thing` is an object for the purposes of RJSF. In this case, `thing` is an object if it has\n * the type `object` but is NOT null, an array or a File.\n *\n * @param thing - The thing to check to see whether it is an object\n * @returns - True if it is a non-null, non-array, non-File object\n */\nexport default function isObject(thing: any): thing is object {\n if (typeof thing !== 'object' || thing === null) {\n return false;\n }\n // lastModified is guaranteed to be a number on a File instance\n // as per https://w3c.github.io/FileAPI/#dfn-lastModified\n if (typeof thing.lastModified === 'number' && typeof File !== 'undefined' && thing instanceof File) {\n return false;\n }\n // getMonth is guaranteed to be a method on a Date instance\n // as per https://tc39.es/ecma262/multipage/numbers-and-dates.html#sec-date.prototype.getmonth\n if (typeof thing.getMonth === 'function' && typeof Date !== 'undefined' && thing instanceof Date) {\n return false;\n }\n return !Array.isArray(thing);\n}\n", "import isObject from './isObject';\nimport type { RJSFSchema, StrictRJSFSchema } from './types';\n\n/** Checks the schema to see if it is allowing additional items, by verifying that `schema.additionalItems` is an\n * object. The user is warned in the console if `schema.additionalItems` has the value `true`.\n *\n * @param schema - The schema object to check\n * @returns - True if additional items is allowed, otherwise false\n */\nexport default function allowAdditionalItems<S extends StrictRJSFSchema = RJSFSchema>(schema: S) {\n if (schema.additionalItems === true) {\n // oxlint-disable-next-line no-console\n console.warn('additionalItems=true is currently not supported');\n }\n return isObject(schema.additionalItems);\n}\n", "/** Attempts to convert the string into a number. If an empty string is provided, then `undefined` is returned. If a\n * `null` is provided, it is returned. If the string ends in a `.` then the string is returned because the user may be\n * in the middle of typing a float number. If a number ends in a pattern like `.0`, `.20`, `.030`, string is returned\n * because the user may be typing number that will end in a non-zero digit. Otherwise, the string is wrapped by\n * `Number()` and if that result is not `NaN`, that number will be returned, otherwise the string `value` will be.\n *\n * @param value - The string or null value to convert to a number\n * @returns - The `value` converted to a number when appropriate, otherwise the `value`\n */\nexport default function asNumber(value: string | null) {\n if (value === '') {\n return undefined;\n }\n if (value === null) {\n return null;\n }\n // oxlint-disable-next-line typescript/prefer-string-starts-ends-with -- regex test() coerces undefined to \"undefined\" safely; endsWith() throws on undefined values passed at runtime\n if (/\\.$/.test(value)) {\n // '3.' can't really be considered a number even if it parses in js. The\n // user is most likely entering a float.\n return value;\n }\n // oxlint-disable-next-line typescript/prefer-string-starts-ends-with -- same as above\n if (/\\.0$/.test(value)) {\n // we need to return this as a string here, to allow for input like 3.07\n return value;\n }\n\n if (/\\.\\d*0$/.test(value)) {\n // It's a number, that's cool - but we need it as a string so it doesn't screw\n // with the user when entering dollar amounts or other values (such as those with\n // specific precision or number of significant digits)\n return value;\n }\n\n const n = Number(value);\n const valid = typeof n === 'number' && !Number.isNaN(n);\n\n return valid ? n : value;\n}\n", "/** Below are the list of all the keys into various elements of a RJSFSchema or UiSchema that are used by the various\n * utility functions. In addition to those keys, there are the special `ADDITIONAL_PROPERTY_FLAG` and\n * `RJSF_ADDITIONAL_PROPERTIES_FLAG` flags that is added to a schema under certain conditions by the `retrieveSchema()`\n * utility.\n */\nexport const ADDITIONAL_PROPERTY_FLAG = '__additional_property';\nexport const ADDITIONAL_PROPERTIES_KEY = 'additionalProperties';\nexport const ALL_OF_KEY = 'allOf';\nexport const ANY_OF_KEY = 'anyOf';\nexport const CONST_KEY = 'const';\nexport const DEFAULT_KEY = 'default';\nexport const DEFINITIONS_KEY = 'definitions';\nexport const DEPENDENCIES_KEY = 'dependencies';\nexport const ENUM_KEY = 'enum';\nexport const ERRORS_KEY = '__errors';\nexport const ID_KEY = '$id';\nexport const IF_KEY = 'if';\nexport const ITEMS_KEY = 'items';\nexport const JUNK_OPTION_ID = '_$junk_option_schema_id$_';\nexport const NAME_KEY = '$name';\nexport const ONE_OF_KEY = 'oneOf';\nexport const PATTERN_PROPERTIES_KEY = 'patternProperties';\nexport const PROPERTIES_KEY = 'properties';\nexport const READONLY_KEY = 'readonly';\nexport const REQUIRED_KEY = 'required';\nexport const SUBMIT_BTN_OPTIONS_KEY = 'submitButtonOptions';\nexport const REF_KEY = '$ref';\nexport const RJSF_REF_KEY = '__rjsf_ref';\nexport const SCHEMA_KEY = '$schema';\nexport const DEFAULT_ID_PREFIX = 'root';\nexport const DEFAULT_ID_SEPARATOR = '_';\n/** The path of the discriminator value returned by the schema endpoint.\n * The discriminator is the value in a `oneOf` that determines which option is selected.\n */\nexport const DISCRIMINATOR_PATH = ['discriminator', 'propertyName'];\n/** The name of the `formContext` attribute in the React JSON Schema Form Registry\n */\nexport const FORM_CONTEXT_NAME = 'formContext';\n\n/** The name of the `layoutGridLookupMap` attribute in the form context\n */\nexport const LOOKUP_MAP_NAME = 'layoutGridLookupMap';\nexport const RJSF_ADDITIONAL_PROPERTIES_FLAG = '__rjsf_additionalProperties';\nexport const ROOT_SCHEMA_PREFIX = '__rjsf_rootSchema';\nexport const UI_FIELD_KEY = 'ui:field';\nexport const UI_WIDGET_KEY = 'ui:widget';\nexport const UI_OPTIONS_KEY = 'ui:options';\nexport const UI_GLOBAL_OPTIONS_KEY = 'ui:globalOptions';\nexport const UI_DEFINITIONS_KEY = 'ui:definitions';\n\n/** The JSON Schema version strings\n */\nexport const JSON_SCHEMA_DRAFT_2019_09 = 'https://json-schema.org/draft/2019-09/schema';\nexport const JSON_SCHEMA_DRAFT_2020_12 = 'https://json-schema.org/draft/2020-12/schema';\n", "import { UI_OPTIONS_KEY, UI_WIDGET_KEY } from './constants';\nimport isObject from './isObject';\nimport type {\n FormContextType,\n GlobalUISchemaOptions,\n RJSFSchema,\n StrictRJSFSchema,\n UIOptionsType,\n UiSchema,\n} from './types';\n\n/** Get all passed options from ui:options, and ui:<optionName>, returning them in an object with the `ui:`\n * stripped off. Any `globalOptions` will always be returned, unless they are overridden by options in the `uiSchema`.\n *\n * @param [uiSchema={}] - The UI Schema from which to get any `ui:xxx` options\n * @param [globalOptions={}] - The optional Global UI Schema from which to get any fallback `xxx` options\n * @returns - An object containing all the `ui:xxx` options with the `ui:` stripped off along with all `globalOptions`\n */\nexport default function getUiOptions<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(\n uiSchema: UiSchema<T, S, F> = {},\n globalOptions: GlobalUISchemaOptions = {},\n): UIOptionsType<T, S, F> {\n // Handle null or undefined uiSchema\n if (!uiSchema) {\n return { ...globalOptions };\n }\n return Object.keys(uiSchema)\n .filter((key) => key.startsWith('ui:'))\n .reduce(\n (options, key) => {\n const value = uiSchema[key];\n if (key === UI_WIDGET_KEY && isObject(value)) {\n // oxlint-disable-next-line no-console\n console.error('Setting options via ui:widget object is no longer supported, use ui:options instead');\n return options;\n }\n if (key === UI_OPTIONS_KEY && isObject(value)) {\n return { ...options, ...value };\n }\n return { ...options, [key.substring(3)]: value };\n },\n { ...globalOptions },\n );\n}\n", "import getUiOptions from './getUiOptions';\nimport type { FormContextType, RJSFSchema, StrictRJSFSchema, UiSchema } from './types';\n\n/** Checks whether the field described by `schema`, having the `uiSchema` and `formData` supports expanding. The UI for\n * the field can expand if it has additional properties, is not forced as non-expandable by the `uiSchema` and the\n * `formData` object doesn't already have `schema.maxProperties` elements.\n *\n * @param schema - The schema for the field that is being checked\n * @param [uiSchema={}] - The uiSchema for the field\n * @param [formData] - The formData for the field\n * @returns - True if the schema element has additionalProperties, is expandable, and not at the maxProperties limit\n */\nexport default function canExpand<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(\n schema: RJSFSchema,\n uiSchema: UiSchema<T, S, F> = {},\n formData?: T,\n) {\n if (!(schema.additionalProperties || schema.patternProperties)) {\n return false;\n }\n const { expandable = true } = getUiOptions<T, S, F>(uiSchema);\n if (expandable === false) {\n return expandable;\n }\n // if ui:options.expandable was not explicitly set to false, we can add\n // another property if we have not exceeded maxProperties yet\n if (schema.maxProperties !== undefined && formData) {\n return Object.keys(formData).length < schema.maxProperties;\n }\n return true;\n}\n", "import isPlainObject from 'lodash/isPlainObject';\n\nimport { ERRORS_KEY } from './constants';\nimport type { FieldValidation, FormValidation, GenericObjectType } from './types';\n\n/** Given a `formData` object, recursively creates a `FormValidation` error handling structure around it\n *\n * @param formData - The form data around which the error handler is created\n * @returns - A `FormValidation` object based on the `formData` structure\n */\nexport default function createErrorHandler<T = any>(formData: T): FormValidation<T> {\n const handler: FieldValidation = {\n // We store the list of errors for this node in a property named __errors\n // to avoid name collision with a possible sub schema field named\n // 'errors' (see `utils.toErrorSchema`).\n [ERRORS_KEY]: [],\n addError(message: string) {\n this[ERRORS_KEY]!.push(message);\n },\n };\n if (Array.isArray(formData)) {\n return formData.reduce((acc, value, key) => ({ ...acc, [key]: createErrorHandler(value) }), handler);\n }\n if (isPlainObject(formData)) {\n const formObject: GenericObjectType = formData as GenericObjectType;\n return Object.keys(formObject).reduce(\n (acc, key) => ({ ...acc, [key]: createErrorHandler(formObject[key]) }),\n handler as FormValidation<T>,\n );\n }\n return handler as FormValidation<T>;\n}\n", "import get from 'lodash/get';\n\nimport { ID_KEY, JSON_SCHEMA_DRAFT_2020_12, SCHEMA_KEY } from './constants';\nimport deepEquals from './deepEquals';\nimport { makeAllReferencesAbsolute } from './findSchemaDefinition';\nimport {\n findFieldInSchema,\n findSelectedOptionInXxxOf,\n getDefaultFormState,\n getDisplayLabel,\n getClosestMatchingOption,\n getFirstMatchingOption,\n getFromSchema,\n isFilesArray,\n isMultiSelect,\n isSelect,\n omitExtraData,\n retrieveSchema,\n sanitizeDataForNewSchema,\n toPathSchema,\n} from './schema';\nimport type {\n Experimental_CustomMergeAllOf,\n Experimental_DefaultFormStateBehavior,\n FormContextType,\n FoundFieldType,\n GlobalUISchemaOptions,\n PathSchema,\n RJSFSchema,\n SchemaFieldPath,\n SchemaUtilsType,\n StrictRJSFSchema,\n UiSchema,\n ValidatorType,\n} from './types';\n\n/** The `SchemaUtils` class provides a wrapper around the publicly exported APIs in the `utils/schema` directory such\n * that one does not have to explicitly pass the `validator`, `rootSchema`, `experimental_defaultFormStateBehavior` or\n * `experimental_customMergeAllOf` to each method. Since these generally do not change across a `Form`, this allows for\n * providing a simplified set of APIs to the `@rjsf/core` components and the various themes as well. This class\n * implements the `SchemaUtilsType` interface.\n */\nclass SchemaUtils<\n T = any,\n S extends StrictRJSFSchema = RJSFSchema,\n F extends FormContextType = any,\n> implements SchemaUtilsType<T, S, F> {\n rootSchema: S;\n validator: ValidatorType<T, S, F>;\n experimental_defaultFormStateBehavior: Experimental_DefaultFormStateBehavior;\n experimental_customMergeAllOf?: Experimental_CustomMergeAllOf<S>;\n\n /** Constructs the `SchemaUtils` instance with the given `validator` and `rootSchema` stored as instance variables\n *\n * @param validator - An implementation of the `ValidatorType` interface that will be forwarded to all the APIs\n * @param rootSchema - The root schema that will be forwarded to all the APIs\n * @param experimental_defaultFormStateBehavior - Configuration flags to allow users to override default form state behavior\n * @param [experimental_customMergeAllOf] - Optional function that allows for custom merging of `allOf` schemas\n */\n constructor(\n validator: ValidatorType<T, S, F>,\n rootSchema: S,\n experimental_defaultFormStateBehavior: Experimental_DefaultFormStateBehavior,\n experimental_customMergeAllOf?: Experimental_CustomMergeAllOf<S>,\n ) {\n if (rootSchema && rootSchema[SCHEMA_KEY] === JSON_SCHEMA_DRAFT_2020_12) {\n this.rootSchema = makeAllReferencesAbsolute(rootSchema, get(rootSchema, ID_KEY, '#'));\n } else {\n this.rootSchema = rootSchema;\n }\n this.validator = validator;\n this.experimental_defaultFormStateBehavior = experimental_defaultFormStateBehavior;\n this.experimental_customMergeAllOf = experimental_customMergeAllOf;\n }\n\n /** Returns the `rootSchema` in the `SchemaUtilsType`\n *\n * @returns - The `rootSchema`\n */\n getRootSchema() {\n return this.rootSchema;\n }\n\n /** Returns the `ValidatorType` in the `SchemaUtilsType`\n *\n * @returns - The `ValidatorType`\n */\n getValidator() {\n return this.validator;\n }\n\n /** Determines whether either the `validator` and `rootSchema` differ from the ones associated with this instance of\n * the `SchemaUtilsType`. If either `validator` or `rootSchema` are falsy, then return false to prevent the creation\n * of a new `SchemaUtilsType` with incomplete properties.\n *\n * @param validator - An implementation of the `ValidatorType` interface that will be compared against the current one\n * @param rootSchema - The root schema that will be compared against the current one\n * @param [experimental_defaultFormStateBehavior] Optional configuration object, if provided, allows users to override default form state behavior\n * @param [experimental_customMergeAllOf] - Optional function that allows for custom merging of `allOf` schemas\n * @returns - True if the `SchemaUtilsType` differs from the given `validator` or `rootSchema`\n */\n doesSchemaUtilsDiffer(\n validator: ValidatorType<T, S, F>,\n rootSchema: S,\n experimental_defaultFormStateBehavior = {},\n experimental_customMergeAllOf?: Experimental_CustomMergeAllOf<S>,\n ): boolean {\n // If either validator or rootSchema are falsy, return false to prevent the creation\n // of a new SchemaUtilsType with incomplete properties.\n if (!validator || !rootSchema) {\n return false;\n }\n\n return (\n this.validator !== validator ||\n !deepEquals(this.rootSchema, rootSchema) ||\n !deepEquals(this.experimental_defaultFormStateBehavior, experimental_defaultFormStateBehavior) ||\n this.experimental_customMergeAllOf !== experimental_customMergeAllOf\n );\n }\n\n /** Finds the field specified by the `path` within the root or recursed `schema`. If there is no field for the specified\n * `path`, then the default `{ field: undefined, isRequired: undefined }` is returned. It determines whether a leaf\n * field is in the `required` list for its parent and if so, it is marked as required on return.\n *\n * @param schema - The current node within the JSON schema\n * @param path - The remaining keys in the path to the desired field\n * @param [formData] - The form data that is used to determine which oneOf option\n * @returns - An object that contains the field and its required state. If no field can be found then\n * `{ field: undefined, isRequired: undefined }` is returned.\n */\n findFieldInSchema(schema: S, path: SchemaFieldPath, formData?: T): FoundFieldType<S> {\n return findFieldInSchema(\n this.validator,\n this.rootSchema,\n schema,\n path,\n formData,\n this.experimental_customMergeAllOf,\n );\n }\n\n /** Finds the oneOf option inside the `schema['any/oneOf']` list which has the `properties[selectorField].default` that\n * matches the `formData[selectorField]` value. For the purposes of this function, `selectorField` is either\n * `schema.discriminator.propertyName` or `fallbackField`.\n *\n * @param schema - The schema element in which to search for the selected oneOf option\n * @param fallbackField - The field to use as a backup selector field if the schema does not have a required field\n * @param xxx - Either `oneOf` or `anyOf`, defines which value is being sought\n * @param [formData={}] - The form data that is used to determine which oneOf option\n * @returns - The anyOf/oneOf option that matches the selector field in the schema or undefined if nothing is selected\n */\n findSelectedOptionInXxxOf(schema: S, fallbackField: string, xxx: 'anyOf' | `oneOf`, formData: T): S | undefined {\n return findSelectedOptionInXxxOf(\n this.validator,\n this.rootSchema,\n schema,\n fallbackField,\n xxx,\n formData,\n this.experimental_customMergeAllOf,\n );\n }\n\n /** Returns the superset of `formData` that includes the given set updated to include any missing fields that have\n * computed to have defaults provided in the `schema`.\n *\n * @param schema - The schema for which the default state is desired\n * @param [formData] - The current formData, if any, onto which to provide any missing defaults\n * @param [includeUndefinedValues=false] - Optional flag, if true, cause undefined values to be added as defaults.\n * If \"excludeObjectChildren\", pass `includeUndefinedValues` as false when computing defaults for any nested\n * object properties.\n * @param initialDefaultsGenerated - Indicates whether or not initial defaults have been generated\n * @returns - The resulting `formData` with all the defaults provided\n */\n getDefaultFormState(\n schema: S,\n formData?: T,\n includeUndefinedValues: boolean | 'excludeObjectChildren' = false,\n initialDefaultsGenerated?: boolean,\n ): T | T[] | undefined {\n return getDefaultFormState<T, S, F>(\n this.validator,\n schema,\n formData,\n this.rootSchema,\n includeUndefinedValues,\n this.experimental_defaultFormStateBehavior,\n this.experimental_customMergeAllOf,\n initialDefaultsGenerated,\n );\n }\n\n /** Determines whether the combination of `schema` and `uiSchema` properties indicates that the label for the `schema`\n * should be displayed in a UI.\n *\n * @param schema - The schema for which the display label flag is desired\n * @param [uiSchema] - The UI schema from which to derive potentially displayable information\n * @param [globalOptions={}] - The optional Global UI Schema from which to get any fallback `xxx` options\n * @returns - True if the label should be displayed or false if it should not\n */\n getDisplayLabel(schema: S, uiSchema?: UiSchema<T, S, F>, globalOptions?: GlobalUISchemaOptions) {\n return getDisplayLabel<T, S, F>(\n this.validator,\n schema,\n uiSchema,\n this.rootSchema,\n globalOptions,\n this.experimental_customMergeAllOf,\n );\n }\n\n /** Determines which of the given `options` provided most closely matches the `formData`.\n * Returns the index of the option that is valid and is the closest match, or 0 if there is no match.\n *\n * The closest match is determined using the number of matching properties, and more heavily favors options with\n * matching readOnly, default, or const values.\n *\n * @param formData - The form data associated with the schema\n * @param options - The list of options that can be selected from\n * @param [selectedOption] - The index of the currently selected option, defaulted to -1 if not specified\n * @param [discriminatorField] - The optional name of the field within the options object whose value is used to\n * determine which option is selected\n * @returns - The index of the option that is the closest match to the `formData` or the `selectedOption` if no match\n */\n getClosestMatchingOption(\n formData: T | undefined,\n options: S[],\n selectedOption?: number,\n discriminatorField?: string,\n ): number {\n return getClosestMatchingOption<T, S, F>(\n this.validator,\n this.rootSchema,\n formData,\n options,\n selectedOption,\n discriminatorField,\n this.experimental_customMergeAllOf,\n );\n }\n\n /** Given the `formData` and list of `options`, attempts to find the index of the first option that matches the data.\n * Always returns the first option if there is nothing that matches.\n *\n * @param formData - The current formData, if any, used to figure out a match\n * @param options - The list of options to find a matching options from\n * @param [discriminatorField] - The optional name of the field within the options object whose value is used to\n * determine which option is selected\n * @returns - The firstindex of the matched option or 0 if none is available\n */\n getFirstMatchingOption(formData: T | undefined, options: S[], discriminatorField?: string): number {\n return getFirstMatchingOption<T, S, F>(this.validator, formData, options, this.rootSchema, discriminatorField);\n }\n\n /** Helper that acts like lodash's `get` but additionally retrieves `$ref`s as needed to get the path for schemas\n * containing potentially nested `$ref`s.\n *\n * @param schema - The current node within the JSON schema recursion\n * @param path - The remaining keys in the path to the desired property\n * @param defaultValue - The value to return if a value is not found for the `pathList` path\n * @returns - The internal schema from the `schema` for the given `path` or the `defaultValue` if not found\n */\n getFromSchema(schema: S, path: SchemaFieldPath, defaultValue: T): T;\n getFromSchema(schema: S, path: SchemaFieldPath, defaultValue: S): S;\n getFromSchema(schema: S, path: SchemaFieldPath, defaultValue: T | S): T | S {\n return getFromSchema<T, S, F>(\n this.validator,\n this.rootSchema,\n schema,\n path,\n // @ts-expect-error TS2769: No overload matches this call\n defaultValue,\n this.experimental_customMergeAllOf,\n );\n }\n\n /** Checks to see if the `schema` and `uiSchema` combination represents an array of files\n *\n * @param schema - The schema for which check for array of files flag is desired\n * @param [uiSchema] - The UI schema from which to check the widget\n * @returns - True if schema/uiSchema contains an array of files, otherwise false\n */\n isFilesArray(schema: S, uiSchema?: UiSchema<T, S, F>) {\n return isFilesArray<T, S, F>(this.validator, schema, uiSchema, this.rootSchema, this.experimental_customMergeAllOf);\n }\n\n /** Checks to see if the `schema` combination represents a multi-select\n *\n * @param schema - The schema for which check for a multi-select flag is desired\n * @returns - True if schema contains a multi-select, otherwise false\n */\n isMultiSelect(schema: S) {\n return isMultiSelect<T, S, F>(this.validator, schema, this.rootSchema, this.experimental_customMergeAllOf);\n }\n\n /** Checks to see if the `schema` combination represents a select\n *\n * @param schema - The schema for which check for a select flag is desired\n * @returns - True if schema contains a select, otherwise false\n */\n isSelect(schema: S) {\n return isSelect<T, S, F>(this.validator, schema, this.rootSchema, this.experimental_customMergeAllOf);\n }\n /**\n * The function takes a `schema` and `formData` and returns a copy of the formData with any fields not defined in the schema removed.\n * This is useful for ensuring that only data that is relevant to the schema is preserved. Objects with `additionalProperties`\n * keyword set to `true` will not have their extra fields removed.\n *\n * @param schema - The schema to use for filtering the `formData`\n * @param [formData] - The formData to filter\n * @returns The new form data, with any fields not defined in the schema removed\n */\n omitExtraData(schema: S, formData?: T): T | undefined {\n return omitExtraData<T, S, F>(this.validator, schema, this.rootSchema, formData);\n }\n\n /** Retrieves an expanded schema that has had all of its conditions, additional properties, references and\n * dependencies resolved and merged into the `schema` given a `rawFormData` that is used to do the potentially\n * recursive resolution.\n *\n * @param schema - The schema for which retrieving a schema is desired\n * @param [rawFormData] - The current formData, if any, to assist retrieving a schema\n * @param [resolveAnyOfOrOneOfRefs] - Optional flag indicating whether to resolved refs in anyOf/oneOf lists\n * @returns - The schema having its conditions, additional properties, references and dependencies resolved\n */\n retrieveSchema(schema: S, rawFormData?: T, resolveAnyOfOrOneOfRefs?: boolean) {\n return retrieveSchema<T, S, F>(\n this.validator,\n schema,\n this.rootSchema,\n rawFormData,\n this.experimental_customMergeAllOf,\n resolveAnyOfOrOneOfRefs,\n );\n }\n\n /** Sanitize the `data` associated with the `oldSchema` so it is considered appropriate for the `newSchema`. If the\n * new schema does not contain any properties, then `undefined` is returned to clear all the form data. Due to the\n * nature of schemas, this sanitization happens recursively for nested objects of data. Also, any properties in the\n * old schemas that are non-existent in the new schema are set to `undefined`.\n *\n * @param [newSchema] - The new schema for which the data is being sanitized\n * @param [oldSchema] - The old schema from which the data originated\n * @param [data={}] - The form data associated with the schema, defaulting to an empty object when undefined\n * @returns - The new form data, with all the fields uniquely associated with the old schema set\n * to `undefined`. Will return `undefined` if the new schema is not an object containing properties.\n */\n sanitizeDataForNewSchema(newSchema?: S, oldSchema?: S, data?: any): T {\n return sanitizeDataForNewSchema(\n this.validator,\n this.rootSchema,\n newSchema,\n oldSchema,\n data,\n this.experimental_customMergeAllOf,\n );\n }\n\n /** Generates an `PathSchema` object for the `schema`, recursively\n *\n * @param schema - The schema for which the display label flag is desired\n * @param [name] - The base name for the schema\n * @param [formData] - The current formData, if any, onto which to provide any missing defaults\n * @returns - The `PathSchema` object for the `schema`\n */\n // oxlint-disable-next-line typescript/no-deprecated\n toPathSchema(schema: S, name?: string, formData?: T): PathSchema<T> {\n // oxlint-disable-next-line typescript/no-deprecated\n return toPathSchema<T, S, F>(\n this.validator,\n schema,\n name,\n this.rootSchema,\n formData,\n this.experimental_customMergeAllOf,\n );\n }\n}\n\n/** Creates a `SchemaUtilsType` interface that is based around the given `validator` and `rootSchema` parameters. The\n * resulting interface implementation will forward the `validator` and `rootSchema` to all the wrapped APIs.\n *\n * @param validator - an implementation of the `ValidatorType` interface that will be forwarded to all the APIs\n * @param rootSchema - The root schema that will be forwarded to all the APIs\n * @param [experimental_defaultFormStateBehavior] Optional configuration object, if provided, allows users to override default form state behavior\n * @param [experimental_customMergeAllOf] - Optional function that allows for custom merging of `allOf` schemas\n * @returns - An implementation of a `SchemaUtilsType` interface\n */\nexport default function createSchemaUtils<\n T = any,\n S extends StrictRJSFSchema = RJSFSchema,\n F extends FormContextType = any,\n>(\n validator: ValidatorType<T, S, F>,\n rootSchema: S,\n experimental_defaultFormStateBehavior = {},\n experimental_customMergeAllOf?: Experimental_CustomMergeAllOf<S>,\n): SchemaUtilsType<T, S, F> {\n return new SchemaUtils<T, S, F>(\n validator,\n rootSchema,\n experimental_defaultFormStateBehavior,\n experimental_customMergeAllOf,\n );\n}\n", "import { createCustomEqual } from 'fast-equals';\n\n/** Implements a deep equals using `fast-equals.createCustomEqual`. Functions\n * are always considered equal, and circular references are tracked to avoid\n * infinite recursion on self-referential inputs.\n *\n * @param a - The first element to compare\n * @param b - The second element to compare\n * @returns - True if the `a` and `b` are deeply equal, false otherwise\n */\nconst deepEquals = createCustomEqual({\n circular: true,\n createCustomConfig: () => ({\n areFunctionsEqual(_a, b) {\n return typeof b === 'function';\n },\n }),\n});\n\nexport default deepEquals;\n", "import UriResolver from 'fast-uri';\nimport jsonpointer from 'jsonpointer';\nimport get from 'lodash/get';\nimport isEmpty from 'lodash/isEmpty';\nimport isObject from 'lodash/isObject';\nimport omit from 'lodash/omit';\n\nimport {\n ALL_OF_KEY,\n ID_KEY,\n JSON_SCHEMA_DRAFT_2019_09,\n JSON_SCHEMA_DRAFT_2020_12,\n REF_KEY,\n SCHEMA_KEY,\n} from './constants';\nimport type { GenericObjectType, RJSFSchema, StrictRJSFSchema } from './types';\n\n/** Looks for the `$id` pointed by `ref` in the schema definitions embedded in\n * a JSON Schema bundle\n *\n * @param schema - The schema wherein `ref` should be searched\n * @param ref - The `$id` of the reference to search for\n * @returns - The schema matching the reference, or `undefined` if no match is found\n */\nfunction findEmbeddedSchemaRecursive<S extends StrictRJSFSchema = RJSFSchema>(schema: S, ref: string): S | undefined {\n if (ID_KEY in schema && UriResolver.equal(schema[ID_KEY] as string, ref)) {\n return schema;\n }\n for (const subSchema of Object.values(schema)) {\n if (Array.isArray(subSchema)) {\n for (const item of subSchema) {\n if (isObject(item)) {\n const result = findEmbeddedSchemaRecursive<S>(item as S, ref);\n if (result !== undefined) {\n return result;\n }\n }\n }\n } else if (isObject(subSchema)) {\n const result = findEmbeddedSchemaRecursive<S>(subSchema as S, ref);\n if (result !== undefined) {\n return result;\n }\n }\n }\n return undefined;\n}\n\n/** Parses a JSONSchema and makes all references absolute with respect to\n * the `baseURI` argument\n * @param schema - The schema to be processed\n * @param baseURI - The base URI to be used for resolving relative references\n */\nexport function makeAllReferencesAbsolute<S extends StrictRJSFSchema = RJSFSchema>(schema: S, baseURI: string): S {\n const currentURI = get(schema, ID_KEY, baseURI);\n let result = schema;\n // Make all other references absolute\n if (REF_KEY in result) {\n result = { ...result, [REF_KEY]: UriResolver.resolve(currentURI, result[REF_KEY]!) };\n }\n // Look for references in nested subschemas\n for (const [key, subSchema] of Object.entries(result)) {\n if (Array.isArray(subSchema)) {\n result = {\n ...result,\n [key]: subSchema.map((item) => (isObject(item) ? makeAllReferencesAbsolute(item as S, currentURI) : item)),\n };\n } else if (isObject(subSchema)) {\n result = { ...result, [key]: makeAllReferencesAbsolute(subSchema as S, currentURI) };\n }\n }\n return result;\n}\n\n/** Splits out the value at the `key` in `object` from the `object`, returning an array that contains in the first\n * location, the `object` minus the `key: value` and in the second location the `value`.\n *\n * @param key - The key from the object to extract\n * @param object - The object from which to extract the element\n * @returns - An array with the first value being the object minus the `key` element and the second element being the\n * value from `object[key]`\n */\nexport function splitKeyElementFromObject(key: string, object: GenericObjectType) {\n const value = object[key];\n const remaining = omit(object, [key]);\n return [remaining, value];\n}\n\n/** Given the name of a `$ref` from within a schema, using the `rootSchema`, recursively look up and return the\n * sub-schema using the path provided by that reference. If `#` is not the first character of the reference, the path\n * does not exist in the schema, or the reference resolves circularly back to itself, then throw an Error.\n * Otherwise return the sub-schema. Also deals with nested `$ref`s in the sub-schema.\n *\n * @param $ref - The ref string for which the schema definition is desired\n * @param [rootSchema={}] - The root schema in which to search for the definition\n * @param recurseList - List of $refs already resolved to prevent recursion\n * @param [baseURI=rootSchema['$id']] - The base URI to be used for resolving relative references\n * @returns - The sub-schema within the `rootSchema` which matches the `$ref` if it exists\n * @throws - Error indicating that no schema for that reference could be resolved\n */\nexport function findSchemaDefinitionRecursive<S extends StrictRJSFSchema = RJSFSchema>(\n $ref?: string,\n rootSchema: S = {} as S,\n recurseList: string[] = [],\n baseURI: string | undefined = get(rootSchema, [ID_KEY]),\n): S {\n const ref = $ref || '';\n let current: S | undefined = undefined;\n let currentBaseURI = baseURI;\n if (ref.startsWith('#')) {\n // Decode URI fragment representation.\n const decodedRef = decodeURIComponent(ref.substring(1));\n if (currentBaseURI === undefined || (ID_KEY in rootSchema && rootSchema[ID_KEY] === currentBaseURI)) {\n current = jsonpointer.get(rootSchema, decodedRef);\n } else if (rootSchema[SCHEMA_KEY] === JSON_SCHEMA_DRAFT_2020_12) {\n current = findEmbeddedSchemaRecursive<S>(rootSchema, currentBaseURI.replace(/\\/$/, ''));\n if (current !== undefined) {\n current = jsonpointer.get(current, decodedRef);\n }\n }\n } else if (rootSchema[SCHEMA_KEY] === JSON_SCHEMA_DRAFT_2020_12) {\n const resolvedRef = currentBaseURI ? UriResolver.resolve(currentBaseURI, ref) : ref;\n const [refId, ...refAnchor] = resolvedRef.replace(/#\\/?$/, '').split('#');\n current = findEmbeddedSchemaRecursive<S>(rootSchema, refId.replace(/\\/$/, ''));\n if (current !== undefined) {\n currentBaseURI = current[ID_KEY];\n if (!isEmpty(refAnchor)) {\n current = jsonpointer.get(current, decodeURIComponent(refAnchor.join('#')));\n }\n }\n }\n if (current === undefined) {\n throw new Error(`Could not find a definition for ${$ref}.`);\n }\n const nextRef = current[REF_KEY];\n if (nextRef) {\n // Check for circular references.\n if (recurseList.includes(nextRef)) {\n if (recurseList.length === 1) {\n throw new Error(`Definition for ${$ref} is a circular reference`);\n }\n const [firstRef, ...restRefs] = recurseList;\n const circularPath = [...restRefs, ref, firstRef].join(' -> ');\n throw new Error(`Definition for ${firstRef} contains a circular reference through ${circularPath}`);\n }\n const [remaining, theRef] = splitKeyElementFromObject(REF_KEY, current);\n const subSchema = findSchemaDefinitionRecursive<S>(theRef, rootSchema, [...recurseList, ref], currentBaseURI);\n if (Object.keys(remaining).length > 0) {\n if (\n rootSchema[SCHEMA_KEY] === JSON_SCHEMA_DRAFT_2019_09 ||\n rootSchema[SCHEMA_KEY] === JSON_SCHEMA_DRAFT_2020_12\n ) {\n return { [ALL_OF_KEY]: [remaining, subSchema] } as S;\n }\n return { ...remaining, ...subSchema };\n }\n return subSchema;\n }\n return current;\n}\n\n/** Given the name of a `$ref` from within a schema, using the `rootSchema`, look up and return the sub-schema using the\n * path provided by that reference. If `#` is not the first character of the reference, the path does not exist in\n * the schema, or the reference resolves circularly back to itself, then throw an Error. Otherwise return the\n * sub-schema. Also deals with nested `$ref`s in the sub-schema.\n *\n * @param $ref - The ref string for which the schema definition is desired\n * @param [rootSchema={}] - The root schema in which to search for the definition\n * @param [baseURI=rootSchema['$id']] - The base URI to be used for resolving relative references\n * @returns - The sub-schema within the `rootSchema` which matches the `$ref` if it exists\n * @throws - Error indicating that no schema for that reference could be resolved\n */\nexport default function findSchemaDefinition<S extends StrictRJSFSchema = RJSFSchema>(\n $ref?: string,\n rootSchema: S = {} as S,\n baseURI: string | undefined = get(rootSchema, [ID_KEY]),\n): S {\n const recurseList: string[] = [];\n return findSchemaDefinitionRecursive($ref, rootSchema, recurseList, baseURI);\n}\n", "import get from 'lodash/get';\nimport has from 'lodash/has';\n\nimport { ANY_OF_KEY, ONE_OF_KEY, PROPERTIES_KEY, REQUIRED_KEY } from '../constants';\nimport type {\n Experimental_CustomMergeAllOf,\n FormContextType,\n FoundFieldType,\n RJSFSchema,\n SchemaFieldPath,\n StrictRJSFSchema,\n ValidatorType,\n} from '../types';\nimport findSelectedOptionInXxxOf from './findSelectedOptionInXxxOf';\nimport getFromSchema from './getFromSchema';\n\n/** Unique schema that represents no schema was found, exported for testing purposes */\nexport const NOT_FOUND_SCHEMA = { title: '!@#$_UNKNOWN_$#@!' };\n\n/** Finds the field specified by the `path` within the root or recursed `schema`. If there is no field for the specified\n * `path`, then the default `{ field: undefined, isRequired: undefined }` is returned. It determines whether a leaf\n * field is in the `required` list for its parent and if so, it is marked as required on return.\n *\n * @param validator - An implementation of the `ValidatorType` interface that will be forwarded to all the APIs\n * @param rootSchema - The root schema that will be forwarded to all the APIs\n * @param schema - The node within the JSON schema in which to search\n * @param path - The keys in the path to the desired field\n * @param [formData={}] - The form data that is used to determine which anyOf/oneOf option to descend\n * @param [experimental_customMergeAllOf] - Optional function that allows for custom merging of `allOf` schemas\n * @returns - An object that contains the field and its required state. If no field can be found then\n * `{ field: undefined, isRequired: undefined }` is returned.\n */\nexport default function findFieldInSchema<\n T = undefined,\n S extends StrictRJSFSchema = RJSFSchema,\n F extends FormContextType = any,\n>(\n validator: ValidatorType<T, S, F>,\n rootSchema: S,\n schema: S,\n path: SchemaFieldPath,\n formData: T = {} as T,\n experimental_customMergeAllOf?: Experimental_CustomMergeAllOf<S>,\n): FoundFieldType<S> {\n const pathList = Array.isArray(path) ? [...path] : path.split('.');\n let parentField = schema;\n\n // store the desired field into a variable and removing it from the `pathList`\n const fieldName = pathList.pop()!;\n const fieldNameKey = String(fieldName);\n\n if (pathList.length) {\n // drilling into the schema for each sub-path and taking into account of the any/oneOfs\n pathList.forEach((subPath) => {\n parentField = getFromSche