@abgov/jsonforms-components 2.67.6 → 2.67.8

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
@@ -1,22 +1,23 @@
1
- import * as runtime from 'react/jsx-runtime';
2
1
  import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
3
2
  import React, { useContext, useReducer, useMemo, useEffect, createContext, useCallback, useRef, useState, useLayoutEffect } from 'react';
4
- import { GoabFormItem, GoabDropdown, GoabDropdownItem, GoabInput, GoabTextArea, GoabCallout, GoabRadioGroup, GoabRadioItem, GoabCheckbox, GoabIcon, GoabButton, GoabGrid, GoabIconButton, GoabTable, GoabModal, GoabButtonGroup, GoabContainer, GoabDetails, GoabFormStepper, GoabFormStep, GoabPages, GoabBadge, GoabText, GoabFileUploadInput, GoabCircularProgress, GoabSpinner } from '@abgov/react-components';
3
+ import { GoabFormItem, GoabDropdown, GoabDropdownItem, GoabInput, GoabTextArea, GoabCallout, GoabRadioGroup, GoabRadioItem, GoabCheckbox, GoabIcon, GoabButton, GoabTable, GoabGrid, GoabIconButton, GoabModal, GoabButtonGroup, GoabContainer, GoabDetails, GoabFormStepper, GoabFormStep, GoabPages, GoabBadge, GoabText, GoabFileUploadInput, GoabCircularProgress, GoabSpinner } from '@abgov/react-components';
5
4
  import Ajv from 'ajv';
6
5
  import styled from 'styled-components';
7
6
  import axios from 'axios';
8
7
  import get$1 from 'lodash/get';
9
8
  import { isVisible, isEnabled, deriveLabelForUISchemaElement, rankWith, isStringControl, and, optionIs, isDateControl, isNumberControl, isIntegerControl, isDateTimeControl, isTimeControl, uiTypeIs, isControl as isControl$1, isEnumControl, or, isOneOfEnumControl, isBooleanControl, createDefaultValue, Paths, Resolve, toDataPath, schemaTypeIs, formatIs, getAjv, schemaMatches, isObjectArrayControl, isPrimitiveArrayControl, composePaths, hasType, isCategorization, isLayout, INIT, UPDATE_CORE } from '@jsonforms/core';
10
9
  import * as _$c from 'lodash';
11
- import ___default, { isObject as isObject$i, isEmpty as isEmpty$1 } from 'lodash';
10
+ import ___default, { isEmpty, isObject as isObject$i } from 'lodash';
12
11
  import { useJsonForms, withJsonFormsControlProps, withJsonFormsEnumProps, withTranslateProps, JsonFormsDispatch, withJsonFormsAllOfProps, withJsonFormsArrayLayoutProps, withJsonFormsLayoutProps, withJsonFormsCellProps } from '@jsonforms/react';
13
12
  import dompurify from 'dompurify';
14
13
  import * as xss from 'xss';
15
14
  import merge from 'lodash/merge';
16
- import isEmpty from 'lodash/isEmpty';
15
+ import isEmpty$1 from 'lodash/isEmpty';
17
16
  import range from 'lodash/range';
18
17
  import pluralize from 'pluralize';
19
- import { evaluateSync, compileSync } from '@mdx-js/mdx';
18
+ import { compileSync } from '@mdx-js/mdx';
19
+ import ReactMarkdown from 'react-markdown';
20
+ import rehypeSanitize, { defaultSchema } from 'rehype-sanitize';
20
21
  import { Parser } from 'expr-eval-fork';
21
22
  import addErrors from 'ajv-errors';
22
23
  import addFormats from 'ajv-formats';
@@ -7269,6 +7270,16 @@ const ADDRESS_LOOKUP_LABELS = {
7269
7270
  subdivisionCode: 'Province',
7270
7271
  country: 'Country'
7271
7272
  };
7273
+ const VALIDATION_KEYWORDS = {
7274
+ REQUIRED: 'required',
7275
+ MIN_LENGTH: 'minLength',
7276
+ MAX_LENGTH: 'maxLength',
7277
+ FORMAT: 'format',
7278
+ MINIMUM: 'minimum',
7279
+ MAXIMUM: 'maximum',
7280
+ TYPE: 'type',
7281
+ ERROR_MESSAGE: 'errorMessage'
7282
+ };
7272
7283
  const getAddressLookupFieldLabel = fieldName => {
7273
7284
  return ADDRESS_LOOKUP_LABELS[fieldName] || fieldName;
7274
7285
  };
@@ -9108,6 +9119,195 @@ const ObjectArrayToolBar = /*#__PURE__*/React.memo(function TableToolbar({
9108
9119
  });
9109
9120
  });
9110
9121
 
