@abgov/jsonforms-components 2.21.1 → 2.21.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.esm.js CHANGED
@@ -5,9 +5,9 @@ import { GoAFormItem, GoAInput, GoATextArea, GoACallout, GoAInputDate, GoAInputD
5
5
  import styled from 'styled-components';
6
6
  import axios from 'axios';
7
7
  import get$1 from 'lodash/get';
8
- import { rankWith, isStringControl, and, optionIs, uiTypeIs, isDateControl, isNumberControl, isIntegerControl, isDateTimeControl, isTimeControl, isEnumControl, isBooleanControl, getAjv, isVisible, getControlPath, toDataPath, isEnabled, deriveLabelForUISchemaElement, schemaTypeIs, formatIs, createDefaultValue, or, isObjectArrayControl, isPrimitiveArrayControl, Paths, schemaMatches, hasType, isControl, isCategorization, isLayout } from '@jsonforms/core';
8
+ import { rankWith, isStringControl, and, optionIs, uiTypeIs, isDateControl, isNumberControl, isIntegerControl, isDateTimeControl, isTimeControl, isEnumControl, isBooleanControl, getAjv, isVisible, toDataPath, isEnabled, deriveLabelForUISchemaElement, schemaTypeIs, formatIs, createDefaultValue, or, isObjectArrayControl, isPrimitiveArrayControl, Paths, schemaMatches, hasType, isControl, isCategorization, isLayout } from '@jsonforms/core';
9
9
  import { withJsonFormsControlProps, withJsonFormsEnumProps, withTranslateProps, JsonFormsDispatch, useJsonForms, withJsonFormsLayoutProps, withJsonFormsArrayLayoutProps, withJsonFormsAllOfProps, withJsonFormsCellProps } from '@jsonforms/react';
10
- import * as _$a from 'lodash';
10
+ import * as _$b from 'lodash';
11
11
  import { isEqual, isEmpty as isEmpty$1, isObject as isObject$f } from 'lodash';
12
12
  import merge from 'lodash/merge';
13
13
  import isEmpty from 'lodash/isEmpty';
@@ -3547,16 +3547,16 @@ const onChangeForNumericControl = props => {
3547
3547
  }
3548
3548
  };
3549
3549
 
3550
- let _$9 = t => t,
3551
- _t$9,
3550
+ let _$a = t => t,
3551
+ _t$a,
3552
3552
  _t2$7;
