@rjsf/utils 5.0.0-beta.16 → 5.0.0-beta.18

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.
@@ -7,6 +7,11 @@ var get = require('lodash/get');
7
7
  var isEmpty = require('lodash/isEmpty');
8
8
  var jsonpointer = require('jsonpointer');
9
9
  var omit = require('lodash/omit');
10
+ var has = require('lodash/has');
11
+ var isObject$1 = require('lodash/isObject');
12
+ var isString = require('lodash/isString');
13
+ var reduce = require('lodash/reduce');
14
+ var times = require('lodash/times');
10
15
  var set = require('lodash/set');
11
16
  var mergeAllOf = require('json-schema-merge-allof');
12
17
  var union = require('lodash/union');
@@ -21,6 +26,11 @@ var get__default = /*#__PURE__*/_interopDefaultLegacy(get);
21
26
  var isEmpty__default = /*#__PURE__*/_interopDefaultLegacy(isEmpty);
22
27
  var jsonpointer__default = /*#__PURE__*/_interopDefaultLegacy(jsonpointer);
23
28
  var omit__default = /*#__PURE__*/_interopDefaultLegacy(omit);
29
+ var has__default = /*#__PURE__*/_interopDefaultLegacy(has);
30
+ var isObject__default = /*#__PURE__*/_interopDefaultLegacy(isObject$1);
31
+ var isString__default = /*#__PURE__*/_interopDefaultLegacy(isString);
32
+ var reduce__default = /*#__PURE__*/_interopDefaultLegacy(reduce);
33
+ var times__default = /*#__PURE__*/_interopDefaultLegacy(times);
24
34
  var set__default = /*#__PURE__*/_interopDefaultLegacy(set);
25
35
  var mergeAllOf__default = /*#__PURE__*/_interopDefaultLegacy(mergeAllOf);
26
36
  var union__default = /*#__PURE__*/_interopDefaultLegacy(union);
@@ -99,7 +109,7 @@ function _defineProperties(target, props) {
99
109
  descriptor.enumerable = descriptor.enumerable || false;
100
110
  descriptor.configurable = true;
101
111
  if ("value" in descriptor) descriptor.writable = true;
102
- Object.defineProperty(target, descriptor.key, descriptor);
112
+ Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor);
103
113
  }
104
114
  }
105
115
  function _createClass(Constructor, protoProps, staticProps) {
@@ -139,6 +149,20 @@ function _objectWithoutPropertiesLoose(source, excluded) {
139
149
  }
140
150
  return target;
141
151
  }
152
+ function _toPrimitive(input, hint) {
153
+ if (typeof input !== "object" || input === null) return input;
154
+ var prim = input[Symbol.toPrimitive];
155
+ if (prim !== undefined) {
156
+ var res = prim.call(input, hint || "default");
157
+ if (typeof res !== "object") return res;
158
+ throw new TypeError("@@toPrimitive must return a primitive value.");
159
+ }
160
+ return (hint === "string" ? String : Number)(input);
161
+ }
162
+ function _toPropertyKey(arg) {
163
+ var key = _toPrimitive(arg, "string");
164
+ return typeof key === "symbol" ? key : String(key);
165
+ }
142
166
 
143
167
  /** Below are the list of all the keys into various elements of a RJSFSchema or UiSchema that are used by the various
144
168
  * utility functions. In addition to those keys, there are the special `ADDITIONAL_PROPERTY_FLAG` and
@@ -293,12 +317,14 @@ function findSchemaDefinition($ref, rootSchema) {
293
317
  }
294
318
 
295
319
  /** Given the `formData` and list of `options`, attempts to find the index of the option that best matches the data.
320
+ * Deprecated, use `getFirstMatchingOption()` instead.
296
321
  *
297
322
  * @param validator - An implementation of the `ValidatorType` interface that will be used when necessary
298
323
  * @param formData - The current formData, if any, used to figure out a match
299
324
  * @param options - The list of options to find a matching options from
300
325
  * @param rootSchema - The root schema, used to primarily to look up `$ref`s
301
326
  * @returns - The index of the matched option or 0 if none is available
327
+ * @deprecated
302
328
  */
