@abgov/jsonforms-components 2.44.1 → 2.44.2

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
@@ -3177,7 +3177,6 @@ const checkFieldValidity = props => {
3177
3177
  errors: ajvErrors,
3178
3178
  required,
3179
3179
  label,
3180
- uischema,
3181
3180
  schema
3182
3181
  } = props;
3183
3182
  const labelToUpdate = label;
@@ -3561,7 +3560,8 @@ styled.div(_t$c || (_t$c = _$b`
3561
3560
  `));
3562
3561
  const Visible = styled.div(_t2$7 || (_t2$7 = _$b`
3563
3562
  display: ${0};
3564
- `), p => p.visible ? 'initial' : 'none');
3563
+ width: 100%;
3564
+ `), p => p.visible ? 'block' : 'none');
3565
3565
 
3566
3566
  const ADD_REGISTER_DATA_ACTION = 'jsonforms/register/data/add';
3567
3567
  const ADD_NO_ANONYMOUS_ACTION = 'jsonforms/register/no_anonymous';
@@ -5189,16 +5189,21 @@ let _$a = t => t,
5189
5189
  _t5$4,
5190
5190
  _t6$3,
5191
5191
  _t7$2,
5192
- _t8$2;
5192
+ _t8$2,
5193
+ _t9$2,
5194
+ _t0$2,
5195
+ _t1$2,
5196
+ _t10$2;
5193
5197
  const FormFieldWrapper = styled.div(_t$b || (_t$b = _$a`
5194
5198
  margin-bottom: var(--goa-space-l);
5195
5199
  `));
5196
5200
  const WarningIconDiv = styled.div(_t2$6 || (_t2$6 = _$a`
5197
- display: inline-flex;
5201
+ display: flex;
5198
5202
  align-items: flex-start;
5199
- gap: 0.25rem;
5200
- font-size: var(--goa-font-size-2);
5201
- color: var(--goa-color-interactive-error);
5203
+ gap: var(--goa-space-2xs);
5204
+ font: var(--goa-form-item-message-typography);
5205
+ color: var(--goa-form-item-error-message-color);
5206
+ margin-top: var(--goa-form-item-message-margin-top);
5202
5207
  `));
5203
5208
  const RequiredTextLabel = styled.label(_t3$5 || (_t3$5 = _$a`
5204
5209
  color: var(--goa-color-greyscale-700);
@@ -5219,15 +5224,39 @@ const PageReviewValueCol = styled.td(_t5$4 || (_t5$4 = _$a`
5219
5224
  text-align: left;
5220
5225
  vertical-align: top;
5221
5226
  `));
5227
+ const PageReviewContainer = styled.td(_t6$3 || (_t6$3 = _$a`
5228
+ padding: 12px 0px;
5229
+ border-bottom: 1px solid #ccc;
5230
+ width: 100%;
5231
+ vertical-align: top;
5232
+ `));
5233
+ const ReviewHeader = styled.div(_t7$2 || (_t7$2 = _$a`
5234
+ display: flex;
5235
+ justify-content: space-between;
5236
+ align-items: center;
5237
+ width: 100%;
5238
+ `));
5239
+ const ReviewLabel = styled.div(_t8$2 || (_t8$2 = _$a`
5240
+ font-weight: var(--goa-font-weight-bold);
5241
+ font-size: var(--goa-font-size-4);
5242
+ line-height: var(--goa-line-height-3);
5243
+ color: var(--goa-color-text-default);
5244
+ `));
5245
+ const ReviewValue = styled.div(_t9$2 || (_t9$2 = _$a`
5246
+ margin-top: var(--goa-space-m);
5247
+ color: var(--goa-color-text-default);
5248
+ font-size: var(--goa-font-size-4);
5249
+ line-height: var(--goa-line-height-3);
5250
+ `));
5222
5251
  //Check and unchecked are different heights otherwise
