@react-typed-forms/schemas 11.10.0 → 11.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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,12 @@ 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
+ })(exports.ValidationMessageType || (exports.ValidationMessageType = {}));
27
33
  exports.ControlDefinitionType = void 0;
28
34
  (function (ControlDefinitionType) {
29
35
  ControlDefinitionType["Data"] = "Data";
@@ -611,21 +617,25 @@ function makeHook(runHook, state, deps) {
611
617
  runHook: runHook
612
618
  };
613
619
  }
620
+ function makeHookDepString(deps, asHookDep) {
621
+ return deps.map(function (x) {
622
+ return toDepString(asHookDep(x));
623
+ }).join(",");
624
+ }
614
625
  function useDynamicHooks(hooks) {
615
626
  var hookEntries = Object.entries(hooks);
616
- var deps = hookEntries.map(function (_ref2) {
617
- var x = _ref2[1];
618
- return toDepString(x.deps);
619
- }).join(",");
627
+ var deps = makeHookDepString(hookEntries, function (x) {
628
+ return x[1].deps;
629
+ });
620
630
  var ref = React.useRef({});
621
631
  var s = ref.current;
622
632
  hookEntries.forEach(function (x) {
623
633
  return s[x[0]] = x[1].state;
624
634
  });
625
635
  return React.useCallback(function (p) {
626
- return Object.fromEntries(hookEntries.map(function (_ref3) {
627
- var f = _ref3[0],
628
- hg = _ref3[1];
636
+ return Object.fromEntries(hookEntries.map(function (_ref2) {
637
+ var f = _ref2[0],
638
+ hg = _ref2[1];
629
639
  return [f, hg.runHook(p, ref.current[f])];
630
640
  }));
631
641
  }, [deps]);
@@ -1179,73 +1189,97 @@ function makeDynamicPropertyHook(dynamicValue, makeDefault, state, deps) {
1179
1189
  };
1180
1190
  }
1181
1191
 
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) {
1192
+ function useMakeValidationHook(definition, field, useValidatorFor) {
1193
+ var _dd$validators;
1194
+ if (useValidatorFor === void 0) {
1195
+ useValidatorFor = useDefaultValidator;
1196
+ }
1197
+ var dd = field && isDataControlDefinition(definition) ? definition : undefined;
1198
+ var refData = useUpdatedRef({
1199
+ dd: dd,
1200
+ field: field,
1201
+ useValidatorFor: useValidatorFor
1202
+ });
1203
+ var depString = makeHookDepString((_dd$validators = dd == null ? void 0 : dd.validators) != null ? _dd$validators : [], function (x) {
1185
1204
  return x.type;
1186
- })) != null ? _definition$validator : [] : null;
1187
- var r = useUpdatedRef({
1188
- definition: definition,
1189
- field: field
1190
1205
  });
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;
1206
+ return React.useCallback(function (ctx) {
1207
+ var _dd$validators2;
1208
+ var _refData$current = refData.current,
1209
+ dd = _refData$current.dd,
1210
+ field = _refData$current.field;
1211
+ if (!dd || !field) return;
1212
+ var control = ctx.control,
1213
+ hiddenControl = ctx.hiddenControl,
1214
+ schemaInterface = ctx.dataContext.schemaInterface;
1197
1215
  core.useValueChangeEffect(control, function () {
1198
1216
  return control.setError("default", "");
1199
1217
  });
1200
1218
  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
- }
1219
+ return !hiddenControl.value && dd.required && schemaInterface.isEmptyValue(field, v) ? schemaInterface.validationMessageText(field, exports.ValidationMessageType.NotEmpty, false, true) : null;
1220
+ }, "required", undefined, [dd.required]);
1221
+ (_dd$validators2 = dd.validators) == null || _dd$validators2.forEach(function (v, i) {
1222
+ return useValidatorFor(v, _extends({}, ctx, {
1223
+ index: i,
1224
+ field: field,
1225
+ definition: dd
1226
+ }));
1239
1227
  });
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);
1228
+ }, [!!dd, depString, useValidatorFor]);
1229
+ }
1230
+ function useDefaultValidator(validator, ctx) {
1231
+ switch (validator.type) {
1232
+ case exports.ValidatorType.Length:
1233
+ useLengthValidator(validator, ctx);
1234
+ break;
1235
+ case exports.ValidatorType.Jsonata:
1236
+ useJsonataValidator(validator, ctx);
1237
+ break;
1238
+ case exports.ValidatorType.Date:
1239
+ useDateValidator(validator, ctx);
1240
+ break;
1241
+ }
1242
+ }
1243
+ function useJsonataValidator(validator, ctx) {
1244
+ var errorMsg = useJsonataExpression(validator.expression, ctx.dataContext);
1245
+ core.useValidator(ctx.control, function () {
1246
+ return !ctx.hiddenControl.value ? errorMsg.value : null;
1247
+ }, "jsonata" + ctx.index);
1248
+ }
1249
+ function useLengthValidator(lv, ctx) {
1250
+ var control = ctx.control,
1251
+ schemaInterface = ctx.dataContext.schemaInterface,
1252
+ hiddenControl = ctx.hiddenControl,
1253
+ field = ctx.field;
1254
+ core.useValidator(control, function (v) {
1255
+ var len = schemaInterface.controlLength(field, control);
1256
+ var hidden = hiddenControl.value;
1257
+ if (hidden) {
1258
+ return undefined;
1259
+ }
1260
+ if (lv.min != null && len < lv.min) {
1261
+ if (field != null && field.collection) {
1262
+ control.setValue(function (v) {
1263
+ return Array.isArray(v) ? v.concat(Array.from({
1264
+ length: lv.min - v.length
1265
+ })) : Array.from({
1266
+ length: lv.min
1267
+ });
1268
+ });
1269
+ } else {
1270
+ return schemaInterface.validationMessageText(field, exports.ValidationMessageType.MinLength, len, lv.min);
1271
+ }
1272
+ } else if (lv.max != null && len > lv.max) {
1273
+ return schemaInterface.validationMessageText(field, exports.ValidationMessageType.MaxLength, len, lv.max);
1274
+ }
1275
+ return undefined;
1276
+ }, "length" + ctx.index);
1247
1277
  }
