@evoke-platform/ui-components 1.0.0-dev.229 → 1.0.0-dev.231

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 (20) hide show
  1. package/dist/published/components/custom/Form/Common/Form.js +5 -5
  2. package/dist/published/components/custom/Form/FormComponents/DocumentComponent/DocumentComponent.d.ts +1 -0
  3. package/dist/published/components/custom/Form/FormComponents/DocumentComponent/DocumentComponent.js +3 -14
  4. package/dist/published/components/custom/Form/FormComponents/FormFieldComponent.d.ts +1 -0
  5. package/dist/published/components/custom/Form/FormComponents/FormFieldComponent.js +3 -14
  6. package/dist/published/components/custom/Form/FormComponents/ImageComponent/ImageComponent.d.ts +1 -0
  7. package/dist/published/components/custom/Form/FormComponents/ImageComponent/ImageComponent.js +12 -24
  8. package/dist/published/components/custom/Form/FormComponents/ObjectComponent/ObjectComponent.d.ts +2 -0
  9. package/dist/published/components/custom/Form/FormComponents/ObjectComponent/ObjectComponent.js +13 -25
  10. package/dist/published/components/custom/Form/FormComponents/ObjectComponent/ObjectPropertyInput.js +3 -3
  11. package/dist/published/components/custom/Form/FormComponents/ObjectComponent/RelatedObjectInstance.d.ts +2 -0
  12. package/dist/published/components/custom/Form/FormComponents/ObjectComponent/RelatedObjectInstance.js +2 -2
  13. package/dist/published/components/custom/Form/FormComponents/UserComponent/UserComponent.d.ts +1 -0
  14. package/dist/published/components/custom/Form/FormComponents/UserComponent/UserComponent.js +15 -27
  15. package/dist/published/components/custom/Form/FormComponents/ViewOnlyComponent.d.ts +1 -0
  16. package/dist/published/components/custom/Form/FormComponents/ViewOnlyComponent.js +8 -6
  17. package/dist/published/components/custom/Form/types.d.ts +2 -0
  18. package/dist/published/components/custom/Form/utils.d.ts +3 -2
  19. package/dist/published/components/custom/Form/utils.js +17 -4
  20. package/package.json +1 -1
@@ -36,7 +36,7 @@ export function Form(props) {
36
36
  ViewOnlyTextField: ViewOnlyComponent,
37
37
  ViewOnlyDecimal: ViewOnlyComponent,
38
38
  ViewOnlyInteger: ViewOnlyComponent,
39
- ViewOnlyRichText: richTextEditor,
39
+ ViewOnlyRichText: richTextEditor ?? ViewOnlyComponent,
40
40
  ViewOnlySection: Components.components.fieldset,
41
41
  ViewOnlyManyToManyRepeatableField: RepeatableFieldComponent,
42
42
  ViewOnlyRepeatableField: RepeatableFieldComponent,
@@ -59,7 +59,7 @@ export function Form(props) {
59
59
  Integer: FormFieldComponent,
60
60
  Buttons: ButtonComponent,
61
61
  Content: Components.components.content,
62
- RichText: richTextEditor,
62
+ RichText: richTextEditor ?? FormFieldComponent,
63
63
  Section: Components.components.tabs,
64
64
  ManyToManyRepeatableField: RepeatableFieldComponent,
65
65
  RepeatableField: RepeatableFieldComponent,
@@ -124,7 +124,7 @@ export function Form(props) {
124
124
  navigateTo,
125
125
  apiServices,
126
126
  user: userAccount,
127
- }, undefined, isReadOnly, allDefaultPages, navigateTo, queryAddresses, apiServices, !!closeModal, fieldHeight);
127
+ }, undefined, isReadOnly, allDefaultPages, navigateTo, queryAddresses, apiServices, !!closeModal, fieldHeight, richTextEditor);
128
128
  const components = isReadOnly ? newComponentProps : [...newComponentProps, BottomButtons];
129
129
  setComponentProps(components);
130
130
  }
@@ -205,7 +205,7 @@ export function Form(props) {
205
205
  navigateTo,
206
206
  apiServices,
207
207
  user: userAccount,
208
- }, undefined, undefined, undefined, undefined, undefined, undefined, !!closeModal, fieldHeight)),
208
+ }, undefined, undefined, undefined, undefined, undefined, undefined, !!closeModal, fieldHeight, richTextEditor)),
209
209
  BottomButtons,
210
210
  ]);
211
211
  }
@@ -221,7 +221,7 @@ export function Form(props) {
221
221
  navigateTo,
222
222
  apiServices,
223
223
  user,
224
- }, !!action, undefined, isReadOnly, queryAddresses, !!closeModal, fieldHeight),
224
+ }, !!action, undefined, isReadOnly, queryAddresses, !!closeModal, fieldHeight, richTextEditor),
225
225
  !isReadOnly && BottomButtons,
226
226
  ]);
227
227
  }
@@ -20,4 +20,5 @@ export declare class DocumentComponent extends ReactComponent {
20
20
  handleValidation(value?: (File | SavedDocumentReference)[] | null): void;
21
21
  beforeSubmit(): Promise<void>;
22
22
  attachReact(element: Element): void;
23
+ detachReact(element: Element): void;
23
24
  }