5223
- const CheckboxWrapper = styled.div(_t6$3 || (_t6$3 = _$a`
5252
+ const CheckboxWrapper = styled.div(_t0$2 || (_t0$2 = _$a`
5224
5253
  min-height: 28px;
5225
5254
  `));
5226
- styled.h4(_t7$2 || (_t7$2 = _$a`
5255
+ styled.h4(_t1$2 || (_t1$2 = _$a`
5227
5256
  margin: 0 0 0.25rem 0;
5228
5257
  fontsize: larger;
5229
5258
  `));
5230
- styled.h4(_t8$2 || (_t8$2 = _$a`
5259
+ styled.h4(_t10$2 || (_t10$2 = _$a`
5231
5260
  border-bottom: 1px solid #ddd;
5232
5261
  `));
5233
5262
 
@@ -6306,14 +6335,14 @@ const stepperReducer = (state, action) => {
6306
6335
  } = action.payload;
6307
6336
  ajv.validate(schema, data);
6308
6337
  const newCategories = state.categories.map(cat => {
6309
- var _ajv$errors;
6310
6338
  // ✅ compare against cat.id, not the index
6311
6339
  if (cat.id !== id) {
6312
6340
  return cat;
6313
6341
  }
6342
+ const filteredErrors = ajv.errors && ajv.errors.filter(error => (error == null ? void 0 : error.data) != null);
6314
6343
  const status = getStepStatus({
6315
6344
  scopes: cat.scopes,
6316
- errors: (_ajv$errors = ajv.errors) != null ? _ajv$errors : [],
6345
+ errors: filteredErrors != null ? filteredErrors : [],
6317
6346
  schema
6318
6347
  });
6319
6348
  return Object.assign({}, cat, {
@@ -6354,7 +6383,7 @@ const stepperReducer = (state, action) => {
6354
6383
  };
6355
6384
 
6356
6385
  const createStepperContextInitData = props => {
6357
- var _ajv$errors, _uischema$options, _uischema$options2, _categorization$eleme;
6386
+ var _uischema$options, _uischema$options2, _categorization$eleme;
6358
6387
  const {
6359
6388
  uischema,
6360
6389
  data,
@@ -6364,18 +6393,18 @@ const createStepperContextInitData = props => {
6364
6393
  path
6365
6394
  } = props;
6366
6395
  const categorization = uischema;
6396
+ const filteredErrors = ajv.errors && ajv.errors.filter(error => (error == null ? void 0 : error.data) != null);
6367
6397
  // run validation once, capture errors
6368
6398
  const valid = ajv.validate(schema, data || {});
6369
- (_ajv$errors = ajv.errors) != null ? _ajv$errors : [];
6370
6399
  const isPage = (uischema == null || (_uischema$options = uischema.options) == null ? void 0 : _uischema$options.variant) === 'pages';
6371
6400
  const isCacheStatus = (_uischema$options2 = uischema.options) == null ? void 0 : _uischema$options2.cacheStatus;
6372
6401
  isCacheStatus && getIsVisitFromLocalStorage() || [];
6373
6402
  const categories = (_categorization$eleme = categorization.elements) == null ? void 0 : _categorization$eleme.map((c, id) => {
6374
- var _ajv$errors2, _deriveLabelForUISche;
6403
+ var _deriveLabelForUISche;
6375
6404
  const scopes = pickPropertyValues(c, 'scope', 'ListWithDetail');
6376
6405
  const status = getStepStatus({
6377
6406
  scopes,
6378
- errors: (_ajv$errors2 = ajv.errors) != null ? _ajv$errors2 : [],
6407
+ errors: filteredErrors != null ? filteredErrors : [],
6379
6408
  schema
6380
6409
  });
6381
6410
  return {
@@ -8254,7 +8283,7 @@ const GoInputBaseReview = props => jsx(GoAInputBaseControl, Object.assign({}, pr
8254
8283
  const GoAInputBaseReviewControl = withJsonFormsControlProps(GoInputBaseReview);
8255
8284
 
8256
8285
  const GoAInputBaseTableReview = props => {
8257
- var _uischema$options3;
8286
+ var _uischema$options, _jsonForms$core, _activeError, _activeError2, _uischema$options4;
8258
8287
  const {
8259
8288
  data,
8260
8289
  uischema,
@@ -8263,23 +8292,28 @@ const GoAInputBaseTableReview = props => {
8263
8292
  path,
8264
8293
  errors,
8265
8294
  enabled,
8266
- cells
8295
+ cells,
8296
+ required
8267
8297
  } = props;
8268
8298
  const context = useContext(JsonFormsStepperContext);
8269
8299
  const jsonForms = useJsonForms();
8270
- const labelToUpdate = convertToSentenceCase(getLabelText(uischema.scope, label || ''));
8300
+ let labelToUpdate = (_uischema$options = uischema.options) != null && _uischema$options.reviewLabel ? uischema.options.reviewLabel : convertToSentenceCase(getLabelText(uischema.scope, label || ''));
8301
+ if (labelToUpdate === '') {
8302
+ const scopeName = uischema.scope ? getLastSegmentFromPointer(uischema.scope) : '';
8303
+ labelToUpdate = convertToSentenceCase(scopeName);
8304
+ }
8271
8305
  let reviewText = data;
8272
8306
  const isBoolean = typeof data === 'boolean';
8273
8307
  if (isBoolean) {
8274
- var _uischema$options, _uischema$options2;
8308
+ var _uischema$options2, _uischema$options3;
8275
8309
  let checkboxLabel = '';
8276
- if ((_uischema$options = uischema.options) != null && (_uischema$options = _uischema$options.text) != null && _uischema$options.trim()) {
8310
+ if ((_uischema$options2 = uischema.options) != null && (_uischema$options2 = _uischema$options2.text) != null && _uischema$options2.trim()) {
8277
8311
  checkboxLabel = uischema.options.text.trim();
8278
8312
  } else if (uischema.scope && uischema.scope.startsWith('#/')) {
8279
8313
  const fallbackLabel = getLastSegmentFromPointer(uischema.scope);
8280
8314
  checkboxLabel = fallbackLabel.charAt(0).toUpperCase() + fallbackLabel.slice(1);
8281
8315
  }
8282
- if (((_uischema$options2 = uischema.options) == null ? void 0 : _uischema$options2.radio) === true) {
8316
+ if (((_uischema$options3 = uischema.options) == null ? void 0 : _uischema$options3.radio) === true) {
8283
8317
  reviewText = data ? `Yes` : `No`;
8284
8318
  } else {
8285
8319
  if (label !== '' || typeof label === 'boolean') {
@@ -8289,34 +8323,76 @@ const GoAInputBaseTableReview = props => {
8289
8323
  }
8290
8324
  }
8291
8325
  }
8326
+ // Helper to extract errors manually from global state, bypassing "touched" filter
8327
+ const normalizePath = p => p.replace(/\[(\d+)\]/g, '.$1').replace(/^\./, '').replace(/\//g, '.');
8328
+ const findMatchingError = currentErrors => {
8329
+ if (!currentErrors) return undefined;
8330
+ const normalizedPropPath = normalizePath(path || '');
8331
+ for (const e of currentErrors) {
8332
+ var _e$params2;
8333
+ const errorPath = normalizePath(e.dataPath || e.instancePath || '');
8334
+ if (errorPath === normalizedPropPath) {
8335
+ return e.message;
8336
+ }
8337
+ if (e.keyword === 'required') {
8338
+ var _e$params;
8339
+ const missing = (_e$params = e.params) == null ? void 0 : _e$params.missingProperty;
8340
+ if (missing) {
8341
+ const missingPath = errorPath ? `${errorPath}.${missing}` : missing;
8342
+ if (missingPath === normalizedPropPath) {
8343
+ return e.message;
8344
+ }
8345
+ }
8346
+ }
8347
+ if (e.keyword === 'errorMessage' && (_e$params2 = e.params) != null && _e$params2.errors) {
8348
+ const nested = findMatchingError(e.params.errors);
8349
+ if (nested) return e.message;
8350
+ }
8351
+ }
8352
+ return undefined;
8353
+ };
8354
+ let activeError = findMatchingError((_jsonForms$core = jsonForms.core) == null ? void 0 : _jsonForms$core.errors);
8355
+ if (required && (data === undefined || data === null || data === '') && !activeError) {
8356
+ activeError = `${labelToUpdate} is required`;
8357
+ } else if ((_activeError = activeError) != null && _activeError.includes('is a required property') || (_activeError2 = activeError) != null && _activeError2.includes('must have required property')) {
8358
+ activeError = `${labelToUpdate} is required`;
8359
+ }
8292
8360
  // eslint-disable-next-line
8293
- const stepId = (_uischema$options3 = uischema.options) == null ? void 0 : _uischema$options3.stepId;
8294
- return jsxs("tr", {
8361
+ const stepId = (_uischema$options4 = uischema.options) == null ? void 0 : _uischema$options4.stepId;
8362
+ return jsx("tr", {
8295
8363
  "data-testid": `input-base-table-${label}-row`,
8296
- children: [jsx(PageReviewNameCol, {
8297
- children: labelToUpdate && jsx("strong", {
8298
- children: labelToUpdate
8299
- })
8300
- }), jsx(PageReviewValueCol, {
8301
- children: typeof reviewText === 'string' || typeof reviewText === 'number' ? jsx("div", {
8302
- children: reviewText
8303
- }) : jsx(JsonFormsDispatch, {
8304
- "data-testid": `jsonforms-object-list-defined-elements-dispatch`,
8305
- schema: schema,
8306
- uischema: uischema,
8307
- enabled: enabled,
8308
- renderers: jsonForms.renderers,
8309
- cells: cells
8310
- })
8311
- }), jsx("td", {
8312
- className: "goa-table-number-col",
8313
- children: stepId !== undefined && jsx(GoabButton, {
8314
- type: "tertiary",
8315
- size: "compact",
8316
- onClick: () => context == null ? void 0 : context.goToPage(stepId),
8317
- children: "Change"
8318
- })
8319
- })]
8364
+ children: jsxs(PageReviewContainer, {
8365
+ colSpan: 3,
8366
+ children: [jsxs(ReviewHeader, {
8367
+ children: [jsxs(ReviewLabel, {
8368
+ children: [labelToUpdate, required && jsx(RequiredTextLabel, {
8369
+ children: " (required)"
8370
+ })]
8371
+ }), stepId !== undefined && jsx(GoabButton, {
8372
+ type: "tertiary",
8373
+ size: "compact",
8374
+ onClick: () => context == null ? void 0 : context.goToPage(stepId),
8375
+ children: "Change"
8376
+ })]
8377
+ }), jsxs(ReviewValue, {
8378
+ children: [typeof reviewText === 'string' || typeof reviewText === 'number' ? jsx("div", {
8379
+ "data-testid": `review-value-${label}`,
8380
+ children: reviewText
8381
+ }) : jsx(JsonFormsDispatch, {
8382
+ "data-testid": `jsonforms-object-list-defined-elements-dispatch`,
8383
+ schema: schema,
8384
+ uischema: uischema,
8385
+ enabled: enabled,
8386
+ renderers: jsonForms.renderers,
8387
+ cells: cells
8388
+ }), activeError && jsxs(WarningIconDiv, {
8389
+ children: [jsx(GoabIcon, {
8390
+ type: "warning",
8391
+ size: "small"
8392
+ }), activeError]
8393
+ })]
8394
+ })]
8395
+ })
8320
8396
  });
8321
8397
  };
8322
8398
  const GoAInputBaseTableReviewControl = withJsonFormsControlProps(GoAInputBaseTableReview);
@@ -9125,28 +9201,48 @@ const FullNameControlReview = props => {
9125
9201
  var _props$uischema, _props$data, _props$data2, _props$data3, _props$data4;
9126
9202
  const context = useContext(JsonFormsStepperContext);
9127
9203
  const stepId = (_props$uischema = props.uischema) == null || (_props$uischema = _props$uischema.options) == null ? void 0 : _props$uischema.stepId;
9128
- const renderRow = (label, value, testId) => jsxs("tr", {
9129
- children: [jsx(PageReviewNameCol, {
9130
- children: jsx("strong", {
9131
- children: label
9132
- })
9133
- }), jsx(PageReviewValueCol, {
9134
- children: jsx("div", {
9135
- "data-testid": testId,
9136
- children: value
9137
- })
9138
- }), jsx("td", {
9139
- className: "goa-table-width-limit",
9140
- children: jsx(GoabButton, {
9141
- type: "tertiary",
9142
- size: "compact",
9143
- onClick: () => context == null ? void 0 : context.goToPage(stepId),
9144
- children: "Change"
9145
- })
9146
- })]
9204
+ const {
9205
+ label,
9206
+ errors,
9207
+ required
9208
+ } = props;
9209
+ const renderRow = (label, value, testId) => jsx("tr", {
9210
+ children: jsxs(PageReviewContainer, {
9211
+ colSpan: 3,
9212
+ children: [jsxs(ReviewHeader, {
9213
+ children: [jsx(ReviewLabel, {
9214
+ children: label
9215
+ }), jsx(GoabButton, {
9216
+ type: "tertiary",
9217
+ size: "compact",
9218
+ onClick: () => context == null ? void 0 : context.goToPage(stepId),
9219
+ children: "Change"
9220
+ })]
9221
+ }), jsx(ReviewValue, {
9222
+ children: jsx("div", {
9223
+ "data-testid": testId,
9224
+ children: value
9225
+ })
9226
+ })]
9227
+ })
9147
9228
  });
9148
9229
  return jsxs(Fragment, {
9149
- children: [renderRow('First name', (_props$data = props.data) == null ? void 0 : _props$data.firstName, `firstName-control-${props.id}`), ((_props$data2 = props.data) == null ? void 0 : _props$data2.middleName) && renderRow('Middle name', (_props$data3 = props.data) == null ? void 0 : _props$data3.middleName, `middleName-control-${props.id}`), renderRow('Last name', (_props$data4 = props.data) == null ? void 0 : _props$data4.lastName, `lastName-control-${props.id}`)]
9230
+ children: [jsx("tr", {
9231
+ "data-testid": "full-name-header",
9232
+ children: jsxs(PageReviewContainer, {
9233
+ colSpan: 3,
9234
+ children: [jsxs(ReviewLabel, {
9235
+ children: [label, required && jsx(RequiredTextLabel, {
9236
+ children: " (required)"
9237
+ })]
9238
+ }), errors && jsxs(WarningIconDiv, {
9239
+ children: [jsx(GoabIcon, {
9240
+ type: "warning",
9241
+ size: "small"
9242
+ }), errors != null && errors.includes('is a required property') ? `${label} is required` : errors]
9243
+ })]
9244
+ })
9245
+ }), renderRow('First name', (_props$data = props.data) == null ? void 0 : _props$data.firstName, `firstName-control-${props.id}`), ((_props$data2 = props.data) == null ? void 0 : _props$data2.middleName) && renderRow('Middle name', (_props$data3 = props.data) == null ? void 0 : _props$data3.middleName, `middleName-control-${props.id}`), renderRow('Last name', (_props$data4 = props.data) == null ? void 0 : _props$data4.lastName, `lastName-control-${props.id}`)]
9150
9246
  });
9151
9247
  };
9152
9248
  const GoAInputBaseFullNameControlReview = withJsonFormsAllOfProps(FullNameControlReview);
@@ -9673,9 +9769,10 @@ const renderCellColumn = ({
9673
9769
  });
9674
9770
  };
9675
9771
  if (data === undefined && isRequired || error !== '' && error !== undefined) {
9676
- return renderWarningCell(data);
9772
+ const message = error || (isRequired && data === undefined ? 'Required' : data);
9773
+ return renderWarningCell(message);
9677
9774
  } else if (data !== undefined && isRequired && error) {
9678
- return renderWarningCell(data);
9775
+ return renderWarningCell(error);
9679
9776
  }
9680
9777
  const path = `/${rowPath}/${index}/${element}/${index === 0 ? index : index - 1}`;
9681
9778
  const nestedErrors = errors == null ? void 0 : errors.filter(e => e.instancePath.includes(path));
@@ -9685,6 +9782,10 @@ const renderCellColumn = ({
9685
9782
  } else if (typeof data === 'object' || Array.isArray(data)) {
9686
9783
  const result = Object.keys(data);
9687
9784
  if (!isRequired && nestedErrors.length === 0) {
9785
+ if ('year' in data && 'month' in data && 'day' in data) {
9786
+ const dateObj = data;
9787
+ return `${dateObj.year}-${dateObj.month}-${dateObj.day}`;
9788
+ }
9688
9789
  return jsx("pre", {
9689
9790
  children: JSON.stringify(data, null, 2)
9690
9791
  });
@@ -9761,8 +9862,11 @@ const EmptyList$1 = ({
9761
9862
  numColumns,
9762
9863
  noDataMessage,
9763
9864
  translations
9764
- }) => jsx(GoabGrid, {
9765
- minChildWidth: "30ch",
9865
+ }) => jsx("div", {
9866
+ style: {
9867
+ width: '100%',
9868
+ padding: '1rem 0'
9869
+ },
9766
9870
  children: jsx(TextCenter, {
9767
9871
  children: jsx("b", {
9768
9872
  children: noDataMessage
@@ -9814,6 +9918,11 @@ const NonEmptyCellComponent$1 = /*#__PURE__*/React.memo(function NonEmptyCellCom
9814
9918
  properties && Object.keys(properties).forEach(item => {
9815
9919
  if (Object.keys(tableKeys).includes(item)) {
9816
9920
  tempTableKeys[item] = tableKeys[item];
9921
+ } else {
9922
+ // If the property is not in the tableKeys (e.g. it was a nested object in the UI schema),
9923
+ // we still need a header for it to maintain alignment.
9924
+ // Use the property title from the schema, or capitalize the property name.
9925
+ tempTableKeys[item] = properties[item].title || capitalizeFirstLetter(item);
9817
9926
  }
9818
9927
  });
9819
9928
  tableKeys = tempTableKeys;
@@ -9864,6 +9973,10 @@ const NonEmptyCellComponent$1 = /*#__PURE__*/React.memo(function NonEmptyCellCom
9864
9973
  }, 0)
9865
9974
  }), jsx("tbody", {
9866
9975
  children: range(count || 0).map((num, i) => {
9976
+ // Skip rendering empty rows in review mode
9977
+ if (isInReview === true && (data === undefined || data[num] === undefined || Object.keys(data[num]).length === 0)) {
9978
+ return null;
9979
+ }
9867
9980
  const errorRow = errors == null ? void 0 : errors.find(error => error.instancePath.includes(`/${props.rowPath.replace(/\./g, '/')}/${i}`));
9868
9981
  return jsxs("tr", {
9869
9982
  children: [Object.keys(properties).map((element, ix) => {
@@ -9889,7 +10002,7 @@ const NonEmptyCellComponent$1 = /*#__PURE__*/React.memo(function NonEmptyCellCom
9889
10002
  display: 'block'
9890
10003
  },
9891
10004
  children: renderCellColumn({
9892
- data: currentData ? String(currentData) : undefined,
10005
+ data: currentData !== '' && currentData !== null && currentData !== undefined ? currentData : undefined,
9893
10006
  error: error == null ? void 0 : error.message,
9894
10007
  isRequired: (_required$includes = required == null ? void 0 : required.includes(tableKeys[element])) != null ? _required$includes : false,
9895
10008
  errors: errors !== undefined ? errors : [],
@@ -10008,7 +10121,11 @@ const NonEmptyRowComponent$1 = ({
10008
10121
  handleChange
10009
10122
  }) => {
10010
10123
  return jsx("div", {
10011
- children: enabled ? jsx(GoabContainer, {
10124
+ children: enabled ? isInReview ? jsx("div", {
10125
+ children: jsx("div", {
10126
+ children: GenerateRows$1(NonEmptyCell$1, schema, childPath, enabled, openDeleteDialog, handleChange, cells, uischema, isInReview, count, data)
10127
+ })
10128
+ }) : jsx(GoabContainer, {
10012
10129
  children: jsx("div", {
10013
10130
  children: jsx("div", {
10014
10131
  children: GenerateRows$1(NonEmptyCell$1, schema, childPath, enabled, openDeleteDialog, handleChange, cells, uischema, isInReview, count, data)
@@ -10062,11 +10179,12 @@ const ObjectArrayList$1 = ({
10062
10179
  }, 0);
10063
10180
  };
10064
10181
  const ObjectArrayControl = props => {
10065
- var _uischema$options5, _registers$categories, _registers$categories2;
10182
+ var _uischema$options5, _registers$categories3, _registers$categories4;
10066
10183
  const [registers, dispatch] = useReducer(objectListReducer, initialState);
10067
10184
  const [open, setOpen] = useState(false);
10068
10185
  const [rowData, setRowData] = useState(0);
10069
10186
  const [maxItemsError, setMaxItemsError] = useState('');
10187
+ const context = useContext(JsonFormsStepperContext);
10070
10188
  const {
10071
10189
  label,
10072
10190
  path,
@@ -10197,22 +10315,70 @@ const ObjectArrayControl = props => {
10197
10315
  const listTitle = label || ((_uischema$options5 = uischema.options) == null ? void 0 : _uischema$options5.title);
10198
10316
  const isInReview = isStepperReview === true;
10199
10317
  const isListWithDetail = controlElement.type === 'ListWithDetail';
10200
- return jsxs(Visible, {
10318
+ if (isInReview) {
10319
+ var _uischema$options6, _registers$categories, _registers$categories2;
10320
+ return jsx("tr", {
10321
+ children: jsxs(PageReviewContainer, {
10322
+ colSpan: 3,
10323
+ children: [listTitle ? isListWithDetail && additionalProps.required && (data === null || data === undefined) ? jsx("b", {
10324
+ children: jsxs(ListWithDetailWarningIconDiv, {
10325
+ children: [jsx(GoabIcon, {
10326
+ type: "warning",
10327
+ title: "warning",
10328
+ size: "small",
10329
+ theme: "filled",
10330
+ ml: "2xs",
10331
+ mt: "2xs"
10332
+ }), listTitle, " is required."]
10333
+ })
10334
+ }) : jsxs(ReviewHeader, {
10335
+ style: {
10336
+ width: '100%',
10337
+ display: 'grid',
10338
+ gridTemplateColumns: '1fr auto',
10339
+ alignItems: 'center'
10340
+ },
10341
+ children: [jsxs(ReviewLabel, {
10342
+ children: [listTitle, " ", jsx("span", {
10343
+ children: additionalProps.required && '(required)'
10344
+ }), maxItemsError && jsx("span", {
10345
+ style: {
10346
+ color: 'red',
10347
+ marginLeft: '1rem'
10348
+ },
10349
+ children: maxItemsError
10350
+ })]
10351
+ }), ((_uischema$options6 = uischema.options) == null ? void 0 : _uischema$options6.stepId) !== undefined && jsx(GoabButton, {
10352
+ type: "tertiary",
10353
+ size: "compact",
10354
+ onClick: () => {
10355
+ var _uischema$options7;
10356
+ return context == null ? void 0 : context.goToPage((_uischema$options7 = uischema.options) == null ? void 0 : _uischema$options7.stepId);
10357
+ },
10358
+ children: "Change"
10359
+ })]
10360
+ }) : null, jsx(ObjectArrayList$1, Object.assign({
10361
+ path: path,
10362
+ schema: schema,
10363
+ uischema: uischema,
10364
+ enabled: enabled,
10365
+ openDeleteDialog: openDeleteDialog,
10366
+ translations: {},
10367
+ count: ((_registers$categories = registers.categories[path]) == null ? void 0 : _registers$categories.count) || Object.keys(data || []).length,
10368
+ data: data || ((_registers$categories2 = registers.categories[path]) == null ? void 0 : _registers$categories2.data),
10369
+ cells: cells,
10370
+ config: config,
10371
+ isInReview: isInReview,
10372
+ handleChange: handleChangeWithData
10373
+ }, additionalProps))]
10374
+ })
10375
+ });
10376
+ }
10377
+ const content = jsxs(Visible, {
10201
10378
  visible: visible,
10202
10379
  "data-testid": "jsonforms-object-list-wrapper",
10203
10380
  children: [jsxs(ToolBarHeader, {
10204
- children: [isInReview ? listTitle ? isListWithDetail && additionalProps.required && (data === null || data === undefined) ? jsx("b", {
10205
- children: jsxs(ListWithDetailWarningIconDiv, {
10206
- children: [jsx(GoabIcon, {
10207
- type: "warning",
10208
- title: "warning",
10209
- size: "small",
10210
- theme: "filled",
10211
- ml: "2xs",
10212
- mt: "2xs"
10213
- }), listTitle, " is required."]
10214
- })
10215
- }) : jsxs("b", {
10381
+ children: [listTitle && jsxs(ObjectArrayTitle, {
10216
10382
  children: [listTitle, " ", jsx("span", {
10217
10383
  children: additionalProps.required && '(required)'
10218
10384
  }), maxItemsError && jsx("span", {
@@ -10222,17 +10388,7 @@ const ObjectArrayControl = props => {
10222
10388
  },
10223
10389
  children: maxItemsError
10224
10390
  })]
10225
- }) : null : listTitle && jsxs(ObjectArrayTitle, {
10226
- children: [listTitle, " ", jsx("span", {
10227
- children: additionalProps.required && '(required)'
10228
- }), maxItemsError && jsx("span", {
10229
- style: {
10230
- color: 'red',
10231
- marginLeft: '1rem'
10232
- },
10233
- children: maxItemsError
10234
- })]
10235
- }), !isInReview && jsx(ObjectArrayToolBar, {
10391
+ }), jsx(ObjectArrayToolBar, {
10236
10392
  errors: errors,
10237
10393
  label: label,
10238
10394
  addItem: (a, b) => () => addItem(a, b),
@@ -10251,8 +10407,8 @@ const ObjectArrayControl = props => {
10251
10407
  enabled: enabled,
10252
10408
  openDeleteDialog: openDeleteDialog,
10253
10409
  translations: {},
10254
- count: ((_registers$categories = registers.categories[path]) == null ? void 0 : _registers$categories.count) || Object.keys(data || []).length,
10255
- data: data || ((_registers$categories2 = registers.categories[path]) == null ? void 0 : _registers$categories2.data),
10410
+ count: ((_registers$categories3 = registers.categories[path]) == null ? void 0 : _registers$categories3.count) || Object.keys(data || []).length,
10411
+ data: data || ((_registers$categories4 = registers.categories[path]) == null ? void 0 : _registers$categories4.data),
10256
10412
  cells: cells,
10257
10413
  config: config,
10258
10414
  isInReview: isInReview,
@@ -10266,6 +10422,7 @@ const ObjectArrayControl = props => {
10266
10422
  })]
10267
10423
  })]
10268
10424
  });
10425
+ return content;
10269
10426
  };
10270
10427
 
10271
10428
  const ArrayControl = props => {
@@ -10298,16 +10455,14 @@ const ArrayControlReview = props => {
10298
10455
  const {
10299
10456
  visible
10300
10457
  } = props;
10301
- return jsx(Visible, {
10302
- visible: visible,
10303
- children: jsx(ObjectArrayControl, Object.assign({
10304
- arraySchema: {}
10305
- }, props, {
10306
- addItem: () => () => {},
10307
- isStepperReview: true,
10308
- enabled: true
10309
- }))
10310
- });
10458
+ if (!visible) return null;
10459
+ return jsx(ObjectArrayControl, Object.assign({
10460
+ arraySchema: {}
10461
+ }, props, {
10462
+ addItem: () => () => {},
10463
+ isStepperReview: true,
10464
+ enabled: true
10465
+ }));
10311
10466
  };
10312
10467
  const GoAArrayControlRenderer = withJsonFormsControlProps(ArrayControlBase);
10313
10468
  const GoAArrayControlReviewRenderer = withJsonFormsControlProps(ArrayControlReview);
@@ -10831,7 +10986,6 @@ const LeftTab = ({
10831
10986
  children: [jsx(TabName, {
10832
10987
  children: name
10833
10988
  }), enabled ? jsx(Trash, {
10834
- role: "trash button",
10835
10989
  children: jsx(GoabIconButton, {
10836
10990
  disabled: !enabled,
10837
10991
  icon: "trash",
@@ -11479,8 +11633,10 @@ const AddressLoopUpControlTableReview = props => {
11479
11633
  const {
11480
11634
  data,
11481
11635
  schema,
11482
- uischema
11636
+ uischema,
11637
+ path
11483
11638
  } = props;
11639
+ const jsonForms = useJsonForms();
11484
11640
  // eslint-disable-next-line
11485
11641
  const stepId = (_uischema$options = uischema.options) == null ? void 0 : _uischema$options.stepId;
11486
11642
  const formStepperCtx = useContext(JsonFormsStepperContext);
@@ -11526,36 +11682,80 @@ const AddressLoopUpControlTableReview = props => {
11526
11682
  label: 'Yukon'
11527
11683
  }];
11528
11684
  const provinceLabel = isAlbertaAddress ? 'Alberta' : ((_provinces$find = provinces.find(p => p.value === (data == null ? void 0 : data.subdivisionCode))) == null ? void 0 : _provinces$find.label) || (data == null ? void 0 : data.subdivisionCode);
11529
- const renderRow = (label, value) => jsxs("tr", {
11530
- children: [jsx(PageReviewNameCol, {
11531
- children: label
11532
- }), jsx(PageReviewNameCol, {
11533
- children: value
11534
- }), jsx("td", {
11535
- className: "goa-table-width-limit",
11536
- children: jsx(GoabButton, {
11537
- type: "tertiary",
11538
- size: "compact",
11539
- onClick: () => formStepperCtx == null ? void 0 : formStepperCtx.goToPage(stepId),
11540
- children: "Change"
11685
+ const getError = propName => {
11686
+ var _findMatchingError, _jsonForms$core;
11687
+ const normalizePath = p => p.replace(/\[(\d+)\]/g, '.$1').replace(/^\./, '').replace(/\//g, '.');
11688
+ // We need to return the message of the MATCHED error, but findError above returns boolean (mostly) or message if I refactor.
11689
+ // Let's refactor to return the error object or message.
11690
+ const findMatchingError = errors => {
11691
+ if (!errors) return undefined;
11692
+ for (const e of errors) {
11693
+ var _e$params, _e$params2;
11694
+ const rawErrorPath = e.dataPath || e.instancePath || '';
11695
+ const errorPath = normalizePath(rawErrorPath);
11696
+ const currentPath = normalizePath(path || '');
11697
+ const dotPath = currentPath ? `${currentPath}.${propName}` : propName;
11698
+ if (e.keyword === 'errorMessage' && (_e$params = e.params) != null && _e$params.errors) {
11699
+ const nested = findMatchingError(e.params.errors);
11700
+ if (nested) return e; // Return the wrapper error (contains the custom message)
11701
+ }
11702
+ if (errorPath === dotPath) return e;
11703
+ const isRequiredError = e.keyword === 'required';
11704
+ const missingProperty = (_e$params2 = e.params) == null ? void 0 : _e$params2.missingProperty;
11705
+ if (isRequiredError && missingProperty === propName) {
11706
+ if (errorPath === currentPath) return e;
11707
+ }
11708
+ }
11709
+ return undefined;
11710
+ };
11711
+ return (_findMatchingError = findMatchingError((_jsonForms$core = jsonForms.core) == null ? void 0 : _jsonForms$core.errors)) == null ? void 0 : _findMatchingError.message;
11712
+ };
11713
+ const isRequired = propName => {
11714
+ var _schema$required;
11715
+ return schema == null || (_schema$required = schema.required) == null ? void 0 : _schema$required.includes(propName);
11716
+ };
11717
+ const renderRow = (label, value, propName, showButton = true) => {
11718
+ var _error, _error2;
11719
+ let error = getError(propName);
11720
+ const required = isRequired(propName);
11721
+ if (required && !value && !error) {
11722
+ error = `${label} is required`;
11723
+ }
11724
+ return jsx("tr", {
11725
+ children: jsxs(PageReviewContainer, {
11726
+ colSpan: 3,
11727
+ children: [jsxs(ReviewHeader, {
11728
+ children: [jsxs(ReviewLabel, {
11729
+ children: [label, required && jsx(RequiredTextLabel, {
11730
+ children: " (required)"
11731
+ })]
11732
+ }), showButton && jsx(GoabButton, {
11733
+ type: "tertiary",
11734
+ size: "compact",
11735
+ onClick: () => formStepperCtx == null ? void 0 : formStepperCtx.goToPage(stepId),
11736
+ children: "Change"
11737
+ })]
11738
+ }), jsxs(ReviewValue, {
11739
+ children: [value, error && jsxs(WarningIconDiv, {
11740
+ children: [jsx(GoabIcon, {
11741
+ type: "warning",
11742
+ size: "small"
11743
+ }), (_error = error) != null && _error.includes('is a required property') || (_error2 = error) != null && _error2.includes('required property') ? `${label} is required` : error]
11744
+ })]
11745
+ })]
11541
11746
  })
11542
- })]
11543
- });
11747
+ });
11748
+ };
11544
11749
  return jsxs(Fragment, {
11545
- children: [jsxs("tr", {
11750
+ children: [jsx("tr", {
11546
11751
  "data-testid": "address-lookup-table-review",
11547
- children: [jsx(PageReviewNameCol, {
11548
- children: jsx("strong", {
11752
+ children: jsx(PageReviewContainer, {
11753
+ colSpan: 3,
11754
+ children: jsx(ReviewLabel, {
11549
11755
  children: `${isAlbertaAddress ? 'Alberta' : 'Canada'} postal address`
11550
11756
  })
11551
- }), jsx("td", {
11552
- style: {
11553
- verticalAlign: 'top'
11554
- }
11555
- }), jsx("td", {
11556
- className: "goa-table-width-limit"
11557
- })]
11558
- }), renderRow('Address line 1', data == null ? void 0 : data.addressLine1), (data == null ? void 0 : data.addressLine2) && renderRow('Address line 2', data.addressLine2), renderRow('City', data == null ? void 0 : data.municipality), renderRow('Postal Code', data == null ? void 0 : data.postalCode), renderRow('Province', provinceLabel), renderRow('Country', 'Canada')]
11757
+ })
11758
+ }), renderRow('Address line 1', data == null ? void 0 : data.addressLine1, 'addressLine1'), (data == null ? void 0 : data.addressLine2) && renderRow('Address line 2', data.addressLine2, 'addressLine2'), renderRow('City', data == null ? void 0 : data.municipality, 'municipality'), renderRow('Postal Code', data == null ? void 0 : data.postalCode, 'postalCode'), renderRow('Province', provinceLabel, 'subdivisionCode'), renderRow('Country', 'Canada', 'country', false)]
11559
11759
  });
11560
11760
  };
11561
11761
 
@@ -12167,10 +12367,10 @@ const GoABaseTableReviewRenderers$1 = [
12167
12367
  renderer: GoAInputBaseTableReviewControl
12168
12368
  }, {
12169
12369
  tester: GoAArrayControlTester,
12170
- renderer: GoAInputBaseTableReviewControl
12370
+ renderer: GoAArrayControlReviewRenderer
12171
12371
  }, {
12172
12372
  tester: GoAListWithDetailsTester,
12173
- renderer: GoAInputBaseTableReviewControl
12373
+ renderer: GoAArrayControlReviewRenderer
12174
12374
  }, {
12175
12375
  tester: FullNameDobTester,
12176
12376
  renderer: GoAInputBaseTableReviewControl
@@ -12189,6 +12389,9 @@ const GoABaseTableReviewRenderers$1 = [
12189
12389
  }, {
12190
12390
  tester: HelpContentTester,
12191
12391
  renderer: EmptyHelpContentRenderer
12392
+ }, {
12393
+ tester: GoACalloutControlTester,
12394
+ renderer: CalloutReviewControl
12192
12395
  }];
12193
12396
  [
12194
12397
  // controls
@@ -12236,10 +12439,10 @@ const GoABaseTableReviewRenderers$1 = [
12236
12439
  renderer: GoAInputBaseReviewControl
12237
12440
  }, {
12238
12441
  tester: GoAArrayControlTester,
12239
- renderer: GoAInputBaseTableReviewControl // Array might still need table or custom grid
12442
+ renderer: GoAArrayControlReviewRenderer // Array might still need table or custom grid
12240
12443
  }, {
12241
12444
  tester: GoAListWithDetailsTester,
12242
- renderer: GoAInputBaseTableReviewControl // List with details is complex
12445
+ renderer: GoAArrayControlReviewRenderer // List with details is complex
12243
12446
  }, {
12244
12447
  tester: AddressLookUpTester,
12245
12448
  renderer: withJsonFormsControlProps(AddressLookUpControlReview)
@@ -12255,6 +12458,9 @@ const GoABaseTableReviewRenderers$1 = [
12255
12458
  }, {
12256
12459
  tester: HelpContentTester,
12257
12460
  renderer: EmptyHelpContentRenderer
12461
+ }, {
12462
+ tester: GoACalloutControlTester,
12463
+ renderer: CalloutReviewControl
12258
12464
  }];
12259
12465
  const FormStepperReviewer = props => {
12260
12466
  var _uischema$options$com, _uischema$options, _componentProps$readO;
@@ -12275,43 +12481,61 @@ const FormStepperReviewer = props => {
12275
12481
  return jsx(ReviewItem, {
12276
12482
  children: categories.map((category, categoryIndex) => {
12277
12483
  const categoryLabel = category.label || category.i18n || 'Unknown Category';
12484
+ const hasVisibleContent = element => {
12485
+ if (!isVisible(element, data, '', ajv, undefined)) {
12486
+ return false;
12487
+ }
12488
+ if (element.type === 'HelpContent' || element.type === 'Callout') {
12489
+ return false;
12490
+ }
12491
+ if (element.elements && Array.isArray(element.elements)) {
12492
+ return element.elements.some(child => hasVisibleContent(child));
12493
+ }
12494
+ return true;
12495
+ };
12496
+ const elementsToRender = category.elements
12497
+ //eslint-disable-next-line
12498
+ .filter(field => {
12499
+ var _field$rule;
12500
+ if (!hasVisibleContent(field)) {
12501
+ return false;
12502
+ }
12503
+ const conditionProps = (_field$rule = field.rule) == null ? void 0 : _field$rule.condition;
12504
+ /* istanbul ignore next */
12505
+ if (conditionProps && data) {
12506
+ var _conditionProps$scope;
12507
+ const canHideControlParts = conditionProps == null || (_conditionProps$scope = conditionProps.scope) == null ? void 0 : _conditionProps$scope.split('/');
12508
+ const canHideControl = canHideControlParts && canHideControlParts[(canHideControlParts == null ? void 0 : canHideControlParts.length) - 1];
12509
+ const isHidden = getProperty(data, canHideControl);
12510
+ if (!isHidden) {
12511
+ return field;
12512
+ }
12513
+ return false;
12514
+ }
12515
+ return true;
12516
+ }).map(e => {
12517
+ const layout = e;
12518
+ if (rescopeMaps.some(scope => {
12519
+ var _layout$elements;
12520
+ return (_layout$elements = layout.elements) == null ? void 0 : _layout$elements.map(el => {
12521
+ const element = el;
12522
+ return element.scope;
12523
+ }).includes(scope);
12524
+ })) {
12525
+ return layout.elements;
12526
+ } else {
12527
+ return e;
12528
+ }
12529
+ }).flat();
12530
+ if (elementsToRender.length === 0) {
12531
+ return null;
12532
+ }
12278
12533
  return jsxs(ReviewItemSection, {
12279
12534
  children: [jsx(ReviewItemHeader, {
12280
12535
  children: jsx(ReviewItemTitle, {
12281
12536
  children: categoryLabel
12282
12537
  })
12283
- }), category.elements
12284
- //eslint-disable-next-line
12285
- .filter(field => {
12286
- var _field$rule;
12287
- // [TODO] we need to double check why we cannot hide the elements at the element level
12288
- const conditionProps = (_field$rule = field.rule) == null ? void 0 : _field$rule.condition;
12289
- /* istanbul ignore next */
12290
- if (conditionProps && data) {
12291
- var _conditionProps$scope;
12292
- const canHideControlParts = conditionProps == null || (_conditionProps$scope = conditionProps.scope) == null ? void 0 : _conditionProps$scope.split('/');
12293
- const canHideControl = canHideControlParts && canHideControlParts[(canHideControlParts == null ? void 0 : canHideControlParts.length) - 1];
12294
- const isHidden = getProperty(data, canHideControl);
12295
- if (!isHidden) {
12296
- return field;
12297
- }
12298
- } else {
12299
- return field;
12300
- }
12301
- }).map(e => {
12302
- const layout = e;
12303
- if (rescopeMaps.some(scope => {
12304
- var _layout$elements;
12305
- return (_layout$elements = layout.elements) == null ? void 0 : _layout$elements.map(el => {
12306
- const element = el;
12307
- return element.scope;
12308
- }).includes(scope);
12309
- })) {
12310
- return layout.elements;
12311
- } else {
12312
- return e;
12313
- }
12314
- }).flat().map((element, elementIndex) => {
12538
+ }), elementsToRender.map((element, elementIndex) => {
12315
12539
  const stepperElement = Object.assign({}, element);
12316
12540
  stepperElement.options = Object.assign({}, stepperElement.options, {
12317
12541
  stepId: categoryIndex
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abgov/jsonforms-components",
3
- "version": "2.44.1",
3
+ "version": "2.44.2",
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",
@@ -3,6 +3,10 @@ export declare const WarningIconDiv: import("styled-components/dist/types").ISty
3
3
  export declare const RequiredTextLabel: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").LabelHTMLAttributes<HTMLLabelElement>, HTMLLabelElement>, never>> & string;
4
4
  export declare const PageReviewNameCol: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").TdHTMLAttributes<HTMLTableDataCellElement>, HTMLTableDataCellElement>, never>> & string;
5
5
  export declare const PageReviewValueCol: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").TdHTMLAttributes<HTMLTableDataCellElement>, HTMLTableDataCellElement>, never>> & string;
6
+ export declare const PageReviewContainer: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").TdHTMLAttributes<HTMLTableDataCellElement>, HTMLTableDataCellElement>, never>> & string;
7
+ export declare const ReviewHeader: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
8
+ export declare const ReviewLabel: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
9
+ export declare const ReviewValue: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
6
10
  export declare const CheckboxWrapper: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
7
11
  export declare const H4Large: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLHeadingElement>, HTMLHeadingElement>, never>> & string;
8
12
  export declare const Row: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLHeadingElement>, HTMLHeadingElement>, never>> & string;
@@ -4,6 +4,6 @@ export type CombinedProps = ControlProps & ArrayLayoutProps;
4
4
  export declare const ArrayControl: (props: CombinedProps) => import("react/jsx-runtime").JSX.Element;
5
5
  export declare const GoAArrayControlTester: RankedTester;
6
6
  export declare const ArrayControlBase: (props: ControlProps) => import("react/jsx-runtime").JSX.Element;
7
- export declare const ArrayControlReview: (props: ControlProps) => import("react/jsx-runtime").JSX.Element;
7
+ export declare const ArrayControlReview: (props: ControlProps) => import("react/jsx-runtime").JSX.Element | null;
8
8
  export declare const GoAArrayControlRenderer: React.ComponentType<import("@jsonforms/core").OwnPropsOfControl>;
9
9
  export declare const GoAArrayControlReviewRenderer: React.ComponentType<import("@jsonforms/core").OwnPropsOfControl>;