3553
- styled.div(_t$9 || (_t$9 = _$9`
3553
+ styled.div(_t$a || (_t$a = _$a`
3554
3554
  height: 70vh;
3555
3555
  overflow-y: auto;
3556
3556
  padding-left: var(--goa-space-2xs);
3557
3557
  padding-right: var(--goa-space-2xs);
3558
3558
  `));
3559
- const Visible = styled.div(_t2$7 || (_t2$7 = _$9`
3559
+ const Visible = styled.div(_t2$7 || (_t2$7 = _$a`
3560
3560
  display: ${0};
3561
3561
  `), p => p.visible ? 'initial' : 'none');
3562
3562
 
@@ -5188,8 +5188,8 @@ const JsonFormRegisterProvider = ({
5188
5188
  });
5189
5189
  };
5190
5190
 
5191
- let _$8 = t => t,
5192
- _t$8,
5191
+ let _$9 = t => t,
5192
+ _t$9,
5193
5193
  _t2$6,
5194
5194
  _t3$5,
5195
5195
  _t4$5,
@@ -5197,42 +5197,42 @@ let _$8 = t => t,
5197
5197
  _t6$3,
5198
5198
  _t7$2,
5199
5199
  _t8$2;
5200
- const FormFieldWrapper = styled.div(_t$8 || (_t$8 = _$8`
5200
+ const FormFieldWrapper = styled.div(_t$9 || (_t$9 = _$9`
5201
5201
  margin-bottom: var(--goa-space-l);
5202
5202
  `));
5203
- const WarningIconDiv = styled.div(_t2$6 || (_t2$6 = _$8`
5203
+ const WarningIconDiv = styled.div(_t2$6 || (_t2$6 = _$9`
5204
5204
  display: inline-flex;
5205
5205
  align-items: flex-start;
5206
5206
  gap: 0.25rem;
5207
5207
  font-size: var(--goa-font-size-2);
5208
5208
  color: var(--goa-color-interactive-error);
5209
5209
  `));
5210
- const RequiredTextLabel = styled.label(_t3$5 || (_t3$5 = _$8`
5210
+ const RequiredTextLabel = styled.label(_t3$5 || (_t3$5 = _$9`
5211
5211
  color: var(--goa-color-greyscale-700);
5212
5212
  font-weight: var(--goa-font-weight-regular);
5213
5213
  font-size: var(--goa-font-size-2);
5214
5214
  line-height: var(--goa-line-height-1);
5215
5215
  font-style: normal;
5216
5216
  `));
5217
- const PageReviewNameCol = styled.td(_t4$5 || (_t4$5 = _$8`
5217
+ const PageReviewNameCol = styled.td(_t4$5 || (_t4$5 = _$9`
5218
5218
  width: 5%;
5219
5219
  padding-top: var(--goa-space-s);
5220
5220
  padding-bottom: var(--goa-space-s);
5221
5221
  padding-right: var(--goa-space-m);
5222
5222
  `));
5223
- const PageReviewValueCol = styled.td(_t5$4 || (_t5$4 = _$8`
5223
+ const PageReviewValueCol = styled.td(_t5$4 || (_t5$4 = _$9`
5224
5224
  width: 20%;
5225
5225
  text-align: left;
5226
5226
  `));
5227
5227
  //Check and unchecked are different heights otherwise
5228
- const CheckboxWrapper = styled.div(_t6$3 || (_t6$3 = _$8`
5228
+ const CheckboxWrapper = styled.div(_t6$3 || (_t6$3 = _$9`
5229
5229
  height: 28px;
5230
5230
  `));
5231
- styled.h4(_t7$2 || (_t7$2 = _$8`
5231
+ styled.h4(_t7$2 || (_t7$2 = _$9`
5232
5232
  margin: 0 0 0.25rem 0;
5233
5233
  fontsize: larger;
5234
5234
  `));
5235
- styled.h4(_t8$2 || (_t8$2 = _$8`
5235
+ styled.h4(_t8$2 || (_t8$2 = _$9`
5236
5236
  border-bottom: 1px solid #ddd;
5237
5237
  `));
5238
5238
 
@@ -5457,12 +5457,12 @@ const SPACE_KEY = ' ';
5457
5457
  const ALT_KEY = 'Alt';
5458
5458
  const SHIFT_KEY = 'Shift';
5459
5459
 
5460
- let _$7 = t => t,
5461
- _t$7,
5460
+ let _$8 = t => t,
5461
+ _t$8,
5462
5462
  _t2$5,
5463
5463
  _t3$4,
5464
5464
  _t4$4;
5465
- const GoADropdownTextbox = styled.div(_t$7 || (_t$7 = _$7`
5465
+ const GoADropdownTextbox = styled.div(_t$8 || (_t$8 = _$8`
5466
5466
  border-radius: var(--goa-space-2xs);
5467
5467
  box-shadow: ${0};
5468
5468
  &:hover {
@@ -5473,11 +5473,11 @@ const GoADropdownTextbox = styled.div(_t$7 || (_t$7 = _$7`
5473
5473
  box-shadow: ${0};
5474
5474
  }
5475
5475
  `), p => p.isOpen ? `0 0 0 3px var(--goa-color-interactive-focus)` : '', p => p.isOpen ? `0 0 0 3px var(--goa-color-interactive-focus) !important` : '');
5476
- const GoADropdownListContainerWrapper = styled.div(_t2$5 || (_t2$5 = _$7`
5476
+ const GoADropdownListContainerWrapper = styled.div(_t2$5 || (_t2$5 = _$8`
5477
5477
  position: relative;
5478
5478
  display: ${0};
5479
5479
  `), p => !(p === null || p === void 0 ? void 0 : p.isOpen) && 'none');
5480
- const GoADropdownListContainer = styled.div(_t3$4 || (_t3$4 = _$7`
5480
+ const GoADropdownListContainer = styled.div(_t3$4 || (_t3$4 = _$8`
5481
5481
  border: solid 1px var(--goa-color-greyscale-200);
5482
5482
  border-radius: var(--goa-space-2xs);
5483
5483
  background: var(--goa-color-greyscale-white);
@@ -5501,7 +5501,7 @@ const GoADropdownListContainer = styled.div(_t3$4 || (_t3$4 = _$7`
5501
5501
  scrollbar-color: #a8a8a8 var(--goa-color-greyscale-100) !important;
5502
5502
  }
5503
5503
  `), p => p.optionListMaxHeight || '272px');
5504
- const GoADropdownListOption = styled.div(_t4$4 || (_t4$4 = _$7`
5504
+ const GoADropdownListOption = styled.div(_t4$4 || (_t4$4 = _$8`
5505
5505
  padding: var(--goa-space-2xs) var(--goa-space-s);
5506
5506
  text-overflow: ellipsis;
5507
5507
  color: ${0} !important;
@@ -6578,8 +6578,8 @@ const BooleanRadioControl = props => jsx(GoAInputBaseControl, Object.assign({},
6578
6578
  const GoABooleanRadioControlTester = rankWith(3, and(isBooleanControl, optionIs('radio', true)));
6579
6579
  const GoABooleanRadioControl = withJsonFormsControlProps(BooleanRadioControl);
6580
6580
 
6581
- let _$6 = t => t,
6582
- _t$6;
6581
+ let _$7 = t => t,
6582
+ _t$7;
6583
6583
  const Checkboxes = ({
6584
6584
  children,
6585
6585
  orientation,
@@ -6591,7 +6591,7 @@ const Checkboxes = ({
6591
6591
  children: children
6592
6592
  });
6593
6593
  };
6594
- const CheckBoxGroupDiv = styled.div(_t$6 || (_t$6 = _$6`
6594
+ const CheckBoxGroupDiv = styled.div(_t$7 || (_t$7 = _$7`
6595
6595
  .horizontal {
6596
6596
  display: flex;
6597
6597
  flex-direction: row;
@@ -6799,8 +6799,8 @@ const GoAInputBaseTableReview = props => {
6799
6799
  };
6800
6800
  const GoAInputBaseTableReviewControl = withJsonFormsControlProps(GoAInputBaseTableReview);
6801
6801
 
6802
- let _$5 = t => t,
6803
- _t$5;
6802
+ let _$6 = t => t,
6803
+ _t$6;
6804
6804
  const renderLayoutElements = (elements, schema, path, enabled, renderers, cells) => {
6805
6805
  return elements.map((child, index) => jsx(JsonFormsDispatch, {
6806
6806
  uischema: child,
@@ -6879,14 +6879,14 @@ const ReviewLayoutRenderer = ({
6879
6879
  }
6880
6880
  }
6881
6881
  };
6882
- const ReviewGrid = styled.div(_t$5 || (_t$5 = _$5`
6882
+ const ReviewGrid = styled.div(_t$6 || (_t$6 = _$6`
6883
6883
  display: grid;
6884
6884
  grid-template-columns: repeat(auto-fit, minmax(250px, calc(50% - 8px)));
6885
6885
  gap: 16px;
6886
6886
  `));
6887
6887
 
6888
- let _$4 = t => t,
6889
- _t$4,
6888
+ let _$5 = t => t,
6889
+ _t$5,
6890
6890
  _t2$4,
6891
6891
  _t3$3,
6892
6892
  _t4$3,
@@ -6908,7 +6908,7 @@ let _$4 = t => t,
6908
6908
  _t20$1,
6909
6909
  _t21,
6910
6910
  _t22;
6911
- const ReviewItem = styled.div(_t$4 || (_t$4 = _$4`
6911
+ const ReviewItem = styled.div(_t$5 || (_t$5 = _$5`
6912
6912
  display: flex;
6913
6913
  flex-direction: column;
6914
6914
  border: var(--goa-border-width-s) solid grey;
@@ -6919,7 +6919,7 @@ const ReviewItem = styled.div(_t$4 || (_t$4 = _$4`
6919
6919
  display: none;
6920
6920
  }
6921
6921
  `));
6922
- const ReviewItemSection = styled.div(_t2$4 || (_t2$4 = _$4`
6922
+ const ReviewItemSection = styled.div(_t2$4 || (_t2$4 = _$5`
6923
6923
  background-color: #f1f1f1;
6924
6924
  margin-bottom: var(--goa-space-m);
6925
6925
  padding: var(--goa-space-m);
@@ -6930,18 +6930,18 @@ const ReviewItemSection = styled.div(_t2$4 || (_t2$4 = _$4`
6930
6930
  max-width: 1600px;
6931
6931
  }
6932
6932
  `));
6933
- const ReviewItemHeader = styled.div(_t3$3 || (_t3$3 = _$4`
6933
+ const ReviewItemHeader = styled.div(_t3$3 || (_t3$3 = _$5`
6934
6934
  display: flex;
6935
6935
  align-items: center;
6936
6936
  justify-content: space-between;
6937
6937
  margin-bottom: var(--goa-space-xl);
6938
6938
  `));
6939
- const ReviewItemTitle = styled.div(_t4$3 || (_t4$3 = _$4`
6939
+ const ReviewItemTitle = styled.div(_t4$3 || (_t4$3 = _$5`
6940
6940
  font-size: var(--goa-space-l);
6941
6941
  line-height: var(--goa-space-xl);
6942
6942
  font-weight: 300;
6943
6943
  `));
6944
- const Anchor = styled.div(_t5$3 || (_t5$3 = _$4`
6944
+ const Anchor = styled.div(_t5$3 || (_t5$3 = _$5`
6945
6945
  color: #0070c4;
6946
6946
  text-decoration: underline;
6947
6947
  outline: none;
@@ -6952,20 +6952,20 @@ const Anchor = styled.div(_t5$3 || (_t5$3 = _$4`
6952
6952
  background-color: #e6f7ff;
6953
6953
  }
6954
6954
  `));
6955
- styled.div(_t6$2 || (_t6$2 = _$4`
6955
+ styled.div(_t6$2 || (_t6$2 = _$5`
6956
6956
  margin-left: var(--goa-space-m);
6957
6957
  `));
6958
- styled.div(_t7$1 || (_t7$1 = _$4`
6958
+ styled.div(_t7$1 || (_t7$1 = _$5`
6959
6959
  margin-bottom: var(--goa-space-m);
6960
6960
  `));
6961
- styled.div(_t8$1 || (_t8$1 = _$4`
6961
+ styled.div(_t8$1 || (_t8$1 = _$5`
6962
6962
  margin: var(--goa-space-s);
6963
6963
  width: 100%;
6964
6964
  `));
6965
- styled.h3(_t9$1 || (_t9$1 = _$4`
6965
+ styled.h3(_t9$1 || (_t9$1 = _$5`
6966
6966
  text-transform: capitalize;
6967
6967
  `));
6968
- const RightAlignmentDiv = styled.div(_t10$1 || (_t10$1 = _$4`
6968
+ const RightAlignmentDiv = styled.div(_t10$1 || (_t10$1 = _$5`
6969
6969
  @media screen and (max-width: 767px) {
6970
6970
  margin-bottom: var(--goa-space-l);
6971
6971
  }
@@ -6975,55 +6975,55 @@ const RightAlignmentDiv = styled.div(_t10$1 || (_t10$1 = _$4`
6975
6975
  margin-bottom: var(--goa-space-l);
6976
6976
  }
6977
6977
  `));
6978
- const FormStepperSummaryH3 = styled.h3(_t11$1 || (_t11$1 = _$4`
6978
+ const FormStepperSummaryH3 = styled.h3(_t11$1 || (_t11$1 = _$5`
6979
6979
  flex: 1;
6980
6980
  margin-bottom: var(--goa-space-m);
6981
6981
  font-size: var(--goa-font-size-7);
6982
6982
  line-height: var(--goa-line-height-4);
6983
6983
  font-weight: var(--goa-font-weight-regular);
6984
6984
  `));
6985
- const PageRenderPadding = styled.div(_t12$1 || (_t12$1 = _$4`
6985
+ const PageRenderPadding = styled.div(_t12$1 || (_t12$1 = _$5`
6986
6986
  margin-top: var(--goa-space-2xl);
6987
6987
  `));
6988
- styled.div(_t13$1 || (_t13$1 = _$4`
6988
+ styled.div(_t13$1 || (_t13$1 = _$5`
6989
6989
  margin-bottom: var(--goa-space-2xl);
6990
6990
  `));
6991
- const PageBorder = styled.h3(_t14$1 || (_t14$1 = _$4`
6991
+ const PageBorder = styled.h3(_t14$1 || (_t14$1 = _$5`
6992
6992
  padding: var(--goa-space-3xl);
6993
6993
  `));
6994
- const TableReviewItemSection = styled.div(_t15$1 || (_t15$1 = _$4`
6994
+ const TableReviewItemSection = styled.div(_t15$1 || (_t15$1 = _$5`
6995
6995
  .element-style {
6996
6996
  max-width: 1600px;
6997
6997
  }
6998
6998
  `));
6999
- const TableReviewItem = styled.div(_t16$1 || (_t16$1 = _$4`
6999
+ const TableReviewItem = styled.div(_t16$1 || (_t16$1 = _$5`
7000
7000
  border: 1px solid #dcdcdc;
7001
7001
  border-radius: 5px;
7002
7002
  padding: var(--goa-space-2xl);
7003
7003
  `));
7004
- const TableReviewPageTitleRow = styled.div(_t17$1 || (_t17$1 = _$4`
7004
+ const TableReviewPageTitleRow = styled.div(_t17$1 || (_t17$1 = _$5`
7005
7005
  margin-top: var(--goa-space-xl);
7006
7006
  display: flex;
7007
7007
  justify-content: space-between;
7008
7008
  `));
7009
- const TableReviewCategoryLabel = styled.h3(_t18$1 || (_t18$1 = _$4`
7009
+ const TableReviewCategoryLabel = styled.h3(_t18$1 || (_t18$1 = _$5`
7010
7010
  color: var(--goa-color-text-secondary) !important;
7011
7011
  margin-bottom: var(--goa-space-l);
7012
7012
  `));
7013
- const CategoryStatus = styled.td(_t19$1 || (_t19$1 = _$4`
7013
+ const CategoryStatus = styled.td(_t19$1 || (_t19$1 = _$5`
7014
7014
  width: var(--goa-space-xl);
7015
7015
  padding-right: var(--goa-space-xl);
7016
7016
  `));
7017
- const TocPageRef = styled.td(_t20$1 || (_t20$1 = _$4`
7017
+ const TocPageRef = styled.td(_t20$1 || (_t20$1 = _$5`
7018
7018
  padding-left: var(--goa-space-xl);
7019
7019
  `));
7020
- const CompletionStatus = styled.div(_t21 || (_t21 = _$4`
7020
+ const CompletionStatus = styled.div(_t21 || (_t21 = _$5`
7021
7021
  padding: 0;
7022
7022
  margin: 0;
7023
7023
  padding-left: var(--goa-space-xl);
7024
7024
  padding-bottom: var(--goa-space-xl);
7025
7025
  `));
7026
- const PageStepperRow = styled.tr(_t22 || (_t22 = _$4`
7026
+ const PageStepperRow = styled.tr(_t22 || (_t22 = _$5`
7027
7027
  ${0}
7028
7028
  `), ({
7029
7029
  disabled
@@ -7403,7 +7403,7 @@ const pickPropertyValues = (obj, property, endWithType) => {
7403
7403
  Object.entries(obj).forEach(function ([key, value]) {
7404
7404
  if (key === property) {
7405
7405
  values.push(value);
7406
- } else if (_$a.isObject(value)) {
7406
+ } else if (_$b.isObject(value)) {
7407
7407
  // if the object type is equal to end type, we are not going to continue the recursive approach
7408
7408
  if ((value === null || value === void 0 ? void 0 : value.type) === endWithType) {
7409
7409
  if (property in value) {
@@ -7412,7 +7412,7 @@ const pickPropertyValues = (obj, property, endWithType) => {
7412
7412
  } else {
7413
7413
  values = [...values, ...pickPropertyValues(value, property, endWithType)];
7414
7414
  }
7415
- } else if (_$a.isArray(value)) {
7415
+ } else if (_$b.isArray(value)) {
7416
7416
  const nextValues = value.map(function (arrayObj) {
7417
7417
  return pickPropertyValues(arrayObj, property, endWithType);
7418
7418
  });
@@ -7509,26 +7509,31 @@ const FormStepperReviewer = props => {
7509
7509
  };
7510
7510
  const FormStepperReviewControl = withAjvProps(withTranslateProps(withJsonFormsLayoutProps(FormStepperReviewer)));
7511
7511
 
7512
- const isErrorPathIncluded = (errorPaths, path) => {
7513
- return errorPaths.some(ePath => {
7514
- /**
7515
- * case A: errorPaths: [name] path: [name]
7516
- *
7517
- * case B: errorPath: [name] path: [name.firstName]
7518
- * */
7519
- return ePath === path || path.startsWith(ePath + '.');
7520
- });
7521
- };
7522
7512
  function isNumber(value) {
7523
7513
  return value != null && value !== '' && !isNaN(Number(value.toString()));
7524
7514
  }
7525
- const getIncompletePaths = (ajv, scopes) => {
7526
- var _a;
7527
- const requiredErrorPaths = (_a = ajv === null || ajv === void 0 ? void 0 : ajv.errors) === null || _a === void 0 ? void 0 : _a.filter(e => e.keyword === 'required' || e.keyword === 'minLength' || e.keyword === 'minItems' || e.keyword === 'errorMessage').map(e => {
7528
- return getControlPath(e);
7529
- });
7530
- const _scopes = scopes.map(scope => toDataPath(scope)).filter(path => requiredErrorPaths && isErrorPathIncluded(requiredErrorPaths, path));
7531
- return _scopes;
7515
+ const getIncompletePaths = (ajv, schema, data, scopes) => {
7516
+ var _a, _b, _c, _d;
7517
+ const incomplete = [];
7518
+ for (const scope of scopes) {
7519
+ const path = toDataPath(scope);
7520
+ const value = get$1(data, path);
7521
+ const schemaPath = path.split('.');
7522
+ let currentSchema = schema;
7523
+ for (const key of schemaPath) {
7524
+ if (!currentSchema || !currentSchema.properties || !currentSchema.properties[key]) {
7525
+ currentSchema = null;
7526
+ break;
7527
+ }
7528
+ currentSchema = currentSchema.properties[key];
7529
+ }
7530
+ const isRequired = schemaPath.length > 1 ? (_c = (_b = (_a = schema === null || schema === void 0 ? void 0 : schema.properties) === null || _a === void 0 ? void 0 : _a[schemaPath[0]]) === null || _b === void 0 ? void 0 : _b.required) === null || _c === void 0 ? void 0 : _c.includes(schemaPath[1]) : (_d = schema === null || schema === void 0 ? void 0 : schema.required) === null || _d === void 0 ? void 0 : _d.includes(path);
7531
+ const hasMinLength = (currentSchema === null || currentSchema === void 0 ? void 0 : currentSchema.minLength) !== undefined;
7532
+ if (isRequired && (value === undefined || value === null || value === '') || hasMinLength && typeof value === 'string' && value.length < currentSchema.minLength) {
7533
+ incomplete.push(path);
7534
+ }
7535
+ }
7536
+ return incomplete;
7532
7537
  };
7533
7538
  const subErrorInParent = (error, paths) => {
7534
7539
  /*
@@ -7556,6 +7561,10 @@ const getErrorsInScopes = (errors, scopes) => {
7556
7561
  return dataPaths.includes(e.instancePath) || subErrorInParent(e, dataPaths);
7557
7562
  });
7558
7563
  };
7564
+ const hasDataInScopes = (data, scopes) => {
7565
+ const dataPaths = scopes.map(s => toDataPath(s));
7566
+ return dataPaths.map(p => get$1(data, p)).some(data => data !== undefined);
7567
+ };
7559
7568
  const getLocalStorageKeyPrefix = () => {
7560
7569
  return window.location.href + '_' + new Date().toISOString().slice(0, 10);
7561
7570
  };
@@ -7645,15 +7654,21 @@ const stepperReducer = (state, action) => {
7645
7654
  const {
7646
7655
  id,
7647
7656
  ajv,
7648
- errors
7657
+ errors = [],
7658
+ schema,
7659
+ data
7649
7660
  } = action.payload;
7650
- if (id === state.categories.length || id === state.categories.length + 1) {
7661
+ if (id >= state.categories.length) {
7651
7662
  return Object.assign({}, state);
7652
7663
  }
7653
- /*
7654
- ctx.core.errors only includes required errors when the fields are touched. In this case, we still ajv to figure out the required errors at the very beginning.
7655
- */
7656
- const incompletePaths = getIncompletePaths(ajv, ((_a = state.categories[id]) === null || _a === void 0 ? void 0 : _a.scopes) || []);
7664
+ if (schema && typeof schema === 'object') {
7665
+ try {
7666
+ ajv.validate(schema, data);
7667
+ } catch (err) {
7668
+ console.warn('AJV validation error:', err);
7669
+ }
7670
+ }
7671
+ const incompletePaths = getIncompletePaths(ajv, schema, data, ((_a = state.categories[id]) === null || _a === void 0 ? void 0 : _a.scopes) || []);
7657
7672
  const errorsInCategory = getErrorsInScopes(errors, ((_b = state.categories[id]) === null || _b === void 0 ? void 0 : _b.scopes) || []);
7658
7673
  if (state.categories[id]) {
7659
7674
  state.categories[id].isCompleted = (incompletePaths === null || incompletePaths === void 0 ? void 0 : incompletePaths.length) === 0;
@@ -7665,7 +7680,7 @@ const stepperReducer = (state, action) => {
7665
7680
  case 'validate/form':
7666
7681
  {
7667
7682
  const {
7668
- errors
7683
+ errors = []
7669
7684
  } = action.payload;
7670
7685
  state.isValid = errors.length === 0;
7671
7686
  return Object.assign({}, state);
@@ -7691,7 +7706,6 @@ const createStepperContextInitData = props => {
7691
7706
  schema,
7692
7707
  ajv,
7693
7708
  t,
7694
- visible,
7695
7709
  path
7696
7710
  } = props;
7697
7711
  const categorization = uischema;
@@ -7700,17 +7714,22 @@ const createStepperContextInitData = props => {
7700
7714
  const isCacheStatus = (_b = uischema.options) === null || _b === void 0 ? void 0 : _b.cacheStatus;
7701
7715
  /* istanbul ignore next */
7702
7716
  const cachedStatus = isCacheStatus && getIsVisitFromLocalStorage() || [];
7717
+ ajv.validate(schema, data);
7703
7718
  const categories = (_c = categorization.elements) === null || _c === void 0 ? void 0 : _c.map((c, id) => {
7704
7719
  const scopes = pickPropertyValues(c, 'scope', 'ListWithDetail');
7705
- const incompletePaths = getIncompletePaths(ajv, scopes) || [];
7720
+ const incompletePaths = getIncompletePaths(ajv, schema, data, scopes);
7721
+ const hasAnyData = hasDataInScopes(data, scopes);
7722
+ const isVisited = isCacheStatus ? cachedStatus.at(id) : hasAnyData;
7723
+ const isCompleted = isVisited && incompletePaths.length === 0;
7724
+ const isValid = isCompleted;
7706
7725
  return {
7707
7726
  id,
7708
7727
  label: deriveLabelForUISchemaElement(c, t),
7709
7728
  scopes,
7710
7729
  /* istanbul ignore next */
7711
- isVisited: isCacheStatus ? cachedStatus.at(id) : false,
7712
- isCompleted: (incompletePaths === null || incompletePaths === void 0 ? void 0 : incompletePaths.length) === 0,
7713
- isValid: (incompletePaths === null || incompletePaths === void 0 ? void 0 : incompletePaths.length) === 0,
7730
+ isVisited,
7731
+ isCompleted,
7732
+ isValid,
7714
7733
  uischema: c,
7715
7734
  showReviewPageLink: props.withBackReviewBtn || false,
7716
7735
  isEnabled: isEnabled(c, data, '', ajv),
@@ -7793,7 +7812,9 @@ const JsonFormsStepperContextProvider = ({
7793
7812
  payload: {
7794
7813
  errors: (_a = ctx === null || ctx === void 0 ? void 0 : ctx.core) === null || _a === void 0 ? void 0 : _a.errors,
7795
7814
  id,
7796
- ajv
7815
+ ajv,
7816
+ schema,
7817
+ data
7797
7818
  }
7798
7819
  });
7799
7820
  },
@@ -7807,7 +7828,9 @@ const JsonFormsStepperContextProvider = ({
7807
7828
  payload: {
7808
7829
  errors: (_b = ctx === null || ctx === void 0 ? void 0 : ctx.core) === null || _b === void 0 ? void 0 : _b.errors,
7809
7830
  id: i,
7810
- ajv
7831
+ ajv,
7832
+ schema,
7833
+ data
7811
7834
  }
7812
7835
  });
7813
7836
  }
@@ -7834,7 +7857,7 @@ const JsonFormsStepperContextProvider = ({
7834
7857
  });
7835
7858
  }
7836
7859
  };
7837
- }, [stepperDispatch, stepperState, (_b = ctx.core) === null || _b === void 0 ? void 0 : _b.errors, ajv]);
7860
+ }, [stepperDispatch, stepperState, (_b = ctx.core) === null || _b === void 0 ? void 0 : _b.errors, ajv, schema, data]);
7838
7861
  /* istanbul ignore next */
7839
7862
  useEffect(() => {
7840
7863
  const handleBeforeUnload = () => {
@@ -8326,6 +8349,56 @@ const FormStepperPageReviewer = props => {
8326
8349
  };
8327
8350
  withAjvProps(withTranslateProps(withJsonFormsLayoutProps(FormStepperPageReviewer)));
8328
8351
 
8352
+ let _$4 = t => t,
8353
+ _t$4;
8354
+ const BackButtonWrapper = styled.span(_t$4 || (_t$4 = _$4`
8355
+ .back-link::before {
8356
+ content: '';
8357
+ display: inline-block;
8358
+ width: 42px;
8359
+ height: 24px;
8360
+ vertical-align: middle;
8361
+ background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 2 22 22" fill="none" stroke="%230070C4" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"></polyline></svg>')
8362
+ center center no-repeat;
8363
+ }
8364
+
8365
+ .back-link:visited::before,
8366
+ .back-link:hover::before {
8367
+ background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 2 22 22" fill="none" stroke="%23004f84" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"></polyline></svg>')
8368
+ center center no-repeat;
8369
+ }
8370
+
8371
+ .back-link {
8372
+ margin-top: var(--goa-space-m);
8373
+ }
8374
+ display: inline-block;
8375
+ color: #0070c4;
8376
+ cursor: pointer;
8377
+
8378
+ on .goa-icon {
8379
+ display: inline-block !important;
8380
+ position: relative;
8381
+ top: 3px;
8382
+ right: 2px;
8383
+ color: #0070c4;
8384
+ margin-left: 4px;
8385
+ }
8386
+ `));
8387
+ const BackButton = ({
8388
+ text,
8389
+ testId,
8390
+ link
8391
+ }) => {
8392
+ return jsx(BackButtonWrapper, {
8393
+ "data-testid": "back-button-click",
8394
+ onClick: link,
8395
+ children: jsx("div", {
8396
+ className: "back-link",
8397
+ children: text
8398
+ })
8399
+ });
8400
+ };
8401
+
8329
8402
  const RenderPages = props => {
8330
8403
  var _a, _b;
8331
8404
  const {
@@ -8379,7 +8452,14 @@ const RenderPages = props => {
8379
8452
  children: jsx("div", {
8380
8453
  id: `${path || `goa`}-form-pages`,
8381
8454
  children: jsxs(PageBorder, {
8382
- children: [categories === null || categories === void 0 ? void 0 : categories.map((category, index) => {
8455
+ children: [jsx(BackButton, {
8456
+ text: "Back to tasks",
8457
+ link: () => {
8458
+ handleSave();
8459
+ goToTableOfContext();
8460
+ },
8461
+ testId: "back-to-tasks"
8462
+ }), categories === null || categories === void 0 ? void 0 : categories.map((category, index) => {
8383
8463
  const categoryProps = {
8384
8464
  category: category.uischema,
8385
8465
  categoryIndex: category.id,
@@ -8405,17 +8485,23 @@ const RenderPages = props => {
8405
8485
  children: jsxs(GoAGrid, {
8406
8486
  minChildWidth: "100px",
8407
8487
  gap: "2xs",
8408
- children: [jsx(GoAButtonGroup, {
8488
+ children: [jsxs(GoAButtonGroup, {
8409
8489
  alignment: "start",
8410
- children: jsx(GoAButton, {
8490
+ children: [activeId > 0 && jsx(GoAButton, {
8411
8491
  type: "secondary",
8412
8492
  onClick: () => {
8413
- validatePage(index);
8414
- goToTableOfContext();
8493
+ handleSave();
8494
+ let prevId = activeId - 1;
8495
+ while (prevId >= 0 && categories[prevId].visible === false) {
8496
+ prevId = prevId - 1;
8497
+ }
8498
+ if (prevId >= 0) {
8499
+ goToPage(prevId);
8500
+ }
8415
8501
  },
8416
- testId: "back-button",
8502
+ testId: "pages-prev-btn",
8417
8503
  children: "Previous"
8418
- })
8504
+ }), ' ']
8419
8505
  }), jsx(GoAButtonGroup, {
8420
8506
  alignment: "end",
8421
8507
  children: jsx(GoAButton, {
@@ -8428,7 +8514,7 @@ const RenderPages = props => {
8428
8514
  }
8429
8515
  goToPage(nextId);
8430
8516
  },
8431
- disabled: !(category.isValid && category.isCompleted) || !enabled,
8517
+ disabled: !enabled,
8432
8518
  testId: "pages-save-continue-btn",
8433
8519
  children: "Next"
8434
8520
  })
@@ -8442,20 +8528,10 @@ const RenderPages = props => {
8442
8528
  children: [jsx(FormStepperPageReviewer, Object.assign({}, props.categoryProps, {
8443
8529
  navigationFunc: goToPage
8444
8530
  })), jsx(PageRenderPadding, {
8445
- children: jsxs(GoAGrid, {
8531
+ children: jsx(GoAGrid, {
8446
8532
  minChildWidth: "100px",
8447
8533
  gap: "2xs",
8448
- children: [jsx(GoAButtonGroup, {
8449
- alignment: "start",
8450
- children: jsx(GoAButton, {
8451
- type: "secondary",
8452
- onClick: () => {
8453
- goToTableOfContext();
8454
- },
8455
- testId: "back-button",
8456
- children: "Previous"
8457
- })
8458
- }), jsx(GoAButtonGroup, {
8534
+ children: jsx(GoAButtonGroup, {
8459
8535
  alignment: "end",
8460
8536
  children: !hideSubmit ? jsx(GoAButton, {
8461
8537
  type: 'primary',
@@ -8464,7 +8540,7 @@ const RenderPages = props => {
8464
8540
  testId: "pages-submit-btn",
8465
8541
  children: "Submit"
8466
8542
  }) : null
8467
- })]
8543
+ })
8468
8544
  })
8469
8545
  })]
8470
8546
  })]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abgov/jsonforms-components",
3
- "version": "2.21.1",
3
+ "version": "2.21.3",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Government of Alberta - React renderers for JSON Forms based on the design system.",
6
6
  "repository": "https://github.com/GovAlta/adsp-monorepo",
@@ -18,6 +18,8 @@ export type StepperAction = {
18
18
  errors?: ErrorObject[];
19
19
  id: number;
20
20
  ajv: Ajv;
21
+ schema: any;
22
+ data: any;
21
23
  };
22
24
  } | {
23
25
  type: 'validate/form';
@@ -1,6 +1,6 @@
1
1
  import Ajv, { ErrorObject } from 'ajv';
2
2
  export declare const isErrorPathIncluded: (errorPaths: string[], path: string) => boolean;
3
- export declare const getIncompletePaths: (ajv: Ajv, scopes: string[]) => string[];
3
+ export declare const getIncompletePaths: (ajv: Ajv, schema: any, data: any, scopes: string[]) => string[];
4
4
  export declare const subErrorInParent: (error: ErrorObject, paths: string[]) => boolean;
5
5
  export declare const getErrorsInScopes: (errors: ErrorObject[], scopes: string[]) => ErrorObject[];
6
6
  export declare const hasDataInScopes: (data: object, scopes: string[]) => boolean;