@@ -28,20 +28,6 @@ export class DocumentComponent extends ReactComponent {
28
28
  this.handleChange = this.handleChange.bind(this);
29
29
  }
30
30
  init() {
31
- this.on('changed-' + this.component.conditional.when, (value) => {
32
- // set default value when conditional field is shown
33
- if (this.component.defaultValue && value === this.component.conditional.eq) {
34
- this.setValue(this.component.defaultValue);
35
- this.updateValue(this.component.defaultValue, { modified: true });
36
- }
37
- // clear data and errors when a true conditional field is hidden
38
- if (this.component.conditional.show && value !== this.component.conditional.eq) {
39
- this.setValue('');
40
- this.updateValue('', { modified: true });
41
- this.clearErrors();
42
- super.detach();
43
- }
44
- });
45
31
  this.on(`api-error`, (details) => {
46
32
  const error = details.find((detail) => detail.code === 'errorMessage' && detail.path.replace('/', '') === this.component.key);
47
33
  if (error) {
@@ -147,4 +133,7 @@ export class DocumentComponent extends ReactComponent {
147
133
  React.createElement(FormComponentWrapper, { ...this.component, inputId: inputId, viewOnly: !this.component.canUpdateProperty, errorMessage: this.errorMessages() },
148
134
  React.createElement(Document, { ...this.component, id: inputId, handleChange: this.handleChange, error: this.hasErrors(), value: this.dataValue }))), root);
149
135
  }
136
+ detachReact(element) {
137
+ ReactDOM.unmountComponentAtNode(element);
138
+ }
150
139
  }
@@ -38,5 +38,6 @@ export declare class FormFieldComponent extends ReactComponent {
38
38
  handleComponentChange: (components: any, value: any) => void;
39
39
  handleChange: (key: string, value: any) => void;
40
40
  attachReact(element: Element): void;
41
+ detachReact(element: Element): void;
41
42
  }
42
43
  export {};
@@ -145,20 +145,6 @@ export class FormFieldComponent extends ReactComponent {
145
145
  this.handleChange = this.handleChange.bind(this);
146
146
  }
147
147
  init() {
148
- this.on('changed-' + this.component.conditional.when, (value) => {
149
- //set default value when conditional field is shown
150
- if (this.component.defaultValue && value === this.component.conditional.eq) {
151
- this.setValue(this.component.defaultValue);
152
- this.updateValue(this.component.defaultValue, { modified: true });
153
- }
154
- //clear data and errors when a true conditional field is hidden
155
- if (value !== this.component.conditional.eq) {
156
- this.setValue('');
157
- this.updateValue('', { modified: true });
158
- this.clearErrors();
159
- super.detach();
160
- }
161
- });
162
148
  if (this.component.key.includes('.city') ||
163
149
  this.component.key.includes('.county') ||
164
150
  this.component.key.includes('.state') ||
@@ -481,4 +467,7 @@ export class FormFieldComponent extends ReactComponent {
481
467
  this.emit('changed-' + this.component.key, e.target.value);
482
468
  }, ...this.component, id: inputId, defaultValue: this.dataValue, mask: this.component.inputMask, error: this.hasErrors(), size: this.component.fieldHeight ?? 'medium' }))), root);
483
469
  }
470
+ detachReact(element) {
471
+ ReactDOM.unmountComponentAtNode(element);
472
+ }
484
473
  }
@@ -22,4 +22,5 @@ export declare class ImageComponent extends ReactComponent {
22
22
  handleChange: (key: string, value: string | null) => void;
23
23
  beforeSubmit(): void;
24
24
  attachReact(element: Element): void;
25
+ detachReact(element: Element): void;
25
26
  }
@@ -1,7 +1,7 @@
1
1
  import { ReactComponent } from '@formio/react';
2
2
  import { isEmpty } from 'lodash';
3
3
  import React from 'react';
4
- import { createRoot } from 'react-dom/client';
4
+ import ReactDOM from 'react-dom';
5
5
  import { FormComponentWrapper } from '../../Common';
6
6
  import { isPropertyVisible } from '../../utils';
7
7
  import { Image } from './Image';
@@ -27,25 +27,6 @@ export class ImageComponent extends ReactComponent {
27
27
  this.handleChange = this.handleChange.bind(this);
28
28
  }
