@react-typed-forms/schemas 11.10.1 → 11.11.1

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.
@@ -1,8 +1,9 @@
1
1
  import React, { CSSProperties, FC, Key, ReactElement, ReactNode } from "react";
2
2
  import { Control } from "@react-typed-forms/core";
3
- import { AdornmentPlacement, ControlAdornment, ControlDefinition, DataControlDefinition, DisplayData, FieldOption, GroupRenderOptions, RenderOptions, SchemaField, SchemaInterface } from "./types";
3
+ import { AdornmentPlacement, ControlAdornment, ControlDefinition, DataControlDefinition, DisplayData, FieldOption, GroupRenderOptions, RenderOptions, SchemaField, SchemaInterface, SchemaValidator } from "./types";
4
4
  import { ControlDataContext, JsonPath } from "./util";
5
5
  import { EvalExpressionHook, UseEvalExpressionHook } from "./hooks";
6
+ import { ValidationContext } from "./validators";
6
7
  export interface FormRenderer {
7
8
  renderData: (props: DataRendererProps) => (layout: ControlLayoutProps) => ControlLayoutProps;
8
9
  renderGroup: (props: GroupRendererProps) => (layout: ControlLayoutProps) => ControlLayoutProps;
@@ -155,6 +156,7 @@ export type CreateDataProps = (controlProps: DataControlProps) => DataRendererPr
155
156
  export interface ControlRenderOptions extends FormContextOptions {
156
157
  useDataHook?: (c: ControlDefinition) => CreateDataProps;
157
158
  actionOnClick?: (actionId: string, actionData: any) => () => void;
159
+ useValidationHook?: (validator: SchemaValidator, ctx: ValidationContext) => void;
158
160
  useEvalExpressionHook?: UseEvalExpressionHook;
159
161
  clearHidden?: boolean;
160
162
  schemaInterface?: SchemaInterface;
package/lib/index.js CHANGED
@@ -24,6 +24,14 @@ exports.FieldType = void 0;
24
24
  FieldType["Image"] = "Image";
25
25
  FieldType["Any"] = "Any";
26
26
  })(exports.FieldType || (exports.FieldType = {}));
27
+ exports.ValidationMessageType = void 0;
28
+ (function (ValidationMessageType) {
29
+ ValidationMessageType["NotEmpty"] = "NotEmpty";
30
+ ValidationMessageType["MinLength"] = "MinLength";
31
+ ValidationMessageType["MaxLength"] = "MaxLength";
32
+ ValidationMessageType["NotAfterDate"] = "NotAfterDate";
33
+ ValidationMessageType["NotBeforeDate"] = "NotBeforeDate";
34
+ })(exports.ValidationMessageType || (exports.ValidationMessageType = {}));
27
35
  exports.ControlDefinitionType = void 0;