1248
- function useDateValidator(control, dv, i) {
1278
+ function useDateValidator(dv, ctx) {
1279
+ var control = ctx.control,
1280
+ field = ctx.field,
1281
+ index = ctx.index,
1282
+ schemaInterface = ctx.dataContext.schemaInterface;
1249
1283
  var comparisonDate;
1250
1284
  if (dv.fixedDate) {
1251
1285
  comparisonDate = Date.parse(dv.fixedDate);
@@ -1258,14 +1292,14 @@ function useDateValidator(control, dv, i) {
1258
1292
  }
1259
1293
  core.useValidator(control, function (v) {
1260
1294
  if (v) {
1261
- var selDate = Date.parse(v);
1295
+ var selDate = schemaInterface.parseToMillis(field, v);
1262
1296
  var notAfter = dv.comparison === exports.DateComparison.NotAfter;
1263
1297
  if (notAfter ? selDate > comparisonDate : selDate < comparisonDate) {
1264
1298
  return "Date must not be " + (notAfter ? "after" : "before") + " " + new Date(comparisonDate).toDateString();
1265
1299
  }
1266
1300
  }
1267
1301
  return null;
1268
- }, "date" + i);
1302
+ }, "date" + index);
1269
1303
  }
1270
1304
 
1271
1305
  function cc(n) {
@@ -1281,6 +1315,21 @@ var DefaultSchemaInterface = /*#__PURE__*/function () {
1281
1315
  this.boolStrings = boolStrings;
1282
1316
  }
1283
1317
  var _proto = DefaultSchemaInterface.prototype;
1318
+ _proto.parseToMillis = function parseToMillis(field, v) {
1319
+ return Date.parse(v);
1320
+ };
1321
+ _proto.validationMessageText = function validationMessageText(field, messageType, actual, expected) {
1322
+ switch (messageType) {
1323
+ case exports.ValidationMessageType.NotEmpty:
1324
+ return "Please enter a value";
1325
+ case exports.ValidationMessageType.MinLength:
1326
+ return "Length must be at least " + expected;
1327
+ case exports.ValidationMessageType.MaxLength:
1328
+ return "Length must be less than " + expected;
1329
+ default:
1330
+ return "Unknown error";
1331
+ }
1332
+ };
1284
1333
  _proto.getOptions = function getOptions(_ref) {
1285
1334
  var options = _ref.options;
1286
1335
  return options && options.length > 0 ? options : null;
@@ -1338,6 +1387,7 @@ function useControlRenderer(definition, fields, renderer, options) {
1338
1387
  var useExpr = (_options$useEvalExpre = options.useEvalExpressionHook) != null ? _options$useEvalExpre : defaultUseEvalExpressionHook;
1339
1388
  var fieldPath = lookupSchemaField(definition, fields);
1340
1389
  var schemaField = fieldPath == null ? void 0 : fieldPath.at(-1);
1390
+ var useValidation = useMakeValidationHook(definition, schemaField, options.useValidationHook);
1341
1391
  var dynamicHooks = useDynamicHooks({
1342
1392
  defaultValueControl: useEvalDefaultValueHook(useExpr, definition, schemaField, elementIndex != null),
1343
1393
  visibleControl: useEvalVisibilityHook(useExpr, definition, fieldPath),
@@ -1350,7 +1400,6 @@ function useControlRenderer(definition, fields, renderer, options) {
1350
1400
  layoutStyle: useEvalStyleHook(useExpr, exports.DynamicPropertyType.LayoutStyle, definition),
1351
1401
  displayControl: useEvalDisplayHook(useExpr, definition)
1352
1402
  });
1353
- var useValidation = useValidationHook(definition, schemaField);
1354
1403
  var r = useUpdatedRef({
1355
1404
  options: options,
1356
1405
  definition: definition,
@@ -1438,15 +1487,20 @@ function useControlRenderer(definition, fields, renderer, options) {
1438
1487
  }
1439
1488
  }
1440
1489
  }, true);
1441
- var myOptions = core.useCalculatedControl(function () {
1490
+ var myOptionsControl = core.useCalculatedControl(function () {
1442
1491
  var _visibility$fields;
1443
1492
  return {
1444
1493
  hidden: _options.hidden || !((_visibility$fields = visibility.fields) != null && _visibility$fields.showing.value),
1445
1494
  readonly: _options.readonly || readonlyControl.value,
1446
1495
  disabled: _options.disabled || disabledControl.value
1447
1496
  };
1448
- }).value;
1449
- useValidation(control != null ? control : core.newControl(null), !!myOptions.hidden, parentDataContext, schemaInterface);
1497
+ });
1498
+ var myOptions = core.trackedValue(myOptionsControl);
1499
+ useValidation({
1500
+ control: control != null ? control : core.newControl(null),
1501
+ hiddenControl: myOptionsControl.fields.hidden,
1502
+ dataContext: parentDataContext
1503
+ });
1450
1504
  var childOptions = _extends({}, _options, myOptions, {
1451
1505
  elementIndex: undefined
1452
1506
  });
@@ -1591,7 +1645,8 @@ function defaultDataProps(_ref4) {
1591
1645
  var className = cc(definition.styleClass);
1592
1646
  var required = !!definition.required;
1593
1647
  var fieldOptions = schemaInterface.getOptions(field);
1594
- var allowed = (_allowedOptions$value = allowedOptions == null ? void 0 : allowedOptions.value) != null ? _allowedOptions$value : [];
1648
+ var _allowed = (_allowedOptions$value = allowedOptions == null ? void 0 : allowedOptions.value) != null ? _allowedOptions$value : [];
1649
+ var allowed = Array.isArray(_allowed) ? _allowed : [_allowed];
1595
1650
  return _extends({
1596
1651
  definition: definition,
1597
1652
  childDefinitions: (_definition$children = definition.children) != null ? _definition$children : [],
@@ -3019,6 +3074,7 @@ exports.lookupSchemaField = lookupSchemaField;
3019
3074
  exports.makeCompoundField = makeCompoundField;
3020
3075
  exports.makeEvalExpressionHook = makeEvalExpressionHook;
3021
3076
  exports.makeHook = makeHook;
3077
+ exports.makeHookDepString = makeHookDepString;
3022
3078
  exports.makeScalarField = makeScalarField;
3023
3079
  exports.matchesType = matchesType;
3024
3080
  exports.mergeField = mergeField;
@@ -3035,6 +3091,7 @@ exports.timeField = timeField;
3035
3091
  exports.toDepString = toDepString;
3036
3092
  exports.useControlDefinitionForSchema = useControlDefinitionForSchema;
3037
3093
  exports.useControlRenderer = useControlRenderer;
3094
+ exports.useDateValidator = useDateValidator;
3038
3095
  exports.useDynamicHooks = useDynamicHooks;
3039
3096
  exports.useEvalActionHook = useEvalActionHook;
3040
3097
  exports.useEvalAllowedOptionsHook = useEvalAllowedOptionsHook;
@@ -3048,8 +3105,10 @@ exports.useEvalReadonlyHook = useEvalReadonlyHook;
3048
3105
  exports.useEvalStyleHook = useEvalStyleHook;
3049
3106
  exports.useEvalVisibilityHook = useEvalVisibilityHook;
3050
3107
  exports.useJsonataExpression = useJsonataExpression;
3108
+ exports.useJsonataValidator = useJsonataValidator;
3109
+ exports.useLengthValidator = useLengthValidator;
3110
+ exports.useMakeValidationHook = useMakeValidationHook;
3051
3111
  exports.useUpdatedRef = useUpdatedRef;
3052
- exports.useValidationHook = useValidationHook;
3053
3112
  exports.visitControlData = visitControlData;
3054
3113
  exports.visitControlDataArray = visitControlDataArray;
3055
3114
  exports.visitControlDefinition = visitControlDefinition;