29
29
  init() {
30
- this.on('changed-' + this.component.conditional.when, (value) => {
31
- //set default value when conditional field is shown
32
- if (this.component.defaultValue && value === this.component.conditional.eq) {
33
- this.setValue(this.component.defaultValue);
34
- this.updateValue(this.component.defaultValue, { modified: true });
35
- }
36
- //clear data and errors when a true conditional field is hidden
37
- if (this.component.conditional.show && value !== this.component.conditional.eq) {
38
- this.setValue('');
39
- this.updateValue('', { modified: true });
40
- this.clearErrors();
41
- super.detach();
42
- // Detach the componentRoot when the component is hidden
43
- if (this.componentRoot) {
44
- this.componentRoot.unmount();
45
- this.componentRoot = undefined;
46
- }
47
- }
48
- });
49
30
  if (this.component.initialValue && /^{{.*}}$/.test(this.component.initialValue)) {
50
31
  const regex = /^{{input\.(?<relatedObjectProperty>[a-zA-Z][a-zA-Z0-9_]*)\.(?<nestedProperty>[a-zA-Z][a-zA-Z0-9_]*)}}$/;
51
32
  const groups = regex.exec(this.component.initialValue)?.groups;
@@ -122,12 +103,19 @@ export class ImageComponent extends ReactComponent {
122
103
  this.element && this.attach(this.element);
123
104
  }
124
105
  attachReact(element) {
125
- if (!this.componentRoot) {
126
- this.componentRoot = createRoot(element);
106
+ let root = ReactDOM.findDOMNode(element);
107
+ if (!root) {
108
+ root = element;
127
109
  }
128
110
  // FormIO uses id for an enclosing div, so we need to give the input field a different id.
129
111
  const inputId = `${this.component.id}-input`;
130
- return this.componentRoot.render(React.createElement("div", null, !this.component.hidden ? (React.createElement(FormComponentWrapper, { ...this.component, inputId: inputId, viewOnly: !this.component.canUpdateProperty, errorMessage: this.errorMessages() },
131
- React.createElement(Image, { ...this.component, id: inputId, value: this.dataValue, handleChange: this.handleChange, error: this.hasErrors() }))) : null));
112
+ /* TODO: You'll see warnings to upgrade to React 18's createRoot();
113
+ * It'll cause issues with: field-level errors not showing up, conditional visibility not working, focus moving out of the form on keypress
114
+ * Will need to be revisited later. Possibly look into using this.ref */
115
+ return ReactDOM.render(React.createElement("div", null, !this.component.hidden ? (React.createElement(FormComponentWrapper, { ...this.component, inputId: inputId, viewOnly: !this.component.canUpdateProperty, errorMessage: this.errorMessages() },
116
+ React.createElement(Image, { ...this.component, id: inputId, value: this.dataValue, handleChange: this.handleChange, error: this.hasErrors() }))) : null), root);
117
+ }
118
+ detachReact(element) {
119
+ ReactDOM.unmountComponentAtNode(element);
132
120
  }
133
121
  }
@@ -6,6 +6,7 @@ interface ObjectComponentProps extends BaseFormComponentProps {
6
6
  mode: 'default' | 'existingOnly';
7
7
  defaultValueCriteria?: Record<string, unknown>;
8
8
  initialValue?: string;
9
+ richTextEditor?: typeof ReactComponent;
9
10
  }
10
11
  export declare class ObjectComponent extends ReactComponent {
11
12
  relatedObject?: Obj;
@@ -31,5 +32,6 @@ export declare class ObjectComponent extends ReactComponent {
31
32
  handleChangeObjectProperty: (key: string, value?: ObjectInstance | null) => void;
32
33
  beforeSubmit(): void;
33
34
  attachReact(element: Element): void;
35
+ detachReact(element: Element): void;
34
36
  }
35
37
  export {};
@@ -2,7 +2,7 @@ import { ReactComponent } from '@formio/react';
2
2
  import dot from 'dot-object';
3
3
  import { cloneDeep, isEmpty, pick } from 'lodash';
4
4
  import React from 'react';
5
- import { createRoot } from 'react-dom/client';
5
+ import ReactDOM from 'react-dom';
6
6
  import { FormComponentWrapper } from '../../Common';
7
7
  import { getAllCriteriaInputs, getPrefixedUrl, isPropertyVisible, transformToWhere, updateCriteriaInputs, } from '../../utils';
8
8
  import { ObjectPropertyInput } from './ObjectPropertyInput';
@@ -33,25 +33,6 @@ export class ObjectComponent extends ReactComponent {
33
33
  this.handleChangeObjectProperty = this.handleChangeObjectProperty.bind(this);
34
34
  }
35
35
  init() {
36
- this.on('changed-' + this.component.conditional.when, (value) => {
37
- //set default value when conditional field is shown
38
- if (this.component.defaultValue && value === this.component.conditional.eq) {
39
- this.setValue(this.component.defaultValue);
40
- this.updateValue(this.component.defaultValue, { modified: true });
41
- }
42
- //clear data and errors when a true conditional field is hidden
43
- if (this.component.conditional.show && value !== this.component.conditional.eq) {
44
- this.setValue('');
45
- this.updateValue('', { modified: true });
46
- this.clearErrors();
47
- super.detach();
48
- // Detach the componentRoot when the component is hidden
49
- if (this.componentRoot) {
50
- this.componentRoot.unmount();
51
- this.componentRoot = undefined;
52
- }
53
- }
54
- });
55
36
  const data = dot.dot(this.root._data);
56
37
  if (this.criteria) {
57
38
  const inputProps = getAllCriteriaInputs(this.criteria);
@@ -182,6 +163,10 @@ export class ObjectComponent extends ReactComponent {
182
163
  this.element && this.attach(this.element);
183
164
  }
184
165
  attachReact(element) {
166
+ let root = ReactDOM.findDOMNode(element);
167
+ if (!root) {
168
+ root = element;
169
+ }
185
170
  const updatedComponent = {
186
171
  ...this.component,
187
172
  instance: {
@@ -190,13 +175,16 @@ export class ObjectComponent extends ReactComponent {
190
175
  },
191
176
  defaultValueCriteria: this.updatedDefaultValueCriteria,
192
177
  };
193
- if (!this.componentRoot) {
194
- this.componentRoot = createRoot(element);
195
- }
196
178
  // FormIO uses id for an enclosing div, so we need to give the input field a different id.
197
179
  const inputId = `${this.component.id}-input`;
198
- return this.componentRoot.render(React.createElement("div", null,
180
+ /* TODO: You'll see warnings to upgrade to React 18's createRoot();
181
+ * It'll cause issues with: field-level errors not showing up, conditional visibility not working, focus moving out of the form on keypress
182
+ * Will need to be revisited later. Possibly look into using this.ref */
183
+ return ReactDOM.render(React.createElement("div", null,
199
184
  React.createElement(FormComponentWrapper, { ...updatedComponent, inputId: inputId, errorMessage: this.errorMessages() },
200
- React.createElement(ObjectPropertyInput, { ...updatedComponent, id: inputId, handleChangeObjectProperty: this.handleChangeObjectProperty, error: this.hasErrors(), filter: this.criteria ? { where: transformToWhere(this.updatedCriteria) } : undefined }))));
185
+ React.createElement(ObjectPropertyInput, { ...updatedComponent, id: inputId, handleChangeObjectProperty: this.handleChangeObjectProperty, error: this.hasErrors(), filter: this.criteria ? { where: transformToWhere(this.updatedCriteria) } : undefined, richTextEditor: this.component.richTextEditor }))), root);
186
+ }
187
+ detachReact(element) {
188
+ ReactDOM.unmountComponentAtNode(element);
201
189
  }
202
190
  }
@@ -8,7 +8,7 @@ import { Box } from '../../../../layout';
8
8
  import { getPrefixedUrl, normalizeDates, transformToWhere } from '../../utils';
9
9
  import { RelatedObjectInstance } from './RelatedObjectInstance';
10
10
  export const ObjectPropertyInput = (props) => {
11
- const { id, instance, property, apiServices, defaultPages, handleChangeObjectProperty, nestedFieldsView, canUpdateProperty, error, navigateTo, mode, displayOption, filter, defaultValueCriteria, sortBy, orderBy, setSnackbarError, isModal, user, viewLayout, } = props;
11
+ const { id, instance, property, apiServices, defaultPages, handleChangeObjectProperty, nestedFieldsView, canUpdateProperty, error, navigateTo, mode, displayOption, filter, defaultValueCriteria, sortBy, orderBy, setSnackbarError, isModal, user, viewLayout, richTextEditor, } = props;
12
12
  const [relatedObject, setRelatedObject] = useState();
13
13
  const [openCreateDialog, setOpenCreateDialog] = useState(false);
14
14
  const [selectedInstance, setSelectedInstance] = useState();
@@ -333,7 +333,7 @@ export const ObjectPropertyInput = (props) => {
333
333
  event.stopPropagation();
334
334
  setOpenCreateDialog(true);
335
335
  }, "aria-label": `Add`, disabled: !canUpdateProperty }, "Add")))),
