@evoke-platform/ui-components 1.6.0-testing.12 → 1.6.0-testing.14

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.
Files changed (72) hide show
  1. package/dist/published/components/custom/CriteriaBuilder/CriteriaBuilder.d.ts +2 -3
  2. package/dist/published/components/custom/FormField/AddressFieldComponent/AddressFieldComponent.test.js +1 -1
  3. package/dist/published/components/custom/FormField/AddressFieldComponent/addressFieldComponent.js +1 -1
  4. package/dist/published/components/custom/FormField/BooleanSelect/BooleanSelect.js +3 -3
  5. package/dist/published/components/custom/FormField/DatePickerSelect/DatePickerSelect.js +7 -1
  6. package/dist/published/components/custom/FormField/DateTimePickerSelect/DateTimePickerSelect.js +7 -1
  7. package/dist/published/components/custom/FormField/FormField.d.ts +3 -2
  8. package/dist/published/components/custom/FormField/InputFieldComponent/InputFieldComponent.js +6 -3
  9. package/dist/published/components/custom/FormField/Select/Select.test.js +16 -41
  10. package/dist/published/components/custom/FormField/TimePickerSelect/TimePickerSelect.js +13 -3
  11. package/dist/published/components/custom/FormV2/FormRenderer.d.ts +19 -0
  12. package/dist/published/components/custom/FormV2/FormRenderer.js +183 -0
  13. package/dist/published/components/custom/FormV2/components/AccordionSections.d.ts +4 -0
  14. package/dist/published/components/custom/FormV2/components/AccordionSections.js +131 -0
  15. package/dist/published/components/custom/FormV2/components/ActionButtons.d.ts +19 -0
  16. package/dist/published/components/custom/FormV2/components/ActionButtons.js +106 -0
  17. package/dist/published/components/custom/FormV2/components/FieldWrapper.d.ts +24 -0
  18. package/dist/published/components/custom/FormV2/components/FieldWrapper.js +100 -0
  19. package/dist/published/components/custom/FormV2/components/FormContext.d.ts +12 -0
  20. package/dist/published/components/custom/FormV2/components/FormContext.js +8 -0
  21. package/dist/published/components/custom/FormV2/components/FormFieldTypes/AddressFields.d.ts +17 -0
  22. package/dist/published/components/custom/FormV2/components/FormFieldTypes/AddressFields.js +50 -0
  23. package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/ActionDialog.d.ts +14 -0
  24. package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/ActionDialog.js +88 -0
  25. package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/DocumentViewerCell.d.ts +13 -0
  26. package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/DocumentViewerCell.js +140 -0
  27. package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/DropdownRepeatableField.d.ts +17 -0
  28. package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/DropdownRepeatableField.js +233 -0
  29. package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/DropdownRepeatableFieldInput.d.ts +40 -0
  30. package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/DropdownRepeatableFieldInput.js +95 -0
  31. package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/RepeatableField.d.ts +12 -0
  32. package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/RepeatableField.js +526 -0
  33. package/dist/published/components/custom/FormV2/components/FormFieldTypes/Criteria.d.ts +12 -0
  34. package/dist/published/components/custom/FormV2/components/FormFieldTypes/Criteria.js +93 -0
  35. package/dist/published/components/custom/FormV2/components/FormFieldTypes/DocumentFiles/Document.d.ts +16 -0
  36. package/dist/published/components/custom/FormV2/components/FormFieldTypes/DocumentFiles/Document.js +73 -0
  37. package/dist/published/components/custom/FormV2/components/FormFieldTypes/DocumentFiles/DocumentList.d.ts +13 -0
  38. package/dist/published/components/custom/FormV2/components/FormFieldTypes/DocumentFiles/DocumentList.js +179 -0
  39. package/dist/published/components/custom/FormV2/components/FormFieldTypes/Image.d.ts +12 -0
  40. package/dist/published/components/custom/FormV2/components/FormFieldTypes/Image.js +108 -0
  41. package/dist/published/components/custom/FormV2/components/FormFieldTypes/UserProperty.d.ts +16 -0
  42. package/dist/published/components/custom/FormV2/components/FormFieldTypes/UserProperty.js +129 -0
  43. package/dist/published/components/custom/FormV2/components/FormFieldTypes/relatedObjectFiles/InstanceLookup.d.ts +15 -0
  44. package/dist/published/components/custom/FormV2/components/FormFieldTypes/relatedObjectFiles/InstanceLookup.js +226 -0
  45. package/dist/published/components/custom/FormV2/components/FormFieldTypes/relatedObjectFiles/ObjectPropertyInput.d.ts +4 -0
  46. package/dist/published/components/custom/FormV2/components/FormFieldTypes/relatedObjectFiles/ObjectPropertyInput.js +439 -0
  47. package/dist/published/components/custom/FormV2/components/FormFieldTypes/relatedObjectFiles/RelatedObjectInstance.d.ts +29 -0
  48. package/dist/published/components/custom/FormV2/components/FormFieldTypes/relatedObjectFiles/RelatedObjectInstance.js +74 -0
  49. package/dist/published/components/custom/FormV2/components/FormSections.d.ts +4 -0
  50. package/dist/published/components/custom/FormV2/components/FormSections.js +104 -0
  51. package/dist/published/components/custom/FormV2/components/RecursiveEntryRenderer.d.ts +2 -0
  52. package/dist/published/components/custom/FormV2/components/RecursiveEntryRenderer.js +209 -0
  53. package/dist/published/components/custom/FormV2/components/TabNav.d.ts +10 -0
  54. package/dist/published/components/custom/FormV2/components/TabNav.js +23 -0
  55. package/dist/published/components/custom/FormV2/components/ValidationFiles/Validation.d.ts +3 -0
  56. package/dist/published/components/custom/FormV2/components/ValidationFiles/Validation.js +176 -0
  57. package/dist/published/components/custom/FormV2/components/ValidationFiles/ValidationErrorDisplay.d.ts +10 -0
  58. package/dist/published/components/custom/FormV2/components/ValidationFiles/ValidationErrorDisplay.js +45 -0
  59. package/dist/published/components/custom/FormV2/components/types.d.ts +131 -0
  60. package/dist/published/components/custom/FormV2/components/types.js +1 -0
  61. package/dist/published/components/custom/FormV2/components/utils.d.ts +47 -0
  62. package/dist/published/components/custom/FormV2/components/utils.js +434 -0
  63. package/dist/published/components/custom/FormV2/index.d.ts +1 -0
  64. package/dist/published/components/custom/FormV2/index.js +1 -0
  65. package/dist/published/components/custom/index.d.ts +1 -0
  66. package/dist/published/components/custom/index.js +1 -0
  67. package/dist/published/index.d.ts +2 -2
  68. package/dist/published/index.js +2 -2
  69. package/dist/published/stories/FormField.stories.js +2 -1
  70. package/dist/published/theme/hooks.d.ts +7 -0
  71. package/dist/published/theme/hooks.js +9 -0
  72. package/package.json +4 -2
