@abgov/jsonforms-components 2.79.2 → 2.79.4

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
@@ -9321,7 +9321,9 @@ class ContextProviderClass {
9321
9321
  this.enumValues.set(key, () => data);
9322
9322
  };
9323
9323
  this.setup = props => {
9324
- var _props$isFormSubmitte, _props$showChangeButt, _props$autoPopulatedD, _this$selfProps;
9324
+ var _this$selfProps, _this$selfProps2, _props$isFormSubmitte, _props$showChangeButt, _props$autoPopulatedD, _this$selfProps3;
9325
+ const previousFileManagement = (_this$selfProps = this.selfProps) == null ? void 0 : _this$selfProps.fileManagement;
9326
+ const previousData = (_this$selfProps2 = this.selfProps) == null ? void 0 : _this$selfProps2.data;
9325
9327
  this.selfProps = props;
9326
9328
  if (props.fileManagement) {
9327
9329
  const {
@@ -9370,24 +9372,27 @@ class ContextProviderClass {
9370
9372
  navigationTarget: props.navigationTarget,
9371
9373
  onNavigationChange: props.onNavigationChange
9372
9374
  });
9373
- if (HOST_CONTROLLED_KEYS.some(key => next[key] !== this.baseEnumerator[key])) {
9375
+ const hostControlledChanged = HOST_CONTROLLED_KEYS.some(key => next[key] !== this.baseEnumerator[key]);
9376
+ const fileManagementChanged = props.fileManagement !== previousFileManagement;
9377
+ const dataChanged = props.data !== previousData;
9378
+ if (hostControlledChanged || fileManagementChanged || dataChanged) {
9374
9379
  this.baseEnumerator = next;
9375
9380
  }
9376
9381
  return jsx(JsonFormContext.Provider, {
9377
9382
  value: this.baseEnumerator,
9378
- children: (_this$selfProps = this.selfProps) == null ? void 0 : _this$selfProps.children
9383
+ children: (_this$selfProps3 = this.selfProps) == null ? void 0 : _this$selfProps3.children
9379
9384
  });
9380
9385
  };
9381
9386
  this.getContextProvider = () => {
9382
- var _this$selfProps2;
9387
+ var _this$selfProps4;
9383
9388
  return jsx(JsonFormContext.Provider, {
9384
9389
  value: this.baseEnumerator,
9385
- children: (_this$selfProps2 = this.selfProps) == null ? void 0 : _this$selfProps2.children
9390
+ children: (_this$selfProps4 = this.selfProps) == null ? void 0 : _this$selfProps4.children
9386
9391
  });
9387
9392
  };
9388
9393
  this.getFormUrl = () => {
9389
- var _this$selfProps3;
9390
- return (_this$selfProps3 = this.selfProps) == null ? void 0 : _this$selfProps3.formUrl;
9394
+ var _this$selfProps5;
9395
+ return (_this$selfProps5 = this.selfProps) == null ? void 0 : _this$selfProps5.formUrl;
9391
9396
  };
9392
9397
  this.getAxiosInterceptorConfig = axios => {
9393
9398
  const requestId = axios.interceptors.request.use(req => {
@@ -15803,7 +15808,6 @@ const NonEmptyCellComponent = /*#__PURE__*/React.memo(function NonEmptyCellCompo
15803
15808
  paddingTop: '18px'
15804
15809
  },
15805
15810
  children: jsx("div", {
15806
- "aria-hidden": "true",
15807
15811
  children: jsx(GoabIconButton, {
15808
15812
  icon: "trash",
15809
15813
  title: "trash button",
@@ -16173,6 +16177,366 @@ const ObjectArrayControl = props => {
16173
16177
  return content;
16174
16178
  };
16175
16179
 
16180
+ let _$1 = t => t,
16181
+ _t$2;
16182
+ const GoAContextMenuIcon = props => {
16183
+ return jsx(GoabIconButton, {
16184
+ icon: props.type,
16185
+ onClick: props.onClick,
16186
+ title: props.title,
16187
+ testId: props.testId,
16188
+ size: "small",
16189
+ disabled: props.disabled
16190
+ });
16191
+ };
16192
+ const GoAContextMenu = styled.div(_t$2 || (_t$2 = _$1`
16193
+ display: flex;
16194
+ align-items: center;
16195
+ background-color: #fff;
16196
+ gap: var(--goa-space-2xs);
16197
+
16198
+ > .goa-icon-button {
16199
+ cursor: pointer;
16200
+ border-radius: var(--goa-border-radius-m);
16201
+ padding: var(--goa-space-2xs);
16202
+ }
16203
+ > .goa-icon-button + .goa-icon-button {
16204
+ margin-left: var(--goa-space-none);
16205
+ }
16206
+ `));
16207
+
16208
+ const DeleteFileModal = ({
16209
+ isOpen,
16210
+ title,
16211
+ content,
16212
+ onDelete,
16213
+ onCancel
16214
+ }) => {
16215
+ return jsx(GoabModal, {
16216
+ testId: "delete-confirmation",
16217
+ open: isOpen,
16218
+ heading: title,
16219
+ maxWidth: "640px",
16220
+ actions: jsxs(GoabButtonGroup, {
16221
+ alignment: "end",
16222
+ children: [jsx(GoabButton, {
16223
+ type: "secondary",
16224
+ testId: "delete-cancel",
16225
+ onClick: onCancel,
16226
+ children: "Cancel"
16227
+ }), jsx(GoabButton, {
16228
+ type: "primary",
16229
+ variant: "destructive",
16230
+ testId: "delete-confirm",
16231
+ onClick: onDelete,
16232
+ children: "Delete"
16233
+ })]
16234
+ }),
16235
+ children: content
16236
+ });
16237
+ };
16238
+
16239
+ let _2 = t => t,
16240
+ _t$1,
16241
+ _t2$1,
16242
+ _t3,
16243
+ _t4;
16244
+ const _excluded$3 = ["data", "path", "handleChange", "uischema"];
16245
+ const FileUploaderReview = props => {
16246
+ return FileUploader(Object.assign({}, props, {
16247
+ isStepperReview: true
16248
+ }));
16249
+ };
16250
+ const FileUploader = _ref => {
16251
+ var _enumerators$function, _enumerators$function2, _enumerators$function3, _uischema$options, _uischema$options2, _uischema$options3, _uischema$options4, _props$schema, _uischema$options$com, _uischema$options5, _uischema$options6, _uischema$options$com2, _uischema$options7, _uischema$options$com3, _uischema$options8, _uischema$options9;
16252
+ let {
16253
+ data,
16254
+ path,
16255
+ handleChange,
16256
+ uischema
16257
+ } = _ref,
16258
+ props = _objectWithoutPropertiesLoose(_ref, _excluded$3);
16259
+ const enumerators = useContext(JsonFormContext);
16260
+ const uploadTriggerFunction = enumerators == null || (_enumerators$function = enumerators.functions) == null ? void 0 : _enumerators$function.get('upload-file');
16261
+ const uploadTrigger = uploadTriggerFunction && uploadTriggerFunction();
16262
+ const downloadTriggerFunction = enumerators == null || (_enumerators$function2 = enumerators.functions) == null ? void 0 : _enumerators$function2.get('download-file');
16263
+ const downloadTrigger = downloadTriggerFunction && downloadTriggerFunction();
16264
+ const deleteTriggerFunction = enumerators == null || (_enumerators$function3 = enumerators.functions) == null ? void 0 : _enumerators$function3.get('delete-file');
16265
+ const deleteTrigger = deleteTriggerFunction && deleteTriggerFunction();
16266
+ const fileListValue = enumerators == null ? void 0 : enumerators.data.get('file-list');
16267
+ const [loadingFileName, setLoadingFileName] = useState(undefined);
16268
+ const [uploadError, setUploadError] = useState(undefined);
16269
+ const countries = ['Argentina', 'Brazil', 'Canada', 'Denmark', 'Egypt', 'France', 'Greece', 'India', 'Japan', 'Kenya'];
16270
+ enumerators == null || enumerators.addFormContextData('countries', countries);
16271
+ const user = enumerators == null ? void 0 : enumerators.getFormContextData('user');
16272
+ // eslint-disable-next-line
16273
+ const fileList = fileListValue && fileListValue();
16274
+ const {
16275
+ required,
16276
+ label,
16277
+ i18nKeyPrefix,
16278
+ visible
16279
+ } = props;
16280
+ const propertyId = i18nKeyPrefix;
16281
+ const rootPath = typeof path === 'string' ? path.replace(/(\.\d+|\[\d+\])$/, '') : path;
16282
+ const variant = (uischema == null || (_uischema$options = uischema.options) == null ? void 0 : _uischema$options.variant) || 'button';
16283
+ const noDownloadButton = uischema == null || (_uischema$options2 = uischema.options) == null || (_uischema$options2 = _uischema$options2.format) == null ? void 0 : _uischema$options2.noDownloadButton;
16284
+ const noDownloadButtonInReview = uischema == null || (_uischema$options3 = uischema.options) == null || (_uischema$options3 = _uischema$options3.format) == null || (_uischema$options3 = _uischema$options3.review) == null ? void 0 : _uischema$options3.noDownloadButton;
16285
+ const noDeleteButton = uischema == null || (_uischema$options4 = uischema.options) == null || (_uischema$options4 = _uischema$options4.format) == null || (_uischema$options4 = _uischema$options4.review) == null ? void 0 : _uischema$options4.noDeleteButton;
16286
+ const isArraySchema = (props == null || (_props$schema = props.schema) == null ? void 0 : _props$schema.type) === 'array' || Array.isArray(data);
16287
+ const maxFiles = (_uischema$options$com = uischema == null || (_uischema$options5 = uischema.options) == null || (_uischema$options5 = _uischema$options5.componentProps) == null ? void 0 : _uischema$options5.maximum) != null ? _uischema$options$com : isArraySchema ? Number.MAX_SAFE_INTEGER : 1;
16288
+ const isMultiFile = maxFiles > 1 || isArraySchema;
16289
+ const metadataKey = path;
16290
+ const [deleteHide, setDeleteHide] = useState(false);
16291
+ const [deleteConfirmIndex, setDeleteConfirmIndex] = useState(null);
16292
+ const pendingUploadIndexRef = useRef(null);
16293
+ const uploadQueueRef = useRef(Promise.resolve());
16294
+ const filesForDisplay = useMemo(() => {
16295
+ if (!fileList) return [];
16296
+ if (isMultiFile) {
16297
+ const files = fileList[metadataKey] || fileList[rootPath] || fileList[propertyId] || [];
16298
+ const dataUrns = Array.isArray(data) ? data : data ? [data] : [];
16299
+ if (dataUrns.length > 0) {
16300
+ const urnSet = new Set(dataUrns);
16301
+ const scopedFiles = files.filter(f => urnSet.has(f.urn));
16302
+ if (scopedFiles.length > 0) {
16303
+ return scopedFiles.filter((file, index, all) => all.findIndex(f => f.urn === file.urn) === index);
16304
+ }
16305
+ const allFiles = Object.values(fileList).flat();
16306
+ const filesByUrn = dataUrns.map(urn => allFiles.find(f => (f == null ? void 0 : f.urn) === urn)).filter(f => !!f);
16307
+ if (filesByUrn.length > 0) {
16308
+ return filesByUrn.filter((file, index, all) => all.findIndex(f => f.urn === file.urn) === index);
16309
+ }
16310
+ }
16311
+ // Keep a stable list even if upstream metadata briefly duplicates entries.
16312
+ return files.filter((file, index, all) => all.findIndex(f => f.urn === file.urn) === index);
16313
+ }
16314
+ return fileList[metadataKey] || fileList[propertyId] || [];
16315
+ }, [fileList, isMultiFile, metadataKey, rootPath, propertyId, data]);
16316
+ const fileListLength = filesForDisplay.length;
16317
+ useEffect(() => {
16318
+ // Clear pending upload index when rendered file list catches up.
16319
+ pendingUploadIndexRef.current = null;
16320
+ }, [fileListLength, metadataKey, rootPath]);
16321
+ const getNextUploadIndex = () => {
16322
+ const baseIndex = filesForDisplay.length;
16323
+ if (pendingUploadIndexRef.current === null || pendingUploadIndexRef.current < baseIndex) {
16324
+ pendingUploadIndexRef.current = baseIndex;
16325
+ }
16326
+ const nextIndex = pendingUploadIndexRef.current;
16327
+ pendingUploadIndexRef.current += 1;
16328
+ return nextIndex;
16329
+ };
16330
+ async function uploadFile(file, requestedIndex) {
16331
+ if (!uploadTrigger) return;
16332
+ const fileListLength = requestedIndex != null ? requestedIndex : isMultiFile ? getNextUploadIndex() : filesForDisplay.length;
16333
+ // Single-file controls should allow selecting a new file to replace the current one.
16334
+ if (isMultiFile && fileListLength >= maxFiles) {
16335
+ setUploadError(`You can only upload up to ${maxFiles} file${maxFiles > 1 ? 's' : ''}.`);
16336
+ return;
16337
+ }
16338
+ setUploadError(undefined);
16339
+ setLoadingFileName(file == null ? void 0 : file.name);
16340
+ await Promise.resolve(uploadTrigger(file, isMultiFile ? `${rootPath}.${fileListLength}` : path));
16341
+ setDeleteHide(false);
16342
+ }
16343
+ function queueUpload(file, requestedIndex) {
16344
+ uploadQueueRef.current = uploadQueueRef.current.then(() => uploadFile(file, requestedIndex)).catch(() => {
16345
+ // Keep queue alive after an individual upload failure.
16346
+ });
16347
+ }
16348
+ function downloadFile(file) {
16349
+ if (downloadTrigger && file) {
16350
+ downloadTrigger(file, propertyId);
16351
+ }
16352
+ }
16353
+ function deleteFile(file) {
16354
+ if (deleteTrigger && file) {
16355
+ deleteTrigger(file, propertyId);
16356
+ }
16357
+ }
16358
+ function getFileName(index) {
16359
+ var _getFile;
16360
+ return (_getFile = getFile(index)) == null ? void 0 : _getFile.filename;
16361
+ }
16362
+ function getFile(index) {
16363
+ return filesForDisplay == null ? void 0 : filesForDisplay[index];
16364
+ }
16365
+ useEffect(() => {
16366
+ if (loadingFileName !== undefined) {
16367
+ setLoadingFileName(undefined);
16368
+ }
16369
+ const delayedFunction = () => {
16370
+ if (!fileList) return;
16371
+ const filesForControl = filesForDisplay || [];
16372
+ const hasFileListEntryForPath = Object.prototype.hasOwnProperty.call(fileList, metadataKey) || Object.prototype.hasOwnProperty.call(fileList, rootPath) || !isMultiFile && Object.prototype.hasOwnProperty.call(fileList, propertyId);
16373
+ const urns = filesForControl.map(f => f.urn);
16374
+ if (urns.length === 0) {
16375
+ if (hasFileListEntryForPath && data !== undefined && data !== null && data !== '') {
16376
+ handleChange(isMultiFile ? rootPath : path, undefined);
16377
+ }
16378
+ } else if (isMultiFile) {
16379
+ handleChange(rootPath, urns);
16380
+ } else {
16381
+ // Single-file replacement appends metadata; keep the latest selection as the current value.
16382
+ handleChange(path, urns[urns.length - 1]);
16383
+ }
16384
+ };
16385
+ const timeoutId = setTimeout(delayedFunction, 1);
16386
+ return () => clearTimeout(timeoutId);
16387
+ }, [data, fileList, filesForDisplay, rootPath, path, propertyId, metadataKey, isMultiFile, handleChange, loadingFileName]);
16388
+ const readOnly = (uischema == null || (_uischema$options6 = uischema.options) == null || (_uischema$options6 = _uischema$options6.componentProps) == null ? void 0 : _uischema$options6.readOnly) === true || (props == null ? void 0 : props.isStepperReview) === true || user === null;
16389
+ const maxFileSize = (_uischema$options$com2 = uischema == null || (_uischema$options7 = uischema.options) == null || (_uischema$options7 = _uischema$options7.componentProps) == null ? void 0 : _uischema$options7.maxFileSize) != null ? _uischema$options$com2 : '';
16390
+ const accept = (_uischema$options$com3 = uischema == null || (_uischema$options8 = uischema.options) == null || (_uischema$options8 = _uischema$options8.componentProps) == null ? void 0 : _uischema$options8.accept) != null ? _uischema$options$com3 : '';
16391
+ if (!enumerators) {
16392
+ //eslint-disable-next-line
16393
+ return jsx(Fragment, {});
16394
+ }
16395
+ const helpText = uischema == null || (_uischema$options9 = uischema.options) == null ? void 0 : _uischema$options9.help;
16396
+ const sentenceCaseLabel = label;
16397
+ const renderFileItem = index => {
16398
+ var _getFile2;
16399
+ const showFileDeleteConfirmation = deleteConfirmIndex === index;
16400
+ return jsx("div", {
16401
+ children: readOnly ? jsxs(AttachmentBorderDisabled, {
16402
+ children: [getFileName(index), noDownloadButtonInReview !== true && jsx(GoAContextMenuIcon, {
16403
+ testId: "download-icon",
16404
+ title: "Download",
16405
+ type: "download",
16406
+ onClick: () => downloadFile(getFile(index))
16407
+ })]
16408
+ }) : jsxs(AttachmentBorder, {
16409
+ children: [jsx("div", {
16410
+ children: getFileName(index)
16411
+ }), jsxs(GoAContextMenu, {
16412
+ children: [noDownloadButton !== true && jsx(GoAContextMenuIcon, {
16413
+ testId: "download-icon",
16414
+ title: "Download",
16415
+ type: "download",
16416
+ onClick: () => downloadFile(getFile(index))
16417
+ }), noDeleteButton !== true && jsx(GoAContextMenuIcon, {
16418
+ "data-testid": "delete-icon",
16419
+ title: "Delete",
16420
+ type: "trash",
16421
+ onClick: () => {
16422
+ setDeleteConfirmIndex(index);
16423
+ }
16424
+ })]
16425
+ }), jsx(DeleteFileModal, {
16426
+ isOpen: showFileDeleteConfirmation,
16427
+ title: "Delete file",
16428
+ content: `Delete file ${(_getFile2 = getFile(index)) == null ? void 0 : _getFile2.filename} ?`,
16429
+ onCancel: () => setDeleteConfirmIndex(null),
16430
+ onDelete: () => {
16431
+ setDeleteConfirmIndex(null);
16432
+ deleteFile(getFile(index));
16433
+ if (!isMultiFile) {
16434
+ setDeleteHide(true);
16435
+ }
16436
+ setUploadError(undefined);
16437
+ }
16438
+ })]
16439
+ })
16440
+ });
16441
+ };
16442
+ return jsx(Visible, {
16443
+ "$visible": visible,
16444
+ children: jsxs(FileUploaderStyle, {
16445
+ className: "FileUploader",
16446
+ children: [jsx(GoabFormItem, {
16447
+ label: sentenceCaseLabel,
16448
+ requirement: required ? 'required' : undefined,
16449
+ error: uploadError
16450
+ }), !readOnly && jsx("div", {
16451
+ className: "file-upload",
16452
+ children: jsx(GoabFileUploadInput, {
16453
+ variant: variant,
16454
+ onSelectFile: detail => {
16455
+ var _detail$files;
16456
+ const selectedFiles = detail != null && (_detail$files = detail.files) != null && _detail$files.length ? detail.files : detail != null && detail.file ? [detail.file] : [];
16457
+ if (selectedFiles.length === 0) {
16458
+ return;
16459
+ }
16460
+ if (isMultiFile) {
16461
+ for (const selectedFile of selectedFiles) {
16462
+ const nextIndex = getNextUploadIndex();
16463
+ if (nextIndex >= maxFiles) {
16464
+ setUploadError(`You can only upload up to ${maxFiles} file${maxFiles > 1 ? 's' : ''}.`);
16465
+ break;
16466
+ }
16467
+ queueUpload(selectedFile, nextIndex);
16468
+ }
16469
+ } else {
16470
+ queueUpload(selectedFiles[0]);
16471
+ }
16472
+ },
16473
+ maxFileSize: maxFileSize,
16474
+ accept: accept
16475
+ })
16476
+ }), helpText && jsx(HelpText, {
16477
+ children: helpText
16478
+ }), jsx("div", {
16479
+ children: loadingFileName !== undefined ? jsx(GoabModal, {
16480
+ open: loadingFileName !== undefined,
16481
+ children: jsx("div", {
16482
+ className: "align-center",
16483
+ children: jsx(GoabCircularProgress, {
16484
+ visible: true,
16485
+ message: `Uploading ${loadingFileName}`,
16486
+ size: "large"
16487
+ })
16488
+ })
16489
+ }) : jsx("div", {
16490
+ children: (fileList && isMultiFile ? filesForDisplay.map((_, i) => i) : !deleteHide && getFile(fileListLength - 1) && fileListLength >= 0 ? [fileListLength - 1] : []).map(index => jsx(React.Fragment, {
16491
+ children: renderFileItem(index)
16492
+ }, index))
16493
+ })
16494
+ })]
16495
+ })
16496
+ });
16497
+ };
16498
+ const HelpText = styled.div(_t$1 || (_t$1 = _2`
16499
+ margin-top: var(--goa-space-xs);
16500
+ font-size: var(--goa-font-size-3);
16501
+ color: var(--goa-color-text-secondary);
16502
+ `));
16503
+ const AttachmentBorderDisabled = styled.div(_t2$1 || (_t2$1 = _2`
16504
+ display: flex;
16505
+ flex-direction: row;
16506
+ border: var(--goa-border-width-s) solid #dcdcdc;
16507
+ border-radius: var(--goa-border-radius-m);
16508
+ padding: var(--goa-space-xs);
16509
+ width: fit-content;
16510
+ background-color: #f1f1f1;
16511
+ `));
16512
+ const AttachmentBorder = styled.div(_t3 || (_t3 = _2`
16513
+ display: flex;
16514
+ flex-direction: row;
16515
+ border: var(--goa-border-width-s) solid #dcdcdc;
16516
+ border-radius: var(--goa-border-radius-m);
16517
+ padding: var(--goa-space-xs);
16518
+ width: fit-content;
16519
+ margin-top: var(--goa-space-2xs);
16520
+ `));
16521
+ const FileUploaderStyle = styled.div(_t4 || (_t4 = _2`
16522
+ margin-bottom: var(--goa-space-l);
16523
+ .label {
16524
+ display: block;
16525
+ font-weight: var(--goa-font-weight-bold);
16526
+ color: var(--goa-color-text-default);
16527
+ font-size: var(--goa-font-size-4);
16528
+ padding: 0 0 var(--goa-space-xs) 0;
16529
+ }
16530
+
16531
+ .align-center {
16532
+ text-align-last: center;
16533
+ }
16534
+
16535
+ .file-upload {
16536
+ margin-bottom: var(--goa-space-xs);
16537
+ }
16538
+ `));
16539
+
16176
16540
  const ArrayControl = props => {
16177
16541
  const {
16178
16542
  visible,
@@ -16229,6 +16593,8 @@ const PrimitiveArrayControl = props => {
16229
16593
  cells
16230
16594
  } = props;
16231
16595
  const enumerators = useContext(JsonFormContext);
16596
+ const itemSchema = schema == null ? void 0 : schema.items;
16597
+ const isFileUrnArray = (itemSchema == null ? void 0 : itemSchema.format) === 'file-urn';
16232
16598
  const rawItems = Array.isArray(data) ? data : [];
16233
16599
  const items = rawItems.filter(item => item !== undefined && item !== null);
16234
16600
  const deleteTriggerFunction = enumerators == null || (_enumerators$function = enumerators.functions) == null ? void 0 : _enumerators$function.get('delete-file');
@@ -16240,6 +16606,14 @@ const PrimitiveArrayControl = props => {
16240
16606
  handleChange(path, items.length > 0 ? items : undefined);
16241
16607
  }
16242
16608
  }, [rawItems, items, handleChange, path]);
16609
+ if (isFileUrnArray) {
16610
+ return jsx(Visible, {
16611
+ "$visible": visible,
16612
+ children: jsx(FileUploader, Object.assign({}, props, {
16613
+ data: items
16614
+ }))
16615
+ });
16616
+ }
16243
16617
  const addItem = () => {
16244
16618
  handleChange(path, [...items, '']);
16245
16619
  };
@@ -16247,7 +16621,6 @@ const PrimitiveArrayControl = props => {
16247
16621
  const getOptionLabel = option => typeof option === 'string' ? option : option.title || option.const;
16248
16622
  const getOptionDescription = option => typeof option === 'string' ? undefined : option.description;
16249
16623
  const removeItem = index => {
16250
- const itemSchema = schema == null ? void 0 : schema.items;
16251
16624
  const removedItem = items[index];
16252
16625
  const itemPath = composePaths(path, `${index}`);
16253
16626
  if ((itemSchema == null ? void 0 : itemSchema.format) === 'file-urn' && deleteTrigger && removedItem) {
@@ -16923,10 +17296,10 @@ const GoAGroupReviewControlComponent = props => {
16923
17296
  const GoAGroupReviewLayoutTester = rankWith(1, uiTypeIs('Group'));
16924
17297
  const GoAGroupReviewControl = withJsonFormsLayoutProps(GoAGroupReviewControlComponent, true);
16925
17298
 
16926
- let _$1 = t => t,
16927
- _t$2,
16928
- _t2$1;
16929
- const HelpContentDiv = styled.div(_t$2 || (_t$2 = _$1`
17299
+ let _ = t => t,
17300
+ _t,
17301
+ _t2;
17302
+ const HelpContentDiv = styled.div(_t || (_t = _`
16930
17303
  .parent-label {
16931
17304
  font-size: 24px;
16932
17305
  margin-bottom: var(--goa-space-m);
@@ -17006,45 +17379,17 @@ const HelpContentDiv = styled.div(_t$2 || (_t$2 = _$1`
17006
17379
  top: 2.2rem;
17007
17380
  bottom: 0.5rem;
17008
17381
  width: 2px;
17009
- background-color: #ccc;
17010
- pointer-events: none;
17011
- }
17012
-
17013
- .help-content-markdown summary {
17014
- text-decoration: underline;
17015
- }
17016
- `));
17017
- const InvalidMarkdown = styled.div(_t2$1 || (_t2$1 = _$1`
17018
- color: var(--goa-color-interactive-error);
17019
- `));
17020
-
17021
- let _ = t => t,
17022
- _t$1;
17023
- const GoAContextMenuIcon = props => {
17024
- return jsx(GoabIconButton, {
17025
- icon: props.type,
17026
- onClick: props.onClick,
17027
- title: props.title,
17028
- testId: props.testId,
17029
- size: "small",
17030
- disabled: props.disabled
17031
- });
17032
- };
17033
- const GoAContextMenu = styled.div(_t$1 || (_t$1 = _`
17034
- display: flex;
17035
- align-items: center;
17036
- background-color: #fff;
17037
- gap: var(--goa-space-2xs);
17038
-
17039
- > .goa-icon-button {
17040
- cursor: pointer;
17041
- border-radius: var(--goa-border-radius-m);
17042
- padding: var(--goa-space-2xs);
17382
+ background-color: #ccc;
17383
+ pointer-events: none;
17043
17384
  }
17044
- > .goa-icon-button + .goa-icon-button {
17045
- margin-left: var(--goa-space-none);
17385
+
17386
+ .help-content-markdown summary {
17387
+ text-decoration: underline;
17046
17388
  }
17047
17389
  `));
17390
+ const InvalidMarkdown = styled.div(_t2 || (_t2 = _`
17391
+ color: var(--goa-color-interactive-error);
17392
+ `));
17048
17393
 
17049
17394
  const linkLength = 40;
17050
17395
  const invalidExtensions = ['exe'];
@@ -17106,12 +17451,12 @@ const RenderLink = props => {
17106
17451
  });
17107
17452
  };
17108
17453
 
17109
- const _excluded$3 = ["node"],
17454
+ const _excluded$2 = ["node"],
17110
17455
  _excluded2 = ["isParent", "showLabel"];
17111
17456
  const markdownComponents = {
17112
17457
  // Destructure node out (react-markdown internal prop) so it is not forwarded to the DOM element.
17113
17458
  a: _ref => {
17114
- let props = _objectWithoutPropertiesLoose(_ref, _excluded$3);
17459
+ let props = _objectWithoutPropertiesLoose(_ref, _excluded$2);
17115
17460
  return jsx("a", Object.assign({}, props, {
17116
17461
  target: "_blank",
17117
17462
  rel: "noopener noreferrer"
@@ -17953,7 +18298,7 @@ const SummaryRow = ({
17953
18298
  });
17954
18299
  };
17955
18300
 
17956
- const _excluded$2 = ["type"];
18301
+ const _excluded$1 = ["type"];
17957
18302
  const AdditionalInstructionsRow = ({
17958
18303
  additionalInstructions,
17959
18304
  componentProps
@@ -17962,7 +18307,7 @@ const AdditionalInstructionsRow = ({
17962
18307
  const calloutType = (componentProps == null ? void 0 : componentProps.type) || 'information';
17963
18308
  const type = validTypes.includes(calloutType) ? calloutType : 'information';
17964
18309
  const _ref = componentProps || {},
17965
- otherProps = _objectWithoutPropertiesLoose(_ref, _excluded$2);
18310
+ otherProps = _objectWithoutPropertiesLoose(_ref, _excluded$1);
17966
18311
  const sanitizedHtml = sanitizeHtml(additionalInstructions);
17967
18312
  return jsx("tr", {
17968
18313
  children: jsx("td", {
@@ -18453,280 +18798,14 @@ const CategorizationPagesRendererTester = rankWith(2, and(uiTypeIs('Categorizati
18453
18798
  return ((_uischema$options3 = uischema.options) == null ? void 0 : _uischema$options3.variant) === 'pages';
18454
18799
  }));
18455
18800
 
18456
- const DeleteFileModal = ({
18457
- isOpen,
18458
- title,
18459
- content,
18460
- onDelete,
18461
- onCancel
18462
- }) => {
18463
- return jsx(GoabModal, {
18464
- testId: "delete-confirmation",
18465
- open: isOpen,
18466
- heading: title,
18467
- maxWidth: "640px",
18468
- actions: jsxs(GoabButtonGroup, {
18469
- alignment: "end",
18470
- children: [jsx(GoabButton, {
18471
- type: "secondary",
18472
- testId: "delete-cancel",
18473
- onClick: onCancel,
18474
- children: "Cancel"
18475
- }), jsx(GoabButton, {
18476
- type: "primary",
18477
- variant: "destructive",
18478
- testId: "delete-confirm",
18479
- onClick: onDelete,
18480
- children: "Delete"
18481
- })]
18482
- }),
18483
- children: content
18484
- });
18485
- };
18486
-
18487
- let _2 = t => t,
18488
- _t,
18489
- _t2,
18490
- _t3,
18491
- _t4;
18492
- const _excluded$1 = ["data", "path", "handleChange", "uischema"];
18493
- const FileUploaderReview = props => {
18494
- return FileUploader(Object.assign({}, props, {
18495
- isStepperReview: true
18496
- }));
18497
- };
18498
- const FileUploader = _ref => {
18499
- var _enumerators$function, _enumerators$function2, _enumerators$function3, _uischema$options, _uischema$options2, _uischema$options3, _uischema$options4, _fileList$path, _uischema$options$com, _uischema$options5, _uischema$options6, _uischema$options$com2, _uischema$options7, _uischema$options$com3, _uischema$options8, _uischema$options9;
18500
- let {
18501
- data,
18502
- path,
18503
- handleChange,
18504
- uischema
18505
- } = _ref,
18506
- props = _objectWithoutPropertiesLoose(_ref, _excluded$1);
18507
- const enumerators = useContext(JsonFormContext);
18508
- const uploadTriggerFunction = enumerators == null || (_enumerators$function = enumerators.functions) == null ? void 0 : _enumerators$function.get('upload-file');
18509
- const uploadTrigger = uploadTriggerFunction && uploadTriggerFunction();
18510
- const downloadTriggerFunction = enumerators == null || (_enumerators$function2 = enumerators.functions) == null ? void 0 : _enumerators$function2.get('download-file');
18511
- const downloadTrigger = downloadTriggerFunction && downloadTriggerFunction();
18512
- const deleteTriggerFunction = enumerators == null || (_enumerators$function3 = enumerators.functions) == null ? void 0 : _enumerators$function3.get('delete-file');
18513
- const deleteTrigger = deleteTriggerFunction && deleteTriggerFunction();
18514
- const fileListValue = enumerators == null ? void 0 : enumerators.data.get('file-list');
18515
- const [loadingFileName, setLoadingFileName] = useState(undefined);
18516
- const [uploadError, setUploadError] = useState(undefined);
18517
- const countries = ['Argentina', 'Brazil', 'Canada', 'Denmark', 'Egypt', 'France', 'Greece', 'India', 'Japan', 'Kenya'];
18518
- enumerators == null || enumerators.addFormContextData('countries', countries);
18519
- const user = enumerators == null ? void 0 : enumerators.getFormContextData('user');
18520
- // eslint-disable-next-line
18521
- const fileList = fileListValue && fileListValue();
18522
- const {
18523
- required,
18524
- label,
18525
- i18nKeyPrefix,
18526
- visible
18527
- } = props;
18528
- const propertyId = i18nKeyPrefix;
18529
- const variant = (uischema == null || (_uischema$options = uischema.options) == null ? void 0 : _uischema$options.variant) || 'button';
18530
- const noDownloadButton = uischema == null || (_uischema$options2 = uischema.options) == null || (_uischema$options2 = _uischema$options2.format) == null ? void 0 : _uischema$options2.noDownloadButton;
18531
- const noDownloadButtonInReview = uischema == null || (_uischema$options3 = uischema.options) == null || (_uischema$options3 = _uischema$options3.format) == null || (_uischema$options3 = _uischema$options3.review) == null ? void 0 : _uischema$options3.noDownloadButton;
18532
- const noDeleteButton = uischema == null || (_uischema$options4 = uischema.options) == null || (_uischema$options4 = _uischema$options4.format) == null || (_uischema$options4 = _uischema$options4.review) == null ? void 0 : _uischema$options4.noDeleteButton;
18533
- const [deleteHide, setDeleteHide] = useState(false);
18534
- const [deleteConfirmIndex, setDeleteConfirmIndex] = useState(null);
18535
- const fileListLength = fileList && ((_fileList$path = fileList[path]) == null ? void 0 : _fileList$path.length) || 0;
18536
- const maxFiles = (_uischema$options$com = uischema == null || (_uischema$options5 = uischema.options) == null || (_uischema$options5 = _uischema$options5.componentProps) == null ? void 0 : _uischema$options5.maximum) != null ? _uischema$options$com : 1;
18537
- const isMultiFile = maxFiles > 1;
18538
- function uploadFile(file) {
18539
- var _fileList$propertyId;
18540
- if (!uploadTrigger) return;
18541
- const fileListLength = fileList && ((_fileList$propertyId = fileList[propertyId]) == null ? void 0 : _fileList$propertyId.length) || 0;
18542
- if (fileListLength >= maxFiles) {
18543
- setUploadError(`You can only upload up to ${maxFiles} file${maxFiles > 1 ? 's' : ''}.`);
18544
- return;
18545
- }
18546
- setUploadError(undefined);
18547
- setLoadingFileName(file == null ? void 0 : file.name);
18548
- uploadTrigger(file, path);
18549
- setDeleteHide(false);
18550
- }
18551
- function downloadFile(file) {
18552
- if (downloadTrigger) {
18553
- downloadTrigger(file, propertyId);
18554
- }
18555
- }
18556
- function deleteFile(file) {
18557
- if (deleteTrigger) {
18558
- deleteTrigger(file, propertyId);
18559
- }
18560
- }
18561
- function getFileName(index) {
18562
- var _getFile;
18563
- return (_getFile = getFile(index)) == null ? void 0 : _getFile.filename;
18564
- }
18565
- function getFile(index) {
18566
- var _fileList$path2;
18567
- return fileList == null || (_fileList$path2 = fileList[path]) == null ? void 0 : _fileList$path2[index];
18568
- }
18569
- useEffect(() => {
18570
- if (loadingFileName !== undefined) {
18571
- setLoadingFileName(undefined);
18572
- }
18573
- const delayedFunction = () => {
18574
- if (!fileList) return;
18575
- const filesForControl = (fileList == null ? void 0 : fileList[path]) || [];
18576
- const hasFileListEntryForPath = Object.prototype.hasOwnProperty.call(fileList, path);
18577
- const urns = filesForControl.map(f => f.urn);
18578
- if (urns.length === 0) {
18579
- if (hasFileListEntryForPath && data !== undefined && data !== null && data !== '') {
18580
- handleChange(path, undefined);
18581
- }
18582
- } else if (isMultiFile) {
18583
- handleChange(path, urns);
18584
- } else {
18585
- handleChange(path, urns[0]);
18586
- }
18587
- };
18588
- const timeoutId = setTimeout(delayedFunction, 1);
18589
- return () => clearTimeout(timeoutId);
18590
- //eslint-disable-next-line
18591
- }, [data, fileList, path, propertyId, isMultiFile, handleChange, loadingFileName]);
18592
- const readOnly = (uischema == null || (_uischema$options6 = uischema.options) == null || (_uischema$options6 = _uischema$options6.componentProps) == null ? void 0 : _uischema$options6.readOnly) === true || (props == null ? void 0 : props.isStepperReview) === true || user === null;
18593
- const maxFileSize = (_uischema$options$com2 = uischema == null || (_uischema$options7 = uischema.options) == null || (_uischema$options7 = _uischema$options7.componentProps) == null ? void 0 : _uischema$options7.maxFileSize) != null ? _uischema$options$com2 : '';
18594
- const accept = (_uischema$options$com3 = uischema == null || (_uischema$options8 = uischema.options) == null || (_uischema$options8 = _uischema$options8.componentProps) == null ? void 0 : _uischema$options8.accept) != null ? _uischema$options$com3 : '';
18595
- if (!enumerators) {
18596
- //eslint-disable-next-line
18597
- return jsx(Fragment, {});
18598
- }
18599
- const helpText = uischema == null || (_uischema$options9 = uischema.options) == null ? void 0 : _uischema$options9.help;
18600
- const sentenceCaseLabel = label;
18601
- const renderFileItem = index => {
18602
- var _getFile2;
18603
- const showFileDeleteConfirmation = deleteConfirmIndex === index;
18604
- return jsx("div", {
18605
- children: readOnly ? jsxs(AttachmentBorderDisabled, {
18606
- children: [getFileName(index), noDownloadButtonInReview !== true && jsx(GoAContextMenuIcon, {
18607
- testId: "download-icon",
18608
- title: "Download",
18609
- type: "download",
18610
- onClick: () => downloadFile(getFile(index))
18611
- })]
18612
- }) : jsxs(AttachmentBorder, {
18613
- children: [jsx("div", {
18614
- children: getFileName(index)
18615
- }), jsxs(GoAContextMenu, {
18616
- children: [noDownloadButton !== true && jsx(GoAContextMenuIcon, {
18617
- testId: "download-icon",
18618
- title: "Download",
18619
- type: "download",
18620
- onClick: () => downloadFile(getFile(index))
18621
- }), noDeleteButton !== true && jsx(GoAContextMenuIcon, {
18622
- "data-testid": "delete-icon",
18623
- title: "Delete",
18624
- type: "trash",
18625
- onClick: () => {
18626
- setDeleteConfirmIndex(index);
18627
- }
18628
- })]
18629
- }), jsx(DeleteFileModal, {
18630
- isOpen: showFileDeleteConfirmation,
18631
- title: "Delete file",
18632
- content: `Delete file ${(_getFile2 = getFile(index)) == null ? void 0 : _getFile2.filename} ?`,
18633
- onCancel: () => setDeleteConfirmIndex(null),
18634
- onDelete: () => {
18635
- setDeleteConfirmIndex(null);
18636
- deleteFile(getFile(index));
18637
- if (!isMultiFile) {
18638
- setDeleteHide(true);
18639
- }
18640
- setUploadError(undefined);
18641
- }
18642
- })]
18643
- })
18644
- });
18645
- };
18646
- return jsx(Visible, {
18647
- "$visible": visible,
18648
- children: jsxs(FileUploaderStyle, {
18649
- className: "FileUploader",
18650
- children: [jsx(GoabFormItem, {
18651
- label: sentenceCaseLabel,
18652
- requirement: required ? 'required' : undefined,
18653
- error: uploadError
18654
- }), !readOnly && jsx("div", {
18655
- className: "file-upload",
18656
- children: jsx(GoabFileUploadInput, {
18657
- variant: variant,
18658
- onSelectFile: detail => {
18659
- // adjust based on the actual shape of "detail"
18660
- uploadFile(detail.file); // or detail.files[0], etc.
18661
- },
18662
- maxFileSize: maxFileSize,
18663
- accept: accept
18664
- })
18665
- }), helpText && jsx(HelpText, {
18666
- children: helpText
18667
- }), jsx("div", {
18668
- children: loadingFileName !== undefined ? jsx(GoabModal, {
18669
- open: loadingFileName !== undefined,
18670
- children: jsx("div", {
18671
- className: "align-center",
18672
- children: jsx(GoabCircularProgress, {
18673
- visible: true,
18674
- message: `Uploading ${loadingFileName}`,
18675
- size: "large"
18676
- })
18677
- })
18678
- }) : jsx("div", {
18679
- children: (fileList && isMultiFile ? (fileList[path] || []).map((_, i) => i) : !deleteHide && getFile(fileListLength - 1) && fileListLength >= 0 ? [fileListLength - 1] : []).map(index => jsx(React.Fragment, {
18680
- children: renderFileItem(index)
18681
- }, index))
18682
- })
18683
- })]
18684
- })
18685
- });
18686
- };
18687
- const HelpText = styled.div(_t || (_t = _2`
18688
- margin-top: var(--goa-space-xs);
18689
- font-size: var(--goa-font-size-3);
18690
- color: var(--goa-color-text-secondary);
18691
- `));
18692
- const AttachmentBorderDisabled = styled.div(_t2 || (_t2 = _2`
18693
- display: flex;
18694
- flex-direction: row;
18695
- border: var(--goa-border-width-s) solid #dcdcdc;
18696
- border-radius: var(--goa-border-radius-m);
18697
- padding: var(--goa-space-xs);
18698
- width: fit-content;
18699
- background-color: #f1f1f1;
18700
- `));
18701
- const AttachmentBorder = styled.div(_t3 || (_t3 = _2`
18702
- display: flex;
18703
- flex-direction: row;
18704
- border: var(--goa-border-width-s) solid #dcdcdc;
18705
- border-radius: var(--goa-border-radius-m);
18706
- padding: var(--goa-space-xs);
18707
- width: fit-content;
18708
- margin-top: var(--goa-space-2xs);
18709
- `));
18710
- const FileUploaderStyle = styled.div(_t4 || (_t4 = _2`
18711
- margin-bottom: var(--goa-space-l);
18712
- .label {
18713
- display: block;
18714
- font-weight: var(--goa-font-weight-bold);
18715
- color: var(--goa-color-text-default);
18716
- font-size: var(--goa-font-size-4);
18717
- padding: 0 0 var(--goa-space-xs) 0;
18718
- }
18719
-
18720
- .align-center {
18721
- text-align-last: center;
18722
- }
18723
-
18724
- .file-upload {
18725
- margin-bottom: var(--goa-space-xs);
18801
+ const isSingleFileUrn = and(schemaTypeIs('string'), formatIs('file-urn'));
18802
+ const isFileUrnArray = and(schemaTypeIs('array'), schemaMatches(schema => {
18803
+ if (!(schema != null && schema.items) || Array.isArray(schema.items)) {
18804
+ return false;
18726
18805
  }
18727
- `));
18728
-
18729
- const FileUploaderTester = rankWith(3, and(schemaTypeIs('string'), formatIs('file-urn')));
18806
+ return schema.items.type === 'string' && schema.items.format === 'file-urn';
18807
+ }));
18808
+ const FileUploaderTester = rankWith(3, or(isSingleFileUrn, isFileUrnArray));
18730
18809
 
18731
18810
  const AddressInputs = ({
18732
18811
  address,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abgov/jsonforms-components",
3
- "version": "2.79.2",
3
+ "version": "2.79.4",
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",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": "1.0.0",
3
- "generatedAt": "2026-10-16T15:49:46.071Z",
4
- "sourceCommit": "e67361e621b104d80dd5540685cf85f7a57bf941",
3
+ "generatedAt": "2026-10-28T20:42:38.992Z",
4
+ "sourceCommit": "dc35c087a12660681557962655deb565941cc540",
5
5
  "sourcePath": "libs/jsonforms-components/src/index.ts",
6
6
  "rendererCount": 23,
7
7
  "renderers": [