336
- openCreateDialog && (React.createElement(React.Fragment, null, nestedFieldsView ? (React.createElement(RelatedObjectInstance, { apiServices: apiServices, handleClose: handleClose, handleChangeObjectProperty: handleChangeObjectProperty, instance: instance, setSelectedInstance: setSelectedInstance, relatedObject: relatedObject, property: property, nestedFieldsView: nestedFieldsView, mode: mode, setSnackbarError: setSnackbarError, displayOption: displayOption, setOptions: setOptions, options: options, filter: filter, user: user, layout: layout })) : (React.createElement(Dialog, { fullWidth: true, maxWidth: "md", open: openCreateDialog, onClose: (e, reason) => reason !== 'backdropClick' && handleClose },
336
+ openCreateDialog && (React.createElement(React.Fragment, null, nestedFieldsView ? (React.createElement(RelatedObjectInstance, { apiServices: apiServices, handleClose: handleClose, handleChangeObjectProperty: handleChangeObjectProperty, instance: instance, setSelectedInstance: setSelectedInstance, relatedObject: relatedObject, property: property, nestedFieldsView: nestedFieldsView, mode: mode, setSnackbarError: setSnackbarError, displayOption: displayOption, setOptions: setOptions, options: options, filter: filter, user: user, layout: layout, richTextEditor: richTextEditor })) : (React.createElement(Dialog, { fullWidth: true, maxWidth: "md", open: openCreateDialog, onClose: (e, reason) => reason !== 'backdropClick' && handleClose },
337
337
  React.createElement(Typography, { sx: {
338
338
  marginTop: '28px',
339
339
  fontSize: '22px',
@@ -341,5 +341,5 @@ export const ObjectPropertyInput = (props) => {
341
341
  marginLeft: '24px',
342
342
  marginBottom: '10px',
343
343
  } }, `Add ${property.name}`),
344
- React.createElement(RelatedObjectInstance, { apiServices: apiServices, handleClose: handleClose, handleChangeObjectProperty: handleChangeObjectProperty, instance: instance, setSnackbarError: setSnackbarError, setSelectedInstance: setSelectedInstance, nestedFieldsView: nestedFieldsView, relatedObject: relatedObject, property: property, mode: mode, displayOption: displayOption, setOptions: setOptions, options: options, filter: filter, user: user, layout: layout })))))));
344
+ React.createElement(RelatedObjectInstance, { apiServices: apiServices, handleClose: handleClose, handleChangeObjectProperty: handleChangeObjectProperty, instance: instance, setSnackbarError: setSnackbarError, setSelectedInstance: setSelectedInstance, nestedFieldsView: nestedFieldsView, relatedObject: relatedObject, property: property, mode: mode, displayOption: displayOption, setOptions: setOptions, options: options, filter: filter, user: user, layout: layout, richTextEditor: richTextEditor })))))));
345
345
  };