303
329
  function getMatchingOption(validator, formData, options, rootSchema) {
304
330
  // For performance, skip validating subschemas if formData is undefined. We just
@@ -354,6 +380,19 @@ function getMatchingOption(validator, formData, options, rootSchema) {
354
380
  return 0;
355
381
  }
356
382
 
383
+ /** Given the `formData` and list of `options`, attempts to find the index of the first option that matches the data.
384
+ * Always returns the first option if there is nothing that matches.
385
+ *
386
+ * @param validator - An implementation of the `ValidatorType` interface that will be used when necessary
387
+ * @param formData - The current formData, if any, used to figure out a match
388
+ * @param options - The list of options to find a matching options from
389
+ * @param rootSchema - The root schema, used to primarily to look up `$ref`s
390
+ * @returns - The index of the first matched option or 0 if none is available
391
+ */
392
+ function getFirstMatchingOption(validator, formData, options, rootSchema) {
393
+ return getMatchingOption(validator, formData, options, rootSchema);
394
+ }
395
+
357
396
  /** Given a specific `value` attempts to guess the type of a schema element. In the case where we have to implicitly
358
397
  * create a schema, it is useful to know what type to use based on the data we are defining.
359
398
  *
@@ -405,6 +444,12 @@ function getSchemaType(schema) {
405
444
  if (!type && (schema.properties || schema.additionalProperties)) {
406
445
  return "object";
407
446
  }
447
+ if (!type && Array.isArray(schema.oneOf) && schema.oneOf.length) {
448
+ return getSchemaType(schema.oneOf[0]);
449
+ }
450
+ if (!type && Array.isArray(schema.anyOf) && schema.anyOf.length) {
451
+ return getSchemaType(schema.anyOf[0]);
452
+ }
408
453
  if (Array.isArray(type) && type.length === 2 && type.includes("null")) {
409
454
  type = type.find(function (type) {
410
455
  return type !== "null";
@@ -413,99 +458,6 @@ function getSchemaType(schema) {
413
458
  return type;
414
459
  }
415
460
 
416
- /** Detects whether the given `schema` contains fixed items. This is the case when `schema.items` is a non-empty array
417
- * that only contains objects.
418
- *
419
- * @param schema - The schema in which to check for fixed items
420
- * @returns - True if there are fixed items in the schema, false otherwise
421
- */
422
- function isFixedItems(schema) {
423
- return Array.isArray(schema.items) && schema.items.length > 0 && schema.items.every(function (item) {
424
- return isObject(item);
425
- });
426
- }
427
-
428
- /** Merges the `defaults` object of type `T` into the `formData` of type `T`
429
- *
430
- * When merging defaults and form data, we want to merge in this specific way:
431
- * - objects are deeply merged
432
- * - arrays are merged in such a way that:
433
- * - when the array is set in form data, only array entries set in form data
434
- * are deeply merged; additional entries from the defaults are ignored
435
- * - when the array is not set in form data, the default is copied over
436
- * - scalars are overwritten/set by form data
437
- *
438
- * @param defaults - The defaults to merge
439
- * @param formData - The form data into which the defaults will be merged
440
- * @returns - The resulting merged form data with defaults
441
- */
442
- function mergeDefaultsWithFormData(defaults, formData) {
443
- if (Array.isArray(formData)) {
444
- var defaultsArray = Array.isArray(defaults) ? defaults : [];
445
- var mapped = formData.map(function (value, idx) {
446
- if (defaultsArray[idx]) {
447
- return mergeDefaultsWithFormData(defaultsArray[idx], value);
448
- }
449
- return value;
450
- });
451
- return mapped;
452
- }
453
- if (isObject(formData)) {
454
- var acc = Object.assign({}, defaults); // Prevent mutation of source object.
455
- return Object.keys(formData).reduce(function (acc, key) {
456
- acc[key] = mergeDefaultsWithFormData(defaults ? get__default["default"](defaults, key) : {}, get__default["default"](formData, key));
457
- return acc;
458
- }, acc);
459
- }
460
- return formData;
461
- }
462
-
463
- /** Recursively merge deeply nested objects.
464
- *
465
- * @param obj1 - The first object to merge
466
- * @param obj2 - The second object to merge
467
- * @param [concatArrays=false] - Optional flag that, when true, will cause arrays to be concatenated. Use
468
- * "preventDuplicates" to merge arrays in a manner that prevents any duplicate entries from being merged.
469
- * NOTE: Uses shallow comparison for the duplicate checking.
470
- * @returns - A new object that is the merge of the two given objects
471
- */
472
- function mergeObjects(obj1, obj2, concatArrays) {
473
- if (concatArrays === void 0) {
474
- concatArrays = false;
475
- }
476
- return Object.keys(obj2).reduce(function (acc, key) {
477
- var left = obj1 ? obj1[key] : {},
478
- right = obj2[key];
479
- if (obj1 && key in obj1 && isObject(right)) {
480
- acc[key] = mergeObjects(left, right, concatArrays);
481
- } else if (concatArrays && Array.isArray(left) && Array.isArray(right)) {
482
- var toMerge = right;
483
- if (concatArrays === "preventDuplicates") {
484
- toMerge = right.reduce(function (result, value) {
485
- if (!left.includes(value)) {
486
- result.push(value);
487
- }
488
- return result;
489
- }, []);
490
- }
491
- acc[key] = left.concat(toMerge);
492
- } else {
493
- acc[key] = right;
494
- }
495
- return acc;
496
- }, Object.assign({}, obj1)); // Prevent mutation of source object.
497
- }
498
-
499
- /** This function checks if the given `schema` matches a single constant value. This happens when either the schema has
500
- * an `enum` array with a single value or there is a `const` defined.
501
- *
502
- * @param schema - The schema for a field
503
- * @returns - True if the `schema` has a single constant value, false otherwise
504
- */
505
- function isConstant(schema) {
506
- return Array.isArray(schema["enum"]) && schema["enum"].length === 1 || CONST_KEY in schema;
507
- }
508
-
509
461
  /** Recursively merge deeply nested schemas. The difference between `mergeSchemas` and `mergeObjects` is that
510
462
  * `mergeSchemas` only concats arrays for values under the 'required' keyword, and when it does, it doesn't include
511
463
  * duplicate values.
@@ -542,7 +494,7 @@ var _excluded$1 = ["if", "then", "else"],
542
494
  * @param validator - An implementation of the `ValidatorType<T, S>` interface that is used to detect valid schema conditions
543
495
  * @param schema - The schema for which resolving a condition is desired
544
496
  * @param rootSchema - The root schema that will be forwarded to all the APIs
545
- * @param formData - The current formData to assist retrieving a schema
497
+ * @param [formData] - The current formData to assist retrieving a schema
546
498
  * @returns - A schema with the appropriate condition resolved
547
499
  */
548
500
  function resolveCondition(validator, schema, rootSchema, formData) {
@@ -630,6 +582,10 @@ function stubExistingAdditionalProperties(validator, theSchema, rootSchema, aFor
630
582
  }, rootSchema, formData);
631
583
  } else if ("type" in schema.additionalProperties) {
632
584
  additionalProperties = _extends({}, schema.additionalProperties);
585
+ } else if (ANY_OF_KEY in schema.additionalProperties || ONE_OF_KEY in schema.additionalProperties) {
586
+ additionalProperties = _extends({
587
+ type: "object"
588
+ }, schema.additionalProperties);
633
589
  } else {
634
590
  additionalProperties = {
635
591
  type: guessType(get__default["default"](formData, [key]))
@@ -701,9 +657,9 @@ function resolveDependencies(validator, schema, rootSchema, formData) {
701
657
  remainingSchema = _objectWithoutPropertiesLoose(schema, _excluded4);
702
658
  var resolvedSchema = remainingSchema;
703
659
  if (Array.isArray(resolvedSchema.oneOf)) {
704
- resolvedSchema = resolvedSchema.oneOf[getMatchingOption(validator, formData, resolvedSchema.oneOf, rootSchema)];
660
+ resolvedSchema = resolvedSchema.oneOf[getFirstMatchingOption(validator, formData, resolvedSchema.oneOf, rootSchema)];
705
661
  } else if (Array.isArray(resolvedSchema.anyOf)) {
706
- resolvedSchema = resolvedSchema.anyOf[getMatchingOption(validator, formData, resolvedSchema.anyOf, rootSchema)];
662
+ resolvedSchema = resolvedSchema.anyOf[getFirstMatchingOption(validator, formData, resolvedSchema.anyOf, rootSchema)];
707
663
  }
708
664
  return processDependencies(validator, dependencies, resolvedSchema, rootSchema, formData);
709
665
  }
@@ -824,6 +780,242 @@ function withExactlyOneSubschema(validator, schema, rootSchema, dependencyKey, o
824
780
  return mergeSchemas(schema, retrieveSchema(validator, dependentSchema, rootSchema, formData));
825
781
  }
826
782
 
783
+ /** A junk option used to determine when the getFirstMatchingOption call really matches an option rather than returning
784
+ * the first item
785
+ */
786
+ var JUNK_OPTION = {
787
+ type: "object",
788
+ properties: {
789
+ __not_really_there__: {
790
+ type: "number"
791
+ }
792
+ }
793
+ };
794
+ /** Recursive function that calculates the score of a `formData` against the given `schema`. The computation is fairly
795
+ * simple. Initially the total score is 0. When `schema.properties` object exists, then all the `key/value` pairs within
796
+ * the object are processed as follows after obtaining the formValue from `formData` using the `key`:
797
+ * - If the `value` contains a `$ref`, `calculateIndexScore()` is called recursively with the formValue and the new
798
+ * schema that is the result of the ref in the schema being resolved and that sub-schema's resulting score is added to
799
+ * the total.
800
+ * - If the `value` contains a `oneOf` and there is a formValue, then score based on the index returned from calling
801
+ * `getClosestMatchingOption()` of that oneOf.
802
+ * - If the type of the `value` is 'object', `calculateIndexScore()` is called recursively with the formValue and the
803
+ * `value` itself as the sub-schema, and the score is added to the total.
804
+ * - If the type of the `value` matches the guessed-type of the `formValue`, the score is incremented by 1, UNLESS the
805
+ * value has a `default` or `const`. In those case, if the `default` or `const` and the `formValue` match, the score
806
+ * is incremented by another 1 otherwise it is decremented by 1.
807
+ *
808
+ * @param validator - An implementation of the `ValidatorType` interface that will be used when necessary
809
+ * @param rootSchema - The root JSON schema of the entire form
810
+ * @param schema - The schema for which the score is being calculated
811
+ * @param formData - The form data associated with the schema, used to calculate the score
812
+ * @returns - The score a schema against the formData
813
+ */
814
+ function calculateIndexScore(validator, rootSchema, schema, formData) {
815
+ if (formData === void 0) {
816
+ formData = {};
817
+ }
818
+ var totalScore = 0;
819
+ if (schema) {
820
+ if (isObject__default["default"](schema.properties)) {
821
+ totalScore += reduce__default["default"](schema.properties, function (score, value, key) {
822
+ var formValue = get__default["default"](formData, key);
823
+ if (typeof value === "boolean") {
824
+ return score;
825
+ }
826
+ if (has__default["default"](value, REF_KEY)) {
827
+ var newSchema = retrieveSchema(validator, value, rootSchema, formValue);
828
+ return score + calculateIndexScore(validator, rootSchema, newSchema, formValue || {});
829
+ }
830
+ if (has__default["default"](value, ONE_OF_KEY) && formValue) {
831
+ return score + getClosestMatchingOption(validator, rootSchema, formValue, get__default["default"](value, ONE_OF_KEY));
832
+ }
833
+ if (value.type === "object") {
834
+ return score + calculateIndexScore(validator, rootSchema, value, formValue || {});
835
+ }
836
+ if (value.type === guessType(formValue)) {
837
+ // If the types match, then we bump the score by one
838
+ var newScore = score + 1;
839
+ if (value["default"]) {
840
+ // If the schema contains a readonly default value score the value that matches the default higher and
841
+ // any non-matching value lower
842
+ newScore += formValue === value["default"] ? 1 : -1;
843
+ } else if (value["const"]) {
844
+ // If the schema contains a const value score the value that matches the default higher and
845
+ // any non-matching value lower
846
+ newScore += formValue === value["const"] ? 1 : -1;
847
+ }
848
+ // TODO eventually, deal with enums/arrays
849
+ return newScore;
850
+ }
851
+ return score;
852
+ }, 0);
853
+ } else if (isString__default["default"](schema.type) && schema.type === guessType(formData)) {
854
+ totalScore += 1;
855
+ }
856
+ }
857
+ return totalScore;
858
+ }
859
+ /** Determines which of the given `options` provided most closely matches the `formData`. Using
860
+ * `getFirstMatchingOption()` to match two schemas that differ only by the readOnly, default or const value of a field
861
+ * based on the `formData` and returns 0 when there is no match. Rather than passing in all the `options` at once to
862
+ * this utility, instead an array of valid option indexes is created by iterating over the list of options, call
863
+ * `getFirstMatchingOptions` with a list of one junk option and one good option, seeing if the good option is considered
864
+ * matched.
865
+ *
866
+ * Once the list of valid indexes is created, if there is only one valid index, just return it. Otherwise, if there are
867
+ * no valid indexes, then fill the valid indexes array with the indexes of all the options. Next, the index of the
868
+ * option with the highest score is determined by iterating over the list of valid options, calling
869
+ * `calculateIndexScore()` on each, comparing it against the current best score, and returning the index of the one that
870
+ * eventually has the best score.
871
+ *
872
+ * @param validator - An implementation of the `ValidatorType` interface that will be used when necessary
873
+ * @param rootSchema - The root JSON schema of the entire form
874
+ * @param formData - The form data associated with the schema
875
+ * @param options - The list of options that can be selected from
876
+ * @param [selectedOption=-1] - The index of the currently selected option, defaulted to -1 if not specified
877
+ * @returns - The index of the option that is the closest match to the `formData` or the `selectedOption` if no match
878
+ */
879
+ function getClosestMatchingOption(validator, rootSchema, formData, options, selectedOption) {
880
+ if (selectedOption === void 0) {
881
+ selectedOption = -1;
882
+ }
883
+ // Reduce the array of options down to a list of the indexes that are considered matching options
884
+ var allValidIndexes = options.reduce(function (validList, option, index) {
885
+ var testOptions = [JUNK_OPTION, option];
886
+ var match = getFirstMatchingOption(validator, formData, testOptions, rootSchema);
887
+ // The match is the real option, so add its index to list of valid indexes
888
+ if (match === 1) {
889
+ validList.push(index);
890
+ }
891
+ return validList;
892
+ }, []);
893
+ // There is only one valid index, so return it!
894
+ if (allValidIndexes.length === 1) {
895
+ return allValidIndexes[0];
896
+ }
897
+ if (!allValidIndexes.length) {
898
+ // No indexes were valid, so we'll score all the options, add all the indexes
899
+ times__default["default"](options.length, function (i) {
900
+ return allValidIndexes.push(i);
901
+ });
902
+ }
903
+ // Score all the options in the list of valid indexes and return the index with the best score
904
+ var _allValidIndexes$redu = allValidIndexes.reduce(function (scoreData, index) {
905
+ var bestScore = scoreData.bestScore;
906
+ var option = options[index];
907
+ if (has__default["default"](option, REF_KEY)) {
908
+ option = retrieveSchema(validator, option, rootSchema, formData);
909
+ }
910
+ var score = calculateIndexScore(validator, rootSchema, option, formData);
911
+ if (score > bestScore) {
912
+ return {
913
+ bestIndex: index,
914
+ bestScore: score
915
+ };
916
+ }
917
+ return scoreData;
918
+ }, {
919
+ bestIndex: selectedOption,
920
+ bestScore: 0
921
+ }),
922
+ bestIndex = _allValidIndexes$redu.bestIndex;
923
+ return bestIndex;
924
+ }
925
+
926
+ /** Detects whether the given `schema` contains fixed items. This is the case when `schema.items` is a non-empty array
927
+ * that only contains objects.
928
+ *
929
+ * @param schema - The schema in which to check for fixed items
930
+ * @returns - True if there are fixed items in the schema, false otherwise
931
+ */
932
+ function isFixedItems(schema) {
933
+ return Array.isArray(schema.items) && schema.items.length > 0 && schema.items.every(function (item) {
934
+ return isObject(item);
935
+ });
936
+ }
937
+
938
+ /** Merges the `defaults` object of type `T` into the `formData` of type `T`
939
+ *
940
+ * When merging defaults and form data, we want to merge in this specific way:
941
+ * - objects are deeply merged
942
+ * - arrays are merged in such a way that:
943
+ * - when the array is set in form data, only array entries set in form data
944
+ * are deeply merged; additional entries from the defaults are ignored
945
+ * - when the array is not set in form data, the default is copied over
946
+ * - scalars are overwritten/set by form data
947
+ *
948
+ * @param [defaults] - The defaults to merge
949
+ * @param [formData] - The form data into which the defaults will be merged
950
+ * @returns - The resulting merged form data with defaults
951
+ */
952
+ function mergeDefaultsWithFormData(defaults, formData) {
953
+ if (Array.isArray(formData)) {
954
+ var defaultsArray = Array.isArray(defaults) ? defaults : [];
955
+ var mapped = formData.map(function (value, idx) {
956
+ if (defaultsArray[idx]) {
957
+ return mergeDefaultsWithFormData(defaultsArray[idx], value);
958
+ }
959
+ return value;
960
+ });
961
+ return mapped;
962
+ }
963
+ if (isObject(formData)) {
964
+ var acc = Object.assign({}, defaults); // Prevent mutation of source object.
965
+ return Object.keys(formData).reduce(function (acc, key) {
966
+ acc[key] = mergeDefaultsWithFormData(defaults ? get__default["default"](defaults, key) : {}, get__default["default"](formData, key));
967
+ return acc;
968
+ }, acc);
969
+ }
970
+ return formData;
971
+ }
972
+
973
+ /** Recursively merge deeply nested objects.
974
+ *
975
+ * @param obj1 - The first object to merge
976
+ * @param obj2 - The second object to merge
977
+ * @param [concatArrays=false] - Optional flag that, when true, will cause arrays to be concatenated. Use
978
+ * "preventDuplicates" to merge arrays in a manner that prevents any duplicate entries from being merged.
979
+ * NOTE: Uses shallow comparison for the duplicate checking.
980
+ * @returns - A new object that is the merge of the two given objects
981
+ */
982
+ function mergeObjects(obj1, obj2, concatArrays) {
983
+ if (concatArrays === void 0) {
984
+ concatArrays = false;
985
+ }
986
+ return Object.keys(obj2).reduce(function (acc, key) {
987
+ var left = obj1 ? obj1[key] : {},
988
+ right = obj2[key];
989
+ if (obj1 && key in obj1 && isObject(right)) {
990
+ acc[key] = mergeObjects(left, right, concatArrays);
991
+ } else if (concatArrays && Array.isArray(left) && Array.isArray(right)) {
992
+ var toMerge = right;
993
+ if (concatArrays === "preventDuplicates") {
994
+ toMerge = right.reduce(function (result, value) {
995
+ if (!left.includes(value)) {
996
+ result.push(value);
997
+ }
998
+ return result;
999
+ }, []);
1000
+ }
1001
+ acc[key] = left.concat(toMerge);
1002
+ } else {
1003
+ acc[key] = right;
1004
+ }
1005
+ return acc;
1006
+ }, Object.assign({}, obj1)); // Prevent mutation of source object.
1007
+ }
1008
+
1009
+ /** This function checks if the given `schema` matches a single constant value. This happens when either the schema has
1010
+ * an `enum` array with a single value or there is a `const` defined.
1011
+ *
1012
+ * @param schema - The schema for a field
1013
+ * @returns - True if the `schema` has a single constant value, false otherwise
1014
+ */
1015
+ function isConstant(schema) {
1016
+ return Array.isArray(schema["enum"]) && schema["enum"].length === 1 || CONST_KEY in schema;
1017
+ }
1018
+
827
1019
  /** Checks to see if the `schema` combination represents a select
828
1020
  *
829
1021
  * @param validator - An implementation of the `ValidatorType` interface that will be used when necessary
@@ -949,9 +1141,9 @@ function computeDefaults(validator, rawSchema, parentDefaults, rootSchema, rawFo
949
1141
  return computeDefaults(validator, itemSchema, Array.isArray(parentDefaults) ? parentDefaults[idx] : undefined, rootSchema, formData, includeUndefinedValues);
950
1142
  });
951
1143
  } else if (ONE_OF_KEY in schema) {
952
- schema = schema.oneOf[getMatchingOption(validator, isEmpty__default["default"](formData) ? undefined : formData, schema.oneOf, rootSchema)];
1144
+ schema = schema.oneOf[getClosestMatchingOption(validator, rootSchema, isEmpty__default["default"](formData) ? undefined : formData, schema.oneOf, 0)];
953
1145
  } else if (ANY_OF_KEY in schema) {
954
- schema = schema.anyOf[getMatchingOption(validator, isEmpty__default["default"](formData) ? undefined : formData, schema.anyOf, rootSchema)];
1146
+ schema = schema.anyOf[getClosestMatchingOption(validator, rootSchema, isEmpty__default["default"](formData) ? undefined : formData, schema.anyOf, 0)];
955
1147
  }
956
1148
  // Not defaults defined for this node, fallback to generic typed ones.
957
1149
  if (typeof defaults === "undefined") {
@@ -1143,6 +1335,169 @@ function mergeValidationData(validator, validationData, additionalErrorSchema) {
1143
1335
  };
1144
1336
  }
1145
1337
 
1338
+ var NO_VALUE = /*#__PURE__*/Symbol("no Value");
1339
+ /** Sanitize the `data` associated with the `oldSchema` so it is considered appropriate for the `newSchema`. If the new
1340
+ * schema does not contain any properties, then `undefined` is returned to clear all the form data. Due to the nature
1341
+ * of schemas, this sanitization happens recursively for nested objects of data. Also, any properties in the old schema
1342
+ * that are non-existent in the new schema are set to `undefined`. The data sanitization process has the following flow:
1343
+ *
1344
+ * - If the new schema is an object that contains a `properties` object then:
1345
+ * - Create a `removeOldSchemaData` object, setting each key in the `oldSchema.properties` having `data` to undefined
1346
+ * - Create an empty `nestedData` object for use in the key filtering below:
1347
+ * - Iterate over each key in the `newSchema.properties` as follows:
1348
+ * - Get the `formValue` of the key from the `data`
1349
+ * - Get the `oldKeySchema` and `newKeyedSchema` for the key, defaulting to `{}` when it doesn't exist
1350
+ * - Retrieve the schema for any refs within each `oldKeySchema` and/or `newKeySchema`
1351
+ * - Get the types of the old and new keyed schemas and if the old doesn't exist or the old & new are the same then:
1352
+ * - If `removeOldSchemaData` has an entry for the key, delete it since the new schema has the same property
1353
+ * - If type of the key in the new schema is `object`:
1354
+ * - Store the value from the recursive `sanitizeDataForNewSchema` call in `nestedData[key]`
1355
+ * - Otherwise, check for default or const values:
1356
+ * - Get the old and new `default` values from the schema and check:
1357
+ * - If the new `default` value does not match the form value:
1358
+ * - If the old `default` value DOES match the form value, then:
1359
+ * - Replace `removeOldSchemaData[key]` with the new `default`
1360
+ * - Otherwise, if the new schema is `readOnly` then replace `removeOldSchemaData[key]` with undefined
1361
+ * - Get the old and new `const` values from the schema and check:
1362
+ * - If the new `const` value does not match the form value:
1363
+ * - If the old `const` value DOES match the form value, then:
1364
+ * - Replace `removeOldSchemaData[key]` with the new `const`
1365
+ * - Otherwise, replace `removeOldSchemaData[key]` with undefined
1366
+ * - Once all keys have been processed, return an object built as follows:
1367
+ * - `{ ...removeOldSchemaData, ...nestedData, ...pick(data, keysToKeep) }`
1368
+ * - If the new and old schema types are array and the `data` is an array then:
1369
+ * - If the type of the old and new schema `items` are a non-array objects:
1370
+ * - Retrieve the schema for any refs within each `oldKeySchema.items` and/or `newKeySchema.items`
1371
+ * - If the `type`s of both items are the same (or the old does not have a type):
1372
+ * - If the type is "object", then:
1373
+ * - For each element in the `data` recursively sanitize the data, stopping at `maxItems` if specified
1374
+ * - Otherwise, just return the `data` removing any values after `maxItems` if it is set
1375
+ * - If the type of the old and new schema `items` are booleans of the same value, return `data` as is
1376
+ * - Otherwise return `undefined`
1377
+ *
1378
+ * @param validator - An implementation of the `ValidatorType` interface that will be used when necessary
1379
+ * @param rootSchema - The root JSON schema of the entire form
1380
+ * @param [newSchema] - The new schema for which the data is being sanitized
1381
+ * @param [oldSchema] - The old schema from which the data originated
1382
+ * @param [data={}] - The form data associated with the schema, defaulting to an empty object when undefined
1383
+ * @returns - The new form data, with all the fields uniquely associated with the old schema set
1384
+ * to `undefined`. Will return `undefined` if the new schema is not an object containing properties.
1385
+ */
1386
+ function sanitizeDataForNewSchema(validator, rootSchema, newSchema, oldSchema, data) {
1387
+ if (data === void 0) {
1388
+ data = {};
1389
+ }
1390
+ // By default, we will clear the form data
1391
+ var newFormData;
1392
+ // If the new schema is of type object and that object contains a list of properties
1393
+ if (has__default["default"](newSchema, PROPERTIES_KEY)) {
1394
+ // Create an object containing root-level keys in the old schema, setting each key to undefined to remove the data
1395
+ var removeOldSchemaData = {};
1396
+ if (has__default["default"](oldSchema, PROPERTIES_KEY)) {
1397
+ var properties = get__default["default"](oldSchema, PROPERTIES_KEY, {});
1398
+ Object.keys(properties).forEach(function (key) {
1399
+ if (has__default["default"](data, key)) {
1400
+ removeOldSchemaData[key] = undefined;
1401
+ }
1402
+ });
1403
+ }
1404
+ var keys = Object.keys(get__default["default"](newSchema, PROPERTIES_KEY, {}));
1405
+ // Create a place to store nested data that will be a side-effect of the filter
1406
+ var nestedData = {};
1407
+ keys.forEach(function (key) {
1408
+ var formValue = get__default["default"](data, key);
1409
+ var oldKeyedSchema = get__default["default"](oldSchema, [PROPERTIES_KEY, key], {});
1410
+ var newKeyedSchema = get__default["default"](newSchema, [PROPERTIES_KEY, key], {});
1411
+ // Resolve the refs if they exist
1412
+ if (has__default["default"](oldKeyedSchema, REF_KEY)) {
1413
+ oldKeyedSchema = retrieveSchema(validator, oldKeyedSchema, rootSchema, formValue);
1414
+ }
1415
+ if (has__default["default"](newKeyedSchema, REF_KEY)) {
1416
+ newKeyedSchema = retrieveSchema(validator, newKeyedSchema, rootSchema, formValue);
1417
+ }
1418
+ // Now get types and see if they are the same
1419
+ var oldSchemaTypeForKey = get__default["default"](oldKeyedSchema, "type");
1420
+ var newSchemaTypeForKey = get__default["default"](newKeyedSchema, "type");
1421
+ // Check if the old option has the same key with the same type
1422
+ if (!oldSchemaTypeForKey || oldSchemaTypeForKey === newSchemaTypeForKey) {
1423
+ if (has__default["default"](removeOldSchemaData, key)) {
1424
+ // SIDE-EFFECT: remove the undefined value for a key that has the same type between the old and new schemas
1425
+ delete removeOldSchemaData[key];
1426
+ }
1427
+ // If it is an object, we'll recurse and store the resulting sanitized data for the key
1428
+ if (newSchemaTypeForKey === "object" || newSchemaTypeForKey === "array" && Array.isArray(formValue)) {
1429
+ // SIDE-EFFECT: process the new schema type of object recursively to save iterations
1430
+ var itemData = sanitizeDataForNewSchema(validator, rootSchema, newKeyedSchema, oldKeyedSchema, formValue);
1431
+ if (itemData !== undefined || newSchemaTypeForKey === "array") {
1432
+ // only put undefined values for the array type and not the object type
1433
+ nestedData[key] = itemData;
1434
+ }
1435
+ } else {
1436
+ // Ok, the non-object types match, let's make sure that a default or a const of a different value is replaced
1437
+ // with the new default or const. This allows the case where two schemas differ that only by the default/const
1438
+ // value to be properly selected
1439
+ var newOptionDefault = get__default["default"](newKeyedSchema, "default", NO_VALUE);
1440
+ var oldOptionDefault = get__default["default"](oldKeyedSchema, "default", NO_VALUE);
1441
+ if (newOptionDefault !== NO_VALUE && newOptionDefault !== formValue) {
1442
+ if (oldOptionDefault === formValue) {
1443
+ // If the old default matches the formValue, we'll update the new value to match the new default
1444
+ removeOldSchemaData[key] = newOptionDefault;
1445
+ } else if (get__default["default"](newKeyedSchema, "readOnly") === true) {
1446
+ // If the new schema has the default set to read-only, treat it like a const and remove the value
1447
+ removeOldSchemaData[key] = undefined;
1448
+ }
1449
+ }
1450
+ var newOptionConst = get__default["default"](newKeyedSchema, "const", NO_VALUE);
1451
+ var oldOptionConst = get__default["default"](oldKeyedSchema, "const", NO_VALUE);
1452
+ if (newOptionConst !== NO_VALUE && newOptionConst !== formValue) {
1453
+ // Since this is a const, if the old value matches, replace the value with the new const otherwise clear it
1454
+ removeOldSchemaData[key] = oldOptionConst === formValue ? newOptionConst : undefined;
1455
+ }
1456
+ }
1457
+ }
1458
+ });
1459
+ newFormData = _extends({}, data, removeOldSchemaData, nestedData);
1460
+ // First apply removing the old schema data, then apply the nested data, then apply the old data keys to keep
1461
+ } else if (get__default["default"](oldSchema, "type") === "array" && get__default["default"](newSchema, "type") === "array" && Array.isArray(data)) {
1462
+ var oldSchemaItems = get__default["default"](oldSchema, "items");
1463
+ var newSchemaItems = get__default["default"](newSchema, "items");
1464
+ // If any of the array types `items` are arrays (remember arrays are objects) then we'll just drop the data
1465
+ // Eventually, we may want to deal with when either of the `items` are arrays since those tuple validations
1466
+ if (typeof oldSchemaItems === "object" && typeof newSchemaItems === "object" && !Array.isArray(oldSchemaItems) && !Array.isArray(newSchemaItems)) {
1467
+ if (has__default["default"](oldSchemaItems, REF_KEY)) {
1468
+ oldSchemaItems = retrieveSchema(validator, oldSchemaItems, rootSchema, data);
1469
+ }
1470
+ if (has__default["default"](newSchemaItems, REF_KEY)) {
1471
+ newSchemaItems = retrieveSchema(validator, newSchemaItems, rootSchema, data);
1472
+ }
1473
+ // Now get types and see if they are the same
1474
+ var oldSchemaType = get__default["default"](oldSchemaItems, "type");
1475
+ var newSchemaType = get__default["default"](newSchemaItems, "type");
1476
+ // Check if the old option has the same key with the same type
1477
+ if (!oldSchemaType || oldSchemaType === newSchemaType) {
1478
+ var maxItems = get__default["default"](newSchema, "maxItems", -1);
1479
+ if (newSchemaType === "object") {
1480
+ newFormData = data.reduce(function (newValue, aValue) {
1481
+ var itemValue = sanitizeDataForNewSchema(validator, rootSchema, newSchemaItems, oldSchemaItems, aValue);
1482
+ if (itemValue !== undefined && (maxItems < 0 || newValue.length < maxItems)) {
1483
+ newValue.push(itemValue);
1484
+ }
1485
+ return newValue;
1486
+ }, []);
1487
+ } else {
1488
+ newFormData = maxItems > 0 && data.length > maxItems ? data.slice(0, maxItems) : data;
1489
+ }
1490
+ }
1491
+ } else if (typeof oldSchemaItems === "boolean" && typeof newSchemaItems === "boolean" && oldSchemaItems === newSchemaItems) {
1492
+ // If they are both booleans and have the same value just return the data as is otherwise fall-thru to undefined
1493
+ newFormData = data;
1494
+ }
1495
+ // Also probably want to deal with `prefixItems` as tuples with the latest 2020 draft
1496
+ }
1497
+
1498
+ return newFormData;
1499
+ }
1500
+
1146
1501
  /** Generates an `IdSchema` object for the `schema`, recursively
1147
1502
  *
1148
1503
  * @param validator - An implementation of the `ValidatorType` interface that will be used when necessary
@@ -1288,11 +1643,37 @@ var SchemaUtils = /*#__PURE__*/function () {
1288
1643
  _proto.getDisplayLabel = function getDisplayLabel$1(schema, uiSchema) {
1289
1644
  return getDisplayLabel(this.validator, schema, uiSchema, this.rootSchema);
1290
1645
  }
1646
+ /** Determines which of the given `options` provided most closely matches the `formData`.
1647
+ * Returns the index of the option that is valid and is the closest match, or 0 if there is no match.
1648
+ *
1649
+ * The closest match is determined using the number of matching properties, and more heavily favors options with
1650
+ * matching readOnly, default, or const values.
1651
+ *
1652
+ * @param formData - The form data associated with the schema
1653
+ * @param options - The list of options that can be selected from
1654
+ * @param [selectedOption] - The index of the currently selected option, defaulted to -1 if not specified
1655
+ * @returns - The index of the option that is the closest match to the `formData` or the `selectedOption` if no match
1656
+ */;
1657
+ _proto.getClosestMatchingOption = function getClosestMatchingOption$1(formData, options, selectedOption) {
1658
+ return getClosestMatchingOption(this.validator, this.rootSchema, formData, options, selectedOption);
1659
+ }
1660
+ /** Given the `formData` and list of `options`, attempts to find the index of the first option that matches the data.
1661
+ * Always returns the first option if there is nothing that matches.
1662
+ *
1663
+ * @param formData - The current formData, if any, used to figure out a match
1664
+ * @param options - The list of options to find a matching options from
1665
+ * @returns - The firstindex of the matched option or 0 if none is available
1666
+ */;
1667
+ _proto.getFirstMatchingOption = function getFirstMatchingOption$1(formData, options) {
1668
+ return getFirstMatchingOption(this.validator, formData, options, this.rootSchema);
1669
+ }
1291
1670
  /** Given the `formData` and list of `options`, attempts to find the index of the option that best matches the data.
1671
+ * Deprecated, use `getFirstMatchingOption()` instead.
1292
1672
  *
1293
1673
  * @param formData - The current formData, if any, onto which to provide any missing defaults
1294
1674
  * @param options - The list of options to find a matching options from
1295
1675
  * @returns - The index of the matched option or 0 if none is available
1676
+ * @deprecated
1296
1677
  */;
1297
1678
  _proto.getMatchingOption = function getMatchingOption$1(formData, options) {
1298
1679
  return getMatchingOption(this.validator, formData, options, this.rootSchema);
@@ -1345,6 +1726,20 @@ var SchemaUtils = /*#__PURE__*/function () {
1345
1726
  _proto.retrieveSchema = function retrieveSchema$1(schema, rawFormData) {
1346
1727
  return retrieveSchema(this.validator, schema, this.rootSchema, rawFormData);
1347
1728
  }
1729
+ /** Sanitize the `data` associated with the `oldSchema` so it is considered appropriate for the `newSchema`. If the
1730
+ * new schema does not contain any properties, then `undefined` is returned to clear all the form data. Due to the
1731
+ * nature of schemas, this sanitization happens recursively for nested objects of data. Also, any properties in the
1732
+ * old schemas that are non-existent in the new schema are set to `undefined`.
1733
+ *
1734
+ * @param [newSchema] - The new schema for which the data is being sanitized
1735
+ * @param [oldSchema] - The old schema from which the data originated
1736
+ * @param [data={}] - The form data associated with the schema, defaulting to an empty object when undefined
1737
+ * @returns - The new form data, with all the fields uniquely associated with the old schema set
1738
+ * to `undefined`. Will return `undefined` if the new schema is not an object containing properties.
1739
+ */;
1740
+ _proto.sanitizeDataForNewSchema = function sanitizeDataForNewSchema$1(newSchema, oldSchema, data) {
1741
+ return sanitizeDataForNewSchema(this.validator, this.rootSchema, newSchema, oldSchema, data);
1742
+ }
1348
1743
  /** Generates an `IdSchema` object for the `schema`, recursively
1349
1744
  *
1350
1745
  * @param schema - The schema for which the display label flag is desired
@@ -1428,6 +1823,43 @@ function dataURItoBlob(dataURI) {
1428
1823
  };
1429
1824
  }
1430
1825
 
1826
+ /** Removes the `value` from the currently `selected` list of values
1827
+ *
1828
+ * @param value - The value to be removed from the selected list
1829
+ * @param selected - The current list of selected values
1830
+ * @returns - The updated `selected` list with the `value` removed from it
1831
+ */
1832
+ function enumOptionsDeselectValue(value, selected) {
1833
+ return selected.filter(function (v) {
1834
+ return v !== value;
1835
+ });
1836
+ }
1837
+
1838
+ /** Add the `value` to the list of `selected` values in the proper order as defined by `allEnumOptions`
1839
+ *
1840
+ * @param value - The value that should be selected
1841
+ * @param selected - The current list of selected values
1842
+ * @param allEnumOptions - The list of all the known enumOptions
1843
+ * @returns - The updated list of selected enum values with `value` added to it in the proper location
1844
+ */
1845
+ function enumOptionsSelectValue(value, selected, allEnumOptions) {
1846
+ if (allEnumOptions === void 0) {
1847
+ allEnumOptions = [];
1848
+ }
1849
+ var all = allEnumOptions.map(function (_ref) {
1850
+ var value = _ref.value;
1851
+ return value;
1852
+ });
1853
+ var at = all.indexOf(value);
1854
+ // If location of the value is not in the list of all enum values, just put it at the end
1855
+ var updated = at === -1 ? selected.concat(value) : selected.slice(0, at).concat(value, selected.slice(at));
1856
+ // As inserting values at predefined index positions doesn't work with empty
1857
+ // arrays, we need to reorder the updated selection to match the initial order
1858
+ return updated.sort(function (a, b) {
1859
+ return Number(all.indexOf(a) > all.indexOf(b));
1860
+ });
1861
+ }
1862
+
1431
1863
  /** The `ErrorSchemaBuilder<T>` is used to build an `ErrorSchema<T>` since the definition of the `ErrorSchema` type is
1432
1864
  * designed for reading information rather than writing it. Use this class to add, replace or clear errors in an error
1433
1865
  * schema by using either dotted path or an array of path names. Once you are done building the `ErrorSchema`, you can
@@ -1787,6 +2219,80 @@ function hasWidget(schema, widget, registeredWidgets) {
1787
2219
  }
1788
2220
  }
1789
2221
 
2222
+ /** Generates a consistent `id` pattern for a given `id` and a `suffix`
2223
+ *
2224
+ * @param id - Either simple string id or an IdSchema from which to extract it
2225
+ * @param suffix - The suffix to append to the id
2226
+ */
2227
+ function idGenerator(id, suffix) {
2228
+ var theId = isString__default["default"](id) ? id : id[ID_KEY];
2229
+ return theId + "__" + suffix;
2230
+ }
2231
+ /** Return a consistent `id` for the field description element
2232
+ *
2233
+ * @param id - Either simple string id or an IdSchema from which to extract it
2234
+ * @returns - The consistent id for the field description element from the given `id`
2235
+ */
2236
+ function descriptionId(id) {
2237
+ return idGenerator(id, "description");
2238
+ }
2239
+ /** Return a consistent `id` for the field error element
2240
+ *
2241
+ * @param id - Either simple string id or an IdSchema from which to extract it
2242
+ * @returns - The consistent id for the field error element from the given `id`
2243
+ */
2244
+ function errorId(id) {
2245
+ return idGenerator(id, "error");
2246
+ }
2247
+ /** Return a consistent `id` for the field examples element
2248
+ *
2249
+ * @param id - Either simple string id or an IdSchema from which to extract it
2250
+ * @returns - The consistent id for the field examples element from the given `id`
2251
+ */
2252
+ function examplesId(id) {
2253
+ return idGenerator(id, "examples");
2254
+ }
2255
+ /** Return a consistent `id` for the field help element
2256
+ *
2257
+ * @param id - Either simple string id or an IdSchema from which to extract it
2258
+ * @returns - The consistent id for the field help element from the given `id`
2259
+ */
2260
+ function helpId(id) {
2261
+ return idGenerator(id, "help");
2262
+ }
2263
+ /** Return a consistent `id` for the field title element
2264
+ *
2265
+ * @param id - Either simple string id or an IdSchema from which to extract it
2266
+ * @returns - The consistent id for the field title element from the given `id`
2267
+ */
2268
+ function titleId(id) {
2269
+ return idGenerator(id, "title");
2270
+ }
2271
+ /** Return a list of element ids that contain additional information about the field that can be used to as the aria
2272
+ * description of the field. This is correctly omitting `titleId` which would be "labeling" rather than "describing" the
2273
+ * element.
2274
+ *
2275
+ * @param id - Either simple string id or an IdSchema from which to extract it
2276
+ * @param [includeExamples=false] - Optional flag, if true, will add the `examplesId` into the list
2277
+ * @returns - The string containing the list of ids for use in an `aria-describedBy` attribute
2278
+ */
2279
+ function ariaDescribedByIds(id, includeExamples) {
2280
+ if (includeExamples === void 0) {
2281
+ includeExamples = false;
2282
+ }
2283
+ var examples = includeExamples ? " " + examplesId(id) : "";
2284
+ return errorId(id) + " " + descriptionId(id) + " " + helpId(id) + examples;
2285
+ }
2286
+ /** Return a consistent `id` for the `option`s of a `Radio` or `Checkboxes` widget
2287
+ *
2288
+ * @param id - The id of the parent component for the option
2289
+ * @param option - The option for which the id is desired
2290
+ * @returns - An id for the option based on the parent `id`
2291
+ */
2292
+ function optionId(id, option) {
2293
+ return id + "-" + option.value;
2294
+ }
2295
+
1790
2296
  /** Converts a local Date string into a UTC date string
1791
2297
  *
1792
2298
  * @param dateString - The string representation of a date as accepted by the `Date()` constructor
@@ -2112,14 +2618,22 @@ exports.UI_FIELD_KEY = UI_FIELD_KEY;
2112
2618
  exports.UI_OPTIONS_KEY = UI_OPTIONS_KEY;
2113
2619
  exports.UI_WIDGET_KEY = UI_WIDGET_KEY;
2114
2620
  exports.allowAdditionalItems = allowAdditionalItems;
2621
+ exports.ariaDescribedByIds = ariaDescribedByIds;
2115
2622
  exports.asNumber = asNumber;
2116
2623
  exports.canExpand = canExpand;
2117
2624
  exports.createSchemaUtils = createSchemaUtils;
2118
2625
  exports.dataURItoBlob = dataURItoBlob;
2119
2626
  exports.deepEquals = deepEquals;
2627
+ exports.descriptionId = descriptionId;
2628
+ exports.enumOptionsDeselectValue = enumOptionsDeselectValue;
2629
+ exports.enumOptionsSelectValue = enumOptionsSelectValue;
2630
+ exports.errorId = errorId;
2631
+ exports.examplesId = examplesId;
2120
2632
  exports.findSchemaDefinition = findSchemaDefinition;
2633
+ exports.getClosestMatchingOption = getClosestMatchingOption;
2121
2634
  exports.getDefaultFormState = getDefaultFormState;
2122
2635
  exports.getDisplayLabel = getDisplayLabel;
2636
+ exports.getFirstMatchingOption = getFirstMatchingOption;
2123
2637
  exports.getInputProps = getInputProps;
2124
2638
  exports.getMatchingOption = getMatchingOption;
2125
2639
  exports.getSchemaType = getSchemaType;
@@ -2129,6 +2643,7 @@ exports.getUiOptions = getUiOptions;
2129
2643
  exports.getWidget = getWidget;
2130
2644
  exports.guessType = guessType;
2131
2645
  exports.hasWidget = hasWidget;
2646
+ exports.helpId = helpId;
2132
2647
  exports.isConstant = isConstant;
2133
2648
  exports.isCustomWidget = isCustomWidget;
2134
2649
  exports.isFilesArray = isFilesArray;
@@ -2141,6 +2656,7 @@ exports.mergeDefaultsWithFormData = mergeDefaultsWithFormData;
2141
2656
  exports.mergeObjects = mergeObjects;
2142
2657
  exports.mergeSchemas = mergeSchemas;
2143
2658
  exports.mergeValidationData = mergeValidationData;
2659
+ exports.optionId = optionId;
2144
2660
  exports.optionsList = optionsList;
2145
2661
  exports.orderProperties = orderProperties;
2146
2662
  exports.pad = pad;
@@ -2148,8 +2664,10 @@ exports.parseDateString = parseDateString;
2148
2664
  exports.processSelectValue = processSelectValue;
2149
2665
  exports.rangeSpec = rangeSpec;
2150
2666
  exports.retrieveSchema = retrieveSchema;
2667
+ exports.sanitizeDataForNewSchema = sanitizeDataForNewSchema;
2151
2668
  exports.schemaRequiresTrueValue = schemaRequiresTrueValue;
2152
2669
  exports.shouldRender = shouldRender;
2670
+ exports.titleId = titleId;
2153
2671
  exports.toConstant = toConstant;
2154
2672
  exports.toDateString = toDateString;
2155
2673
  exports.toIdSchema = toIdSchema;