@evoke-platform/ui-components 1.7.0-testing.3 → 1.7.0-testing.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.
@@ -153,7 +153,7 @@ function FormRenderer(props) {
153
153
  paddingBottom: '0px',
154
154
  paddingTop: !hasSections ? undefined : '0px',
155
155
  } },
156
- entries.map((entry, index) => (React.createElement(RecursiveEntryRenderer, { fieldHeight: fieldHeight, key: index, entry: entry, handleChange: onChange, errors: errors, showSubmitError: !!(isSubmitted && errors), instance: instance, richTextEditor: richTextEditor, expandedSections: expandedSections, setExpandedSections: setExpandedSections, expandAll: expandAll, setExpandAll: setExpandAll, triggerFieldReset: triggerFieldReset, parameters: parameters }))),
156
+ entries.map((entry, index) => (React.createElement(RecursiveEntryRenderer, { fieldHeight: fieldHeight, key: index, entry: entry, handleChange: onChange, errors: errors, showSubmitError: !!(isSubmitted && errors), instance: instance, richTextEditor: richTextEditor, expandedSections: expandedSections, setExpandedSections: setExpandedSections, expandAll: expandAll, setExpandAll: setExpandAll, triggerFieldReset: triggerFieldReset, parameters: parameters, isDocument: !!(form.id === 'documentForm') }))),
157
157
  !hideButtons && (actionId || form.id === 'documentForm') && onSubmit && (React.createElement(Box, { sx: {
158
158
  ...(stickyFooter === false ? { position: 'static' } : { position: 'sticky' }),
159
159
  bottom: isModal ? -5 : isSmallerThanMd ? 0 : 24,
@@ -0,0 +1,21 @@
1
+ import React, { ComponentType } from 'react';
2
+ import { BaseProps, SimpleEditorProps } from './components/types';
3
+ export type FormProps = BaseProps & {
4
+ formId?: string;
5
+ instanceId?: string;
6
+ defaultPages?: Record<string, string>;
7
+ pageNavigation?: string;
8
+ documentId?: string;
9
+ dataType?: 'documents' | 'objectInstances';
10
+ display?: {
11
+ fieldHeight?: 'small' | 'medium';
12
+ };
13
+ actionId?: string;
14
+ stickyFooter?: boolean;
15
+ objectId: string;
16
+ richTextEditor?: ComponentType<SimpleEditorProps>;
17
+ onClose?: () => void;
18
+ onSubmit?: (submission: Record<string, unknown>) => Promise<void>;
19
+ };
20
+ declare function FormRendererContainer(props: FormProps): React.JSX.Element;
21
+ export default FormRendererContainer;
@@ -0,0 +1,489 @@
1
+ import { useApiServices, useApp, useAuthenticationContext, useNavigate, useObject, } from '@evoke-platform/context';
2
+ import { LocalDateTime } from '@js-joda/core';
3
+ import axios from 'axios';
4
+ import { get, isArray, isEmpty, isEqual, merge, omit, pick, set, uniq } from 'lodash';
5
+ import React, { useEffect, useState } from 'react';
6
+ import { Skeleton, Snackbar } from '../../core';
7
+ import { Box } from '../../layout';
8
+ import ErrorComponent from '../ErrorComponent';
9
+ import { evalDefaultVals, processValueUpdate } from './components/DefaultValues';
10
+ import { convertDocToEntries, encodePageSlug, formatDataToDoc, getEntryId, getPrefixedUrl, getUnnestedEntries, isAddressProperty, isEmptyWithDefault, normalizeDateTime, } from './components/utils';
11
+ import FormRenderer from './FormRenderer';
12
+ function FormRendererContainer(props) {
13
+ const { instanceId, pageNavigation, documentId, dataType, display, formId, stickyFooter, objectId, actionId, richTextEditor, } = props;
14
+ const apiServices = useApiServices();
15
+ const navigateTo = useNavigate();
16
+ const { id: appId, defaultPages } = useApp();
17
+ const [hasDocumentUpdateAccess, setHasDocumentUpdateAccess] = useState();
18
+ const [defaultPagesWithSlugs, setDefaultPagesWithSlugs] = useState({});
19
+ const [sanitizedObject, setSanitizedObject] = useState();
20
+ const [navigationSlug, setNavigationSlug] = useState();
21
+ const [parameters, setParameters] = useState();
22
+ const [document, setDocument] = useState();
23
+ const [instance, setInstance] = useState();
24
+ const [formData, setFormData] = useState();
25
+ const [action, setAction] = useState();
26
+ const [error, setError] = useState();
27
+ const [form, setForm] = useState();
28
+ const [snackbarError, setSnackbarError] = useState({
29
+ showAlert: false,
30
+ isError: true,
31
+ });
32
+ const userAccount = useAuthenticationContext()?.account;
33
+ const objectStore = useObject(form?.objectId ?? objectId);
34
+ const onError = (err) => {
35
+ const code = axios.isAxiosError(err) ? err.response?.status : undefined;
36
+ setSnackbarError({ ...snackbarError, isError: true });
37
+ setError(code ?? true);
38
+ };
39
+ useEffect(() => {
40
+ (async () => {
41
+ try {
42
+ if (dataType === 'documents') {
43
+ const object = await objectStore.get({ sanitized: true });
44
+ const document = await apiServices.get(getPrefixedUrl(`/objects/${objectId}/instances/${instanceId}/documents/${documentId}`));
45
+ if (document) {
46
+ setDocument(document);
47
+ const accessCheck = await apiServices.get(getPrefixedUrl(`/objects/${objectId}/instances/${instanceId}/documents/${documentId}/checkAccess?action=update`));
48
+ setHasDocumentUpdateAccess(accessCheck.result);
49
+ }
50
+ setSanitizedObject(omit(object, 'properties'));
51
+ }
52
+ else {
53
+ if (instanceId) {
54
+ objectStore.getInstance(instanceId).then((instance) => {
55
+ setInstance(instance);
56
+ });
57
+ }
58
+ const object = await apiServices.get(getPrefixedUrl(`/objects/${form?.objectId || objectId}${instanceId ? `/instances/${instanceId}/object` : '/effective'}`), { params: { sanitizedVersion: true } });
59
+ setSanitizedObject(object);
60
+ const action = object?.actions?.find((a) => a.id === (form?.actionId || actionId));
61
+ if (action && (instanceId || action.type === 'create')) {
62
+ setAction(action);
63
+ }
64
+ else {
65
+ setError(true);
66
+ }
67
+ }
68
+ }
69
+ catch (error) {
70
+ onError(error);
71
+ }
72
+ })();
73
+ }, [dataType, form, instanceId, documentId]);
74
+ useEffect(() => {
75
+ if (pageNavigation) {
76
+ apiServices
77
+ .get(getPrefixedUrl(`/apps/${appId}/pages/${encodePageSlug(pageNavigation)}`))
78
+ .then((page) => {
79
+ setNavigationSlug(page?.slug);
80
+ });
81
+ }
82
+ if (defaultPages) {
83
+ for (const [objectId, defaultPage] of Object.entries(defaultPages)) {
84
+ const pageId = defaultPage.includes('/')
85
+ ? encodePageSlug(defaultPage.split('/').slice(2).join('/'))
86
+ : defaultPage;
87
+ apiServices.get(getPrefixedUrl(`/apps/${appId}/pages/${pageId}`)).then((page) => {
88
+ setDefaultPagesWithSlugs({
89
+ ...defaultPagesWithSlugs,
90
+ [objectId]: '/' + page.appId + '/' + page.slug,
91
+ });
92
+ });
93
+ }
94
+ }
95
+ }, []);
96
+ useEffect(() => {
97
+ if (dataType === 'documents' || form)
98
+ return;
99
+ if (formId || action?.defaultFormId) {
100
+ apiServices
101
+ .get(getPrefixedUrl(`data/forms/${formId || action?.defaultFormId}`))
102
+ .then((evokeForm) => {
103
+ if (evokeForm?.actionId === actionId) {
104
+ setForm(evokeForm);
105
+ }
106
+ else {
107
+ setError(true);
108
+ }
109
+ })
110
+ .catch((error) => {
111
+ onError(error);
112
+ });
113
+ }
114
+ else if (action && !action?.defaultFormId) {
115
+ apiServices
116
+ .get(getPrefixedUrl(`data/forms?filter[where][actionId]=${action.id}`))
117
+ .then((matchingForms) => {
118
+ if (matchingForms.length === 1) {
119
+ if (matchingForms[0]?.actionId === actionId) {
120
+ setForm(matchingForms[0]);
121
+ }
122
+ else {
123
+ setError(true);
124
+ }
125
+ }
126
+ })
127
+ .catch((error) => {
128
+ onError(error);
129
+ });
130
+ }
131
+ }, [action]);
132
+ useEffect(() => {
133
+ if (form?.id === 'documentForm') {
134
+ setParameters([
135
+ {
136
+ id: 'type',
137
+ name: 'Type',
138
+ type: 'string',
139
+ },
140
+ {
141
+ id: 'view_permission',
142
+ name: 'View Permission',
143
+ type: 'string',
144
+ enum: ['Public', 'Private', 'Portal'],
145
+ },
146
+ ]);
147
+ }
148
+ else if (form) {
149
+ const unnestedEntries = getUnnestedEntries(form.entries);
150
+ const inputFieldParams = unnestedEntries
151
+ .filter((entry) => entry.type === 'inputField')
152
+ .map((entry) => entry.input);
153
+ setParameters(uniq([...(action?.parameters ?? []), ...inputFieldParams]));
154
+ }
155
+ }, [form, action]);
156
+ useEffect(() => {
157
+ const getInitialValues = async () => {
158
+ if (document && objectId) {
159
+ const defaultValues = await getDefaultValues(convertDocToEntries(document), document);
160
+ setFormData(defaultValues);
161
+ if (!form) {
162
+ setForm({
163
+ id: 'documentForm',
164
+ name: 'Document Form',
165
+ entries: convertDocToEntries(document),
166
+ objectId: objectId,
167
+ });
168
+ }
169
+ }
170
+ else if (form && (instance || !instanceId)) {
171
+ const defaultValues = await getDefaultValues(form.entries, instance || {});
172
+ setFormData(defaultValues);
173
+ }
174
+ };
175
+ getInitialValues();
176
+ }, [form, instance, sanitizedObject]);
177
+ const uploadDocuments = async (files, metadata) => {
178
+ const allDocuments = [];
179
+ const formData = new FormData();
180
+ for (const [index, file] of files.entries()) {
181
+ if ('size' in file) {
182
+ formData.append(`files[${index}]`, file);
183
+ }
184
+ else {
185
+ allDocuments.push(file);
186
+ }
187
+ }
188
+ if (metadata) {
189
+ for (const [key, value] of Object.entries(metadata)) {
190
+ formData.append(key, value);
191
+ }
192
+ }
193
+ const docs = await apiServices?.post(getPrefixedUrl(`/objects/${form?.objectId}/instances/${instanceId}/documents`), formData);
194
+ return allDocuments.concat(docs?.map((doc) => ({
195
+ id: doc.id,
196
+ name: doc.name,
197
+ })) ?? []);
198
+ };
199
+ const deleteDocuments = async (submittedFields, requestSuccess, action) => {
200
+ const documentProperties = action?.parameters
201
+ ? action.parameters.filter((param) => param.type === 'document')
202
+ : sanitizedObject?.properties?.filter((prop) => prop.type === 'document');
203
+ for (const docProperty of documentProperties ?? []) {
204
+ const savedValue = submittedFields[docProperty.id];
205
+ const originalValue = instance?.[docProperty.id];
206
+ const documentsToRemove = requestSuccess
207
+ ? (originalValue?.filter((file) => !savedValue?.some((f) => f.id === file.id)) ?? [])
208
+ : (savedValue?.filter((file) => !originalValue?.some((f) => f.id === file.id)) ?? []);
209
+ for (const doc of documentsToRemove) {
210
+ try {
211
+ await apiServices?.delete(getPrefixedUrl(`/objects/${form?.objectId}/instances/${instanceId}/documents/${doc.id}`));
212
+ }
213
+ catch (error) {
214
+ if (error) {
215
+ setSnackbarError({
216
+ showAlert: true,
217
+ message: `An error occurred while removing document '${doc.name}'`,
218
+ isError: true,
219
+ });
220
+ }
221
+ }
222
+ }
223
+ }
224
+ };
225
+ const onSubmissionSuccess = (updatedInstance) => {
226
+ setSnackbarError({
227
+ showAlert: true,
228
+ message: 'Your changes have been submitted',
229
+ isError: false,
230
+ });
231
+ if (navigationSlug) {
232
+ if (navigationSlug.includes(':instanceId') && navigationSlug.includes(':documentId')) {
233
+ navigateTo(`/${appId}/${navigationSlug
234
+ .replace(':instanceId', instanceId ?? ':instanceId')
235
+ .replace(':documentId', documentId ?? ':documentId')}`);
236
+ }
237
+ else if (navigationSlug.includes(':instanceId')) {
238
+ const navigateInstanceId = action?.type === 'create' ? updatedInstance?.id : instanceId;
239
+ navigateTo(`/${appId}/${navigationSlug.replace(':instanceId', navigateInstanceId ?? ':instanceId')}`);
240
+ }
241
+ else {
242
+ navigateTo(`/${appId}/${navigationSlug}`);
243
+ }
244
+ }
245
+ setInstance(updatedInstance);
246
+ };
247
+ const saveHandler = async (submission) => {
248
+ if (!form)
249
+ return;
250
+ // checks for a file upload and handles getting the new format to upload
251
+ for (const [key, value] of Object.entries(submission)) {
252
+ if (isArray(value)) {
253
+ const fileInArray = value.some((item) => item instanceof File);
254
+ if (fileInArray) {
255
+ try {
256
+ const uploadedDocuments = await uploadDocuments(value, {
257
+ type: '',
258
+ view_permission: '',
259
+ });
260
+ submission[key] = uploadedDocuments;
261
+ }
262
+ catch (err) {
263
+ if (err) {
264
+ setSnackbarError({
265
+ showAlert: true,
266
+ message: `An error occurred while uploading associated documents`,
267
+ isError: true,
268
+ });
269
+ }
270
+ return;
271
+ }
272
+ }
273
+ // if there are address fields with no value address needs to be set to undefined to be able to submit
274
+ }
275
+ else if (typeof value === 'object' && value !== null) {
276
+ if (Object.values(value).every((v) => v === undefined)) {
277
+ submission[key] = undefined;
278
+ // only submit the name and id of a related object
279
+ }
280
+ else if ('id' in value && 'name' in value) {
281
+ submission[key] = pick(value, 'id', 'name');
282
+ }
283
+ }
284
+ else if ((value === '' && !document) || value === undefined) {
285
+ submission[key] = null;
286
+ }
287
+ else if (value instanceof LocalDateTime) {
288
+ submission[key] = normalizeDateTime(value);
289
+ }
290
+ }
291
+ if (document) {
292
+ submission = formatDataToDoc(submission);
293
+ }
294
+ try {
295
+ if (dataType === 'documents' && !!document) {
296
+ try {
297
+ await apiServices.patch(getPrefixedUrl(`/objects/${form.objectId}/instances/${instanceId}/documents/${documentId}`), pick(submission, ['metadata']).metadata ?? submission);
298
+ setDocument((prev) => ({
299
+ ...prev,
300
+ metadata: submission.metadata,
301
+ }));
302
+ setSnackbarError({
303
+ showAlert: true,
304
+ message: 'Your changes have been submitted',
305
+ isError: false,
306
+ });
307
+ }
308
+ catch (error) {
309
+ setSnackbarError({
310
+ isError: true,
311
+ showAlert: true,
312
+ message: error.response?.data?.error?.message ?? 'An error occurred',
313
+ });
314
+ }
315
+ }
316
+ else if (action?.type === 'create') {
317
+ const response = await apiServices.post(getPrefixedUrl(`/objects/${form.objectId}/instances/actions`), {
318
+ actionId: form.actionId,
319
+ input: pick(submission, sanitizedObject?.properties
320
+ ?.filter((property) => !property.formula && property.type !== 'collection')
321
+ .map((property) => property.id) ?? []),
322
+ });
323
+ if (response) {
324
+ onSubmissionSuccess(response);
325
+ }
326
+ }
327
+ else if (instanceId && action) {
328
+ const response = await objectStore.instanceAction(instanceId, {
329
+ actionId: action.id,
330
+ input: pick(submission, sanitizedObject?.properties
331
+ ?.filter((property) => !property.formula && property.type !== 'collection')
332
+ .map((property) => property.id) ?? []),
333
+ });
334
+ if (response) {
335
+ onSubmissionSuccess(response);
336
+ deleteDocuments(submission, !!response, action ?? undefined);
337
+ }
338
+ }
339
+ }
340
+ catch (error) {
341
+ setSnackbarError({
342
+ isError: true,
343
+ showAlert: true,
344
+ message: error.response?.data?.error?.message ?? 'An error occurred',
345
+ });
346
+ }
347
+ };
348
+ const getDefaultValues = async (entries, instanceData) => {
349
+ const result = {};
350
+ const processEntries = async (entries) => {
351
+ if (!entries)
352
+ return;
353
+ for (const entry of entries) {
354
+ if (entry.type === 'sections' || entry.type === 'columns') {
355
+ const subEntries = entry.type === 'sections' ? entry.sections : entry.columns;
356
+ for (const subEntry of subEntries) {
357
+ if (subEntry.entries) {
358
+ const nested = await getDefaultValues(subEntry.entries, instanceData);
359
+ merge(result, nested);
360
+ }
361
+ }
362
+ }
363
+ if ((entry.type === 'input' || entry.type === 'inputField') &&
364
+ isAddressProperty(entry.parameterId || entry.input?.id)) {
365
+ const fieldId = getEntryId(entry);
366
+ if (!fieldId)
367
+ return;
368
+ const fieldValue = get(instanceData, fieldId);
369
+ if ((isEmpty(instanceData) ||
370
+ fieldValue === undefined ||
371
+ fieldValue === null ||
372
+ fieldValue === '') &&
373
+ entry?.display?.defaultValue &&
374
+ parameters) {
375
+ const defaultValuesArray = await evalDefaultVals(parameters, entry, fieldValue, fieldId, apiServices, userAccount, instanceData);
376
+ if (isArray(defaultValuesArray)) {
377
+ defaultValuesArray.forEach(({ fieldId, fieldValue }) => {
378
+ set(result, fieldId, fieldValue);
379
+ });
380
+ }
381
+ }
382
+ else if (fieldValue !== undefined && fieldValue !== null) {
383
+ set(result, fieldId, fieldValue);
384
+ }
385
+ }
386
+ else if (entry.type !== 'sections' && entry.type !== 'columns' && entry.type !== 'content') {
387
+ const fieldId = entry.type === 'input'
388
+ ? entry.parameterId
389
+ : entry.type === 'inputField'
390
+ ? entry.input?.id
391
+ : undefined;
392
+ if (fieldId) {
393
+ const fieldValue = instanceData?.[fieldId] ??
394
+ instanceData?.metadata?.[fieldId];
395
+ const parameter = parameters?.find((param) => param.id === fieldId);
396
+ if (entry.type !== 'readonlyField' && isEmptyWithDefault(fieldValue, entry, instanceData)) {
397
+ if (fieldId && parameters && parameters.length > 0) {
398
+ const defaultValuesArray = await evalDefaultVals(parameters, entry, fieldValue, fieldId, apiServices, userAccount, instanceData);
399
+ for (const { fieldId, fieldValue } of defaultValuesArray) {
400
+ const parameter = parameters?.find((param) => param.id === fieldId);
401
+ if (parameter?.type === 'object') {
402
+ const dependentFields = await processValueUpdate(form?.entries, parameters, fieldValue, apiServices, fieldId, formData, userAccount);
403
+ for (const field of dependentFields) {
404
+ set(result, field.fieldId, field.fieldValue);
405
+ }
406
+ }
407
+ set(result, fieldId, fieldValue);
408
+ }
409
+ }
410
+ }
411
+ else if (parameter?.type === 'boolean' && (fieldValue === undefined || fieldValue === null)) {
412
+ result[fieldId] = false;
413
+ }
414
+ else if (fieldValue !== undefined && fieldValue !== null) {
415
+ result[fieldId] = fieldValue;
416
+ }
417
+ }
418
+ }
419
+ }
420
+ };
421
+ await processEntries(entries);
422
+ return result;
423
+ };
424
+ async function onChange(id, value) {
425
+ const parameter = parameters?.find((param) => param.id === id);
426
+ const entries = getUnnestedEntries(form.entries);
427
+ const isReadOnlyField = entries.some((e) => e.type === 'readonlyField' && e.propertyId === id) &&
428
+ !entries.some((e) => (e.type === 'input' && e.parameterId === id) || (e.type === 'inputField' && e.input.id === id));
429
+ if (isReadOnlyField)
430
+ return;
431
+ if (parameter) {
432
+ if (parameter.type === 'object' && parameters && parameters.length > 0) {
433
+ // On change of a related object, update default values dependent on that object
434
+ const dependentFields = await processValueUpdate(form?.entries, parameters, value, apiServices, id, formData, userAccount);
435
+ for (const field of dependentFields) {
436
+ onChange(field.fieldId, field.fieldValue);
437
+ }
438
+ }
439
+ else if (parameter.type === 'string' && parameter.enum && value) {
440
+ // If a single select property has a sortBy option that isn't NONE the value gets spread and doesn't save properly,
441
+ // this will make it correctly save the value
442
+ value = value.value ? value.value : value;
443
+ }
444
+ }
445
+ if (!isEqual(value, get(formData, id))) {
446
+ setFormData((prev) => {
447
+ const newData = { ...prev };
448
+ set(newData, id, value);
449
+ return newData;
450
+ });
451
+ }
452
+ }
453
+ function onCancel() {
454
+ (async () => {
455
+ if (document) {
456
+ const defaultValues = await getDefaultValues(convertDocToEntries(document), document);
457
+ setFormData(defaultValues);
458
+ }
459
+ else if (form) {
460
+ const defaultValues = await getDefaultValues(form.entries, instance || {});
461
+ setFormData(defaultValues);
462
+ }
463
+ })();
464
+ }
465
+ const isLoading = (instanceId && !formData && !document) || !form || !sanitizedObject;
466
+ return !error ? (React.createElement(Box, { sx: {
467
+ backgroundColor: '#ffffff',
468
+ borderRadius: '6px',
469
+ padding: '0px',
470
+ border: !isLoading ? '1px solid #dbe0e4' : undefined,
471
+ } },
472
+ !isLoading ? (React.createElement(React.Fragment, null,
473
+ React.createElement(FormRenderer, { onSubmit: saveHandler, hideButtons: document && !hasDocumentUpdateAccess, richTextEditor: richTextEditor, fieldHeight: display?.fieldHeight ?? 'medium', value: formData, stickyFooter: stickyFooter, form: form, instance: dataType !== 'documents' ? instance : document, onChange: onChange, onCancel: onCancel }))) : (React.createElement(Box, { sx: { padding: '20px' } },
474
+ React.createElement(Box, { display: 'flex', width: '100%', justifyContent: 'space-between' },
475
+ React.createElement(Skeleton, { width: '78%', sx: { borderRadius: '8px', height: '40px' } }),
476
+ React.createElement(Skeleton, { width: '20%', sx: { borderRadius: '8px', height: '40px' } })),
477
+ React.createElement(Box, { display: 'flex', width: '100%', justifyContent: 'space-between' },
478
+ React.createElement(Skeleton, { width: '32%', sx: { borderRadius: '8px', height: '40px' } }),
479
+ React.createElement(Skeleton, { width: '33%', sx: { borderRadius: '8px', height: '40px' } }),
480
+ React.createElement(Skeleton, { width: '32%', sx: { borderRadius: '8px', height: '40px' } })),
481
+ React.createElement(Box, { display: 'flex', width: '100%', justifyContent: 'space-between' },
482
+ React.createElement(Skeleton, { width: '49%', sx: { borderRadius: '8px', height: '40px' } }),
483
+ React.createElement(Skeleton, { width: '49%', sx: { borderRadius: '8px', height: '40px' } })))),
484
+ React.createElement(Snackbar, { open: snackbarError.showAlert, handleClose: () => setSnackbarError({
485
+ isError: snackbarError.isError,
486
+ showAlert: false,
487
+ }), message: snackbarError.message, error: snackbarError.isError }))) : (React.createElement(ErrorComponent, { colspan: props.colspan, code: error === 403 ? 'AccessDenied' : error === 404 ? 'NotFound' : 'Misconfigured' }));
488
+ }
489
+ export default FormRendererContainer;
@@ -0,0 +1,10 @@
1
+ import { ApiServices, FormEntry, InputField, InputParameter, InputParameterReference, ObjectInstance, Reference, UserAccount } from '@evoke-platform/context';
2
+ import { FieldValues } from 'react-hook-form';
3
+ export declare function evalDefaultVals(parameters: InputParameter[], entry: InputParameterReference | InputField, fieldValue: unknown, fieldId: string, apiServices: ApiServices, userAccount?: UserAccount, formValues?: FieldValues, updatedRelatedObjectValue?: ObjectInstance | null | Reference): Promise<{
4
+ fieldId: string;
5
+ fieldValue: unknown;
6
+ }[]>;
7
+ export declare function processValueUpdate(entries: FormEntry[] | undefined, parameters: InputParameter[], updatedRelatedObjectValue: ObjectInstance | null | Reference, apiServices: ApiServices, changedEntryId?: string, formValues?: FieldValues, userAccount?: UserAccount): Promise<{
8
+ fieldId: string;
9
+ fieldValue: unknown;
10
+ }[]>;
@@ -0,0 +1,208 @@
1
+ import { isArray, isEmpty, uniq } from 'lodash';
2
+ import { DateTime } from 'luxon';
3
+ import { getEntryId, getPrefixedUrl, isAddressProperty } from './utils';
4
+ export async function evalDefaultVals(parameters, entry, fieldValue, fieldId, apiServices, userAccount, formValues, updatedRelatedObjectValue) {
5
+ const updates = [];
6
+ const parameter = parameters.find((param) => param.id === fieldId);
7
+ const defaultValue = entry.display?.defaultValue;
8
+ // Handles dynamic default values
9
+ // Identifies a combination of static and dynamic values mixed in the same array,
10
+ // Example of mixed values: ["{{input.relatedObject.nestedProperty}}", "{{input.secondRelatedObject.nestedProperty}}", "option1"]
11
+ if (isArray(defaultValue) && defaultValue.some((item) => /^{{.*}}$/.test(item))) {
12
+ const staticValues = defaultValue.filter((item) => !/^{{.*}}$/.test(item));
13
+ for (const item of defaultValue.filter((item) => /^{{.*}}$/.test(item))) {
14
+ const regex = /^{{input\.(?<relatedObjectProperty>[a-zA-Z][a-zA-Z0-9_]*)\.(?<nestedProperty>[a-zA-Z][a-zA-Z0-9_]*)}}$/;
15
+ const groups = regex.exec(item)?.groups;
16
+ if (groups?.relatedObjectProperty && groups?.nestedProperty) {
17
+ const relatedObjectParameter = parameters.find((param) => param.id === groups?.relatedObjectProperty);
18
+ let relatedObject = updatedRelatedObjectValue;
19
+ if (!relatedObject && !isEmpty(formValues)) {
20
+ relatedObject = formValues[groups.relatedObjectProperty];
21
+ }
22
+ if (updatedRelatedObjectValue?.[groups.nestedProperty]) {
23
+ fieldValue = uniq([
24
+ ...staticValues,
25
+ ...(isArray(updatedRelatedObjectValue[groups.nestedProperty])
26
+ ? updatedRelatedObjectValue[groups.nestedProperty]
27
+ : []),
28
+ ]);
29
+ updates.push({ fieldId, fieldValue });
30
+ }
31
+ else if (relatedObject && relatedObject.id && relatedObjectParameter) {
32
+ const instance = await new Promise((resolve) => {
33
+ apiServices.get(getPrefixedUrl(`/objects/${relatedObjectParameter.objectId}/instances/${relatedObject?.id}`), (error, instance) => {
34
+ if (error) {
35
+ console.error(error);
36
+ return resolve(undefined);
37
+ }
38
+ resolve(instance);
39
+ });
40
+ });
41
+ if (instance) {
42
+ fieldValue = uniq([
43
+ ...staticValues,
44
+ ...(isArray(instance[groups.nestedProperty])
45
+ ? instance[groups.nestedProperty]
46
+ : []),
47
+ ]);
48
+ updates.push({ fieldId, fieldValue });
49
+ }
50
+ }
51
+ else {
52
+ updates.push({ fieldId, fieldValue: staticValues });
53
+ }
54
+ }
55
+ else {
56
+ staticValues.length > 0 && updates.push({ fieldId, fieldValue: staticValues });
57
+ }
58
+ }
59
+ // Identifies dynamic values using Handlebars syntax: {{input.relatedObject.nestedProperty}} or {{input.relatedObject.address.nestedAddressProperty}}
60
+ }
61
+ else if (typeof defaultValue === 'string' && /^{{.*}}$/.test(defaultValue)) {
62
+ if (isAddressProperty(fieldId)) {
63
+ const regex = /^{{input\.(?<relatedObjectProperty>[a-zA-Z][a-zA-Z0-9_]*)\.(?<addressProperty>[a-zA-Z][a-zA-Z0-9_]*)\.(?<nestedAddressProperty>line1|line2|city|county|state|zipCode)}}$/;
64
+ const groups = regex.exec(defaultValue)?.groups;
65
+ if (groups?.relatedObjectProperty && groups?.addressProperty && groups?.nestedAddressProperty) {
66
+ const relatedObjectParameter = parameters.find((param) => param.id === groups?.relatedObjectProperty);
67
+ let relatedObject = updatedRelatedObjectValue;
68
+ if (!relatedObject && !isEmpty(formValues)) {
69
+ relatedObject = formValues[groups.relatedObjectProperty];
70
+ }
71
+ if (updatedRelatedObjectValue?.[groups.addressProperty]?.[groups.nestedAddressProperty]) {
72
+ fieldValue = updatedRelatedObjectValue?.[groups.addressProperty]?.[groups.nestedAddressProperty];
73
+ updates.push({ fieldId, fieldValue });
74
+ }
75
+ else if (relatedObject && relatedObject.id && relatedObjectParameter) {
76
+ const instance = await new Promise((resolve) => {
77
+ apiServices.get(getPrefixedUrl(`/objects/${relatedObjectParameter.objectId}/instances/${relatedObject?.id}`), (error, instance) => {
78
+ if (error) {
79
+ console.error(error);
80
+ return resolve(undefined);
81
+ }
82
+ resolve(instance);
83
+ });
84
+ });
85
+ // Clear dependent fields only if value is explicitly null (user cleared it).
86
+ // If updatedRelatedObjectValue is undefined (not triggered by onChange), use the value from the instance.
87
+ if (updatedRelatedObjectValue === null) {
88
+ updates.push({ fieldId, fieldValue: '' });
89
+ }
90
+ else if (instance) {
91
+ fieldValue = instance?.[groups.addressProperty]?.[groups.nestedAddressProperty];
92
+ updates.push({ fieldId, fieldValue });
93
+ }
94
+ }
95
+ }
96
+ }
97
+ else {
98
+ const regex = /^{{input\.(?<relatedObjectProperty>[a-zA-Z][a-zA-Z0-9_]*)\.(?<nestedProperty>[a-zA-Z][a-zA-Z0-9_]*)}}$/;
99
+ const groups = regex.exec(defaultValue)?.groups;
100
+ if (groups?.relatedObjectProperty && groups?.nestedProperty) {
101
+ const relatedObjectParameter = parameters.find((param) => param.id === groups?.relatedObjectProperty);
102
+ let relatedObject = updatedRelatedObjectValue;
103
+ if (!relatedObject && !isEmpty(formValues)) {
104
+ relatedObject = formValues[groups.relatedObjectProperty];
105
+ }
106
+ if (updatedRelatedObjectValue?.[groups.nestedProperty]) {
107
+ fieldValue = updatedRelatedObjectValue[groups.nestedProperty];
108
+ updates.push({ fieldId, fieldValue });
109
+ }
110
+ else if (relatedObject?.id && relatedObjectParameter) {
111
+ const instance = await new Promise((resolve) => {
112
+ apiServices.get(getPrefixedUrl(`/objects/${relatedObjectParameter.objectId}/instances/${relatedObject?.id}`), (error, instance) => {
113
+ if (error) {
114
+ console.error(error);
115
+ return resolve(undefined);
116
+ }
117
+ resolve(instance);
118
+ });
119
+ });
120
+ // Clear dependent fields only if value is explicitly null (user cleared it).
121
+ // If updatedRelatedObjectValue is undefined (not triggered by onChange), use the value from the instance.
122
+ if (updatedRelatedObjectValue === null) {
123
+ updates.push({ fieldId, fieldValue: null });
124
+ }
125
+ else if (instance) {
126
+ fieldValue = instance?.[groups.nestedProperty] || null;
127
+ updates.push({ fieldId, fieldValue });
128
+ }
129
+ }
130
+ }
131
+ }
132
+ // all other default values set here
133
+ }
134
+ else if (parameter?.type !== 'object') {
135
+ let updatedValue = defaultValue;
136
+ // handles current default values ie: "Current logged in user", "Today" etc.
137
+ if (updatedValue === 'currentDate') {
138
+ updatedValue = DateTime.now().toISODate();
139
+ }
140
+ else if (updatedValue === 'currentTime') {
141
+ updatedValue = DateTime.now().toISOTime({
142
+ includeOffset: false,
143
+ suppressMilliseconds: true,
144
+ });
145
+ }
146
+ else if (updatedValue === 'currentDateTime') {
147
+ updatedValue = DateTime.now().toISO();
148
+ }
149
+ else if (updatedValue === '$_CURRENT') {
150
+ updatedValue = { name: userAccount?.name, id: userAccount?.id };
151
+ }
152
+ updates.push({ fieldId, fieldValue: updatedValue });
153
+ }
154
+ return updates;
155
+ }
156
+ export async function processValueUpdate(entries, parameters, updatedRelatedObjectValue, apiServices, changedEntryId, formValues, userAccount) {
157
+ const updates = [];
158
+ for (const entry of entries || []) {
159
+ if (entry.type === 'sections' || entry.type === 'columns') {
160
+ const subEntries = entry.type === 'sections' ? entry.sections : entry.columns;
161
+ for (const subEntry of subEntries) {
162
+ const subUpdates = await processValueUpdate(subEntry.entries, parameters, updatedRelatedObjectValue, apiServices, changedEntryId, formValues, userAccount);
163
+ updates.push(...subUpdates);
164
+ }
165
+ }
166
+ if ((entry.type === 'input' || entry.type === 'inputField') && entry?.display?.defaultValue) {
167
+ const parameterId = getEntryId(entry);
168
+ if (!parameterId)
169
+ return [];
170
+ if (isAddressProperty(parameterId)) {
171
+ const regex = /^{{input\.(?<relatedObjectProperty>[a-zA-Z][a-zA-Z0-9_]*)\.(?<addressProperty>[a-zA-Z][a-zA-Z0-9_]*)\.(?<nestedAddressProperty>line1|line2|city|county|state|zipCode)}}$/;
172
+ const groups = regex.exec(entry.display.defaultValue)?.groups;
173
+ const [addressObject, addressField] = parameterId.split('.');
174
+ if (groups?.relatedObjectProperty &&
175
+ groups?.addressProperty &&
176
+ groups?.nestedAddressProperty &&
177
+ changedEntryId === groups.relatedObjectProperty) {
178
+ const result = await evalDefaultVals(parameters, entry, formValues?.[addressObject]?.[addressField], parameterId, apiServices, userAccount, formValues, updatedRelatedObjectValue);
179
+ updates.push(...result);
180
+ }
181
+ }
182
+ else if (isArray(entry.display.defaultValue) &&
183
+ entry.display.defaultValue.some((item) => /^{{.*}}$/.test(item))) {
184
+ for (const item of entry.display.defaultValue.filter((item) => /^{{.*}}$/.test(item))) {
185
+ const regex = /^{{input\.(?<relatedObjectProperty>[a-zA-Z][a-zA-Z0-9_]*)\.(?<nestedProperty>[a-zA-Z][a-zA-Z0-9_]*)}}$/;
186
+ const groups = regex.exec(item)?.groups;
187
+ if (groups?.relatedObjectProperty &&
188
+ groups?.nestedProperty &&
189
+ changedEntryId === groups.relatedObjectProperty) {
190
+ const result = await evalDefaultVals(parameters, entry, entry.display.defaultValue, parameterId, apiServices, userAccount, formValues, updatedRelatedObjectValue);
191
+ updates.push(...result);
192
+ }
193
+ }
194
+ }
195
+ else {
196
+ const regex = /^{{input\.(?<relatedObjectProperty>[a-zA-Z][a-zA-Z0-9_]*)\.(?<nestedProperty>[a-zA-Z][a-zA-Z0-9_]*)}}$/;
197
+ const groups = regex.exec(entry.display.defaultValue)?.groups;
198
+ if (groups?.relatedObjectProperty &&
199
+ groups?.nestedProperty &&
200
+ changedEntryId === groups.relatedObjectProperty) {
201
+ const result = await evalDefaultVals(parameters, entry, formValues?.[parameterId], parameterId, apiServices, userAccount, formValues, updatedRelatedObjectValue);
202
+ updates.push(...result);
203
+ }
204
+ }
205
+ }
206
+ }
207
+ return updates;
208
+ }
@@ -18,7 +18,7 @@ import { Image } from './FormFieldTypes/Image';
18
18
  import ObjectPropertyInput from './FormFieldTypes/relatedObjectFiles/ObjectPropertyInput';
19
19
  import UserProperty from './FormFieldTypes/UserProperty';
20
20
  import FormSections from './FormSections';
21
- import { entryIsVisible, fetchCollectionData, getEntryId, isAddressProperty, isOptionEqualToValue, updateCriteriaInputs, } from './utils';
21
+ import { docProperties, entryIsVisible, fetchCollectionData, getEntryId, isAddressProperty, isOptionEqualToValue, updateCriteriaInputs, } from './utils';
22
22
  function getFieldWrapperProps(fieldDefinition, entry, entryId, fieldValue, display, fieldHeight, errors, validation) {
23
23
  return {
24
24
  inputId: entryId,
@@ -38,7 +38,7 @@ function getFieldWrapperProps(fieldDefinition, entry, entryId, fieldValue, displ
38
38
  };
39
39
  }
40
40
  export function RecursiveEntryRenderer(props) {
41
- const { handleChange, errors, showSubmitError, fieldHeight, instance, richTextEditor, expandedSections, setExpandedSections, expandAll, setExpandAll, parameters, entry, triggerFieldReset, } = props;
41
+ const { handleChange, errors, showSubmitError, fieldHeight, instance, richTextEditor, expandedSections, setExpandedSections, expandAll, setExpandAll, parameters, entry, triggerFieldReset, isDocument, } = props;
42
42
  const { fetchedOptions, setFetchedOptions, object, getValues } = useFormContext();
43
43
  // If the entry is hidden, clear its value and any nested values, and skip rendering
44
44
  if (!entryIsVisible(entry, getValues(), instance)) {
@@ -58,9 +58,11 @@ export function RecursiveEntryRenderer(props) {
58
58
  def = parameters?.find((param) => param.id === entry.parameterId);
59
59
  }
60
60
  else if (entry.type === 'readonlyField') {
61
- def = isAddressProperty(entry.propertyId)
62
- ? object?.properties?.find((prop) => prop.id === entry.propertyId.split('.')[0])
63
- : object?.properties?.find((prop) => prop.id === entry.propertyId);
61
+ def = isDocument
62
+ ? docProperties.find((prop) => prop.id === entry.propertyId)
63
+ : isAddressProperty(entry.propertyId)
64
+ ? object?.properties?.find((prop) => prop.id === entry.propertyId.split('.')[0])
65
+ : object?.properties?.find((prop) => prop.id === entry.propertyId);
64
66
  }
65
67
  else if (entry.type === 'inputField') {
66
68
  def = entry.input;
@@ -104,6 +104,7 @@ export type EntryRendererProps = BaseProps & {
104
104
  parameters?: InputParameter[];
105
105
  readOnly?: boolean;
106
106
  triggerFieldReset?: boolean;
107
+ isDocument?: boolean;
107
108
  };
108
109
  export type SectionsProps = {
109
110
  entry: Sections;
@@ -120,3 +121,13 @@ export type SectionsProps = {
120
121
  triggerFieldReset?: boolean;
121
122
  showSubmitError?: boolean;
122
123
  };
124
+ export type DocumentData = {
125
+ id: string;
126
+ name: string;
127
+ contentType: string;
128
+ size: number;
129
+ uploadedDate: string;
130
+ versionId: string;
131
+ type: string;
132
+ view_permission: string;
133
+ };
@@ -1,8 +1,8 @@
1
- import { ApiServices, Column, Columns, FormEntry, InputParameter, Obj, ObjectInstance, Property, Section, Sections, UserAccount } from '@evoke-platform/context';
1
+ import { ApiServices, Column, Columns, FormEntry, InputField, InputParameter, InputParameterReference, Obj, ObjectInstance, Property, Section, Sections, UserAccount } from '@evoke-platform/context';
2
2
  import { LocalDateTime } from '@js-joda/core';
3
3
  import { FieldErrors, FieldValues } from 'react-hook-form';
4
4
  import { AutocompleteOption } from '../../../core';
5
- import { Document } from './types';
5
+ import { Document, DocumentData } from './types';
6
6
  export declare const scrollIntoViewWithOffset: (el: HTMLElement, offset: number, container?: HTMLElement) => void;
7
7
  export declare const normalizeDateTime: (dateTime: LocalDateTime) => string;
8
8
  export declare function isAddressProperty(key: string): boolean;
@@ -45,3 +45,19 @@ export declare const convertDocToParameters: (obj: Document) => InputParameter[]
45
45
  export declare const propertyToParameter: (property: Property) => InputParameter;
46
46
  export declare const propertyValidationToParameterValidation: (property: Property) => InputParameter['validation'];
47
47
  export declare const convertPropertiesToParams: (object: Obj) => InputParameter[] | undefined;
48
+ export declare function convertDocToEntries(document: Document): FormEntry[];
49
+ export declare function formatDataToDoc(data: DocumentData): {
50
+ id: string;
51
+ name: string;
52
+ contentType: string;
53
+ size: number;
54
+ uploadedDate: string;
55
+ versionId: string;
56
+ metadata: {
57
+ type: string;
58
+ view_permission: string;
59
+ };
60
+ };
61
+ export declare function getUnnestedEntries(entries: FormEntry[]): FormEntry[];
62
+ export declare const isEmptyWithDefault: (fieldValue: unknown, entry: InputParameterReference | InputField, instance: Record<string, unknown> | object) => boolean | "" | 0 | undefined;
63
+ export declare const docProperties: Property[];
@@ -1,6 +1,6 @@
1
1
  import { LocalDateTime } from '@js-joda/core';
2
2
  import jsonLogic from 'json-logic-js';
3
- import { get, isArray, isObject, omit, startCase, transform } from 'lodash';
3
+ import { get, isArray, isEmpty, isObject, omit, startCase, transform } from 'lodash';
4
4
  import { DateTime } from 'luxon';
5
5
  import Handlebars from 'no-eval-handlebars';
6
6
  import { defaultRuleProcessorMongoDB, formatQuery, parseMongoDB } from 'react-querybuilder';
@@ -389,13 +389,7 @@ export const convertDocToParameters = (obj) => {
389
389
  },
390
390
  ];
391
391
  }
392
- return [
393
- {
394
- id: key,
395
- name: startCase(key),
396
- type: 'string',
397
- },
398
- ];
392
+ return [];
399
393
  });
400
394
  };
401
395
  export const propertyToParameter = (property) => {
@@ -432,3 +426,139 @@ export const convertPropertiesToParams = (object) => {
432
426
  .sort((a, b) => a.name.localeCompare(b.name))
433
427
  .map(propertyToParameter);
434
428
  };
429
+ export function convertDocToEntries(document) {
430
+ const entries = [
431
+ {
432
+ type: 'readonlyField',
433
+ propertyId: 'id',
434
+ display: {
435
+ label: 'Id',
436
+ },
437
+ },
438
+ {
439
+ type: 'readonlyField',
440
+ propertyId: 'name',
441
+ display: {
442
+ label: 'Name',
443
+ },
444
+ },
445
+ {
446
+ type: 'readonlyField',
447
+ propertyId: 'contentType',
448
+ display: {
449
+ label: 'Content Type',
450
+ },
451
+ },
452
+ {
453
+ type: 'readonlyField',
454
+ propertyId: 'size',
455
+ display: {
456
+ label: 'Size',
457
+ },
458
+ },
459
+ {
460
+ type: 'readonlyField',
461
+ propertyId: 'uploadedDate',
462
+ display: {
463
+ label: 'Uploaded Date',
464
+ },
465
+ },
466
+ ];
467
+ if (!isEmpty(document.metadata)) {
468
+ entries.push({
469
+ type: 'input',
470
+ parameterId: 'type',
471
+ display: {
472
+ label: 'Type',
473
+ },
474
+ }, {
475
+ type: 'input',
476
+ parameterId: 'view_permission',
477
+ display: {
478
+ label: 'View Permission',
479
+ choicesDisplay: {
480
+ type: 'dropdown',
481
+ sortBy: 'ASC',
482
+ },
483
+ },
484
+ enumWithLabels: [
485
+ { label: 'Public', value: 'Public' },
486
+ { label: 'Private', value: 'Private' },
487
+ { label: 'Portal', value: 'Portal' },
488
+ ],
489
+ });
490
+ }
491
+ entries.push({
492
+ type: 'readonlyField',
493
+ propertyId: 'versionId',
494
+ display: {
495
+ label: 'Version Id',
496
+ },
497
+ });
498
+ return entries;
499
+ }
500
+ export function formatDataToDoc(data) {
501
+ return {
502
+ id: data.id,
503
+ name: data.name,
504
+ contentType: data.contentType,
505
+ size: data.size,
506
+ uploadedDate: data.uploadedDate,
507
+ versionId: data.versionId,
508
+ metadata: {
509
+ type: data.type,
510
+ view_permission: data.view_permission,
511
+ },
512
+ };
513
+ }
514
+ export function getUnnestedEntries(entries) {
515
+ return entries?.flatMap((entry) => {
516
+ if (entry.type === 'columns' && isArray(entry.columns)) {
517
+ return entry.columns.flatMap((column) => isArray(column.entries) ? getUnnestedEntries(column.entries) : []);
518
+ }
519
+ if (entry.type === 'sections' && isArray(entry.sections)) {
520
+ return entry.sections.flatMap((section) => isArray(section.entries) ? getUnnestedEntries(section.entries) : []);
521
+ }
522
+ return [entry];
523
+ });
524
+ }
525
+ export const isEmptyWithDefault = (fieldValue, entry, instance) => {
526
+ return ((isEmpty(instance) ||
527
+ fieldValue === undefined ||
528
+ fieldValue === null ||
529
+ (isArray(fieldValue) && fieldValue.length === 0)) &&
530
+ entry.display?.defaultValue &&
531
+ (!isObject(entry.display?.defaultValue) || !isEmpty(entry.display?.defaultValue)));
532
+ };
533
+ export const docProperties = [
534
+ {
535
+ id: 'id',
536
+ name: 'id',
537
+ type: 'string',
538
+ },
539
+ {
540
+ id: 'name',
541
+ name: 'Name',
542
+ type: 'string',
543
+ },
544
+ {
545
+ id: 'contentType',
546
+ name: 'contentType',
547
+ type: 'string',
548
+ },
549
+ {
550
+ id: 'size',
551
+ name: 'size',
552
+ type: 'string',
553
+ },
554
+ {
555
+ id: 'uploadedDate',
556
+ name: 'uploadedDate',
557
+ type: 'string',
558
+ },
559
+ {
560
+ id: 'versionId',
561
+ name: 'versionId',
562
+ type: 'string',
563
+ },
564
+ ];
@@ -1 +1,2 @@
1
1
  export { default as FormRenderer } from './FormRenderer';
2
+ export { default as FormRendererContainer } from './FormRendererContainer';
@@ -1 +1,2 @@
1
1
  export { default as FormRenderer } from './FormRenderer';
2
+ export { default as FormRendererContainer } from './FormRendererContainer';
@@ -5,7 +5,7 @@ export { ErrorComponent } from './ErrorComponent';
5
5
  export { Form } from './Form';
6
6
  export type { FormRef } from './Form';
7
7
  export { FormField } from './FormField';
8
- export { FormRenderer } from './FormV2';
8
+ export { FormRenderer, FormRendererContainer } from './FormV2';
9
9
  export { HistoryLog } from './HistoryLog';
10
10
  export { MenuBar } from './Menubar';
11
11
  export { MultiSelect } from './MultiSelect';
@@ -4,7 +4,7 @@ export { DataGrid } from './DataGrid';
4
4
  export { ErrorComponent } from './ErrorComponent';
5
5
  export { Form } from './Form';
6
6
  export { FormField } from './FormField';
7
- export { FormRenderer } from './FormV2';
7
+ export { FormRenderer, FormRendererContainer } from './FormV2';
8
8
  export { HistoryLog } from './HistoryLog';
9
9
  export { MenuBar } from './Menubar';
10
10
  export { MultiSelect } from './MultiSelect';
@@ -2,7 +2,7 @@ export { ClickAwayListener, createTheme, darken, lighten, styled, Toolbar, useMe
2
2
  export { CalendarPicker, DateTimePicker, MonthPicker, PickersDay, StaticDateTimePicker, StaticTimePicker, TimePicker, YearPicker, } from '@mui/x-date-pickers';
3
3
  export * from './colors';
4
4
  export * from './components/core';
5
- export { BuilderGrid, CriteriaBuilder, DataGrid, ErrorComponent, Form, FormField, FormRenderer, getReadableQuery, HistoryLog, MenuBar, MultiSelect, RepeatableField, ResponsiveOverflow, RichTextViewer, UserAvatar, } from './components/custom';
5
+ export { BuilderGrid, CriteriaBuilder, DataGrid, ErrorComponent, Form, FormField, FormRenderer, FormRendererContainer, getReadableQuery, HistoryLog, MenuBar, MultiSelect, RepeatableField, ResponsiveOverflow, RichTextViewer, UserAvatar, } from './components/custom';
6
6
  export type { FormRef } from './components/custom';
7
7
  export { NumericFormat } from './components/custom/FormField/InputFieldComponent';
8
8
  export { Box, Container, Grid, Stack } from './components/layout';
@@ -2,7 +2,7 @@ export { ClickAwayListener, createTheme, darken, lighten, styled, Toolbar, useMe
2
2
  export { CalendarPicker, DateTimePicker, MonthPicker, PickersDay, StaticDateTimePicker, StaticTimePicker, TimePicker, YearPicker, } from '@mui/x-date-pickers';
3
3
  export * from './colors';
4
4
  export * from './components/core';
5
- export { BuilderGrid, CriteriaBuilder, DataGrid, ErrorComponent, Form, FormField, FormRenderer, getReadableQuery, HistoryLog, MenuBar, MultiSelect, RepeatableField, ResponsiveOverflow, RichTextViewer, UserAvatar, } from './components/custom';
5
+ export { BuilderGrid, CriteriaBuilder, DataGrid, ErrorComponent, Form, FormField, FormRenderer, FormRendererContainer, getReadableQuery, HistoryLog, MenuBar, MultiSelect, RepeatableField, ResponsiveOverflow, RichTextViewer, UserAvatar, } from './components/custom';
6
6
  export { NumericFormat } from './components/custom/FormField/InputFieldComponent';
7
7
  export { Box, Container, Grid, Stack } from './components/layout';
8
8
  export * from './theme';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evoke-platform/ui-components",
3
- "version": "1.7.0-testing.3",
3
+ "version": "1.7.0-testing.4",
4
4
  "description": "",
5
5
  "main": "dist/published/index.js",
6
6
  "module": "dist/published/index.js",