@@ -1,5 +1,6 @@
1
1
  /// <reference types="react" />
2
2
  import { ApiServices, Obj, ObjectInstance, Property, TableViewLayout, UserAccount } from '@evoke-platform/context';
3
+ import { ReactComponent } from '@formio/react';
3
4
  export declare type RelatedObjectInstanceProps = {
4
5
  relatedObject?: Obj;
5
6
  property: Property;
@@ -21,5 +22,6 @@ export declare type RelatedObjectInstanceProps = {
21
22
  filter?: Record<string, unknown>;
22
23
  user?: UserAccount;
23
24
  layout?: TableViewLayout;
25
+ richTextEditor?: typeof ReactComponent;
24
26
  };
25
27
  export declare const RelatedObjectInstance: (props: RelatedObjectInstanceProps) => JSX.Element;
@@ -20,7 +20,7 @@ const styles = {
20
20
  };
21
21
  const DEFAULT_CREATE_ACTION = '_create';
22
22
  export const RelatedObjectInstance = (props) => {
23
- const { relatedObject, property, setSelectedInstance, handleChangeObjectProperty, handleClose, apiServices, setSnackbarError, nestedFieldsView, mode, displayOption, setOptions, options, filter, user, layout, } = props;
23
+ const { relatedObject, property, setSelectedInstance, handleChangeObjectProperty, handleClose, apiServices, setSnackbarError, nestedFieldsView, mode, displayOption, setOptions, options, filter, user, layout, richTextEditor, } = props;
24
24
  const [relationType, setRelationType] = useState(displayOption === 'dropdown' ? 'new' : 'existing');
25
25
  const [selectedRow, setSelectedRow] = useState();
26
26
  const [errors, setErrors] = useState([]);
@@ -104,7 +104,7 @@ export const RelatedObjectInstance = (props) => {
104
104
  React.createElement(Form, { actionId: "_create", actionType: "create", object: relatedObject, onSave: createNewInstance, submitButtonLabel: 'Add', closeModal: onClose, apiServices: apiServices, clearable: true, objectInputCommonProps: {
105
105
  apiServices: apiServices,
106
106
  setSnackbarError: setSnackbarError,
107
- }, queryAddresses: queryAddresses, user: userAccount }))) : (relatedObject && (React.createElement(React.Fragment, null,
107
+ }, queryAddresses: queryAddresses, user: userAccount, richTextEditor: richTextEditor }))) : (relatedObject && (React.createElement(React.Fragment, null,
108
108
  React.createElement(InstanceLookup, { apiServices: apiServices, nestedFieldsView: nestedFieldsView, setRelationType: setRelationType, object: relatedObject, setSelectedInstance: setSelectedRow, mode: mode, filter: filter, layout: layout }))))),
