@bpmn-io/form-js-viewer 1.14.0 → 1.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +101 -71
- package/dist/index.cjs.map +1 -1
- package/dist/index.es.js +101 -71
- package/dist/index.es.js.map +1 -1
- package/dist/types/render/components/form-fields/DocumentPreview.d.ts +9 -7
- package/dist/types/render/components/index.d.ts +1 -1
- package/dist/types/util/constants/DatetimeConstants.d.ts +6 -2
- package/dist/types/util/constants/OptionsSourceConstants.d.ts +9 -3
- package/package.json +6 -6
package/dist/index.es.js
CHANGED
|
@@ -907,7 +907,6 @@ function useDeepCompareMemoize(value) {
|
|
|
907
907
|
* @enum { String }
|
|
908
908
|
*/
|
|
909
909
|
const LOAD_STATES = {
|
|
910
|
-
LOADING: 'loading',
|
|
911
910
|
LOADED: 'loaded',
|
|
912
911
|
ERROR: 'error'
|
|
913
912
|
};
|
|
@@ -1118,6 +1117,9 @@ function _isElementScrollable(el) {
|
|
|
1118
1117
|
return (overflowY === 'auto' || overflowY === 'scroll') && el.scrollHeight > el.clientHeight;
|
|
1119
1118
|
}
|
|
1120
1119
|
|
|
1120
|
+
const EMPTY_OBJECT = {};
|
|
1121
|
+
const EMPTY_ARRAY$2 = [];
|
|
1122
|
+
|
|
1121
1123
|
/**
|
|
1122
1124
|
* Custom hook to scroll an element within a scrollable container.
|
|
1123
1125
|
*
|
|
@@ -1131,8 +1133,8 @@ function _isElementScrollable(el) {
|
|
|
1131
1133
|
* @param {Array} [flagRefs] - An array of refs that are used as flags to control when to scroll.
|
|
1132
1134
|
*/
|
|
1133
1135
|
function useScrollIntoView(scrolledElementRef, deps, scrollOptions, flagRefs) {
|
|
1134
|
-
const _scrollOptions = scrollOptions;
|
|
1135
|
-
const _flagRefs = flagRefs;
|
|
1136
|
+
const _scrollOptions = scrollOptions || EMPTY_OBJECT;
|
|
1137
|
+
const _flagRefs = flagRefs || EMPTY_ARRAY$2;
|
|
1136
1138
|
useEffect(() => {
|
|
1137
1139
|
// return early if flags are not raised, or component is not mounted
|
|
1138
1140
|
if (some(_flagRefs, ref => !ref.current) || !scrolledElementRef.current) {
|
|
@@ -5901,10 +5903,15 @@ var SvgDownload = function SvgDownload(props) {
|
|
|
5901
5903
|
|
|
5902
5904
|
const type = 'documentPreview';
|
|
5903
5905
|
|
|
5906
|
+
/**
|
|
5907
|
+
* @typedef DocumentEndpointBuilder
|
|
5908
|
+
* @property {(document: DocumentMetadata) => string} buildUrl
|
|
5909
|
+
*/
|
|
5910
|
+
|
|
5904
5911
|
/**
|
|
5905
5912
|
* @typedef DocumentMetadata
|
|
5906
5913
|
* @property {string} documentId
|
|
5907
|
-
* @property {string}
|
|
5914
|
+
* @property {string} endpoint
|
|
5908
5915
|
* @property {Object} metadata
|
|
5909
5916
|
* @property {string|undefined} [metadata.contentType]
|
|
5910
5917
|
* @property {string} metadata.fileName
|
|
@@ -5913,7 +5920,6 @@ const type = 'documentPreview';
|
|
|
5913
5920
|
* @property {string} id
|
|
5914
5921
|
* @property {string} [title]
|
|
5915
5922
|
* @property {string} [dataSource]
|
|
5916
|
-
* @property {string} [endpointKey]
|
|
5917
5923
|
* @property {number} [maxHeight]
|
|
5918
5924
|
* @property {string} [label]
|
|
5919
5925
|
*
|
|
@@ -5925,18 +5931,18 @@ const type = 'documentPreview';
|
|
|
5925
5931
|
* @returns {import("preact").JSX.Element}
|
|
5926
5932
|
*/
|
|
5927
5933
|
function DocumentPreview(props) {
|
|
5934
|
+
/** @type {DocumentEndpointBuilder | null} */
|
|
5935
|
+
const documentEndpointBuilder = useService('documentEndpointBuilder', false);
|
|
5928
5936
|
const {
|
|
5929
5937
|
field,
|
|
5930
5938
|
domId
|
|
5931
5939
|
} = props;
|
|
5932
5940
|
const {
|
|
5933
5941
|
dataSource,
|
|
5934
|
-
endpointKey,
|
|
5935
5942
|
maxHeight,
|
|
5936
5943
|
label
|
|
5937
5944
|
} = field;
|
|
5938
5945
|
const errorMessageId = `${domId}-error-message`;
|
|
5939
|
-
const endpoint = useExpressionEvaluation(endpointKey || '');
|
|
5940
5946
|
const data = useValidDocumentData(dataSource || '');
|
|
5941
5947
|
const evaluatedLabel = useSingleLineTemplateEvaluation(label, {
|
|
5942
5948
|
debug: true
|
|
@@ -5949,18 +5955,19 @@ function DocumentPreview(props) {
|
|
|
5949
5955
|
}), jsx("div", {
|
|
5950
5956
|
class: `fjs-${type}-document-container`,
|
|
5951
5957
|
id: domId,
|
|
5952
|
-
children:
|
|
5953
|
-
|
|
5954
|
-
|
|
5955
|
-
|
|
5956
|
-
|
|
5957
|
-
|
|
5958
|
+
children: data.map((document, index) => {
|
|
5959
|
+
const finalEndpoint = tryCatch(() => documentEndpointBuilder?.buildUrl(document)) ?? document.endpoint;
|
|
5960
|
+
return isValidDocumentEndpoint(finalEndpoint) ? jsx(DocumentRenderer, {
|
|
5961
|
+
documentMetadata: document,
|
|
5962
|
+
endpoint: finalEndpoint,
|
|
5963
|
+
maxHeight: maxHeight,
|
|
5964
|
+
domId: `${domId}-${index}`
|
|
5965
|
+
}, document.documentId) : null;
|
|
5966
|
+
})
|
|
5958
5967
|
}), jsx(Errors, {
|
|
5959
5968
|
id: errorMessageId,
|
|
5960
5969
|
errors: getErrors({
|
|
5961
|
-
dataSource
|
|
5962
|
-
endpoint,
|
|
5963
|
-
endpointKey
|
|
5970
|
+
dataSource
|
|
5964
5971
|
})
|
|
5965
5972
|
})]
|
|
5966
5973
|
});
|
|
@@ -5972,43 +5979,27 @@ DocumentPreview.config = {
|
|
|
5972
5979
|
name: 'Document preview',
|
|
5973
5980
|
create: (options = {}) => ({
|
|
5974
5981
|
label: 'Document preview',
|
|
5975
|
-
endpointKey: DEFAULT_ENDPOINT_KEY,
|
|
5976
5982
|
...options
|
|
5977
5983
|
})
|
|
5978
5984
|
};
|
|
5979
5985
|
|
|
5980
5986
|
// helpers /////////////////////////////
|
|
5981
5987
|
|
|
5982
|
-
const DOCUMENT_ID_PLACEHOLDER = '{documentId}';
|
|
5983
|
-
const DEFAULT_ENDPOINT_KEY = '=defaultDocumentsEndpointKey';
|
|
5984
|
-
|
|
5985
5988
|
/**
|
|
5986
5989
|
* @typedef GetErrorOptions
|
|
5987
5990
|
* @property {string|undefined} dataSource
|
|
5988
|
-
* @property {string|undefined} endpointKey
|
|
5989
|
-
* @property {string|null} endpoint
|
|
5990
5991
|
*
|
|
5991
5992
|
* @param {GetErrorOptions} options
|
|
5992
5993
|
* @returns {string[]}
|
|
5993
5994
|
*/
|
|
5994
5995
|
function getErrors(options) {
|
|
5995
5996
|
const {
|
|
5996
|
-
dataSource
|
|
5997
|
-
endpointKey,
|
|
5998
|
-
endpoint
|
|
5997
|
+
dataSource
|
|
5999
5998
|
} = options;
|
|
6000
5999
|
let errors = [];
|
|
6001
6000
|
if (!isString(dataSource) || dataSource.length < 1) {
|
|
6002
6001
|
errors.push('Document reference is not defined.');
|
|
6003
6002
|
}
|
|
6004
|
-
if (!isString(endpointKey) || endpointKey.length < 1) {
|
|
6005
|
-
errors.push('Endpoint key is not defined.');
|
|
6006
|
-
}
|
|
6007
|
-
if (endpointKey !== DEFAULT_ENDPOINT_KEY && !URL.canParse(endpoint)) {
|
|
6008
|
-
errors.push(`If you change the endpoint key from "${DEFAULT_ENDPOINT_KEY}", the document preview won't work with Camunda Tasklist and you must provide a valid URL.`);
|
|
6009
|
-
} else if (endpointKey !== DEFAULT_ENDPOINT_KEY && !isValidDocumentEndpoint(endpoint)) {
|
|
6010
|
-
errors.push('Endpoint must contain "{documentId}".');
|
|
6011
|
-
}
|
|
6012
6003
|
return errors;
|
|
6013
6004
|
}
|
|
6014
6005
|
|
|
@@ -6018,7 +6009,7 @@ function getErrors(options) {
|
|
|
6018
6009
|
* @returns boolean
|
|
6019
6010
|
*/
|
|
6020
6011
|
function isValidDocumentEndpoint(endpoint) {
|
|
6021
|
-
return typeof endpoint === 'string' && URL.canParse(endpoint)
|
|
6012
|
+
return typeof endpoint === 'string' && URL.canParse(endpoint);
|
|
6022
6013
|
}
|
|
6023
6014
|
|
|
6024
6015
|
/**
|
|
@@ -6041,6 +6032,61 @@ function useValidDocumentData(dataSource) {
|
|
|
6041
6032
|
return data.filter(isValidDocument);
|
|
6042
6033
|
}
|
|
6043
6034
|
|
|
6035
|
+
/**
|
|
6036
|
+
* @param {Object} props
|
|
6037
|
+
* @param {string} props.url
|
|
6038
|
+
* @param {string} props.fileName
|
|
6039
|
+
* @param {Function} props.onError
|
|
6040
|
+
* @param {string} props.errorMessageId
|
|
6041
|
+
* @returns {import("preact").JSX.Element}
|
|
6042
|
+
*/
|
|
6043
|
+
function PdfRenderer(props) {
|
|
6044
|
+
const {
|
|
6045
|
+
url,
|
|
6046
|
+
onError,
|
|
6047
|
+
errorMessageId
|
|
6048
|
+
} = props;
|
|
6049
|
+
/** @type {ReturnType<typeof import("preact/hooks").useState<null | string>>} */
|
|
6050
|
+
const [pdfObjectUrl, setPdfObjectUrl] = useState(null);
|
|
6051
|
+
const [hasError, setHasError] = useState(false);
|
|
6052
|
+
useEffect(() => {
|
|
6053
|
+
/** @type {null | string} */
|
|
6054
|
+
let objectUrl = null;
|
|
6055
|
+
const fetchPdf = async () => {
|
|
6056
|
+
try {
|
|
6057
|
+
const response = await fetch(url);
|
|
6058
|
+
if (!response.ok) {
|
|
6059
|
+
setHasError(true);
|
|
6060
|
+
onError();
|
|
6061
|
+
return;
|
|
6062
|
+
}
|
|
6063
|
+
const blob = await response.blob();
|
|
6064
|
+
objectUrl = URL.createObjectURL(blob);
|
|
6065
|
+
setPdfObjectUrl(objectUrl);
|
|
6066
|
+
} catch {
|
|
6067
|
+
setHasError(true);
|
|
6068
|
+
onError();
|
|
6069
|
+
}
|
|
6070
|
+
};
|
|
6071
|
+
fetchPdf();
|
|
6072
|
+
return () => {
|
|
6073
|
+
if (objectUrl) {
|
|
6074
|
+
URL.revokeObjectURL(objectUrl);
|
|
6075
|
+
}
|
|
6076
|
+
};
|
|
6077
|
+
}, [url, onError]);
|
|
6078
|
+
return jsxs(Fragment, {
|
|
6079
|
+
children: [pdfObjectUrl !== null ? jsx("embed", {
|
|
6080
|
+
src: pdfObjectUrl,
|
|
6081
|
+
type: "application/pdf",
|
|
6082
|
+
class: `fjs-${type}-pdf-viewer`
|
|
6083
|
+
}) : null, hasError ? jsx(Errors, {
|
|
6084
|
+
id: errorMessageId,
|
|
6085
|
+
errors: ['Unable to download document']
|
|
6086
|
+
}) : null]
|
|
6087
|
+
});
|
|
6088
|
+
}
|
|
6089
|
+
|
|
6044
6090
|
/**
|
|
6045
6091
|
*
|
|
6046
6092
|
* @param {Object} props
|
|
@@ -6064,11 +6110,6 @@ function DocumentRenderer(props) {
|
|
|
6064
6110
|
const [hasError, setHasError] = useState(false);
|
|
6065
6111
|
const ref = useRef(null);
|
|
6066
6112
|
const isInViewport = useInViewport(ref);
|
|
6067
|
-
const fullUrl = buildUrl({
|
|
6068
|
-
baseUrl: endpoint,
|
|
6069
|
-
documentId: documentMetadata.documentId,
|
|
6070
|
-
contentHash: documentMetadata.contentHash
|
|
6071
|
-
});
|
|
6072
6113
|
const singleDocumentContainerClassName = `fjs-${type}-single-document-container`;
|
|
6073
6114
|
const errorMessageId = `${domId}-error-message`;
|
|
6074
6115
|
const errorMessage = 'Unable to download document';
|
|
@@ -6081,11 +6122,11 @@ function DocumentRenderer(props) {
|
|
|
6081
6122
|
},
|
|
6082
6123
|
"aria-describedby": hasError ? errorMessageId : undefined,
|
|
6083
6124
|
children: [jsx("img", {
|
|
6084
|
-
src:
|
|
6125
|
+
src: endpoint,
|
|
6085
6126
|
alt: metadata.fileName,
|
|
6086
6127
|
class: `fjs-${type}-image`
|
|
6087
6128
|
}), jsx(DownloadButton, {
|
|
6088
|
-
endpoint:
|
|
6129
|
+
endpoint: endpoint,
|
|
6089
6130
|
fileName: metadata.fileName,
|
|
6090
6131
|
onDownloadError: () => {
|
|
6091
6132
|
setHasError(true);
|
|
@@ -6097,20 +6138,18 @@ function DocumentRenderer(props) {
|
|
|
6097
6138
|
});
|
|
6098
6139
|
}
|
|
6099
6140
|
if (isContentTypePresent && metadata.contentType.toLowerCase() === 'application/pdf' && isInViewport) {
|
|
6100
|
-
return
|
|
6141
|
+
return jsx("div", {
|
|
6101
6142
|
class: singleDocumentContainerClassName,
|
|
6102
6143
|
style: {
|
|
6103
6144
|
maxHeight
|
|
6104
6145
|
},
|
|
6105
6146
|
"aria-describedby": hasError ? errorMessageId : undefined,
|
|
6106
|
-
children:
|
|
6107
|
-
|
|
6108
|
-
|
|
6109
|
-
|
|
6110
|
-
|
|
6111
|
-
|
|
6112
|
-
errors: [errorMessage]
|
|
6113
|
-
}) : null]
|
|
6147
|
+
children: jsx(PdfRenderer, {
|
|
6148
|
+
url: endpoint,
|
|
6149
|
+
fileName: metadata.fileName,
|
|
6150
|
+
onError: () => setHasError(true),
|
|
6151
|
+
errorMessageId: errorMessageId
|
|
6152
|
+
})
|
|
6114
6153
|
});
|
|
6115
6154
|
}
|
|
6116
6155
|
return jsxs("div", {
|
|
@@ -6126,7 +6165,7 @@ function DocumentRenderer(props) {
|
|
|
6126
6165
|
errors: [errorMessage]
|
|
6127
6166
|
}) : null]
|
|
6128
6167
|
}), jsx(DownloadButton, {
|
|
6129
|
-
endpoint:
|
|
6168
|
+
endpoint: endpoint,
|
|
6130
6169
|
fileName: metadata.fileName,
|
|
6131
6170
|
onDownloadError: () => {
|
|
6132
6171
|
setHasError(true);
|
|
@@ -6206,27 +6245,18 @@ function useInViewport(ref) {
|
|
|
6206
6245
|
}
|
|
6207
6246
|
|
|
6208
6247
|
/**
|
|
6209
|
-
*
|
|
6210
|
-
*
|
|
6211
|
-
* @
|
|
6212
|
-
* @param {string} options.baseUrl
|
|
6213
|
-
* @param {string} options.documentId
|
|
6214
|
-
* @param {string} [options.contentHash]
|
|
6215
|
-
*
|
|
6216
|
-
* @returns {string}
|
|
6248
|
+
* @template T
|
|
6249
|
+
* @param {() => T} fn - Function to execute
|
|
6250
|
+
* @returns {T | null}
|
|
6217
6251
|
*/
|
|
6218
|
-
|
|
6219
|
-
|
|
6220
|
-
|
|
6221
|
-
|
|
6222
|
-
|
|
6223
|
-
|
|
6224
|
-
const finalUrl = new URL(baseUrl.replace(DOCUMENT_ID_PLACEHOLDER, documentId));
|
|
6225
|
-
if (contentHash !== undefined) {
|
|
6226
|
-
finalUrl.searchParams.set('contentHash', contentHash);
|
|
6252
|
+
const tryCatch = fn => {
|
|
6253
|
+
try {
|
|
6254
|
+
return fn();
|
|
6255
|
+
} catch (error) {
|
|
6256
|
+
console.error(error);
|
|
6257
|
+
return null;
|
|
6227
6258
|
}
|
|
6228
|
-
|
|
6229
|
-
}
|
|
6259
|
+
};
|
|
6230
6260
|
|
|
6231
6261
|
/**
|
|
6232
6262
|
* This file must not be changed or exchanged.
|
|
@@ -6385,7 +6415,7 @@ class FormFields {
|
|
|
6385
6415
|
}
|
|
6386
6416
|
}
|
|
6387
6417
|
|
|
6388
|
-
const EXPRESSION_PROPERTIES = ['alt', 'appearance.prefixAdorner', 'appearance.suffixAdorner', 'conditional.hide', 'description', 'label', 'source', 'readonly', 'text', 'validate.min', 'validate.max', 'validate.minLength', 'validate.maxLength', 'valuesExpression', 'url', 'dataSource', 'columnsExpression', 'expression', 'multiple', 'accept', '
|
|
6418
|
+
const EXPRESSION_PROPERTIES = ['alt', 'appearance.prefixAdorner', 'appearance.suffixAdorner', 'conditional.hide', 'description', 'label', 'source', 'readonly', 'text', 'validate.min', 'validate.max', 'validate.minLength', 'validate.maxLength', 'valuesExpression', 'url', 'dataSource', 'columnsExpression', 'expression', 'multiple', 'accept', 'title'];
|
|
6389
6419
|
const TEMPLATE_PROPERTIES = ['alt', 'appearance.prefixAdorner', 'appearance.suffixAdorner', 'description', 'label', 'source', 'text', 'content', 'url', 'title'];
|
|
6390
6420
|
|
|
6391
6421
|
/**
|