9122
+ const jsonPreviewStyle = {
9123
+ display: 'block',
9124
+ width: '100%',
9125
+ boxSizing: 'border-box',
9126
+ margin: 0,
9127
+ padding: 0,
9128
+ whiteSpace: 'pre-wrap',
9129
+ textAlign: 'left',
9130
+ overflowX: 'auto'
9131
+ };
9132
+ function prettify(prop) {
9133
+ return prop.replace(/([A-Z])/g, ' $1').replace(/[_-]/g, ' ').replace(/^./, c => c.toUpperCase()).trim();
9134
+ }
9135
+ /**
9136
+ * Extract Json data schema name attribute and the ui schema label name.
9137
+ * @param obj
9138
+ * @param names
9139
+ * @returns A key value of the data attribute name and the uiSchema label value
9140
+ */
9141
+ const extractNames = (obj, names = {}) => {
9142
+ if (Array.isArray(obj)) {
9143
+ obj.forEach(item => extractNames(item, names));
9144
+ } else if (typeof obj === 'object' && obj !== null) {
9145
+ const typedObj = obj;
9146
+ if (typeof typedObj.scope === 'string') {
9147
+ const parts = typedObj.scope.split('/');
9148
+ const key = parts[parts.length - 1];
9149
+ if (typeof typedObj.label === 'string' && typedObj.label.trim()) {
9150
+ names[key] = typedObj.label;
9151
+ } else if (typeof typedObj.label === 'object' && typedObj.label !== null && 'text' in typedObj.label && typeof typedObj.label.text === 'string' && typedObj.label.text.trim()) {
9152
+ names[key] = typedObj.label.text;
9153
+ } else {
9154
+ names[key] = prettify(key);
9155
+ }
9156
+ }
9157
+ Object.values(typedObj).forEach(value => extractNames(value, names));
9158
+ }
9159
+ return names;
9160
+ };
9161
+ function getHeaderLabel(headName, itemsSchema, columnLabels) {
9162
+ if (columnLabels != null && columnLabels[headName]) {
9163
+ return columnLabels[headName];
9164
+ }
9165
+ const fieldSchema = itemsSchema == null ? void 0 : itemsSchema[headName];
9166
+ if (fieldSchema && typeof fieldSchema.title === 'string' && fieldSchema.title.trim()) {
9167
+ return fieldSchema.title;
9168
+ }
9169
+ return prettify(headName);
9170
+ }
9171
+ const DataTable = ({
9172
+ itemsSchema,
9173
+ data,
9174
+ columnLabels
9175
+ }) => {
9176
+ var _Object$keys;
9177
+ return jsxs(GoabTable, {
9178
+ width: "100%",
9179
+ children: [jsx("thead", {
9180
+ children: jsx("tr", {
9181
+ children: itemsSchema && ((_Object$keys = Object.keys(itemsSchema)) == null ? void 0 : _Object$keys.map((headNames, ix) => {
9182
+ return jsx("th", {
9183
+ children: getHeaderLabel(headNames, itemsSchema, columnLabels)
9184
+ }, ix);
9185
+ }))
9186
+ })
9187
+ }), jsx("tbody", {
9188
+ children: data.map((obj, index) => jsx("tr", {
9189
+ children: itemsSchema && Object.keys(itemsSchema).map((headNames, ix) => {
9190
+ return jsx("td", {
9191
+ children: obj[headNames]
9192
+ }, ix);
9193
+ })
9194
+ }, index))
9195
+ })]
9196
+ });
9197
+ };
9198
+ const isObjectArrayEmpty = currentData => {
9199
+ const result = isEmpty(currentData) || JSON.stringify(currentData) === '[{}]';
9200
+ return result;
9201
+ };
9202
+ const renderNoneGivenText = data => {
9203
+ return !data ? jsxs(Fragment, {
9204
+ children: [jsx(NoneGivenTableText, {
9205
+ children: "(none given)"
9206
+ }), jsx("br", {})]
9207
+ }) : data;
9208
+ };
9209
+ const renderCellColumn = ({
9210
+ data,
9211
+ error,
9212
+ errors,
9213
+ index,
9214
+ rowPath,
9215
+ element,
9216
+ isRequired
9217
+ }) => {
9218
+ const renderWarningCell = error => {
9219
+ return jsxs(HilightCellWarning, {
9220
+ children: [renderNoneGivenText(data), error && jsxs(ObjectArrayWarningIconDiv, {
9221
+ children: [jsx(GoabIcon, {
9222
+ type: "warning",
9223
+ title: "warning",
9224
+ size: "small",
9225
+ theme: "filled",
9226
+ mt: "2xs"
9227
+ }), error ? error : '']
9228
+ })]
9229
+ });
9230
+ };
9231
+ if (data === undefined && isRequired || error !== '' && error !== undefined) {
9232
+ const message = error || (isRequired && data === undefined ? 'Required' : data);
9233
+ return renderWarningCell(message);
9234
+ } else if (data === undefined && !isRequired) {
9235
+ return renderWarningCell('');
9236
+ } else if (data !== undefined && isRequired && error) {
9237
+ return renderWarningCell(error);
9238
+ }
9239
+ const path = `/${rowPath}/${index}/${element}/${index === 0 ? index : index - 1}`;
9240
+ const nestedErrors = errors == null ? void 0 : errors.filter(e => e.instancePath.includes(path));
9241
+ /* istanbul ignore next */
9242
+ if (typeof data === 'boolean') {
9243
+ return data ? 'Yes' : 'No';
9244
+ } else if (typeof data === 'number') {
9245
+ return String(data);
9246
+ } else if (typeof data === 'string') {
9247
+ return data;
9248
+ } else if (typeof data === 'object' || Array.isArray(data)) {
9249
+ const result = Object.keys(data);
9250
+ if (!isRequired && nestedErrors.length === 0) {
9251
+ if ('year' in data && 'month' in data && ('day' in data || 'date' in data)) {
9252
+ const dateObj = data;
9253
+ const dayValue = 'day' in dateObj ? dateObj.day : dateObj.date;
9254
+ return `${dateObj.year}-${dateObj.month}-${dayValue}`;
9255
+ }
9256
+ return jsx("pre", {
9257
+ style: jsonPreviewStyle,
9258
+ children: JSON.stringify(data, null, 2)
9259
+ });
9260
+ } else if (result.length === 0) {
9261
+ return renderWarningCell();
9262
+ } else if (result.length > 0 && (isObjectArrayEmpty(data) || nestedErrors.length > 0)) {
9263
+ return jsx("pre", {
9264
+ style: jsonPreviewStyle,
9265
+ children: renderWarningCell(JSON.stringify(data, null, 2))
9266
+ });
9267
+ } else if (data !== undefined && result.length > 0 && error !== '' && error !== undefined) {
9268
+ const values = Object.values(data);
9269
+ if (values && values.length > 0) {
9270
+ return jsx("pre", {
9271
+ style: jsonPreviewStyle,
9272
+ children: renderWarningCell(JSON.stringify(values.at(0), null, 2))
9273
+ });
9274
+ }
9275
+ } else {
9276
+ const firstRow = Array.isArray(data) ? data[0] : undefined;
9277
+ const columnLabels = extractNames(firstRow);
9278
+ return jsx(DataTable, {
9279
+ itemsSchema: data[0],
9280
+ data: data,
9281
+ columnLabels: columnLabels
9282
+ });
9283
+ }
9284
+ }
9285
+ return null;
9286
+ };
9287
+ const createHumanizeError = (error, schema, uischema) => {
9288
+ let humanMessage;
9289
+ if (error) {
9290
+ try {
9291
+ humanMessage = humanizeAjvError(error, schema, uischema);
9292
+ if (typeof humanMessage === 'string' && (humanMessage.includes('must have required property') || humanMessage.includes(REQUIRED_PROPERTY_ERROR))) {
9293
+ const propertyMatch = humanMessage.match(/'([^']+)'/);
9294
+ if (propertyMatch && propertyMatch[1]) {
9295
+ humanMessage = prettify(propertyMatch[1]) + ' is required';
9296
+ }
9297
+ }
9298
+ } catch (err) {
9299
+ const raw = error.message;
9300
+ const propertyMatch = raw == null ? void 0 : raw.match(/'([^']+)'/);
9301
+ if (propertyMatch && propertyMatch[1]) {
9302
+ humanMessage = prettify(propertyMatch[1]) + ' is required';
9303
+ } else {
9304
+ humanMessage = raw;
9305
+ }
9306
+ }
9307
+ }
9308
+ return humanMessage;
9309
+ };
9310
+
9111
9311
  const _excluded$5 = ["label", "path", "schema", "rootSchema", "uischema", "errors", "openDeleteDialog", "visible", "enabled", "cells", "data", "config"];