109
109
  relationType !== 'new' && (React.createElement(Box, { sx: styles.actionButtons },
110
110
  React.createElement(Button, { onClick: onClose, color: 'inherit', sx: {
@@ -25,4 +25,5 @@ export declare class UserComponent extends ReactComponent {
25
25
  handleChangeUserProperty: (value: AutocompleteOption) => void;
26
26
  beforeSubmit(): void;
27
27
  attachReact(element: Element): void;
28
+ detachReact(element: Element): void;
28
29
  }
@@ -1,9 +1,9 @@
1
1
  import { ReactComponent } from '@formio/react';
2
2
  import { cloneDeep, isEmpty } from 'lodash';
3
3
  import React from 'react';
4
- import { createRoot } from 'react-dom/client';
4
+ import ReactDOM from 'react-dom';
5
5
  import { FormComponentWrapper } from '../../Common';
6
- import { isPropertyVisible, transformToWhere } from '../../utils';
6
+ import { transformToWhere } from '../../utils';
7
7
  import { UserProperty } from './UserProperty';
8
8
  export class UserComponent extends ReactComponent {
9
9
  constructor(component, options, data) {
@@ -29,25 +29,6 @@ export class UserComponent extends ReactComponent {
29
29
  this.handleChangeUserProperty = this.handleChangeUserProperty.bind(this);
30
30
  }
31
31
  init() {
32
- this.on('changed-' + this.component.conditional.when, (value) => {
33
- // set default value when conditional field is shown
34
- if (this.component.defaultValue && value === this.component.conditional.eq) {
35
- this.setValue(this.component.defaultValue);
36
- this.updateValue(this.component.defaultValue, { modified: true });
37
- }
38
- // clear data and errors when a true conditional field is hidden
39
- if (this.component.conditional.show && value !== this.component.conditional.eq) {
40
- this.setValue('');
41
- this.updateValue('', { modified: true });
42
- this.clearErrors();
43
- super.detach();
44
- // Detach the componentRoot when the component is hidden
45
- if (this.componentRoot) {
46
- this.componentRoot.unmount();
47
- this.componentRoot = undefined;
48
- }
49
- }
50
- });
51
32
  if (this.component.initialValue && /^{{.*}}$/.test(this.component.initialValue)) {
52
33
  const regex = /^{{input\.(?<relatedObjectProperty>[a-zA-Z][a-zA-Z0-9_]*)\.(?<nestedProperty>[a-zA-Z][a-zA-Z0-9_]*)}}$/;
53
34
  const groups = regex.exec(this.component.initialValue)?.groups;
@@ -90,7 +71,7 @@ export class UserComponent extends ReactComponent {
90
71
  this.root.customErrors = this.root.customErrors.filter((error) => error.formattedKeyOrPath !== this.component.key);
91
72
  }
92
73
  handleValidation() {
93
- if (!isPropertyVisible(this.component.conditional, this.root.data)) {
74
+ if (!this.visible) {
94
75
  return;
95
76
  }
96
77
  // check for out-of-the-box formio errors which store on this.root.errors
@@ -123,6 +104,10 @@ export class UserComponent extends ReactComponent {
123
104
  this.element && this.attach(this.element);
124
105
  }
125
106
  attachReact(element) {
107
+ let root = ReactDOM.findDOMNode(element);
108
+ if (!root) {
109
+ root = element;
110
+ }
126
111
  const updatedComponent = {
127
112
  ...this.component,
128
113
  instance: {
@@ -130,13 +115,16 @@ export class UserComponent extends ReactComponent {
130
115
  [this.component.key]: isEmpty(this.dataValue) ? null : this.dataValue,
131
116
  },
132
117
  };
133
- if (!this.componentRoot) {
134
- this.componentRoot = createRoot(element, { onRecoverableError: console.error });
135
- }
136
118
  // FormIO uses id for an enclosing div, so we need to give the input field a different id.
137
119
  const inputId = `${this.component.id}-input`;
138
- return this.componentRoot.render(React.createElement("div", null,
120
+ /* TODO: You'll see warnings to upgrade to React 18's createRoot();
121
+ * It'll cause issues with: field-level errors not showing up, conditional visibility not working, focus moving out of the form on keypress
122
+ * Will need to be revisited later. Possibly look into using this.ref */
123
+ return ReactDOM.render(React.createElement("div", null,
139
124
  React.createElement(FormComponentWrapper, { ...updatedComponent, inputId: inputId, errorMessage: this.errorMessages() },
140
- React.createElement(UserProperty, { ...updatedComponent, id: inputId, value: this.dataValue ?? '', handleChangeUserProperty: this.handleChangeUserProperty, error: this.hasErrors(), filter: this.criteria ? { where: transformToWhere(this.updatedCriteria) } : undefined }))));
125
+ React.createElement(UserProperty, { ...updatedComponent, id: inputId, value: this.dataValue ?? '', handleChangeUserProperty: this.handleChangeUserProperty, error: this.hasErrors(), filter: this.criteria ? { where: transformToWhere(this.updatedCriteria) } : undefined }))), root);
126
+ }
127
+ detachReact(element) {
128
+ ReactDOM.unmountComponentAtNode(element);
141
129
  }
142
130
  }
@@ -17,4 +17,5 @@ export declare class ViewOnlyComponent extends ReactComponent {
17
17
  constructor(component: BaseFormComponentProps, options: any, data: any);
18
18
  showValue(value: unknown): {} | undefined;
19
19
  attachReact(element: Element): void;
20
+ detachReact(element: Element): void;
20
21
  }
@@ -3,7 +3,6 @@ import { get, isEmpty } from 'lodash';
3
3
  import { DateTime } from 'luxon';
4
4
  import React from 'react';
5
5
  import ReactDOM from 'react-dom';
6
- import { createRoot } from 'react-dom/client';
7
6
  import { Link, Typography } from '../../../core';
8
7
  import { FormComponentWrapper } from '../Common/FormComponentWrapper';
9
8
  export class ViewOnlyComponent extends ReactComponent {
@@ -74,13 +73,16 @@ export class ViewOnlyComponent extends ReactComponent {
74
73
  if (!root) {
75
74
  root = element;
76
75
  }
77
- if (!this.componentRoot) {
78
- this.componentRoot = createRoot(root);
79
- }
80
- return this.componentRoot.render(React.createElement("div", null,
76
+ /* TODO: You'll see warnings to upgrade to React 18's createRoot();
77
+ * It'll cause issues with: field-level errors not showing up, conditional visibility not working, focus moving out of the form on keypress
78
+ * Will need to be revisited later. Possibly look into using this.ref */
79
+ return ReactDOM.render(React.createElement("div", null,
81
80
  React.createElement(FormComponentWrapper, { ...this.component, viewOnly: true },
82
81
  React.createElement(Typography, { variant: "body1", key: this.component.key }, this.showValue(this.component.instance
83
82
  ? get(this.component.instance, this.component.key)
84
- : this.component.defaultValue)))));
83
+ : this.component.defaultValue)))), root);
84
+ }
85
+ detachReact(element) {
86
+ ReactDOM.unmountComponentAtNode(element);
85
87
  }
86
88
  }
@@ -1,4 +1,5 @@
1
1
  import { ApiServices, ObjectInstance, Property, UserAccount, ViewLayoutEntityReference } from '@evoke-platform/context';
2
+ import { ReactComponent } from '@formio/react';
2
3
  import { AutocompleteOption } from '../../core';
3
4
  export declare type BaseFormComponentProps = {
4
5
  key: string;
@@ -76,6 +77,7 @@ export declare type ObjectPropertyInputProps = {
76
77
  isModal?: boolean;
77
78
  label?: string;
78
79
  viewLayout?: ViewLayoutEntityReference;
80
+ richTextEditor?: typeof ReactComponent;
79
81
  };
80
82
  export declare type Address = {
81
83
  line1?: string;
@@ -1,4 +1,5 @@
1
1
  import { ActionInput, ActionInputType, ApiServices, FormEntry, InputParameter, InputParameterReference, Obj, ObjectInstance, Property, PropertyType } from '@evoke-platform/context';
2
+ import { ReactComponent } from '@formio/react';
2
3
  import { LocalDateTime } from '@js-joda/core';
3
4
  import { AutocompleteOption } from '../../core';
4
5
  import { ObjectPropertyInputProps } from './types';
@@ -20,9 +21,9 @@ export declare function getMiddleObject(instance: ObjectInstance, property: Prop
20
21
  } | undefined;
21
22
  export declare function getMiddleInstance(instanceId: string, property: Property, middleObjectInstances: ObjectInstance[]): ObjectInstance | undefined;
22
23
  export declare function getPrefixedUrl(url: string): string;
23
- export declare function addObjectPropertiesToComponentProps(properties: Property[], formComponents: any[], instance?: ObjectInstance, objectPropertyInputProps?: ObjectPropertyInputProps, autoSave?: (data: Record<string, unknown>) => void, readOnly?: boolean, defaultPages?: Record<string, string>, navigateTo?: (path: string) => void, queryAddresses?: unknown, apiServices?: ApiServices, isModal?: boolean, fieldHeight?: 'small' | 'medium'): Promise<ActionInput[]>;
24
+ export declare function addObjectPropertiesToComponentProps(properties: Property[], formComponents: any[], instance?: ObjectInstance, objectPropertyInputProps?: ObjectPropertyInputProps, autoSave?: (data: Record<string, unknown>) => void, readOnly?: boolean, defaultPages?: Record<string, string>, navigateTo?: (path: string) => void, queryAddresses?: unknown, apiServices?: ApiServices, isModal?: boolean, fieldHeight?: 'small' | 'medium', richTextEditor?: typeof ReactComponent): Promise<ActionInput[]>;
24
25
  export declare function getDefaultValue(initialValue: unknown, selectOptions?: AutocompleteOption[]): unknown;
25
- export declare const buildComponentPropsFromObjectProperties: (properties: Property[], objectId: string, instance?: ObjectInstance, objectPropertyInputProps?: ObjectPropertyInputProps, hasActionPermissions?: boolean, autoSave?: ((data: Record<string, unknown>) => void) | undefined, readOnly?: boolean, queryAddresses?: unknown, isModal?: boolean, fieldHeight?: 'small' | 'medium') => unknown[];
26
+ export declare const buildComponentPropsFromObjectProperties: (properties: Property[], objectId: string, instance?: ObjectInstance, objectPropertyInputProps?: ObjectPropertyInputProps, hasActionPermissions?: boolean, autoSave?: ((data: Record<string, unknown>) => void) | undefined, readOnly?: boolean, queryAddresses?: unknown, isModal?: boolean, fieldHeight?: 'small' | 'medium', richTextEditor?: typeof ReactComponent) => unknown[];
26
27
  export declare const buildComponentPropsFromDocumentProperties: (documentProperties: [string, unknown][], readOnly?: boolean, autoSave?: ((data: Record<string, unknown>) => void) | undefined, fieldHeight?: 'small' | 'medium') => {
27
28
  type: string;
28
29
  key: string;
@@ -468,7 +468,7 @@ export function getPrefixedUrl(url) {
468
468
  // This function is used when there is no form configured in the form builder.
469
469
  export async function addObjectPropertiesToComponentProps(properties,
470
470
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
471
- formComponents, instance, objectPropertyInputProps, autoSave, readOnly, defaultPages, navigateTo, queryAddresses, apiServices, isModal, fieldHeight) {
471
+ formComponents, instance, objectPropertyInputProps, autoSave, readOnly, defaultPages, navigateTo, queryAddresses, apiServices, isModal, fieldHeight, richTextEditor) {
472
472
  return [
473
473
  ...(await Promise.all(formComponents
474
474
  ?.filter((component) => !isUndefined(component) && !isNil(component))
@@ -625,6 +625,9 @@ formComponents, instance, objectPropertyInputProps, autoSave, readOnly, defaultP
625
625
  middleObject,
626
626
  getMiddleObjectInstances,
627
627
  isModal,
628
+ richTextEditor: ['RepeatableField', 'Object'].includes(component.type)
629
+ ? richTextEditor
630
+ : undefined,
628
631
  };
629
632
  }
630
633
  const defaultValue = getDefaultValue(isNil(instanceValue) ? component.initialValue : instanceValue, component?.data?.values);
@@ -665,11 +668,14 @@ formComponents, instance, objectPropertyInputProps, autoSave, readOnly, defaultP
665
668
  }
666
669
  : undefined,
667
670
  isModal,
671
+ richTextEditor: ['RepeatableField', 'Object'].includes(component.type)
672
+ ? richTextEditor
673
+ : undefined,
668
674
  };
669
675
  }
670
676
  if (component.columns) {
671
677
  for (const column of component.columns) {
672
- column.components = await addObjectPropertiesToComponentProps(properties, column.components, instance, objectPropertyInputProps, autoSave, readOnly, undefined, undefined, queryAddresses, apiServices, isModal, fieldHeight);
678
+ column.components = await addObjectPropertiesToComponentProps(properties, column.components, instance, objectPropertyInputProps, autoSave, readOnly, undefined, undefined, queryAddresses, apiServices, isModal, fieldHeight, richTextEditor);
673
679
  }
674
680
  return component;
675
681
  }
@@ -703,6 +709,9 @@ formComponents, instance, objectPropertyInputProps, autoSave, readOnly, defaultP
703
709
  item.navigateTo = navigateTo;
704
710
  item.isModal = isModal;
705
711
  item.fieldHeight = fieldHeight;
712
+ item.richTextEditor = ['RepeatableField', 'Object'].includes(item.type)
713
+ ? richTextEditor
714
+ : undefined;
706
715
  if (item.addressPropertyId) {
707
716
  item.queryAddresses = queryAddresses;
708
717
  }
@@ -724,7 +733,7 @@ formComponents, instance, objectPropertyInputProps, autoSave, readOnly, defaultP
724
733
  }
725
734
  }
726
735
  return {
727
- components: await addObjectPropertiesToComponentProps(properties, component.components, instance, objectPropertyInputProps, autoSave, readOnly, defaultPages, navigateTo, queryAddresses, apiServices, isModal, fieldHeight),
736
+ components: await addObjectPropertiesToComponentProps(properties, component.components, instance, objectPropertyInputProps, autoSave, readOnly, defaultPages, navigateTo, queryAddresses, apiServices, isModal, fieldHeight, richTextEditor),
728
737
  ...component,
729
738
  ...(component.type === 'Object' && objectPropertyInputProps),
730
739
  type: `${readOnly ? 'ViewOnly' : ''}${component.type}`,
@@ -738,6 +747,9 @@ formComponents, instance, objectPropertyInputProps, autoSave, readOnly, defaultP
738
747
  queryAddresses: component.isAddressLine1 ? queryAddresses : undefined,
739
748
  isModal,
740
749
  fieldHeight,
750
+ richTextEditor: ['RepeatableField', 'Object'].includes(component.type)
751
+ ? richTextEditor
752
+ : undefined,
741
753
  };
742
754
  }
743
755
  }))).filter((component) => !!component),
@@ -788,7 +800,7 @@ export function getDefaultValue(initialValue, selectOptions) {
788
800
  }
789
801
  // The following function adds the configured properties to the form components.
790
802
  // This function is used when there is a form configured in the form builder.
791
- export const buildComponentPropsFromObjectProperties = (properties, objectId, instance, objectPropertyInputProps, hasActionPermissions, autoSave, readOnly, queryAddresses, isModal, fieldHeight) => {
803
+ export const buildComponentPropsFromObjectProperties = (properties, objectId, instance, objectPropertyInputProps, hasActionPermissions, autoSave, readOnly, queryAddresses, isModal, fieldHeight, richTextEditor) => {
792
804
  const matchType = (type) => {
793
805
  switch (type) {
794
806
  case 'boolean':
@@ -1049,6 +1061,7 @@ export const buildComponentPropsFromObjectProperties = (properties, objectId, in
1049
1061
  autoSave,
1050
1062
  queryAddresses: ['collection', 'object'].includes(property?.type) ? queryAddresses : undefined,
1051
1063
  isModal,
1064
+ richTextEditor: property.type === 'object' ? richTextEditor : undefined,
1052
1065
  };
1053
1066
  });
1054
1067
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evoke-platform/ui-components",
3
- "version": "1.0.0-dev.229",
3
+ "version": "1.0.0-dev.231",
4
4
  "description": "",
5
5
  "main": "dist/published/index.js",
6
6
  "module": "dist/published/index.js",