@@ -0,0 +1,131 @@
1
+ import { ExpandMoreOutlined } from '@mui/icons-material';
2
+ import { nanoid } from 'nanoid';
3
+ import React, { useEffect } from 'react';
4
+ import { useResponsive } from '../../../../theme';
5
+ import { Accordion, AccordionDetails, AccordionSummary, Typography } from '../../../core';
6
+ import { Box } from '../../../layout';
7
+ import { RecursiveEntryRenderer } from './RecursiveEntryRenderer';
8
+ import { getErrorCountForSection } from './utils';
9
+ function AccordionSections(props) {
10
+ const { entry, handleChange, fieldHeight, richTextEditor, instance, expandedSections, setExpandedSections, expandAll, setExpandAll, errors, parameters, triggerFieldReset, showSubmitError, } = props;
11
+ const { isMd, isLg, isXl } = useResponsive();
12
+ const lastSection = entry.sections.length - 1;
13
+ const sectionsWithIds = React.useMemo(() => assignIds(entry.sections), [entry]);
14
+ function collectNestedSections(entries = []) {
15
+ const nestedSections = [];
16
+ entries.forEach((entry) => {
17
+ if (entry.type === 'sections') {
18
+ nestedSections.push(entry);
19
+ }
20
+ else if (entry.type === 'columns') {
21
+ const columnEntry = entry;
22
+ columnEntry.columns.forEach((column) => {
23
+ const columnSections = collectNestedSections(column.entries);
24
+ nestedSections.push(...columnSections);
25
+ });
26
+ }
27
+ });
28
+ return nestedSections;
29
+ }
30
+ // need to add ids to section so expanded sections can differentiate between sections with the same label
31
+ function assignIds(sections) {
32
+ const result = [];
33
+ sections.forEach((section) => {
34
+ const newSection = {
35
+ ...section,
36
+ id: nanoid(),
37
+ };
38
+ result.push(newSection);
39
+ if (section.entries) {
40
+ const nestedSections = collectNestedSections(section.entries);
41
+ nestedSections.forEach((nestedSection) => {
42
+ nestedSection.sections = assignIds(nestedSection.sections);
43
+ });
44
+ }
45
+ });
46
+ return result;
47
+ }
48
+ function getExpandedSections(sections, expandAll) {
49
+ const expandedSections = [];
50
+ const processSections = (sectionList) => {
51
+ sectionList.forEach((section, index) => {
52
+ expandedSections.push({
53
+ label: section.label,
54
+ expanded: expandAll ?? (index === 0 || isMd || isLg || isXl),
55
+ id: section?.id,
56
+ });
57
+ if (section.entries) {
58
+ const nestedSections = collectNestedSections(section.entries).flatMap((s) => s.sections);
59
+ processSections(nestedSections);
60
+ }
61
+ });
62
+ };
63
+ processSections(sections);
64
+ return expandedSections;
65
+ }
66
+ useEffect(() => {
67
+ if (expandAll !== null) {
68
+ setExpandedSections(getExpandedSections(sectionsWithIds, expandAll));
69
+ }
70
+ }, [expandAll, sectionsWithIds]);
71
+ const handleAccordionChange = (id) => {
72
+ const updatedSections = expandedSections.map((section) => section.id === id ? { ...section, expanded: !section.expanded } : section);
73
+ setExpandedSections(updatedSections);
74
+ setExpandAll(null);
75
+ };
76
+ return (React.createElement(Box, null, sectionsWithIds.map((section, sectionIndex) => {
77
+ const errorCount = getErrorCountForSection(section, errors);
78
+ return (React.createElement(Accordion, { key: section.id, expanded: expandedSections.find((expandedSection) => expandedSection.id === section.id)?.expanded ??
79
+ !!expandAll, onChange: () => handleAccordionChange(section.id), defaultExpanded: sectionIndex === 0, sx: {
80
+ border: '1px solid #dbe0e4',
81
+ boxShadow: 'none',
82
+ marginBottom: '16px',
83
+ borderRadius: '6px',
84
+ '&:before': {
85
+ display: 'none',
86
+ },
87
+ } },
88
+ React.createElement(AccordionSummary, { sx: {
89
+ '&.Mui-expanded': {
90
+ borderBottom: '1px solid #dbe0e4',
91
+ minHeight: '44px',
92
+ borderBottomLeftRadius: '0px',
93
+ borderBottomRightRadius: '0px',
94
+ },
95
+ minHeight: '44px',
96
+ maxHeight: '44px',
97
+ backgroundColor: '#F4F6F8',
98
+ borderRadius: '5px',
99
+ // MUI accordion summaries have different border radius for the first and last item
100
+ borderTopLeftRadius: sectionIndex === 0 ? '3px' : undefined,
101
+ borderTopRightRadius: sectionIndex === 0 ? '3px' : undefined,
102
+ borderBottomRightRadius: sectionIndex === lastSection ? '3px' : undefined,
103
+ borderBottomLeftRadius: sectionIndex === lastSection ? '3px' : undefined,
104
+ }, expandIcon: React.createElement(ExpandMoreOutlined, { fontSize: "medium" }) },
105
+ React.createElement(Box, { sx: {
106
+ display: 'flex',
107
+ alignItems: 'center',
108
+ width: '100%',
109
+ justifyContent: 'space-between',
110
+ } },
111
+ React.createElement(Typography, { sx: {
112
+ fontWeight: '600',
113
+ } }, section.label),
114
+ errorCount > 0 && showSubmitError && (React.createElement(Box, { sx: {
115
+ ml: 1,
116
+ bgcolor: '#FF4842',
117
+ color: 'white',
118
+ borderRadius: '50%',
119
+ minWidth: '20px',
120
+ minHeight: '20px',
121
+ display: 'flex',
122
+ justifyContent: 'center',
123
+ alignItems: 'center',
124
+ fontSize: '12px',
125
+ margin: '0px',
126
+ marginRight: '16px',
127
+ } }, errorCount)))),
128
+ React.createElement(AccordionDetails, null, section.entries?.map((sectionEntry, index) => (React.createElement(RecursiveEntryRenderer, { key: sectionEntry.type + index, entry: sectionEntry, handleChange: handleChange, errors: errors, fieldHeight: fieldHeight, richTextEditor: richTextEditor, instance: instance, expandedSections: expandedSections, setExpandedSections: setExpandedSections, expandAll: expandAll, setExpandAll: setExpandAll, parameters: parameters, triggerFieldReset: triggerFieldReset, showSubmitError: showSubmitError }))))));
129
+ })));
130
+ }
131
+ export default AccordionSections;
@@ -0,0 +1,19 @@
1
+ import { ActionType, FormEntry } from '@evoke-platform/context';
2
+ import React from 'react';
3
+ import { FieldErrors, FieldValues, UseFormReturn, UseFormSetValue, UseFormUnregister } from 'react-hook-form';
4
+ type ActionButtonProps = {
5
+ onSubmit: (data: FieldValues) => void;
6
+ handleSubmit: UseFormReturn['handleSubmit'];
7
+ isModal: boolean;
8
+ submitButtonLabel?: string;
9
+ actionType?: ActionType;
10
+ onReset: () => void;
11
+ errors?: FieldErrors;
12
+ unregister: UseFormUnregister<FieldValues>;
13
+ entries: FormEntry[];
14
+ setValue: UseFormSetValue<FieldValues>;
15
+ formId?: string;
16
+ instance?: FieldValues;
17
+ };
18
+ declare function ActionButtons(props: ActionButtonProps): React.JSX.Element;
19
+ export default ActionButtons;
@@ -0,0 +1,106 @@
1
+ import { isEmpty, omit } from 'lodash';
2
+ import React, { useContext, useState } from 'react';
3
+ import { useResponsive } from '../../../../theme';
4
+ import { Button, LoadingButton } from '../../../core';
5
+ import { Box } from '../../../layout';
6
+ import { FormContext } from './FormContext';
7
+ import { entryIsVisible, getEntryId, getNestedParameterIds, isAddressProperty, scrollIntoViewWithOffset, } from './utils';
8
+ function ActionButtons(props) {
9
+ const { onSubmit, submitButtonLabel, actionType, handleSubmit, onReset, unregister, errors, isModal, entries, setValue, formId, instance, } = props;
10
+ const { isXs } = useResponsive();
11
+ const [isSubmitLoading, setIsSubmitLoading] = useState(false);
12
+ const { getValues } = useContext(FormContext);
13
+ const unregisterHiddenFields = (entriesToCheck) => {
14
+ entriesToCheck.forEach((entry) => {
15
+ if (entry.type === 'sections' || entry.type === 'columns') {
16
+ const subEntries = entry.type === 'sections' ? entry.sections : entry.columns;
17
+ subEntries.forEach((subEntry) => {
18
+ if (subEntry.entries) {
19
+ unregisterHiddenFields(subEntry.entries);
20
+ }
21
+ });
22
+ }
23
+ if (!entryIsVisible(entry, getValues(), instance)) {
24
+ if (entry.type === 'sections' || entry.type === 'columns') {
25
+ const fieldsToUnregister = getNestedParameterIds(entry);
26
+ fieldsToUnregister.forEach(processFieldUnregister);
27
+ }
28
+ else {
29
+ const fieldId = getEntryId(entry);
30
+ if (fieldId)
31
+ processFieldUnregister(fieldId);
32
+ }
33
+ }
34
+ });
35
+ };
36
+ const processFieldUnregister = (fieldId) => {
37
+ if (isAddressProperty(fieldId)) {
38
+ // Unregister entire 'address' to clear hidden field errors, then restore existing values since unregistering address.line1 etc is not working
39
+ let addressValues = getValues('address');
40
+ addressValues = omit(addressValues, fieldId.split('.')[1]);
41
+ unregister('address');
42
+ setValue('address', addressValues);
43
+ }
44
+ else {
45
+ unregister(fieldId);
46
+ }
47
+ };
48
+ async function showErrorsOrSubmit() {
49
+ setIsSubmitLoading(true);
50
+ unregisterHiddenFields(entries ?? []);
51
+ try {
52
+ await handleSubmit((data) => onSubmit(actionType === 'delete' ? {} : data))();
53
+ }
54
+ finally {
55
+ setIsSubmitLoading(false);
56
+ }
57
+ if (!isEmpty(errors)) {
58
+ setTimeout(() => {
59
+ const errorElement = document.getElementById(`validation-error-display-${formId}`);
60
+ let modal = errorElement?.closest('.MuiPaper-root');
61
+ const hasCloseIcon = modal?.querySelector('svg[data-testid="CloseIcon"]');
62
+ modal = hasCloseIcon ? document.querySelector('.MuiDialogContent-root') : modal;
63
+ if (errorElement) {
64
+ scrollIntoViewWithOffset(errorElement, 170, modal);
65
+ }
66
+ }, 0);
67
+ }
68
+ }
69
+ return (React.createElement(Box, { sx: {
70
+ display: 'flex',
71
+ justifyContent: 'flex-end',
72
+ flexWrap: 'wrap-reverse',
73
+ width: '100%',
74
+ } },
75
+ React.createElement(Button, { key: "cancel", variant: "outlined", sx: {
76
+ margin: '5px',
77
+ marginX: isXs ? '0px' : undefined,
78
+ color: 'black',
79
+ border: '1px solid rgb(206, 212, 218)',
80
+ width: isXs ? '100%' : 'auto',
81
+ '&:hover': {
82
+ backgroundColor: '#f2f4f7',
83
+ border: '1px solid rgb(206, 212, 218)',
84
+ },
85
+ }, onClick: () => onReset() }, isModal ? 'Cancel' : 'Discard Changes'),
86
+ React.createElement(LoadingButton, { key: "submit", variant: "contained", sx: {
87
+ lineHeight: '2.75',
88
+ margin: '5px 0 5px 5px',
89
+ marginX: isXs ? '0px' : undefined,
90
+ padding: '0 23px',
91
+ backgroundColor: actionType === 'delete' ? '#A12723' : 'primary',
92
+ borderRadius: '8px',
93
+ boxShadow: 'none',
94
+ whiteSpace: 'nowrap',
95
+ width: isXs ? '100%' : 'auto',
96
+ '& .MuiCircularProgress-root': {
97
+ color: 'white',
98
+ },
99
+ '&:hover': {
100
+ backgroundColor: actionType === 'delete' ? ' #8C2421' : '#014E7B',
101
+ },
102
+ }, onClick: () => {
103
+ showErrorsOrSubmit();
104
+ }, loading: isSubmitLoading }, submitButtonLabel || 'Submit')));
105
+ }
106
+ export default ActionButtons;
@@ -0,0 +1,24 @@
1
+ import React, { ReactNode } from 'react';
2
+ type FieldWrapperProps = {
3
+ inputId: string;
4
+ inputType: string;
5
+ label: string;
6
+ description?: string;
7
+ tooltip?: string;
8
+ prefix?: string;
9
+ suffix?: string;
10
+ value?: unknown;
11
+ errorMessage?: string;
12
+ showCharCount?: boolean;
13
+ viewOnly: boolean;
14
+ children: ReactNode;
15
+ required: boolean;
16
+ fieldHeight?: 'small' | 'medium';
17
+ maxLength?: number;
18
+ };
19
+ /**
20
+ * A component that wraps a FormField and adds a label,
21
+ * description, tooltip, prefix, suffix and word/char counts
22
+ */
23
+ declare const FieldWrapper: (props: FieldWrapperProps) => React.JSX.Element;
24
+ export default FieldWrapper;
@@ -0,0 +1,100 @@
1
+ import { Help, InfoRounded } from '@mui/icons-material';
2
+ import React from 'react';
3
+ import { IconButton, InputLabel, Tooltip, Typography } from '../../../core';
4
+ import { Box } from '../../../layout';
5
+ const underFieldStyles = {
6
+ display: 'flex',
7
+ flexDirection: 'row',
8
+ justifyContent: 'space-between',
9
+ alignItems: 'center',
10
+ };
11
+ const descriptionStyles = {
12
+ color: '#999',
13
+ whiteSpace: 'normal',
14
+ display: 'block',
15
+ };
16
+ const PrefixSuffix = (props) => {
17
+ const { prefix, suffix, height, isViewOnly } = props;
18
+ const text = prefix || suffix;
19
+ const prefixSuffixStyles = {
20
+ display: 'inline-flex',
21
+ alignItems: 'center',
22
+ background: isViewOnly ? undefined : '#f5f5f5',
23
+ padding: '5px',
24
+ border: isViewOnly ? undefined : '1px solid #ccc',
25
+ ...(suffix && {
26
+ borderTopRightRadius: '5px',
27
+ borderBottomRightRadius: '5px',
28
+ marginLeft: '-5px',
29
+ padding: '7px 5px 7px 10px',
30
+ marginTop: '6px',
31
+ }),
32
+ ...(prefix && {
33
+ borderTopLeftRadius: '5px',
34
+ borderBottomLeftRadius: '5px',
35
+ marginRight: '-5px',
36
+ padding: '7px 10px 7px 5px',
37
+ marginTop: '6px',
38
+ }),
39
+ height: height === 'small' ? 24 : 40,
40
+ };
41
+ if (!prefix && !suffix)
42
+ return null;
43
+ return (React.createElement(Box, { sx: prefixSuffixStyles },
44
+ React.createElement(Typography, null, text)));
45
+ };
46
+ /**
47
+ * A component that wraps a FormField and adds a label,
48
+ * description, tooltip, prefix, suffix and word/char counts
49
+ */
50
+ const FieldWrapper = (props) => {
51
+ const { inputId, label, description, tooltip, prefix, suffix, value, maxLength, errorMessage, showCharCount, inputType, viewOnly, children, fieldHeight, required, } = props;
52
+ const charCount = typeof value === 'string' ? value.length : 0;
53
+ const remainingChars = maxLength ? maxLength - charCount : undefined;
54
+ return (React.createElement(Box, null,
55
+ React.createElement(Box, { sx: { padding: '10px 0' } },
56
+ inputType !== 'boolean' && (React.createElement(InputLabel, { htmlFor: inputId, sx: {
57
+ display: 'flex',
58
+ alignItems: 'center',
59
+ color: viewOnly ? 'text.secondary' : 'text.primary',
60
+ fontSize: '14px',
61
+ } },
62
+ label,
63
+ required ? (React.createElement(Typography, { component: 'span', sx: { color: 'red', fontSize: '12px', lineHeight: '22px', paddingLeft: '4px' } }, `*`)) : null,
64
+ tooltip && (React.createElement(Tooltip, { placement: "right", title: tooltip },
65
+ React.createElement(IconButton, null,
66
+ React.createElement(Help, { sx: { fontSize: '14px' } })))))),
67
+ React.createElement(Box, { sx: {
68
+ display: 'flex',
69
+ flexDirection: 'row',
70
+ alignItems: viewOnly ? 'center' : 'flex-start',
71
+ } },
72
+ inputType === 'string' && (React.createElement(PrefixSuffix, { prefix: prefix, height: fieldHeight || 'medium', isViewOnly: viewOnly })),
73
+ React.createElement(Box, { sx: {
74
+ width: viewOnly && suffix ? undefined : '100%',
75
+ marginTop: '6px',
76
+ borderRadius: '8px',
77
+ } },
78
+ children,
79
+ inputType !== 'boolean' && (errorMessage || description || showCharCount) && (React.createElement(Box, { sx: underFieldStyles },
80
+ React.createElement(Box, { sx: {
81
+ width: '100%',
82
+ display: 'flex',
83
+ justifyContent: 'space-between',
84
+ alignItems: 'flex-start',
85
+ flexWrap: 'wrap',
86
+ paddingTop: '4px',
87
+ } },
88
+ React.createElement(Box, { sx: { display: 'flex', flexDirection: 'column' } },
89
+ errorMessage ? (React.createElement(Box, { display: 'flex', alignItems: 'center' },
90
+ React.createElement(InfoRounded, { color: 'error', sx: { fontSize: '.75rem', marginRight: '3px' } }),
91
+ React.createElement(Typography, { fontSize: '12px', color: 'error', sx: { lineHeight: '18px' } }, errorMessage))) : (React.createElement("span", null)),
92
+ description && (React.createElement(Typography, { id: `${inputId}-description`, variant: "caption", sx: descriptionStyles }, description))),
93
+ showCharCount && (React.createElement(Typography, { variant: "caption", sx: { color: '#999999', whiteSpace: 'nowrap' } },
94
+ remainingChars ?? charCount,
95
+ ' ',
96
+ (remainingChars ?? charCount) === 1 ? 'character' : 'characters',
97
+ !!maxLength && ` remaining`)))))),
98
+ inputType === 'string' && (React.createElement(PrefixSuffix, { suffix: suffix, height: fieldHeight || 'medium', isViewOnly: viewOnly }))))));
99
+ };
100
+ export default FieldWrapper;
@@ -0,0 +1,12 @@
1
+ /// <reference types="react" />
2
+ import { Obj } from '@evoke-platform/context';
3
+ import { FieldValues, UseFormGetValues } from 'react-hook-form';
4
+ type FormContextType = {
5
+ fetchedOptions: FieldValues;
6
+ setFetchedOptions: (newData: FieldValues) => void;
7
+ getValues: UseFormGetValues<FieldValues>;
8
+ stickyFooter?: boolean;
9
+ object?: Obj;
10
+ };
11
+ export declare const FormContext: import("react").Context<FormContextType>;
12
+ export {};
@@ -0,0 +1,8 @@
1
+ import { createContext } from 'react';
2
+ export const FormContext = createContext({
3
+ fetchedOptions: {},
4
+ setFetchedOptions: () => { },
5
+ getValues: (() => ({})),
6
+ stickyFooter: false,
7
+ object: undefined,
8
+ });
@@ -0,0 +1,17 @@
1
+ import { InputField, InputParameter, InputParameterReference, Property, ReadonlyField } from '@evoke-platform/context';
2
+ import React from 'react';
3
+ import { FieldErrors, FieldValues } from 'react-hook-form';
4
+ import { Address } from '../../../FormField/AddressFieldComponent';
5
+ interface AddressProps {
6
+ entry: InputParameterReference | ReadonlyField | InputField;
7
+ errors?: FieldErrors;
8
+ handleChange: (propertyId: string, value: string | Address | undefined) => void;
9
+ fieldHeight?: 'small' | 'medium';
10
+ readOnly?: boolean;
11
+ parameters?: InputParameter[];
12
+ instance?: FieldValues;
13
+ entryId: string;
14
+ fieldDefinition: InputParameter | Property;
15
+ }
16
+ declare function AddressFields(props: AddressProps): React.JSX.Element;
17
+ export default AddressFields;
@@ -0,0 +1,50 @@
1
+ import { useApiServices, } from '@evoke-platform/context';
2
+ import React from 'react';
3
+ import { useFormContext } from '../../../../../theme/hooks';
4
+ import { Typography } from '../../../../core';
5
+ import FormField from '../../../FormField';
6
+ import FieldWrapper from '../FieldWrapper';
7
+ import { getPrefixedUrl, isOptionEqualToValue } from '../utils';
8
+ function AddressFields(props) {
9
+ const { entry, errors, handleChange, fieldHeight, readOnly, parameters, instance, entryId, fieldDefinition } = props;
10
+ const { getValues } = useFormContext();
11
+ const apiServices = useApiServices();
12
+ const addressObject = entryId.split('.')[0];
13
+ const addressField = entryId.split('.')[1];
14
+ const addressValues = entry.type === 'readonlyField' ? instance?.[addressObject] : getValues(addressObject);
15
+ const fieldValue = addressValues?.[addressField];
16
+ const display = entry?.display;
17
+ const validation = fieldDefinition?.validation
18
+ ? fieldDefinition.validation
19
+ : {};
20
+ const queryAddresses = async (query) => {
21
+ return await apiServices.get(getPrefixedUrl(`/locations/search`), {
22
+ params: { query: query },
23
+ });
24
+ };
25
+ const handleAddressChange = (name, value) => {
26
+ if (addressField === 'line1' && typeof value === 'object' && value.line1) {
27
+ const addressKeys = ['line1', 'city', 'county', 'state', 'zipCode'];
28
+ addressKeys.forEach((key) => {
29
+ const fullKey = `${addressObject}.${key}`;
30
+ if (parameters?.some((p) => p.id === fullKey)) {
31
+ const fieldValue = value[key];
32
+ handleChange(fullKey, fieldValue);
33
+ }
34
+ });
35
+ }
36
+ else {
37
+ handleChange(name, value);
38
+ }
39
+ };
40
+ const addressErrors = errors?.[addressObject];
41
+ const addressFieldError = addressErrors?.[addressField];
42
+ return (React.createElement(FieldWrapper, { inputId: entryId, inputType: "string", label: display?.label || 'default', description: !readOnly ? display?.description : undefined, tooltip: display?.tooltip, value: fieldValue, maxLength: 'maxLength' in validation ? validation?.maxLength : 0, required: entry.display?.required || false, showCharCount: !readOnly && display?.charCount, viewOnly: !!readOnly, prefix: display?.prefix, suffix: display?.suffix }, !readOnly ? (React.createElement(FormField, { property: fieldDefinition, defaultValue: fieldValue, onChange: handleAddressChange, isMultiLineText: !!display?.rowCount, readOnly: entry.type === 'readonlyField', ...(addressField === 'line1' && { queryAddresses }), mask: validation?.mask, placeholder: display?.placeholder, isOptionEqualToValue: isOptionEqualToValue, size: fieldHeight, error: !!addressFieldError, errorMessage: addressFieldError?.message, additionalProps: {
43
+ ...(display?.description && {
44
+ inputProps: {
45
+ 'aria-describedby': `${entryId}-description`,
46
+ },
47
+ }),
48
+ } })) : (React.createElement(Typography, { variant: "body1", key: entryId, sx: { height: '24px', paddingTop: '6px' } }, fieldValue))));
49
+ }
50
+ export default AddressFields;
@@ -0,0 +1,14 @@
1
+ import { Action, ActionType, EvokeForm, InputParameter, Obj } from '@evoke-platform/context';
2
+ import React from 'react';
3
+ export type ActionDialogProps = {
4
+ open: boolean;
5
+ onClose: () => void;
6
+ action: Action;
7
+ instanceInput: Record<string, unknown>;
8
+ handleSubmit: (actionType: ActionType, input: Record<string, unknown> | undefined, instanceId?: string, setSubmitting?: (value: boolean) => void) => void;
9
+ object: Obj;
10
+ instanceId?: string;
11
+ relatedParameter?: InputParameter;
12
+ relatedForm?: EvokeForm;
13
+ };
14
+ export declare const ActionDialog: (props: ActionDialogProps) => React.JSX.Element;
@@ -0,0 +1,88 @@
1
+ import { useApiServices } from '@evoke-platform/context';
2
+ import { Close } from '@mui/icons-material';
3
+ import React, { useEffect, useState } from 'react';
4
+ import { Dialog, DialogContent, DialogTitle, IconButton, Skeleton } from '../../../../../core';
5
+ import { Box } from '../../../../../layout';
6
+ import ErrorComponent from '../../../../ErrorComponent';
7
+ import { getPrefixedUrl } from '../../utils';
8
+ const styles = {
9
+ button: {
10
+ textTransform: 'initial',
11
+ fontSize: '14px',
12
+ fontWeight: 700,
13
+ marginRight: '10px',
14
+ },
15
+ dialogTitle: {
16
+ fontSize: '18px',
17
+ fontWeight: 700,
18
+ paddingTop: '35px',
19
+ paddingBottom: '20px',
20
+ },
21
+ closeIcon: {
22
+ position: 'absolute',
23
+ right: '17px',
24
+ top: '22px',
25
+ },
26
+ cancelBtn: {
27
+ border: '1px solid #ced4da',
28
+ width: '75px',
29
+ marginRight: '10px',
30
+ color: 'black',
31
+ },
32
+ deleteBtn: {
33
+ color: '#ffffff',
34
+ backgroundColor: '#A12723',
35
+ '&:hover': { backgroundColor: '#A12723' },
36
+ },
37
+ };
38
+ export const ActionDialog = (props) => {
39
+ const { open, onClose, action, object, instanceId, relatedForm, instanceInput } = props;
40
+ const [loading, setLoading] = useState(false);
41
+ const [hasAccess, setHasAccess] = useState();
42
+ const [form, setForm] = useState();
43
+ const apiServices = useApiServices();
44
+ const isDeleteAction = action.type === 'delete';
45
+ useEffect(() => {
46
+ if (instanceId) {
47
+ setLoading(true);
48
+ apiServices.get(getPrefixedUrl(`/objects/${object.id}/instances/${instanceId}/checkAccess`), {
49
+ params: { action: 'execute', field: action.id },
50
+ }, (error, result) => {
51
+ setHasAccess(result?.result ?? false);
52
+ setLoading(false);
53
+ });
54
+ }
55
+ else {
56
+ setHasAccess(true);
57
+ setLoading(false);
58
+ }
59
+ }, [object, instanceId]);
60
+ useEffect(() => {
61
+ setForm(isDeleteAction && !form
62
+ ? {
63
+ id: '',
64
+ name: '',
65
+ entries: [
66
+ {
67
+ type: 'content',
68
+ html: `<p>You are about to delete ${instanceInput?.name}. Deleted records can't be restored. Are you sure you want to continue?</p>`,
69
+ },
70
+ ],
71
+ objectId: object.id,
72
+ actionId: '_delete',
73
+ display: {
74
+ submitLabel: 'Delete',
75
+ },
76
+ }
77
+ : relatedForm);
78
+ }, [relatedForm, action, form]);
79
+ return (React.createElement(Dialog, { maxWidth: 'md', fullWidth: true, open: open, onClose: (e, reason) => reason !== 'backdropClick' && onClose() },
80
+ React.createElement(DialogTitle, { sx: styles.dialogTitle },
81
+ React.createElement(IconButton, { sx: styles.closeIcon, onClick: onClose },
82
+ React.createElement(Close, { fontSize: "small" })),
83
+ action && hasAccess && !loading ? action?.name : ''),
84
+ React.createElement(DialogContent, { sx: { paddingBottom: loading ? undefined : '0px' } }, hasAccess ? (React.createElement(Box, { sx: { width: '100%', marginTop: '10px' } })) : (React.createElement(React.Fragment, null, loading ? (React.createElement(React.Fragment, null,
85
+ React.createElement(Skeleton, { height: '30px', animation: 'wave' }),
86
+ React.createElement(Skeleton, { height: '30px', animation: 'wave' }),
87
+ React.createElement(Skeleton, { height: '30px', animation: 'wave' }))) : (React.createElement(ErrorComponent, { code: 'AccessDenied', message: 'You do not have permission to perform this action.', styles: { boxShadow: 'none' } })))))));
88
+ };
@@ -0,0 +1,13 @@
1
+ import { ObjectInstance } from '@evoke-platform/context';
2
+ import React from 'react';
3
+ export type DocumentViewerCellProps = {
4
+ instance: ObjectInstance;
5
+ propertyId: string;
6
+ setSnackbarError: (error: {
7
+ showAlert: boolean;
8
+ message?: string;
9
+ isError?: boolean;
10
+ }) => void;
11
+ smallerThanMd?: boolean;
12
+ };
13
+ export declare const DocumentViewerCell: (props: DocumentViewerCellProps) => React.JSX.Element;