9112
9312
  const getItemsTitle = schema => {
9113
9313
  const items = schema == null ? void 0 : schema.items;
@@ -9243,12 +9443,10 @@ const NonEmptyCellComponent$1 = /*#__PURE__*/React.memo(function NonEmptyCellCom
9243
9443
  var _uischema$elements3, _uischema$options0, _uiSchemaElementsForN;
9244
9444
  const {
9245
9445
  schema,
9246
- errors,
9247
9446
  enabled,
9248
9447
  renderers,
9249
9448
  cells,
9250
9449
  rowPath,
9251
- isValid,
9252
9450
  uischema
9253
9451
  } = props;
9254
9452
  const propNames = getValidColumnProps$1(schema);
@@ -9327,7 +9525,7 @@ const NonEmptyCellComponent$1 = /*#__PURE__*/React.memo(function NonEmptyCellCom
9327
9525
  const NonEmptyCell$1 = ownProps => {
9328
9526
  const ctx = useJsonForms();
9329
9527
  const emptyCellProps = ctxToNonEmptyCellProps$1(ctx, ownProps);
9330
- const isValid = isEmpty(emptyCellProps.errors);
9528
+ const isValid = isEmpty$1(emptyCellProps.errors);
9331
9529
  return jsx(NonEmptyCellComponent$1, Object.assign({}, emptyCellProps, {
9332
9530
  isValid: isValid
9333
9531
  }));
@@ -9376,12 +9574,9 @@ function getValue(obj, path) {
9376
9574
  return undefined;
9377
9575
  }, obj);
9378
9576
  }
9379
- function prettify$1(prop) {
9380
- return prop.replace(/([A-Z])/g, ' $1').replace(/[_-]/g, ' ').replace(/^./, c => c.toUpperCase());
9381
- }
9382
9577
  function findLabelForPath(path, uiSchema, schema) {
9383
9578
  const propertyKey = path.split('.').pop() || path;
9384
- const fallbackLabel = prettify$1(propertyKey);
9579
+ const fallbackLabel = prettify(propertyKey);
9385
9580
  if (!uiSchema) {
9386
9581
  return fallbackLabel;
9387
9582
  }
@@ -9572,7 +9767,7 @@ function resolveLabel(instancePath, schema, uischema) {
9572
9767
  if (resolvedSchema != null && resolvedSchema.title) {
9573
9768
  return resolvedSchema.title;
9574
9769
  }
9575
- return prettify$1(prop || 'Unknown field');
9770
+ return prettify(prop || 'Unknown field');
9576
9771
  }
9577
9772
  function ajvPathToSchemaPath(instancePath) {
9578
9773
  const parts = instancePath.split('/').filter(Boolean);
@@ -9603,15 +9798,6 @@ function findControlLabel(uischema, scope) {
9603
9798
  }
9604
9799
  return;
9605
9800
  }
9606
- const VALIDATION_KEYWORDS = {
9607
- REQUIRED: 'required',
9608
- MIN_LENGTH: 'minLength',
9609
- MAX_LENGTH: 'maxLength',
9610
- FORMAT: 'format',
9611
- MINIMUM: 'minimum',
9612
- MAXIMUM: 'maximum',
9613
- TYPE: 'type'
9614
- };
9615
9801
  function humanizeAjvError(error, schema, uischema) {
9616
9802
  var _error$message;
9617
9803
  const path = getEffectiveInstancePath(error);
@@ -9728,9 +9914,9 @@ const MainTab = ({
9728
9914
  const rowData = getDataAtPath(core == null ? void 0 : core.data, childPath);
9729
9915
  function resolveField(e) {
9730
9916
  var _e$params;
9731
- if (e.keyword === 'required') {
9917
+ if (e.keyword === VALIDATION_KEYWORDS.REQUIRED) {
9732
9918
  return e.params.missingProperty;
9733
- } else if (e.keyword === 'errorMessage' && (_e$params = e.params) != null && _e$params.errors[0].params.missingProperty) {
9919
+ } else if (e.keyword === VALIDATION_KEYWORDS.ERROR_MESSAGE && (_e$params = e.params) != null && _e$params.errors[0].params.missingProperty) {
9734
9920
  return e.params.errors[0].params.missingProperty;
9735
9921
  }
9736
9922
  const path = e.instancePath.split('/');
@@ -9740,22 +9926,22 @@ const MainTab = ({
9740
9926
  const fieldErrors = core == null || (_core$errors = core.errors) == null ? void 0 : _core$errors.filter(e => e.instancePath === rowBase || e.instancePath.startsWith(rowBase + '/')).reduce((acc, e) => {
9741
9927
  var _e$params2;
9742
9928
  const field = resolveField(e);
9743
- if (e.keyword === 'errorMessage' && (_e$params2 = e.params) != null && _e$params2.errors) {
9929
+ if (e.keyword === VALIDATION_KEYWORDS.ERROR_MESSAGE && (_e$params2 = e.params) != null && _e$params2.errors) {
9744
9930
  const nestedErrors = e.params.errors;
9745
9931
  if (field) {
9746
9932
  try {
9747
- acc.fields[field] = nestedErrors.map(ne => humanizeAjvError(ne, core.schema, core.uischema)).join(', ');
9933
+ acc.fields[field] = e.message ? e.message : nestedErrors.map(ne => humanizeAjvError(ne, core.schema, core.uischema)).join(', ');
9748
9934
  } catch (err) {
9749
9935
  var _nestedErrors$;
9750
9936
  // Fallback: if nestedErrors contain a missingProperty, use it
9751
9937
  const missingFromNested = nestedErrors == null || (_nestedErrors$ = nestedErrors[0]) == null || (_nestedErrors$ = _nestedErrors$.params) == null ? void 0 : _nestedErrors$.missingProperty;
9752
9938
  if (missingFromNested) {
9753
- acc.fields[field] = prettify$1(missingFromNested) + ' is required';
9939
+ acc.fields[field] = prettify(missingFromNested) + ' is required';
9754
9940
  } else {
9755
9941
  const raw = e.message;
9756
9942
  if (raw && (raw.includes('must have required property') || raw.includes(REQUIRED_PROPERTY_ERROR))) {
9757
9943
  const m = raw.match(/'([^']+)'/);
9758
- if (m && m[1]) acc.fields[field] = prettify$1(m[1]) + ' is required';else acc.fields[field] = raw;
9944
+ if (m && m[1]) acc.fields[field] = prettify(m[1]) + ' is required';else acc.fields[field] = raw;
9759
9945
  } else {
9760
9946
  acc.fields[field] = raw || 'Unknown error';
9761
9947
  }
@@ -9768,12 +9954,12 @@ const MainTab = ({
9768
9954
  var _nestedErrors$2;
9769
9955
  const missingFromNested = nestedErrors == null || (_nestedErrors$2 = nestedErrors[0]) == null || (_nestedErrors$2 = _nestedErrors$2.params) == null ? void 0 : _nestedErrors$2.missingProperty;
9770
9956
  if (missingFromNested) {
9771
- acc.row = prettify$1(missingFromNested) + ' is required';
9957
+ acc.row = prettify(missingFromNested) + ' is required';
9772
9958
  } else {
9773
9959
  const raw = e == null ? void 0 : e.message;
9774
9960
  if (raw && (raw.includes('must have required property') || raw.includes(REQUIRED_PROPERTY_ERROR))) {
9775
9961
  const m = raw.match(/'([^']+)'/);
9776
- if (m && m[1]) acc.row = prettify$1(m[1]) + ' is required';else acc.row = raw;
9962
+ if (m && m[1]) acc.row = prettify(m[1]) + ' is required';else acc.row = raw;
9777
9963
  } else {
9778
9964
  acc.row = raw || 'Unknown error';
9779
9965
  }
@@ -9787,7 +9973,7 @@ const MainTab = ({
9787
9973
  if (typeof msg === 'string' && (msg.includes('must have required property') || msg.includes(REQUIRED_PROPERTY_ERROR))) {
9788
9974
  const propertyMatch = msg.match(/'([^']+)'/);
9789
9975
  if (propertyMatch && propertyMatch[1]) {
9790
- msg = prettify$1(propertyMatch[1]) + ' is required';
9976
+ msg = prettify(propertyMatch[1]) + ' is required';
9791
9977
  }
9792
9978
  }
9793
9979
  acc.fields[field] = msg;
@@ -10603,7 +10789,7 @@ const LayoutRenderer = ({
10603
10789
  visible,
10604
10790
  width
10605
10791
  }) => {
10606
- if (isEmpty(elements)) {
10792
+ if (isEmpty$1(elements)) {
10607
10793
  return null;
10608
10794
  } else {
10609
10795
  if (direction === 'row') {
@@ -10633,7 +10819,7 @@ const ReviewLayoutRenderer = ({
10633
10819
  visible,
10634
10820
  width
10635
10821
  }) => {
10636
- if (isEmpty(elements)) {
10822
+ if (isEmpty$1(elements)) {
10637
10823
  return null;
10638
10824
  } else {
10639
10825
  if (direction === 'row') {
@@ -11940,195 +12126,6 @@ const DeleteDialog = /*#__PURE__*/React.memo(function DeleteDialog({
11940
12126
  }, 1);
11941
12127
  });
11942
12128
 
11943
- const jsonPreviewStyle = {
11944
- display: 'block',
11945
- width: '100%',
11946
- boxSizing: 'border-box',
11947
- margin: 0,
11948
- padding: 0,
11949
- whiteSpace: 'pre-wrap',
11950
- textAlign: 'left',
11951
- overflowX: 'auto'
11952
- };
11953
- function prettify(prop) {
11954
- return prop.replace(/([A-Z])/g, ' $1').replace(/[_-]/g, ' ').replace(/^./, c => c.toUpperCase()).trim();
11955
- }
11956
- /**
11957
- * Extract Json data schema name attribute and the ui schema label name.
11958
- * @param obj
11959
- * @param names
11960
- * @returns A key value of the data attribute name and the uiSchema label value
11961
- */
11962
- const extractNames = (obj, names = {}) => {
11963
- if (Array.isArray(obj)) {
11964
- obj.forEach(item => extractNames(item, names));
11965
- } else if (typeof obj === 'object' && obj !== null) {
11966
- const typedObj = obj;
11967
- if (typeof typedObj.scope === 'string') {
11968
- const parts = typedObj.scope.split('/');
11969
- const key = parts[parts.length - 1];
11970
- if (typeof typedObj.label === 'string' && typedObj.label.trim()) {
11971
- names[key] = typedObj.label;
11972
- } else if (typeof typedObj.label === 'object' && typedObj.label !== null && 'text' in typedObj.label && typeof typedObj.label.text === 'string' && typedObj.label.text.trim()) {
11973
- names[key] = typedObj.label.text;
11974
- } else {
11975
- names[key] = prettify(key);
11976
- }
11977
- }
11978
- Object.values(typedObj).forEach(value => extractNames(value, names));
11979
- }
11980
- return names;
11981
- };
11982
- function getHeaderLabel(headName, itemsSchema, columnLabels) {
11983
- if (columnLabels != null && columnLabels[headName]) {
11984
- return columnLabels[headName];
11985
- }
11986
- const fieldSchema = itemsSchema == null ? void 0 : itemsSchema[headName];
11987
- if (fieldSchema && typeof fieldSchema.title === 'string' && fieldSchema.title.trim()) {
11988
- return fieldSchema.title;
11989
- }
11990
- return prettify(headName);
11991
- }
11992
- const DataTable = ({
11993
- itemsSchema,
11994
- data,
11995
- columnLabels
11996
- }) => {
11997
- var _Object$keys;
11998
- return jsxs(GoabTable, {
11999
- width: "100%",
12000
- children: [jsx("thead", {
12001
- children: jsx("tr", {
12002
- children: itemsSchema && ((_Object$keys = Object.keys(itemsSchema)) == null ? void 0 : _Object$keys.map((headNames, ix) => {
12003
- return jsx("th", {
12004
- children: getHeaderLabel(headNames, itemsSchema, columnLabels)
12005
- }, ix);
12006
- }))
12007
- })
12008
- }), jsx("tbody", {
12009
- children: data.map((obj, index) => jsx("tr", {
12010
- children: itemsSchema && Object.keys(itemsSchema).map((headNames, ix) => {
12011
- return jsx("td", {
12012
- children: obj[headNames]
12013
- }, ix);
12014
- })
12015
- }, index))
12016
- })]
12017
- });
12018
- };
12019
- const isObjectArrayEmpty = currentData => {
12020
- const result = isEmpty$1(currentData) || JSON.stringify(currentData) === '[{}]';
12021
- return result;
12022
- };
12023
- const renderNoneGivenText = data => {
12024
- return !data ? jsxs(Fragment, {
12025
- children: [jsx(NoneGivenTableText, {
12026
- children: "(none given)"
12027
- }), jsx("br", {})]
12028
- }) : data;
12029
- };
12030
- const renderCellColumn = ({
12031
- data,
12032
- error,
12033
- errors,
12034
- index,
12035
- rowPath,
12036
- element,
12037
- isRequired
12038
- }) => {
12039
- const renderWarningCell = error => {
12040
- return jsxs(HilightCellWarning, {
12041
- children: [renderNoneGivenText(data), error && jsxs(ObjectArrayWarningIconDiv, {
12042
- children: [jsx(GoabIcon, {
12043
- type: "warning",
12044
- title: "warning",
12045
- size: "small",
12046
- theme: "filled",
12047
- mt: "2xs"
12048
- }), error ? error : '']
12049
- })]
12050
- });
12051
- };
12052
- if (data === undefined && isRequired || error !== '' && error !== undefined) {
12053
- const message = error || (isRequired && data === undefined ? 'Required' : data);
12054
- return renderWarningCell(message);
12055
- } else if (data === undefined && !isRequired) {
12056
- return renderWarningCell('');
12057
- } else if (data !== undefined && isRequired && error) {
12058
- return renderWarningCell(error);
12059
- }
12060
- const path = `/${rowPath}/${index}/${element}/${index === 0 ? index : index - 1}`;
12061
- const nestedErrors = errors == null ? void 0 : errors.filter(e => e.instancePath.includes(path));
12062
- /* istanbul ignore next */
12063
- if (typeof data === 'boolean') {
12064
- return data ? 'Yes' : 'No';
12065
- } else if (typeof data === 'number') {
12066
- return String(data);
12067
- } else if (typeof data === 'string') {
12068
- return data;
12069
- } else if (typeof data === 'object' || Array.isArray(data)) {
12070
- const result = Object.keys(data);
12071
- if (!isRequired && nestedErrors.length === 0) {
12072
- if ('year' in data && 'month' in data && ('day' in data || 'date' in data)) {
12073
- const dateObj = data;
12074
- const dayValue = 'day' in dateObj ? dateObj.day : dateObj.date;
12075
- return `${dateObj.year}-${dateObj.month}-${dayValue}`;
12076
- }
12077
- return jsx("pre", {
12078
- style: jsonPreviewStyle,
12079
- children: JSON.stringify(data, null, 2)
12080
- });
12081
- } else if (result.length === 0) {
12082
- return renderWarningCell();
12083
- } else if (result.length > 0 && (isObjectArrayEmpty(data) || nestedErrors.length > 0)) {
12084
- return jsx("pre", {
12085
- style: jsonPreviewStyle,
12086
- children: renderWarningCell(JSON.stringify(data, null, 2))
12087
- });
12088
- } else if (data !== undefined && result.length > 0 && error !== '' && error !== undefined) {
12089
- const values = Object.values(data);
12090
- if (values && values.length > 0) {
12091
- return jsx("pre", {
12092
- style: jsonPreviewStyle,
12093
- children: renderWarningCell(JSON.stringify(values.at(0), null, 2))
12094
- });
12095
- }
12096
- } else {
12097
- const firstRow = Array.isArray(data) ? data[0] : undefined;
12098
- const columnLabels = extractNames(firstRow);
12099
- return jsx(DataTable, {
12100
- itemsSchema: data[0],
12101
- data: data,
12102
- columnLabels: columnLabels
12103
- });
12104
- }
12105
- }
12106
- return null;
12107
- };
12108
- const createHumanizeError = (error, schema, uischema) => {
12109
- let humanMessage;
12110
- if (error) {
12111
- try {
12112
- humanMessage = humanizeAjvError(error, schema, uischema);
12113
- if (typeof humanMessage === 'string' && (humanMessage.includes('must have required property') || humanMessage.includes(REQUIRED_PROPERTY_ERROR))) {
12114
- const propertyMatch = humanMessage.match(/'([^']+)'/);
12115
- if (propertyMatch && propertyMatch[1]) {
12116
- humanMessage = prettify(propertyMatch[1]) + ' is required';
12117
- }
12118
- }
12119
- } catch (err) {
12120
- const raw = error.message;
12121
- const propertyMatch = raw == null ? void 0 : raw.match(/'([^']+)'/);
12122
- if (propertyMatch && propertyMatch[1]) {
12123
- humanMessage = prettify(propertyMatch[1]) + ' is required';
12124
- } else {
12125
- humanMessage = raw;
12126
- }
12127
- }
12128
- }
12129
- return humanMessage;
12130
- };
12131
-
12132
12129
  const _excluded$4 = ["label", "path", "schema", "rootSchema", "uischema", "errors", "visible", "enabled", "cells", "data", "config", "isStepperReview", "handleChange", "removeItems"];
12133
12130
  const GenerateRows = (Cell, schema, rowPath, enabled, openDeleteDialog, handleChange, cells, uischema, isInReview, count, data, errors) => {
12134
12131
  if ((schema == null ? void 0 : schema.type) === 'object') {
@@ -12458,7 +12455,7 @@ const NonEmptyCell = ownProps => {
12458
12455
  const emptyCellProps = ctxToNonEmptyCellProps(ctx, Object.assign({}, ownProps, {
12459
12456
  data
12460
12457
  }));
12461
- const isValid = isEmpty(emptyCellProps.errors);
12458
+ const isValid = isEmpty$1(emptyCellProps.errors);
12462
12459
  return jsx(NonEmptyCellComponent, Object.assign({}, emptyCellProps, {
12463
12460
  handleChange: ownProps == null ? void 0 : ownProps.handleChange,
12464
12461
  isInReview: ownProps == null ? void 0 : ownProps.isInReview,
@@ -13734,13 +13731,24 @@ const RenderLink = props => {
13734
13731
  });
13735
13732
  };
13736
13733
 
13737
- const _excluded$3 = ["isParent", "showLabel"];
13734
+ const _excluded$3 = ["node"],
13735
+ _excluded2 = ["isParent", "showLabel"];
13738
13736
  const markdownComponents = {
13739
- a: props => jsx("a", Object.assign({}, props, {
13740
- target: "_blank",
13741
- rel: "noopener noreferrer"
13742
- }))
13737
+ // Destructure node out (react-markdown internal prop) so it is not forwarded to the DOM element.
13738
+ a: _ref => {
13739
+ let props = _objectWithoutPropertiesLoose(_ref, _excluded$3);
13740
+ return jsx("a", Object.assign({}, props, {
13741
+ target: "_blank",
13742
+ rel: "noopener noreferrer"
13743
+ }));
13744
+ }
13743
13745
  };
13746
+ // rehype-sanitize strips dangerous HTML (script tags, event-handler attributes, javascript: hrefs, etc.)
13747
+ // from the HAST tree before rendering. defaultSchema allows standard HTML but blocks XSS vectors.
13748
+ // Cast required: react-markdown vendors its own copy of unified, causing a type mismatch with the
13749
+ // top-level unified package even though the runtime behaviour is identical.
13750
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
13751
+ const rehypePlugins = [[rehypeSanitize, defaultSchema]];
13744
13752
  const HelpContentReviewComponent = () => {
13745
13753
  return jsx(Fragment, {
13746
13754
  children: " "
@@ -13750,7 +13758,11 @@ const checkMarkDownIsValid = markdown => {
13750
13758
  let isValid = true;
13751
13759
  let error = '';
13752
13760
  try {
13753
- compileSync(markdown, {});
13761
+ // clean-code-ignore: 2.14
13762
+ // to allow testing the compile and catching the error
13763
+ compileSync(markdown, {
13764
+ rehypePlugins: [[rehypeSanitize, defaultSchema]]
13765
+ });
13754
13766
  } catch (err) {
13755
13767
  if (err instanceof Error) {
13756
13768
  error = err.message;
@@ -13768,26 +13780,23 @@ const MarkdownComponent = ({
13768
13780
  }) => {
13769
13781
  const response = checkMarkDownIsValid(markdown);
13770
13782
  if (response.isValid) {
13771
- const {
13772
- default: MDXContent
13773
- } = evaluateSync(markdown, Object.assign({}, runtime, {
13774
- Fragment: React.Fragment
13775
- }));
13776
- return /*#__PURE__*/React.createElement(MDXContent, {
13777
- components: markdownComponents
13783
+ return jsx(ReactMarkdown, {
13784
+ rehypePlugins: rehypePlugins,
13785
+ components: markdownComponents,
13786
+ children: markdown
13778
13787
  });
13779
13788
  }
13780
13789
  return jsxs(InvalidMarkdown, {
13781
13790
  children: ["Help content markdown is invalid: ", response.error, " "]
13782
13791
  });
13783
13792
  };
13784
- const HelpContentComponent = _ref => {
13793
+ const HelpContentComponent = _ref2 => {
13785
13794
  var _uischema$options, _uischema$options$mar, _uischema$options2, _uischema$options3, _uischema$options4, _uischema$options5, _uischema$options6, _uischema$options7, _uischema$options1, _uischema$options10, _uischema$options11, _uischema$options12, _uischema$options13, _uischema$options14, _uischema$options15, _uischema$options16, _uischema$options17, _uischema$elements2, _uischema$options18;
13786
13795
  let {
13787
13796
  isParent = true,
13788
13797
  showLabel = true
13789
- } = _ref,
13790
- props = _objectWithoutPropertiesLoose(_ref, _excluded$3);
13798
+ } = _ref2,
13799
+ props = _objectWithoutPropertiesLoose(_ref2, _excluded2);
13791
13800
  const labelClass = isParent ? 'parent-label' : 'child-label';
13792
13801
  const marginClass = isParent ? 'parent-margin' : 'child-margin';
13793
13802
  // eslint-disable-next-line
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abgov/jsonforms-components",
3
- "version": "2.67.6",
3
+ "version": "2.67.8",
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",
@@ -17,7 +17,9 @@
17
17
  "ajv-formats": "^3.0.1",
18
18
  "@mdx-js/mdx": "^3.1.0",
19
19
  "expr-eval-fork": "^3.0.1",
20
- "pluralize": "^8.0.0"
20
+ "pluralize": "^8.0.0",
21
+ "rehype-sanitize": "^6.0.0",
22
+ "react-markdown": "^8.0.3"
21
23
  },
22
24
  "dependencies": {
23
25
  "axios": "^1.15.2",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": "1.0.0",
3
- "generatedAt": "2026-06-23T21:16:03.119Z",
4
- "sourceCommit": "a83b527a2f034d3e3d4699630165799b4f644517",
3
+ "generatedAt": "2026-06-25T21:22:05.583Z",
4
+ "sourceCommit": "a25b638498bc63728b41889ca6e86a9972cfde8a",
5
5
  "sourcePath": "libs/jsonforms-components/src/index.ts",
6
6
  "rendererCount": 33,
7
7
  "renderers": [
@@ -1,8 +1,7 @@
1
1
  import React from 'react';
2
2
  import { RankedTester } from '@jsonforms/core';
3
3
  import { ControlProps, ControlElement } from '@jsonforms/core';
4
- import * as runtime from 'react/jsx-runtime';
5
- import './HelpContent.css';
4
+ import './HelpContent';
6
5
  interface OptionProps {
7
6
  ariaLabel?: string;
8
7
  help?: string | string[];
@@ -29,7 +28,9 @@ interface MdxMarkdown {
29
28
  markdown: string;
30
29
  }
31
30
  export declare const markdownComponents: {
32
- a: (props: React.AnchorHTMLAttributes<HTMLAnchorElement>) => runtime.JSX.Element;
31
+ a: ({ node, ...props }: React.AnchorHTMLAttributes<HTMLAnchorElement> & {
32
+ node?: unknown;
33
+ }) => import("react/jsx-runtime").JSX.Element;
33
34
  };
34
35
  export declare const MarkdownComponent: ({ markdown }: MdxMarkdown) => JSX.Element;
35
36
  export declare const HelpContentComponent: ({ isParent, showLabel, ...props }: CustomControlProps & ExtraHelpContentProps) => JSX.Element;
@@ -1,26 +1,10 @@
1
+ import { ArrayLayoutProps, ControlElement, JsonSchema, JsonFormsCellRendererRegistryEntry, ArrayTranslations, UISchemaElement } from '@jsonforms/core';
1
2
  import React from 'react';
2
3
  import type { ErrorObject } from 'ajv';
3
- import { ArrayLayoutProps, ControlElement, JsonSchema, JsonFormsRendererRegistryEntry, JsonFormsCellRendererRegistryEntry, ArrayTranslations, UISchemaElement, Layout } from '@jsonforms/core';
4
4
  import { WithDeleteDialogSupport } from './DeleteDialog';
5
+ import { NonEmptyRowComponentProps } from './ListWithDetailTypes';
5
6
  export type ObjectArrayControlProps = ArrayLayoutProps & WithDeleteDialogSupport;
6
7
  export declare const extractScopesFromUISchema: (uischema: any) => string[];
7
- export interface EmptyListProps {
8
- numColumns: number;
9
- noDataMessage: string;
10
- translations: ArrayTranslations;
11
- }
12
- interface NonEmptyRowComponentProps {
13
- propName?: string;
14
- schema: JsonSchema;
15
- rootSchema?: JsonSchema;
16
- rowPath: string;
17
- errors: string;
18
- enabled: boolean;
19
- renderers?: JsonFormsRendererRegistryEntry[];
20
- cells?: JsonFormsCellRendererRegistryEntry[];
21
- isValid: boolean;
22
- uischema?: ControlElement | Layout;
23
- }
24
8
  export declare const NonEmptyCellComponent: React.NamedExoticComponent<NonEmptyRowComponentProps>;
25
9
  interface NonEmptyRowProps {
26
10
  childPath: string;
@@ -0,0 +1,92 @@
1
+ import { ArrayLayoutProps, ArrayTranslations, ControlElement, JsonFormsCellRendererRegistryEntry, JsonFormsRendererRegistryEntry, JsonSchema, Layout, UISchemaElement } from '@jsonforms/core';
2
+ import { WithDeleteDialogSupport } from './DeleteDialog';
3
+ export type ListWithDetailArrayControlProps = ArrayLayoutProps & WithDeleteDialogSupport;
4
+ export interface EmptyListProps {
5
+ numColumns: number;
6
+ noDataMessage: string;
7
+ translations: ArrayTranslations;
8
+ }
9
+ export interface NonEmptyCellProps extends OwnPropsOfNonEmptyCell {
10
+ rootSchema?: JsonSchema;
11
+ errors: string;
12
+ enabled: boolean;
13
+ }
14
+ export interface OwnPropsOfNonEmptyCell {
15
+ rowPath: string;
16
+ propName?: string;
17
+ schema: JsonSchema;
18
+ enabled: boolean;
19
+ renderers?: JsonFormsRendererRegistryEntry[];
20
+ cells?: JsonFormsCellRendererRegistryEntry[];
21
+ uischema?: ControlElement;
22
+ }
23
+ export interface NonEmptyRowComponentProps {
24
+ propName?: string;
25
+ schema: JsonSchema;
26
+ rootSchema?: JsonSchema;
27
+ rowPath: string;
28
+ errors: string;
29
+ enabled: boolean;
30
+ renderers?: JsonFormsRendererRegistryEntry[];
31
+ cells?: JsonFormsCellRendererRegistryEntry[];
32
+ isValid: boolean;
33
+ uischema?: ControlElement | Layout;
34
+ }
35
+ export interface NonEmptyRowProps {
36
+ childPath: string;
37
+ schema: JsonSchema;
38
+ rowIndex: number;
39
+ showSortButtons: boolean;
40
+ enabled: boolean;
41
+ cells?: JsonFormsCellRendererRegistryEntry[];
42
+ path: string;
43
+ translations: ArrayTranslations;
44
+ uischema: ControlElement;
45
+ listTitle?: string;
46
+ }
47
+ export interface MainRowProps {
48
+ childPath: string;
49
+ rowIndex: number;
50
+ enabled: boolean;
51
+ currentTab: number;
52
+ current: HTMLElement | null;
53
+ selectCurrentTab: (index: number) => void;
54
+ setCurrentListPage: (index: number) => void;
55
+ rowData?: Record<string, any>;
56
+ uischema?: ControlElement;
57
+ schema?: JsonSchema;
58
+ }
59
+ export interface LeftRowProps {
60
+ childPath: string;
61
+ rowIndex: number;
62
+ enabled: boolean;
63
+ currentTab: number;
64
+ current: HTMLElement | null;
65
+ selectCurrentTab: (index: number) => void;
66
+ rowData?: Record<string, any>;
67
+ uischema?: ControlElement;
68
+ schema?: JsonSchema;
69
+ name: string;
70
+ translations: ArrayTranslations;
71
+ }
72
+ export interface TableRowsProp {
73
+ data: number;
74
+ path: string;
75
+ schema: JsonSchema;
76
+ uischema: ControlElement;
77
+ config?: any;
78
+ enabled: boolean;
79
+ cells?: JsonFormsCellRendererRegistryEntry[];
80
+ translations: ArrayTranslations;
81
+ currentIndex: number;
82
+ setCurrentIndex: (index: number) => void;
83
+ setCurrentListPage: (index: number) => void;
84
+ currentListPage: number;
85
+ listTitle?: string;
86
+ errors: string;
87
+ }
88
+ export interface SummaryDisplayProps {
89
+ rowData: Record<string, unknown> | undefined;
90
+ uischema?: UISchemaElement;
91
+ schema?: JsonSchema;
92
+ }
@@ -10,4 +10,14 @@ export declare const ADDRESS_LOOKUP_LABELS: {
10
10
  readonly subdivisionCode: "Province";
11
11
  readonly country: "Country";
12
12
  };
13
+ export declare const VALIDATION_KEYWORDS: {
14
+ REQUIRED: string;
15
+ MIN_LENGTH: string;
16
+ MAX_LENGTH: string;
17
+ FORMAT: string;
18
+ MINIMUM: string;
19
+ MAXIMUM: string;
20
+ TYPE: string;
21
+ ERROR_MESSAGE: string;
22
+ };
13
23
  export declare const getAddressLookupFieldLabel: (fieldName: string) => string;