28
36
  (function (ControlDefinitionType) {
29
37
  ControlDefinitionType["Data"] = "Data";
@@ -611,21 +619,25 @@ function makeHook(runHook, state, deps) {
611
619
  runHook: runHook
612
620
  };
613
621
  }
622
+ function makeHookDepString(deps, asHookDep) {
623
+ return deps.map(function (x) {
624
+ return toDepString(asHookDep(x));
625
+ }).join(",");
626
+ }
614
627
  function useDynamicHooks(hooks) {
615
628
  var hookEntries = Object.entries(hooks);
616
- var deps = hookEntries.map(function (_ref2) {
617
- var x = _ref2[1];
618
- return toDepString(x.deps);
619
- }).join(",");
629
+ var deps = makeHookDepString(hookEntries, function (x) {
630
+ return x[1].deps;
631
+ });
620
632
  var ref = React.useRef({});
621
633
  var s = ref.current;
622
634
  hookEntries.forEach(function (x) {
623
635
  return s[x[0]] = x[1].state;
624
636
  });
625
637
  return React.useCallback(function (p) {
626
- return Object.fromEntries(hookEntries.map(function (_ref3) {
627
- var f = _ref3[0],
628
- hg = _ref3[1];
638
+ return Object.fromEntries(hookEntries.map(function (_ref2) {
639
+ var f = _ref2[0],
640
+ hg = _ref2[1];
629
641
  return [f, hg.runHook(p, ref.current[f])];
630
642
  }));
631
643
  }, [deps]);
@@ -1179,76 +1191,100 @@ function makeDynamicPropertyHook(dynamicValue, makeDefault, state, deps) {
1179
1191
  };
1180
1192
  }
1181
1193
 
1182
- function useValidationHook(definition, field) {
1183
- var _definition$validator, _definition$validator2;
1184
- var validatorTypes = isDataControlDefinition(definition) ? (_definition$validator = (_definition$validator2 = definition.validators) == null ? void 0 : _definition$validator2.map(function (x) {
1194
+ function useMakeValidationHook(definition, field, useValidatorFor) {
1195
+ var _dd$validators;
1196
+ if (useValidatorFor === void 0) {
1197
+ useValidatorFor = useDefaultValidator;
1198
+ }
1199
+ var dd = field && isDataControlDefinition(definition) ? definition : undefined;
1200
+ var refData = useUpdatedRef({
1201
+ dd: dd,
1202
+ field: field,
1203
+ useValidatorFor: useValidatorFor
1204
+ });
1205
+ var depString = makeHookDepString((_dd$validators = dd == null ? void 0 : dd.validators) != null ? _dd$validators : [], function (x) {
1185
1206
  return x.type;
1186
- })) != null ? _definition$validator : [] : null;
1187
- var r = useUpdatedRef({
1188
- definition: definition,
1189
- field: field
1190
1207
  });
1191
- return React.useCallback(function (control, hidden, groupContext, schemaInterface) {
1192
- var _dd$validators;
1193
- if (!validatorTypes) return;
1194
- var _r$current = r.current,
1195
- dd = _r$current.definition,
1196
- field = _r$current.field;
1208
+ return React.useCallback(function (ctx) {
1209
+ var _dd$validators2;
1210
+ var _refData$current = refData.current,
1211
+ dd = _refData$current.dd,
1212
+ field = _refData$current.field;
1213
+ if (!dd || !field) return;
1214
+ var control = ctx.control,
1215
+ hiddenControl = ctx.hiddenControl,
1216
+ schemaInterface = ctx.dataContext.schemaInterface;
1197
1217
  core.useValueChangeEffect(control, function () {
1198
1218
  return control.setError("default", "");
1199
1219
  });
1200
1220
  core.useValidator(control, function (v) {
1201
- return !hidden && dd.required && field && schemaInterface.isEmptyValue(field, v) ? "Please enter a value" : null;
1202
- }, "required", undefined, [hidden, dd.required, !!field]);
1203
- ((_dd$validators = dd.validators) != null ? _dd$validators : []).forEach(function (x, i) {
1204
- switch (x.type) {
1205
- case exports.ValidatorType.Length:
1206
- var lv = x;
1207
- core.useControlEffect(function () {
1208
- core.trackControlChange(control, core.ControlChange.Validate);
1209
- return [field ? schemaInterface.controlLength(field, control) : 0, hidden];
1210
- }, function (_ref) {
1211
- var len = _ref[0],
1212
- hidden = _ref[1];
1213
- if (hidden) {
1214
- control.setError("length", undefined);
1215
- return;
1216
- }
1217
- if (lv.min != null && len < lv.min) {
1218
- if (field != null && field.collection) {
1219
- control.setValue(function (v) {
1220
- return Array.isArray(v) ? v.concat(Array.from({
1221
- length: lv.min - v.length
1222
- })) : Array.from({
1223
- length: lv.min
1224
- });
1225
- });
1226
- } else {
1227
- control.setError("length", "Length must be at least " + lv.min);
1228
- }
1229
- } else if (lv.max != null && len > lv.max) {
1230
- control.setError("length", "Length must be less than " + lv.max);
1231
- }
1232
- }, true);
1233
- break;
1234
- case exports.ValidatorType.Jsonata:
1235
- return useJsonataValidator(control, groupContext, x, hidden, i);
1236
- case exports.ValidatorType.Date:
1237
- return useDateValidator(control, x, i);
1238
- }
1221
+ return !hiddenControl.value && dd.required && schemaInterface.isEmptyValue(field, v) ? schemaInterface.validationMessageText(field, exports.ValidationMessageType.NotEmpty, false, true) : null;
1222
+ }, "required", undefined, [dd.required]);
1223
+ (_dd$validators2 = dd.validators) == null || _dd$validators2.forEach(function (v, i) {
1224
+ return useValidatorFor(v, _extends({}, ctx, {
1225
+ index: i,
1226
+ field: field,
1227
+ definition: dd
1228
+ }));
1239
1229
  });
1240
- }, validatorTypes ? validatorTypes : [null]);
1241
- }
1242
- function useJsonataValidator(control, context, expr, hidden, i) {
1243
- var errorMsg = useJsonataExpression(expr.expression, context);
1244
- core.useValidator(control, function () {
1245
- return !hidden ? errorMsg.value : null;
1246
- }, "jsonata" + i);
1230
+ }, [!!dd, depString, useValidatorFor]);
1231
+ }
1232
+ function useDefaultValidator(validator, ctx) {
1233
+ switch (validator.type) {
1234
+ case exports.ValidatorType.Length:
1235
+ useLengthValidator(validator, ctx);
1236
+ break;
1237
+ case exports.ValidatorType.Jsonata:
1238
+ useJsonataValidator(validator, ctx);
1239
+ break;
1240
+ case exports.ValidatorType.Date:
1241
+ useDateValidator(validator, ctx);
1242
+ break;
1243
+ }
1244
+ }
1245
+ function useJsonataValidator(validator, ctx) {
1246
+ var errorMsg = useJsonataExpression(validator.expression, ctx.dataContext);
1247
+ core.useValidator(ctx.control, function () {
1248
+ return !ctx.hiddenControl.value ? errorMsg.value : null;
1249
+ }, "jsonata" + ctx.index);
1250
+ }
1251
+ function useLengthValidator(lv, ctx) {
1252
+ var control = ctx.control,
1253
+ schemaInterface = ctx.dataContext.schemaInterface,
1254
+ hiddenControl = ctx.hiddenControl,
1255
+ field = ctx.field;
1256
+ core.useValidator(control, function (v) {
1257
+ var len = schemaInterface.controlLength(field, control);
1258
+ var hidden = hiddenControl.value;
1259
+ if (hidden) {
1260
+ return undefined;
1261
+ }
1262
+ if (lv.min != null && len < lv.min) {
1263
+ if (field != null && field.collection) {
1264
+ control.setValue(function (v) {
1265
+ return Array.isArray(v) ? v.concat(Array.from({
1266
+ length: lv.min - v.length
1267
+ })) : Array.from({
1268
+ length: lv.min
1269
+ });
1270
+ });
1271
+ } else {
1272
+ return schemaInterface.validationMessageText(field, exports.ValidationMessageType.MinLength, len, lv.min);
1273
+ }
1274
+ } else if (lv.max != null && len > lv.max) {
1275
+ return schemaInterface.validationMessageText(field, exports.ValidationMessageType.MaxLength, len, lv.max);
1276
+ }
1277
+ return undefined;
1278
+ }, "length" + ctx.index);
1247
1279
  }
1248
- function useDateValidator(control, dv, i) {
1280
+ function useDateValidator(dv, ctx) {
1281
+ var control = ctx.control,
1282
+ field = ctx.field,
1283
+ index = ctx.index,
1284
+ schemaInterface = ctx.dataContext.schemaInterface;
1249
1285
  var comparisonDate;
1250
1286
  if (dv.fixedDate) {
1251
- comparisonDate = Date.parse(dv.fixedDate);
1287
+ comparisonDate = schemaInterface.parseToMillis(field, dv.fixedDate);
1252
1288
  } else {
1253
1289
  var nowDate = new Date();
1254
1290
  comparisonDate = Date.UTC(nowDate.getFullYear(), nowDate.getMonth(), nowDate.getDate());
@@ -1258,14 +1294,14 @@ function useDateValidator(control, dv, i) {
1258
1294
  }
1259
1295
  core.useValidator(control, function (v) {
1260
1296
  if (v) {
1261
- var selDate = Date.parse(v);
1297
+ var selDate = schemaInterface.parseToMillis(field, v);
1262
1298
  var notAfter = dv.comparison === exports.DateComparison.NotAfter;
1263
1299
  if (notAfter ? selDate > comparisonDate : selDate < comparisonDate) {
1264
- return "Date must not be " + (notAfter ? "after" : "before") + " " + new Date(comparisonDate).toDateString();
1300
+ return schemaInterface.validationMessageText(field, notAfter ? exports.ValidationMessageType.NotAfterDate : exports.ValidationMessageType.NotBeforeDate, selDate, comparisonDate);
1265
1301
  }
1266
1302
  }
1267
1303
  return null;
1268
- }, "date" + i);
1304
+ }, "date" + index);
1269
1305
  }
1270
1306
 
1271
1307
  function cc(n) {
@@ -1281,6 +1317,25 @@ var DefaultSchemaInterface = /*#__PURE__*/function () {
1281
1317
  this.boolStrings = boolStrings;
1282
1318
  }
1283
1319
  var _proto = DefaultSchemaInterface.prototype;
1320
+ _proto.parseToMillis = function parseToMillis(field, v) {
1321
+ return Date.parse(v);
1322
+ };
1323
+ _proto.validationMessageText = function validationMessageText(field, messageType, actual, expected) {
1324
+ switch (messageType) {
1325
+ case exports.ValidationMessageType.NotEmpty:
1326
+ return "Please enter a value";
1327
+ case exports.ValidationMessageType.MinLength:
1328
+ return "Length must be at least " + expected;
1329
+ case exports.ValidationMessageType.MaxLength:
1330
+ return "Length must be less than " + expected;
1331
+ case exports.ValidationMessageType.NotBeforeDate:
1332
+ return "Date must not be before " + new Date(expected).toDateString();
1333
+ case exports.ValidationMessageType.NotAfterDate:
1334
+ return "Date must not be after " + new Date(expected).toDateString();
1335
+ default:
1336
+ return "Unknown error";
1337
+ }
1338
+ };
1284
1339
  _proto.getOptions = function getOptions(_ref) {
1285
1340
  var options = _ref.options;
1286
1341
  return options && options.length > 0 ? options : null;
@@ -1338,6 +1393,7 @@ function useControlRenderer(definition, fields, renderer, options) {
1338
1393
  var useExpr = (_options$useEvalExpre = options.useEvalExpressionHook) != null ? _options$useEvalExpre : defaultUseEvalExpressionHook;
1339
1394
  var fieldPath = lookupSchemaField(definition, fields);
1340
1395
  var schemaField = fieldPath == null ? void 0 : fieldPath.at(-1);
1396
+ var useValidation = useMakeValidationHook(definition, schemaField, options.useValidationHook);
1341
1397
  var dynamicHooks = useDynamicHooks({
1342
1398
  defaultValueControl: useEvalDefaultValueHook(useExpr, definition, schemaField, elementIndex != null),
1343
1399
  visibleControl: useEvalVisibilityHook(useExpr, definition, fieldPath),
@@ -1350,7 +1406,6 @@ function useControlRenderer(definition, fields, renderer, options) {
1350
1406
  layoutStyle: useEvalStyleHook(useExpr, exports.DynamicPropertyType.LayoutStyle, definition),
1351
1407
  displayControl: useEvalDisplayHook(useExpr, definition)
1352
1408
  });
1353
- var useValidation = useValidationHook(definition, schemaField);
1354
1409
  var r = useUpdatedRef({
1355
1410
  options: options,
1356
1411
  definition: definition,
@@ -1438,15 +1493,20 @@ function useControlRenderer(definition, fields, renderer, options) {
1438
1493
  }
1439
1494
  }
1440
1495
  }, true);
1441
- var myOptions = core.useCalculatedControl(function () {
1496
+ var myOptionsControl = core.useCalculatedControl(function () {
1442
1497
  var _visibility$fields;
1443
1498
  return {
1444
1499
  hidden: _options.hidden || !((_visibility$fields = visibility.fields) != null && _visibility$fields.showing.value),
1445
1500
  readonly: _options.readonly || readonlyControl.value,
1446
1501
  disabled: _options.disabled || disabledControl.value
1447
1502
  };
1448
- }).value;
1449
- useValidation(control != null ? control : core.newControl(null), !!myOptions.hidden, parentDataContext, schemaInterface);
1503
+ });
1504
+ var myOptions = core.trackedValue(myOptionsControl);
1505
+ useValidation({
1506
+ control: control != null ? control : core.newControl(null),
1507
+ hiddenControl: myOptionsControl.fields.hidden,
1508
+ dataContext: parentDataContext
1509
+ });
1450
1510
  var childOptions = _extends({}, _options, myOptions, {
1451
1511
  elementIndex: undefined
1452
1512
  });
@@ -3020,6 +3080,7 @@ exports.lookupSchemaField = lookupSchemaField;
3020
3080
  exports.makeCompoundField = makeCompoundField;
3021
3081
  exports.makeEvalExpressionHook = makeEvalExpressionHook;
3022
3082
  exports.makeHook = makeHook;
3083
+ exports.makeHookDepString = makeHookDepString;
3023
3084
  exports.makeScalarField = makeScalarField;
3024
3085
  exports.matchesType = matchesType;
3025
3086
  exports.mergeField = mergeField;
@@ -3036,6 +3097,7 @@ exports.timeField = timeField;
3036
3097
  exports.toDepString = toDepString;
3037
3098
  exports.useControlDefinitionForSchema = useControlDefinitionForSchema;
3038
3099
  exports.useControlRenderer = useControlRenderer;
3100
+ exports.useDateValidator = useDateValidator;
3039
3101
  exports.useDynamicHooks = useDynamicHooks;
3040
3102
  exports.useEvalActionHook = useEvalActionHook;
3041
3103
  exports.useEvalAllowedOptionsHook = useEvalAllowedOptionsHook;
@@ -3049,8 +3111,10 @@ exports.useEvalReadonlyHook = useEvalReadonlyHook;
3049
3111
  exports.useEvalStyleHook = useEvalStyleHook;
3050
3112
  exports.useEvalVisibilityHook = useEvalVisibilityHook;
3051
3113
  exports.useJsonataExpression = useJsonataExpression;
3114
+ exports.useJsonataValidator = useJsonataValidator;
3115
+ exports.useLengthValidator = useLengthValidator;
3116
+ exports.useMakeValidationHook = useMakeValidationHook;
3052
3117
  exports.useUpdatedRef = useUpdatedRef;
3053
- exports.useValidationHook = useValidationHook;
3054
3118
  exports.visitControlData = visitControlData;
3055
3119
  exports.visitControlDataArray = visitControlDataArray;
3056
3120
  exports.visitControlDefinition = visitControlDefinition;